logic: Don't shutdown face when destructing Logic instance
refs: #4525
Change-Id: I3a50b818c6553d08fc807869107e53f55775c43d
diff --git a/tests/unit-tests/dummy-forwarder.cpp b/tests/unit-tests/dummy-forwarder.cpp
index 224dcd3..45a8cd6 100644
--- a/tests/unit-tests/dummy-forwarder.cpp
+++ b/tests/unit-tests/dummy-forwarder.cpp
@@ -1,6 +1,6 @@
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil -*- */
/*
- * Copyright (c) 2012-2017 University of California, Los Angeles
+ * Copyright (c) 2012-2018 University of California, Los Angeles
*
* This file is part of ChronoSync, synchronization library for distributed realtime
* applications for NDN.
@@ -35,29 +35,30 @@
{
auto face = std::make_shared<util::DummyClientFace>(m_io, m_keyChain,
util::DummyClientFace::Options{true, true});
- face->onSendInterest.connect([this, face] (const Interest& interest) {
+ util::DummyClientFace* self = &*face; // to prevent memory leak
+ face->onSendInterest.connect([this, self] (const Interest& interest) {
Interest i(interest);
for (auto& otherFace : m_faces) {
- if (&*face == &*otherFace) {
+ if (self == &*otherFace) {
continue;
}
m_io.post([=] { otherFace->receive(i); });
}
});
- face->onSendData.connect([this, face] (const Data& data) {
+ face->onSendData.connect([this, self] (const Data& data) {
Data d(data);
for (auto& otherFace : m_faces) {
- if (&*face == &*otherFace) {
+ if (self == &*otherFace) {
continue;
}
m_io.post([=] { otherFace->receive(d); });
}
});
- face->onSendNack.connect([this, face] (const lp::Nack& nack) {
+ face->onSendNack.connect([this, self] (const lp::Nack& nack) {
lp::Nack n(nack);
for (auto& otherFace : m_faces) {
- if (&*face == &*otherFace) {
+ if (self == &*otherFace) {
continue;
}
m_io.post([=] { otherFace->receive(n); });
@@ -68,5 +69,11 @@
return *face;
}
+void
+DummyForwarder::removeFaces()
+{
+ m_faces.clear();
+}
+
} // namespace chronosync
} // namespace ndn
diff --git a/tests/unit-tests/dummy-forwarder.hpp b/tests/unit-tests/dummy-forwarder.hpp
index 3e7d9b3..7965338 100644
--- a/tests/unit-tests/dummy-forwarder.hpp
+++ b/tests/unit-tests/dummy-forwarder.hpp
@@ -1,6 +1,6 @@
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil -*- */
/*
- * Copyright (c) 2012-2017 University of California, Los Angeles
+ * Copyright (c) 2012-2018 University of California, Los Angeles
*
* This file is part of ChronoSync, synchronization library for distributed realtime
* applications for NDN.
@@ -49,6 +49,9 @@
return *m_faces.at(nFace);
}
+ void
+ removeFaces();
+
private:
boost::asio::io_service& m_io;
KeyChain& m_keyChain;
diff --git a/tests/unit-tests/test-logic.cpp b/tests/unit-tests/test-logic.cpp
index 83e8708..dafc00b 100644
--- a/tests/unit-tests/test-logic.cpp
+++ b/tests/unit-tests/test-logic.cpp
@@ -114,10 +114,10 @@
BOOST_AUTO_TEST_CASE(TwoBasic)
{
- handler[0] = make_shared<Handler>(ref(fw.addFace()), syncPrefix, userPrefix[0]);
+ handler[0] = make_shared<Handler>(fw.addFace(), syncPrefix, userPrefix[0]);
advanceClocks(ndn::time::milliseconds(10), 100);
- handler[1] = make_shared<Handler>(ref(fw.addFace()), syncPrefix, userPrefix[1]);
+ handler[1] = make_shared<Handler>(fw.addFace(), syncPrefix, userPrefix[1]);
advanceClocks(ndn::time::milliseconds(10), 100);
handler[0]->updateSeqNo(1);
@@ -141,13 +141,13 @@
BOOST_AUTO_TEST_CASE(ThreeBasic)
{
- handler[0] = make_shared<Handler>(ref(fw.addFace()), syncPrefix, userPrefix[0]);
+ handler[0] = make_shared<Handler>(fw.addFace(), syncPrefix, userPrefix[0]);
advanceClocks(ndn::time::milliseconds(10), 100);
- handler[1] = make_shared<Handler>(ref(fw.addFace()), syncPrefix, userPrefix[1]);
+ handler[1] = make_shared<Handler>(fw.addFace(), syncPrefix, userPrefix[1]);
advanceClocks(ndn::time::milliseconds(10), 100);
- handler[2] = make_shared<Handler>(ref(fw.addFace()), syncPrefix, userPrefix[2]);
+ handler[2] = make_shared<Handler>(fw.addFace(), syncPrefix, userPrefix[2]);
advanceClocks(ndn::time::milliseconds(10), 100);
handler[0]->updateSeqNo(1);
@@ -171,10 +171,10 @@
BOOST_AUTO_TEST_CASE(ResetRecover)
{
- handler[0] = make_shared<Handler>(ref(fw.addFace()), syncPrefix, userPrefix[0]);
+ handler[0] = make_shared<Handler>(fw.addFace(), syncPrefix, userPrefix[0]);
advanceClocks(ndn::time::milliseconds(10), 100);
- handler[1] = make_shared<Handler>(ref(fw.addFace()), syncPrefix, userPrefix[1]);
+ handler[1] = make_shared<Handler>(fw.addFace(), syncPrefix, userPrefix[1]);
advanceClocks(ndn::time::milliseconds(10), 100);
handler[0]->updateSeqNo(1);
@@ -188,7 +188,7 @@
BOOST_CHECK_EQUAL(handler[0]->map[handler[1]->logic.getSessionName()], 2);
advanceClocks(ndn::time::milliseconds(10), 100);
- handler[2] = make_shared<Handler>(ref(fw.addFace()), syncPrefix, userPrefix[2]);
+ handler[2] = make_shared<Handler>(fw.addFace(), syncPrefix, userPrefix[2]);
advanceClocks(ndn::time::milliseconds(10), 100);
BOOST_CHECK_EQUAL(handler[2]->map[handler[0]->logic.getSessionName()], 1);
@@ -203,13 +203,13 @@
BOOST_AUTO_TEST_CASE(RecoverConflict)
{
- handler[0] = make_shared<Handler>(ref(fw.addFace()), syncPrefix, userPrefix[0]);
+ handler[0] = make_shared<Handler>(fw.addFace(), syncPrefix, userPrefix[0]);
advanceClocks(ndn::time::milliseconds(10), 100);
- handler[1] = make_shared<Handler>(ref(fw.addFace()), syncPrefix, userPrefix[1]);
+ handler[1] = make_shared<Handler>(fw.addFace(), syncPrefix, userPrefix[1]);
advanceClocks(ndn::time::milliseconds(10), 100);
- handler[2] = make_shared<Handler>(ref(fw.addFace()), syncPrefix, userPrefix[2]);
+ handler[2] = make_shared<Handler>(fw.addFace(), syncPrefix, userPrefix[2]);
advanceClocks(ndn::time::milliseconds(10), 100);
handler[0]->updateSeqNo(1);
@@ -230,16 +230,16 @@
BOOST_AUTO_TEST_CASE(PartitionRecover)
{
- handler[0] = make_shared<Handler>(ref(fw.addFace()), syncPrefix, userPrefix[0]);
+ handler[0] = make_shared<Handler>(fw.addFace(), syncPrefix, userPrefix[0]);
advanceClocks(ndn::time::milliseconds(10), 100);
- handler[1] = make_shared<Handler>(ref(fw.addFace()), syncPrefix, userPrefix[1]);
+ handler[1] = make_shared<Handler>(fw.addFace(), syncPrefix, userPrefix[1]);
advanceClocks(ndn::time::milliseconds(10), 100);
- handler[2] = make_shared<Handler>(ref(fw.addFace()), syncPrefix, userPrefix[2]);
+ handler[2] = make_shared<Handler>(fw.addFace(), syncPrefix, userPrefix[2]);
advanceClocks(ndn::time::milliseconds(10), 100);
- handler[3] = make_shared<Handler>(ref(fw.addFace()), syncPrefix, userPrefix[3]);
+ handler[3] = make_shared<Handler>(fw.addFace(), syncPrefix, userPrefix[3]);
advanceClocks(ndn::time::milliseconds(10), 100);
handler[0]->updateSeqNo(1);
@@ -291,10 +291,10 @@
BOOST_AUTO_TEST_CASE(MultipleUserUnderOneLogic)
{
- handler[0] = make_shared<Handler>(ref(fw.addFace()), syncPrefix, userPrefix[0]);
+ handler[0] = make_shared<Handler>(fw.addFace(), syncPrefix, userPrefix[0]);
advanceClocks(ndn::time::milliseconds(10), 100);
- handler[1] = make_shared<Handler>(ref(fw.addFace()), syncPrefix, userPrefix[2]);
+ handler[1] = make_shared<Handler>(fw.addFace(), syncPrefix, userPrefix[2]);
advanceClocks(ndn::time::milliseconds(10), 100);
handler[0]->logic.addUserNode(userPrefix[1]);
@@ -322,6 +322,58 @@
BOOST_CHECK_EQUAL(handler[1]->logic.getSessionNames().size(), 2);
}
+BOOST_AUTO_TEST_CASE(CancelOutstandingEvents)
+{
+ auto h1 = make_shared<Handler>(fw.addFace(), syncPrefix, userPrefix[0]);
+ advanceClocks(ndn::time::milliseconds(10), 100);
+
+ auto h2 = make_shared<Handler>(fw.addFace(), syncPrefix, userPrefix[1]);
+ advanceClocks(ndn::time::milliseconds(10), 100);
+
+ h1->updateSeqNo(1);
+
+ advanceClocks(ndn::time::milliseconds(10), 100);
+ BOOST_CHECK_EQUAL(h2->map[h1->logic.getSessionName()], 1);
+
+ h2->updateSeqNo(2);
+
+ advanceClocks(ndn::time::milliseconds(10), 100);
+ BOOST_CHECK_EQUAL(h1->map[h2->logic.getSessionName()], 2);
+
+ advanceClocks(ndn::time::milliseconds(10), 100);
+ auto h3 = make_shared<Handler>(fw.addFace(), syncPrefix, userPrefix[2]);
+ // Bringing this handler online later causes recovery interests to
+ // be sent -- h3 has no record of any digests
+
+ advanceClocks(ndn::time::milliseconds(10), 100);
+ BOOST_CHECK_EQUAL(h3->map[h1->logic.getSessionName()], 1);
+ BOOST_CHECK_EQUAL(h3->map[h2->logic.getSessionName()], 2);
+
+ h3->updateSeqNo(4);
+
+ advanceClocks(ndn::time::milliseconds(10), 100);
+ BOOST_CHECK_EQUAL(h2->map[h3->logic.getSessionName()], 4);
+ BOOST_CHECK_EQUAL(h1->map[h3->logic.getSessionName()], 4);
+
+ h1.reset();
+
+ BOOST_CHECK_NE(io.poll(), 0); // some cancel events handlers are expected
+ advanceClocks(ndn::time::minutes(1), 60); // should not crash
+
+ h2.reset();
+ h3.reset();
+
+ BOOST_CHECK_NE(io.poll(), 0); // some cancel events handlers are expected
+ fw.removeFaces();
+ while (io.poll() != 0); // execute all other ready events that may have been scheduled
+
+ steadyClock->advance(ndn::time::hours(1));
+ systemClock->advance(ndn::time::hours(1));
+
+ BOOST_CHECK_EQUAL(io.poll(), 0); // no delayed handlers are expected
+ BOOST_CHECK_EQUAL(io.stopped(), true); // io_service expected to be stopped
+}
+
BOOST_FIXTURE_TEST_CASE(TrimState, ndn::tests::IdentityManagementTimeFixture)
{
Name syncPrefix("/ndn/broadcast/sync");