summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorStanislaw Halik <sthalik@misaki.pl>2024-03-03 17:34:36 +0100
committerStanislaw Halik <sthalik@misaki.pl>2024-03-04 06:58:14 +0100
commit542d03a49fc5fc8a3aa0bb301973f68b199274e5 (patch)
treea06ec8e800ef445e652f49f722223c7ed4a164b5
parente18740b132b10604f7f76f67d92eaff81453436e (diff)
a?
-rw-r--r--src/timer-test.cpp5
-rw-r--r--src/timer.hpp14
-rw-r--r--test/critter.cpp164
3 files changed, 126 insertions, 57 deletions
diff --git a/src/timer-test.cpp b/src/timer-test.cpp
index 36d31b30..5c764da0 100644
--- a/src/timer-test.cpp
+++ b/src/timer-test.cpp
@@ -4,9 +4,8 @@ namespace floormat {
namespace {
-constexpr auto MAX = 18446744073709551615u, HALF = 9223372036854775808u;
-static_assert(std::is_same_v<uint64_t, std::decay_t<decltype(MAX)>>);
-static_assert(std::is_same_v<uint64_t, std::decay_t<decltype(HALF)>>);
+constexpr uint64_t MAX{18446744073709551615ULL} , HALF{9223372036854775808ULL};
+static_assert(sizeof MAX == 8);
static_assert(MAX == (uint64_t)-1);
static_assert(HALF + (HALF - 1) == MAX);
static_assert(MAX - HALF == HALF - 1);
diff --git a/src/timer.hpp b/src/timer.hpp
index 1835d7e4..faf92a3e 100644
--- a/src/timer.hpp
+++ b/src/timer.hpp
@@ -4,6 +4,8 @@
namespace floormat {
+// todo! move to .inl
+
struct Ns
{
explicit constexpr Ns(): stamp{0} {}
@@ -70,14 +72,6 @@ struct Ns
}
#endif
- static constexpr Ns from_millis(uint64_t a)
- {
- constexpr auto b = uint64_t(1e6);
- const auto x = a * b;
- fm_assert(a == 0 || x / a == b);
- return Ns{x};
- }
-
friend constexpr Ns operator+(const Ns& lhs, const Ns& rhs)
{
constexpr auto max = (uint64_t)-1;
@@ -186,8 +180,8 @@ struct Ns
uint64_t stamp;
};
-constexpr inline Ns Second{1000000000}, Millisecond{1000000}, Microsecond{1000};
-constexpr inline const Ns& Seconds{Second}, Milliseconds{Millisecond}, Microseconds{Microsecond};
+constexpr inline Ns Minute{60000000000}, Second{1000000000}, Millisecond{1000000}, Microsecond{1000};
+constexpr inline const Ns& Minutes{Minute}, Seconds{Second}, Milliseconds{Millisecond}, Microseconds{Microsecond};
struct Time final
{
diff --git a/test/critter.cpp b/test/critter.cpp
index db974eb7..89c494fc 100644
--- a/test/critter.cpp
+++ b/test/critter.cpp
@@ -2,18 +2,25 @@
#include <cinttypes>
#include "compat/debug.hpp"
#include "compat/shared-ptr-wrapper.hpp"
+#include "compat/function2.hpp"
#include "src/critter.hpp"
#include "src/world.hpp"
#include "src/wall-atlas.hpp"
#include "src/timer.hpp"
#include "src/log.hpp"
+#include "src/point.inl"
#include "loader/loader.hpp"
#include <iostream>
+// todo! find all places where singed division is used
+
namespace floormat {
namespace {
+using enum rotation;
+using fu2::function_view;
+
constexpr auto constantly(const auto& x) noexcept {
return [x]<typename... Ts> (const Ts&...) constexpr -> const auto& { return x; };
}
@@ -31,70 +38,126 @@ critter_proto make_proto(int accel)
return proto;
}
-template<typename F>
-void run(StringView name, const F& make_dt, critter& npc,
- const point start, const rotation r,
- const point end, const Ns expected_time,
- const uint32_t fuzz_pixels, const Ns fuzz_time,
- const Ns max_time = Second*300, bool no_crash = false)
+struct Start
{
- constexpr uint32_t max_steps = 10'000;
- fm_assert(max_time <= Second*300);
+ StringView name, instance;
+ point pt;
+ enum rotation rotation = N;
+};
+
+struct Expected
+{
+ point pt;
+ Ns time;
+};
+
+struct Grace
+{
+ Ns max_time = 600*Seconds;
+ uint32_t distance_L2 = 24;
+ uint32_t max_steps = 10'000;
+ bool no_crash = false;
+};
+
+bool run(StringView subtest_name, critter& npc, const function_view<Ns() const>& make_dt,
+ Start start, Expected expected, Grace grace = {})
+{
+ //validate_start(start);
+ //validate_expected(expected);
+ //validate_grace(grace);
+ fm_assert(start.name);
+ fm_assert(start.instance);
+ fm_assert(start.rotation < rotation_COUNT);
+ fm_assert(expected.time > Ns{});
+ fm_assert(expected.time <= grace.max_time);
+ fm_assert(grace.max_time <= 10*Minutes);
+ fm_assert(grace.max_time > Ns{});
+ fm_assert(grace.distance_L2 <= (uint32_t)Vector2((iTILE_SIZE2 * TILE_MAX_DIM)).length());
+ fm_assert(grace.max_steps > 0);
+ fm_assert(grace.max_steps <= 1000'00);
auto index = npc.index();
- npc.teleport_to(index, start, rotation_COUNT);
+ npc.teleport_to(index, start.pt, rotation_COUNT);
char buf[81];
Ns time{0};
- Debug{} << name << npc.position();
-
+ auto last_pos = npc.position();
uint32_t i;
bool stopped = false;
- constexpr auto bar = Second*1000;
+ if (subtest_name)
+ Debug{} << "-----" << start.name << "->" << start.instance << Debug::nospace << subtest_name << "-----";
+ else
+ Debug{} << "-----" << start.name << subtest_name << "-----";
+
+ constexpr auto print_pos = [](StringView prefix, point start, point pos, Ns time, Ns dt) {
+ DBG_nospace << prefix << " " << pos << "--"
+ << " time:" << time
+ << " dt:" << dt
+ << " dist:" << point::distance_l2(pos, start);
+ };
- for (i = 0; i <= max_steps; i++)
+ for (i = 0; i <= grace.max_steps; i++)
{
- auto dt = Ns{make_dt()};
- //fm_assert(dt == Millisecond * 100);
- const auto last_pos = npc.position();
- Debug{} << "-" << last_pos << colon(',')
- << "time" << time
- << Debug::nospace << ", dt" << dt;
+ const auto dt = Ns{make_dt()};
+ if (dt == Ns{}) [[unlikely]]
+ {
+ Debug{} << "| dt == 0, breaking";
+ break;
+ }
+ print_pos("-", expected.pt, npc.position(), time, dt);
fm_assert(dt >= Millisecond*1e-1);
fm_assert(dt <= Second * 1000);
- npc.update_movement(index, dt, r);
+ npc.update_movement(index, dt, start.rotation);
const auto pos = npc.position();
+ const bool same_pos = pos == last_pos;
+ last_pos = pos;
+
time += dt;
- if (pos == last_pos)
+
+ if (same_pos) [[unlikely]]
{
- stopped = true;
- Debug{} << "-" << last_pos << colon(',')
- << "time" << time << Debug::nospace
- << ", dt" << dt;
- Debug{} << "break!";
+ print_pos("-", expected.pt, pos, time, dt);
+ Debug{} << "===>" << i << "iters" << colon(',') << time;
+ fm_assert(i != 0);
break;
}
- if (time > max_time) [[unlikely]]
+ if (time > grace.max_time) [[unlikely]]
{
- Error{&std::cerr} << "timeout:" << max_time << "reached!";
- if (no_crash)
- return;
+ print_pos("*", start.pt, last_pos, time, dt);
+ Error{&std::cerr} << "!!! fatal: timeout" << grace.max_time << "reached!";
+ if (grace.no_crash)
+ return false;
else
- fm_EMIT_ABORT();
+ fm_assert(false);
+ }
+ if (i > grace.max_steps) [[unlikely]]
+ {
+ print_pos("*", start.pt, last_pos, time, dt);
+ Error{&std::cerr} << "!!! fatal: position doesn't converge after" << i << "iterations!";
+ if (grace.no_crash)
+ return false;
+ else
+ fm_assert(false);
}
-
- fm_assert(i != max_steps);
}
- if (stopped)
+
+
+ if (const auto dist_l2 = point::distance_l2(last_pos, expected.pt);
+ dist_l2 > grace.distance_L2)
{
- Debug{} << "===>" << i << "iters" << colon(',') << time;
- // todo! calc distance
+ Error{&std::cerr} << "!!! error: distance" << dist_l2 << "pixels" << "over grace distance of" << grace.distance_L2;
+ if (grace.no_crash)
+ fm_assert(false);
+ else
+ fm_assert(false);
}
else
- Debug{} << "!!! error: position doesn't converge after" << i << "iterations!";
+ Debug{} << "*" << "distance:" << dist_l2 << "pixels";
+
+ return true;
}
/* ***** TEST 1 *****
@@ -113,9 +176,7 @@ void run(StringView name, const F& make_dt, critter& npc,
* time=6800ms
*/
-using enum rotation;
-
-template<typename F> void test1(const F& make_dt, int accel)
+template<typename F> void test1(StringView instance_name, const F& make_dt, int accel)
{
const auto W = wall_image_proto{ loader.wall_atlas("empty"), 0 };
@@ -132,7 +193,21 @@ template<typename F> void test1(const F& make_dt, int accel)
w[chunk_coords_{0,0,0}].mark_modified();
w[chunk_coords_{0,1,0}].mark_modified();
- run("test1"_s, make_dt, *player, init, N, end, Second*7, 16, Second*60);
+ bool ret = run("test1", *player, make_dt,
+ Start{
+ .name = "test1",
+ .instance = instance_name,
+ .pt = init,
+ .rotation = N,
+ },
+ Expected{
+ .pt = end,
+ .time = Millisecond*6950,
+ },
+ Grace{});
+ fm_assert(ret);
+
+ //run("test1"_s, make_dt, *player, init, N, end, Second*7, Millisecond*16.667, Second*60);
}
/* ***** TEST 2 *****
@@ -151,9 +226,10 @@ void test_app::test_critter()
Debug{} << "";
Debug{} << "--";
Debug{} << "";
- test1(constantly(Millisecond * 100), 1);
- test1(constantly(Millisecond * 10), 1);
- test1(constantly(Millisecond * 1), 1);
+ test1("dt=1000 ms",constantly(Millisecond * 1000), 1);
+ test1("dt=100 ms", constantly(Millisecond * 100), 1);
+ test1("dt=50 ms", constantly(Millisecond * 50), 1);
+ test1("dt=16.667 ms", constantly(Millisecond * 16.667), 1);
Debug{} << "";
}