Skip to content

Commit

Permalink
test/critter: fix it
Browse files Browse the repository at this point in the history
Hopefully the CI failure as well.
  • Loading branch information
sthalik committed Mar 5, 2024
1 parent 54365cb commit ce339c6
Show file tree
Hide file tree
Showing 3 changed files with 142 additions and 76 deletions.
66 changes: 50 additions & 16 deletions src/timer-ns.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,27 +8,61 @@ namespace floormat {



Debug& operator<<(Debug& dbg, const Ns& box)
Debug& operator<<(Debug& dbg, const Ns& val)
{
const auto value = (float)((double)box.stamp * 1e-6);
const auto absval = Math::abs(value);
const char* unit;
double x = val.stamp;
int precision;
if (absval < 2)
precision = 4;
else if (absval < 5)
precision = 2;
else if (absval < 100)
if (val >= 10*Second)
{
unit = "s";
x *= 1e-9;
precision = 1;
}
#if 0
else if (val >= 1*Second)
{
unit = "ms";
x *= 1e-6;
precision = 3;

}
#endif
else if (val >= 100*Millisecond)
{
unit = "ms";
x *= 1e-6;
precision = 3;
}
else if (val >= 50*Microsecond)
{
unit = "ms";
x *= 1e-6;
precision = 4;
}
else if (val >= 1*Microsecond)
{
unit = "usec";
x *= 1e-3;
precision = 3;
}
else if (val.stamp > 1000)
{
char buf[64];
std::snprintf(buf, sizeof buf, "%llu_%llu ns",
val.stamp / 1000, val.stamp % 1000);
return dbg;
}
else
{
unit = "ns";
precision = 0;
auto flags = dbg.flags();
dbg << "";
dbg.setFlags(flags | Debug::Flag::NoSpace);
//dbg << "{";
dbg << fraction(value, precision);
dbg << " ms";
//dbg << "}";
dbg.setFlags(flags);
}
if (!precision)
dbg << (uint64_t)x << Debug::space << unit;
else
dbg << fraction((float)x, precision) << Debug::space << unit;

return dbg;
}

Expand Down
25 changes: 13 additions & 12 deletions src/timer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down
127 changes: 79 additions & 48 deletions test/critter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 0
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
};

Expand All @@ -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();
Expand All @@ -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
Expand All @@ -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]]
Expand All @@ -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!";
Expand All @@ -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
Expand All @@ -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,
Expand All @@ -229,9 +238,11 @@ 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);
}

Expand All @@ -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);
}

Expand All @@ -270,18 +284,35 @@ void test_app::test_critter()
// <ESC>[2K
// \n

const bool is_noisy = Start{}.verbose;

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);

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);
Expand Down

0 comments on commit ce339c6

Please sign in to comment.