Keep the colleague's microbu-esp32c5 tree in this repository
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).
This commit is contained in:
@@ -0,0 +1,15 @@
|
||||
include(UseGTest)
|
||||
configure_gtest_directory(LINK_LIBRARIES common)
|
||||
|
||||
add_gtest(BitNumber bit_number.cpp)
|
||||
add_gtest(ByteBuffer byte_buffer.cpp)
|
||||
add_gtest(ByteBufferSink byte_buffer_sink.cpp)
|
||||
add_gtest(ByteBufferSource byte_buffer_source.cpp)
|
||||
add_gtest(ByteOrder byte_order.cpp)
|
||||
add_gtest(ByteView byte_view.cpp)
|
||||
add_gtest(Hook hook.cpp)
|
||||
add_gtest(LruCache lru_cache.cpp)
|
||||
add_gtest(ObjectContainer object_container.cpp)
|
||||
add_gtest(ManualRuntime manual_runtime.cpp)
|
||||
add_gtest(UnitInterval unit_interval.cpp)
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include <vanetza/common/bit_number.hpp>
|
||||
#include <cstdint>
|
||||
|
||||
using namespace vanetza;
|
||||
|
||||
TEST(BitNumber, ctor) {
|
||||
BitNumber<uint32_t, 20> a;
|
||||
EXPECT_EQ(a.raw(), 0);
|
||||
|
||||
BitNumber<uint32_t, 20> b(0x0fffff);
|
||||
EXPECT_EQ(b.raw(), 0x0fffff);
|
||||
}
|
||||
|
||||
TEST(BitNumber, mask) {
|
||||
BitNumber<uint32_t, 20> a(0xf01234);
|
||||
EXPECT_EQ(a.raw(), 0x1234);
|
||||
|
||||
BitNumber<uint32_t, 1> b(4);
|
||||
EXPECT_EQ(b.raw(), 0);
|
||||
b = 1;
|
||||
EXPECT_EQ(b.raw(), 1);
|
||||
}
|
||||
|
||||
TEST(BitNumber, equality) {
|
||||
BitNumber<int8_t, 3> a;
|
||||
BitNumber<int8_t, 3> b(0);
|
||||
EXPECT_EQ(a, b);
|
||||
|
||||
a = 3;
|
||||
EXPECT_NE(a, b);
|
||||
}
|
||||
|
||||
TEST(BitNumber, less) {
|
||||
BitNumber<uint16_t, 4> a(3);
|
||||
BitNumber<uint16_t, 4> b(4);
|
||||
EXPECT_LT(a, b);
|
||||
EXPECT_LE(a, b);
|
||||
EXPECT_GT(b, a);
|
||||
|
||||
a = 4;
|
||||
EXPECT_LE(a, b);
|
||||
EXPECT_GE(a, b);
|
||||
|
||||
b = 17; // 17 is masked to 1
|
||||
EXPECT_LE(b, a);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include <vanetza/common/byte_buffer.hpp>
|
||||
#include <cstring>
|
||||
|
||||
using namespace vanetza;
|
||||
|
||||
struct A
|
||||
{
|
||||
char b[10];
|
||||
};
|
||||
|
||||
TEST(ByteBuffer, buffer_cast) {
|
||||
ByteBuffer buf = { 'A', ' ', 't', 'e', 's', 't', ' ', 'b', 'u', 'f', 'f', 'e', 'r' };
|
||||
ASSERT_GE(buf.size(), sizeof(A));
|
||||
A* a = buffer_cast<A>(buf);
|
||||
ASSERT_NE(nullptr, a);
|
||||
EXPECT_EQ(a->b[0], 'A');
|
||||
EXPECT_EQ(a->b[4], 's');
|
||||
EXPECT_EQ(a->b[9], 'f');
|
||||
}
|
||||
|
||||
TEST(ByteBuffer, buffer_copy) {
|
||||
A a;
|
||||
strcpy(a.b, "123456789");
|
||||
auto copy = buffer_copy(a);
|
||||
ASSERT_EQ(copy.size(), 10);
|
||||
EXPECT_EQ(copy[0], '1');
|
||||
EXPECT_EQ(copy[3], '4');
|
||||
EXPECT_EQ(copy[8], '9');
|
||||
EXPECT_EQ(copy[9], '\0');
|
||||
|
||||
a.b[0] = 'X';
|
||||
EXPECT_EQ(copy[0], '1');
|
||||
}
|
||||
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include <vanetza/common/byte_buffer_sink.hpp>
|
||||
#include <boost/iostreams/stream_buffer.hpp>
|
||||
#include <ostream>
|
||||
#include <string>
|
||||
|
||||
using namespace vanetza;
|
||||
|
||||
TEST(ByteBufferSink, write) {
|
||||
ByteBuffer buf;
|
||||
byte_buffer_sink sink(buf);
|
||||
boost::iostreams::stream_buffer<byte_buffer_sink> stream(sink);
|
||||
ASSERT_TRUE(buf.empty());
|
||||
|
||||
std::ostream os(&stream);
|
||||
ASSERT_TRUE(os.good());
|
||||
|
||||
const std::string data("Hello World!");
|
||||
os << data;
|
||||
os.flush();
|
||||
EXPECT_EQ(buf.size(), 12);
|
||||
|
||||
for (unsigned i = 0; i < buf.size(); ++i) {
|
||||
EXPECT_EQ(buf[i], data[i]);
|
||||
}
|
||||
|
||||
EXPECT_TRUE(os.good());
|
||||
}
|
||||
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include <vanetza/common/byte_buffer_source.hpp>
|
||||
#include <boost/iostreams/stream_buffer.hpp>
|
||||
#include <istream>
|
||||
|
||||
using namespace vanetza;
|
||||
|
||||
TEST(ByteBufferSource, read) {
|
||||
const ByteBuffer buf = { 0x01, 0x11, 0x12, 0x22, 0x23, 0x33, 0x34, 0x44 };
|
||||
byte_buffer_source source(buf);
|
||||
boost::iostreams::stream_buffer<byte_buffer_source> stream(source);
|
||||
|
||||
std::istream is(&stream);
|
||||
ASSERT_TRUE(is.good());
|
||||
|
||||
char read = '\0';
|
||||
unsigned read_bytes = 0;
|
||||
for (uint8_t byte : buf) {
|
||||
is >> read;
|
||||
EXPECT_NE(byte, '\0');
|
||||
EXPECT_EQ(byte, read);
|
||||
++read_bytes;
|
||||
}
|
||||
EXPECT_EQ(read_bytes, 8);
|
||||
|
||||
is >> read;
|
||||
EXPECT_TRUE(is.eof());
|
||||
}
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include <vanetza/common/byte_order.hpp>
|
||||
#include <sstream>
|
||||
|
||||
using namespace vanetza;
|
||||
|
||||
using le_type = EndianType<uint32_t, ByteOrder::LittleEndian>;
|
||||
using be_type = EndianType<uint32_t, ByteOrder::BigEndian>;
|
||||
|
||||
TEST(ByteOrder, equality)
|
||||
{
|
||||
EndianType<int, ByteOrder::BigEndian> a(3);
|
||||
EndianType<int, ByteOrder::BigEndian> b(3);
|
||||
EXPECT_EQ(a, b);
|
||||
|
||||
a = host_cast(static_cast<int>(4));
|
||||
EXPECT_NE(a, b);
|
||||
}
|
||||
|
||||
TEST(ByteOrder, access)
|
||||
{
|
||||
le_type a = host_cast<uint32_t>(0x12345678);
|
||||
be_type b = host_cast<uint32_t>(0x12345678);
|
||||
EXPECT_NE(a.get(), b.get());
|
||||
EXPECT_EQ(a.net(), b.net());
|
||||
EXPECT_EQ(a.host(), b.host());
|
||||
}
|
||||
|
||||
TEST(ByteOrder, less)
|
||||
{
|
||||
uint8be_t a { 3 };
|
||||
uint8be_t b { 5 };
|
||||
uint8be_t c { 5 };
|
||||
EXPECT_TRUE(a < b);
|
||||
EXPECT_FALSE(b < c);
|
||||
EXPECT_FALSE(b < a);
|
||||
}
|
||||
|
||||
TEST(ByteOrder, hash)
|
||||
{
|
||||
le_type a = host_cast<uint32_t>(0x12345678);
|
||||
be_type b = host_cast<uint32_t>(0x12345678);
|
||||
be_type c = host_cast<uint32_t>(0x78563412);
|
||||
EXPECT_EQ(std::hash<le_type>()(a), std::hash<le_type>()(a));
|
||||
EXPECT_EQ(std::hash<be_type>()(b), std::hash<be_type>()(b));
|
||||
EXPECT_NE(std::hash<be_type>()(b), std::hash<be_type>()(c));
|
||||
}
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include <vanetza/common/byte_view.hpp>
|
||||
#include <vanetza/common/byte_buffer_convertible.hpp>
|
||||
|
||||
using namespace vanetza;
|
||||
|
||||
TEST(ByteView, range_buffer) {
|
||||
ByteBuffer buffer = {1, 2, 3, 4, 5, 6, 7, 8};
|
||||
byte_view_range view = create_byte_view(buffer);
|
||||
ASSERT_EQ(buffer.size(), view.size());
|
||||
EXPECT_EQ(1, *view.begin());
|
||||
EXPECT_EQ(3, view[2]);
|
||||
}
|
||||
|
||||
TEST(ByteView, range_convertible) {
|
||||
byte_view_range view = create_byte_view(ByteBuffer());
|
||||
{
|
||||
std::string buffer = "temporary data";
|
||||
ByteBufferConvertible convertible { std::move(buffer) };
|
||||
// view should now own a byte buffer copy of original string
|
||||
view = create_byte_view(convertible);
|
||||
}
|
||||
|
||||
ASSERT_EQ(14, view.size());
|
||||
EXPECT_EQ('t', view[0]);
|
||||
EXPECT_EQ('y', view[8]);
|
||||
EXPECT_EQ('d', view[10]);
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include <vanetza/common/hook.hpp>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
using namespace vanetza;
|
||||
|
||||
TEST(Hook, variants) {
|
||||
Hook<int> hook_int;
|
||||
hook_int(28); // rvalue call
|
||||
int x = 29;
|
||||
hook_int(x); // lvalue (exact type)
|
||||
int& y = x;
|
||||
hook_int(y); // lvalue (compatible type)
|
||||
|
||||
Hook<double, float> hook_fp;
|
||||
hook_fp(23.0, -42.0f);
|
||||
|
||||
Hook<const std::string&, std::vector<int>> hook_objects;
|
||||
hook_objects("foo", {3, 2});
|
||||
|
||||
Hook<std::string&&> hook_rvalue_ref;
|
||||
hook_rvalue_ref("bar");
|
||||
}
|
||||
|
||||
TEST(Hook, invocation) {
|
||||
Hook<double, float> hook;
|
||||
double d = 3.0;
|
||||
float f = 5.3f;
|
||||
|
||||
// empty hook does nothing
|
||||
hook(0.0, 1.0f);
|
||||
EXPECT_EQ(3.0, d);
|
||||
EXPECT_EQ(5.3f, f);
|
||||
|
||||
// set hook and test it's magic
|
||||
hook = [&d, &f](double _d, float _f) { d = _d; f = _f; };
|
||||
hook(23.1, -384.34f);
|
||||
EXPECT_EQ(23.1, d);
|
||||
EXPECT_EQ(-384.34f, f);
|
||||
|
||||
// reset hook and it should do nothing again
|
||||
hook.reset();
|
||||
hook(0.0, 3.33f);
|
||||
EXPECT_EQ(23.1, d);
|
||||
EXPECT_EQ(-384.34f, f);
|
||||
}
|
||||
|
||||
TEST(HookRegistry, registration) {
|
||||
Hook<double> hook;
|
||||
HookRegistry<double> registry(hook);
|
||||
|
||||
double d = 42.0;
|
||||
registry = [&d](double _d) { d = _d; };
|
||||
hook(21.0);
|
||||
EXPECT_EQ(21.0, d);
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include <vanetza/common/lru_cache.hpp>
|
||||
|
||||
using namespace vanetza;
|
||||
|
||||
class LruCacheTest : public ::testing::Test
|
||||
{
|
||||
protected:
|
||||
void SetUp() override
|
||||
{
|
||||
generator_calls = 0;
|
||||
last_key = 0;
|
||||
}
|
||||
|
||||
std::function<int(int)> generator()
|
||||
{
|
||||
return [this](int key) {
|
||||
++generator_calls;
|
||||
last_key = key;
|
||||
return ~key;
|
||||
};
|
||||
}
|
||||
|
||||
unsigned generator_calls;
|
||||
int last_key;
|
||||
};
|
||||
|
||||
|
||||
TEST_F(LruCacheTest, caching)
|
||||
{
|
||||
LruCache<int, int> cache(generator(), 5);
|
||||
|
||||
// generate one new entry
|
||||
EXPECT_EQ(~8, cache[8]);
|
||||
EXPECT_EQ(1, generator_calls);
|
||||
|
||||
// refer to cached entry
|
||||
EXPECT_EQ(~8, cache[8]);
|
||||
EXPECT_EQ(1, generator_calls);
|
||||
|
||||
// further entry
|
||||
EXPECT_EQ(~4, cache[4]);
|
||||
EXPECT_EQ(2, generator_calls);
|
||||
|
||||
// first entry is still there
|
||||
EXPECT_EQ(~8, cache[8]);
|
||||
EXPECT_EQ(2, generator_calls);
|
||||
}
|
||||
|
||||
TEST_F(LruCacheTest, modify)
|
||||
{
|
||||
LruCache<int, int> cache(generator(), 5);
|
||||
|
||||
// modify new cache entry
|
||||
cache[8] = 23;
|
||||
EXPECT_EQ(23, cache[8]);
|
||||
|
||||
// modify existing entry
|
||||
cache[8] = 42;
|
||||
EXPECT_EQ(42, cache[8]);
|
||||
|
||||
EXPECT_EQ(1, generator_calls);
|
||||
}
|
||||
|
||||
TEST_F(LruCacheTest, drop_lru)
|
||||
{
|
||||
LruCache<int, int> cache(generator(), 3);
|
||||
cache[1];
|
||||
cache[2];
|
||||
cache[3];
|
||||
EXPECT_EQ(3, generator_calls);
|
||||
|
||||
EXPECT_EQ(~2, cache[2]); // LRU: 1, 3, 2
|
||||
cache[4]; // drop 1, LRU: 3, 2, 4
|
||||
cache[1]; // re-create entry, LRU: 2, 4, 1
|
||||
EXPECT_EQ(5, generator_calls);
|
||||
|
||||
EXPECT_EQ(~2, cache[2]);
|
||||
EXPECT_EQ(~4, cache[4]);
|
||||
EXPECT_EQ(~1, cache[1]);
|
||||
EXPECT_EQ(5, generator_calls);
|
||||
}
|
||||
+199
@@ -0,0 +1,199 @@
|
||||
#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);
|
||||
}
|
||||
+117
@@ -0,0 +1,117 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include <vanetza/common/object_container.hpp>
|
||||
|
||||
using namespace vanetza;
|
||||
|
||||
struct ObjectA
|
||||
{
|
||||
int a = 1;
|
||||
};
|
||||
|
||||
struct ObjectB
|
||||
{
|
||||
int b = 2;
|
||||
};
|
||||
|
||||
struct ObjectC
|
||||
{
|
||||
int c = 3;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
std::unique_ptr<T> create_unique()
|
||||
{
|
||||
return std::unique_ptr<T> { new T() };
|
||||
}
|
||||
|
||||
|
||||
TEST(ObjectContainer, size)
|
||||
{
|
||||
ObjectContainer c;
|
||||
EXPECT_EQ(0, c.size());
|
||||
|
||||
c.insert(create_unique<ObjectA>());
|
||||
EXPECT_EQ(1, c.size());
|
||||
|
||||
c.insert(create_unique<ObjectA>());
|
||||
EXPECT_EQ(1, c.size());
|
||||
|
||||
c.insert(create_unique<ObjectB>());
|
||||
EXPECT_EQ(2, c.size());
|
||||
|
||||
c.clear();
|
||||
EXPECT_EQ(0, c.size());
|
||||
}
|
||||
|
||||
TEST(ObjectContainer, insert)
|
||||
{
|
||||
ObjectContainer c;
|
||||
EXPECT_TRUE(c.insert(create_unique<ObjectA>()));
|
||||
EXPECT_FALSE(c.insert(create_unique<ObjectA>()));
|
||||
EXPECT_TRUE(c.insert(create_unique<ObjectB>()));
|
||||
}
|
||||
|
||||
TEST(ObjectContainer, find)
|
||||
{
|
||||
ObjectContainer c;
|
||||
EXPECT_EQ(nullptr, c.find<ObjectA>());
|
||||
|
||||
auto a = create_unique<ObjectA>();
|
||||
ObjectA* pa = a.get();
|
||||
auto b = create_unique<ObjectB>();
|
||||
ObjectB* pb = b.get();
|
||||
|
||||
c.insert(std::move(a));
|
||||
c.insert(std::move(b));
|
||||
EXPECT_EQ(pa, c.find<ObjectA>());
|
||||
EXPECT_EQ(pb, c.find<ObjectB>());
|
||||
}
|
||||
|
||||
TEST(ObjectContainer, erase)
|
||||
{
|
||||
ObjectContainer c;
|
||||
c.insert(create_unique<ObjectA>());
|
||||
ASSERT_EQ(1, c.size());
|
||||
c.erase<ObjectB>();
|
||||
EXPECT_EQ(1, c.size());
|
||||
c.erase<ObjectA>();
|
||||
EXPECT_EQ(0, c.size());
|
||||
|
||||
c.insert(create_unique<ObjectA>());
|
||||
c.insert(create_unique<ObjectB>());
|
||||
c.insert(create_unique<ObjectC>());
|
||||
c.erase<ObjectB>();
|
||||
EXPECT_EQ(2, c.size());
|
||||
EXPECT_NE(nullptr, c.find<ObjectA>());
|
||||
EXPECT_EQ(nullptr, c.find<ObjectB>());
|
||||
EXPECT_NE(nullptr, c.find<ObjectC>());
|
||||
}
|
||||
|
||||
TEST(ObjectContainer, move)
|
||||
{
|
||||
ObjectContainer c1;
|
||||
c1.insert(create_unique<ObjectA>());
|
||||
c1.insert(create_unique<ObjectB>());
|
||||
c1.insert(create_unique<ObjectC>());
|
||||
ASSERT_EQ(3, c1.size());
|
||||
|
||||
auto* pa = c1.find<ObjectA>();
|
||||
auto* pb = c1.find<ObjectB>();
|
||||
auto* pc = c1.find<ObjectC>();
|
||||
|
||||
ObjectContainer c2 = std::move(c1);
|
||||
EXPECT_EQ(0, c1.size());
|
||||
EXPECT_EQ(3, c2.size());
|
||||
EXPECT_EQ(pa, c2.find<ObjectA>());
|
||||
EXPECT_EQ(pb, c2.find<ObjectB>());
|
||||
EXPECT_EQ(pc, c2.find<ObjectC>());
|
||||
}
|
||||
|
||||
TEST(ObjectContainer, get)
|
||||
{
|
||||
ObjectContainer c;
|
||||
EXPECT_EQ(nullptr, c.find<ObjectA>());
|
||||
ObjectA& a = c.get<ObjectA>();
|
||||
EXPECT_EQ(1, a.a);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,168 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include <vanetza/common/unit_interval.hpp>
|
||||
|
||||
using namespace vanetza;
|
||||
|
||||
namespace vanetza {
|
||||
void PrintTo(const UnitInterval& cl, std::ostream* os) { *os << cl.value(); }
|
||||
}
|
||||
|
||||
TEST(UnitInterval, construction)
|
||||
{
|
||||
UnitInterval v1;
|
||||
EXPECT_DOUBLE_EQ(0.0, v1.value());
|
||||
|
||||
UnitInterval v2(0.42);
|
||||
EXPECT_DOUBLE_EQ(0.42, v2.value());
|
||||
|
||||
UnitInterval v3 = v2;
|
||||
EXPECT_DOUBLE_EQ(0.42, v3.value());
|
||||
|
||||
v3 = v1;
|
||||
EXPECT_DOUBLE_EQ(0.0, v3.value());
|
||||
}
|
||||
|
||||
TEST(UnitInterval, partially_ordered)
|
||||
{
|
||||
// only test < and == (other operators are provided by Boost)
|
||||
EXPECT_LT(UnitInterval(0.3), UnitInterval(0.4));
|
||||
EXPECT_EQ(UnitInterval(0.5), UnitInterval(0.5));
|
||||
|
||||
// stress equality comparison
|
||||
UnitInterval v1 { 0.0000001 };
|
||||
UnitInterval v2 { 0.00000005 };
|
||||
EXPECT_EQ(v1 * 1000000, v2 * 2000000);
|
||||
EXPECT_NE(UnitInterval(0.000000001), UnitInterval(0.0000000011));
|
||||
}
|
||||
|
||||
TEST(UnitInterval, range)
|
||||
{
|
||||
UnitInterval v1 { 3.14 };
|
||||
EXPECT_EQ(UnitInterval(1.0), v1);
|
||||
|
||||
UnitInterval v2 { -42.0 };
|
||||
EXPECT_EQ(UnitInterval(0.0), v2);
|
||||
}
|
||||
|
||||
TEST(UnitInterval, arithmetic_interval)
|
||||
{
|
||||
// only test +=, -=, *=, /= (symmetric operators by Boost)
|
||||
UnitInterval a1(0.45);
|
||||
a1 += UnitInterval(0.53);
|
||||
EXPECT_EQ(UnitInterval(0.98), a1);
|
||||
|
||||
UnitInterval a2(0.45);
|
||||
a2 += UnitInterval(0.6);
|
||||
EXPECT_EQ(UnitInterval(1.0), a2);
|
||||
|
||||
UnitInterval s1(0.45);
|
||||
s1 -= UnitInterval(0.35);
|
||||
EXPECT_EQ(UnitInterval(0.1), s1);
|
||||
|
||||
UnitInterval s2(0.3);
|
||||
s2 -= UnitInterval(0.4);
|
||||
EXPECT_EQ(UnitInterval(0.0), s2);
|
||||
|
||||
UnitInterval m1(0.2);
|
||||
m1 *= UnitInterval(0.5);
|
||||
EXPECT_EQ(UnitInterval(0.1), m1);
|
||||
|
||||
UnitInterval m2(0.4);
|
||||
m2 *= UnitInterval(0.0);
|
||||
EXPECT_EQ(UnitInterval(0.0), m2);
|
||||
|
||||
UnitInterval m3(1.0);
|
||||
m3 *= UnitInterval(1.0);
|
||||
EXPECT_EQ(UnitInterval(1.0), m3);
|
||||
|
||||
UnitInterval d1(0.6);
|
||||
d1 /= UnitInterval(0.8);
|
||||
EXPECT_EQ(UnitInterval(0.75), d1);
|
||||
|
||||
UnitInterval d2(0.5);
|
||||
d2 /= UnitInterval(0.1);
|
||||
EXPECT_EQ(UnitInterval(1.0), d2);
|
||||
}
|
||||
|
||||
TEST(UnitInterval, arithmetic_double)
|
||||
{
|
||||
// only test +=, -=, *=, /= (symmetric operators by Boost)
|
||||
UnitInterval a1(0.45);
|
||||
a1 += 0.53;
|
||||
EXPECT_EQ(UnitInterval(0.98), a1);
|
||||
|
||||
UnitInterval a2(0.45);
|
||||
a2 += 0.6;
|
||||
EXPECT_EQ(UnitInterval(1.0), a2);
|
||||
|
||||
UnitInterval a3(0.45);
|
||||
a3 += -0.7;
|
||||
EXPECT_EQ(UnitInterval(0.0), a3);
|
||||
|
||||
UnitInterval s1(0.45);
|
||||
s1 -= 0.35;
|
||||
EXPECT_EQ(UnitInterval(0.1), s1);
|
||||
|
||||
UnitInterval s2(0.3);
|
||||
s2 -= 0.4;
|
||||
EXPECT_EQ(UnitInterval(0.0), s2);
|
||||
|
||||
UnitInterval s3(0.3);
|
||||
s3 -= -0.8;
|
||||
EXPECT_EQ(UnitInterval(1.0), s3);
|
||||
|
||||
UnitInterval m1(0.2);
|
||||
m1 *= 0.5;
|
||||
EXPECT_EQ(UnitInterval(0.1), m1);
|
||||
|
||||
UnitInterval m2(0.4);
|
||||
m2 *= 0.0;
|
||||
EXPECT_EQ(UnitInterval(0.0), m2);
|
||||
|
||||
UnitInterval m3(1.0);
|
||||
m3 *= 1.2;
|
||||
EXPECT_EQ(UnitInterval(1.0), m3);
|
||||
|
||||
UnitInterval m4(0.3);
|
||||
m4 *= -0.1;
|
||||
EXPECT_EQ(UnitInterval(0.0), m4);
|
||||
|
||||
UnitInterval d1(0.6);
|
||||
d1 /= 0.8;
|
||||
EXPECT_EQ(UnitInterval(0.75), d1);
|
||||
|
||||
UnitInterval d2(0.5);
|
||||
d2 /= 0.1;
|
||||
EXPECT_EQ(UnitInterval(1.0), d2);
|
||||
|
||||
UnitInterval d3(0.2);
|
||||
d3 /= 2.0;
|
||||
EXPECT_EQ(UnitInterval(0.1), d3);
|
||||
|
||||
UnitInterval d4(0.5);
|
||||
d4 /= -0.4;
|
||||
EXPECT_EQ(UnitInterval(0.0), d4);
|
||||
}
|
||||
|
||||
TEST(UnitInterval, complement)
|
||||
{
|
||||
EXPECT_EQ(UnitInterval(0.0), UnitInterval(1.0).complement());
|
||||
EXPECT_EQ(UnitInterval(1.0), UnitInterval(0.0).complement());
|
||||
EXPECT_EQ(UnitInterval(1.0), UnitInterval(0.67) + UnitInterval(0.67).complement());
|
||||
}
|
||||
|
||||
TEST(UnitInterval, mean)
|
||||
{
|
||||
EXPECT_EQ(UnitInterval(0.3), mean(UnitInterval(0.1), UnitInterval(0.5)));
|
||||
EXPECT_EQ(UnitInterval(0.0), mean(UnitInterval(0.0), UnitInterval(0.0)));
|
||||
EXPECT_EQ(UnitInterval(0.75), mean(UnitInterval(1.0), UnitInterval(0.5)));
|
||||
}
|
||||
|
||||
TEST(UnitInterval, mean_range)
|
||||
{
|
||||
UnitInterval a[3] = { UnitInterval (0.4), UnitInterval(0.2), UnitInterval(0.9) };
|
||||
EXPECT_EQ(UnitInterval(0.0), mean(a, a));
|
||||
EXPECT_EQ(UnitInterval(0.2), mean(a + 1, a + 2));
|
||||
EXPECT_EQ(UnitInterval(0.3), mean(a, a + 2 ));
|
||||
EXPECT_EQ(UnitInterval(0.5), mean(a, a + 3));
|
||||
}
|
||||
Reference in New Issue
Block a user