Files
Ashin Walpola d107534eb2 Keep vanetza-idf in obu-firmware, so a plain clone builds the firmware
obu-firmware builds against the vanetza-idf C-ITS library, which until now
came from the colleague's microbu-esp32c5 tree beside the repository and was
not tracked here, so a clone of this repository could not build the firmware
it ships. The library alone is now part of obu-firmware, as
obu-firmware/external/vanetza-idf: their external/vanetza-idf at commit
cf4b99f, unchanged (9775 files; see its PROVENANCE.md). CMake takes it from
there by default; -DVANETZA_IDF_DIR still points the build elsewhere.

The rest of the colleague's tree (their own VAM firmware, PKI tooling,
station-link Python tools, the V2X2MAP bridge) stays out of this repository
and gitignored; nothing is pushed to their repository. NOTES.md, docs/06,
TODO.md and the pcap verifier's usage line point at the new location.
2026-09-24 10:56:05 +02:00

200 lines
5.7 KiB
C++

#include <gtest/gtest.h>
#include <vanetza/common/manual_runtime.hpp>
#include <chrono>
#include <functional>
#include <string>
#include <vector>
using namespace vanetza;
using std::chrono::hours;
using std::chrono::minutes;
using std::chrono::seconds;
TEST(ManualRuntime, default_construction)
{
ManualRuntime r;
EXPECT_EQ(std::chrono::milliseconds(0), r.now().time_since_epoch());
}
TEST(ManualRuntime, time_progress_absolute)
{
ManualRuntime r;
const Clock::time_point t1 { hours(27) };
r.trigger(t1);
EXPECT_EQ(t1, r.now());
const Clock::time_point t2 { hours(28) };
r.trigger(t2);
EXPECT_EQ(t2, r.now());
}
TEST(ManualRuntime, time_progress_relative)
{
ManualRuntime r;
r.trigger(hours(3));
EXPECT_EQ(Clock::time_point { hours(3) }, r.now());
r.trigger(hours(2));
EXPECT_EQ(Clock::time_point { hours(5) }, r.now());
}
TEST(ManualRuntime, sorting)
{
ManualRuntime r;
r.trigger(hours(3));
EXPECT_EQ(Clock::time_point::max(), r.next());
auto cb = [](Clock::time_point) {};
const auto tp1 = Clock::time_point { hours(2) };
static_cast<Runtime*>(&r)->schedule(tp1, cb);
EXPECT_EQ(tp1, r.next());
r.schedule(Clock::time_point { hours(3) }, cb);
EXPECT_EQ(tp1, r.next());
const auto tp2 = Clock::time_point { hours(1) };
r.schedule(tp2, cb);
EXPECT_EQ(tp2, r.next());
r.schedule(minutes(30), cb);
EXPECT_EQ(tp2, r.next());
}
TEST(ManualRuntime, scheduling)
{
ManualRuntime r;
r.trigger(hours(5));
namespace ph = std::placeholders;
std::string seq;
std::vector<Clock::time_point> deadlines;
auto cb = [&seq, &deadlines](const char* str, Clock::time_point deadline) {
deadlines.push_back(deadline);
seq.append(str);
};
r.schedule(hours(10), std::bind<void>(cb, "1", ph::_1));
r.schedule(hours(11), std::bind<void>(cb, "2", ph::_1));
r.schedule(hours(11), std::bind<void>(cb, "2", ph::_1));
r.schedule(hours(5), std::bind<void>(cb, "3", ph::_1));
r.trigger(hours(4));
EXPECT_EQ("", seq);
r.trigger(hours(1));
EXPECT_EQ("3", seq);
r.trigger(hours(5));
EXPECT_EQ("31", seq);
// schedule expired callback (immediate invocation at next trigger)
r.schedule(Clock::time_point { hours(2) }, std::bind<void>(cb, "4", ph::_1));
r.trigger(hours(0));
EXPECT_EQ("314", seq);
r.trigger(hours(5));
EXPECT_EQ("31422", seq);
r.trigger(Clock::time_point::max());
EXPECT_EQ("31422", seq);
const std::vector<Clock::time_point> expected_deadlines = {
Clock::time_point { hours(10) },
Clock::time_point { hours(15) },
Clock::time_point { hours(2) },
Clock::time_point { hours(16) },
Clock::time_point { hours(16) },
};
EXPECT_EQ(expected_deadlines, deadlines);
}
TEST(ManualRuntime, reset)
{
ManualRuntime r;
unsigned calls = 0;
auto cb = [&calls](Clock::time_point) { ++calls; };
r.trigger(hours(23));
for (unsigned i = 10; i < 100; ++i) {
r.schedule(seconds(i), cb);
}
r.trigger(seconds(9));
EXPECT_EQ(0, calls);
r.trigger(seconds(2));
EXPECT_EQ(2, calls);
EXPECT_EQ(Clock::time_point { hours(23) + seconds(11) }, r.now());
r.reset(Clock::time_point { hours(10) });
EXPECT_EQ(Clock::time_point { hours(10) }, r.now());
EXPECT_EQ(90, calls);
r.trigger(Clock::duration::max());
EXPECT_EQ(90, calls);
}
TEST(ManualRuntime, cancel)
{
ManualRuntime r;
std::vector<char> calls;
auto cb = [&calls](char c, Clock::time_point) { calls.push_back(c); };
// some dummy scopes
const int foo = 1;
const int bar = 2;
const int doe = 3;
namespace ph = std::placeholders;
r.schedule(minutes(3), std::bind<void>(cb, 'a', ph::_1));
r.schedule(minutes(4), std::bind<void>(cb, 'b', ph::_1), &foo);
r.schedule(minutes(5), std::bind<void>(cb, 'c', ph::_1));
r.schedule(minutes(3), std::bind<void>(cb, 'd', ph::_1), &bar);
r.schedule(minutes(4), std::bind<void>(cb, 'e', ph::_1));
r.schedule(minutes(5), std::bind<void>(cb, 'f', ph::_1), &foo);
r.schedule(minutes(6), std::bind<void>(cb, 'g', ph::_1), &doe);
r.schedule(minutes(7), std::bind<void>(cb, 'h', ph::_1), nullptr);
// cancel single callback
r.cancel(&bar);
r.trigger(minutes(8));
EXPECT_EQ((std::vector<char> {'a', 'b', 'e', 'c', 'f', 'g', 'h'}), calls);
// cancel several callbacks
calls.clear();
r.schedule(minutes(1), std::bind<void>(cb, 'a', ph::_1), &foo);
r.schedule(minutes(1), std::bind<void>(cb, 'b', ph::_1), &bar);
r.schedule(minutes(1), std::bind<void>(cb, 'c', ph::_1), &bar);
r.schedule(minutes(1), std::bind<void>(cb, 'd', ph::_1), &foo);
r.cancel(&foo);
r.trigger(minutes(1));
EXPECT_EQ((std::vector<char> {'b', 'c'}), calls);
}
TEST(ManualRuntime, scope)
{
ManualRuntime r;
std::vector<char> calls;
auto cb = [&calls](char c, Clock::time_point) { calls.push_back(c); };
int scope1, scope2;
namespace ph = std::placeholders;
r.schedule(minutes(3), std::bind<void>(cb, 'a', ph::_1), &scope1);
r.schedule(minutes(1), std::bind<void>(cb, 'b', ph::_1), &scope2);
r.schedule(minutes(2), std::bind<void>(cb, 'c', ph::_1));
r.schedule(minutes(5), std::bind<void>(cb, 'd', ph::_1), &scope1);
r.schedule(minutes(4), std::bind<void>(cb, 'e', ph::_1), &scope2);
r.schedule(minutes(6), std::bind<void>(cb, 'f', ph::_1), "");
// cancel scope 1 and trigger all callbacks within 3 minutes
r.cancel(&scope1);
r.trigger(minutes(3));
EXPECT_EQ((std::vector<char> {'b', 'c'}), calls);
calls.clear();
// canceling nullptr scope has no effect
r.cancel(nullptr);
r.trigger(minutes(10));
EXPECT_EQ((std::vector<char> {'e', 'f'}), calls);
}