Exemple #1
0
BOOST_FIXTURE_TEST_CASE(NotificationStream, DispatcherFixture)
{
  static Block block("\x82\x01\x02", 3);

  auto post = dispatcher.addNotificationStream("test");

  post(block);
  advanceClocks(time::milliseconds(1));
  BOOST_CHECK_EQUAL(face->sentDatas.size(), 0);

  dispatcher.addTopPrefix("/root");
  advanceClocks(time::milliseconds(1));
  face->sentDatas.clear();

  post(block);
  advanceClocks(time::milliseconds(1));
  BOOST_CHECK_EQUAL(face->sentDatas.size(), 1);

  post(block);
  post(block);
  post(block);
  advanceClocks(time::milliseconds(1), 10);

  BOOST_CHECK_EQUAL(face->sentDatas.size(), 4);
  BOOST_CHECK_EQUAL(face->sentDatas[0].getName(), "/root/test/%FE%00");
  BOOST_CHECK_EQUAL(face->sentDatas[1].getName(), "/root/test/%FE%01");
  BOOST_CHECK_EQUAL(face->sentDatas[2].getName(), "/root/test/%FE%02");
  BOOST_CHECK_EQUAL(face->sentDatas[3].getName(), "/root/test/%FE%03");

  BOOST_CHECK(face->sentDatas[0].getContent().blockFromValue() == block);
  BOOST_CHECK(face->sentDatas[1].getContent().blockFromValue() == block);
  BOOST_CHECK(face->sentDatas[2].getContent().blockFromValue() == block);
  BOOST_CHECK(face->sentDatas[3].getContent().blockFromValue() == block);
}
Exemple #2
0
BOOST_FIXTURE_TEST_CASE(ControlCommand, DispatcherFixture)
{
  size_t nCallbackCalled = 0;
  dispatcher
    .addControlCommand<VoidParameters>("test",
                                       makeTestAuthorization(),
                                       bind([] { return true; }),
                                       bind([&nCallbackCalled] { ++nCallbackCalled; }));

  dispatcher.addTopPrefix("/root");
  advanceClocks(time::milliseconds(1));
  face->sentDatas.clear();

  face->receive(*util::makeInterest("/root/test/%80%00")); // returns 403
  face->receive(*util::makeInterest("/root/test/%80%00/invalid")); // returns 403
  face->receive(*util::makeInterest("/root/test/%80%00/silent")); // silently ignored
  face->receive(*util::makeInterest("/root/test/.../invalid")); // silently ignored (wrong format)
  face->receive(*util::makeInterest("/root/test/.../valid"));  // silently ignored (wrong format)
  advanceClocks(time::milliseconds(1), 20);
  BOOST_CHECK_EQUAL(nCallbackCalled, 0);
  BOOST_CHECK_EQUAL(face->sentDatas.size(), 2);

  BOOST_CHECK(face->sentDatas[0].getContentType() == tlv::ContentType_Blob);
  BOOST_CHECK_EQUAL(ControlResponse(face->sentDatas[0].getContent().blockFromValue()).getCode(), 403);
  BOOST_CHECK(face->sentDatas[1].getContentType() == tlv::ContentType_Blob);
  BOOST_CHECK_EQUAL(ControlResponse(face->sentDatas[1].getContent().blockFromValue()).getCode(), 403);

  face->receive(*util::makeInterest("/root/test/%80%00/valid"));
  advanceClocks(time::milliseconds(1), 10);
  BOOST_CHECK_EQUAL(nCallbackCalled, 1);
}
BOOST_FIXTURE_TEST_CASE(TripleWithInitialSegmentFetching, Fixture)
{
  ValidatorNull nullValidator;
  SegmentFetcher::fetch(face, Interest("/hello/world", time::seconds(1000)),
                        nullValidator,
                        bind(&Fixture::onComplete, this, _1),
                        bind(&Fixture::onError, this, _1));

  advanceClocks(time::milliseconds(1), 10);
  face.receive(*makeDataSegment("/hello/world/version0", 1, false));

  advanceClocks(time::milliseconds(1), 10);
  face.receive(*makeDataSegment("/hello/world/version0", 0, false));

  advanceClocks(time::milliseconds(1), 10);
  face.receive(*makeDataSegment("/hello/world/version0", 1, false));

  advanceClocks(time::milliseconds(1), 10);
  face.receive(*makeDataSegment("/hello/world/version0", 2, true));

  advanceClocks(time::milliseconds(1), 10);

  BOOST_CHECK_EQUAL(nErrors, 0);
  BOOST_CHECK_EQUAL(nDatas, 1);

  BOOST_CHECK_EQUAL(dataSize, 42);

  BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 4);
  BOOST_CHECK_EQUAL(face.sentData.size(), 0);

  {
    const Interest& interest = face.sentInterests[0];
    BOOST_CHECK_EQUAL(interest.getName(), "/hello/world");
    BOOST_CHECK_EQUAL(interest.getMustBeFresh(), true);
    BOOST_CHECK_EQUAL(interest.getChildSelector(), 1);
  }

  {
    const Interest& interest = face.sentInterests[1];
    BOOST_CHECK_EQUAL(interest.getName(), "/hello/world/version0/%00%00");
    BOOST_CHECK_EQUAL(interest.getMustBeFresh(), false);
    BOOST_CHECK_EQUAL(interest.getChildSelector(), 0);
  }

  {
    const Interest& interest = face.sentInterests[2];
    BOOST_CHECK_EQUAL(interest.getName(), "/hello/world/version0/%00%01");
    BOOST_CHECK_EQUAL(interest.getMustBeFresh(), false);
    BOOST_CHECK_EQUAL(interest.getChildSelector(), 0);
  }

  {
    const Interest& interest = face.sentInterests[3];
    BOOST_CHECK_EQUAL(interest.getName(),  "/hello/world/version0/%00%02");
    BOOST_CHECK_EQUAL(interest.getMustBeFresh(), false);
    BOOST_CHECK_EQUAL(interest.getChildSelector(), 0);
  }
}
Exemple #4
0
BOOST_FIXTURE_TEST_CASE(NotificationStream, DispatcherFixture)
{
    static Block block("\x82\x01\x02", 3);

    auto post = dispatcher.addNotificationStream("test");

    post(block);
    advanceClocks(time::milliseconds(1));
    BOOST_CHECK_EQUAL(face.sentData.size(), 0);

    dispatcher.addTopPrefix("/root");
    advanceClocks(time::milliseconds(1));
    face.sentData.clear();

    post(block);
    advanceClocks(time::milliseconds(1));
    BOOST_CHECK_EQUAL(face.sentData.size(), 1);
    BOOST_CHECK_EQUAL(storage.size(), 1);

    post(block);
    post(block);
    post(block);
    advanceClocks(time::milliseconds(1), 10);

    BOOST_CHECK_EQUAL(face.sentData.size(), 4);
    BOOST_CHECK_EQUAL(face.sentData[0].getName(), "/root/test/%FE%00");
    BOOST_CHECK_EQUAL(face.sentData[1].getName(), "/root/test/%FE%01");
    BOOST_CHECK_EQUAL(face.sentData[2].getName(), "/root/test/%FE%02");
    BOOST_CHECK_EQUAL(face.sentData[3].getName(), "/root/test/%FE%03");

    BOOST_CHECK(face.sentData[0].getContent().blockFromValue() == block);
    BOOST_CHECK(face.sentData[1].getContent().blockFromValue() == block);
    BOOST_CHECK(face.sentData[2].getContent().blockFromValue() == block);
    BOOST_CHECK(face.sentData[3].getContent().blockFromValue() == block);

    // each version of notification will be sent to both places
    std::vector<Data> dataInStorage;
    std::copy(storage.begin(), storage.end(), std::back_inserter(dataInStorage));
    BOOST_CHECK_EQUAL(dataInStorage.size(), 4);
    BOOST_CHECK_EQUAL(dataInStorage[0].getName(), "/root/test/%FE%00");
    BOOST_CHECK_EQUAL(dataInStorage[1].getName(), "/root/test/%FE%01");
    BOOST_CHECK_EQUAL(dataInStorage[2].getName(), "/root/test/%FE%02");
    BOOST_CHECK_EQUAL(dataInStorage[3].getName(), "/root/test/%FE%03");

    BOOST_CHECK(dataInStorage[0].getContent().blockFromValue() == block);
    BOOST_CHECK(dataInStorage[1].getContent().blockFromValue() == block);
    BOOST_CHECK(dataInStorage[2].getContent().blockFromValue() == block);
    BOOST_CHECK(dataInStorage[3].getContent().blockFromValue() == block);
}
BOOST_FIXTURE_TEST_CASE(SegmentValidationFailure, Fixture)
{
  ValidatorFailed failedValidator;
  SegmentFetcher::fetch(face, Interest("/hello/world", time::seconds(1000)),
                        failedValidator,
                        bind(&Fixture::onComplete, this, _1),
                        bind(&Fixture::onError, this, _1));

  advanceClocks(time::milliseconds(1), 10);
  face.receive(*makeDataSegment("/hello/world/version0", 0, true));
  advanceClocks(time::milliseconds(1), 10);

  BOOST_CHECK_EQUAL(nErrors, 1);
  BOOST_CHECK_EQUAL(lastError, static_cast<uint32_t>(SegmentFetcher::SEGMENT_VALIDATION_FAIL));
  BOOST_CHECK_EQUAL(nDatas, 0);
}
BOOST_FIXTURE_TEST_CASE(MultipleSegmentFetching, Fixture)
{
  ValidatorNull nullValidator;
  SegmentFetcher::fetch(face, Interest("/hello/world", time::seconds(1000)),
                        nullValidator,
                        bind(&Fixture::onComplete, this, _1),
                        bind(&Fixture::onError, this, _1));

  advanceClocks(time::milliseconds(1), 10);

  for (uint64_t i = 0; i < 400; i++) {
    advanceClocks(time::milliseconds(1), 10);
    face.receive(*makeDataSegment("/hello/world/version0", i, false));
  }
  advanceClocks(time::milliseconds(1), 10);
  face.receive(*makeDataSegment("/hello/world/version0", 400, true));

  advanceClocks(time::milliseconds(1), 10);

  BOOST_CHECK_EQUAL(nErrors, 0);
  BOOST_CHECK_EQUAL(nDatas, 1);
}
BOOST_FIXTURE_TEST_CASE(SegmentZero, Fixture)
{
  int nNacks = 2;

  ndn::Name interestName("ndn:/A");
  SegmentFetcher::fetch(face,
                        Interest(interestName),
                        make_shared<ValidatorNull>(),
                        bind(&Fixture::onComplete, this, _1),
                        bind(&Fixture::onError, this, _1));

  advanceClocks(time::milliseconds(1000));

  for (uint64_t segmentNo = 0; segmentNo <= 3; segmentNo++) {
    if (segmentNo == 1) {
      while (nNacks--) {
        nackLastInterest(lp::NackReason::CONGESTION);
        advanceClocks(time::milliseconds(10));
      }
    }

    auto data = makeDataSegment(interestName, segmentNo, segmentNo == 3);
    face.receive(*data);
    advanceClocks(time::milliseconds(10));
  }

  // Total number of sent interests should be 6: one interest for segment zero and segment one each,
  // two re-expressed interests for segment one after getting nack twice, and two interests for
  // segment two and three
  BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 6);

  BOOST_CHECK_EQUAL(face.sentInterests[0].getName(), ndn::Name("ndn:/A"));
  BOOST_CHECK_EQUAL(face.sentInterests[1].getName(), ndn::Name("ndn:/A/%00%01"));
  BOOST_CHECK_EQUAL(face.sentInterests[2].getName(), ndn::Name("ndn:/A/%00%01"));
  BOOST_CHECK_EQUAL(face.sentInterests[3].getName(), ndn::Name("ndn:/A/%00%01"));
  BOOST_CHECK_EQUAL(face.sentInterests[4].getName(), ndn::Name("ndn:/A/%00%02"));
  BOOST_CHECK_EQUAL(face.sentInterests[5].getName(), ndn::Name("ndn:/A/%00%03"));
}
BOOST_FIXTURE_TEST_CASE(ZeroComponentName, Fixture)
{
  SegmentFetcher::fetch(face, Interest("ndn:/"),
                        make_shared<ValidatorNull>(),
                        bind(&Fixture::onComplete, this, _1),
                        bind(&Fixture::onError, this, _1));
  advanceClocks(time::milliseconds(10));
  nackLastInterest(lp::NackReason::DUPLICATE);
  face.receive(*makeDataSegment("/hello/world", 0, true));

  BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 2);
  BOOST_CHECK_EQUAL(face.sentInterests[0].getName(), ndn::Name("ndn:/"));
  BOOST_CHECK_EQUAL(face.sentInterests[1].getName(), ndn::Name("ndn:/"));
  BOOST_REQUIRE_EQUAL(nData, 1);
}
BOOST_FIXTURE_TEST_CASE(SegmentFetcherCongestionNack, Fixture)
{
  SegmentFetcher::fetch(face, Interest("/hello/world", time::seconds(1000)),
                        make_shared<ValidatorNull>(),
                        bind(&Fixture::onComplete, this, _1),
                        bind(&Fixture::onError, this, _1));
  advanceClocks(time::milliseconds(1), 10);

  // receive nack for the original interest
  nackLastInterest(lp::NackReason::CONGESTION);

  // receive nack due to Congestion for the reexpressed interests
  for (uint32_t i = 1; i <= SegmentFetcher::MAX_INTEREST_REEXPRESS; ++i) {
    nackLastInterest(lp::NackReason::CONGESTION);
  }

  BOOST_CHECK_EQUAL(face.sentInterests.size(), (SegmentFetcher::MAX_INTEREST_REEXPRESS + 1));
  BOOST_CHECK_EQUAL(lastError, static_cast<uint32_t>(SegmentFetcher::NACK_ERROR));
}
Exemple #10
0
BOOST_FIXTURE_TEST_CASE(StatusDataset, DispatcherFixture)
{
  static Block smallBlock("\x81\x01\0x01", 3);
  static Block largeBlock = [] () -> Block {
    EncodingBuffer encoder;
    for (size_t i = 0; i < 2500; ++i) {
      encoder.prependByte(1);
    }
    encoder.prependVarNumber(2500);
    encoder.prependVarNumber(129);
    return encoder.block();
  }();

  dispatcher.addStatusDataset("test/small",
                              makeTestAuthorization(),
                              [] (const Name& prefix, const Interest& interest,
                                  StatusDatasetContext context) {
                                context.append(smallBlock);
                                context.append(smallBlock);
                                context.append(smallBlock);
                                context.end();
                              });

  dispatcher.addStatusDataset("test/large",
                              makeTestAuthorization(),
                              [] (const Name& prefix, const Interest& interest,
                                  StatusDatasetContext context) {
                                context.append(largeBlock);
                                context.append(largeBlock);
                                context.append(largeBlock);
                                context.end();
                              });

  dispatcher.addStatusDataset("test/reject",
                              makeTestAuthorization(),
                              [] (const Name& prefix, const Interest& interest,
                                  StatusDatasetContext context) {
                                context.reject();
                              });

  dispatcher.addTopPrefix("/root");
  advanceClocks(time::milliseconds(1));
  face->sentDatas.clear();

  face->receive(*util::makeInterest("/root/test/small/%80%00")); // returns 403
  face->receive(*util::makeInterest("/root/test/small/%80%00/invalid")); // returns 403
  face->receive(*util::makeInterest("/root/test/small/%80%00/silent")); // silently ignored
  advanceClocks(time::milliseconds(1), 20);
  BOOST_CHECK_EQUAL(face->sentDatas.size(), 2);

  BOOST_CHECK(face->sentDatas[0].getContentType() == tlv::ContentType_Blob);
  BOOST_CHECK_EQUAL(ControlResponse(face->sentDatas[0].getContent().blockFromValue()).getCode(), 403);
  BOOST_CHECK(face->sentDatas[1].getContentType() == tlv::ContentType_Blob);
  BOOST_CHECK_EQUAL(ControlResponse(face->sentDatas[1].getContent().blockFromValue()).getCode(), 403);

  face->sentDatas.clear();
  face->receive(*util::makeInterest("/root/test/small/valid"));
  advanceClocks(time::milliseconds(1), 10);
  BOOST_CHECK_EQUAL(face->sentDatas.size(), 1);

  face->receive(*util::makeInterest(Name("/root/test/small/valid").appendVersion(10))); // should be ignored
  face->receive(*util::makeInterest(Name("/root/test/small/valid").appendSegment(20))); // should be ignored
  advanceClocks(time::milliseconds(1), 10);
  BOOST_CHECK_EQUAL(face->sentDatas.size(), 1);

  Block content = face->sentDatas[0].getContent();
  BOOST_CHECK_NO_THROW(content.parse());

  BOOST_CHECK_EQUAL(content.elements().size(), 3);
  BOOST_CHECK(content.elements()[0] == smallBlock);
  BOOST_CHECK(content.elements()[1] == smallBlock);
  BOOST_CHECK(content.elements()[2] == smallBlock);

  face->sentDatas.clear();
  face->receive(*util::makeInterest("/root/test/large/valid"));
  advanceClocks(time::milliseconds(1), 10);
  BOOST_CHECK_EQUAL(face->sentDatas.size(), 2);

  const auto& datas = face->sentDatas;
  content = [&datas] () -> Block {
    EncodingBuffer encoder;
    size_t valueLength = encoder.prependByteArray(datas[1].getContent().value(),
                                                  datas[1].getContent().value_size());
    valueLength += encoder.prependByteArray(datas[0].getContent().value(),
                                            datas[0].getContent().value_size());
    encoder.prependVarNumber(valueLength);
    encoder.prependVarNumber(tlv::Content);
    return encoder.block();
  }();

  BOOST_CHECK_NO_THROW(content.parse());

  BOOST_CHECK_EQUAL(content.elements().size(), 3);
  BOOST_CHECK(content.elements()[0] == largeBlock);
  BOOST_CHECK(content.elements()[1] == largeBlock);
  BOOST_CHECK(content.elements()[2] == largeBlock);

  face->sentDatas.clear();
  face->receive(*util::makeInterest("/root/test/reject/%80%00/valid")); // returns nack
  advanceClocks(time::milliseconds(1));
  BOOST_CHECK_EQUAL(face->sentDatas.size(), 1);
  BOOST_CHECK(face->sentDatas[0].getContentType() == tlv::ContentType_Nack);
  BOOST_CHECK_EQUAL(ControlResponse(face->sentDatas[0].getContent().blockFromValue()).getCode(), 400);
}
Exemple #11
0
BOOST_FIXTURE_TEST_CASE(AddRemoveTopPrefix, DispatcherFixture)
{
  std::map<std::string, size_t> nCallbackCalled;
  dispatcher
    .addControlCommand<VoidParameters>("test/1", makeAcceptAllAuthorization(),
                                       bind([] { return true; }),
                                       bind([&nCallbackCalled] { ++nCallbackCalled["test/1"]; }));

  dispatcher
    .addControlCommand<VoidParameters>("test/2", makeAcceptAllAuthorization(),
                                       bind([] { return true; }),
                                       bind([&nCallbackCalled] { ++nCallbackCalled["test/2"]; }));

  face->receive(*util::makeInterest("/root/1/test/1/%80%00"));
  advanceClocks(time::milliseconds(1));
  BOOST_CHECK_EQUAL(nCallbackCalled["test/1"], 0);
  BOOST_CHECK_EQUAL(nCallbackCalled["test/2"], 0);

  dispatcher.addTopPrefix("/root/1");
  advanceClocks(time::milliseconds(1));

  face->receive(*util::makeInterest("/root/1/test/1/%80%00"));
  advanceClocks(time::milliseconds(1));
  BOOST_CHECK_EQUAL(nCallbackCalled["test/1"], 1);
  BOOST_CHECK_EQUAL(nCallbackCalled["test/2"], 0);

  face->receive(*util::makeInterest("/root/1/test/2/%80%00"));
  advanceClocks(time::milliseconds(1));
  BOOST_CHECK_EQUAL(nCallbackCalled["test/1"], 1);
  BOOST_CHECK_EQUAL(nCallbackCalled["test/2"], 1);

  face->receive(*util::makeInterest("/root/2/test/1/%80%00"));
  face->receive(*util::makeInterest("/root/2/test/2/%80%00"));
  advanceClocks(time::milliseconds(1));
  BOOST_CHECK_EQUAL(nCallbackCalled["test/1"], 1);
  BOOST_CHECK_EQUAL(nCallbackCalled["test/2"], 1);

  dispatcher.addTopPrefix("/root/2");
  advanceClocks(time::milliseconds(1));

  face->receive(*util::makeInterest("/root/1/test/1/%80%00"));
  advanceClocks(time::milliseconds(1));
  BOOST_CHECK_EQUAL(nCallbackCalled["test/1"], 2);

  face->receive(*util::makeInterest("/root/2/test/1/%80%00"));
  advanceClocks(time::milliseconds(1));
  BOOST_CHECK_EQUAL(nCallbackCalled["test/1"], 3);

  dispatcher.removeTopPrefix("/root/1");
  advanceClocks(time::milliseconds(1));

  face->receive(*util::makeInterest("/root/1/test/1/%80%00"));
  advanceClocks(time::milliseconds(1));
  BOOST_CHECK_EQUAL(nCallbackCalled["test/1"], 3);

  face->receive(*util::makeInterest("/root/2/test/1/%80%00"));
  advanceClocks(time::milliseconds(1));
  BOOST_CHECK_EQUAL(nCallbackCalled["test/1"], 4);
}
Exemple #12
0
BOOST_FIXTURE_TEST_CASE(StatusDataset, DispatcherFixture)
{
    static Block smallBlock("\x81\x01\0x01", 3);
    static Block largeBlock = [] () -> Block {
        EncodingBuffer encoder;
        for (size_t i = 0; i < 2500; ++i) {
            encoder.prependByte(1);
        }
        encoder.prependVarNumber(2500);
        encoder.prependVarNumber(129);
        return encoder.block();
    }();

    dispatcher.addStatusDataset("test/small",
                                makeTestAuthorization(),
                                [] (const Name& prefix, const Interest& interest,
    StatusDatasetContext& context) {
        context.append(smallBlock);
        context.append(smallBlock);
        context.append(smallBlock);
        context.end();
    });

    dispatcher.addStatusDataset("test/large",
                                makeTestAuthorization(),
                                [] (const Name& prefix, const Interest& interest,
    StatusDatasetContext& context) {
        context.append(largeBlock);
        context.append(largeBlock);
        context.append(largeBlock);
        context.end();
    });

    dispatcher.addStatusDataset("test/reject",
                                makeTestAuthorization(),
                                [] (const Name& prefix, const Interest& interest,
    StatusDatasetContext& context) {
        context.reject();
    });

    dispatcher.addTopPrefix("/root");
    advanceClocks(time::milliseconds(1));
    face.sentData.clear();

    face.receive(*util::makeInterest("/root/test/small/%80%00")); // returns 403
    face.receive(*util::makeInterest("/root/test/small/%80%00/invalid")); // returns 403
    face.receive(*util::makeInterest("/root/test/small/%80%00/silent")); // silently ignored
    advanceClocks(time::milliseconds(1), 20);
    BOOST_CHECK_EQUAL(face.sentData.size(), 2);

    BOOST_CHECK(face.sentData[0].getContentType() == tlv::ContentType_Blob);
    BOOST_CHECK_EQUAL(ControlResponse(face.sentData[0].getContent().blockFromValue()).getCode(), 403);
    BOOST_CHECK(face.sentData[1].getContentType() == tlv::ContentType_Blob);
    BOOST_CHECK_EQUAL(ControlResponse(face.sentData[1].getContent().blockFromValue()).getCode(), 403);

    face.sentData.clear();

    auto interestSmall = *util::makeInterest("/root/test/small/valid");
    face.receive(interestSmall);
    advanceClocks(time::milliseconds(1), 10);

    // one data packet is generated and sent to both places
    BOOST_CHECK_EQUAL(face.sentData.size(), 1);
    BOOST_CHECK_EQUAL(storage.size(), 1);

    auto fetchedData = storage.find(interestSmall);
    BOOST_REQUIRE(fetchedData != nullptr);
    BOOST_CHECK(face.sentData[0].wireEncode() == fetchedData->wireEncode());

    face.receive(*util::makeInterest(Name("/root/test/small/valid").appendVersion(10))); // should be ignored
    face.receive(*util::makeInterest(Name("/root/test/small/valid").appendSegment(20))); // should be ignored
    advanceClocks(time::milliseconds(1), 10);
    BOOST_CHECK_EQUAL(face.sentData.size(), 1);
    BOOST_CHECK_EQUAL(storage.size(), 1);

    Block content = face.sentData[0].getContent();
    BOOST_CHECK_NO_THROW(content.parse());

    BOOST_CHECK_EQUAL(content.elements().size(), 3);
    BOOST_CHECK(content.elements()[0] == smallBlock);
    BOOST_CHECK(content.elements()[1] == smallBlock);
    BOOST_CHECK(content.elements()[2] == smallBlock);

    storage.erase("/", true); // clear the storage
    face.sentData.clear();
    face.receive(*util::makeInterest("/root/test/large/valid"));
    advanceClocks(time::milliseconds(1), 10);

    // two data packets are generated, the first one will be sent to both places
    // while the second one will only be inserted into the in-memory storage
    BOOST_CHECK_EQUAL(face.sentData.size(), 1);
    BOOST_CHECK_EQUAL(storage.size(), 2);

    // segment0 should be sent through the face
    const auto& component = face.sentData[0].getName().at(-1);
    BOOST_CHECK(component.isSegment());
    BOOST_CHECK_EQUAL(component.toSegment(), 0);

    std::vector<Data> dataInStorage;
    std::copy(storage.begin(), storage.end(), std::back_inserter(dataInStorage));

    // the Data sent through the face should be the same as the first Data in the storage
    BOOST_CHECK_EQUAL(face.sentData[0].getName(), dataInStorage[0].getName());
    BOOST_CHECK(face.sentData[0].getContent() == dataInStorage[0].getContent());

    content = [&dataInStorage] () -> Block {
        EncodingBuffer encoder;
        size_t valueLength = encoder.prependByteArray(dataInStorage[1].getContent().value(),
        dataInStorage[1].getContent().value_size());
        valueLength += encoder.prependByteArray(dataInStorage[0].getContent().value(),
        dataInStorage[0].getContent().value_size());
        encoder.prependVarNumber(valueLength);
        encoder.prependVarNumber(tlv::Content);
        return encoder.block();
    }();

    BOOST_CHECK_NO_THROW(content.parse());
    BOOST_CHECK_EQUAL(content.elements().size(), 3);
    BOOST_CHECK(content.elements()[0] == largeBlock);
    BOOST_CHECK(content.elements()[1] == largeBlock);
    BOOST_CHECK(content.elements()[2] == largeBlock);

    storage.erase("/", true);// clear the storage
    face.sentData.clear();
    face.receive(*util::makeInterest("/root/test/reject/%80%00/valid")); // returns nack
    advanceClocks(time::milliseconds(1));
    BOOST_CHECK_EQUAL(face.sentData.size(), 1);
    BOOST_CHECK(face.sentData[0].getContentType() == tlv::ContentType_Nack);
    BOOST_CHECK_EQUAL(ControlResponse(face.sentData[0].getContent().blockFromValue()).getCode(), 400);
    BOOST_CHECK_EQUAL(storage.size(), 0); // the nack packet will not be inserted into the in-memory storage
}
FaceManagerCommandFixture::~FaceManagerCommandFixture()
{
  advanceClocks(1_ms, 5);
}
FaceManagerCommandFixture::FaceManagerCommandFixture()
  : node1(m_keyChain, 16363)
  , node2(m_keyChain, 26363)
{
  advanceClocks(1_ms, 5);
}