From 6d9591660a1f83e8abe1f1d4f1ca68a9ae7a8325 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Tue, 9 Apr 2024 11:41:37 +0200 Subject: a --- test/app.cpp | 2 +- test/app.hpp | 2 +- test/save.cpp | 174 ++++++++++++++++++++++++++++++++++++++++++++++++++++ test/serializer.cpp | 167 ------------------------------------------------- 4 files changed, 176 insertions(+), 169 deletions(-) create mode 100644 test/save.cpp delete mode 100644 test/serializer.cpp diff --git a/test/app.cpp b/test/app.cpp index 0ff2bdaa..38269296 100644 --- a/test/app.cpp +++ b/test/app.cpp @@ -61,7 +61,7 @@ int test_app::exec() FM_TEST(test_json3), FM_TEST(test_bitmask), FM_TEST(test_loader2), - FM_TEST(test_serializer1), + FM_TEST(test_save), FM_TEST(test_loader3), FM_TEST(test_astar_pool), FM_TEST(test_astar), diff --git a/test/app.hpp b/test/app.hpp index 6ec88371..98e08523 100644 --- a/test/app.hpp +++ b/test/app.hpp @@ -42,7 +42,7 @@ struct test_app final : private FM_APPLICATION static void test_region(); static void test_saves(); static void test_script(); - static void test_serializer1(); + static void test_save(); static void test_tile_iter(); static void test_wall_atlas(); static void test_wall_atlas2(); diff --git a/test/save.cpp b/test/save.cpp new file mode 100644 index 00000000..a2c7f48a --- /dev/null +++ b/test/save.cpp @@ -0,0 +1,174 @@ +#include "app.hpp" +#include "src/world.hpp" +#include "loader/loader.hpp" +#include "src/scenery.hpp" +#include "src/critter.hpp" +#include "src/light.hpp" +#include "src/ground-atlas.hpp" +#include "src/anim-atlas.hpp" +#include "src/tile-iterator.hpp" +#include "src/nanosecond.inl" +#include + +namespace floormat { + +namespace Path = Corrade::Utility::Path; + +chunk& test_app::make_test_chunk(world& w, chunk_coords_ ch) +{ + chunk& c = w[ch]; + c.mark_modified(); + + auto metal2 = loader.wall_atlas("empty", loader_policy::warn); + auto tiles = loader.ground_atlas("tiles"); + auto door = loader.scenery("door1"); + auto table = loader.scenery("table1"); + auto control_panel = loader.scenery("control panel (wall) 1"); + + constexpr auto N = TILE_MAX_DIM; + for (auto [x, k, pt] : c) + x.ground() = { tiles, variant_t(k % tiles->num_tiles()) }; + control_panel.r = rotation::W; + constexpr auto K = N/2; + c[{K, K }].wall_north() = { metal2, 0 }; + c[{K, K }].wall_west() = { metal2, 0 }; + c[{K, K+1}].wall_north() = { metal2, 0 }; + c[{K+1, K }].wall_west() = { metal2, 0 }; + w.make_object(w.make_id(), {ch, {3, 4}}, table); + w.make_object(w.make_id(), {ch, {K, K+1}}, control_panel); + + const auto add_player = [&](StringView name, Vector2i coord, bool playable) { + critter_proto cproto; + cproto.name = name; + cproto.playable = playable; + auto& p = *w.make_object(w.make_id(), global_coords{ch, {coord.x(), coord.y()}}, cproto); + p.frame = (uint16_t)coord.x(); + }; + add_player("Player 1", {12, 11}, true); // duplicate + add_player("Player 1", {13, 11}, true); // duplicate + add_player("Player 2", {14, 11}, false); + add_player("Player 3", {15, 11}, true); + + { + auto& e = *w.make_object(w.make_id(), {ch, {K+3, K+1}}, door); + const auto end = e.atlas->info().nframes-1; + constexpr auto dt = Second / 60; + fm_assert(e.frame == end); + { auto& x = std::get(e.subtype); + fm_assert(!x.active); + e.activate(e.index()); + fm_assert(x.active); + { auto index = e.index(); e.update(index, dt); } + fm_assert(e.frame != end); + for (int i = 0; i < 60*3; i++) + { auto index = e.index(); e.update(index, dt); } + fm_assert(e.frame == 0); + fm_assert(!x.active); + } + } + return c; +} + +namespace { + +void assert_chunks_equal(const chunk& a, const chunk& b) +{ + fm_assert(a.objects().size() == b.objects().size()); + + for (auto i = 0uz; i < TILE_COUNT; i++) + { + const auto &a1 = a[i], &b1 = b[i]; + fm_assert(a1 == b1); + } + + for (auto i = 0uz; i < a.objects().size(); i++) + { + const auto& ae = *a.objects()[i]; + const auto& be = *b.objects()[i]; + const auto type = ae.type(); + fm_assert(ae.type() == be.type()); + fm_assert(type < object_type::COUNT && type != object_type::none); + switch (type) + { + case object_type::none: + case object_type::COUNT: std::unreachable(); + case object_type::critter: { + const auto& e1 = static_cast(ae); + const auto& e2 = static_cast(be); + const auto p1 = critter_proto(e1), p2 = critter_proto(e2); + fm_assert(p1 == p2); + break; + } + case object_type::scenery: { + const auto& e1 = static_cast(ae); + const auto& e2 = static_cast(be); + const auto p1 = scenery_proto(e1), p2 = scenery_proto(e2); + fm_assert(p1 == p2); + break; + } + case object_type::light: { + const auto& e1 = static_cast(ae); + const auto& e2 = static_cast(be); + const auto p1 = light_proto(e1), p2 = light_proto(e2); + fm_assert(p1 == p2); + break; + } + } + } +} + +void test_save1(StringView input, StringView tmp) +{ + if (Path::exists(tmp)) + Path::remove(tmp); + chunk_coords_ coord{}; + world w; + if (input) + w = world::deserialize(input, loader_policy::ignore); + else + { + coord = {1, 1, 0}; + w = world(); + auto& c = test_app::make_test_chunk(w, coord); + fm_assert(!c.empty(true)); + } + w.serialize(tmp); + auto w2 = world::deserialize(tmp, loader_policy::ignore); + auto& c2 = w2[coord]; + fm_assert(!c2.empty(true)); + assert_chunks_equal(w[coord], c2); +} + +void test_offset_frac(StringView tmp) +{ + // todo! test non-zero offset_frac +} + +} // namespace + +void test_app::test_save() +{ + fm_assert(Path::exists(Path::join(loader.TEMP_PATH, "CMakeCache.txt"))); + const auto tmp_filename = Path::join(loader.TEMP_PATH, "test/test-serializer1.dat"_s); + + test_save1({}, tmp_filename); + test_offset_frac(tmp_filename); +} + +void test_app::test_saves() +{ + fm_assert(Path::exists(Path::join(loader.TEMP_PATH, "CMakeCache.txt"))); + const auto tmp_filename = Path::join(loader.TEMP_PATH, "test/test-serializer2.dat"_s); + const auto dir = Path::join(loader.TEMP_PATH, "test/save/"_s); + using LF = Path::ListFlag; + auto files = Path::list(dir, LF::SkipDirectories|LF::SkipSpecial|LF::SkipDotAndDotDot); + fm_assert(files); + for (const StringView file : *files) + { + fm_assert(file.hasSuffix(".dat"_s)); + auto path = Path::join(dir, file); + test_save1(path, tmp_filename); + } +} + +} // namespace floormat diff --git a/test/serializer.cpp b/test/serializer.cpp deleted file mode 100644 index c933a12f..00000000 --- a/test/serializer.cpp +++ /dev/null @@ -1,167 +0,0 @@ -#include "app.hpp" -#include "src/world.hpp" -#include "loader/loader.hpp" -#include "src/scenery.hpp" -#include "src/critter.hpp" -#include "src/light.hpp" -#include "src/ground-atlas.hpp" -#include "src/anim-atlas.hpp" -#include "src/tile-iterator.hpp" -#include "src/nanosecond.inl" -#include - -namespace floormat { - -namespace Path = Corrade::Utility::Path; - -chunk& test_app::make_test_chunk(world& w, chunk_coords_ ch) -{ - chunk& c = w[ch]; - c.mark_modified(); - - auto metal2 = loader.wall_atlas("empty", loader_policy::warn); - auto tiles = loader.ground_atlas("tiles"); - auto door = loader.scenery("door1"); - auto table = loader.scenery("table1"); - auto control_panel = loader.scenery("control panel (wall) 1"); - - constexpr auto N = TILE_MAX_DIM; - for (auto [x, k, pt] : c) - x.ground() = { tiles, variant_t(k % tiles->num_tiles()) }; - control_panel.r = rotation::W; - constexpr auto K = N/2; - c[{K, K }].wall_north() = { metal2, 0 }; - c[{K, K }].wall_west() = { metal2, 0 }; - c[{K, K+1}].wall_north() = { metal2, 0 }; - c[{K+1, K }].wall_west() = { metal2, 0 }; - w.make_object(w.make_id(), {ch, {3, 4}}, table); - w.make_object(w.make_id(), {ch, {K, K+1}}, control_panel); - - const auto add_player = [&](StringView name, Vector2i coord, bool playable) { - critter_proto cproto; - cproto.name = name; - cproto.playable = playable; - auto& p = *w.make_object(w.make_id(), global_coords{ch, {coord.x(), coord.y()}}, cproto); - p.frame = (uint16_t)coord.x(); - }; - add_player("Player 1", {12, 11}, true); // duplicate - add_player("Player 1", {13, 11}, true); // duplicate - add_player("Player 2", {14, 11}, false); - add_player("Player 3", {15, 11}, true); - - { - auto& e = *w.make_object(w.make_id(), {ch, {K+3, K+1}}, door); - const auto end = e.atlas->info().nframes-1; - constexpr auto dt = Second / 60; - fm_assert(e.frame == end); - { auto& x = std::get(e.subtype); - fm_assert(!x.active); - e.activate(e.index()); - fm_assert(x.active); - { auto index = e.index(); e.update(index, dt); } - fm_assert(e.frame != end); - for (int i = 0; i < 60*3; i++) - { auto index = e.index(); e.update(index, dt); } - fm_assert(e.frame == 0); - fm_assert(!x.active); - } - } - return c; -} - -namespace { - -void assert_chunks_equal(const chunk& a, const chunk& b) -{ - fm_assert(a.objects().size() == b.objects().size()); - - for (auto i = 0uz; i < TILE_COUNT; i++) - { - const auto &a1 = a[i], &b1 = b[i]; - fm_assert(a1 == b1); - } - - for (auto i = 0uz; i < a.objects().size(); i++) - { - const auto& ae = *a.objects()[i]; - const auto& be = *b.objects()[i]; - const auto type = ae.type(); - fm_assert(ae.type() == be.type()); - fm_assert(type < object_type::COUNT && type != object_type::none); - switch (type) - { - case object_type::none: - case object_type::COUNT: std::unreachable(); - case object_type::critter: { - const auto& e1 = static_cast(ae); - const auto& e2 = static_cast(be); - const auto p1 = critter_proto(e1), p2 = critter_proto(e2); - fm_assert(p1 == p2); - break; - } - case object_type::scenery: { - const auto& e1 = static_cast(ae); - const auto& e2 = static_cast(be); - const auto p1 = scenery_proto(e1), p2 = scenery_proto(e2); - fm_assert(p1 == p2); - break; - } - case object_type::light: { - const auto& e1 = static_cast(ae); - const auto& e2 = static_cast(be); - const auto p1 = light_proto(e1), p2 = light_proto(e2); - fm_assert(p1 == p2); - break; - } - } - } -} - -void test_serializer(StringView input, StringView tmp) -{ - if (Path::exists(tmp)) - Path::remove(tmp); - chunk_coords_ coord{}; - world w; - if (input) - w = world::deserialize(input, loader_policy::ignore); - else - { - coord = {1, 1, 0}; - w = world(); - auto& c = test_app::make_test_chunk(w, coord); - fm_assert(!c.empty(true)); - } - w.serialize(tmp); - auto w2 = world::deserialize(tmp, loader_policy::ignore); - auto& c2 = w2[coord]; - fm_assert(!c2.empty(true)); - assert_chunks_equal(w[coord], c2); -} - -} // namespace - -void test_app::test_serializer1() -{ - fm_assert(Path::exists(Path::join(loader.TEMP_PATH, "CMakeCache.txt"))); - const auto tmp_filename = Path::join(loader.TEMP_PATH, "test/test-serializer1.dat"_s); - test_serializer({}, tmp_filename); -} - -void test_app::test_saves() -{ - fm_assert(Path::exists(Path::join(loader.TEMP_PATH, "CMakeCache.txt"))); - const auto tmp_filename = Path::join(loader.TEMP_PATH, "test/test-serializer2.dat"_s); - const auto dir = Path::join(loader.TEMP_PATH, "test/save/"_s); - using LF = Path::ListFlag; - auto files = Path::list(dir, LF::SkipDirectories|LF::SkipSpecial|LF::SkipDotAndDotDot); - fm_assert(files); - for (const StringView file : *files) - { - fm_assert(file.hasSuffix(".dat"_s)); - auto path = Path::join(dir, file); - test_serializer(path, tmp_filename); - } -} - -} // namespace floormat -- cgit v1.2.3