mirror of
https://gitee.com/mirrors_PX4/PX4-Autopilot.git
synced 2026-10-23 18:43:34 +08:00
Superrefactoring - all time values were replaced with new safer classes from uavcan/time.hpp; generated types were moved away from anonymous namespaces because this makes it impossible to use a type from different compilation units. Some less vital fixes are to follow - see the next few commits
This commit is contained in:
+20
-14
@@ -28,21 +28,21 @@ public:
|
||||
utc += usec;
|
||||
}
|
||||
|
||||
uint64_t getMonotonicMicroseconds() const
|
||||
uavcan::MonotonicTime getMonotonic() const
|
||||
{
|
||||
assert(this);
|
||||
const uint64_t res = monotonic;
|
||||
advance(monotonic_auto_advance);
|
||||
return res;
|
||||
return uavcan::MonotonicTime::fromUSec(res);
|
||||
}
|
||||
|
||||
uint64_t getUtcMicroseconds() const
|
||||
uavcan::UtcTime getUtc() const
|
||||
{
|
||||
assert(this);
|
||||
return utc;
|
||||
return uavcan::UtcTime::fromUSec(utc);
|
||||
}
|
||||
|
||||
void adjustUtcMicroseconds(uint64_t new_timestamp_usec, int64_t offset_usec)
|
||||
void adjustUtc(uavcan::UtcTime, uavcan::UtcDuration)
|
||||
{
|
||||
assert(0);
|
||||
}
|
||||
@@ -52,37 +52,43 @@ public:
|
||||
class SystemClockDriver : public uavcan::ISystemClock
|
||||
{
|
||||
public:
|
||||
uint64_t getMonotonicMicroseconds() const
|
||||
uavcan::MonotonicTime getMonotonic() const
|
||||
{
|
||||
struct timespec ts;
|
||||
const int ret = clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||
if (ret != 0)
|
||||
{
|
||||
assert(0);
|
||||
return 0;
|
||||
return uavcan::MonotonicTime();
|
||||
}
|
||||
return uint64_t(ts.tv_sec) * 1000000UL + ts.tv_nsec / 1000UL;
|
||||
return uavcan::MonotonicTime::fromUSec(uint64_t(ts.tv_sec) * 1000000UL + ts.tv_nsec / 1000UL);
|
||||
}
|
||||
|
||||
uint64_t getUtcMicroseconds() const
|
||||
uavcan::UtcTime getUtc() const
|
||||
{
|
||||
struct timeval tv;
|
||||
const int ret = gettimeofday(&tv, NULL);
|
||||
if (ret != 0)
|
||||
{
|
||||
assert(0);
|
||||
return 0;
|
||||
return uavcan::UtcTime();
|
||||
}
|
||||
return uint64_t(tv.tv_sec) * 1000000UL + tv.tv_usec;
|
||||
return uavcan::UtcTime::fromUSec(uint64_t(tv.tv_sec) * 1000000UL + tv.tv_usec);
|
||||
}
|
||||
|
||||
void adjustUtcMicroseconds(uint64_t new_timestamp_usec, int64_t offset_usec)
|
||||
void adjustUtc(uavcan::UtcTime, uavcan::UtcDuration)
|
||||
{
|
||||
assert(0);
|
||||
}
|
||||
};
|
||||
|
||||
static bool areTimestampsClose(int64_t a, int64_t b, int64_t precision_usec = 10000)
|
||||
static uavcan::MonotonicTime tsMono(uint64_t usec) { return uavcan::MonotonicTime::fromUSec(usec); }
|
||||
static uavcan::UtcTime tsUtc(uint64_t usec) { return uavcan::UtcTime::fromUSec(usec); }
|
||||
|
||||
static uavcan::MonotonicDuration durMono(int64_t usec) { return uavcan::MonotonicDuration::fromUSec(usec); }
|
||||
|
||||
template <typename T>
|
||||
static bool areTimestampsClose(const T& a, const T& b, int64_t precision_usec = 10000)
|
||||
{
|
||||
return std::abs(a - b) < precision_usec;
|
||||
return (a - b).getAbs().toUSec() < precision_usec;
|
||||
}
|
||||
|
||||
@@ -47,35 +47,35 @@ TEST(Scheduler, Timers)
|
||||
|
||||
ASSERT_EQ(0, sch.getMonotonicDeadlineScheduler().getNumHandlers());
|
||||
|
||||
const uint64_t start_ts = clock_driver.getMonotonicMicroseconds();
|
||||
const uavcan::MonotonicTime start_ts = clock_driver.getMonotonic();
|
||||
|
||||
a.startOneShotWithDeadline(start_ts + 100000);
|
||||
b.startPeriodic(1000);
|
||||
a.startOneShotWithDeadline(start_ts + durMono(100000));
|
||||
b.startPeriodic(durMono(1000));
|
||||
|
||||
ASSERT_EQ(2, sch.getMonotonicDeadlineScheduler().getNumHandlers());
|
||||
|
||||
/*
|
||||
* Spinning
|
||||
*/
|
||||
ASSERT_EQ(0, sch.spin(start_ts + 1000000));
|
||||
ASSERT_EQ(0, sch.spin(start_ts + durMono(1000000)));
|
||||
|
||||
ASSERT_EQ(1, tcc.events_a.size());
|
||||
ASSERT_TRUE(areTimestampsClose(tcc.events_a[0].scheduled_monotonic_deadline, start_ts + 100000));
|
||||
ASSERT_TRUE(areTimestampsClose(tcc.events_a[0].monotonic_timestamp,
|
||||
tcc.events_a[0].scheduled_monotonic_deadline));
|
||||
ASSERT_TRUE(areTimestampsClose(tcc.events_a[0].scheduled_deadline, start_ts + durMono(100000)));
|
||||
ASSERT_TRUE(areTimestampsClose(tcc.events_a[0].current_timestamp,
|
||||
tcc.events_a[0].scheduled_deadline));
|
||||
ASSERT_EQ(&a, tcc.events_a[0].timer);
|
||||
|
||||
ASSERT_LT(900, tcc.events_b.size());
|
||||
ASSERT_GT(1100, tcc.events_b.size());
|
||||
{
|
||||
uint64_t next_expected_deadline = start_ts + 1000;
|
||||
uavcan::MonotonicTime next_expected_deadline = start_ts + durMono(1000);
|
||||
for (unsigned int i = 0; i < tcc.events_b.size(); i++)
|
||||
{
|
||||
ASSERT_TRUE(areTimestampsClose(tcc.events_b[i].scheduled_monotonic_deadline, next_expected_deadline));
|
||||
ASSERT_TRUE(areTimestampsClose(tcc.events_b[i].monotonic_timestamp,
|
||||
tcc.events_b[i].scheduled_monotonic_deadline));
|
||||
ASSERT_TRUE(areTimestampsClose(tcc.events_b[i].scheduled_deadline, next_expected_deadline));
|
||||
ASSERT_TRUE(areTimestampsClose(tcc.events_b[i].current_timestamp,
|
||||
tcc.events_b[i].scheduled_deadline));
|
||||
ASSERT_EQ(&b, tcc.events_b[i].timer);
|
||||
next_expected_deadline += 1000;
|
||||
next_expected_deadline += durMono(1000);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -85,12 +85,12 @@ TEST(Scheduler, Timers)
|
||||
ASSERT_EQ(1, sch.getMonotonicDeadlineScheduler().getNumHandlers());
|
||||
|
||||
ASSERT_FALSE(a.isRunning());
|
||||
ASSERT_EQ(uavcan::Timer::InfinitePeriod, a.getPeriod());
|
||||
ASSERT_EQ(uavcan::MonotonicDuration::getInfinite(), a.getPeriod());
|
||||
|
||||
ASSERT_TRUE(b.isRunning());
|
||||
ASSERT_EQ(1000, b.getPeriod());
|
||||
ASSERT_EQ(1000, b.getPeriod().toUSec());
|
||||
}
|
||||
|
||||
ASSERT_EQ(0, sch.getMonotonicDeadlineScheduler().getNumHandlers()); // Both timers were destroyed now
|
||||
ASSERT_EQ(0, sch.spin(clock_driver.getMonotonicMicroseconds() + 1000)); // Spin some more without timers
|
||||
ASSERT_EQ(0, sch.getMonotonicDeadlineScheduler().getNumHandlers()); // Both timers were destroyed now
|
||||
ASSERT_EQ(0, sch.spin(clock_driver.getMonotonic() + durMono(1000))); // Spin some more without timers
|
||||
}
|
||||
|
||||
@@ -21,12 +21,17 @@ public:
|
||||
struct FrameWithTime
|
||||
{
|
||||
uavcan::CanFrame frame;
|
||||
uint64_t time;
|
||||
uavcan::MonotonicTime time;
|
||||
|
||||
FrameWithTime(const uavcan::CanFrame& frame, uint64_t time)
|
||||
FrameWithTime(const uavcan::CanFrame& frame, uavcan::MonotonicTime time)
|
||||
: frame(frame)
|
||||
, time(time)
|
||||
{ }
|
||||
|
||||
FrameWithTime(const uavcan::CanFrame& frame, uint64_t time_usec)
|
||||
: frame(frame)
|
||||
, time(uavcan::MonotonicTime::fromUSec(time_usec))
|
||||
{ }
|
||||
};
|
||||
|
||||
std::queue<FrameWithTime> tx; ///< Queue of outgoing frames (bus <-- library)
|
||||
@@ -47,7 +52,7 @@ public:
|
||||
|
||||
void pushRx(const uavcan::CanFrame& frame)
|
||||
{
|
||||
rx.push(FrameWithTime(frame, iclock.getMonotonicMicroseconds()));
|
||||
rx.push(FrameWithTime(frame, iclock.getMonotonic()));
|
||||
}
|
||||
|
||||
void pushRx(const uavcan::RxFrame& frame)
|
||||
@@ -57,7 +62,7 @@ public:
|
||||
rx.push(FrameWithTime(can_frame, frame.getMonotonicTimestamp()));
|
||||
}
|
||||
|
||||
bool matchAndPopTx(const uavcan::CanFrame& frame, uint64_t tx_deadline)
|
||||
bool matchAndPopTx(const uavcan::CanFrame& frame, uavcan::MonotonicTime tx_deadline)
|
||||
{
|
||||
if (tx.empty())
|
||||
{
|
||||
@@ -69,7 +74,12 @@ public:
|
||||
return (frame_time.frame == frame) && (frame_time.time == tx_deadline);
|
||||
}
|
||||
|
||||
int send(const uavcan::CanFrame& frame, uint64_t tx_timeout_usec)
|
||||
bool matchAndPopTx(const uavcan::CanFrame& frame, uint64_t tx_deadline_usec)
|
||||
{
|
||||
return matchAndPopTx(frame, uavcan::MonotonicTime::fromUSec(tx_deadline_usec));
|
||||
}
|
||||
|
||||
int send(const uavcan::CanFrame& frame, uavcan::MonotonicTime tx_deadline)
|
||||
{
|
||||
assert(this);
|
||||
EXPECT_TRUE(writeable); // Shall never be called when not writeable
|
||||
@@ -77,12 +87,11 @@ public:
|
||||
return -1;
|
||||
if (!writeable)
|
||||
return 0;
|
||||
const uint64_t monotonic_deadline = tx_timeout_usec + iclock.getMonotonicMicroseconds();
|
||||
tx.push(FrameWithTime(frame, monotonic_deadline));
|
||||
tx.push(FrameWithTime(frame, tx_deadline));
|
||||
return 1;
|
||||
}
|
||||
|
||||
int receive(uavcan::CanFrame& out_frame, uint64_t& out_ts_monotonic_usec, uint64_t& out_ts_utc_usec)
|
||||
int receive(uavcan::CanFrame& out_frame, uavcan::MonotonicTime& out_ts_monotonic, uavcan::UtcTime& out_ts_utc)
|
||||
{
|
||||
assert(this);
|
||||
EXPECT_TRUE(rx.size()); // Shall never be called when not readable
|
||||
@@ -93,8 +102,8 @@ public:
|
||||
const FrameWithTime frame = rx.front();
|
||||
rx.pop();
|
||||
out_frame = frame.frame;
|
||||
out_ts_monotonic_usec = frame.time;
|
||||
out_ts_utc_usec = 0;
|
||||
out_ts_monotonic = frame.time;
|
||||
out_ts_utc = uavcan::UtcTime();
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -119,7 +128,7 @@ public:
|
||||
, select_failure(false)
|
||||
{ }
|
||||
|
||||
int select(int& inout_write_iface_mask, int& inout_read_iface_mask, uint64_t timeout_usec)
|
||||
int select(int& inout_write_iface_mask, int& inout_read_iface_mask, uavcan::MonotonicTime deadline)
|
||||
{
|
||||
assert(this);
|
||||
//std::cout << "Write/read masks: " << inout_write_iface_mask << "/" << inout_read_iface_mask << std::endl;
|
||||
@@ -145,11 +154,19 @@ public:
|
||||
inout_read_iface_mask = out_read_mask;
|
||||
if ((out_write_mask | out_read_mask) == 0)
|
||||
{
|
||||
const uavcan::MonotonicTime ts = iclock.getMonotonic();
|
||||
const uavcan::MonotonicDuration diff = deadline - ts;
|
||||
SystemClockMock* const mock = dynamic_cast<SystemClockMock*>(&iclock);
|
||||
if (mock)
|
||||
mock->advance(timeout_usec); // Emulating timeout
|
||||
{
|
||||
if (diff.isPositive())
|
||||
mock->advance(diff.toUSec()); // Emulating timeout
|
||||
}
|
||||
else
|
||||
usleep(timeout_usec);
|
||||
{
|
||||
if (diff.isPositive())
|
||||
usleep(diff.toUSec());
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
return 1; // This value is not being checked anyway, it just has to be greater than zero
|
||||
|
||||
@@ -17,7 +17,7 @@ TEST(CanIOManager, CanDriverMock)
|
||||
// All WR, no RD
|
||||
int mask_wr = 7;
|
||||
int mask_rd = 7;
|
||||
EXPECT_LT(0, driver.select(mask_wr, mask_rd, 100));
|
||||
EXPECT_LT(0, driver.select(mask_wr, mask_rd, uavcan::MonotonicTime::fromUSec(100)));
|
||||
EXPECT_EQ(7, mask_wr);
|
||||
EXPECT_EQ(0, mask_rd);
|
||||
|
||||
@@ -27,7 +27,7 @@ TEST(CanIOManager, CanDriverMock)
|
||||
// No WR, no RD
|
||||
mask_wr = 7;
|
||||
mask_rd = 7;
|
||||
EXPECT_EQ(0, driver.select(mask_wr, mask_rd, 100));
|
||||
EXPECT_EQ(0, driver.select(mask_wr, mask_rd, uavcan::MonotonicTime::fromUSec(100)));
|
||||
EXPECT_EQ(0, mask_wr);
|
||||
EXPECT_EQ(0, mask_rd);
|
||||
EXPECT_EQ(100, clockmock.monotonic);
|
||||
@@ -38,22 +38,23 @@ TEST(CanIOManager, CanDriverMock)
|
||||
driver.ifaces.at(1).pushRx(fr1);
|
||||
mask_wr = 7;
|
||||
mask_rd = 6;
|
||||
EXPECT_LT(0, driver.select(mask_wr, mask_rd, 100));
|
||||
EXPECT_LT(0, driver.select(mask_wr, mask_rd, uavcan::MonotonicTime::fromUSec(100)));
|
||||
EXPECT_EQ(0, mask_wr);
|
||||
EXPECT_EQ(2, mask_rd);
|
||||
CanFrame fr2;
|
||||
uint64_t ts_monotonic, ts_utc;
|
||||
uavcan::MonotonicTime ts_monotonic;
|
||||
uavcan::UtcTime ts_utc;
|
||||
EXPECT_EQ(1, driver.getIface(1)->receive(fr2, ts_monotonic, ts_utc));
|
||||
EXPECT_EQ(fr1, fr2);
|
||||
EXPECT_EQ(100, ts_monotonic);
|
||||
EXPECT_EQ(0, ts_utc);
|
||||
EXPECT_EQ(100, ts_monotonic.toUSec());
|
||||
EXPECT_EQ(0, ts_utc.toUSec());
|
||||
|
||||
// #0 WR, #1 RD, Select failure
|
||||
driver.ifaces.at(0).writeable = true;
|
||||
driver.select_failure = true;
|
||||
mask_wr = 1;
|
||||
mask_rd = 7;
|
||||
EXPECT_EQ(-1, driver.select(mask_wr, mask_rd, 100));
|
||||
EXPECT_EQ(1, mask_wr); // Leaving masks unchanged - library must ignore them
|
||||
EXPECT_EQ(-1, driver.select(mask_wr, mask_rd, uavcan::MonotonicTime::fromUSec(100)));
|
||||
EXPECT_EQ(1, mask_wr); // Leaving masks unchanged - the library must ignore them
|
||||
EXPECT_EQ(7, mask_rd);
|
||||
}
|
||||
|
||||
@@ -5,9 +5,8 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include "can.hpp"
|
||||
|
||||
|
||||
static bool rxFrameEquals(const uavcan::CanRxFrame& rxframe, const uavcan::CanFrame& frame,
|
||||
uint64_t timestamp, int iface_index)
|
||||
uint64_t timestamp_usec, int iface_index)
|
||||
{
|
||||
if (static_cast<const uavcan::CanFrame&>(rxframe) != frame)
|
||||
{
|
||||
@@ -16,7 +15,7 @@ static bool rxFrameEquals(const uavcan::CanRxFrame& rxframe, const uavcan::CanFr
|
||||
<< " " << frame.toString(uavcan::CanFrame::StrAligned) << std::endl;
|
||||
}
|
||||
return (static_cast<const uavcan::CanFrame&>(rxframe) == frame) &&
|
||||
(rxframe.ts_monotonic == timestamp) && (rxframe.iface_index == iface_index);
|
||||
(rxframe.ts_mono == uavcan::MonotonicTime::fromUSec(timestamp_usec)) && (rxframe.iface_index == iface_index);
|
||||
}
|
||||
|
||||
TEST(CanIOManager, Reception)
|
||||
@@ -38,7 +37,7 @@ TEST(CanIOManager, Reception)
|
||||
* Empty, will time out
|
||||
*/
|
||||
uavcan::CanRxFrame frame;
|
||||
EXPECT_EQ(0, iomgr.receive(frame, 100));
|
||||
EXPECT_EQ(0, iomgr.receive(frame, tsMono(100)));
|
||||
EXPECT_EQ(100, clockmock.monotonic);
|
||||
EXPECT_EQ(100, clockmock.utc);
|
||||
|
||||
@@ -61,36 +60,36 @@ TEST(CanIOManager, Reception)
|
||||
driver.ifaces.at(1).pushRx(frames[1][2]);
|
||||
clockmock.advance(10);
|
||||
|
||||
EXPECT_EQ(1, iomgr.receive(frame, 0));
|
||||
EXPECT_EQ(1, iomgr.receive(frame, uavcan::MonotonicTime()));
|
||||
EXPECT_TRUE(rxFrameEquals(frame, frames[0][0], 110, 0));
|
||||
|
||||
EXPECT_EQ(1, iomgr.receive(frame, 0));
|
||||
EXPECT_EQ(1, iomgr.receive(frame, uavcan::MonotonicTime()));
|
||||
EXPECT_TRUE(rxFrameEquals(frame, frames[0][1], 120, 0));
|
||||
|
||||
EXPECT_EQ(1, iomgr.receive(frame, 0));
|
||||
EXPECT_EQ(1, iomgr.receive(frame, uavcan::MonotonicTime()));
|
||||
EXPECT_TRUE(rxFrameEquals(frame, frames[0][2], 130, 0));
|
||||
|
||||
EXPECT_EQ(1, iomgr.receive(frame, 0));
|
||||
EXPECT_EQ(1, iomgr.receive(frame, uavcan::MonotonicTime()));
|
||||
EXPECT_TRUE(rxFrameEquals(frame, frames[1][0], 110, 1));
|
||||
|
||||
EXPECT_EQ(1, iomgr.receive(frame, 0));
|
||||
EXPECT_EQ(1, iomgr.receive(frame, uavcan::MonotonicTime()));
|
||||
EXPECT_TRUE(rxFrameEquals(frame, frames[1][1], 120, 1));
|
||||
|
||||
EXPECT_EQ(1, iomgr.receive(frame, 0));
|
||||
EXPECT_EQ(1, iomgr.receive(frame, uavcan::MonotonicTime()));
|
||||
EXPECT_TRUE(rxFrameEquals(frame, frames[1][2], 130, 1));
|
||||
|
||||
EXPECT_EQ(0, iomgr.receive(frame, 0)); // Will time out
|
||||
EXPECT_EQ(0, iomgr.receive(frame, uavcan::MonotonicTime())); // Will time out
|
||||
|
||||
/*
|
||||
* Errors
|
||||
*/
|
||||
driver.select_failure = true;
|
||||
EXPECT_EQ(-1, iomgr.receive(frame, 0));
|
||||
EXPECT_EQ(-1, iomgr.receive(frame, uavcan::MonotonicTime()));
|
||||
|
||||
driver.select_failure = false;
|
||||
driver.ifaces.at(1).pushRx(frames[0][0]);
|
||||
driver.ifaces.at(1).rx_failure = true;
|
||||
EXPECT_EQ(-1, iomgr.receive(frame, 0));
|
||||
EXPECT_EQ(-1, iomgr.receive(frame, uavcan::MonotonicTime()));
|
||||
|
||||
driver.ifaces.at(0).num_errors = 9000;
|
||||
driver.ifaces.at(1).num_errors = 100500;
|
||||
@@ -127,11 +126,11 @@ TEST(CanIOManager, Transmission)
|
||||
/*
|
||||
* Simple transmission
|
||||
*/
|
||||
EXPECT_EQ(2, iomgr.send(frames[0], 100, 0, ALL_IFACES_MASK, CanTxQueue::Volatile)); // To both
|
||||
EXPECT_EQ(2, iomgr.send(frames[0], tsMono(100), tsMono(0), ALL_IFACES_MASK, CanTxQueue::Volatile)); // To both
|
||||
EXPECT_TRUE(driver.ifaces.at(0).matchAndPopTx(frames[0], 100));
|
||||
EXPECT_TRUE(driver.ifaces.at(1).matchAndPopTx(frames[0], 100));
|
||||
|
||||
EXPECT_EQ(1, iomgr.send(frames[1], 200, 100, 2, CanTxQueue::Persistent)); // To #1
|
||||
EXPECT_EQ(1, iomgr.send(frames[1], tsMono(200), tsMono(100), 2, CanTxQueue::Persistent)); // To #1
|
||||
EXPECT_TRUE(driver.ifaces.at(1).matchAndPopTx(frames[1], 200));
|
||||
|
||||
EXPECT_EQ(0, clockmock.monotonic);
|
||||
@@ -148,7 +147,7 @@ TEST(CanIOManager, Transmission)
|
||||
|
||||
// Sending to both, #0 blocked
|
||||
driver.ifaces.at(0).writeable = false;
|
||||
EXPECT_LT(0, iomgr.send(frames[0], 201, 200, ALL_IFACES_MASK, CanTxQueue::Persistent));
|
||||
EXPECT_LT(0, iomgr.send(frames[0], tsMono(201), tsMono(200), ALL_IFACES_MASK, CanTxQueue::Persistent));
|
||||
EXPECT_TRUE(driver.ifaces.at(1).matchAndPopTx(frames[0], 201));
|
||||
EXPECT_EQ(200, clockmock.monotonic);
|
||||
EXPECT_EQ(200, clockmock.utc);
|
||||
@@ -158,11 +157,11 @@ TEST(CanIOManager, Transmission)
|
||||
|
||||
// Sending to both, both blocked
|
||||
driver.ifaces.at(1).writeable = false;
|
||||
EXPECT_EQ(0, iomgr.send(frames[1], 777, 300, ALL_IFACES_MASK, CanTxQueue::Volatile));
|
||||
EXPECT_EQ(0, iomgr.send(frames[1], tsMono(777), tsMono(300), ALL_IFACES_MASK, CanTxQueue::Volatile));
|
||||
EXPECT_EQ(3, pool.getNumUsedBlocks()); // Total 3 frames in TX queue now
|
||||
|
||||
// Sending to #0, both blocked
|
||||
EXPECT_EQ(0, iomgr.send(frames[2], 888, 400, 1, CanTxQueue::Persistent));
|
||||
EXPECT_EQ(0, iomgr.send(frames[2], tsMono(888), tsMono(400), 1, CanTxQueue::Persistent));
|
||||
EXPECT_EQ(400, clockmock.monotonic);
|
||||
EXPECT_EQ(400, clockmock.utc);
|
||||
EXPECT_TRUE(driver.ifaces.at(0).tx.empty());
|
||||
@@ -176,7 +175,7 @@ TEST(CanIOManager, Transmission)
|
||||
// Sending to #1, both writeable
|
||||
driver.ifaces.at(0).writeable = true;
|
||||
driver.ifaces.at(1).writeable = true;
|
||||
EXPECT_LT(0, iomgr.send(frames[0], 999, 500, 2, CanTxQueue::Persistent)); // One frame per each iface will be sent
|
||||
EXPECT_LT(0, iomgr.send(frames[0], tsMono(999), tsMono(500), 2, CanTxQueue::Persistent)); // One frame per each iface will be sent
|
||||
EXPECT_TRUE(driver.ifaces.at(0).matchAndPopTx(frames[1], 777)); // Note that frame[0] on iface #0 has expired
|
||||
EXPECT_TRUE(driver.ifaces.at(1).matchAndPopTx(frames[0], 999)); // In different order due to prioritization
|
||||
EXPECT_TRUE(driver.ifaces.at(0).tx.empty());
|
||||
@@ -184,7 +183,7 @@ TEST(CanIOManager, Transmission)
|
||||
|
||||
// Calling receive() to flush the rest two frames
|
||||
uavcan::CanRxFrame dummy_rx_frame;
|
||||
EXPECT_EQ(0, iomgr.receive(dummy_rx_frame, 0));
|
||||
EXPECT_EQ(0, iomgr.receive(dummy_rx_frame, tsMono(0)));
|
||||
EXPECT_TRUE(driver.ifaces.at(0).matchAndPopTx(frames[2], 888));
|
||||
EXPECT_TRUE(driver.ifaces.at(1).matchAndPopTx(frames[1], 777));
|
||||
|
||||
@@ -202,9 +201,9 @@ TEST(CanIOManager, Transmission)
|
||||
driver.ifaces.at(1).writeable = false;
|
||||
|
||||
// Sending 5 frames, one will be rejected
|
||||
EXPECT_EQ(0, iomgr.send(frames[2], 2222, 1000, ALL_IFACES_MASK, CanTxQueue::Persistent));
|
||||
EXPECT_EQ(0, iomgr.send(frames[0], 3333, 1100, 2, CanTxQueue::Persistent));
|
||||
EXPECT_EQ(0, iomgr.send(frames[1], 4444, 1200, ALL_IFACES_MASK, CanTxQueue::Volatile)); // One frame kicked here
|
||||
EXPECT_EQ(0, iomgr.send(frames[2], tsMono(2222), tsMono(1000), ALL_IFACES_MASK, CanTxQueue::Persistent));
|
||||
EXPECT_EQ(0, iomgr.send(frames[0], tsMono(3333), tsMono(1100), 2, CanTxQueue::Persistent));
|
||||
EXPECT_EQ(0, iomgr.send(frames[1], tsMono(4444), tsMono(1200), ALL_IFACES_MASK, CanTxQueue::Volatile)); // One frame kicked here
|
||||
|
||||
// State checks
|
||||
EXPECT_EQ(4, pool.getNumUsedBlocks()); // TX queue is full
|
||||
@@ -222,12 +221,12 @@ TEST(CanIOManager, Transmission)
|
||||
|
||||
// This shall transmit _some_ frames now, at least one per iface (exact number can be changed - it will be OK)
|
||||
uavcan::CanRxFrame rx_frame;
|
||||
EXPECT_EQ(1, iomgr.receive(rx_frame, 0)); // Non-blocking
|
||||
EXPECT_EQ(1, iomgr.receive(rx_frame, tsMono(0))); // Non-blocking
|
||||
EXPECT_TRUE(rxFrameEquals(rx_frame, rx_frames[0], 1200, 0));
|
||||
EXPECT_TRUE(driver.ifaces.at(0).matchAndPopTx(frames[1], 4444));
|
||||
EXPECT_TRUE(driver.ifaces.at(1).matchAndPopTx(frames[0], 3333));
|
||||
|
||||
EXPECT_EQ(1, iomgr.receive(rx_frame, 0));
|
||||
EXPECT_EQ(1, iomgr.receive(rx_frame, tsMono(0)));
|
||||
EXPECT_TRUE(rxFrameEquals(rx_frame, rx_frames[1], 1200, 1));
|
||||
EXPECT_TRUE(driver.ifaces.at(0).matchAndPopTx(frames[2], 2222));
|
||||
EXPECT_TRUE(driver.ifaces.at(1).matchAndPopTx(frames[2], 2222)); // Iface #1, frame[1] was rejected (VOLATILE)
|
||||
@@ -246,8 +245,8 @@ TEST(CanIOManager, Transmission)
|
||||
*/
|
||||
// Select failure
|
||||
driver.select_failure = true;
|
||||
EXPECT_EQ(-1, iomgr.receive(rx_frame, 2000));
|
||||
EXPECT_EQ(-1, iomgr.send(frames[0], 2100, 2000, ALL_IFACES_MASK, CanTxQueue::Volatile));
|
||||
EXPECT_EQ(-1, iomgr.receive(rx_frame, tsMono(2000)));
|
||||
EXPECT_EQ(-1, iomgr.send(frames[0], tsMono(2100), tsMono(2000), ALL_IFACES_MASK, CanTxQueue::Volatile));
|
||||
EXPECT_EQ(1200, clockmock.monotonic);
|
||||
EXPECT_EQ(1200, clockmock.utc);
|
||||
|
||||
@@ -257,14 +256,14 @@ TEST(CanIOManager, Transmission)
|
||||
driver.ifaces.at(1).writeable = true;
|
||||
driver.ifaces.at(0).tx_failure = true;
|
||||
driver.ifaces.at(1).tx_failure = true;
|
||||
EXPECT_GE(0, iomgr.send(frames[0], 2200, 0, ALL_IFACES_MASK, CanTxQueue::Persistent)); // Non-blocking - return < 0
|
||||
EXPECT_GE(0, iomgr.send(frames[0], tsMono(2200), tsMono(0), ALL_IFACES_MASK, CanTxQueue::Persistent)); // Non-blocking - return < 0
|
||||
|
||||
ASSERT_EQ(2, pool.getNumUsedBlocks()); // Untransmitted frames will be buffered
|
||||
|
||||
// Failure removed - transmission shall proceed
|
||||
driver.ifaces.at(0).tx_failure = false;
|
||||
driver.ifaces.at(1).tx_failure = false;
|
||||
EXPECT_EQ(0, iomgr.receive(rx_frame, 2500));
|
||||
EXPECT_EQ(0, iomgr.receive(rx_frame, tsMono(2500)));
|
||||
EXPECT_TRUE(driver.ifaces.at(0).matchAndPopTx(frames[0], 2200));
|
||||
EXPECT_TRUE(driver.ifaces.at(1).matchAndPopTx(frames[0], 2200));
|
||||
EXPECT_EQ(0, pool.getNumUsedBlocks()); // All transmitted
|
||||
|
||||
@@ -33,8 +33,8 @@ static bool isInQueue(uavcan::CanTxQueue& queue, const uavcan::CanFrame& frame)
|
||||
|
||||
TEST(CanTxQueue, Qos)
|
||||
{
|
||||
uavcan::CanTxQueue::Entry e1(makeCanFrame(100, "", EXT), 1000, uavcan::CanTxQueue::Volatile);
|
||||
uavcan::CanTxQueue::Entry e2(makeCanFrame(100, "", EXT), 1000, uavcan::CanTxQueue::Volatile);
|
||||
uavcan::CanTxQueue::Entry e1(makeCanFrame(100, "", EXT), tsMono(1000), uavcan::CanTxQueue::Volatile);
|
||||
uavcan::CanTxQueue::Entry e2(makeCanFrame(100, "", EXT), tsMono(1000), uavcan::CanTxQueue::Volatile);
|
||||
|
||||
EXPECT_FALSE(e1.qosHigherThan(e2));
|
||||
EXPECT_FALSE(e2.qosHigherThan(e1));
|
||||
@@ -86,7 +86,7 @@ TEST(CanTxQueue, TxQueue)
|
||||
/*
|
||||
* Priority insertion
|
||||
*/
|
||||
queue.push(f4, 100, CanTxQueue::Persistent);
|
||||
queue.push(f4, tsMono(100), CanTxQueue::Persistent);
|
||||
EXPECT_FALSE(queue.isEmpty());
|
||||
EXPECT_EQ(1, pool32.getNumUsedBlocks());
|
||||
EXPECT_EQ(f4, queue.peek()->frame);
|
||||
@@ -94,13 +94,13 @@ TEST(CanTxQueue, TxQueue)
|
||||
EXPECT_TRUE(queue.topPriorityHigherOrEqual(f4)); // Equal
|
||||
EXPECT_FALSE(queue.topPriorityHigherOrEqual(f3));
|
||||
|
||||
queue.push(f3, 200, CanTxQueue::Persistent);
|
||||
queue.push(f3, tsMono(200), CanTxQueue::Persistent);
|
||||
EXPECT_EQ(f3, queue.peek()->frame);
|
||||
|
||||
queue.push(f0, 300, CanTxQueue::Volatile);
|
||||
queue.push(f0, tsMono(300), CanTxQueue::Volatile);
|
||||
EXPECT_EQ(f0, queue.peek()->frame);
|
||||
|
||||
queue.push(f1, 400, CanTxQueue::Volatile);
|
||||
queue.push(f1, tsMono(400), CanTxQueue::Volatile);
|
||||
EXPECT_EQ(f0, queue.peek()->frame); // Still f0, since it is highest
|
||||
EXPECT_TRUE(queue.topPriorityHigherOrEqual(f0)); // Equal
|
||||
EXPECT_TRUE(queue.topPriorityHigherOrEqual(f1));
|
||||
@@ -125,28 +125,28 @@ TEST(CanTxQueue, TxQueue)
|
||||
* QoS
|
||||
*/
|
||||
EXPECT_FALSE(isInQueue(queue, f2));
|
||||
queue.push(f2, 100, CanTxQueue::Volatile); // Non preempting, will be rejected
|
||||
queue.push(f2, tsMono(100), CanTxQueue::Volatile); // Non preempting, will be rejected
|
||||
EXPECT_FALSE(isInQueue(queue, f2));
|
||||
|
||||
queue.push(f2, 500, CanTxQueue::Persistent); // Will override f1 (f3 and f4 are presistent)
|
||||
queue.push(f2, tsMono(500), CanTxQueue::Persistent); // Will override f1 (f3 and f4 are presistent)
|
||||
EXPECT_TRUE(isInQueue(queue, f2));
|
||||
EXPECT_FALSE(isInQueue(queue, f1));
|
||||
EXPECT_EQ(4, getQueueLength(queue));
|
||||
EXPECT_EQ(2, queue.getNumRejectedFrames());
|
||||
EXPECT_EQ(f0, queue.peek()->frame); // Check the priority
|
||||
|
||||
queue.push(f5, 600, CanTxQueue::Persistent); // Will override f0 (rest are presistent)
|
||||
queue.push(f5, tsMono(600), CanTxQueue::Persistent); // Will override f0 (rest are presistent)
|
||||
EXPECT_TRUE(isInQueue(queue, f5));
|
||||
EXPECT_FALSE(isInQueue(queue, f0));
|
||||
EXPECT_EQ(f2, queue.peek()->frame); // Check the priority
|
||||
|
||||
// No volatile frames left now
|
||||
|
||||
queue.push(f5a, 700, CanTxQueue::Persistent); // Will override f5 (same frame, same QoS)
|
||||
queue.push(f5a, tsMono(700), CanTxQueue::Persistent); // Will override f5 (same frame, same QoS)
|
||||
EXPECT_TRUE(isInQueue(queue, f5a));
|
||||
EXPECT_FALSE(isInQueue(queue, f5));
|
||||
|
||||
queue.push(f6, 700, CanTxQueue::Persistent); // Will be rejected (lowest QoS)
|
||||
queue.push(f6, tsMono(700), CanTxQueue::Persistent); // Will be rejected (lowest QoS)
|
||||
EXPECT_FALSE(isInQueue(queue, f6));
|
||||
|
||||
EXPECT_FALSE(queue.topPriorityHigherOrEqual(f0));
|
||||
@@ -165,19 +165,19 @@ TEST(CanTxQueue, TxQueue)
|
||||
* Expiration
|
||||
*/
|
||||
clockmock.monotonic = 101;
|
||||
queue.push(f0, 800, CanTxQueue::Volatile); // Will replace f4 which is expired now
|
||||
queue.push(f0, tsMono(800), CanTxQueue::Volatile); // Will replace f4 which is expired now
|
||||
EXPECT_TRUE(isInQueue(queue, f0));
|
||||
EXPECT_FALSE(isInQueue(queue, f4));
|
||||
EXPECT_EQ(6, queue.getNumRejectedFrames());
|
||||
|
||||
clockmock.monotonic = 1001;
|
||||
queue.push(f5, 2000, CanTxQueue::Volatile); // Entire queue is expired
|
||||
queue.push(f5, tsMono(2000), CanTxQueue::Volatile); // Entire queue is expired
|
||||
EXPECT_TRUE(isInQueue(queue, f5));
|
||||
EXPECT_EQ(1, getQueueLength(queue)); // Just one entry left - f5
|
||||
EXPECT_EQ(1, pool32.getNumUsedBlocks()); // Make sure there is no leaks
|
||||
EXPECT_EQ(10, queue.getNumRejectedFrames());
|
||||
|
||||
queue.push(f0, 1000, CanTxQueue::Persistent); // This entry is already expired
|
||||
queue.push(f0, tsMono(1000), CanTxQueue::Persistent); // This entry is already expired
|
||||
EXPECT_EQ(1, getQueueLength(queue));
|
||||
EXPECT_EQ(1, pool32.getNumUsedBlocks());
|
||||
EXPECT_EQ(11, queue.getNumRejectedFrames());
|
||||
@@ -185,7 +185,7 @@ TEST(CanTxQueue, TxQueue)
|
||||
/*
|
||||
* Removing
|
||||
*/
|
||||
queue.push(f4, 5000, CanTxQueue::Volatile);
|
||||
queue.push(f4, tsMono(5000), CanTxQueue::Volatile);
|
||||
EXPECT_EQ(2, getQueueLength(queue));
|
||||
EXPECT_TRUE(isInQueue(queue, f4));
|
||||
EXPECT_EQ(f4, queue.peek()->frame);
|
||||
|
||||
@@ -130,7 +130,7 @@ TEST(Dispatcher, Reception)
|
||||
|
||||
while (true)
|
||||
{
|
||||
const int res = dispatcher.spin(0);
|
||||
const int res = dispatcher.spin(tsMono(0));
|
||||
ASSERT_LE(0, res);
|
||||
clockmock.advance(100);
|
||||
if (res == 0)
|
||||
@@ -197,14 +197,14 @@ TEST(Dispatcher, Transmission)
|
||||
/*
|
||||
* Transmission
|
||||
*/
|
||||
static const int TX_DEADLINE = 123456;
|
||||
static const uavcan::MonotonicTime TX_DEADLINE = tsMono(123456);
|
||||
|
||||
// uint_fast16_t data_type_id, TransferType transfer_type, NodeID src_node_id, NodeID dst_node_id,
|
||||
// uint_fast8_t frame_index, TransferID transfer_id, bool last_frame = false
|
||||
uavcan::Frame frame(123, uavcan::TransferTypeMessageUnicast, SELF_NODE_ID, 2, 0, 0, true);
|
||||
frame.setPayload(reinterpret_cast<const uint8_t*>("123"), 3);
|
||||
|
||||
ASSERT_EQ(2, dispatcher.send(frame, TX_DEADLINE, 0, uavcan::CanTxQueue::Volatile));
|
||||
ASSERT_EQ(2, dispatcher.send(frame, TX_DEADLINE, tsMono(0), uavcan::CanTxQueue::Volatile));
|
||||
|
||||
/*
|
||||
* Validation
|
||||
@@ -234,10 +234,10 @@ TEST(Dispatcher, Spin)
|
||||
clockmock.monotonic_auto_advance = 100;
|
||||
|
||||
ASSERT_EQ(100, clockmock.monotonic);
|
||||
ASSERT_EQ(0, dispatcher.spin(1000));
|
||||
ASSERT_EQ(0, dispatcher.spin(tsMono(1000)));
|
||||
ASSERT_LE(1000, clockmock.monotonic);
|
||||
ASSERT_EQ(0, dispatcher.spin(0));
|
||||
ASSERT_EQ(0, dispatcher.spin(tsMono(0)));
|
||||
ASSERT_LE(1000, clockmock.monotonic);
|
||||
ASSERT_EQ(0, dispatcher.spin(1100));
|
||||
ASSERT_EQ(0, dispatcher.spin(tsMono(1100)));
|
||||
ASSERT_LE(1100, clockmock.monotonic);
|
||||
}
|
||||
|
||||
@@ -5,13 +5,14 @@
|
||||
#include <algorithm>
|
||||
#include <gtest/gtest.h>
|
||||
#include <uavcan/internal/transport/transfer_listener.hpp>
|
||||
#include "../../clock.hpp"
|
||||
|
||||
|
||||
static uavcan::RxFrame makeFrame()
|
||||
{
|
||||
uavcan::RxFrame frame(
|
||||
uavcan::Frame(123, uavcan::TransferTypeMessageBroadcast, 1, uavcan::NodeID::Broadcast, 0, 1, true),
|
||||
123, 456, 0);
|
||||
tsMono(123), tsUtc(456), 0);
|
||||
uint8_t data[8];
|
||||
for (unsigned int i = 0; i < sizeof(data); i++)
|
||||
data[i] = i;
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <algorithm>
|
||||
#include <gtest/gtest.h>
|
||||
#include <uavcan/internal/transport/outgoing_transfer_registry.hpp>
|
||||
#include "../../clock.hpp"
|
||||
|
||||
|
||||
TEST(OutgoingTransferRegistry, Basic)
|
||||
@@ -13,7 +14,7 @@ TEST(OutgoingTransferRegistry, Basic)
|
||||
uavcan::PoolManager<1> poolmgr; // Empty
|
||||
uavcan::OutgoingTransferRegistry<4> otr(poolmgr);
|
||||
|
||||
otr.cleanup(1000);
|
||||
otr.cleanup(tsMono(1000));
|
||||
|
||||
static const int NUM_KEYS = 5;
|
||||
const OutgoingTransferRegistryKey keys[NUM_KEYS] =
|
||||
@@ -25,50 +26,50 @@ TEST(OutgoingTransferRegistry, Basic)
|
||||
OutgoingTransferRegistryKey(456, uavcan::TransferTypeServiceRequest, 2)
|
||||
};
|
||||
|
||||
ASSERT_EQ(0, otr.accessOrCreate(keys[0], 1000000)->get());
|
||||
ASSERT_EQ(0, otr.accessOrCreate(keys[1], 1000000)->get());
|
||||
ASSERT_EQ(0, otr.accessOrCreate(keys[2], 1000000)->get());
|
||||
ASSERT_EQ(0, otr.accessOrCreate(keys[3], 1000000)->get());
|
||||
ASSERT_FALSE(otr.accessOrCreate(keys[4], 1000000)); // OOM
|
||||
ASSERT_EQ(0, otr.accessOrCreate(keys[0], tsMono(1000000))->get());
|
||||
ASSERT_EQ(0, otr.accessOrCreate(keys[1], tsMono(1000000))->get());
|
||||
ASSERT_EQ(0, otr.accessOrCreate(keys[2], tsMono(1000000))->get());
|
||||
ASSERT_EQ(0, otr.accessOrCreate(keys[3], tsMono(1000000))->get());
|
||||
ASSERT_FALSE(otr.accessOrCreate(keys[4], tsMono(1000000))); // OOM
|
||||
|
||||
/*
|
||||
* Incrementing a little
|
||||
*/
|
||||
otr.accessOrCreate(keys[0], 2000000)->increment();
|
||||
otr.accessOrCreate(keys[0], 4000000)->increment();
|
||||
otr.accessOrCreate(keys[0], 3000000)->increment();
|
||||
ASSERT_EQ(3, otr.accessOrCreate(keys[0], 5000000)->get());
|
||||
otr.accessOrCreate(keys[0], tsMono(2000000))->increment();
|
||||
otr.accessOrCreate(keys[0], tsMono(4000000))->increment();
|
||||
otr.accessOrCreate(keys[0], tsMono(3000000))->increment();
|
||||
ASSERT_EQ(3, otr.accessOrCreate(keys[0], tsMono(5000000))->get());
|
||||
|
||||
otr.accessOrCreate(keys[2], 2000000)->increment();
|
||||
otr.accessOrCreate(keys[2], 3000000)->increment();
|
||||
ASSERT_EQ(2, otr.accessOrCreate(keys[2], 6000000)->get());
|
||||
otr.accessOrCreate(keys[2], tsMono(2000000))->increment();
|
||||
otr.accessOrCreate(keys[2], tsMono(3000000))->increment();
|
||||
ASSERT_EQ(2, otr.accessOrCreate(keys[2], tsMono(6000000))->get());
|
||||
|
||||
otr.accessOrCreate(keys[3], 9000000)->increment();
|
||||
ASSERT_EQ(1, otr.accessOrCreate(keys[3], 4000000)->get());
|
||||
otr.accessOrCreate(keys[3], tsMono(9000000))->increment();
|
||||
ASSERT_EQ(1, otr.accessOrCreate(keys[3], tsMono(4000000))->get());
|
||||
|
||||
ASSERT_EQ(0, otr.accessOrCreate(keys[1], 4000000)->get());
|
||||
ASSERT_EQ(0, otr.accessOrCreate(keys[1], tsMono(4000000))->get());
|
||||
|
||||
ASSERT_FALSE(otr.accessOrCreate(keys[4], 1000000)); // Still OOM
|
||||
ASSERT_FALSE(otr.accessOrCreate(keys[4], tsMono(1000000))); // Still OOM
|
||||
|
||||
/*
|
||||
* Cleaning up
|
||||
*/
|
||||
otr.cleanup(4000001); // Kills 1, 3
|
||||
ASSERT_EQ(0, otr.accessOrCreate(keys[1], 1000000)->get());
|
||||
ASSERT_EQ(0, otr.accessOrCreate(keys[3], 1000000)->get());
|
||||
otr.accessOrCreate(keys[1], 5000000)->increment();
|
||||
otr.accessOrCreate(keys[3], 5000000)->increment();
|
||||
otr.cleanup(tsMono(4000001)); // Kills 1, 3
|
||||
ASSERT_EQ(0, otr.accessOrCreate(keys[1], tsMono(1000000))->get());
|
||||
ASSERT_EQ(0, otr.accessOrCreate(keys[3], tsMono(1000000))->get());
|
||||
otr.accessOrCreate(keys[1], tsMono(5000000))->increment();
|
||||
otr.accessOrCreate(keys[3], tsMono(5000000))->increment();
|
||||
|
||||
ASSERT_EQ(3, otr.accessOrCreate(keys[0], 5000000)->get());
|
||||
ASSERT_EQ(2, otr.accessOrCreate(keys[2], 6000000)->get());
|
||||
ASSERT_EQ(3, otr.accessOrCreate(keys[0], tsMono(5000000))->get());
|
||||
ASSERT_EQ(2, otr.accessOrCreate(keys[2], tsMono(6000000))->get());
|
||||
|
||||
otr.cleanup(5000001); // Kills 1, 3 (He needs a bath, Jud. He stinks of the ground you buried him in.), 0
|
||||
ASSERT_EQ(0, otr.accessOrCreate(keys[0], 1000000)->get());
|
||||
ASSERT_EQ(0, otr.accessOrCreate(keys[1], 1000000)->get());
|
||||
ASSERT_EQ(0, otr.accessOrCreate(keys[3], 1000000)->get());
|
||||
otr.cleanup(tsMono(5000001)); // Kills 1, 3 (He needs a bath, Jud. He stinks of the ground you buried him in.), 0
|
||||
ASSERT_EQ(0, otr.accessOrCreate(keys[0], tsMono(1000000))->get());
|
||||
ASSERT_EQ(0, otr.accessOrCreate(keys[1], tsMono(1000000))->get());
|
||||
ASSERT_EQ(0, otr.accessOrCreate(keys[3], tsMono(1000000))->get());
|
||||
|
||||
ASSERT_EQ(2, otr.accessOrCreate(keys[2], 1000000)->get());
|
||||
ASSERT_EQ(2, otr.accessOrCreate(keys[2], tsMono(1000000))->get());
|
||||
|
||||
otr.cleanup(5000001); // Frees some memory for 4
|
||||
ASSERT_EQ(0, otr.accessOrCreate(keys[0], 1000000)->get());
|
||||
otr.cleanup(tsMono(5000001)); // Frees some memory for 4
|
||||
ASSERT_EQ(0, otr.accessOrCreate(keys[0], tsMono(1000000))->get());
|
||||
}
|
||||
|
||||
@@ -228,17 +228,17 @@ TEST(Transfer, RxFrameParse)
|
||||
(456 << 19); // Data Type ID
|
||||
|
||||
ASSERT_TRUE(rx_frame.parse(can_rx_frame));
|
||||
ASSERT_EQ(0, rx_frame.getMonotonicTimestamp());
|
||||
ASSERT_EQ(0, rx_frame.getMonotonicTimestamp().toUSec());
|
||||
ASSERT_EQ(0, rx_frame.getIfaceIndex());
|
||||
|
||||
can_rx_frame.ts_monotonic = 123;
|
||||
can_rx_frame.ts_mono = tsMono(123);
|
||||
can_rx_frame.iface_index = 2;
|
||||
|
||||
Frame frame(456, uavcan::TransferTypeMessageBroadcast, 1, uavcan::NodeID::Broadcast, 0, 0);
|
||||
ASSERT_TRUE(frame.compile(can_rx_frame));
|
||||
|
||||
ASSERT_TRUE(rx_frame.parse(can_rx_frame));
|
||||
ASSERT_EQ(123, rx_frame.getMonotonicTimestamp());
|
||||
ASSERT_EQ(123, rx_frame.getMonotonicTimestamp().toUSec());
|
||||
ASSERT_EQ(2, rx_frame.getIfaceIndex());
|
||||
ASSERT_EQ(456, rx_frame.getDataTypeID());
|
||||
ASSERT_EQ(uavcan::TransferTypeMessageBroadcast, rx_frame.getTransferType());
|
||||
@@ -252,13 +252,13 @@ TEST(Transfer, FrameToString)
|
||||
|
||||
// RX frame default
|
||||
RxFrame rx_frame;
|
||||
EXPECT_EQ("dtid=0 tt=4 snid=255 dnid=255 idx=0 last=0 tid=0 payload=[] ts_m=0 ts_utc=0 iface=0", rx_frame.toString());
|
||||
EXPECT_EQ("dtid=0 tt=4 snid=255 dnid=255 idx=0 last=0 tid=0 payload=[] ts_m=0.000000 ts_utc=0.000000 iface=0", rx_frame.toString());
|
||||
|
||||
// RX frame max len
|
||||
rx_frame = RxFrame(Frame(Frame::MaxDataTypeID, uavcan::TransferTypeMessageUnicast,
|
||||
uavcan::NodeID::Max, uavcan::NodeID::Max - 1, Frame::MaxIndex,
|
||||
uavcan::TransferID::Max, true),
|
||||
0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, 3);
|
||||
uavcan::MonotonicTime::getMax(), uavcan::UtcTime::getMax(), 3);
|
||||
|
||||
uint8_t data[8];
|
||||
for (unsigned int i = 0; i < sizeof(data); i++)
|
||||
@@ -266,7 +266,7 @@ TEST(Transfer, FrameToString)
|
||||
rx_frame.setPayload(data, sizeof(data));
|
||||
|
||||
EXPECT_EQ(
|
||||
"dtid=1023 tt=3 snid=127 dnid=126 idx=62 last=1 tid=7 payload=[00 01 02 03 04 05 06] ts_m=18446744073709551615 ts_utc=18446744073709551615 iface=3",
|
||||
"dtid=1023 tt=3 snid=127 dnid=126 idx=62 last=1 tid=7 payload=[00 01 02 03 04 05 06] ts_m=18446744073709.551615 ts_utc=18446744073709.551615 iface=3",
|
||||
rx_frame.toString());
|
||||
|
||||
// Plain frame default
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include "transfer_test_helpers.hpp"
|
||||
#include "../../clock.hpp"
|
||||
|
||||
|
||||
class TransferListenerEmulator : public IncomingTransferEmulatorBase
|
||||
@@ -198,7 +199,7 @@ TEST(TransferListener, Cleanup)
|
||||
/*
|
||||
* Cleanup with huge timestamp value will remove all entries
|
||||
*/
|
||||
static_cast<uavcan::TransferListenerBase&>(subscriber).cleanup(100000000);
|
||||
static_cast<uavcan::TransferListenerBase&>(subscriber).cleanup(tsMono(100000000));
|
||||
|
||||
/*
|
||||
* Sending the same transfers again - they will be accepted since registres were cleared
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <algorithm>
|
||||
#include <gtest/gtest.h>
|
||||
#include <uavcan/internal/transport/transfer_receiver.hpp>
|
||||
#include "../../clock.hpp"
|
||||
|
||||
/*
|
||||
* Beware!
|
||||
@@ -37,7 +38,8 @@ struct RxFrameGenerator
|
||||
|
||||
EXPECT_EQ(data.length(), frame.setPayload(reinterpret_cast<const uint8_t*>(data.c_str()), data.length()));
|
||||
|
||||
return uavcan::RxFrame(frame, ts_monotonic, ts_utc, iface_index);
|
||||
return uavcan::RxFrame(frame, uavcan::MonotonicTime::fromUSec(ts_monotonic),
|
||||
uavcan::UtcTime::fromUSec(ts_utc), iface_index);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -101,15 +103,15 @@ TEST(TransferReceiver, Basic)
|
||||
/*
|
||||
* Empty
|
||||
*/
|
||||
ASSERT_EQ(TransferReceiver::DefaultTransferInterval, rcv.getInterval());
|
||||
ASSERT_EQ(0, rcv.getLastTransferTimestampMonotonic());
|
||||
ASSERT_EQ(TransferReceiver::getDefaultTransferInterval(), rcv.getInterval());
|
||||
ASSERT_EQ(0, rcv.getLastTransferTimestampMonotonic().toUSec());
|
||||
|
||||
/*
|
||||
* Single frame transfer with zero ts, must be ignored
|
||||
*/
|
||||
CHECK_NOT_COMPLETE(rcv.addFrame(gen(0, "Foo", 0, true, 0, 0), bk));
|
||||
ASSERT_EQ(TransferReceiver::DefaultTransferInterval, rcv.getInterval());
|
||||
ASSERT_EQ(0, rcv.getLastTransferTimestampMonotonic());
|
||||
ASSERT_EQ(TransferReceiver::getDefaultTransferInterval(), rcv.getInterval());
|
||||
ASSERT_EQ(0, rcv.getLastTransferTimestampMonotonic().toUSec());
|
||||
|
||||
/*
|
||||
* Valid compound transfer
|
||||
@@ -120,8 +122,8 @@ TEST(TransferReceiver, Basic)
|
||||
|
||||
ASSERT_TRUE(matchBufferContent(bufmgr.access(gen.bufmgr_key), "345678foo"));
|
||||
ASSERT_EQ(0x1234, rcv.getLastTransferCrc());
|
||||
ASSERT_EQ(TransferReceiver::DefaultTransferInterval, rcv.getInterval()); // Not initialized yet
|
||||
ASSERT_EQ(100, rcv.getLastTransferTimestampMonotonic());
|
||||
ASSERT_EQ(TransferReceiver::getDefaultTransferInterval(), rcv.getInterval()); // Not initialized yet
|
||||
ASSERT_EQ(100, rcv.getLastTransferTimestampMonotonic().toUSec());
|
||||
|
||||
/*
|
||||
* Compound transfer mixed with invalid frames; buffer was not released explicitly
|
||||
@@ -138,12 +140,12 @@ TEST(TransferReceiver, Basic)
|
||||
|
||||
ASSERT_TRUE(matchBufferContent(bufmgr.access(gen.bufmgr_key), "345678abcdefgh"));
|
||||
ASSERT_EQ(0x789A, rcv.getLastTransferCrc());
|
||||
ASSERT_GT(TransferReceiver::DefaultTransferInterval, rcv.getInterval());
|
||||
ASSERT_LT(TransferReceiver::MinTransferInterval, rcv.getInterval());
|
||||
ASSERT_EQ(1000, rcv.getLastTransferTimestampMonotonic());
|
||||
ASSERT_FALSE(rcv.isTimedOut(1000));
|
||||
ASSERT_FALSE(rcv.isTimedOut(5000));
|
||||
ASSERT_TRUE(rcv.isTimedOut(60000000));
|
||||
ASSERT_GT(TransferReceiver::getDefaultTransferInterval(), rcv.getInterval());
|
||||
ASSERT_LT(TransferReceiver::getMinTransferInterval(), rcv.getInterval());
|
||||
ASSERT_EQ(1000, rcv.getLastTransferTimestampMonotonic().toUSec());
|
||||
ASSERT_FALSE(rcv.isTimedOut(tsMono(1000)));
|
||||
ASSERT_FALSE(rcv.isTimedOut(tsMono(5000)));
|
||||
ASSERT_TRUE(rcv.isTimedOut(tsMono(60000000)));
|
||||
|
||||
/*
|
||||
* Single-frame transfers
|
||||
@@ -153,11 +155,11 @@ TEST(TransferReceiver, Basic)
|
||||
CHECK_SINGLE_FRAME(rcv.addFrame(gen(0, "qwe", 0, true, 2, 2200), bk));
|
||||
|
||||
ASSERT_FALSE(bufmgr.access(gen.bufmgr_key)); // Buffer must be removed
|
||||
ASSERT_GT(TransferReceiver::DefaultTransferInterval, rcv.getInterval());
|
||||
ASSERT_EQ(2200, rcv.getLastTransferTimestampMonotonic());
|
||||
ASSERT_GT(TransferReceiver::getDefaultTransferInterval(), rcv.getInterval());
|
||||
ASSERT_EQ(2200, rcv.getLastTransferTimestampMonotonic().toUSec());
|
||||
|
||||
CHECK_SINGLE_FRAME(rcv.addFrame(gen(0, "", 0, true, 3, 2500), bk));
|
||||
ASSERT_EQ(2500, rcv.getLastTransferTimestampMonotonic());
|
||||
ASSERT_EQ(2500, rcv.getLastTransferTimestampMonotonic().toUSec());
|
||||
|
||||
CHECK_NOT_COMPLETE(rcv.addFrame(gen(0, "", 0, true, 0, 3000), bk)); // Old TID
|
||||
CHECK_NOT_COMPLETE(rcv.addFrame(gen(0, "", 0, true, 1, 3100), bk)); // Old TID
|
||||
@@ -166,38 +168,38 @@ TEST(TransferReceiver, Basic)
|
||||
CHECK_NOT_COMPLETE(rcv.addFrame(gen(1, "", 0, true, 2, 3400), bk)); // Old TID, wrong iface
|
||||
CHECK_NOT_COMPLETE(rcv.addFrame(gen(1, "", 0, true, 3, 3500), bk)); // Old TID, wrong iface
|
||||
CHECK_SINGLE_FRAME(rcv.addFrame(gen(0, "", 0, true, 4, 3600), bk));
|
||||
ASSERT_EQ(3600, rcv.getLastTransferTimestampMonotonic());
|
||||
ASSERT_EQ(3600, rcv.getLastTransferTimestampMonotonic().toUSec());
|
||||
|
||||
/*
|
||||
* Timeouts
|
||||
*/
|
||||
CHECK_NOT_COMPLETE(rcv.addFrame(gen(1, "qwe", 0, true, 1, 100000), bk)); // Wrong iface - ignored
|
||||
CHECK_SINGLE_FRAME(rcv.addFrame(gen(1, "qwe", 0, true, 6, 600000), bk)); // Accepted due to iface timeout
|
||||
ASSERT_EQ(600000, rcv.getLastTransferTimestampMonotonic());
|
||||
ASSERT_EQ(600000, rcv.getLastTransferTimestampMonotonic().toUSec());
|
||||
|
||||
CHECK_NOT_COMPLETE(rcv.addFrame(gen(0, "qwe", 0, true, 7, 600100), bk));// Ignored - old iface 0
|
||||
CHECK_SINGLE_FRAME(rcv.addFrame(gen(1, "qwe", 0, true, 7, 600100), bk));
|
||||
ASSERT_EQ(600100, rcv.getLastTransferTimestampMonotonic());
|
||||
ASSERT_EQ(600100, rcv.getLastTransferTimestampMonotonic().toUSec());
|
||||
|
||||
CHECK_NOT_COMPLETE(rcv.addFrame(gen(1, "qwe", 0, true, 7, 600100), bk)); // Old TID
|
||||
CHECK_SINGLE_FRAME(rcv.addFrame(gen(0, "qwe", 0, true, 7, 100000000), bk));// Accepted - global timeout
|
||||
ASSERT_EQ(100000000, rcv.getLastTransferTimestampMonotonic());
|
||||
ASSERT_EQ(100000000, rcv.getLastTransferTimestampMonotonic().toUSec());
|
||||
|
||||
CHECK_SINGLE_FRAME(rcv.addFrame(gen(0, "qwe", 0, true, 0, 100000100), bk));
|
||||
ASSERT_EQ(100000100, rcv.getLastTransferTimestampMonotonic());
|
||||
ASSERT_EQ(100000100, rcv.getLastTransferTimestampMonotonic().toUSec());
|
||||
|
||||
ASSERT_TRUE(rcv.isTimedOut(900000000));
|
||||
ASSERT_TRUE(rcv.isTimedOut(tsMono(900000000)));
|
||||
CHECK_NOT_COMPLETE(rcv.addFrame(gen(1, "\x78\x56" "345678", 0, false, 0, 900000000), bk));// Global timeout
|
||||
CHECK_NOT_COMPLETE(rcv.addFrame(gen(0, "12345678", 0, false, 0, 900000100), bk));// Wrong iface
|
||||
CHECK_NOT_COMPLETE(rcv.addFrame(gen(0, "qwe", 1, true, 0, 900000200), bk));// Wrong iface
|
||||
CHECK_COMPLETE( rcv.addFrame(gen(1, "qwe", 1, true, 0, 900000200), bk));
|
||||
ASSERT_EQ(900000000, rcv.getLastTransferTimestampMonotonic());
|
||||
ASSERT_FALSE(rcv.isTimedOut(1000));
|
||||
ASSERT_FALSE(rcv.isTimedOut(900000200));
|
||||
ASSERT_TRUE(rcv.isTimedOut(1000 * 1000000));
|
||||
ASSERT_LT(TransferReceiver::DefaultTransferInterval, rcv.getInterval());
|
||||
ASSERT_LE(TransferReceiver::MinTransferInterval, rcv.getInterval());
|
||||
ASSERT_GE(TransferReceiver::MaxTransferInterval, rcv.getInterval());
|
||||
ASSERT_EQ(900000000, rcv.getLastTransferTimestampMonotonic().toUSec());
|
||||
ASSERT_FALSE(rcv.isTimedOut(tsMono(1000)));
|
||||
ASSERT_FALSE(rcv.isTimedOut(tsMono(900000200)));
|
||||
ASSERT_TRUE(rcv.isTimedOut(tsMono(1000 * 1000000)));
|
||||
ASSERT_LT(TransferReceiver::getDefaultTransferInterval(), rcv.getInterval());
|
||||
ASSERT_LE(TransferReceiver::getMinTransferInterval(), rcv.getInterval());
|
||||
ASSERT_GE(TransferReceiver::getMaxTransferInterval(), rcv.getInterval());
|
||||
ASSERT_TRUE(matchBufferContent(bufmgr.access(gen.bufmgr_key), "345678qwe"));
|
||||
ASSERT_EQ(0x5678, rcv.getLastTransferCrc());
|
||||
|
||||
@@ -227,7 +229,7 @@ TEST(TransferReceiver, OutOfBufferSpace_32bytes)
|
||||
CHECK_NOT_COMPLETE(rcv.addFrame(gen(1, "12345678", 3, false, 1, 100000300), bk)); // 30
|
||||
CHECK_COMPLETE( rcv.addFrame(gen(1, "12", 4, true, 1, 100000400), bk)); // 32
|
||||
|
||||
ASSERT_EQ(100000000, rcv.getLastTransferTimestampMonotonic());
|
||||
ASSERT_EQ(100000000, rcv.getLastTransferTimestampMonotonic().toUSec());
|
||||
ASSERT_TRUE(matchBufferContent(bufmgr.access(gen.bufmgr_key), "34567812345678123456781234567812"));
|
||||
ASSERT_EQ(0x3231, rcv.getLastTransferCrc()); // CRC from "12", which is 0x3231 in little endian
|
||||
|
||||
@@ -240,7 +242,7 @@ TEST(TransferReceiver, OutOfBufferSpace_32bytes)
|
||||
CHECK_NOT_COMPLETE(rcv.addFrame(gen(1, "12345678", 3, false, 2, 100001200), bk)); // 30
|
||||
CHECK_NOT_COMPLETE(rcv.addFrame(gen(1, "12345678", 4, true, 2, 100001300), bk)); // 38 // EOT, ignored - lost sync
|
||||
|
||||
ASSERT_EQ(100000000, rcv.getLastTransferTimestampMonotonic()); // Timestamp will not be overriden
|
||||
ASSERT_EQ(100000000, rcv.getLastTransferTimestampMonotonic().toUSec()); // Timestamp will not be overriden
|
||||
ASSERT_FALSE(bufmgr.access(gen.bufmgr_key)); // Buffer should be removed
|
||||
}
|
||||
|
||||
@@ -260,7 +262,7 @@ TEST(TransferReceiver, UnterminatedTransfer)
|
||||
content += "12345678";
|
||||
}
|
||||
CHECK_COMPLETE(rcv.addFrame(gen(1, "12345678", uavcan::Frame::MaxIndex, true, 0, 1100), bk));
|
||||
ASSERT_EQ(1000, rcv.getLastTransferTimestampMonotonic());
|
||||
ASSERT_EQ(1000, rcv.getLastTransferTimestampMonotonic().toUSec());
|
||||
ASSERT_TRUE(matchBufferContent(bufmgr.access(gen.bufmgr_key), std::string(content, 2)));
|
||||
ASSERT_EQ(0x3231, rcv.getLastTransferCrc());
|
||||
}
|
||||
@@ -281,7 +283,7 @@ TEST(TransferReceiver, OutOfOrderFrames)
|
||||
CHECK_NOT_COMPLETE(rcv.addFrame(gen(1, "--------", 4, true, 7, 100000200), bk)); // Out of order
|
||||
CHECK_COMPLETE( rcv.addFrame(gen(1, "abcd", 2, true, 7, 100000400), bk));
|
||||
|
||||
ASSERT_EQ(100000000, rcv.getLastTransferTimestampMonotonic());
|
||||
ASSERT_EQ(100000000, rcv.getLastTransferTimestampMonotonic().toUSec());
|
||||
ASSERT_TRUE(matchBufferContent(bufmgr.access(gen.bufmgr_key), "345678qwertyuiabcd"));
|
||||
ASSERT_EQ(0x3231, rcv.getLastTransferCrc());
|
||||
}
|
||||
@@ -307,13 +309,13 @@ TEST(TransferReceiver, IntervalMeasurement)
|
||||
|
||||
ASSERT_TRUE(matchBufferContent(bufmgr.access(gen.bufmgr_key), "345678qwertyuiabcd"));
|
||||
ASSERT_EQ(0x3231, rcv.getLastTransferCrc());
|
||||
ASSERT_EQ(timestamp, rcv.getLastTransferTimestampMonotonic());
|
||||
ASSERT_EQ(timestamp, rcv.getLastTransferTimestampMonotonic().toUSec());
|
||||
|
||||
timestamp += INTERVAL;
|
||||
tid.increment();
|
||||
}
|
||||
|
||||
ASSERT_EQ(INTERVAL, rcv.getInterval());
|
||||
ASSERT_EQ(INTERVAL, rcv.getInterval().toUSec());
|
||||
}
|
||||
|
||||
|
||||
@@ -375,8 +377,8 @@ TEST(TransferReceiver, UtcTransferTimestamping)
|
||||
CHECK_COMPLETE( rcv.addFrame(gen(1, "abcd", 2, true, 0, 3, 0), bk));
|
||||
|
||||
ASSERT_TRUE(matchBufferContent(bufmgr.access(gen.bufmgr_key), "345678qwertyuiabcd"));
|
||||
ASSERT_EQ(1, rcv.getLastTransferTimestampMonotonic());
|
||||
ASSERT_EQ(0, rcv.getLastTransferTimestampUtc());
|
||||
ASSERT_EQ(1, rcv.getLastTransferTimestampMonotonic().toUSec());
|
||||
ASSERT_EQ(0, rcv.getLastTransferTimestampUtc().toUSec());
|
||||
|
||||
/*
|
||||
* Non-zero UTC timestamp
|
||||
@@ -386,15 +388,15 @@ TEST(TransferReceiver, UtcTransferTimestamping)
|
||||
CHECK_COMPLETE( rcv.addFrame(gen(1, "abcd", 2, true, 1, 6, 42), bk));
|
||||
|
||||
ASSERT_TRUE(matchBufferContent(bufmgr.access(gen.bufmgr_key), "345678qwertyuiabcd"));
|
||||
ASSERT_EQ(4, rcv.getLastTransferTimestampMonotonic());
|
||||
ASSERT_EQ(123, rcv.getLastTransferTimestampUtc());
|
||||
ASSERT_EQ(4, rcv.getLastTransferTimestampMonotonic().toUSec());
|
||||
ASSERT_EQ(123, rcv.getLastTransferTimestampUtc().toUSec());
|
||||
|
||||
/*
|
||||
* Single-frame transfers
|
||||
*/
|
||||
CHECK_SINGLE_FRAME(rcv.addFrame(gen(1, "abc", 0, true, 2, 10, 100000000), bk)); // Exact value is irrelevant
|
||||
ASSERT_EQ(10, rcv.getLastTransferTimestampMonotonic());
|
||||
ASSERT_EQ(100000000, rcv.getLastTransferTimestampUtc());
|
||||
ASSERT_EQ(10, rcv.getLastTransferTimestampMonotonic().toUSec());
|
||||
ASSERT_EQ(100000000, rcv.getLastTransferTimestampUtc().toUSec());
|
||||
|
||||
/*
|
||||
* Restart recovery
|
||||
@@ -404,8 +406,8 @@ TEST(TransferReceiver, UtcTransferTimestamping)
|
||||
CHECK_COMPLETE( rcv.addFrame(gen(0, "abcd", 2, true, 1, 100000002, 900000000), bk));
|
||||
|
||||
ASSERT_TRUE(matchBufferContent(bufmgr.access(gen.bufmgr_key), "345678qwertyuiabcd"));
|
||||
ASSERT_EQ(100000000, rcv.getLastTransferTimestampMonotonic());
|
||||
ASSERT_EQ(800000000, rcv.getLastTransferTimestampUtc());
|
||||
ASSERT_EQ(100000000, rcv.getLastTransferTimestampMonotonic().toUSec());
|
||||
ASSERT_EQ(800000000, rcv.getLastTransferTimestampUtc().toUSec());
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -13,16 +13,18 @@ static int sendOne(uavcan::TransferSender& sender, const std::string& data,
|
||||
uint64_t monotonic_tx_deadline, uint64_t monotonic_blocking_deadline,
|
||||
uavcan::TransferType transfer_type, uavcan::NodeID dst_node_id)
|
||||
{
|
||||
return sender.send(reinterpret_cast<const uint8_t*>(data.c_str()), data.length(), monotonic_tx_deadline,
|
||||
monotonic_blocking_deadline, transfer_type, dst_node_id);
|
||||
return sender.send(reinterpret_cast<const uint8_t*>(data.c_str()), data.length(),
|
||||
uavcan::MonotonicTime::fromUSec(monotonic_tx_deadline),
|
||||
uavcan::MonotonicTime::fromUSec(monotonic_blocking_deadline), transfer_type, dst_node_id);
|
||||
}
|
||||
|
||||
static int sendOne(uavcan::TransferSender& sender, const std::string& data,
|
||||
uint64_t monotonic_tx_deadline, uint64_t monotonic_blocking_deadline,
|
||||
uavcan::TransferType transfer_type, uavcan::NodeID dst_node_id, uavcan::TransferID tid)
|
||||
{
|
||||
return sender.send(reinterpret_cast<const uint8_t*>(data.c_str()), data.length(), monotonic_tx_deadline,
|
||||
monotonic_blocking_deadline, transfer_type, dst_node_id, tid);
|
||||
return sender.send(reinterpret_cast<const uint8_t*>(data.c_str()), data.length(),
|
||||
uavcan::MonotonicTime::fromUSec(monotonic_tx_deadline),
|
||||
uavcan::MonotonicTime::fromUSec(monotonic_blocking_deadline), transfer_type, dst_node_id, tid);
|
||||
}
|
||||
|
||||
|
||||
@@ -119,7 +121,7 @@ TEST(TransferSender, Basic)
|
||||
|
||||
while (true)
|
||||
{
|
||||
const int res = dispatcher_rx.spin(0);
|
||||
const int res = dispatcher_rx.spin(tsMono(0));
|
||||
ASSERT_LE(0, res);
|
||||
clockmock.advance(100);
|
||||
if (res == 0)
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include "transfer_test_helpers.hpp"
|
||||
#include "../../clock.hpp"
|
||||
|
||||
|
||||
TEST(TransferTestHelpers, Transfer)
|
||||
@@ -15,8 +16,9 @@ TEST(TransferTestHelpers, Transfer)
|
||||
uavcan::TransferBufferManager<128, 1> mgr(poolmgr);
|
||||
uavcan::TransferBufferAccessor tba(mgr, uavcan::TransferBufferManagerKey(0, uavcan::TransferTypeMessageUnicast));
|
||||
|
||||
uavcan::RxFrame frame(uavcan::Frame(123, uavcan::TransferTypeMessageBroadcast, 1, 0, 0, 0, true), 0, 0, 0);
|
||||
uavcan::MultiFrameIncomingTransfer mfit(10, 1000, frame, tba);
|
||||
uavcan::RxFrame frame(uavcan::Frame(123, uavcan::TransferTypeMessageBroadcast, 1, 0, 0, 0, true),
|
||||
uavcan::MonotonicTime(), uavcan::UtcTime(), 0);
|
||||
uavcan::MultiFrameIncomingTransfer mfit(tsMono(10), tsUtc(1000), frame, tba);
|
||||
|
||||
// Filling the buffer with data
|
||||
static const std::string TEST_DATA = "Kaneda! What do you see? Kaneda! What do you see? Kaneda! Kaneda!!!";
|
||||
|
||||
@@ -15,8 +15,8 @@
|
||||
*/
|
||||
struct Transfer
|
||||
{
|
||||
uint64_t ts_monotonic;
|
||||
uint64_t ts_utc;
|
||||
uavcan::MonotonicTime ts_monotonic;
|
||||
uavcan::UtcTime ts_utc;
|
||||
uavcan::TransferType transfer_type;
|
||||
uavcan::TransferID transfer_id;
|
||||
uavcan::NodeID src_node_id;
|
||||
@@ -50,7 +50,7 @@ struct Transfer
|
||||
}
|
||||
}
|
||||
|
||||
Transfer(uint64_t ts_monotonic, uint64_t ts_utc, uavcan::TransferType transfer_type,
|
||||
Transfer(uavcan::MonotonicTime ts_monotonic, uavcan::UtcTime ts_utc, uavcan::TransferType transfer_type,
|
||||
uavcan::TransferID transfer_id, uavcan::NodeID src_node_id, uavcan::NodeID dst_node_id,
|
||||
const std::string& payload, const uavcan::DataTypeDescriptor& data_type)
|
||||
: ts_monotonic(ts_monotonic)
|
||||
@@ -63,11 +63,24 @@ struct Transfer
|
||||
, payload(payload)
|
||||
{ }
|
||||
|
||||
Transfer(uint64_t ts_monotonic, uint64_t ts_utc, uavcan::TransferType transfer_type,
|
||||
uavcan::TransferID transfer_id, uavcan::NodeID src_node_id, uavcan::NodeID dst_node_id,
|
||||
const std::string& payload, const uavcan::DataTypeDescriptor& data_type)
|
||||
: ts_monotonic(uavcan::MonotonicTime::fromUSec(ts_monotonic))
|
||||
, ts_utc(uavcan::UtcTime::fromUSec(ts_utc))
|
||||
, transfer_type(transfer_type)
|
||||
, transfer_id(transfer_id)
|
||||
, src_node_id(src_node_id)
|
||||
, dst_node_id(dst_node_id)
|
||||
, data_type(data_type)
|
||||
, payload(payload)
|
||||
{ }
|
||||
|
||||
bool operator==(const Transfer& rhs) const
|
||||
{
|
||||
return
|
||||
(ts_monotonic == rhs.ts_monotonic) &&
|
||||
((ts_utc && rhs.ts_utc) ? (ts_utc == rhs.ts_utc) : true) &&
|
||||
((!ts_utc.isZero() && !rhs.ts_utc.isZero()) ? (ts_utc == rhs.ts_utc) : true) &&
|
||||
(transfer_type == rhs.transfer_type) &&
|
||||
(transfer_id == rhs.transfer_id) &&
|
||||
(src_node_id == rhs.src_node_id) &&
|
||||
@@ -176,8 +189,8 @@ std::vector<uavcan::RxFrame> serializeTransfer(const Transfer& transfer)
|
||||
std::vector<uavcan::RxFrame> output;
|
||||
unsigned int frame_index = 0;
|
||||
unsigned int offset = 0;
|
||||
uint64_t ts_monotonic = transfer.ts_monotonic;
|
||||
uint64_t ts_utc = transfer.ts_utc;
|
||||
uavcan::MonotonicTime ts_monotonic = transfer.ts_monotonic;
|
||||
uavcan::UtcTime ts_utc = transfer.ts_utc;
|
||||
|
||||
while (true)
|
||||
{
|
||||
@@ -200,8 +213,8 @@ std::vector<uavcan::RxFrame> serializeTransfer(const Transfer& transfer)
|
||||
frame_index++;
|
||||
|
||||
const uavcan::RxFrame rxfrm(frm, ts_monotonic, ts_utc, 0);
|
||||
ts_monotonic += 1;
|
||||
ts_utc += 1;
|
||||
ts_monotonic += uavcan::MonotonicDuration::fromUSec(1);
|
||||
ts_utc += uavcan::UtcDuration::fromUSec(1);
|
||||
|
||||
output.push_back(rxfrm);
|
||||
if (frm.isLast())
|
||||
@@ -221,14 +234,13 @@ uavcan::DataTypeDescriptor makeDataType(uavcan::DataTypeKind kind, uint16_t id,
|
||||
|
||||
class IncomingTransferEmulatorBase
|
||||
{
|
||||
uint64_t ts_;
|
||||
uavcan::MonotonicTime ts_;
|
||||
uavcan::TransferID tid_;
|
||||
uavcan::NodeID dst_node_id_;
|
||||
|
||||
public:
|
||||
IncomingTransferEmulatorBase(uavcan::NodeID dst_node_id)
|
||||
: ts_(0)
|
||||
, dst_node_id_(dst_node_id)
|
||||
: dst_node_id_(dst_node_id)
|
||||
{ }
|
||||
|
||||
virtual ~IncomingTransferEmulatorBase() { }
|
||||
@@ -237,11 +249,12 @@ public:
|
||||
const uavcan::DataTypeDescriptor& type,
|
||||
uavcan::NodeID dst_node_id_override = uavcan::NodeID())
|
||||
{
|
||||
ts_ += 100;
|
||||
ts_ += uavcan::MonotonicDuration::fromUSec(100);
|
||||
const uavcan::UtcTime utc = uavcan::UtcTime::fromUSec(ts_.toUSec() + 1000000000ul);
|
||||
const uavcan::NodeID dst_node_id = (transfer_type == uavcan::TransferTypeMessageBroadcast)
|
||||
? uavcan::NodeID::Broadcast
|
||||
: (dst_node_id_override.isValid() ? dst_node_id_override : dst_node_id_);
|
||||
const Transfer tr(ts_, ts_ + 1000000000ul, transfer_type, tid_, source_node_id, dst_node_id, payload, type);
|
||||
const Transfer tr(ts_, utc, transfer_type, tid_, source_node_id, dst_node_id, payload, type);
|
||||
tid_.increment();
|
||||
return tr;
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ TEST(Publisher, Basic)
|
||||
msg.payload = "Msg";
|
||||
|
||||
const uint8_t expected_transfer_payload[] = {0x42, 0x72, 0x08, 0xa5, 'M', 's', 'g'};
|
||||
const uint64_t tx_timeout = publisher.DefaultTxTimeoutUsec;
|
||||
const uint64_t tx_timeout_usec = publisher.getDefaultTxTimeout().toUSec();
|
||||
|
||||
/*
|
||||
* Broadcast
|
||||
@@ -67,8 +67,8 @@ TEST(Publisher, Basic)
|
||||
uavcan::CanFrame expected_can_frame;
|
||||
ASSERT_TRUE(expected_frame.compile(expected_can_frame));
|
||||
|
||||
ASSERT_TRUE(can_driver.ifaces[0].matchAndPopTx(expected_can_frame, tx_timeout + 100));
|
||||
ASSERT_TRUE(can_driver.ifaces[1].matchAndPopTx(expected_can_frame, tx_timeout + 100));
|
||||
ASSERT_TRUE(can_driver.ifaces[0].matchAndPopTx(expected_can_frame, tx_timeout_usec + 100));
|
||||
ASSERT_TRUE(can_driver.ifaces[1].matchAndPopTx(expected_can_frame, tx_timeout_usec + 100));
|
||||
ASSERT_TRUE(can_driver.ifaces[0].tx.empty());
|
||||
ASSERT_TRUE(can_driver.ifaces[1].tx.empty());
|
||||
|
||||
@@ -80,8 +80,8 @@ TEST(Publisher, Basic)
|
||||
expected_frame.setPayload(expected_transfer_payload, 7);
|
||||
ASSERT_TRUE(expected_frame.compile(expected_can_frame));
|
||||
|
||||
ASSERT_TRUE(can_driver.ifaces[0].matchAndPopTx(expected_can_frame, tx_timeout + 100));
|
||||
ASSERT_TRUE(can_driver.ifaces[1].matchAndPopTx(expected_can_frame, tx_timeout + 100));
|
||||
ASSERT_TRUE(can_driver.ifaces[0].matchAndPopTx(expected_can_frame, tx_timeout_usec + 100));
|
||||
ASSERT_TRUE(can_driver.ifaces[1].matchAndPopTx(expected_can_frame, tx_timeout_usec + 100));
|
||||
ASSERT_TRUE(can_driver.ifaces[0].tx.empty());
|
||||
ASSERT_TRUE(can_driver.ifaces[1].tx.empty());
|
||||
}
|
||||
@@ -103,8 +103,8 @@ TEST(Publisher, Basic)
|
||||
uavcan::CanFrame expected_can_frame;
|
||||
ASSERT_TRUE(expected_frame.compile(expected_can_frame));
|
||||
|
||||
ASSERT_TRUE(can_driver.ifaces[0].matchAndPopTx(expected_can_frame, tx_timeout + 100 + 1000));
|
||||
ASSERT_TRUE(can_driver.ifaces[1].matchAndPopTx(expected_can_frame, tx_timeout + 100 + 1000));
|
||||
ASSERT_TRUE(can_driver.ifaces[0].matchAndPopTx(expected_can_frame, tx_timeout_usec + 100 + 1000));
|
||||
ASSERT_TRUE(can_driver.ifaces[1].matchAndPopTx(expected_can_frame, tx_timeout_usec + 100 + 1000));
|
||||
ASSERT_TRUE(can_driver.ifaces[0].tx.empty());
|
||||
ASSERT_TRUE(can_driver.ifaces[1].tx.empty());
|
||||
}
|
||||
|
||||
@@ -18,8 +18,8 @@ struct SubscriptionListener
|
||||
|
||||
struct ReceivedDataStructureCopy
|
||||
{
|
||||
uint64_t ts_monotonic;
|
||||
uint64_t ts_utc;
|
||||
uavcan::MonotonicTime ts_monotonic;
|
||||
uavcan::UtcTime ts_utc;
|
||||
uavcan::TransferType transfer_type;
|
||||
uavcan::TransferID transfer_id;
|
||||
uavcan::NodeID src_node_id;
|
||||
@@ -120,7 +120,7 @@ TEST(Subscriber, Basic)
|
||||
// uint_fast8_t frame_index, TransferID transfer_id, bool last_frame
|
||||
uavcan::Frame frame(uavcan::mavlink::Message::DefaultDataTypeID, tt, uavcan::NodeID(i + 100), dni, 0, i, true);
|
||||
frame.setPayload(transfer_payload, 7);
|
||||
uavcan::RxFrame rx_frame(frame, clock_driver.getMonotonicMicroseconds(), clock_driver.getUtcMicroseconds(), 0);
|
||||
uavcan::RxFrame rx_frame(frame, clock_driver.getMonotonic(), clock_driver.getUtc(), 0);
|
||||
rx_frames.push_back(rx_frame);
|
||||
}
|
||||
|
||||
@@ -147,7 +147,7 @@ TEST(Subscriber, Basic)
|
||||
can_driver.ifaces[1].pushRx(rx_frames[i]);
|
||||
}
|
||||
|
||||
ASSERT_LE(0, sch.spin(clock_driver.getMonotonicMicroseconds() + 10000));
|
||||
ASSERT_LE(0, sch.spin(clock_driver.getMonotonic() + durMono(10000)));
|
||||
|
||||
/*
|
||||
* Validation
|
||||
@@ -224,13 +224,12 @@ TEST(Subscriber, FailureCount)
|
||||
uavcan::Frame frame(uavcan::mavlink::Message::DefaultDataTypeID, uavcan::TransferTypeMessageBroadcast,
|
||||
uavcan::NodeID(i + 100), uavcan::NodeID::Broadcast, 0, i, true);
|
||||
// No payload - broken transfer
|
||||
uavcan::RxFrame rx_frame(frame, clock_driver.getMonotonicMicroseconds(),
|
||||
clock_driver.getUtcMicroseconds(), 0);
|
||||
uavcan::RxFrame rx_frame(frame, clock_driver.getMonotonic(), clock_driver.getUtc(), 0);
|
||||
can_driver.ifaces[0].pushRx(rx_frame);
|
||||
can_driver.ifaces[1].pushRx(rx_frame);
|
||||
}
|
||||
|
||||
ASSERT_LE(0, sch.spin(clock_driver.getMonotonicMicroseconds() + 10000));
|
||||
ASSERT_LE(0, sch.spin(clock_driver.getMonotonic() + durMono(10000)));
|
||||
|
||||
ASSERT_EQ(4, sub.getFailureCount());
|
||||
|
||||
@@ -276,13 +275,12 @@ TEST(Subscriber, SingleFrameTransfer)
|
||||
uavcan::Frame frame(root_ns_a::EmptyMessage::DefaultDataTypeID, uavcan::TransferTypeMessageBroadcast,
|
||||
uavcan::NodeID(i + 100), uavcan::NodeID::Broadcast, 0, i, true);
|
||||
// No payload - message is empty
|
||||
uavcan::RxFrame rx_frame(frame, clock_driver.getMonotonicMicroseconds(),
|
||||
clock_driver.getUtcMicroseconds(), 0);
|
||||
uavcan::RxFrame rx_frame(frame, clock_driver.getMonotonic(), clock_driver.getUtc(), 0);
|
||||
can_driver.ifaces[0].pushRx(rx_frame);
|
||||
can_driver.ifaces[1].pushRx(rx_frame);
|
||||
}
|
||||
|
||||
ASSERT_LE(0, sch.spin(clock_driver.getMonotonicMicroseconds() + 10000));
|
||||
ASSERT_LE(0, sch.spin(clock_driver.getMonotonic() + durMono(10000)));
|
||||
|
||||
ASSERT_EQ(0, sub.getFailureCount());
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <uavcan/time.hpp>
|
||||
#include <uavcan/Timestamp.hpp>
|
||||
|
||||
|
||||
TEST(Time, Monotonic)
|
||||
|
||||
Reference in New Issue
Block a user