Prashanth Swaminathan | b210590 | 2015-08-20 14:28:54 -0700 | [diff] [blame] | 1 | /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ |
| 2 | /** |
Junxiao Shi | c1264c8 | 2016-07-14 15:04:07 +0000 | [diff] [blame] | 3 | * Copyright (c) 2014-2016, Regents of the University of California |
Prashanth Swaminathan | b210590 | 2015-08-20 14:28:54 -0700 | [diff] [blame] | 4 | * |
| 5 | * This file is part of ndn-group-encrypt (Group-based Encryption Protocol for NDN). |
| 6 | * See AUTHORS.md for complete list of ndn-group-encrypt authors and contributors. |
| 7 | * |
| 8 | * ndn-group-encrypt is free software: you can redistribute it and/or modify it under the terms |
| 9 | * of the GNU General Public License as published by the Free Software Foundation, |
| 10 | * either version 3 of the License, or (at your option) any later version. |
| 11 | * |
| 12 | * ndn-group-encrypt is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; |
| 13 | * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR |
| 14 | * PURPOSE. See the GNU General Public License for more details. |
| 15 | * |
| 16 | * You should have received a copy of the GNU General Public License along with |
| 17 | * ndn-group-encrypt, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>. |
| 18 | */ |
| 19 | |
| 20 | #include "producer.hpp" |
| 21 | #include "algo/encryptor.hpp" |
| 22 | #include "algo/rsa.hpp" |
| 23 | #include "algo/aes.hpp" |
| 24 | #include "encrypted-content.hpp" |
| 25 | #include "unit-test-time-fixture.hpp" |
| 26 | #include "random-number-generator.hpp" |
| 27 | |
| 28 | #include <ndn-cxx/util/dummy-client-face.hpp> |
| 29 | |
| 30 | #include "boost-test.hpp" |
| 31 | #include <boost/asio.hpp> |
| 32 | #include <boost/filesystem.hpp> |
| 33 | |
| 34 | namespace ndn { |
| 35 | namespace gep { |
| 36 | namespace tests { |
| 37 | |
| 38 | static const uint8_t DATA_CONTEN[] = { |
| 39 | 0xcb, 0xe5, 0x6a, 0x80, 0x41, 0x24, 0x58, 0x23, |
| 40 | 0x84, 0x14, 0x15, 0x61, 0x80, 0xb9, 0x5e, 0xbd, |
| 41 | 0xce, 0x32, 0xb4, 0xbe, 0xbc, 0x91, 0x31, 0xd6, |
| 42 | 0x19, 0x00, 0x80, 0x8b, 0xfa, 0x00, 0x05, 0x9c |
| 43 | }; |
| 44 | |
| 45 | class ProducerFixture : public UnitTestTimeFixture |
| 46 | { |
| 47 | public: |
| 48 | ProducerFixture() |
| 49 | : tmpPath(boost::filesystem::path(TMP_TESTS_PATH)) |
Junxiao Shi | c1264c8 | 2016-07-14 15:04:07 +0000 | [diff] [blame] | 50 | , face1(io, keyChain, {true, true}) |
| 51 | , face2(io, keyChain, {true, true}) |
Prashanth Swaminathan | b210590 | 2015-08-20 14:28:54 -0700 | [diff] [blame] | 52 | , readInterestOffset1(0) |
| 53 | , readDataOffset1(0) |
| 54 | , readInterestOffset2(0) |
| 55 | , readDataOffset2(0) |
| 56 | { |
| 57 | boost::filesystem::create_directories(tmpPath); |
| 58 | } |
| 59 | |
| 60 | ~ProducerFixture() |
| 61 | { |
| 62 | boost::filesystem::remove_all(tmpPath); |
| 63 | } |
| 64 | |
| 65 | void |
| 66 | createEncryptionKey(Name eKeyName, const Name& timeMarker) |
| 67 | { |
| 68 | RandomNumberGenerator rng; |
| 69 | RsaKeyParams params; |
| 70 | eKeyName.append(timeMarker); |
| 71 | |
| 72 | Buffer dKeyBuf = algo::Rsa::generateKey(rng, params).getKeyBits(); |
| 73 | Buffer eKeyBuf = algo::Rsa::deriveEncryptKey(dKeyBuf).getKeyBits(); |
| 74 | decryptionKeys[eKeyName] = dKeyBuf; |
| 75 | |
| 76 | shared_ptr<Data> keyData = make_shared<Data>(eKeyName); |
| 77 | keyData->setContent(eKeyBuf.buf(), eKeyBuf.size()); |
| 78 | keyChain.sign(*keyData); |
| 79 | encryptionKeys[eKeyName] = keyData; |
| 80 | } |
| 81 | |
| 82 | bool |
| 83 | passPacket() |
| 84 | { |
| 85 | bool hasPassed = false; |
| 86 | |
Junxiao Shi | c1264c8 | 2016-07-14 15:04:07 +0000 | [diff] [blame] | 87 | checkFace(face1.sentInterests, readInterestOffset1, face2, hasPassed); |
| 88 | checkFace(face1.sentData, readDataOffset1, face2, hasPassed); |
| 89 | checkFace(face2.sentInterests, readInterestOffset2, face1, hasPassed); |
| 90 | checkFace(face2.sentData, readDataOffset2, face1, hasPassed); |
Prashanth Swaminathan | b210590 | 2015-08-20 14:28:54 -0700 | [diff] [blame] | 91 | |
| 92 | return hasPassed; |
| 93 | } |
| 94 | |
| 95 | template<typename Packet> |
| 96 | void |
| 97 | checkFace(std::vector<Packet>& receivedPackets, |
| 98 | size_t& readPacketOffset, |
| 99 | util::DummyClientFace& receiver, |
| 100 | bool& hasPassed) |
| 101 | { |
| 102 | while (receivedPackets.size() > readPacketOffset) { |
| 103 | receiver.receive(receivedPackets[readPacketOffset]); |
| 104 | readPacketOffset++; |
| 105 | hasPassed = true; |
| 106 | } |
| 107 | } |
| 108 | |
| 109 | public: |
| 110 | boost::filesystem::path tmpPath; |
| 111 | |
Junxiao Shi | c1264c8 | 2016-07-14 15:04:07 +0000 | [diff] [blame] | 112 | util::DummyClientFace face1; |
| 113 | util::DummyClientFace face2; |
Prashanth Swaminathan | b210590 | 2015-08-20 14:28:54 -0700 | [diff] [blame] | 114 | |
| 115 | size_t readInterestOffset1; |
| 116 | size_t readDataOffset1; |
| 117 | size_t readInterestOffset2; |
| 118 | size_t readDataOffset2; |
| 119 | |
| 120 | KeyChain keyChain; |
| 121 | |
| 122 | std::unordered_map<Name, Buffer> decryptionKeys; |
| 123 | std::unordered_map<Name, shared_ptr<Data>> encryptionKeys; |
| 124 | }; |
| 125 | |
| 126 | BOOST_FIXTURE_TEST_SUITE(TestProducer, ProducerFixture) |
| 127 | |
| 128 | BOOST_AUTO_TEST_CASE(ContentKeyRequest) |
| 129 | { |
| 130 | std::string dbDir = tmpPath.c_str(); |
| 131 | dbDir += "/test.db"; |
| 132 | |
| 133 | Name prefix("/prefix"); |
| 134 | Name suffix("/a/b/c"); |
| 135 | Name expectedInterest = prefix; |
| 136 | expectedInterest.append(NAME_COMPONENT_READ); |
| 137 | expectedInterest.append(suffix); |
| 138 | expectedInterest.append(NAME_COMPONENT_E_KEY); |
| 139 | |
| 140 | Name cKeyName = prefix; |
| 141 | cKeyName.append(NAME_COMPONENT_SAMPLE); |
| 142 | cKeyName.append(suffix); |
| 143 | cKeyName.append(NAME_COMPONENT_C_KEY); |
| 144 | |
| 145 | Name timeMarker("20150101T100000/20150101T120000"); |
| 146 | time::system_clock::TimePoint testTime1 = time::fromIsoString("20150101T100001"); |
| 147 | time::system_clock::TimePoint testTime2 = time::fromIsoString("20150101T110001"); |
| 148 | name::Component testTimeRounded1("20150101T100000"); |
| 149 | name::Component testTimeRounded2("20150101T110000"); |
Yingdi Yu | 0c530b7 | 2016-03-20 18:19:14 -0700 | [diff] [blame] | 150 | name::Component testTimeComponent2("20150101T110001"); |
Prashanth Swaminathan | b210590 | 2015-08-20 14:28:54 -0700 | [diff] [blame] | 151 | |
| 152 | // Create content keys required for this test case: |
| 153 | for (size_t i = 0; i < suffix.size(); i++) { |
| 154 | createEncryptionKey(expectedInterest, timeMarker); |
| 155 | expectedInterest = expectedInterest.getPrefix(-2).append(NAME_COMPONENT_E_KEY); |
| 156 | } |
| 157 | |
Junxiao Shi | c1264c8 | 2016-07-14 15:04:07 +0000 | [diff] [blame] | 158 | face2.setInterestFilter(prefix, |
| 159 | [&] (const InterestFilter&, const Interest& i) { |
| 160 | Name interestName = i.getName(); |
| 161 | interestName.append(timeMarker); |
| 162 | BOOST_REQUIRE_EQUAL(encryptionKeys.find(interestName) != |
| 163 | encryptionKeys.end(), true); |
| 164 | face2.put(*(encryptionKeys[interestName])); |
| 165 | return; |
| 166 | }, |
| 167 | RegisterPrefixSuccessCallback(), |
| 168 | [] (const Name&, const std::string& e) { }); |
Prashanth Swaminathan | b210590 | 2015-08-20 14:28:54 -0700 | [diff] [blame] | 169 | |
| 170 | do { |
| 171 | advanceClocks(time::milliseconds(10), 20); |
| 172 | } while (passPacket()); |
| 173 | |
Yingdi Yu | 48967a6 | 2016-03-11 22:04:14 -0800 | [diff] [blame] | 174 | // Verify that content key is correctly encrypted for each domain, and the |
| 175 | // produce method encrypts provided data with the same content key. |
Junxiao Shi | c1264c8 | 2016-07-14 15:04:07 +0000 | [diff] [blame] | 176 | Producer producer(prefix, suffix, face1, dbDir); |
Prashanth Swaminathan | b210590 | 2015-08-20 14:28:54 -0700 | [diff] [blame] | 177 | ProducerDB testDb(dbDir); |
| 178 | Buffer contentKey; |
| 179 | |
| 180 | auto checkEncryptionKeys = |
| 181 | [&](const std::vector<Data>& result, |
| 182 | const time::system_clock::TimePoint& testTime, |
| 183 | const name::Component& roundedTime) { |
| 184 | BOOST_CHECK_EQUAL(testDb.hasContentKey(testTime), true); |
| 185 | contentKey = testDb.getContentKey(testTime); |
| 186 | |
| 187 | algo::EncryptParams params(tlv::AlgorithmRsaOaep); |
| 188 | std::vector<Data>::const_iterator it; |
| 189 | for (it = result.begin(); it != result.end(); ++it) { |
| 190 | Name keyName = it->getName(); |
| 191 | BOOST_CHECK_EQUAL(keyName.getSubName(0,6), cKeyName); |
| 192 | BOOST_CHECK_EQUAL(keyName.get(6), roundedTime); |
| 193 | BOOST_CHECK_EQUAL(keyName.get(7), NAME_COMPONENT_FOR); |
| 194 | BOOST_CHECK_EQUAL(decryptionKeys.find(keyName.getSubName(8)) != |
| 195 | decryptionKeys.end(), true); |
| 196 | Name testName = it->getName().getSubName(-8); |
| 197 | Buffer decryptionKey; |
| 198 | |
| 199 | decryptionKey = decryptionKeys.at(keyName.getSubName(8)); |
| 200 | BOOST_CHECK_EQUAL(decryptionKey.size() != 0, true); |
| 201 | Block encryptedKeyBlock = it->getContent(); |
| 202 | encryptedKeyBlock.parse(); |
| 203 | |
| 204 | EncryptedContent content(*(encryptedKeyBlock.elements_begin())); |
| 205 | const Buffer& encryptedKey = content.getPayload(); |
| 206 | Buffer retrievedKey = algo::Rsa::decrypt(decryptionKey.buf(), |
| 207 | decryptionKey.size(), |
| 208 | encryptedKey.buf(), |
| 209 | encryptedKey.size(), |
| 210 | params); |
| 211 | |
| 212 | BOOST_CHECK_EQUAL_COLLECTIONS(contentKey.begin(), |
| 213 | contentKey.end(), |
| 214 | retrievedKey.begin(), |
| 215 | retrievedKey.end()); |
| 216 | } |
| 217 | BOOST_CHECK_EQUAL(result.size(), 3); |
| 218 | }; |
| 219 | |
| 220 | // Initial test to confirm that keys are created for this timeslot |
| 221 | Name contentKeyName1 = |
| 222 | producer.createContentKey(testTime1, |
| 223 | std::bind(checkEncryptionKeys, _1, testTime1, testTimeRounded1)); |
| 224 | |
| 225 | do { |
| 226 | advanceClocks(time::milliseconds(10), 20); |
| 227 | } while (passPacket()); |
| 228 | |
| 229 | // Verify that we do not repeat the search for e-keys, don't advance clock |
| 230 | Name contentKeyName2 = |
| 231 | producer.createContentKey(testTime2, |
| 232 | std::bind(checkEncryptionKeys, _1, testTime2, testTimeRounded2)); |
| 233 | |
| 234 | // Confirm content key names are correct |
| 235 | BOOST_CHECK_EQUAL(contentKeyName1.getPrefix(-1), cKeyName); |
| 236 | BOOST_CHECK_EQUAL(contentKeyName1.get(6), testTimeRounded1); |
| 237 | BOOST_CHECK_EQUAL(contentKeyName2.getPrefix(-1), cKeyName); |
| 238 | BOOST_CHECK_EQUAL(contentKeyName2.get(6), testTimeRounded2); |
| 239 | |
| 240 | // Confirm produce encrypts with correct key and has right name |
| 241 | Data testData; |
| 242 | producer.produce(testData, testTime2, DATA_CONTEN, sizeof(DATA_CONTEN)); |
| 243 | |
| 244 | Name producedName = testData.getName(); |
| 245 | BOOST_CHECK_EQUAL(producedName.getSubName(0,5), cKeyName.getPrefix(-1)); |
Yingdi Yu | 0c530b7 | 2016-03-20 18:19:14 -0700 | [diff] [blame] | 246 | BOOST_CHECK_EQUAL(producedName.get(5), testTimeComponent2); |
Prashanth Swaminathan | b210590 | 2015-08-20 14:28:54 -0700 | [diff] [blame] | 247 | BOOST_CHECK_EQUAL(producedName.get(6), NAME_COMPONENT_FOR); |
| 248 | BOOST_CHECK_EQUAL(producedName.getSubName(7,6), cKeyName); |
| 249 | BOOST_CHECK_EQUAL(producedName.get(13), testTimeRounded2); |
| 250 | |
| 251 | Block dataBlock = testData.getContent(); |
| 252 | dataBlock.parse(); |
| 253 | |
| 254 | EncryptedContent dataContent(*(dataBlock).elements_begin()); |
| 255 | const Buffer& encData = dataContent.getPayload(); |
| 256 | const Buffer& iv = dataContent.getInitialVector(); |
| 257 | |
| 258 | algo::EncryptParams params(tlv::AlgorithmAesCbc, 16); |
| 259 | params.setIV(iv.buf(), iv.size()); |
| 260 | Buffer decryptTest = algo::Aes::decrypt(contentKey.buf(), contentKey.size(), |
| 261 | encData.buf(), encData.size(), params); |
| 262 | BOOST_CHECK_EQUAL_COLLECTIONS(decryptTest.begin(), |
| 263 | decryptTest.end(), |
| 264 | DATA_CONTEN, |
| 265 | DATA_CONTEN + sizeof(DATA_CONTEN)); |
| 266 | } |
| 267 | |
| 268 | BOOST_AUTO_TEST_CASE(ContentKeySearch) |
| 269 | { |
| 270 | std::string dbDir = tmpPath.c_str(); |
| 271 | dbDir += "/test.db"; |
| 272 | |
| 273 | Name timeMarkerFirstHop("20150101T070000/20150101T080000"); |
| 274 | Name timeMarkerSecondHop("20150101T080000/20150101T090000"); |
| 275 | Name timeMarkerThirdHop("20150101T100000/20150101T110000"); |
| 276 | |
| 277 | Name prefix("/prefix"); |
| 278 | Name suffix("/suffix"); |
| 279 | Name expectedInterest = prefix; |
| 280 | expectedInterest.append(NAME_COMPONENT_READ); |
| 281 | expectedInterest.append(suffix); |
| 282 | expectedInterest.append(NAME_COMPONENT_E_KEY); |
| 283 | |
| 284 | Name cKeyName = prefix; |
| 285 | cKeyName.append(NAME_COMPONENT_SAMPLE); |
| 286 | cKeyName.append(suffix); |
| 287 | cKeyName.append(NAME_COMPONENT_C_KEY); |
| 288 | |
| 289 | time::system_clock::TimePoint testTime = time::fromIsoString("20150101T100001"); |
| 290 | |
| 291 | // Create content keys required for this test case: |
| 292 | createEncryptionKey(expectedInterest, timeMarkerFirstHop); |
| 293 | createEncryptionKey(expectedInterest, timeMarkerSecondHop); |
| 294 | createEncryptionKey(expectedInterest, timeMarkerThirdHop); |
| 295 | |
| 296 | size_t requestCount = 0; |
Junxiao Shi | c1264c8 | 2016-07-14 15:04:07 +0000 | [diff] [blame] | 297 | face2.setInterestFilter(prefix, |
| 298 | [&] (const InterestFilter&, const Interest& i) { |
| 299 | BOOST_REQUIRE_EQUAL(i.getName(), expectedInterest); |
| 300 | Name interestName = i.getName(); |
| 301 | switch(requestCount) { |
| 302 | case 0: |
| 303 | interestName.append(timeMarkerFirstHop); |
| 304 | break; |
Prashanth Swaminathan | b210590 | 2015-08-20 14:28:54 -0700 | [diff] [blame] | 305 | |
Junxiao Shi | c1264c8 | 2016-07-14 15:04:07 +0000 | [diff] [blame] | 306 | case 1: |
| 307 | interestName.append(timeMarkerSecondHop); |
| 308 | break; |
Prashanth Swaminathan | b210590 | 2015-08-20 14:28:54 -0700 | [diff] [blame] | 309 | |
Junxiao Shi | c1264c8 | 2016-07-14 15:04:07 +0000 | [diff] [blame] | 310 | case 2: |
| 311 | interestName.append(timeMarkerThirdHop); |
| 312 | break; |
Prashanth Swaminathan | b210590 | 2015-08-20 14:28:54 -0700 | [diff] [blame] | 313 | |
Junxiao Shi | c1264c8 | 2016-07-14 15:04:07 +0000 | [diff] [blame] | 314 | default: |
| 315 | break; |
| 316 | } |
| 317 | face2.put(*(encryptionKeys[interestName])); |
| 318 | requestCount++; |
| 319 | return; |
| 320 | }, |
| 321 | RegisterPrefixSuccessCallback(), |
| 322 | [] (const Name&, const std::string& e) { }); |
Prashanth Swaminathan | b210590 | 2015-08-20 14:28:54 -0700 | [diff] [blame] | 323 | |
| 324 | do { |
| 325 | advanceClocks(time::milliseconds(10), 20); |
| 326 | } while (passPacket()); |
| 327 | |
Yingdi Yu | 48967a6 | 2016-03-11 22:04:14 -0800 | [diff] [blame] | 328 | // Verify that if a key is found, but not within the right timeslot, the search |
| 329 | // is refined until a valid timeslot is found. |
Junxiao Shi | c1264c8 | 2016-07-14 15:04:07 +0000 | [diff] [blame] | 330 | Producer producer(prefix, suffix, face1, dbDir); |
Prashanth Swaminathan | b210590 | 2015-08-20 14:28:54 -0700 | [diff] [blame] | 331 | producer.createContentKey(testTime, |
| 332 | [&](const std::vector<Data>& result){ |
| 333 | BOOST_CHECK_EQUAL(requestCount, 3); |
| 334 | BOOST_CHECK_EQUAL(result.size(), 1); |
| 335 | |
| 336 | Data keyData = result[0]; |
| 337 | Name keyName = keyData.getName(); |
| 338 | BOOST_CHECK_EQUAL(keyName.getSubName(0,4), cKeyName); |
| 339 | BOOST_CHECK_EQUAL(keyName.get(4), timeMarkerThirdHop[0]); |
| 340 | BOOST_CHECK_EQUAL(keyName.get(5), NAME_COMPONENT_FOR); |
| 341 | BOOST_CHECK_EQUAL(keyName.getSubName(6), |
| 342 | expectedInterest.append(timeMarkerThirdHop)); |
| 343 | }); |
| 344 | do { |
| 345 | advanceClocks(time::milliseconds(10), 20); |
| 346 | } while (passPacket()); |
| 347 | } |
| 348 | |
| 349 | BOOST_AUTO_TEST_CASE(ContentKeyTimeout) |
| 350 | { |
| 351 | std::string dbDir = tmpPath.c_str(); |
| 352 | dbDir += "/test.db"; |
| 353 | |
| 354 | Name prefix("/prefix"); |
| 355 | Name suffix("/suffix"); |
| 356 | Name expectedInterest = prefix; |
| 357 | expectedInterest.append(NAME_COMPONENT_READ); |
| 358 | expectedInterest.append(suffix); |
| 359 | expectedInterest.append(NAME_COMPONENT_E_KEY); |
| 360 | |
| 361 | time::system_clock::TimePoint testTime = time::fromIsoString("20150101T100001"); |
| 362 | |
| 363 | size_t timeoutCount = 0; |
Junxiao Shi | c1264c8 | 2016-07-14 15:04:07 +0000 | [diff] [blame] | 364 | face2.setInterestFilter(prefix, |
| 365 | [&] (const InterestFilter&, const Interest& i) { |
| 366 | BOOST_CHECK_EQUAL(i.getName(), expectedInterest); |
| 367 | timeoutCount++; |
| 368 | return; |
| 369 | }, |
| 370 | RegisterPrefixSuccessCallback(), |
| 371 | [] (const Name&, const std::string& e) { }); |
Prashanth Swaminathan | b210590 | 2015-08-20 14:28:54 -0700 | [diff] [blame] | 372 | |
| 373 | do { |
| 374 | advanceClocks(time::milliseconds(10), 20); |
| 375 | } while (passPacket()); |
| 376 | |
Yingdi Yu | 48967a6 | 2016-03-11 22:04:14 -0800 | [diff] [blame] | 377 | // Verify that if no response is received, the producer appropriately times out. |
| 378 | // The result vector should not contain elements that have timed out. |
Junxiao Shi | c1264c8 | 2016-07-14 15:04:07 +0000 | [diff] [blame] | 379 | Producer producer(prefix, suffix, face1, dbDir); |
Prashanth Swaminathan | b210590 | 2015-08-20 14:28:54 -0700 | [diff] [blame] | 380 | producer.createContentKey(testTime, |
| 381 | [&](const std::vector<Data>& result){ |
| 382 | BOOST_CHECK_EQUAL(timeoutCount, 4); |
| 383 | BOOST_CHECK_EQUAL(result.size(), 0); |
| 384 | }); |
| 385 | |
| 386 | do { |
| 387 | advanceClocks(time::milliseconds(10), 500); |
| 388 | } while (passPacket()); |
| 389 | } |
| 390 | |
Yingdi Yu | 48967a6 | 2016-03-11 22:04:14 -0800 | [diff] [blame] | 391 | BOOST_AUTO_TEST_CASE(ProducerWithLink) |
| 392 | { |
| 393 | std::string dbDir = tmpPath.c_str(); |
| 394 | dbDir += "/test.db"; |
| 395 | |
| 396 | Name prefix("/prefix"); |
| 397 | Name suffix("/suffix"); |
| 398 | Name expectedInterest = prefix; |
| 399 | expectedInterest.append(NAME_COMPONENT_READ); |
| 400 | expectedInterest.append(suffix); |
| 401 | expectedInterest.append(NAME_COMPONENT_E_KEY); |
| 402 | |
| 403 | time::system_clock::TimePoint testTime = time::fromIsoString("20150101T100001"); |
| 404 | |
| 405 | size_t timeoutCount = 0; |
| 406 | face2.setInterestFilter(prefix, |
| 407 | [&] (const InterestFilter&, const Interest& i) { |
| 408 | BOOST_CHECK_EQUAL(i.getName(), expectedInterest); |
| 409 | BOOST_CHECK(i.getLink().getDelegations().size() == 3); |
| 410 | timeoutCount++; |
| 411 | return; |
| 412 | }, |
| 413 | RegisterPrefixSuccessCallback(), |
| 414 | [] (const Name&, const std::string& e) { }); |
| 415 | |
| 416 | do { |
| 417 | advanceClocks(time::milliseconds(10), 20); |
| 418 | } while (passPacket()); |
| 419 | |
| 420 | // Verify that if no response is received, the producer appropriately times out. |
| 421 | // The result vector should not contain elements that have timed out. |
| 422 | Link link("test", {{10, "/test1"}, {20, "/test2"}, {100, "/test3"}}); |
| 423 | keyChain.sign(link); |
| 424 | Producer producer(prefix, suffix, face1, dbDir, 3, link); |
| 425 | producer.createContentKey(testTime, |
| 426 | [&](const std::vector<Data>& result){ |
| 427 | BOOST_CHECK_EQUAL(timeoutCount, 4); |
| 428 | BOOST_CHECK_EQUAL(result.size(), 0); |
| 429 | }); |
| 430 | |
| 431 | do { |
| 432 | advanceClocks(time::milliseconds(10), 800); |
| 433 | } while (passPacket()); |
| 434 | } |
| 435 | |
Prashanth Swaminathan | b210590 | 2015-08-20 14:28:54 -0700 | [diff] [blame] | 436 | BOOST_AUTO_TEST_SUITE_END() |
| 437 | |
| 438 | } // namespace tests |
| 439 | } // namespace gep |
| 440 | } // namespace ndn |