TransferBufferManager: using TransferBufferManagerKey instead of plain Node ID, this allows to distinguish transfers of different type from the same Node ID, which is necessary for message broadcasting/unicasting

This commit is contained in:
Pavel Kirienko
2014-02-11 12:21:25 +04:00
parent 149ac87a54
commit 78ff31f9ad
6 changed files with 150 additions and 90 deletions
+29 -19
View File
@@ -232,6 +232,7 @@ static int fillTestData(const std::string& data, uavcan::TransferBufferBase* tbb
TEST(TransferBufferManager, Basic)
{
using uavcan::TransferBufferManager;
using uavcan::TransferBufferManagerKey;
using uavcan::TransferBufferBase;
static const int POOL_BLOCKS = 8;
@@ -243,25 +244,34 @@ TEST(TransferBufferManager, Basic)
std::auto_ptr<TransferBufferManagerType> mgr(new TransferBufferManagerType(&poolmgr));
// Empty
ASSERT_FALSE(mgr->access(0));
ASSERT_FALSE(mgr->access(uavcan::NODE_ID_MAX));
ASSERT_FALSE(mgr->access(TransferBufferManagerKey(0, uavcan::TRANSFER_TYPE_MESSAGE_UNICAST)));
ASSERT_FALSE(mgr->access(TransferBufferManagerKey(uavcan::NODE_ID_MAX, uavcan::TRANSFER_TYPE_MESSAGE_UNICAST)));
TransferBufferBase* tbb = NULL;
const TransferBufferManagerKey keys[5] =
{
TransferBufferManagerKey(0, uavcan::TRANSFER_TYPE_MESSAGE_UNICAST),
TransferBufferManagerKey(1, uavcan::TRANSFER_TYPE_MESSAGE_BROADCAST),
TransferBufferManagerKey(2, uavcan::TRANSFER_TYPE_SERVICE_REQUEST),
TransferBufferManagerKey(127, uavcan::TRANSFER_TYPE_SERVICE_RESPONSE),
TransferBufferManagerKey(64, uavcan::TRANSFER_TYPE_MESSAGE_BROADCAST)
};
// Static 0
ASSERT_TRUE((tbb = mgr->create(0)));
ASSERT_TRUE((tbb = mgr->create(keys[0])));
ASSERT_EQ(MGR_STATIC_BUFFER_SIZE, fillTestData(MGR_TEST_DATA[0], tbb));
ASSERT_EQ(1, mgr->getNumStaticBuffers());
// Static 1
ASSERT_TRUE((tbb = mgr->create(1)));
ASSERT_TRUE((tbb = mgr->create(keys[1])));
ASSERT_EQ(MGR_STATIC_BUFFER_SIZE, fillTestData(MGR_TEST_DATA[1], tbb));
ASSERT_EQ(2, mgr->getNumStaticBuffers());
ASSERT_EQ(0, mgr->getNumDynamicBuffers());
ASSERT_EQ(0, pool.getNumUsedBlocks());
// Dynamic 0
ASSERT_TRUE((tbb = mgr->create(2)));
ASSERT_TRUE((tbb = mgr->create(keys[2])));
ASSERT_EQ(1, pool.getNumUsedBlocks()); // Empty dynamic buffer occupies one block
ASSERT_EQ(MGR_TEST_DATA[2].length(), fillTestData(MGR_TEST_DATA[2], tbb));
ASSERT_EQ(2, mgr->getNumStaticBuffers());
@@ -271,7 +281,7 @@ TEST(TransferBufferManager, Basic)
std::cout << "TransferBufferManager - Basic: Pool usage: " << pool.getNumUsedBlocks() << std::endl;
// Dynamic 2
ASSERT_TRUE((tbb = mgr->create(127)));
ASSERT_TRUE((tbb = mgr->create(keys[3])));
ASSERT_EQ(0, pool.getNumFreeBlocks()); // The test assumes that the memory must be exhausted now
ASSERT_EQ(0, fillTestData(MGR_TEST_DATA[3], tbb));
@@ -279,46 +289,46 @@ TEST(TransferBufferManager, Basic)
ASSERT_EQ(2, mgr->getNumDynamicBuffers());
// Dynamic 3 - will fail due to OOM
ASSERT_FALSE((tbb = mgr->create(64)));
ASSERT_FALSE((tbb = mgr->create(keys[4])));
ASSERT_EQ(2, mgr->getNumStaticBuffers());
ASSERT_EQ(2, mgr->getNumDynamicBuffers());
// Making sure all buffers contain proper data
ASSERT_TRUE((tbb = mgr->access(0)));
ASSERT_TRUE((tbb = mgr->access(keys[0])));
ASSERT_TRUE(matchAgainst(MGR_TEST_DATA[0], *tbb));
ASSERT_TRUE((tbb = mgr->access(1)));
ASSERT_TRUE((tbb = mgr->access(keys[1])));
ASSERT_TRUE(matchAgainst(MGR_TEST_DATA[1], *tbb));
ASSERT_TRUE((tbb = mgr->access(2)));
ASSERT_TRUE((tbb = mgr->access(keys[2])));
ASSERT_TRUE(matchAgainst(MGR_TEST_DATA[2], *tbb));
ASSERT_TRUE((tbb = mgr->access(127)));
ASSERT_TRUE((tbb = mgr->access(keys[3])));
ASSERT_TRUE(matchAgainst(MGR_TEST_DATA[3], *tbb));
// Freeing one static buffer; one dynamic must migrate
mgr->remove(1);
ASSERT_FALSE(mgr->access(1));
mgr->remove(keys[1]);
ASSERT_FALSE(mgr->access(keys[1]));
ASSERT_EQ(2, mgr->getNumStaticBuffers());
ASSERT_EQ(1, mgr->getNumDynamicBuffers()); // One migrated to the static
ASSERT_LT(0, pool.getNumFreeBlocks());
// Removing NodeID 0; migration should fail due to oversized data
mgr->remove(0);
ASSERT_FALSE(mgr->access(0));
mgr->remove(keys[0]);
ASSERT_FALSE(mgr->access(keys[0]));
ASSERT_EQ(1, mgr->getNumStaticBuffers());
ASSERT_EQ(1, mgr->getNumDynamicBuffers()); // Migration failed
// At this time we have the following NodeID: 2, 127
ASSERT_TRUE((tbb = mgr->access(2)));
ASSERT_TRUE((tbb = mgr->access(keys[2])));
ASSERT_TRUE(matchAgainst(MGR_TEST_DATA[2], *tbb));
ASSERT_TRUE((tbb = mgr->access(127)));
ASSERT_TRUE((tbb = mgr->access(keys[3])));
ASSERT_TRUE(matchAgainst(MGR_TEST_DATA[3], *tbb));
// These were deleted: 0, 1
ASSERT_FALSE(mgr->access(1));
ASSERT_FALSE(mgr->access(0));
ASSERT_FALSE(mgr->access(keys[1]));
ASSERT_FALSE(mgr->access(keys[0]));
// Deleting the object; all memory must be freed
ASSERT_NE(0, pool.getNumUsedBlocks());
+23 -22
View File
@@ -11,16 +11,15 @@
struct RxFrameGenerator
{
static const uint8_t DEFAULT_NODE_ID = 42;
static const uavcan::TransferBufferManagerKey DEFAULT_KEY;
uint16_t data_type_id;
uavcan::TransferType ttype;
uint8_t source_node_id;
uavcan::TransferBufferManagerKey bufmgr_key;
RxFrameGenerator(uint16_t data_type_id, uavcan::TransferType ttype, uint8_t source_node_id = DEFAULT_NODE_ID)
RxFrameGenerator(uint16_t data_type_id, uavcan::TransferType ttype,
const uavcan::TransferBufferManagerKey& bufmgr_key = DEFAULT_KEY)
: data_type_id(data_type_id)
, ttype(ttype)
, source_node_id(source_node_id)
, bufmgr_key(bufmgr_key)
{ }
uavcan::RxFrame operator()(int iface_index, const std::string& data, uint8_t frame_index, bool last,
@@ -42,14 +41,16 @@ struct RxFrameGenerator
frm.last_frame = last;
std::copy(data.begin(), data.end(), frm.payload);
frm.payload_len = data.length();
frm.source_node_id = source_node_id;
frm.source_node_id = bufmgr_key.getNodeID();
frm.transfer_id = uavcan::TransferID(transfer_id);
frm.transfer_type = ttype;
frm.transfer_type = bufmgr_key.getTransferType();
return frm;
}
};
const uavcan::TransferBufferManagerKey RxFrameGenerator::DEFAULT_KEY(42, uavcan::TRANSFER_TYPE_MESSAGE_UNICAST);
template <unsigned int BUFSIZE>
struct Context
@@ -62,7 +63,7 @@ struct Context
: bufmgr(&poolmgr)
{
assert(poolmgr.allocate(1) == NULL);
receiver = uavcan::TransferReceiver(&bufmgr, RxFrameGenerator::DEFAULT_NODE_ID);
receiver = uavcan::TransferReceiver(&bufmgr, RxFrameGenerator::DEFAULT_KEY);
}
~Context()
@@ -125,7 +126,7 @@ TEST(TransferReceiver, Basic)
CHECK_NOT_COMPLETE(rcv.addFrame(gen(0, "12345678", 0, false, 0, 100)));
CHECK_COMPLETE(rcv.addFrame(gen(0, "foo", 1, true, 0, 200)));
ASSERT_TRUE(matchBufferContent(bufmgr.access(gen.source_node_id), "12345678foo"));
ASSERT_TRUE(matchBufferContent(bufmgr.access(gen.bufmgr_key), "12345678foo"));
ASSERT_EQ(TransferReceiver::DEFAULT_TRANSFER_INTERVAL, rcv.getInterval()); // Not initialized yet
ASSERT_EQ(100, rcv.getLastTransferTimestamp());
@@ -142,7 +143,7 @@ TEST(TransferReceiver, Basic)
CHECK_NOT_COMPLETE(rcv.addFrame(gen(0, "", 31,true, 1, 1300))); // Unexpected FI
CHECK_COMPLETE( rcv.addFrame(gen(0, "", 2, true, 1, 1300)));
ASSERT_TRUE(matchBufferContent(bufmgr.access(gen.source_node_id), "12345678abcdefgh"));
ASSERT_TRUE(matchBufferContent(bufmgr.access(gen.bufmgr_key), "12345678abcdefgh"));
ASSERT_GT(TransferReceiver::DEFAULT_TRANSFER_INTERVAL, rcv.getInterval());
ASSERT_LT(TransferReceiver::MIN_TRANSFER_INTERVAL, rcv.getInterval());
ASSERT_EQ(1000, rcv.getLastTransferTimestamp());
@@ -157,7 +158,7 @@ TEST(TransferReceiver, Basic)
CHECK_NOT_COMPLETE(rcv.addFrame(gen(1, "qwe", 0, true, 2, 2100))); // Wrong iface
CHECK_SINGLE_FRAME(rcv.addFrame(gen(0, "qwe", 0, true, 2, 2200)));
ASSERT_FALSE(bufmgr.access(RxFrameGenerator::DEFAULT_NODE_ID)); // Buffer must be removed
ASSERT_FALSE(bufmgr.access(gen.bufmgr_key)); // Buffer must be removed
ASSERT_GT(TransferReceiver::DEFAULT_TRANSFER_INTERVAL, rcv.getInterval());
ASSERT_EQ(2200, rcv.getLastTransferTimestamp());
@@ -203,14 +204,14 @@ TEST(TransferReceiver, Basic)
ASSERT_LT(TransferReceiver::DEFAULT_TRANSFER_INTERVAL, rcv.getInterval());
ASSERT_LE(TransferReceiver::MIN_TRANSFER_INTERVAL, rcv.getInterval());
ASSERT_GE(TransferReceiver::MAX_TRANSFER_INTERVAL, rcv.getInterval());
ASSERT_TRUE(matchBufferContent(bufmgr.access(gen.source_node_id), "12345678qwe"));
ASSERT_TRUE(matchBufferContent(bufmgr.access(gen.bufmgr_key), "12345678qwe"));
/*
* Buffer cleanup
*/
ASSERT_TRUE(bufmgr.access(gen.source_node_id));
ASSERT_TRUE(bufmgr.access(gen.bufmgr_key));
context.receiver = TransferReceiver();
ASSERT_FALSE(bufmgr.access(gen.source_node_id));
ASSERT_FALSE(bufmgr.access(gen.bufmgr_key));
}
@@ -231,7 +232,7 @@ TEST(TransferReceiver, OutOfBufferSpace_32bytes)
CHECK_COMPLETE( rcv.addFrame(gen(1, "", 4, true, 10, 100000400))); // 32
ASSERT_EQ(100000000, rcv.getLastTransferTimestamp());
ASSERT_TRUE(matchBufferContent(bufmgr.access(gen.source_node_id), "12345678123456781234567812345678"));
ASSERT_TRUE(matchBufferContent(bufmgr.access(gen.bufmgr_key), "12345678123456781234567812345678"));
/*
* Transfer longer than available buffer space
@@ -243,7 +244,7 @@ TEST(TransferReceiver, OutOfBufferSpace_32bytes)
CHECK_NOT_COMPLETE(rcv.addFrame(gen(1, "12345678", 4, true, 11, 100001300))); // 40 // EOT, ignored - lost sync
ASSERT_EQ(100000000, rcv.getLastTransferTimestamp());
ASSERT_FALSE(bufmgr.access(gen.source_node_id)); // Buffer should be removed
ASSERT_FALSE(bufmgr.access(gen.bufmgr_key)); // Buffer should be removed
}
@@ -262,7 +263,7 @@ TEST(TransferReceiver, UnterminatedTransfer)
}
CHECK_COMPLETE(rcv.addFrame(gen(1, "12345678", uavcan::Frame::FRAME_INDEX_MAX, true, 0, 1100)));
ASSERT_EQ(1000, rcv.getLastTransferTimestamp());
ASSERT_TRUE(matchBufferContent(bufmgr.access(gen.source_node_id), content));
ASSERT_TRUE(matchBufferContent(bufmgr.access(gen.bufmgr_key), content));
}
@@ -281,7 +282,7 @@ TEST(TransferReceiver, OutOfOrderFrames)
CHECK_COMPLETE( rcv.addFrame(gen(1, "abcd", 2, true, 10, 100000400)));
ASSERT_EQ(100000000, rcv.getLastTransferTimestamp());
ASSERT_TRUE(matchBufferContent(bufmgr.access(gen.source_node_id), "12345678qwertyuiabcd"));
ASSERT_TRUE(matchBufferContent(bufmgr.access(gen.bufmgr_key), "12345678qwertyuiabcd"));
}
@@ -302,7 +303,7 @@ TEST(TransferReceiver, IntervalMeasurement)
CHECK_NOT_COMPLETE(rcv.addFrame(gen(1, "qwertyui", 1, false, tid.get(), timestamp)));
CHECK_COMPLETE( rcv.addFrame(gen(1, "abcd", 2, true, tid.get(), timestamp)));
ASSERT_TRUE(matchBufferContent(bufmgr.access(gen.source_node_id), "12345678qwertyuiabcd"));
ASSERT_TRUE(matchBufferContent(bufmgr.access(gen.bufmgr_key), "12345678qwertyuiabcd"));
ASSERT_EQ(timestamp, rcv.getLastTransferTimestamp());
timestamp += INTERVAL;
@@ -334,7 +335,7 @@ TEST(TransferReceiver, Restart)
CHECK_NOT_COMPLETE(rcv.addFrame(gen(1, "12345678", 1, false, 0, 13000300))); // Continue 3 sec later, iface timeout
CHECK_COMPLETE( rcv.addFrame(gen(1, "12345678", 2, true, 0, 13000400))); // OK nevertheless
ASSERT_TRUE(matchBufferContent(bufmgr.access(gen.source_node_id), "123456781234567812345678"));
ASSERT_TRUE(matchBufferContent(bufmgr.access(gen.bufmgr_key), "123456781234567812345678"));
/*
* Begins OK, gets an iface timeout, switches to another iface
@@ -348,5 +349,5 @@ TEST(TransferReceiver, Restart)
CHECK_NOT_COMPLETE(rcv.addFrame(gen(0, "12345678", 1, false, 2, 16000900))); // Continuing
CHECK_COMPLETE( rcv.addFrame(gen(0, "12345678", 2, true, 2, 16000910))); // Done
ASSERT_TRUE(matchBufferContent(bufmgr.access(gen.source_node_id), "123456781234567812345678"));
ASSERT_TRUE(matchBufferContent(bufmgr.access(gen.bufmgr_key), "123456781234567812345678"));
}