libuav original

Dependents:   UAVCAN UAVCAN_Subscriber

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers transfer_receiver.cpp Source File

transfer_receiver.cpp

00001 /*
00002  * Copyright (C) 2014 Pavel Kirienko <pavel.kirienko@gmail.com>
00003  */
00004 
00005 #include <algorithm>
00006 #include <gtest/gtest.h>
00007 #include <uavcan/transport/transfer_receiver.hpp>
00008 #include "../clock.hpp"
00009 #include "transfer_test_helpers.hpp"
00010 
00011 /*
00012  * Beware!
00013  * The code you're about to look at desperately needs some cleaning.
00014  */
00015 
00016 enum SotEotToggle
00017 {
00018     SET000 = 0,
00019     SET001 = 1,
00020     SET010 = 2,
00021     SET011 = 3,
00022     SET100 = 4,
00023     SET101 = 5, // Illegal
00024     SET110 = 6,
00025     SET111 = 7  // Illegal
00026 };
00027 
00028 struct RxFrameGenerator
00029 {
00030     static const uavcan::TransferBufferManagerKey DEFAULT_KEY;
00031     enum { TARGET_NODE_ID = 126 };
00032 
00033     uint16_t data_type_id;
00034     uavcan::TransferBufferManagerKey bufmgr_key;
00035 
00036     RxFrameGenerator(uint16_t data_type_id, const uavcan::TransferBufferManagerKey& bufmgr_key = DEFAULT_KEY)
00037         : data_type_id(data_type_id)
00038         , bufmgr_key(bufmgr_key)
00039     { }
00040 
00041     /// iface_index, data, set, transfer_id, ts_monotonic [, ts_utc]
00042     uavcan::RxFrame operator()(uint8_t iface_index, const std::string& data, SotEotToggle set,
00043                                uint8_t transfer_id, uint64_t ts_monotonic, uint64_t ts_utc = 0)
00044     {
00045         const uavcan::NodeID dst_nid =
00046             (bufmgr_key.getTransferType() == uavcan::TransferTypeMessageBroadcast) ?
00047             uavcan::NodeID::Broadcast : TARGET_NODE_ID;
00048 
00049         uavcan::Frame frame(data_type_id, bufmgr_key.getTransferType(), bufmgr_key.getNodeID(),
00050                             dst_nid, transfer_id);
00051 
00052         frame.setStartOfTransfer((set & (1 << 2)) != 0);
00053         frame.setEndOfTransfer((set & (1 << 1)) != 0);
00054 
00055         if ((set & (1 << 0)) != 0)
00056         {
00057             frame.flipToggle();
00058         }
00059 
00060         EXPECT_EQ(data.length(),
00061                   frame.setPayload(reinterpret_cast<const uint8_t*>(data.c_str()), unsigned(data.length())));
00062 
00063         uavcan::RxFrame output(frame, uavcan::MonotonicTime::fromUSec(ts_monotonic),
00064                                uavcan::UtcTime::fromUSec(ts_utc), iface_index);
00065         //std::cout << "Generated frame: " << output.toString() << std::endl;
00066 
00067         return output;
00068     }
00069 };
00070 
00071 const uavcan::TransferBufferManagerKey RxFrameGenerator::DEFAULT_KEY(42, uavcan::TransferTypeMessageBroadcast);
00072 
00073 
00074 template <unsigned BufSize>
00075 struct Context
00076 {
00077     uavcan::PoolAllocator<uavcan::MemPoolBlockSize * 100, uavcan::MemPoolBlockSize>  pool;
00078     uavcan::TransferReceiver receiver;  // Must be default constructible and copyable
00079     uavcan::TransferBufferManager bufmgr;
00080 
00081     Context() :
00082         bufmgr(BufSize, pool)
00083     { }
00084 
00085     ~Context()
00086     {
00087         // We need to destroy the receiver before its buffer manager
00088         receiver = uavcan::TransferReceiver();
00089     }
00090 };
00091 
00092 
00093 static bool matchBufferContent(const uavcan::ITransferBuffer* tbb, const std::string& content)
00094 {
00095     uint8_t data[1024];
00096     std::fill(data, data + sizeof(data), 0);
00097     if (content.length() > sizeof(data))
00098     {
00099         std::cerr << "matchBufferContent(): Content is too long" << std::endl;
00100         std::exit(1);
00101     }
00102     tbb->read(0, data, unsigned(content.length()));
00103     if (std::equal(content.begin(), content.end(), data))
00104     {
00105         return true;
00106     }
00107     std::cout << "Buffer content mismatch:"
00108               << "\n\tExpected: " << content
00109               << "\n\tActually: " << reinterpret_cast<const char*>(data)
00110               << std::endl;
00111     return false;
00112 }
00113 
00114 
00115 #define CHECK_NOT_COMPLETE(x) ASSERT_EQ(uavcan::TransferReceiver::ResultNotComplete, (x))
00116 #define CHECK_COMPLETE(x)     ASSERT_EQ(uavcan::TransferReceiver::ResultComplete, (x))
00117 #define CHECK_SINGLE_FRAME(x) ASSERT_EQ(uavcan::TransferReceiver::ResultSingleFrame, (x))
00118 
00119 TEST(TransferReceiver, Basic)
00120 {
00121     using uavcan::TransferReceiver;
00122     Context<32> context;
00123     RxFrameGenerator gen(789);
00124     uavcan::TransferReceiver& rcv = context.receiver;
00125     uavcan::TransferBufferManager& bufmgr = context.bufmgr;
00126     uavcan::TransferBufferAccessor bk(context.bufmgr, RxFrameGenerator::DEFAULT_KEY);
00127 
00128     std::cout << "sizeof(TransferReceiver): " << sizeof(TransferReceiver) << std::endl;
00129 
00130     /*
00131      * Empty
00132      */
00133     ASSERT_EQ(TransferReceiver::getDefaultTransferInterval(), rcv.getInterval());
00134     ASSERT_EQ(0, rcv.getLastTransferTimestampMonotonic().toUSec());
00135 
00136     /*
00137      * Single frame transfer with zero ts, must be ignored
00138      */
00139     CHECK_NOT_COMPLETE(rcv.addFrame(gen(0, "Foo", SET110, 0, 0), bk));
00140     ASSERT_EQ(TransferReceiver::getDefaultTransferInterval(), rcv.getInterval());
00141     ASSERT_EQ(0, rcv.getLastTransferTimestampMonotonic().toUSec());
00142 
00143     /*
00144      * Valid compound transfer
00145      * Args: iface_index, data, set, transfer_id, ts_monotonic
00146      */
00147     CHECK_NOT_COMPLETE(rcv.addFrame(gen(0, "\x34\x12" "34567", SET100, 0, 100), bk));
00148     CHECK_COMPLETE(    rcv.addFrame(gen(0, "foo",              SET011, 0, 200), bk));
00149 
00150     ASSERT_TRUE(matchBufferContent(bufmgr.access(gen.bufmgr_key), "34567foo"));
00151     ASSERT_EQ(0x1234, rcv.getLastTransferCrc());
00152     ASSERT_EQ(TransferReceiver::getDefaultTransferInterval(), rcv.getInterval());           // Not initialized yet
00153     ASSERT_EQ(100, rcv.getLastTransferTimestampMonotonic().toUSec());
00154 
00155     /*
00156      * Compound transfer mixed with invalid frames; buffer was not released explicitly
00157      * Args: iface_index, data, set, transfer_id, ts_monotonic
00158      */
00159     CHECK_NOT_COMPLETE(rcv.addFrame(gen(0, "qwe",     SET100, 0, 300), bk));    // Previous TID, rejected
00160     CHECK_NOT_COMPLETE(rcv.addFrame(gen(1, "rty",     SET100, 0, 300), bk));    // Previous TID, wrong iface
00161     CHECK_NOT_COMPLETE(rcv.addFrame(gen(0, "\x9a\x78" "34567", SET100, 1, 1000), bk));
00162     CHECK_NOT_COMPLETE(rcv.addFrame(gen(0, "qwertyu", SET100, 1, 1100), bk));   // Old toggle
00163     CHECK_NOT_COMPLETE(rcv.addFrame(gen(0, "qwertyu", SET000, 1, 1100), bk));   // Old toggle
00164     CHECK_NOT_COMPLETE(rcv.addFrame(gen(0, "abcdefg", SET001, 1, 1200), bk));
00165     CHECK_NOT_COMPLETE(rcv.addFrame(gen(0, "4567891", SET001, 2, 1300), bk));   // Next TID, but not SOT
00166     CHECK_NOT_COMPLETE(rcv.addFrame(gen(1, "",        SET010, 1, 1300), bk));   // Wrong iface
00167     CHECK_NOT_COMPLETE(rcv.addFrame(gen(0, "",        SET001, 1, 1300), bk));   // Unexpected toggle
00168     CHECK_COMPLETE(    rcv.addFrame(gen(0, "",        SET010, 1, 1300), bk));
00169 
00170     ASSERT_TRUE(matchBufferContent(bufmgr.access(gen.bufmgr_key), "34567abcdefg"));
00171     ASSERT_EQ(0x789A, rcv.getLastTransferCrc());
00172     ASSERT_GE(TransferReceiver::getDefaultTransferInterval(), rcv.getInterval());
00173     ASSERT_LE(TransferReceiver::getMinTransferInterval(), rcv.getInterval());
00174     ASSERT_EQ(1000, rcv.getLastTransferTimestampMonotonic().toUSec());
00175     ASSERT_FALSE(rcv.isTimedOut(tsMono(1000)));
00176     ASSERT_FALSE(rcv.isTimedOut(tsMono(5000)));
00177     ASSERT_TRUE(rcv.isTimedOut(tsMono(60000000)));
00178 
00179     /*
00180      * Single-frame transfers
00181      * Args: iface_index, data, set, transfer_id, ts_monotonic
00182      */
00183     CHECK_NOT_COMPLETE(rcv.addFrame(gen(0, "qwe",      SET110, 1, 2000), bk));   // Previous TID
00184     CHECK_NOT_COMPLETE(rcv.addFrame(gen(1, "qwe",      SET110, 2, 2100), bk));   // Wrong iface
00185     CHECK_SINGLE_FRAME(rcv.addFrame(gen(0, "qwe",      SET110, 2, 2200), bk));
00186 
00187     ASSERT_FALSE(bufmgr.access(gen.bufmgr_key));          // Buffer must be removed
00188     ASSERT_GT(TransferReceiver::getDefaultTransferInterval(), rcv.getInterval());
00189     ASSERT_EQ(2200, rcv.getLastTransferTimestampMonotonic().toUSec());
00190 
00191     CHECK_SINGLE_FRAME(rcv.addFrame(gen(0, "",         SET110, 3, 2500), bk));
00192     ASSERT_EQ(2500, rcv.getLastTransferTimestampMonotonic().toUSec());
00193 
00194     CHECK_SINGLE_FRAME(rcv.addFrame(gen(0, "",         SET110, 0, 3000), bk));
00195     CHECK_SINGLE_FRAME(rcv.addFrame(gen(0, "",         SET110, 1, 3100), bk));
00196     CHECK_SINGLE_FRAME(rcv.addFrame(gen(0, "",         SET110, 3, 3200), bk));
00197     CHECK_NOT_COMPLETE(rcv.addFrame(gen(1, "",         SET110, 0, 3300), bk));   // Old TID, wrong iface
00198     CHECK_NOT_COMPLETE(rcv.addFrame(gen(1, "",         SET110, 2, 3400), bk));   // Old TID, wrong iface
00199     CHECK_NOT_COMPLETE(rcv.addFrame(gen(1, "",         SET110, 3, 3500), bk));   // Old TID, wrong iface
00200     CHECK_SINGLE_FRAME(rcv.addFrame(gen(0, "",         SET110, 4, 3600), bk));
00201     ASSERT_EQ(3600, rcv.getLastTransferTimestampMonotonic().toUSec());
00202 
00203     std::cout << "Interval: " << rcv.getInterval().toString() << std::endl;
00204 
00205     /*
00206      * Timeouts
00207      */
00208     CHECK_NOT_COMPLETE(rcv.addFrame(gen(1, "qwe",      SET110, 1, 5000), bk));    // Wrong iface - ignored
00209     CHECK_SINGLE_FRAME(rcv.addFrame(gen(1, "qwe",      SET110, 6, 1500000), bk)); // Accepted due to iface timeout
00210     ASSERT_EQ(1500000, rcv.getLastTransferTimestampMonotonic().toUSec());
00211 
00212     std::cout << "Interval: " << rcv.getInterval().toString() << std::endl;
00213 
00214     CHECK_NOT_COMPLETE(rcv.addFrame(gen(0, "qwe",      SET110, 7, 1500100), bk)); // Ignored - old iface 0
00215     CHECK_SINGLE_FRAME(rcv.addFrame(gen(1, "qwe",      SET110, 7, 1500100), bk));
00216     ASSERT_EQ(1500100, rcv.getLastTransferTimestampMonotonic().toUSec());
00217 
00218     std::cout << "Interval: " << rcv.getInterval().toString() << std::endl;
00219 
00220     CHECK_NOT_COMPLETE(rcv.addFrame(gen(1, "qwe",      SET110, 7, 1500100), bk));   // Old TID
00221     CHECK_SINGLE_FRAME(rcv.addFrame(gen(0, "qwe",      SET110, 7, 100000000), bk)); // Accepted - global timeout
00222     ASSERT_EQ(100000000, rcv.getLastTransferTimestampMonotonic().toUSec());
00223 
00224     std::cout << "Interval: " << rcv.getInterval().toString() << std::endl;
00225 
00226     CHECK_SINGLE_FRAME(rcv.addFrame(gen(0, "qwe",      SET110, 8, 100000100), bk));
00227     ASSERT_EQ(100000100, rcv.getLastTransferTimestampMonotonic().toUSec());
00228 
00229     std::cout << "Interval: " << rcv.getInterval().toString() << std::endl;
00230 
00231     ASSERT_TRUE(rcv.isTimedOut(tsMono(900000000)));
00232     CHECK_NOT_COMPLETE(rcv.addFrame(gen(1, "\x78\x56" "34567", SET100, 0, 900000000), bk)); // Global timeout
00233     CHECK_NOT_COMPLETE(rcv.addFrame(gen(0, "1234567",          SET100, 0, 900000100), bk)); // Wrong iface
00234     CHECK_NOT_COMPLETE(rcv.addFrame(gen(0, "qwe",              SET011, 0, 900000200), bk)); // Wrong iface
00235     CHECK_COMPLETE(    rcv.addFrame(gen(1, "qwe",              SET011, 0, 900000200), bk));
00236 
00237     ASSERT_EQ(900000000, rcv.getLastTransferTimestampMonotonic().toUSec());
00238     std::cout << "Interval: " << rcv.getInterval().toString() << std::endl;
00239 
00240     ASSERT_FALSE(rcv.isTimedOut(tsMono(1000)));
00241     ASSERT_FALSE(rcv.isTimedOut(tsMono(900000300)));
00242     ASSERT_TRUE(rcv.isTimedOut(tsMono(9990000000)));
00243 
00244     ASSERT_LT(TransferReceiver::getDefaultTransferInterval(), rcv.getInterval());
00245     ASSERT_LE(TransferReceiver::getMinTransferInterval(), rcv.getInterval());
00246     ASSERT_GE(TransferReceiver::getMaxTransferInterval(), rcv.getInterval());
00247     ASSERT_TRUE(matchBufferContent(bufmgr.access(gen.bufmgr_key), "34567qwe"));
00248     ASSERT_EQ(0x5678, rcv.getLastTransferCrc());
00249 
00250     /*
00251      * Destruction
00252      */
00253     ASSERT_TRUE(bufmgr.access(gen.bufmgr_key));
00254     context.receiver.~TransferReceiver();         // TransferReceiver does not own the buffer, it must not be released!
00255     ASSERT_TRUE(bufmgr.access(gen.bufmgr_key));   // Making sure that the buffer is still there
00256 }
00257 
00258 
00259 TEST(TransferReceiver, OutOfBufferSpace_32bytes)
00260 {
00261     Context<32> context;
00262     RxFrameGenerator gen(789);
00263     uavcan::TransferReceiver& rcv = context.receiver;
00264     uavcan::TransferBufferManager& bufmgr = context.bufmgr;
00265     uavcan::TransferBufferAccessor bk(context.bufmgr, RxFrameGenerator::DEFAULT_KEY);
00266 
00267     /*
00268      * Simple transfer, maximum buffer length
00269      */
00270     CHECK_NOT_COMPLETE(rcv.addFrame(gen(1, "1234567", SET100, 1, 100000000), bk)); // 5
00271     CHECK_NOT_COMPLETE(rcv.addFrame(gen(1, "1234567", SET001, 1, 100000100), bk)); // 12
00272     CHECK_NOT_COMPLETE(rcv.addFrame(gen(1, "1234567", SET000, 1, 100000200), bk)); // 19
00273     CHECK_NOT_COMPLETE(rcv.addFrame(gen(1, "1234567", SET001, 1, 100000300), bk)); // 26
00274     CHECK_COMPLETE(    rcv.addFrame(gen(1, "123456",  SET010, 1, 100000400), bk)); // 32
00275 
00276     ASSERT_EQ(100000000, rcv.getLastTransferTimestampMonotonic().toUSec());
00277     ASSERT_TRUE(matchBufferContent(bufmgr.access(gen.bufmgr_key), "34567123456712345671234567123456"));
00278     ASSERT_EQ(0x3231, rcv.getLastTransferCrc());                   // CRC from "12", which is 0x3231 in little endian
00279 
00280     /*
00281      * Transfer longer than available buffer space
00282      */
00283     CHECK_NOT_COMPLETE(rcv.addFrame(gen(1, "1234567", SET100, 2, 100001000), bk)); // 5
00284     CHECK_NOT_COMPLETE(rcv.addFrame(gen(1, "1234567", SET001, 2, 100001100), bk)); // 12
00285     CHECK_NOT_COMPLETE(rcv.addFrame(gen(1, "1234567", SET000, 2, 100001200), bk)); // 19
00286     CHECK_NOT_COMPLETE(rcv.addFrame(gen(1, "1234567", SET001, 2, 100001200), bk)); // 26
00287     CHECK_NOT_COMPLETE(rcv.addFrame(gen(1, "1234567", SET010, 2, 100001300), bk)); // 33 // EOT, ignored - lost sync
00288 
00289     ASSERT_EQ(100000000, rcv.getLastTransferTimestampMonotonic().toUSec());  // Timestamp will not be overriden
00290     ASSERT_FALSE(bufmgr.access(gen.bufmgr_key));                    // Buffer should be removed
00291 
00292     ASSERT_EQ(1, rcv.yieldErrorCount());
00293     ASSERT_EQ(0, rcv.yieldErrorCount());
00294 }
00295 
00296 
00297 TEST(TransferReceiver, OutOfOrderFrames)
00298 {
00299     Context<32> context;
00300     RxFrameGenerator gen(789);
00301     uavcan::TransferReceiver& rcv = context.receiver;
00302     uavcan::TransferBufferManager& bufmgr = context.bufmgr;
00303     uavcan::TransferBufferAccessor bk(context.bufmgr, RxFrameGenerator::DEFAULT_KEY);
00304 
00305     CHECK_NOT_COMPLETE(rcv.addFrame(gen(1, "1234567", SET100, 7, 100000000), bk));
00306     CHECK_NOT_COMPLETE(rcv.addFrame(gen(1, "-------", SET000, 7, 100000100), bk));  // Out of order
00307     CHECK_NOT_COMPLETE(rcv.addFrame(gen(1, "-------", SET010, 7, 100000200), bk));  // Out of order
00308     CHECK_NOT_COMPLETE(rcv.addFrame(gen(1, "qwertyu", SET001, 7, 100000300), bk));
00309     CHECK_NOT_COMPLETE(rcv.addFrame(gen(1, "-------", SET011, 7, 100000200), bk));  // Out of order
00310     CHECK_COMPLETE(    rcv.addFrame(gen(1, "abcd",    SET010, 7, 100000400), bk));
00311 
00312     ASSERT_EQ(100000000, rcv.getLastTransferTimestampMonotonic().toUSec());
00313     ASSERT_TRUE(matchBufferContent(bufmgr.access(gen.bufmgr_key), "34567qwertyuabcd"));
00314     ASSERT_EQ(0x3231, rcv.getLastTransferCrc());
00315 
00316     ASSERT_EQ(3, rcv.yieldErrorCount());
00317     ASSERT_EQ(0, rcv.yieldErrorCount());
00318 }
00319 
00320 
00321 TEST(TransferReceiver, IntervalMeasurement)
00322 {
00323     Context<32> context;
00324     RxFrameGenerator gen(789);
00325     uavcan::TransferReceiver& rcv = context.receiver;
00326     uavcan::TransferBufferManager& bufmgr = context.bufmgr;
00327     uavcan::TransferBufferAccessor bk(context.bufmgr, RxFrameGenerator::DEFAULT_KEY);
00328 
00329     static const int INTERVAL = 1000;
00330     uavcan::TransferID tid;
00331     uint64_t timestamp = 100000000;
00332 
00333     for (int i = 0; i < 1000; i++)
00334     {
00335         CHECK_NOT_COMPLETE(rcv.addFrame(gen(1, "1234567", SET100, tid.get(), timestamp), bk));
00336         CHECK_NOT_COMPLETE(rcv.addFrame(gen(1, "qwertyu", SET001, tid.get(), timestamp), bk));
00337         CHECK_COMPLETE(    rcv.addFrame(gen(1, "abcd",    SET010, tid.get(), timestamp), bk));
00338 
00339         ASSERT_TRUE(matchBufferContent(bufmgr.access(gen.bufmgr_key), "34567qwertyuabcd"));
00340         ASSERT_EQ(0x3231, rcv.getLastTransferCrc());
00341         ASSERT_EQ(timestamp, rcv.getLastTransferTimestampMonotonic().toUSec());
00342 
00343         timestamp += uint64_t(INTERVAL);
00344         tid.increment();
00345     }
00346 
00347     ASSERT_EQ(INTERVAL, rcv.getInterval().toUSec());
00348 }
00349 
00350 
00351 TEST(TransferReceiver, Restart)
00352 {
00353     Context<32> context;
00354     RxFrameGenerator gen(789);
00355     uavcan::TransferReceiver& rcv = context.receiver;
00356     uavcan::TransferBufferManager& bufmgr = context.bufmgr;
00357     uavcan::TransferBufferAccessor bk(context.bufmgr, RxFrameGenerator::DEFAULT_KEY);
00358 
00359     /*
00360      * This transfer looks complete, but must be ignored because of large delay after the first frame
00361      * Args: iface_index, data, set, transfer_id, ts_monotonic [, ts_utc]
00362      */
00363     CHECK_NOT_COMPLETE(rcv.addFrame(gen(0, "-------", SET100, 0, 100), bk));       // Begin
00364     CHECK_NOT_COMPLETE(rcv.addFrame(gen(0, "-------", SET001, 0, 100000100), bk)); // Continue 100 sec later, expired
00365     CHECK_NOT_COMPLETE(rcv.addFrame(gen(0, "-------", SET010, 0, 100000200), bk)); // Ignored
00366 
00367     /*
00368      * Begins immediately after, encounters a delay 0.9 sec but completes OK
00369      */
00370     CHECK_NOT_COMPLETE(rcv.addFrame(gen(1, "1234567", SET100, 0, 100000300), bk)); // Begin
00371     CHECK_NOT_COMPLETE(rcv.addFrame(gen(1, "1234567", SET001, 0, 100900300), bk)); // 0.9 sec later
00372     CHECK_COMPLETE(    rcv.addFrame(gen(1, "1234567", SET010, 0, 100900400), bk)); // OK nevertheless
00373 
00374     ASSERT_TRUE(matchBufferContent(bufmgr.access(gen.bufmgr_key), "3456712345671234567"));
00375     ASSERT_EQ(0x3231, rcv.getLastTransferCrc());
00376 
00377     std::cout << "Interval: " << rcv.getInterval().toString() << std::endl;
00378 
00379     /*
00380      * Begins OK, gets a timeout, switches to another iface
00381      */
00382     CHECK_NOT_COMPLETE(rcv.addFrame(gen(1, "-------", SET100, 1, 103000500), bk)); // Begin
00383     CHECK_NOT_COMPLETE(rcv.addFrame(gen(1, "-------", SET001, 1, 105000500), bk)); // 2 sec later, timeout
00384     CHECK_NOT_COMPLETE(rcv.addFrame(gen(0, "-------", SET001, 1, 105000600), bk)); // Same TID, another iface - ignore
00385     CHECK_NOT_COMPLETE(rcv.addFrame(gen(0, "-------", SET001, 2, 105000700), bk)); // Not first frame - ignore
00386     CHECK_NOT_COMPLETE(rcv.addFrame(gen(0, "1234567", SET100, 2, 105000800), bk)); // First, another iface - restart
00387     CHECK_NOT_COMPLETE(rcv.addFrame(gen(1, "-------", SET010, 1, 105000600), bk)); // Old iface - ignore
00388     CHECK_NOT_COMPLETE(rcv.addFrame(gen(0, "1234567", SET001, 2, 105000900), bk)); // Continuing
00389     CHECK_COMPLETE(    rcv.addFrame(gen(0, "1234567", SET010, 2, 105000910), bk)); // Done
00390 
00391     ASSERT_TRUE(matchBufferContent(bufmgr.access(gen.bufmgr_key), "3456712345671234567"));
00392     ASSERT_EQ(0x3231, rcv.getLastTransferCrc());
00393 
00394     ASSERT_EQ(4, rcv.yieldErrorCount());
00395     ASSERT_EQ(0, rcv.yieldErrorCount());
00396 }
00397 
00398 
00399 TEST(TransferReceiver, UtcTransferTimestamping)
00400 {
00401     Context<32> context;
00402     RxFrameGenerator gen(789);
00403     uavcan::TransferReceiver& rcv = context.receiver;
00404     uavcan::TransferBufferManager& bufmgr = context.bufmgr;
00405     uavcan::TransferBufferAccessor bk(context.bufmgr, RxFrameGenerator::DEFAULT_KEY);
00406 
00407     /*
00408      * Zero UTC timestamp must be preserved
00409      */
00410     CHECK_NOT_COMPLETE(rcv.addFrame(gen(1, "1234567", SET100, 0, 1, 0), bk));
00411     CHECK_NOT_COMPLETE(rcv.addFrame(gen(1, "qwertyu", SET001, 0, 2, 0), bk));
00412     CHECK_COMPLETE(    rcv.addFrame(gen(1, "abcd",    SET010, 0, 3, 0), bk));
00413 
00414     ASSERT_TRUE(matchBufferContent(bufmgr.access(gen.bufmgr_key), "34567qwertyuabcd"));
00415     ASSERT_EQ(1, rcv.getLastTransferTimestampMonotonic().toUSec());
00416     ASSERT_EQ(0, rcv.getLastTransferTimestampUtc().toUSec());
00417 
00418     /*
00419      * Non-zero UTC timestamp
00420      */
00421     CHECK_NOT_COMPLETE(rcv.addFrame(gen(1, "1234567", SET100, 1, 4, 123), bk)); // This UTC is going to be preserved
00422     CHECK_NOT_COMPLETE(rcv.addFrame(gen(1, "qwertyu", SET001, 1, 5, 0), bk));   // Following are ignored
00423     CHECK_COMPLETE(    rcv.addFrame(gen(1, "abcd",    SET010, 1, 6, 42), bk));
00424 
00425     ASSERT_TRUE(matchBufferContent(bufmgr.access(gen.bufmgr_key), "34567qwertyuabcd"));
00426     ASSERT_EQ(4, rcv.getLastTransferTimestampMonotonic().toUSec());
00427     ASSERT_EQ(123, rcv.getLastTransferTimestampUtc().toUSec());
00428 
00429     /*
00430      * Single-frame transfers
00431      * iface_index, data, set, transfer_id, ts_monotonic
00432      */
00433     CHECK_SINGLE_FRAME(rcv.addFrame(gen(1, "abc", SET110, 2, 10, 100000000), bk)); // Exact value is irrelevant
00434     ASSERT_EQ(10, rcv.getLastTransferTimestampMonotonic().toUSec());
00435     ASSERT_EQ(100000000, rcv.getLastTransferTimestampUtc().toUSec());
00436 
00437     /*
00438      * Restart recovery
00439      */
00440     CHECK_NOT_COMPLETE(rcv.addFrame(gen(0, "1234567", SET100, 1, 100000000, 800000000), bk));
00441     CHECK_NOT_COMPLETE(rcv.addFrame(gen(0, "qwertyu", SET001, 1, 100000001, 300000000), bk));
00442     CHECK_COMPLETE(    rcv.addFrame(gen(0, "abcd",    SET010, 1, 100000002, 900000000), bk));
00443 
00444     ASSERT_TRUE(matchBufferContent(bufmgr.access(gen.bufmgr_key), "34567qwertyuabcd"));
00445     ASSERT_EQ(100000000, rcv.getLastTransferTimestampMonotonic().toUSec());
00446     ASSERT_EQ(800000000, rcv.getLastTransferTimestampUtc().toUSec());
00447 }
00448 
00449 
00450 TEST(TransferReceiver, HeaderParsing)
00451 {
00452     static const std::string SFT_PAYLOAD = "1234567";
00453 
00454     uavcan::TransferID tid;
00455 
00456     /*
00457      * Broadcast
00458      */
00459     {
00460         Context<32> context;
00461         RxFrameGenerator gen(123);
00462         uavcan::TransferReceiver& rcv = context.receiver;
00463         uavcan::TransferBufferManager& bufmgr = context.bufmgr;
00464 
00465         /*
00466          * MFT, message broadcasting
00467          */
00468         {
00469             gen.bufmgr_key =
00470                 uavcan::TransferBufferManagerKey(gen.bufmgr_key.getNodeID(), uavcan::TransferTypeMessageBroadcast);
00471             uavcan::TransferBufferAccessor bk1(context.bufmgr, gen.bufmgr_key);
00472 
00473             CHECK_NOT_COMPLETE(rcv.addFrame(gen(0, "1234567", SET100, tid.get(), 1), bk1));
00474             CHECK_COMPLETE(    rcv.addFrame(gen(0, "abcd",     SET011,  tid.get(), 2), bk1));
00475 
00476             ASSERT_TRUE(matchBufferContent(bufmgr.access(gen.bufmgr_key), "34567abcd"));
00477             ASSERT_EQ(0x3231, rcv.getLastTransferCrc());
00478 
00479             tid.increment();
00480             bk1.remove();
00481         }
00482 
00483         /*
00484          * SFT, message broadcasting
00485          */
00486         {
00487             gen.bufmgr_key =
00488                 uavcan::TransferBufferManagerKey(gen.bufmgr_key.getNodeID(), uavcan::TransferTypeMessageBroadcast);
00489             uavcan::TransferBufferAccessor bk(context.bufmgr, gen.bufmgr_key);
00490 
00491             const uavcan::RxFrame frame = gen(0, SFT_PAYLOAD, SET110, tid.get(), 1000);
00492 
00493             CHECK_SINGLE_FRAME(rcv.addFrame(frame, bk));
00494             ASSERT_EQ(0x0000, rcv.getLastTransferCrc());                                     // Default value - zero
00495 
00496             // All bytes are payload, zero overhead
00497             ASSERT_TRUE(std::equal(SFT_PAYLOAD.begin(), SFT_PAYLOAD.end(), frame.getPayloadPtr()));
00498 
00499             tid.increment();
00500         }
00501     }
00502 
00503     /*
00504      * Unicast
00505      */
00506     {
00507         Context<32> context;
00508         RxFrameGenerator gen(123);
00509         uavcan::TransferReceiver& rcv = context.receiver;
00510         uavcan::TransferBufferManager& bufmgr = context.bufmgr;
00511 
00512         static const uavcan::TransferType ADDRESSED_TRANSFER_TYPES[2] =
00513         {
00514             uavcan::TransferTypeServiceRequest,
00515             uavcan::TransferTypeServiceResponse
00516         };
00517 
00518         /*
00519          * MFT, service request/response
00520          */
00521         for (unsigned i = 0; i < (sizeof(ADDRESSED_TRANSFER_TYPES) / sizeof(ADDRESSED_TRANSFER_TYPES[0])); i++)
00522         {
00523             gen.bufmgr_key =
00524                 uavcan::TransferBufferManagerKey(gen.bufmgr_key.getNodeID(), ADDRESSED_TRANSFER_TYPES[i]);
00525             uavcan::TransferBufferAccessor bk2(context.bufmgr, gen.bufmgr_key);
00526 
00527             const uint64_t ts_monotonic = i + 10;
00528 
00529             CHECK_NOT_COMPLETE(rcv.addFrame(gen(0, "1234567", SET100, tid.get(), ts_monotonic), bk2));
00530             CHECK_COMPLETE(    rcv.addFrame(gen(0, "abcd",    SET011,  tid.get(), ts_monotonic), bk2));
00531 
00532             ASSERT_TRUE(matchBufferContent(bufmgr.access(gen.bufmgr_key), "34567abcd"));
00533             ASSERT_EQ(0x3231, rcv.getLastTransferCrc());
00534 
00535             tid.increment();
00536             bk2.remove();
00537         }
00538 
00539         /*
00540          * SFT, message unicast, service request/response
00541          */
00542         for (unsigned i = 0; i < int(sizeof(ADDRESSED_TRANSFER_TYPES) / sizeof(ADDRESSED_TRANSFER_TYPES[0])); i++)
00543         {
00544             gen.bufmgr_key =
00545                 uavcan::TransferBufferManagerKey(gen.bufmgr_key.getNodeID(), ADDRESSED_TRANSFER_TYPES[i]);
00546             uavcan::TransferBufferAccessor bk(context.bufmgr, gen.bufmgr_key);
00547 
00548             const uavcan::RxFrame frame = gen(0, SFT_PAYLOAD, SET110, tid.get(), i + 10000U);
00549 
00550             CHECK_SINGLE_FRAME(rcv.addFrame(frame, bk));
00551             ASSERT_EQ(0x0000, rcv.getLastTransferCrc());                                     // Default value - zero
00552 
00553             // First byte must be ignored
00554             ASSERT_TRUE(std::equal(SFT_PAYLOAD.begin(), SFT_PAYLOAD.end(), frame.getPayloadPtr()));
00555 
00556             tid.increment();
00557         }
00558     }
00559 
00560 
00561 }