CAN IO flags

This commit is contained in:
Pavel Kirienko
2014-03-21 16:02:05 +04:00
parent 6246f24297
commit 9d35c616ef
13 changed files with 258 additions and 88 deletions
+24 -6
View File
@@ -42,6 +42,7 @@ struct PairableCanDriver : public uavcan::ICanDriver, public uavcan::ICanIface
uavcan::ISystemClock& clock;
PairableCanDriver* other;
std::queue<uavcan::CanFrame> read_queue;
std::queue<uavcan::CanFrame> loopback_queue;
PairableCanDriver(uavcan::ISystemClock& clock)
: clock(clock)
@@ -67,7 +68,9 @@ struct PairableCanDriver : public uavcan::ICanDriver, public uavcan::ICanIface
{
assert(other);
if (inout_masks.read == 1)
inout_masks.read = read_queue.size() ? 1 : 0;
{
inout_masks.read = (read_queue.size() || loopback_queue.size()) ? 1 : 0;
}
if (inout_masks.read || inout_masks.write)
return 1;
@@ -78,19 +81,34 @@ struct PairableCanDriver : public uavcan::ICanDriver, public uavcan::ICanIface
return 0;
}
int send(const uavcan::CanFrame& frame, uavcan::MonotonicTime)
int send(const uavcan::CanFrame& frame, uavcan::MonotonicTime, uavcan::CanIOFlags flags)
{
assert(other);
other->read_queue.push(frame);
if (flags & uavcan::CanIOFlagLoopback)
{
loopback_queue.push(frame);
}
return 1;
}
int receive(uavcan::CanFrame& out_frame, uavcan::MonotonicTime& out_ts_monotonic, uavcan::UtcTime& out_ts_utc)
int receive(uavcan::CanFrame& out_frame, uavcan::MonotonicTime& out_ts_monotonic, uavcan::UtcTime& out_ts_utc,
uavcan::CanIOFlags& out_flags)
{
assert(other);
assert(read_queue.size());
out_frame = read_queue.front();
read_queue.pop();
out_flags = 0;
if (loopback_queue.empty())
{
assert(read_queue.size());
out_frame = read_queue.front();
read_queue.pop();
}
else
{
out_flags |= uavcan::CanIOFlagLoopback;
out_frame = loopback_queue.front();
loopback_queue.pop();
}
out_ts_monotonic = clock.getMonotonic();
out_ts_utc = clock.getUtc();
return 1;
+28 -12
View File
@@ -36,6 +36,7 @@ public:
std::queue<FrameWithTime> tx; ///< Queue of outgoing frames (bus <-- library)
std::queue<FrameWithTime> rx; ///< Queue of incoming frames (bus --> library)
std::queue<FrameWithTime> loopback; ///< Loopback
bool writeable;
bool tx_failure;
bool rx_failure;
@@ -91,7 +92,7 @@ public:
return frame_time.frame;
}
int send(const uavcan::CanFrame& frame, uavcan::MonotonicTime tx_deadline)
int send(const uavcan::CanFrame& frame, uavcan::MonotonicTime tx_deadline, uavcan::CanIOFlags flags)
{
assert(this);
EXPECT_TRUE(writeable); // Shall never be called when not writeable
@@ -100,21 +101,36 @@ public:
if (!writeable)
return 0;
tx.push(FrameWithTime(frame, tx_deadline));
if (flags & uavcan::CanIOFlagLoopback)
loopback.push(FrameWithTime(frame, iclock.getMonotonic()));
return 1;
}
int receive(uavcan::CanFrame& out_frame, uavcan::MonotonicTime& out_ts_monotonic, uavcan::UtcTime& out_ts_utc)
int receive(uavcan::CanFrame& out_frame, uavcan::MonotonicTime& out_ts_monotonic, uavcan::UtcTime& out_ts_utc,
uavcan::CanIOFlags& out_flags)
{
assert(this);
EXPECT_TRUE(rx.size()); // Shall never be called when not readable
if (rx_failure)
return -1;
if (rx.empty())
return 0;
const FrameWithTime frame = rx.front();
rx.pop();
out_frame = frame.frame;
out_ts_monotonic = frame.time;
out_flags = uavcan::CanIOFlags();
if (loopback.empty())
{
EXPECT_TRUE(rx.size()); // Shall never be called when not readable
if (rx_failure)
return -1;
if (rx.empty())
return 0;
const FrameWithTime frame = rx.front();
rx.pop();
out_frame = frame.frame;
out_ts_monotonic = frame.time;
}
else
{
out_flags |= uavcan::CanIOFlagLoopback;
const FrameWithTime frame = loopback.front();
loopback.pop();
out_frame = frame.frame;
out_ts_monotonic = frame.time;
}
out_ts_utc = uavcan::UtcTime();
return 1;
}
@@ -159,7 +175,7 @@ public:
const int mask = 1 << i;
if ((inout_masks.write & mask) && ifaces.at(i).writeable)
out_write_mask |= mask;
if ((inout_masks.read & mask) && ifaces.at(i).rx.size())
if ((inout_masks.read & mask) && (ifaces.at(i).rx.size() || ifaces.at(i).loopback.size()))
out_read_mask |= mask;
}
inout_masks.write = out_write_mask;
+42 -2
View File
@@ -5,7 +5,7 @@
#include <gtest/gtest.h>
#include "can.hpp"
TEST(CanIOManager, CanDriverMock)
TEST(CanDriverMock, Basic)
{
using uavcan::CanFrame;
using uavcan::CanSelectMasks;
@@ -46,7 +46,9 @@ TEST(CanIOManager, CanDriverMock)
CanFrame fr2;
uavcan::MonotonicTime ts_monotonic;
uavcan::UtcTime ts_utc;
EXPECT_EQ(1, driver.getIface(1)->receive(fr2, ts_monotonic, ts_utc));
uavcan::CanIOFlags flags = 0;
EXPECT_EQ(1, driver.getIface(1)->receive(fr2, ts_monotonic, ts_utc, flags));
EXPECT_EQ(0, flags);
EXPECT_EQ(fr1, fr2);
EXPECT_EQ(100, ts_monotonic.toUSec());
EXPECT_EQ(0, ts_utc.toUSec());
@@ -60,3 +62,41 @@ TEST(CanIOManager, CanDriverMock)
EXPECT_EQ(1, masks.write); // Leaving masks unchanged - the library must ignore them
EXPECT_EQ(7, masks.read);
}
TEST(CanDriverMock, Loopback)
{
using uavcan::CanFrame;
using uavcan::CanSelectMasks;
SystemClockMock clockmock;
CanDriverMock driver(1, clockmock);
CanSelectMasks masks;
masks.write = 1;
masks.read = 1;
EXPECT_LT(0, driver.select(masks, uavcan::MonotonicTime::fromUSec(100)));
EXPECT_EQ(1, masks.write);
EXPECT_EQ(0, masks.read);
clockmock.advance(200);
CanFrame fr1;
fr1.id = 123 | CanFrame::FlagEFF;
EXPECT_EQ(1, driver.getIface(0)->send(fr1, uavcan::MonotonicTime::fromUSec(10000), uavcan::CanIOFlagLoopback));
masks.write = 0;
masks.read = 1;
EXPECT_LT(0, driver.select(masks, uavcan::MonotonicTime::fromUSec(100)));
EXPECT_EQ(0, masks.write);
EXPECT_EQ(1, masks.read);
CanFrame fr2;
uavcan::MonotonicTime ts_monotonic;
uavcan::UtcTime ts_utc;
uavcan::CanIOFlags flags = 0;
EXPECT_EQ(1, driver.getIface(0)->receive(fr2, ts_monotonic, ts_utc, flags));
EXPECT_EQ(uavcan::CanIOFlagLoopback, flags);
EXPECT_EQ(fr1, fr2);
EXPECT_EQ(200, ts_monotonic.toUSec());
EXPECT_EQ(0, ts_utc.toUSec());
}
+95 -26
View File
@@ -37,7 +37,9 @@ TEST(CanIOManager, Reception)
* Empty, will time out
*/
uavcan::CanRxFrame frame;
EXPECT_EQ(0, iomgr.receive(frame, tsMono(100)));
uavcan::CanIOFlags flags = uavcan::CanIOFlags();
EXPECT_EQ(0, iomgr.receive(frame, tsMono(100), flags));
EXPECT_EQ(0, flags);
EXPECT_EQ(100, clockmock.monotonic);
EXPECT_EQ(100, clockmock.utc);
@@ -60,36 +62,43 @@ TEST(CanIOManager, Reception)
driver.ifaces.at(1).pushRx(frames[1][2]);
clockmock.advance(10);
EXPECT_EQ(1, iomgr.receive(frame, uavcan::MonotonicTime()));
EXPECT_EQ(1, iomgr.receive(frame, uavcan::MonotonicTime(), flags));
EXPECT_TRUE(rxFrameEquals(frame, frames[0][0], 110, 0));
EXPECT_EQ(0, flags);
EXPECT_EQ(1, iomgr.receive(frame, uavcan::MonotonicTime()));
EXPECT_EQ(1, iomgr.receive(frame, uavcan::MonotonicTime(), flags));
EXPECT_TRUE(rxFrameEquals(frame, frames[0][1], 120, 0));
EXPECT_EQ(0, flags);
EXPECT_EQ(1, iomgr.receive(frame, uavcan::MonotonicTime()));
EXPECT_EQ(1, iomgr.receive(frame, uavcan::MonotonicTime(), flags));
EXPECT_TRUE(rxFrameEquals(frame, frames[0][2], 130, 0));
EXPECT_EQ(0, flags);
EXPECT_EQ(1, iomgr.receive(frame, uavcan::MonotonicTime()));
EXPECT_EQ(1, iomgr.receive(frame, uavcan::MonotonicTime(), flags));
EXPECT_TRUE(rxFrameEquals(frame, frames[1][0], 110, 1));
EXPECT_EQ(0, flags);
EXPECT_EQ(1, iomgr.receive(frame, uavcan::MonotonicTime()));
EXPECT_EQ(1, iomgr.receive(frame, uavcan::MonotonicTime(), flags));
EXPECT_TRUE(rxFrameEquals(frame, frames[1][1], 120, 1));
EXPECT_EQ(0, flags);
EXPECT_EQ(1, iomgr.receive(frame, uavcan::MonotonicTime()));
EXPECT_EQ(1, iomgr.receive(frame, uavcan::MonotonicTime(), flags));
EXPECT_TRUE(rxFrameEquals(frame, frames[1][2], 130, 1));
EXPECT_EQ(0, flags);
EXPECT_EQ(0, iomgr.receive(frame, uavcan::MonotonicTime())); // Will time out
EXPECT_EQ(0, iomgr.receive(frame, uavcan::MonotonicTime(), flags)); // Will time out
EXPECT_EQ(0, flags);
/*
* Errors
*/
driver.select_failure = true;
EXPECT_EQ(-1, iomgr.receive(frame, uavcan::MonotonicTime()));
EXPECT_EQ(-1, iomgr.receive(frame, uavcan::MonotonicTime(), flags));
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, uavcan::MonotonicTime()));
EXPECT_EQ(-1, iomgr.receive(frame, uavcan::MonotonicTime(), flags));
driver.ifaces.at(0).num_errors = 9000;
driver.ifaces.at(1).num_errors = 100500;
@@ -123,14 +132,16 @@ TEST(CanIOManager, Transmission)
makeCanFrame(1, "a0", EXT), makeCanFrame(99, "a1", EXT), makeCanFrame(803, "a2", STD)
};
uavcan::CanIOFlags flags = uavcan::CanIOFlags();
/*
* Simple transmission
*/
EXPECT_EQ(2, iomgr.send(frames[0], tsMono(100), tsMono(0), ALL_IFACES_MASK, CanTxQueue::Volatile)); // To both
EXPECT_EQ(2, iomgr.send(frames[0], tsMono(100), tsMono(0), ALL_IFACES_MASK, CanTxQueue::Volatile, flags));// 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], tsMono(200), tsMono(100), 2, CanTxQueue::Persistent)); // To #1
EXPECT_EQ(1, iomgr.send(frames[1], tsMono(200), tsMono(100), 2, CanTxQueue::Persistent, flags)); // To #1
EXPECT_TRUE(driver.ifaces.at(1).matchAndPopTx(frames[1], 200));
EXPECT_EQ(0, clockmock.monotonic);
@@ -147,7 +158,7 @@ TEST(CanIOManager, Transmission)
// Sending to both, #0 blocked
driver.ifaces.at(0).writeable = false;
EXPECT_LT(0, iomgr.send(frames[0], tsMono(201), tsMono(200), ALL_IFACES_MASK, CanTxQueue::Persistent));
EXPECT_LT(0, iomgr.send(frames[0], tsMono(201), tsMono(200), ALL_IFACES_MASK, CanTxQueue::Persistent, flags));
EXPECT_TRUE(driver.ifaces.at(1).matchAndPopTx(frames[0], 201));
EXPECT_EQ(200, clockmock.monotonic);
EXPECT_EQ(200, clockmock.utc);
@@ -157,11 +168,11 @@ TEST(CanIOManager, Transmission)
// Sending to both, both blocked
driver.ifaces.at(1).writeable = false;
EXPECT_EQ(0, iomgr.send(frames[1], tsMono(777), tsMono(300), ALL_IFACES_MASK, CanTxQueue::Volatile));
EXPECT_EQ(0, iomgr.send(frames[1], tsMono(777), tsMono(300), ALL_IFACES_MASK, CanTxQueue::Volatile, flags));
EXPECT_EQ(3, pool.getNumUsedBlocks()); // Total 3 frames in TX queue now
// Sending to #0, both blocked
EXPECT_EQ(0, iomgr.send(frames[2], tsMono(888), tsMono(400), 1, CanTxQueue::Persistent));
EXPECT_EQ(0, iomgr.send(frames[2], tsMono(888), tsMono(400), 1, CanTxQueue::Persistent, flags));
EXPECT_EQ(400, clockmock.monotonic);
EXPECT_EQ(400, clockmock.utc);
EXPECT_TRUE(driver.ifaces.at(0).tx.empty());
@@ -175,7 +186,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], tsMono(999), tsMono(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, flags)); // 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());
@@ -183,9 +194,10 @@ TEST(CanIOManager, Transmission)
// Calling receive() to flush the rest two frames
uavcan::CanRxFrame dummy_rx_frame;
EXPECT_EQ(0, iomgr.receive(dummy_rx_frame, tsMono(0)));
EXPECT_EQ(0, iomgr.receive(dummy_rx_frame, tsMono(0), flags));
EXPECT_TRUE(driver.ifaces.at(0).matchAndPopTx(frames[2], 888));
EXPECT_TRUE(driver.ifaces.at(1).matchAndPopTx(frames[1], 777));
ASSERT_EQ(0, flags);
// Final checks
EXPECT_TRUE(driver.ifaces.at(0).tx.empty());
@@ -201,9 +213,9 @@ TEST(CanIOManager, Transmission)
driver.ifaces.at(1).writeable = false;
// Sending 5 frames, one will be rejected
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
EXPECT_EQ(0, iomgr.send(frames[2], tsMono(2222), tsMono(1000), ALL_IFACES_MASK, CanTxQueue::Persistent, flags));
EXPECT_EQ(0, iomgr.send(frames[0], tsMono(3333), tsMono(1100), 2, CanTxQueue::Persistent, flags));
EXPECT_EQ(0, iomgr.send(frames[1], tsMono(4444), tsMono(1200), ALL_IFACES_MASK, CanTxQueue::Volatile, flags)); // One frame kicked here
// State checks
EXPECT_EQ(4, pool.getNumUsedBlocks()); // TX queue is full
@@ -221,15 +233,17 @@ 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, tsMono(0))); // Non-blocking
EXPECT_EQ(1, iomgr.receive(rx_frame, tsMono(0), flags)); // 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));
ASSERT_EQ(0, flags);
EXPECT_EQ(1, iomgr.receive(rx_frame, tsMono(0)));
EXPECT_EQ(1, iomgr.receive(rx_frame, tsMono(0), flags));
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)
ASSERT_EQ(0, flags);
// State checks
EXPECT_EQ(0, pool.getNumUsedBlocks()); // TX queue is empty
@@ -245,10 +259,11 @@ TEST(CanIOManager, Transmission)
*/
// Select failure
driver.select_failure = true;
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(-1, iomgr.receive(rx_frame, tsMono(2000), flags));
EXPECT_EQ(-1, iomgr.send(frames[0], tsMono(2100), tsMono(2000), ALL_IFACES_MASK, CanTxQueue::Volatile, flags));
EXPECT_EQ(1200, clockmock.monotonic);
EXPECT_EQ(1200, clockmock.utc);
ASSERT_EQ(0, flags);
// Transmission failure
driver.select_failure = false;
@@ -256,15 +271,69 @@ 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], tsMono(2200), tsMono(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, flags)); // 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, tsMono(2500)));
EXPECT_EQ(0, iomgr.receive(rx_frame, tsMono(2500), flags));
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
ASSERT_EQ(0, flags);
}
TEST(CanIOManager, Loopback)
{
using uavcan::CanIOManager;
using uavcan::CanTxQueue;
using uavcan::CanFrame;
using uavcan::CanRxFrame;
// Memory
typedef uavcan::PoolAllocator<sizeof(CanTxQueue::Entry) * 4, sizeof(CanTxQueue::Entry)> Pool1;
Pool1* ppool = new Pool1();
Pool1& pool = *ppool;
uavcan::PoolManager<2> poolmgr;
poolmgr.addPool(&pool);
// Platform interface
SystemClockMock clockmock;
CanDriverMock driver(2, clockmock);
// IO Manager
CanIOManager iomgr(driver, poolmgr, clockmock);
ASSERT_EQ(2, iomgr.getNumIfaces());
CanFrame fr1;
fr1.id = 123 | CanFrame::FlagEFF;
CanFrame fr2;
fr2.id = 456 | CanFrame::FlagEFF;
CanRxFrame rfr1;
CanRxFrame rfr2;
uavcan::CanIOFlags flags = 0;
ASSERT_EQ(1, iomgr.send(fr1, tsMono(1000), tsMono(0), 1, CanTxQueue::Volatile, uavcan::CanIOFlagLoopback));
ASSERT_LE(0, iomgr.receive(rfr1, tsMono(100), flags));
ASSERT_EQ(uavcan::CanIOFlagLoopback, flags);
ASSERT_TRUE(rfr1 == fr1);
flags = 0;
ASSERT_EQ(1, iomgr.send(fr1, tsMono(1000), tsMono(0), 1, CanTxQueue::Volatile, uavcan::CanIOFlagLoopback));
ASSERT_EQ(1, iomgr.send(fr2, tsMono(1000), tsMono(0), 1, CanTxQueue::Persistent, uavcan::CanIOFlagLoopback));
ASSERT_LE(0, iomgr.receive(rfr1, tsMono(100), flags));
ASSERT_EQ(uavcan::CanIOFlagLoopback, flags);
ASSERT_LE(0, iomgr.receive(rfr2, tsMono(100), flags));
ASSERT_EQ(uavcan::CanIOFlagLoopback, flags);
ASSERT_TRUE(rfr1 == fr1);
ASSERT_TRUE(rfr2 == fr2);
}
TEST(CanIOManager, Size)
{
std::cout << sizeof(uavcan::CanIOManager) << std::endl;
}
+18 -15
View File
@@ -33,8 +33,9 @@ static bool isInQueue(uavcan::CanTxQueue& queue, const uavcan::CanFrame& frame)
TEST(CanTxQueue, Qos)
{
uavcan::CanTxQueue::Entry e1(makeCanFrame(100, "", EXT), tsMono(1000), uavcan::CanTxQueue::Volatile);
uavcan::CanTxQueue::Entry e2(makeCanFrame(100, "", EXT), tsMono(1000), uavcan::CanTxQueue::Volatile);
const uavcan::CanIOFlags flags = 0;
uavcan::CanTxQueue::Entry e1(makeCanFrame(100, "", EXT), tsMono(1000), uavcan::CanTxQueue::Volatile, flags);
uavcan::CanTxQueue::Entry e2(makeCanFrame(100, "", EXT), tsMono(1000), uavcan::CanTxQueue::Volatile, flags);
EXPECT_FALSE(e1.qosHigherThan(e2));
EXPECT_FALSE(e2.qosHigherThan(e1));
@@ -73,6 +74,8 @@ TEST(CanTxQueue, TxQueue)
CanTxQueue queue(&poolmgr, &clockmock);
EXPECT_TRUE(queue.isEmpty());
const uavcan::CanIOFlags flags = 0;
// Descending priority
const CanFrame f0 = makeCanFrame(0, "f0", EXT);
const CanFrame f1 = makeCanFrame(10, "f1", EXT);
@@ -86,7 +89,7 @@ TEST(CanTxQueue, TxQueue)
/*
* Priority insertion
*/
queue.push(f4, tsMono(100), CanTxQueue::Persistent);
queue.push(f4, tsMono(100), CanTxQueue::Persistent, flags);
EXPECT_FALSE(queue.isEmpty());
EXPECT_EQ(1, pool32.getNumUsedBlocks());
EXPECT_EQ(f4, queue.peek()->frame);
@@ -94,13 +97,13 @@ TEST(CanTxQueue, TxQueue)
EXPECT_TRUE(queue.topPriorityHigherOrEqual(f4)); // Equal
EXPECT_FALSE(queue.topPriorityHigherOrEqual(f3));
queue.push(f3, tsMono(200), CanTxQueue::Persistent);
queue.push(f3, tsMono(200), CanTxQueue::Persistent, flags);
EXPECT_EQ(f3, queue.peek()->frame);
queue.push(f0, tsMono(300), CanTxQueue::Volatile);
queue.push(f0, tsMono(300), CanTxQueue::Volatile, flags);
EXPECT_EQ(f0, queue.peek()->frame);
queue.push(f1, tsMono(400), CanTxQueue::Volatile);
queue.push(f1, tsMono(400), CanTxQueue::Volatile, flags);
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 +128,28 @@ TEST(CanTxQueue, TxQueue)
* QoS
*/
EXPECT_FALSE(isInQueue(queue, f2));
queue.push(f2, tsMono(100), CanTxQueue::Volatile); // Non preempting, will be rejected
queue.push(f2, tsMono(100), CanTxQueue::Volatile, flags); // Non preempting, will be rejected
EXPECT_FALSE(isInQueue(queue, f2));
queue.push(f2, tsMono(500), CanTxQueue::Persistent); // Will override f1 (f3 and f4 are presistent)
queue.push(f2, tsMono(500), CanTxQueue::Persistent, flags); // 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, tsMono(600), CanTxQueue::Persistent); // Will override f0 (rest are presistent)
queue.push(f5, tsMono(600), CanTxQueue::Persistent, flags); // 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, tsMono(700), CanTxQueue::Persistent); // Will override f5 (same frame, same QoS)
queue.push(f5a, tsMono(700), CanTxQueue::Persistent, flags); // Will override f5 (same frame, same QoS)
EXPECT_TRUE(isInQueue(queue, f5a));
EXPECT_FALSE(isInQueue(queue, f5));
queue.push(f6, tsMono(700), CanTxQueue::Persistent); // Will be rejected (lowest QoS)
queue.push(f6, tsMono(700), CanTxQueue::Persistent, flags); // Will be rejected (lowest QoS)
EXPECT_FALSE(isInQueue(queue, f6));
EXPECT_FALSE(queue.topPriorityHigherOrEqual(f0));
@@ -165,19 +168,19 @@ TEST(CanTxQueue, TxQueue)
* Expiration
*/
clockmock.monotonic = 101;
queue.push(f0, tsMono(800), CanTxQueue::Volatile); // Will replace f4 which is expired now
queue.push(f0, tsMono(800), CanTxQueue::Volatile, flags); // 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, tsMono(2000), CanTxQueue::Volatile); // Entire queue is expired
queue.push(f5, tsMono(2000), CanTxQueue::Volatile, flags); // 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, tsMono(1000), CanTxQueue::Persistent); // This entry is already expired
queue.push(f0, tsMono(1000), CanTxQueue::Persistent, flags); // This entry is already expired
EXPECT_EQ(1, getQueueLength(queue));
EXPECT_EQ(1, pool32.getNumUsedBlocks());
EXPECT_EQ(11, queue.getNumRejectedFrames());
@@ -185,7 +188,7 @@ TEST(CanTxQueue, TxQueue)
/*
* Removing
*/
queue.push(f4, tsMono(5000), CanTxQueue::Volatile);
queue.push(f4, tsMono(5000), CanTxQueue::Volatile, flags);
EXPECT_EQ(2, getQueueLength(queue));
EXPECT_TRUE(isInQueue(queue, f4));
EXPECT_EQ(f4, queue.peek()->frame);
+1 -1
View File
@@ -237,7 +237,7 @@ TEST(Dispatcher, Transmission)
ASSERT_TRUE(dispatcher.hasPublisher(123));
ASSERT_FALSE(dispatcher.hasPublisher(456));
ASSERT_EQ(2, dispatcher.send(frame, TX_DEADLINE, tsMono(0), uavcan::CanTxQueue::Volatile));
ASSERT_EQ(2, dispatcher.send(frame, TX_DEADLINE, tsMono(0), uavcan::CanTxQueue::Volatile, 0));
/*
* Validation