summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--src/timer.hpp25
-rw-r--r--test/critter.cpp132
2 files changed, 95 insertions, 62 deletions
diff --git a/src/timer.hpp b/src/timer.hpp
index 6e9bd651..36874e9e 100644
--- a/src/timer.hpp
+++ b/src/timer.hpp
@@ -60,18 +60,6 @@ struct Ns
return Ns{(uint64_t)x};
}
-#if 0
- template<typename T>
- requires (std::is_same_v<T, double>)
- static Ns from_nonzero(T seconds)
- {
- constexpr double max{uint64_t{1} << 53};
- fm_assert(seconds >= 0);
- fm_assert(seconds <= max);
- return Ns((uint64_t)seconds);
- }
-#endif
-
friend constexpr Ns operator+(const Ns& lhs, const Ns& rhs)
{
constexpr auto max = (uint64_t)-1;
@@ -144,6 +132,19 @@ struct Ns
return Ns{a / b};
}
+#if 0
+ template<typename T>
+ requires std::is_floating_point_v<T>
+ friend constexpr double operator/(const Ns& lhs, double b)
+ {
+ fm_assert(b != 0.);
+ auto x = double{lhs.stamp / b};
+ constexpr auto max = double{uint64_t{1} << 53};
+ fm_assert(x <= max);
+ return x;
+ }
+#endif
+
friend constexpr uint64_t operator%(const Ns& lhs, const Ns& rhs)
{
auto a = lhs.stamp, b = rhs.stamp;
diff --git a/test/critter.cpp b/test/critter.cpp
index de443265..939ae811 100644
--- a/test/critter.cpp
+++ b/test/critter.cpp
@@ -52,13 +52,20 @@ struct Start
{
StringView name, instance;
point pt;
- float accel = 1;
+ double accel = 1;
enum rotation rotation = N;
- bool verbose = is_log_verbose();
-#if 0
+#if 1
+ bool quiet = is_log_quiet() || is_log_standard();
+ bool verbose = false;
+#elif 1
+ bool verbose = true;
+ bool quiet = false;
+#elif 0
bool quiet = is_log_quiet();
+ bool verbose = is_log_standard() || is_log_verbose();
#else
- bool quiet = !is_log_verbose();
+ bool quiet = is_log_quiet() || is_log_standard();
+ bool verbose = is_log_verbose();
#endif
};
@@ -70,33 +77,35 @@ struct Expected
struct Grace
{
- Ns max_time = 600*Seconds;
+ Ns time = Ns{250};
uint32_t distance_L2 = 24;
- uint32_t max_steps = 10'000;
bool no_crash = false;
};
-bool run(StringView subtest_name, world& w, const function_view<Ns() const>& make_dt,
+bool run(world& w, const function_view<Ns() const>& make_dt,
Start start, Expected expected, Grace grace = {})
{
+ constexpr auto max_time = 120*Second;
+ constexpr uint32_t max_steps = 10'000;
+
+ fm_assert(grace.time != Ns{});
fm_assert(!start.quiet | !start.verbose);
//validate_start(start);
//validate_expected(expected);
//validate_grace(grace);
+ fm_assert(start.accel > 1e-8);
+ fm_assert(start.accel <= 50);
fm_assert(start.name);
fm_assert(start.instance);
fm_assert(start.rotation < rotation_COUNT);
- fm_assert(expected.time <= grace.max_time);
- fm_assert(grace.max_time <= 10*Minutes);
- fm_assert(grace.max_time > Ns{});
+ expected.time.stamp = uint64_t(expected.time.stamp / start.accel);
+ fm_assert(expected.time <= max_time);
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);
mark_all_modified(w);
object_id id = 0;
- auto npc_ = w.ensure_player_character(id, make_proto(start.accel)).ptr;
+ auto npc_ = w.ensure_player_character(id, make_proto((float)start.accel)).ptr;
auto& npc = *npc_;
auto index = npc.index();
@@ -107,12 +116,7 @@ bool run(StringView subtest_name, world& w, const function_view<Ns() const>& mak
uint32_t i;
if (!start.quiet) [[unlikely]]
- {
- if (subtest_name)
- Debug{} << "**" << start.name << "->" << start.instance << Debug::nospace << subtest_name << colon();
- else
- Debug{} << "**" << start.name << subtest_name << colon();
- }
+ Debug{} << "**" << start.name << start.instance << colon();
constexpr auto print_pos = [](StringView prefix, point start, point pos, Ns time, Ns dt) {
DBG_nospace << prefix
@@ -122,7 +126,7 @@ bool run(StringView subtest_name, world& w, const function_view<Ns() const>& mak
<< " dist:" << point::distance_l2(pos, start);
};
- for (i = 0; i <= grace.max_steps; i++)
+ for (i = 0; true; i++)
{
const auto dt = Ns{make_dt()};
if (dt == Ns{}) [[unlikely]]
@@ -148,31 +152,32 @@ bool run(StringView subtest_name, world& w, const function_view<Ns() const>& mak
{
print_pos("->", expected.pt, pos, time, dt);
DBG_nospace << "===>"
- << " iters" << colon(',')
- << " time" << time
+ << " iters,"
+ << " time:" << time
+ << " distance:" << point::distance_l2(last_pos, expected.pt) << " px"
<< Debug::newline;
}
if (i == 0) [[unlikely]] // todo! check for very small dt before dying
{
{ auto dbg = Error{standard_error(), Debug::Flag::NoSpace};
- dbg << "!!! fatal: took zero iterations";
+ dbg << "!!! fatal: stopped after zero iterations";
dbg << " dt=" << dt << " accel=" << npc.speed;
}
fm_assert(false);
}
break;
}
- if (time > grace.max_time) [[unlikely]]
+ if (time > max_time) [[unlikely]]
{
if (!start.quiet) [[unlikely]]
print_pos("*", start.pt, last_pos, time, dt);
- Error{standard_error()} << "!!! fatal: timeout" << grace.max_time << "reached!";
+ Error{standard_error()} << "!!! fatal: timeout" << max_time << "reached!";
if (grace.no_crash)
return false;
else
fm_assert(false);
}
- if (i > grace.max_steps) [[unlikely]]
+ if (i > max_steps) [[unlikely]]
{
print_pos("*", start.pt, last_pos, time, dt);
Error{standard_error()} << "!!! fatal: position doesn't converge after" << i << "iterations!";
@@ -198,9 +203,13 @@ bool run(StringView subtest_name, world& w, const function_view<Ns() const>& mak
if (expected.time != Ns{})
{
const auto time_diff = Ns{Math::abs((int64_t)expected.time.stamp - (int64_t)time.stamp)};
- if (time_diff > expected.time)
+ if (time_diff > grace.time)
{
- Error{standard_error()} << "!!! fatal: time" << time_diff << "over tolerance of" << grace.max_time;
+ Error{ standard_error(), Debug::Flag::NoSpace }
+ << "!!! fatal: wrong time " << time
+ << " expected:" << expected.time
+ << " diff:" << grace.time
+ << " for " << start.name << "/" << start.instance;
if (grace.no_crash)
return false;
else
@@ -211,7 +220,7 @@ bool run(StringView subtest_name, world& w, const function_view<Ns() const>& mak
return true;
}
-void test1(StringView instance_name, const Function& make_dt, float accel)
+void test1(StringView instance_name, const Function& make_dt, double accel)
{
const auto W = wall_image_proto{ loader.wall_atlas("empty"), 0 };
@@ -219,7 +228,7 @@ void test1(StringView instance_name, const Function& make_dt, float accel)
w[{{0,0,0}, {8,9}}].t.wall_north() = W;
w[{{0,1,0}, {8,0}}].t.wall_north() = W;
- bool ret = run("test1", w, make_dt,
+ bool ret = run(w, make_dt,
Start{
.name = "test1"_s,
.instance = instance_name,
@@ -229,13 +238,15 @@ void test1(StringView instance_name, const Function& make_dt, float accel)
},
Expected{
.pt = {{0,0,0}, {8, 9}, {-6,-15}}, // distance_L2 == 3
- .time = Millisecond*6950,
+ .time = 6950*Millisecond,
},
- Grace{});
+ Grace{
+ .time = 300*Millisecond,
+ });
fm_assert(ret);
}
-void test2(StringView instance_name, const Function& make_dt, float accel)
+void test2(StringView instance_name, const Function& make_dt, double accel)
{
const auto W = wall_image_proto{ loader.wall_atlas("empty"), 0 };
@@ -245,19 +256,22 @@ void test2(StringView instance_name, const Function& make_dt, float accel)
w[{{1,1,0}, {4,5}}].t.wall_north() = W;
w[{{1,1,0}, {5,4}}].t.wall_west() = W;
- bool ret = run("test1", w, make_dt,
+ bool ret = run(w, make_dt,
Start{
- .name = "test1"_s,
+ .name = "test2"_s,
.instance = instance_name,
- .pt = {{1,1,0}, {4,4}, {-29, 8}},
+ .pt = {{-1,-1,0}, {13,14}, {-15,-29}},
.accel = accel,
- .rotation = NW,
+ .rotation = SE,
},
Expected{
- .pt = {{-1,-1,0}, {13, 13}, {-16,-16}}, // distance_L2 == 3
- .time = accel == 1 ? Ns{Millisecond*6900} : Ns{},
+ .pt = {{1,1,0}, {4, 4}, {8,8}},
+ .time = 35'000*Millisecond,
},
- Grace{});
+ Grace{
+ .time = 250*Millisecond,
+ .distance_L2 = 8,
+ });
fm_assert(ret);
}
@@ -270,17 +284,35 @@ void test_app::test_critter()
// <ESC>[2K
// \n
- if (!is_log_quiet())
+ const bool is_noisy = !Start{}.quiet;
+ if (is_noisy)
DBG_nospace << "";
- test1("dt=1000 accel=1", constantly(Millisecond * 1000 ), 1);
- test1("dt=1000 accel=5", constantly(Millisecond * 1000 ), 5);
- test1("dt=100 accel=5", constantly(Millisecond * 100 ), 5);
- test1("dt=50 accel=5", constantly(Millisecond * 50 ), 5);
- test1("dt=16.667 accel=10", constantly(Millisecond * 16.667), 10);
- test1("dt=16.667 accel=1", constantly(Millisecond * 16.667), 1);
- //test1("dt=16.5 ms accel=1", constantly(Millisecond * 16.5), 1); // todo! fix this!
- test2("dt=16.667 accel=5", constantly(Millisecond * 16.667), 5);
- if (!is_log_quiet())
+
+ test1("dt=16.667 accel=1", constantly(Millisecond * 16.667), 1);
+ test1("dt=16.667 accel=2", constantly(Millisecond * 16.667), 2);
+ test1("dt=16.667 accel=5", constantly(Millisecond * 16.667), 5);
+ test1("dt=33.337 accel=1", constantly(Millisecond * 33.337), 1);
+ test1("dt=33.337 accel=2", constantly(Millisecond * 33.337), 2);
+ test1("dt=33.337 accel=5", constantly(Millisecond * 33.337), 5);
+ test1("dt=16.667 accel=1", constantly(Millisecond * 50.000), 1);
+ test1("dt=16.667 accel=2", constantly(Millisecond * 50.000), 2);
+ test1("dt=16.667 accel=5", constantly(Millisecond * 50.000), 5);
+ test1("dt=200 accel=1", constantly(Millisecond * 200.0 ), 1);
+ test1("dt=100 accel=2", constantly(Millisecond * 100.0 ), 2);
+ // test1("dt=16.667 accel=0.5", constantly(Millisecond * 16.667),0.5); // todo! fix this!
+ test1("dt=100 accel=0.5", constantly(Millisecond * 100.0 ), 0.5);
+ //test1("dt=16.667 ms accel=1", constantly(Millisecond * 16.667), 1); // todo! fix this!
+ test2("dt=33.334 accel=1", constantly(Millisecond * 33.334), 1);
+ test2("dt=33.334 accel=2", constantly(Millisecond * 33.334), 2);
+ test2("dt=33.334 accel=5", constantly(Millisecond * 33.334), 5);
+ test2("dt=33.334 accel=10", constantly(Millisecond * 33.334), 10);
+ test2("dt=50.000 accel=1", constantly(Millisecond * 50.000), 1);
+ test2("dt=50.000 accel=2", constantly(Millisecond * 50.000), 2);
+ test2("dt=100.00 accel=1", constantly(Millisecond * 100.00), 1);
+ test2("dt=100.00 accel=2", constantly(Millisecond * 100.00), 2);
+ test2("dt=100.00 accel=0.5", constantly(Millisecond * 100.00), 0.5);
+
+ if (is_noisy)
{
std::fputc('\t', stdout);
std::fflush(stdout);