Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: UAVCAN UAVCAN_Subscriber
transfer_buffer.cpp
00001 /* 00002 * Copyright (C) 2014 Pavel Kirienko <pavel.kirienko@gmail.com> 00003 */ 00004 00005 #if __GNUC__ 00006 // We need auto_ptr for compatibility reasons 00007 # pragma GCC diagnostic ignored "-Wdeprecated-declarations" 00008 # pragma GCC diagnostic ignored "-Wzero-as-null-pointer-constant" 00009 #endif 00010 00011 #include <algorithm> 00012 #include <gtest/gtest.h> 00013 #include <memory> 00014 #include <uavcan/transport/transfer_buffer.hpp> 00015 00016 static const std::string TEST_DATA = 00017 "It was like this: I asked myself one day this question - what if Napoleon, for instance, had happened to be in my " 00018 "place, and if he had not had Toulon nor Egypt nor the passage of Mont Blanc to begin his career with, but " 00019 "instead of all those picturesque and monumental things, there had simply been some ridiculous old hag, a " 00020 "pawnbroker, who had to be murdered too to get money from her trunk (for his career, you understand). " 00021 "Well, would he have brought himself to that if there had been no other means?"; 00022 00023 template <typename T, unsigned Size> 00024 static bool allEqual(const T (&a)[Size]) 00025 { 00026 unsigned n = Size; 00027 while ((--n > 0) && (a[n] == a[0])) { } 00028 return n == 0; 00029 } 00030 00031 template <typename T, unsigned Size, typename R> 00032 static void fill(T (&a)[Size], R value) 00033 { 00034 for (unsigned i = 0; i < Size; i++) 00035 { 00036 a[i] = T(value); 00037 } 00038 } 00039 00040 static bool matchAgainst(const std::string& data, const uavcan::ITransferBuffer& tbb, 00041 unsigned offset = 0, int len = -1) 00042 { 00043 uint8_t local_buffer[1024]; 00044 fill(local_buffer, 0); 00045 assert((len < 0) || (sizeof(local_buffer) >= static_cast<unsigned>(len))); 00046 00047 if (len < 0) 00048 { 00049 const int res = tbb.read(offset, local_buffer, sizeof(local_buffer)); 00050 if (res < 0) 00051 { 00052 std::cout << "matchAgainst(): res " << res << std::endl; 00053 return false; 00054 } 00055 len = res; 00056 } 00057 else 00058 { 00059 const int res = tbb.read(offset, local_buffer, unsigned(len)); 00060 if (res != len) 00061 { 00062 std::cout << "matchAgainst(): res " << res << " expected " << len << std::endl; 00063 return false; 00064 } 00065 } 00066 const bool equals = std::equal(local_buffer, local_buffer + len, data.begin() + offset); 00067 if (!equals) 00068 { 00069 std::cout << "local_buffer:\n\t" << local_buffer << std::endl; 00070 std::cout << "test_data:\n\t" << std::string(data.begin() + offset, data.begin() + offset + len) << std::endl; 00071 } 00072 return equals; 00073 } 00074 00075 static bool matchAgainstTestData(const uavcan::ITransferBuffer& tbb, unsigned offset, int len = -1) 00076 { 00077 return matchAgainst(TEST_DATA, tbb, offset, len); 00078 } 00079 00080 TEST(TransferBuffer, TestDataValidation) 00081 { 00082 ASSERT_LE(4, TEST_DATA.length() / uavcan::MemPoolBlockSize); 00083 uint8_t local_buffer[50]; 00084 std::copy(TEST_DATA.begin(), TEST_DATA.begin() + sizeof(local_buffer), local_buffer); 00085 ASSERT_FALSE(allEqual(local_buffer)); 00086 } 00087 00088 static const int TEST_BUFFER_SIZE = 200; 00089 00090 TEST(StaticTransferBuffer, Basic) 00091 { 00092 using uavcan::StaticTransferBuffer; 00093 StaticTransferBuffer<TEST_BUFFER_SIZE> buf; 00094 00095 uint8_t local_buffer[TEST_BUFFER_SIZE * 2]; 00096 const uint8_t* const test_data_ptr = reinterpret_cast<const uint8_t*>(TEST_DATA.c_str()); 00097 00098 // Empty reads 00099 fill(local_buffer, 0xA5); 00100 ASSERT_EQ(0, buf.read(0, local_buffer, 999)); 00101 ASSERT_EQ(0, buf.read(0, local_buffer, 0)); 00102 ASSERT_EQ(0, buf.read(999, local_buffer, 0)); 00103 ASSERT_TRUE(allEqual(local_buffer)); 00104 00105 // Bulk write 00106 ASSERT_EQ(TEST_BUFFER_SIZE, buf.write(0, test_data_ptr, unsigned(TEST_DATA.length()))); 00107 ASSERT_TRUE(matchAgainstTestData(buf, 0)); 00108 ASSERT_TRUE(matchAgainstTestData(buf, TEST_BUFFER_SIZE)); 00109 ASSERT_TRUE(matchAgainstTestData(buf, TEST_BUFFER_SIZE / 2)); 00110 ASSERT_TRUE(matchAgainstTestData(buf, TEST_BUFFER_SIZE / 2, TEST_BUFFER_SIZE / 4)); 00111 ASSERT_TRUE(matchAgainstTestData(buf, TEST_BUFFER_SIZE / 4, TEST_BUFFER_SIZE / 2)); 00112 ASSERT_TRUE(matchAgainstTestData(buf, 0, TEST_BUFFER_SIZE / 4)); 00113 00114 // Reset 00115 fill(local_buffer, 0xA5); 00116 buf.reset(); 00117 ASSERT_EQ(0, buf.read(0, local_buffer, 0)); 00118 ASSERT_EQ(0, buf.read(0, local_buffer, 999)); 00119 ASSERT_TRUE(allEqual(local_buffer)); 00120 00121 // Random write 00122 ASSERT_EQ(21, buf.write(12, test_data_ptr + 12, 21)); 00123 ASSERT_TRUE(matchAgainstTestData(buf, 12, 21)); 00124 00125 ASSERT_EQ(12, buf.write(0, test_data_ptr, 12)); 00126 ASSERT_TRUE(matchAgainstTestData(buf, 0)); 00127 00128 ASSERT_EQ(0, buf.write(21, test_data_ptr + 21, 0)); 00129 ASSERT_EQ(TEST_BUFFER_SIZE - 21, buf.write(21, test_data_ptr + 21, 999)); 00130 ASSERT_TRUE(matchAgainstTestData(buf, 21, TEST_BUFFER_SIZE - 21)); 00131 ASSERT_TRUE(matchAgainstTestData(buf, 0)); 00132 } 00133 00134 00135 TEST(TransferBufferManagerEntry, Basic) 00136 { 00137 using uavcan::TransferBufferManagerEntry; 00138 00139 static const int MAX_SIZE = TEST_BUFFER_SIZE; 00140 static const int POOL_BLOCKS = 8; 00141 uavcan::PoolAllocator<uavcan::MemPoolBlockSize * POOL_BLOCKS, uavcan::MemPoolBlockSize> pool; 00142 00143 TransferBufferManagerEntry buf(pool, MAX_SIZE); 00144 00145 uint8_t local_buffer[TEST_BUFFER_SIZE * 2]; 00146 const uint8_t* const test_data_ptr = reinterpret_cast<const uint8_t*>(TEST_DATA.c_str()); 00147 00148 // Empty reads 00149 fill(local_buffer, 0xA5); 00150 ASSERT_EQ(0, buf.read(0, local_buffer, 999)); 00151 ASSERT_EQ(0, buf.read(0, local_buffer, 0)); 00152 ASSERT_EQ(0, buf.read(999, local_buffer, 0)); 00153 ASSERT_TRUE(allEqual(local_buffer)); 00154 00155 // Bulk write 00156 ASSERT_EQ(MAX_SIZE, buf.write(0, test_data_ptr, unsigned(TEST_DATA.length()))); 00157 00158 ASSERT_LT(0, pool.getNumUsedBlocks()); // Making sure some memory was used 00159 00160 ASSERT_TRUE(matchAgainstTestData(buf, 0)); 00161 ASSERT_TRUE(matchAgainstTestData(buf, TEST_BUFFER_SIZE)); 00162 ASSERT_TRUE(matchAgainstTestData(buf, TEST_BUFFER_SIZE / 2)); 00163 ASSERT_TRUE(matchAgainstTestData(buf, TEST_BUFFER_SIZE / 2, TEST_BUFFER_SIZE / 4)); 00164 ASSERT_TRUE(matchAgainstTestData(buf, TEST_BUFFER_SIZE / 4, TEST_BUFFER_SIZE / 2)); 00165 ASSERT_TRUE(matchAgainstTestData(buf, 0, TEST_BUFFER_SIZE / 4)); 00166 00167 // Reset 00168 fill(local_buffer, 0xA5); 00169 buf.reset(); 00170 ASSERT_EQ(0, buf.read(0, local_buffer, 0)); 00171 ASSERT_EQ(0, buf.read(0, local_buffer, 999)); 00172 ASSERT_TRUE(allEqual(local_buffer)); 00173 ASSERT_EQ(0, pool.getNumUsedBlocks()); 00174 00175 // Random write 00176 ASSERT_EQ(21, buf.write(12, test_data_ptr + 12, 21)); 00177 ASSERT_TRUE(matchAgainstTestData(buf, 12, 21)); 00178 00179 ASSERT_EQ(60, buf.write(TEST_BUFFER_SIZE - 60, test_data_ptr + TEST_BUFFER_SIZE - 60, 60)); 00180 ASSERT_TRUE(matchAgainstTestData(buf, TEST_BUFFER_SIZE - 60)); 00181 00182 // Now we have two empty regions: empty-data-empty-data 00183 00184 ASSERT_EQ(0, buf.write(0, test_data_ptr, 0)); 00185 ASSERT_EQ(TEST_BUFFER_SIZE - 21, buf.write(21, test_data_ptr + 21, TEST_BUFFER_SIZE - 21)); 00186 ASSERT_TRUE(matchAgainstTestData(buf, 21, TEST_BUFFER_SIZE - 21)); 00187 00188 // Now: empty-data-data-data 00189 00190 ASSERT_EQ(21, buf.write(0, test_data_ptr, 21)); 00191 ASSERT_TRUE(matchAgainstTestData(buf, 0)); 00192 00193 // Destroying the object; memory should be released 00194 ASSERT_LT(0, pool.getNumUsedBlocks()); 00195 buf.~TransferBufferManagerEntry(); 00196 ASSERT_EQ(0, pool.getNumUsedBlocks()); 00197 } 00198 00199 00200 static const std::string MGR_TEST_DATA[4] = 00201 { 00202 "I thought you would cry out again \'don\'t speak of it, leave off.\'\" Raskolnikov gave a laugh, but rather a " 00203 "forced one. \"What, silence again?\" he asked a minute later. \"We must talk about something, you know. ", 00204 00205 "It would be interesting for me to know how you would decide a certain \'problem\' as Lebeziatnikov would say.\" " 00206 "(He was beginning to lose the thread.) \"No, really, I am serious. Imagine, Sonia, that you had known all ", 00207 00208 "Luzhin\'s intentions beforehand. Known, that is, for a fact, that they would be the ruin of Katerina Ivanovna " 00209 "and the children and yourself thrown in--since you don\'t count yourself for anything--Polenka too... for ", 00210 00211 "she\'ll go the same way. Well, if suddenly it all depended on your decision whether he or they should go on " 00212 "living, that is whether Luzhin should go on living and doing wicked things, or Katerina Ivanovna should die? " 00213 "How would you decide which of them was to die? I ask you?" 00214 }; 00215 00216 static const int MGR_MAX_BUFFER_SIZE = 100; 00217 00218 TEST(TransferBufferManager, TestDataValidation) 00219 { 00220 for (unsigned i = 0; i < sizeof(MGR_TEST_DATA) / sizeof(MGR_TEST_DATA[0]); i++) 00221 { 00222 ASSERT_LT(MGR_MAX_BUFFER_SIZE, MGR_TEST_DATA[i].length()); 00223 } 00224 } 00225 00226 00227 static int fillTestData(const std::string& data, uavcan::ITransferBuffer* tbb) 00228 { 00229 return tbb->write(0, reinterpret_cast<const uint8_t*>(data.c_str()), unsigned(data.length())); 00230 } 00231 00232 TEST(TransferBufferManager, Basic) 00233 { 00234 using uavcan::TransferBufferManager; 00235 using uavcan::TransferBufferManagerKey; 00236 using uavcan::ITransferBuffer; 00237 00238 static const int POOL_BLOCKS = 100; 00239 uavcan::PoolAllocator<uavcan::MemPoolBlockSize * POOL_BLOCKS, uavcan::MemPoolBlockSize> pool; 00240 00241 std::auto_ptr<TransferBufferManager> mgr(new TransferBufferManager(MGR_MAX_BUFFER_SIZE, pool)); 00242 00243 // Empty 00244 ASSERT_FALSE(mgr->access(TransferBufferManagerKey(0, uavcan::TransferTypeMessageBroadcast))); 00245 ASSERT_FALSE(mgr->access(TransferBufferManagerKey(127, uavcan::TransferTypeServiceRequest))); 00246 00247 ITransferBuffer* tbb = UAVCAN_NULLPTR; 00248 00249 const TransferBufferManagerKey keys[5] = 00250 { 00251 TransferBufferManagerKey(0, uavcan::TransferTypeServiceRequest), 00252 TransferBufferManagerKey(1, uavcan::TransferTypeMessageBroadcast), 00253 TransferBufferManagerKey(2, uavcan::TransferTypeServiceRequest), 00254 TransferBufferManagerKey(127, uavcan::TransferTypeServiceResponse), 00255 TransferBufferManagerKey(64, uavcan::TransferTypeMessageBroadcast) 00256 }; 00257 00258 ASSERT_TRUE((tbb = mgr->create(keys[0]))); 00259 ASSERT_EQ(MGR_MAX_BUFFER_SIZE, fillTestData(MGR_TEST_DATA[0], tbb)); 00260 ASSERT_EQ(1, mgr->getNumBuffers()); 00261 00262 ASSERT_TRUE((tbb = mgr->create(keys[1]))); 00263 ASSERT_EQ(MGR_MAX_BUFFER_SIZE, fillTestData(MGR_TEST_DATA[1], tbb)); 00264 ASSERT_EQ(2, mgr->getNumBuffers()); 00265 ASSERT_LT(2, pool.getNumUsedBlocks()); 00266 00267 ASSERT_TRUE((tbb = mgr->create(keys[2]))); 00268 ASSERT_EQ(MGR_MAX_BUFFER_SIZE, fillTestData(MGR_TEST_DATA[2], tbb)); 00269 ASSERT_EQ(3, mgr->getNumBuffers()); 00270 00271 std::cout << "TransferBufferManager - Basic: Pool usage: " << pool.getNumUsedBlocks() << std::endl; 00272 00273 ASSERT_TRUE((tbb = mgr->create(keys[3]))); 00274 00275 ASSERT_LT(0, fillTestData(MGR_TEST_DATA[3], tbb)); 00276 ASSERT_EQ(4, mgr->getNumBuffers()); 00277 00278 // Making sure all buffers contain proper data 00279 ASSERT_TRUE((tbb = mgr->access(keys[0]))); 00280 ASSERT_TRUE(matchAgainst(MGR_TEST_DATA[0], *tbb)); 00281 00282 ASSERT_TRUE((tbb = mgr->access(keys[1]))); 00283 ASSERT_TRUE(matchAgainst(MGR_TEST_DATA[1], *tbb)); 00284 00285 ASSERT_TRUE((tbb = mgr->access(keys[2]))); 00286 ASSERT_TRUE(matchAgainst(MGR_TEST_DATA[2], *tbb)); 00287 00288 ASSERT_TRUE((tbb = mgr->access(keys[3]))); 00289 ASSERT_TRUE(matchAgainst(MGR_TEST_DATA[3], *tbb)); 00290 00291 mgr->remove(keys[1]); 00292 ASSERT_FALSE(mgr->access(keys[1])); 00293 ASSERT_EQ(3, mgr->getNumBuffers()); 00294 ASSERT_LT(0, pool.getNumFreeBlocks()); 00295 00296 mgr->remove(keys[0]); 00297 ASSERT_FALSE(mgr->access(keys[0])); 00298 ASSERT_EQ(2, mgr->getNumBuffers()); 00299 00300 // At this time we have the following NodeID: 2, 127 00301 ASSERT_TRUE((tbb = mgr->access(keys[2]))); 00302 ASSERT_TRUE(matchAgainst(MGR_TEST_DATA[2], *tbb)); 00303 00304 ASSERT_TRUE((tbb = mgr->access(keys[3]))); 00305 ASSERT_TRUE(matchAgainst(MGR_TEST_DATA[3], *tbb)); 00306 00307 // These were deleted: 0, 1; 3 is still there 00308 ASSERT_FALSE(mgr->access(keys[1])); 00309 ASSERT_FALSE(mgr->access(keys[0])); 00310 ASSERT_TRUE(mgr->access(keys[3])); 00311 00312 // Filling the memory again in order to check the destruction below 00313 ASSERT_TRUE((tbb = mgr->create(keys[1]))); 00314 ASSERT_LT(0, fillTestData(MGR_TEST_DATA[1], tbb)); 00315 00316 // Deleting the object; all memory must be freed 00317 ASSERT_NE(0, pool.getNumUsedBlocks()); 00318 mgr.reset(); 00319 ASSERT_EQ(0, pool.getNumUsedBlocks()); 00320 }
Generated on Tue Jul 12 2022 17:17:35 by
1.7.2