libuav original

Dependents:   UAVCAN UAVCAN_Subscriber

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers transfer_listener.cpp Source File

transfer_listener.cpp

00001 /*
00002  * Copyright (C) 2014 Pavel Kirienko <pavel.kirienko@gmail.com>
00003  */
00004 
00005 #include <gtest/gtest.h>
00006 #include "transfer_test_helpers.hpp"
00007 #include "../clock.hpp"
00008 
00009 
00010 class TransferListenerEmulator : public IncomingTransferEmulatorBase
00011 {
00012     uavcan::TransferListener& target_;
00013     const uavcan::DataTypeDescriptor data_type_;
00014 
00015 public:
00016     TransferListenerEmulator(uavcan::TransferListener& target, const uavcan::DataTypeDescriptor& type,
00017                              uavcan::NodeID dst_node_id = 127)
00018         : IncomingTransferEmulatorBase(dst_node_id)
00019         , target_(target)
00020         , data_type_(type)
00021     { }
00022 
00023     void sendOneFrame(const uavcan::RxFrame& frame) { target_.handleFrame(frame); }
00024 
00025     Transfer makeTransfer(uavcan::TransferPriority priority, uavcan::TransferType transfer_type,
00026                           uint8_t source_node_id, const std::string& payload)
00027     {
00028         return IncomingTransferEmulatorBase::makeTransfer(priority, transfer_type, source_node_id, payload, data_type_);
00029     }
00030 };
00031 
00032 
00033 TEST(TransferListener, BasicMFT)
00034 {
00035     const uavcan::DataTypeDescriptor type(uavcan::DataTypeKindMessage, 123, uavcan::DataTypeSignature(123456789), "A");
00036 
00037     static const int NUM_POOL_BLOCKS = 100;
00038     uavcan::PoolAllocator<uavcan::MemPoolBlockSize * NUM_POOL_BLOCKS, uavcan::MemPoolBlockSize> pool;
00039 
00040     uavcan::TransferPerfCounter perf;
00041     TestListener subscriber(perf, type, 256, pool);
00042 
00043     /*
00044      * Test data
00045      */
00046     static const std::string DATA[] =
00047     {
00048         "Build a man a fire, and he'll be warm for a day. "
00049         "Set a man on fire, and he'll be warm for the rest of his life.",
00050 
00051         "123456789",
00052 
00053         "In the beginning there was nothing, which exploded.",
00054 
00055         "The USSR, which they'd begun to renovate and improve at about the time when Tatarsky decided to "
00056         "change his profession, improved so much that it ceased to exist",
00057 
00058         "BEWARE JET BLAST"
00059     };
00060 
00061     for (unsigned i = 0; i < sizeof(DATA) / sizeof(DATA[0]); i++)
00062     {
00063         std::cout << "Size of test data chunk " << i << ": " << DATA[i].length() << std::endl;
00064     }
00065 
00066     TransferListenerEmulator emulator(subscriber, type);
00067     const Transfer transfers[] =
00068     {
00069         emulator.makeTransfer(16, uavcan::TransferTypeMessageBroadcast, 1, DATA[0]),
00070         emulator.makeTransfer(16, uavcan::TransferTypeMessageBroadcast, 2, DATA[1]),   // Same NID
00071         emulator.makeTransfer(16, uavcan::TransferTypeMessageBroadcast, 3, DATA[2]),
00072         emulator.makeTransfer(16, uavcan::TransferTypeServiceRequest,   4, DATA[3]),
00073         emulator.makeTransfer(16, uavcan::TransferTypeServiceResponse,  5, DATA[4]),
00074     };
00075 
00076     /*
00077      * Sending concurrently
00078      * Expected reception order: 1, 4, 2, 0, 3
00079      */
00080     emulator.send(transfers);
00081 
00082     ASSERT_TRUE(subscriber.matchAndPop(transfers[1]));
00083     ASSERT_TRUE(subscriber.matchAndPop(transfers[4]));
00084     ASSERT_TRUE(subscriber.matchAndPop(transfers[2]));
00085     ASSERT_TRUE(subscriber.matchAndPop(transfers[0]));
00086     ASSERT_TRUE(subscriber.matchAndPop(transfers[3]));
00087 
00088     ASSERT_TRUE(subscriber.isEmpty());
00089 }
00090 
00091 
00092 TEST(TransferListener, CrcFailure)
00093 {
00094     const uavcan::DataTypeDescriptor type(uavcan::DataTypeKindMessage, 123, uavcan::DataTypeSignature(123456789), "A");
00095 
00096     static const int NUM_POOL_BLOCKS = 100;
00097     uavcan::PoolAllocator<uavcan::MemPoolBlockSize * NUM_POOL_BLOCKS, uavcan::MemPoolBlockSize> poolmgr;
00098     uavcan::TransferPerfCounter perf;
00099     TestListener subscriber(perf, type, 256, poolmgr);  // Static buffer only, 2 entries
00100 
00101     /*
00102      * Generating transfers with damaged payload (CRC is not valid)
00103      */
00104     TransferListenerEmulator emulator(subscriber, type);
00105     const Transfer tr_mft = emulator.makeTransfer(16, uavcan::TransferTypeMessageBroadcast, 42, "123456789abcdefghik");
00106     const Transfer tr_sft = emulator.makeTransfer(16, uavcan::TransferTypeMessageBroadcast, 11, "abcd");
00107 
00108     std::vector<uavcan::RxFrame> ser_mft = serializeTransfer(tr_mft);
00109     std::vector<uavcan::RxFrame> ser_sft = serializeTransfer(tr_sft);
00110 
00111     ASSERT_TRUE(ser_mft.size() > 1);
00112     ASSERT_TRUE(ser_sft.size() == 1);
00113 
00114     const_cast<uint8_t*>(ser_mft[1].getPayloadPtr())[1] = uint8_t(~ser_mft[1].getPayloadPtr()[1]); // CRC invalid now
00115     const_cast<uint8_t*>(ser_sft[0].getPayloadPtr())[2] = uint8_t(~ser_sft[0].getPayloadPtr()[2]);  // no CRC here
00116 
00117     /*
00118      * Sending and making sure that MFT was not received, but SFT was.
00119      */
00120     std::vector<std::vector<uavcan::RxFrame> > sers;
00121     sers.push_back(ser_mft);
00122     sers.push_back(ser_sft);
00123     sers.push_back(ser_mft);  // Ignored
00124     sers.push_back(ser_sft);  // Ignored
00125 
00126     emulator.send(sers);
00127 
00128     Transfer tr_sft_damaged = tr_sft;
00129     tr_sft_damaged.payload[2] = char(~tr_sft.payload[2]);    // Damaging the data similarly, so that it can be matched
00130 
00131     ASSERT_TRUE(subscriber.matchAndPop(tr_sft_damaged));
00132     ASSERT_TRUE(subscriber.isEmpty());
00133 }
00134 
00135 
00136 TEST(TransferListener, BasicSFT)
00137 {
00138     const uavcan::DataTypeDescriptor type(uavcan::DataTypeKindMessage, 123, uavcan::DataTypeSignature(123456789), "A");
00139 
00140     static const int NUM_POOL_BLOCKS = 100;
00141     uavcan::PoolAllocator<uavcan::MemPoolBlockSize * NUM_POOL_BLOCKS, uavcan::MemPoolBlockSize> poolmgr;
00142     uavcan::TransferPerfCounter perf;
00143     TestListener subscriber(perf, type, 0, poolmgr); // Max buf size is 0, i.e. SFT-only
00144 
00145     TransferListenerEmulator emulator(subscriber, type);
00146     const Transfer transfers[] =
00147     {
00148         emulator.makeTransfer(16, uavcan::TransferTypeMessageBroadcast, 1, "123"),
00149         emulator.makeTransfer(16, uavcan::TransferTypeServiceRequest,   1, "456"),          // Same NID
00150         emulator.makeTransfer(16, uavcan::TransferTypeServiceRequest,   2, ""),
00151         emulator.makeTransfer(16, uavcan::TransferTypeServiceRequest,   3, "abc"),
00152         emulator.makeTransfer(16, uavcan::TransferTypeServiceResponse,  4, ""),
00153         emulator.makeTransfer(16, uavcan::TransferTypeServiceRequest,   2, "foo"),          // Same as 2, not ignored
00154         emulator.makeTransfer(16, uavcan::TransferTypeServiceRequest,   2, "123456789abc"), // Same as 2, not SFT - ignore
00155         emulator.makeTransfer(16, uavcan::TransferTypeServiceRequest,   2, "bar"),          // Same as 2, not ignored
00156     };
00157 
00158     emulator.send(transfers);
00159 
00160     ASSERT_TRUE(subscriber.matchAndPop(transfers[0]));
00161     ASSERT_TRUE(subscriber.matchAndPop(transfers[1]));
00162     ASSERT_TRUE(subscriber.matchAndPop(transfers[2]));
00163     ASSERT_TRUE(subscriber.matchAndPop(transfers[3]));
00164     ASSERT_TRUE(subscriber.matchAndPop(transfers[4]));
00165     ASSERT_TRUE(subscriber.matchAndPop(transfers[5]));
00166     ASSERT_TRUE(subscriber.matchAndPop(transfers[7]));
00167 
00168     ASSERT_TRUE(subscriber.isEmpty());
00169 }
00170 
00171 
00172 TEST(TransferListener, Cleanup)
00173 {
00174     const uavcan::DataTypeDescriptor type(uavcan::DataTypeKindMessage, 123, uavcan::DataTypeSignature(123456789), "A");
00175 
00176     static const int NUM_POOL_BLOCKS = 100;
00177     uavcan::PoolAllocator<uavcan::MemPoolBlockSize * NUM_POOL_BLOCKS, uavcan::MemPoolBlockSize> poolmgr;
00178     uavcan::TransferPerfCounter perf;
00179     TestListener subscriber(perf, type, 256, poolmgr);
00180 
00181     /*
00182      * Generating transfers
00183      */
00184     TransferListenerEmulator emulator(subscriber, type);
00185     const Transfer tr_mft = emulator.makeTransfer(16, uavcan::TransferTypeMessageBroadcast, 42, "123456789abcdefghik");
00186     const Transfer tr_sft = emulator.makeTransfer(16, uavcan::TransferTypeServiceResponse, 11, "abcd");
00187 
00188     const std::vector<uavcan::RxFrame> ser_mft = serializeTransfer(tr_mft);
00189     const std::vector<uavcan::RxFrame> ser_sft = serializeTransfer(tr_sft);
00190 
00191     ASSERT_TRUE(ser_mft.size() > 1);
00192     ASSERT_TRUE(ser_sft.size() == 1);
00193 
00194     const std::vector<uavcan::RxFrame> ser_mft_begin(ser_mft.begin(), ser_mft.begin() + 1);
00195 
00196     /*
00197      * Sending the first part and SFT
00198      */
00199     std::vector<std::vector<uavcan::RxFrame> > sers;
00200     sers.push_back(ser_mft_begin);      // Only the first part
00201     sers.push_back(ser_sft);
00202 
00203     emulator.send(sers);
00204 
00205     ASSERT_TRUE(subscriber.matchAndPop(tr_sft));
00206     ASSERT_TRUE(subscriber.isEmpty());
00207 
00208     /*
00209      * Cleanup with huge timestamp value will remove all entries
00210      */
00211     static_cast<uavcan::TransferListener&>(subscriber).cleanup(tsMono(100000000));
00212 
00213     /*
00214      * Sending the same transfers again - they will be accepted since registres were cleared
00215      */
00216     sers.clear();
00217     sers.push_back(ser_mft);   // Complete transfer
00218     sers.push_back(ser_sft);
00219 
00220     emulator.send(sers);
00221 
00222     ASSERT_TRUE(subscriber.matchAndPop(tr_sft));
00223     ASSERT_TRUE(subscriber.matchAndPop(tr_mft));
00224     ASSERT_TRUE(subscriber.isEmpty());
00225 }
00226 
00227 
00228 TEST(TransferListener, AnonymousTransfers)
00229 {
00230     const uavcan::DataTypeDescriptor type(uavcan::DataTypeKindMessage, 123, uavcan::DataTypeSignature(123456789), "A");
00231 
00232     static const int NUM_POOL_BLOCKS = 100;
00233     uavcan::PoolAllocator<uavcan::MemPoolBlockSize * NUM_POOL_BLOCKS, uavcan::MemPoolBlockSize> poolmgr;
00234     uavcan::TransferPerfCounter perf;
00235     TestListener subscriber(perf, type, 0, poolmgr);
00236 
00237     TransferListenerEmulator emulator(subscriber, type);
00238     const Transfer transfers[] =
00239     {
00240         emulator.makeTransfer(16, uavcan::TransferTypeServiceRequest,   0, "1234567"),  // Invalid - not broadcast
00241         emulator.makeTransfer(16, uavcan::TransferTypeMessageBroadcast, 0, "1234567"),  // Valid
00242         emulator.makeTransfer(16, uavcan::TransferTypeMessageBroadcast, 0, "12345678"), // Invalid - not SFT
00243         emulator.makeTransfer(16, uavcan::TransferTypeMessageBroadcast, 0, "")          // Valid
00244     };
00245 
00246     emulator.send(transfers);
00247 
00248     // Nothing will be received, because anonymous transfers are disabled by default
00249     ASSERT_TRUE(subscriber.isEmpty());
00250 
00251     subscriber.allowAnonymousTransfers();
00252 
00253     // Re-send everything again
00254     emulator.send(transfers);
00255 
00256     // Now the anonymous transfers are enabled
00257     ASSERT_TRUE(subscriber.matchAndPop(transfers[1]));    // Only SFT broadcast will be accepted
00258     ASSERT_TRUE(subscriber.matchAndPop(transfers[3]));
00259 
00260     ASSERT_TRUE(subscriber.isEmpty());
00261 }
00262 
00263 TEST(TransferListener, Sizes)
00264 {
00265     using namespace uavcan;
00266 
00267     std::cout << "sizeof(TransferListener): " << sizeof(TransferListener) << std::endl;
00268 }