util: use signals instead of callbacks in SegmentFetcher
Deprecate fetch() static functions in favor of start()
refs #4464
Change-Id: I8632790e6151ad019b19c89ceae1944d37871da2
diff --git a/tests/unit-tests/util/segment-fetcher.t.cpp b/tests/unit-tests/util/segment-fetcher.t.cpp
index c4d6bb8..d8f2bf5 100644
--- a/tests/unit-tests/util/segment-fetcher.t.cpp
+++ b/tests/unit-tests/util/segment-fetcher.t.cpp
@@ -71,7 +71,7 @@
void
onComplete(const ConstBufferPtr& data)
{
- ++nData;
+ ++nCompletions;
dataSize = data->size();
dataString = std::string(data->get<char>());
}
@@ -85,12 +85,19 @@
advanceClocks(10_ms);
}
+ void
+ connectSignals(shared_ptr<SegmentFetcher> fetcher)
+ {
+ fetcher->onComplete.connect(bind(&Fixture::onComplete, this, _1));
+ fetcher->onError.connect(bind(&Fixture::onError, this, _1));
+ }
+
public:
DummyClientFace face;
- uint32_t nErrors = 0;
+ int nErrors = 0;
uint32_t lastError = 0;
- uint32_t nData = 0;
+ int nCompletions = 0;
size_t dataSize = 0;
std::string dataString;
};
@@ -98,10 +105,9 @@
BOOST_FIXTURE_TEST_CASE(Timeout, Fixture)
{
DummyValidator acceptValidator;
- SegmentFetcher::fetch(face, Interest("/hello/world", 100_ms),
- acceptValidator,
- bind(&Fixture::onComplete, this, _1),
- bind(&Fixture::onError, this, _1));
+ shared_ptr<SegmentFetcher> fetcher = SegmentFetcher::start(face, Interest("/hello/world", 100_ms),
+ acceptValidator);
+ connectSignals(fetcher);
advanceClocks(1_ms);
BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 1);
@@ -113,7 +119,7 @@
advanceClocks(98_ms);
BOOST_CHECK_EQUAL(nErrors, 0);
- BOOST_CHECK_EQUAL(nData, 0);
+ BOOST_CHECK_EQUAL(nCompletions, 0);
BOOST_CHECK_EQUAL(face.sentData.size(), 0);
advanceClocks(1_ms, 2);
@@ -123,193 +129,16 @@
BOOST_CHECK_EQUAL(face.sentData.size(), 0);
}
-
BOOST_FIXTURE_TEST_CASE(Basic, Fixture)
{
DummyValidator acceptValidator;
- SegmentFetcher::fetch(face, Interest("/hello/world", 1000_s),
- acceptValidator,
- bind(&Fixture::onComplete, this, _1),
- bind(&Fixture::onError, this, _1));
-
- advanceClocks(10_ms);
-
- face.receive(*makeDataSegment("/hello/world/version0", 0, true));
- advanceClocks(10_ms);
-
- BOOST_CHECK_EQUAL(nErrors, 0);
- BOOST_CHECK_EQUAL(nData, 1);
-
- BOOST_CHECK_EQUAL(dataSize, 14);
-
- const uint8_t buffer[] = "Hello, world!";
- std::string bufferString(reinterpret_cast<const char*>(buffer));
-
- BOOST_CHECK_EQUAL(dataString, bufferString);
-
- BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 1);
- 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);
-}
-
-BOOST_FIXTURE_TEST_CASE(NoSegmentInData, Fixture)
-{
- DummyValidator acceptValidator;
- SegmentFetcher::fetch(face, Interest("/hello/world", 1000_s),
- acceptValidator,
- bind(&Fixture::onComplete, this, _1),
- bind(&Fixture::onError, this, _1));
-
- advanceClocks(10_ms);
-
- const uint8_t buffer[] = "Hello, world!";
- auto data = makeData("/hello/world/version0/no-segment");
- data->setContent(buffer, sizeof(buffer));
-
- face.receive(*data);
- advanceClocks(10_ms);
-
- BOOST_CHECK_EQUAL(nErrors, 1);
- BOOST_CHECK_EQUAL(lastError, static_cast<uint32_t>(SegmentFetcher::DATA_HAS_NO_SEGMENT));
- BOOST_CHECK_EQUAL(nData, 0);
-}
-
-BOOST_FIXTURE_TEST_CASE(SegmentValidationFailure, Fixture)
-{
- DummyValidator rejectValidator(false);
- SegmentFetcher::fetch(face, Interest("/hello/world", 1000_s),
- rejectValidator,
- bind(&Fixture::onComplete, this, _1),
- bind(&Fixture::onError, this, _1));
-
- advanceClocks(10_ms);
- face.receive(*makeDataSegment("/hello/world/version0", 0, true));
- advanceClocks(10_ms);
-
- BOOST_CHECK_EQUAL(nErrors, 1);
- BOOST_CHECK_EQUAL(lastError, static_cast<uint32_t>(SegmentFetcher::SEGMENT_VALIDATION_FAIL));
- BOOST_CHECK_EQUAL(nData, 0);
-}
-
-BOOST_FIXTURE_TEST_CASE(Triple, Fixture)
-{
- DummyValidator acceptValidator;
- SegmentFetcher::fetch(face, Interest("/hello/world", 1000_s),
- acceptValidator,
- bind(&Fixture::onComplete, this, _1),
- bind(&Fixture::onError, this, _1));
-
- advanceClocks(10_ms);
- face.receive(*makeDataSegment("/hello/world/version0", 0, false));
-
- advanceClocks(10_ms);
- face.receive(*makeDataSegment("/hello/world/version0", 1, false));
-
- advanceClocks(10_ms);
- face.receive(*makeDataSegment("/hello/world/version0", 2, true));
-
- advanceClocks(10_ms);
-
- BOOST_CHECK_EQUAL(nErrors, 0);
- BOOST_CHECK_EQUAL(nData, 1);
-
- BOOST_CHECK_EQUAL(dataSize, 42);
-
- BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 3);
- 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%01");
- 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%02");
- BOOST_CHECK_EQUAL(interest.getMustBeFresh(), false);
- BOOST_CHECK_EQUAL(interest.getChildSelector(), 0);
- }
-}
-
-BOOST_FIXTURE_TEST_CASE(TripleWithInitialSegmentFetching, Fixture)
-{
- DummyValidator acceptValidator;
- SegmentFetcher::fetch(face, Interest("/hello/world", 1000_s),
- acceptValidator,
- bind(&Fixture::onComplete, this, _1),
- bind(&Fixture::onError, this, _1));
-
- advanceClocks(10_ms);
- face.receive(*makeDataSegment("/hello/world/version0", 1, false));
-
- advanceClocks(10_ms);
- face.receive(*makeDataSegment("/hello/world/version0", 0, false));
-
- advanceClocks(10_ms);
- face.receive(*makeDataSegment("/hello/world/version0", 1, false));
-
- advanceClocks(10_ms);
- face.receive(*makeDataSegment("/hello/world/version0", 2, true));
-
- advanceClocks(10_ms);
-
- BOOST_CHECK_EQUAL(nErrors, 0);
- BOOST_CHECK_EQUAL(nData, 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);
- }
-}
-
-BOOST_FIXTURE_TEST_CASE(MultipleSegmentFetching, Fixture)
-{
- DummyValidator acceptValidator;
- SegmentFetcher::fetch(face, Interest("/hello/world", 1000_s),
- acceptValidator,
- bind(&Fixture::onComplete, this, _1),
- bind(&Fixture::onError, this, _1));
+ size_t nAfterSegmentReceived = 0;
+ size_t nAfterSegmentValidated = 0;
+ shared_ptr<SegmentFetcher> fetcher = SegmentFetcher::start(face, Interest("/hello/world", 1000_s),
+ acceptValidator);
+ connectSignals(fetcher);
+ fetcher->afterSegmentReceived.connect(bind([&nAfterSegmentReceived] { ++nAfterSegmentReceived; }));
+ fetcher->afterSegmentValidated.connect(bind([&nAfterSegmentValidated] { ++nAfterSegmentValidated; }));
advanceClocks(10_ms);
@@ -323,15 +152,38 @@
advanceClocks(10_ms);
BOOST_CHECK_EQUAL(nErrors, 0);
- BOOST_CHECK_EQUAL(nData, 1);
+ BOOST_CHECK_EQUAL(nCompletions, 1);
+ BOOST_CHECK_EQUAL(nAfterSegmentReceived, 401);
+ BOOST_CHECK_EQUAL(nAfterSegmentValidated, 401);
+}
+
+BOOST_FIXTURE_TEST_CASE(MissingSegmentNum, Fixture)
+{
+ DummyValidator acceptValidator;
+ shared_ptr<SegmentFetcher> fetcher = SegmentFetcher::start(face, Interest("/hello/world", 1000_s),
+ acceptValidator);
+ connectSignals(fetcher);
+
+ advanceClocks(10_ms);
+
+ const uint8_t buffer[] = "Hello, world!";
+ auto data = makeData("/hello/world/version0/no-segment");
+ data->setContent(buffer, sizeof(buffer));
+
+ face.receive(*data);
+ advanceClocks(10_ms);
+
+ BOOST_CHECK_EQUAL(nErrors, 1);
+ BOOST_CHECK_EQUAL(lastError, static_cast<uint32_t>(SegmentFetcher::DATA_HAS_NO_SEGMENT));
+ BOOST_CHECK_EQUAL(nCompletions, 0);
}
BOOST_FIXTURE_TEST_CASE(DuplicateNack, Fixture)
{
- SegmentFetcher::fetch(face, Interest("/hello/world", 1000_s),
- make_shared<DummyValidator>(true),
- bind(&Fixture::onComplete, this, _1),
- bind(&Fixture::onError, this, _1));
+ DummyValidator acceptValidator;
+ shared_ptr<SegmentFetcher> fetcher = SegmentFetcher::start(face, Interest("/hello/world", 1000_s),
+ acceptValidator);
+ connectSignals(fetcher);
advanceClocks(10_ms);
// receive nack for the original interest
@@ -348,10 +200,10 @@
BOOST_FIXTURE_TEST_CASE(CongestionNack, Fixture)
{
- SegmentFetcher::fetch(face, Interest("/hello/world", 1000_s),
- make_shared<DummyValidator>(true),
- bind(&Fixture::onComplete, this, _1),
- bind(&Fixture::onError, this, _1));
+ DummyValidator acceptValidator;
+ shared_ptr<SegmentFetcher> fetcher = SegmentFetcher::start(face, Interest("/hello/world", 1000_s),
+ acceptValidator);
+ connectSignals(fetcher);
advanceClocks(10_ms);
// receive nack for the original interest
@@ -371,11 +223,10 @@
int nNacks = 2;
ndn::Name interestName("ndn:/A");
- SegmentFetcher::fetch(face,
- Interest(interestName),
- make_shared<DummyValidator>(true),
- bind(&Fixture::onComplete, this, _1),
- bind(&Fixture::onError, this, _1));
+ DummyValidator acceptValidator;
+ shared_ptr<SegmentFetcher> fetcher = SegmentFetcher::start(face, Interest(interestName),
+ acceptValidator);
+ connectSignals(fetcher);
advanceClocks(1000_ms);
@@ -405,12 +256,12 @@
BOOST_CHECK_EQUAL(face.sentInterests[5].getName(), ndn::Name("ndn:/A/%00%03"));
}
-BOOST_FIXTURE_TEST_CASE(ZeroComponentName, Fixture)
+BOOST_FIXTURE_TEST_CASE(SingleSegment, Fixture)
{
- SegmentFetcher::fetch(face, Interest("ndn:/"),
- make_shared<DummyValidator>(true),
- bind(&Fixture::onComplete, this, _1),
- bind(&Fixture::onError, this, _1));
+ DummyValidator acceptValidator;
+ shared_ptr<SegmentFetcher> fetcher = SegmentFetcher::start(face, Interest("ndn:/", 1000_s),
+ acceptValidator);
+ connectSignals(fetcher);
advanceClocks(10_ms);
nackLastInterest(lp::NackReason::DUPLICATE);
face.receive(*makeDataSegment("/hello/world", 0, true));
@@ -418,22 +269,18 @@
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_REQUIRE_EQUAL(nCompletions, 1);
}
-BOOST_FIXTURE_TEST_CASE(Signals, Fixture)
+BOOST_FIXTURE_TEST_CASE(ValidationFailure, Fixture)
{
DummyValidator validator;
- bool flipResult = false;
- validator.getPolicy().setResultCallback([&flipResult] (const Name&) {
- flipResult = !flipResult;
- return flipResult;
+ validator.getPolicy().setResultCallback([] (const Name& name) {
+ return name.at(-1).toSegment() % 2 == 0;
});
- shared_ptr<SegmentFetcher> fetcher =
- SegmentFetcher::fetch(face, Interest("/hello/world", 1000_s),
- validator,
- bind(&Fixture::onComplete, this, _1),
- bind(&Fixture::onError, this, _1));
+ shared_ptr<SegmentFetcher> fetcher = SegmentFetcher::start(face, Interest("/hello/world", 1000_s),
+ validator);
+ connectSignals(fetcher);
auto data1 = makeDataSegment("/hello/world", 0, false);
auto data2 = makeDataSegment("/hello/world", 1, true);
@@ -463,6 +310,117 @@
BOOST_CHECK_EQUAL(nErrors, 1);
}
+// Tests deprecated `fetch` API that uses callbacks instead of signals. This test case will be
+// removed when this API is removed.
+BOOST_FIXTURE_TEST_CASE(DeprecatedFetch, Fixture)
+{
+ DummyValidator acceptValidator;
+ SegmentFetcher::fetch(face, Interest("/hello/world", 1000_s),
+ acceptValidator,
+ bind(&Fixture::onComplete, this, _1),
+ bind(&Fixture::onError, this, _1));
+
+ advanceClocks(10_ms);
+
+ face.receive(*makeDataSegment("/hello/world/version0", 0, true));
+ advanceClocks(10_ms);
+
+ BOOST_CHECK_EQUAL(nErrors, 0);
+ BOOST_CHECK_EQUAL(nCompletions, 1);
+
+ BOOST_CHECK_EQUAL(dataSize, 14);
+
+ const uint8_t buffer[] = "Hello, world!";
+ std::string bufferString(reinterpret_cast<const char*>(buffer));
+
+ BOOST_CHECK_EQUAL(dataString, bufferString);
+
+ BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 1);
+ 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);
+}
+
+// Tests deprecated `fetch` API that uses callbacks instead of signals (with an accepting shared_ptr
+// Validator). This test case will be removed when this API is removed.
+BOOST_FIXTURE_TEST_CASE(DeprecatedFetchSharedPtrComplete, Fixture)
+{
+ auto acceptValidator = make_shared<DummyValidator>(true);
+ SegmentFetcher::fetch(face, Interest("/hello/world", 1000_s),
+ acceptValidator,
+ bind(&Fixture::onComplete, this, _1),
+ bind(&Fixture::onError, this, _1));
+
+ weak_ptr<DummyValidator> weakValidator = acceptValidator;
+ BOOST_CHECK(!weakValidator.expired());
+ acceptValidator.reset();
+ BOOST_CHECK(!weakValidator.expired());
+
+ advanceClocks(10_ms);
+
+ BOOST_CHECK(!weakValidator.expired());
+ face.receive(*makeDataSegment("/hello/world/version0", 0, true));
+
+ advanceClocks(10_ms);
+
+ BOOST_CHECK(weakValidator.expired());
+ BOOST_CHECK_EQUAL(nErrors, 0);
+ BOOST_CHECK_EQUAL(nCompletions, 1);
+
+ BOOST_CHECK_EQUAL(dataSize, 14);
+
+ const uint8_t buffer[] = "Hello, world!";
+ std::string bufferString(reinterpret_cast<const char*>(buffer));
+
+ BOOST_CHECK_EQUAL(dataString, bufferString);
+
+ BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 1);
+ 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);
+}
+
+// Tests deprecated `fetch` API that uses callbacks instead of signals (with a rejecting shared_ptr
+// Validator). This test case will be removed when this API is removed.
+BOOST_FIXTURE_TEST_CASE(DeprecatedFetchSharedPtrError, Fixture)
+{
+ auto acceptValidator = make_shared<DummyValidator>(false);
+ SegmentFetcher::fetch(face, Interest("/hello/world", 1000_s),
+ acceptValidator,
+ bind(&Fixture::onComplete, this, _1),
+ bind(&Fixture::onError, this, _1));
+
+ weak_ptr<DummyValidator> weakValidator = acceptValidator;
+ BOOST_CHECK(!weakValidator.expired());
+ acceptValidator.reset();
+ BOOST_CHECK(!weakValidator.expired());
+
+ advanceClocks(10_ms);
+
+ BOOST_CHECK(!weakValidator.expired());
+ face.receive(*makeDataSegment("/hello/world/version0", 0, true));
+
+ advanceClocks(10_ms);
+
+ BOOST_CHECK(weakValidator.expired());
+ BOOST_CHECK_EQUAL(nErrors, 1);
+ BOOST_CHECK_EQUAL(nCompletions, 0);
+
+ BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 1);
+ 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);
+}
+
BOOST_AUTO_TEST_SUITE_END() // TestSegmentFetcher
BOOST_AUTO_TEST_SUITE_END() // Util