obu-firmware builds against vanetza-idf from microbu-esp32c5/external, but that tree was gitignored, so a clone of this repository could not build the firmware it ships. It is now committed here as ordinary files in its own folder, microbu-esp32c5/: the colleague's commit cf4b99f plus the V2X2MAP bridge's signature verification (--trust) used on the bench. Nothing is fetched from or pushed to the colleague's repository; this repository and its remotes carry everything. The folder's own .gitignore keeps build output, downloaded components and private key material out, as it did there; the committed file set is identical to that repository's tracked files. The ESP32-C5 is still flashed from obu-firmware/, which only takes vanetza-idf from microbu-esp32c5/, so the two stay separate folders. FLASHING.md says how to take a newer version of the colleague's tree (copy it over the folder, rebuild, test, commit).
200 lines
5.7 KiB
C++
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);
|
|
}
|