face: scoped prefix registration
refs #3919
Change-Id: I858bf38000014a295cf853635b9c2a4275267d32
diff --git a/ndn-cxx/detail/cancel-handle.cpp b/ndn-cxx/detail/cancel-handle.cpp
new file mode 100644
index 0000000..604522b
--- /dev/null
+++ b/ndn-cxx/detail/cancel-handle.cpp
@@ -0,0 +1,79 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2013-2019 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "ndn-cxx/detail/cancel-handle.hpp"
+
+namespace ndn {
+namespace detail {
+
+CancelHandle::CancelHandle(function<void()> cancel)
+ : doCancel(std::move(cancel))
+{
+}
+
+void
+CancelHandle::cancel()
+{
+ if (doCancel != nullptr) {
+ doCancel();
+ doCancel = nullptr;
+ }
+}
+
+ScopedCancelHandle::ScopedCancelHandle(CancelHandle hdl)
+ : m_hdl(std::move(hdl))
+{
+}
+
+ScopedCancelHandle::ScopedCancelHandle(ScopedCancelHandle&& other)
+ : m_hdl(other.release())
+{
+}
+
+ScopedCancelHandle&
+ScopedCancelHandle::operator=(ScopedCancelHandle&& other)
+{
+ cancel();
+ m_hdl = other.release();
+ return *this;
+}
+
+ScopedCancelHandle::~ScopedCancelHandle()
+{
+ m_hdl.cancel();
+}
+
+void
+ScopedCancelHandle::cancel()
+{
+ release().cancel();
+}
+
+CancelHandle
+ScopedCancelHandle::release()
+{
+ CancelHandle hdl;
+ std::swap(hdl, m_hdl);
+ return hdl;
+}
+
+} // namespace detail
+} // namespace ndn
diff --git a/ndn-cxx/detail/cancel-handle.hpp b/ndn-cxx/detail/cancel-handle.hpp
new file mode 100644
index 0000000..11af4e4
--- /dev/null
+++ b/ndn-cxx/detail/cancel-handle.hpp
@@ -0,0 +1,101 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2013-2019 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#ifndef NDN_DETAIL_CANCEL_HANDLE_HPP
+#define NDN_DETAIL_CANCEL_HANDLE_HPP
+
+#include "ndn-cxx/detail/common.hpp"
+
+namespace ndn {
+namespace detail {
+
+/** \brief Handle to cancel an operation.
+ */
+class CancelHandle
+{
+public:
+ explicit
+ CancelHandle(function<void()> cancel = nullptr);
+
+ /** \brief Cancel the operation.
+ * \warning Cancelling the same operation more than once, using same or different CancelHandle or
+ * ScopedCancelHandle, may trigger undefined behavior.
+ */
+ void
+ cancel();
+
+protected:
+ function<void()> doCancel;
+};
+
+/** \brief Cancels an operation automatically upon destruction.
+ */
+class ScopedCancelHandle
+{
+public:
+ ScopedCancelHandle() = default;
+
+ /** \brief Implicit constructor from CancelHandle.
+ */
+ ScopedCancelHandle(CancelHandle hdl);
+
+ /** \brief Copy construction is disallowed.
+ */
+ ScopedCancelHandle(const ScopedCancelHandle&) = delete;
+
+ /** \brief Move constructor.
+ */
+ ScopedCancelHandle(ScopedCancelHandle&& other);
+
+ /** \brief Copy assignment is disallowed.
+ */
+ ScopedCancelHandle&
+ operator=(const ScopedCancelHandle&) = delete;
+
+ /** \brief Move assignment operator.
+ */
+ ScopedCancelHandle&
+ operator=(ScopedCancelHandle&& other);
+
+ /** \brief Cancel the operation.
+ */
+ ~ScopedCancelHandle();
+
+ /** \brief Cancel the operation.
+ */
+ void
+ cancel();
+
+ /** \brief Release the operation so that it won't be cancelled when this ScopedCancelHandle is
+ * destructed.
+ * \return the CancelHandle.
+ */
+ CancelHandle
+ release();
+
+private:
+ CancelHandle m_hdl;
+};
+
+} // namespace detail
+} // namespace ndn
+
+#endif // NDN_DETAIL_CANCEL_HANDLE_HPP
diff --git a/ndn-cxx/face.cpp b/ndn-cxx/face.cpp
index c4dc023..4e09421 100644
--- a/ndn-cxx/face.cpp
+++ b/ndn-cxx/face.cpp
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
- * Copyright (c) 2013-2018 Regents of the University of California.
+ * Copyright (c) 2013-2019 Regents of the University of California.
*
* This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
*
@@ -267,7 +267,7 @@
return reinterpret_cast<const InterestFilterId*>(filter.get());
}
-const RegisteredPrefixId*
+RegisteredPrefixHandle
Face::registerPrefix(const Name& prefix,
const RegisterPrefixSuccessCallback& onSuccess,
const RegisterPrefixFailureCallback& onFailure,
@@ -277,7 +277,8 @@
nfd::CommandOptions options;
options.setSigningInfo(signingInfo);
- return m_impl->registerPrefix(prefix, nullptr, onSuccess, onFailure, flags, options);
+ auto id = m_impl->registerPrefix(prefix, nullptr, onSuccess, onFailure, flags, options);
+ return RegisteredPrefixHandle(*this, id);
}
void
@@ -410,4 +411,29 @@
}
}
+RegisteredPrefixHandle::RegisteredPrefixHandle(Face& face, const RegisteredPrefixId* id)
+ : CancelHandle([&face, id] { face.unregisterPrefix(id, nullptr, nullptr); })
+ , m_face(&face)
+ , m_id(id)
+{
+ // The lambda passed to CancelHandle constructor cannot call this->unregister,
+ // because base class destructor cannot access the member fields of this subclass.
+}
+
+void
+RegisteredPrefixHandle::unregister(const UnregisterPrefixSuccessCallback& onSuccess,
+ const UnregisterPrefixFailureCallback& onFailure)
+{
+ if (m_id == nullptr) {
+ if (onFailure != nullptr) {
+ onFailure("RegisteredPrefixHandle is empty");
+ }
+ return;
+ }
+
+ m_face->unregisterPrefix(m_id, onSuccess, onFailure);
+ m_face = nullptr;
+ m_id = nullptr;
+}
+
} // namespace ndn
diff --git a/ndn-cxx/face.hpp b/ndn-cxx/face.hpp
index 434e947..b33abd4 100644
--- a/ndn-cxx/face.hpp
+++ b/ndn-cxx/face.hpp
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
- * Copyright (c) 2013-2018 Regents of the University of California.
+ * Copyright (c) 2013-2019 Regents of the University of California.
*
* This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
*
@@ -26,6 +26,7 @@
#include "ndn-cxx/interest.hpp"
#include "ndn-cxx/interest-filter.hpp"
#include "ndn-cxx/detail/asio-fwd.hpp"
+#include "ndn-cxx/detail/cancel-handle.hpp"
#include "ndn-cxx/encoding/nfd-constants.hpp"
#include "ndn-cxx/lp/nack.hpp"
#include "ndn-cxx/security/key-chain.hpp"
@@ -37,6 +38,7 @@
class PendingInterestId;
class RegisteredPrefixId;
+class RegisteredPrefixHandle;
class InterestFilterId;
namespace nfd {
@@ -345,7 +347,7 @@
* @return The registered prefix ID which can be used with unregisterPrefix
* @see nfd::RouteFlags
*/
- const RegisteredPrefixId*
+ RegisteredPrefixHandle
registerPrefix(const Name& prefix,
const RegisterPrefixSuccessCallback& onSuccess,
const RegisterPrefixFailureCallback& onFailure,
@@ -533,6 +535,57 @@
shared_ptr<Impl> m_impl;
};
+/** \brief A handle of registered prefix.
+ */
+class RegisteredPrefixHandle : public detail::CancelHandle
+{
+public:
+ RegisteredPrefixHandle() = default;
+
+ RegisteredPrefixHandle(Face& face, const RegisteredPrefixId* id);
+
+ operator const RegisteredPrefixId*() const
+ {
+ return m_id;
+ }
+
+ /** \brief Unregister the prefix.
+ * \warning Unregistering the same prefix more than once, using same or different
+ * RegisteredPrefixHandle or ScopedRegisteredPrefixHandle, may trigger undefined
+ * behavior.
+ * \warning Unregistering a prefix after the face has been destructed may trigger undefined
+ * behavior.
+ */
+ void
+ unregister(const UnregisterPrefixSuccessCallback& onSuccess = nullptr,
+ const UnregisterPrefixFailureCallback& onFailure = nullptr);
+
+private:
+ Face* m_face = nullptr;
+ const RegisteredPrefixId* m_id = nullptr;
+};
+
+/** \brief A scoped handle of registered prefix.
+ *
+ * Upon destruction of this handle, the prefix is unregistered automatically.
+ * Most commonly, the application keeps a ScopedRegisteredPrefixHandle as a class member field,
+ * so that it can cleanup its prefix registration when the class instance is destructed.
+ * The application will not be notified whether the unregistration was successful.
+ *
+ * \code
+ * {
+ * ScopedRegisteredPrefixHandle hdl = face.registerPrefix(prefix, onSuccess, onFailure);
+ * } // hdl goes out of scope, unregistering the prefix
+ * \endcode
+ *
+ * \warning Unregistering the same prefix more than once, using same or different
+ * RegisteredPrefixHandle or ScopedRegisteredPrefixHandle, may trigger undefined
+ * behavior.
+ * \warning Unregistering a prefix after the face has been destructed may trigger undefined
+ * behavior.
+ */
+using ScopedRegisteredPrefixHandle = detail::ScopedCancelHandle;
+
} // namespace ndn
#endif // NDN_FACE_HPP
diff --git a/ndn-cxx/mgmt/dispatcher.cpp b/ndn-cxx/mgmt/dispatcher.cpp
index d17735f..2c33ef9 100644
--- a/ndn-cxx/mgmt/dispatcher.cpp
+++ b/ndn-cxx/mgmt/dispatcher.cpp
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
- * Copyright (c) 2013-2018 Regents of the University of California.
+ * Copyright (c) 2013-2019 Regents of the University of California.
*
* This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
*
@@ -103,8 +103,8 @@
}
const TopPrefixEntry& topPrefixEntry = it->second;
- if (topPrefixEntry.registeredPrefixId) {
- m_face.unregisterPrefix(*topPrefixEntry.registeredPrefixId, nullptr, nullptr);
+ if (topPrefixEntry.registeredPrefixId != nullptr) {
+ m_face.unregisterPrefix(topPrefixEntry.registeredPrefixId, nullptr, nullptr);
}
for (const auto& filter : topPrefixEntry.interestFilters) {
m_face.unsetInterestFilter(filter);
diff --git a/ndn-cxx/mgmt/dispatcher.hpp b/ndn-cxx/mgmt/dispatcher.hpp
index 2ec308b..ab96c00 100644
--- a/ndn-cxx/mgmt/dispatcher.hpp
+++ b/ndn-cxx/mgmt/dispatcher.hpp
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
- * Copyright (c) 2013-2018 Regents of the University of California.
+ * Copyright (c) 2013-2019 Regents of the University of California.
*
* This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
*
@@ -440,7 +440,7 @@
struct TopPrefixEntry
{
Name topPrefix;
- optional<const RegisteredPrefixId*> registeredPrefixId;
+ const RegisteredPrefixId* registeredPrefixId = nullptr;
std::vector<const InterestFilterId*> interestFilters;
};
std::unordered_map<Name, TopPrefixEntry> m_topLevelPrefixes;
diff --git a/tests/unit/detail/cancel-handle.t.cpp b/tests/unit/detail/cancel-handle.t.cpp
new file mode 100644
index 0000000..b87f9cd
--- /dev/null
+++ b/tests/unit/detail/cancel-handle.t.cpp
@@ -0,0 +1,137 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2013-2019 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "ndn-cxx/detail/cancel-handle.hpp"
+
+#include "tests/boost-test.hpp"
+
+namespace ndn {
+namespace detail {
+namespace tests {
+
+BOOST_AUTO_TEST_SUITE(Detail)
+BOOST_AUTO_TEST_SUITE(TestCancelHandle)
+
+static CancelHandle
+makeDummyCancelHandle(int& nCancels)
+{
+ return CancelHandle([&] { ++nCancels; });
+}
+
+BOOST_AUTO_TEST_SUITE(PlainHandle)
+
+BOOST_AUTO_TEST_CASE(ManualCancel)
+{
+ int nCancels = 0;
+ auto hdl = makeDummyCancelHandle(nCancels);
+ BOOST_CHECK_EQUAL(nCancels, 0);
+
+ hdl.cancel();
+ BOOST_CHECK_EQUAL(nCancels, 1);
+
+ hdl = CancelHandle();
+ BOOST_CHECK_EQUAL(nCancels, 1);
+}
+
+BOOST_AUTO_TEST_SUITE_END() // PlainHandle
+
+BOOST_AUTO_TEST_SUITE(ScopedHandle)
+
+BOOST_AUTO_TEST_CASE(ManualCancel)
+{
+ int nCancels = 0;
+ {
+ ScopedCancelHandle hdl = makeDummyCancelHandle(nCancels);
+ BOOST_CHECK_EQUAL(nCancels, 0);
+
+ hdl.cancel();
+ BOOST_CHECK_EQUAL(nCancels, 1);
+ } // hdl goes out of scope
+ BOOST_CHECK_EQUAL(nCancels, 1);
+}
+
+BOOST_AUTO_TEST_CASE(Destruct)
+{
+ int nCancels = 0;
+ {
+ ScopedCancelHandle hdl = makeDummyCancelHandle(nCancels);
+ BOOST_CHECK_EQUAL(nCancels, 0);
+ } // hdl goes out of scope
+ BOOST_CHECK_EQUAL(nCancels, 1);
+}
+
+BOOST_AUTO_TEST_CASE(Assign)
+{
+ int nCancels1 = 0, nCancels2 = 0;
+ {
+ ScopedCancelHandle hdl = makeDummyCancelHandle(nCancels1);
+ hdl = makeDummyCancelHandle(nCancels2);
+ BOOST_CHECK_EQUAL(nCancels1, 1);
+ BOOST_CHECK_EQUAL(nCancels2, 0);
+ } // hdl goes out of scope
+ BOOST_CHECK_EQUAL(nCancels2, 1);
+}
+
+BOOST_AUTO_TEST_CASE(Release)
+{
+ int nCancels = 0;
+ {
+ ScopedCancelHandle hdl = makeDummyCancelHandle(nCancels);
+ hdl.release();
+ hdl.cancel(); // no effect
+ } // hdl goes out of scope
+ BOOST_CHECK_EQUAL(nCancels, 0);
+}
+
+BOOST_AUTO_TEST_CASE(MoveConstruct)
+{
+ int nCancels = 0;
+ unique_ptr<ScopedCancelHandle> hdl1;
+ {
+ ScopedCancelHandle hdl2 = makeDummyCancelHandle(nCancels);
+ hdl1 = make_unique<ScopedCancelHandle>(std::move(hdl2));
+ } // hdl2 goes out of scope
+ BOOST_CHECK_EQUAL(nCancels, 0);
+ hdl1.reset();
+ BOOST_CHECK_EQUAL(nCancels, 1);
+}
+
+BOOST_AUTO_TEST_CASE(MoveAssign)
+{
+ int nCancels = 0;
+ {
+ ScopedCancelHandle hdl1;
+ {
+ ScopedCancelHandle hdl2 = makeDummyCancelHandle(nCancels);
+ hdl1 = std::move(hdl2);
+ } // hdl2 goes out of scope
+ BOOST_CHECK_EQUAL(nCancels, 0);
+ } // hdl1 goes out of scope
+ BOOST_CHECK_EQUAL(nCancels, 1);
+}
+
+BOOST_AUTO_TEST_SUITE_END() // ScopedHandle
+BOOST_AUTO_TEST_SUITE_END() // TestCancelHandle
+BOOST_AUTO_TEST_SUITE_END() // Detail
+
+} // namespace tests
+} // namespace detail
+} // namespace ndn
diff --git a/tests/unit/face.t.cpp b/tests/unit/face.t.cpp
index 6f7bb17..c9b8205 100644
--- a/tests/unit/face.t.cpp
+++ b/tests/unit/face.t.cpp
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
- * Copyright (c) 2013-2018 Regents of the University of California.
+ * Copyright (c) 2013-2019 Regents of the University of California.
*
* This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
*
@@ -30,34 +30,63 @@
#include "tests/make-interest-data.hpp"
#include "tests/unit/identity-management-time-fixture.hpp"
+#include <boost/logic/tribool.hpp>
+
namespace ndn {
namespace tests {
using ndn::util::DummyClientFace;
+struct WantPrefixRegReply;
+struct NoPrefixRegReply;
+
+template<typename PrefixRegReply = WantPrefixRegReply>
class FaceFixture : public IdentityManagementTimeFixture
{
public:
- explicit
- FaceFixture(bool enableRegistrationReply = true)
- : face(io, m_keyChain, {true, enableRegistrationReply})
+ FaceFixture()
+ : face(io, m_keyChain, {true, !std::is_same<PrefixRegReply, NoPrefixRegReply>::value})
{
+ static_assert(std::is_same<PrefixRegReply, WantPrefixRegReply>::value ||
+ std::is_same<PrefixRegReply, NoPrefixRegReply>::value, "");
+ }
+
+ /** \brief Execute a prefix registration, and optionally check the name in callback.
+ * \return whether the prefix registration succeeded.
+ */
+ bool
+ runPrefixReg(function<void(const RegisterPrefixSuccessCallback& success,
+ const RegisterPrefixFailureCallback& failure)> f)
+ {
+ boost::logic::tribool result = boost::logic::indeterminate;
+ f([&] (const Name&) { result = true; },
+ [&] (const Name&, const std::string&) { result = false; });
+
+ advanceClocks(1_ms);
+ BOOST_REQUIRE(!boost::logic::indeterminate(result));
+ return static_cast<bool>(result);
+ }
+
+ /** \brief Execute a prefix unregistration, and optionally check the name in callback.
+ * \return whether the prefix unregistration succeeded.
+ */
+ bool
+ runPrefixUnreg(function<void(const UnregisterPrefixSuccessCallback& success,
+ const UnregisterPrefixFailureCallback& failure)> f)
+ {
+ boost::logic::tribool result = boost::logic::indeterminate;
+ f([&] { result = true; }, [&] (const std::string&) { result = false; });
+
+ advanceClocks(1_ms);
+ BOOST_REQUIRE(!boost::logic::indeterminate(result));
+ return static_cast<bool>(result);
}
public:
DummyClientFace face;
};
-class FacesNoRegistrationReplyFixture : public FaceFixture
-{
-public:
- FacesNoRegistrationReplyFixture()
- : FaceFixture(false)
- {
- }
-};
-
-BOOST_FIXTURE_TEST_SUITE(TestFace, FaceFixture)
+BOOST_FIXTURE_TEST_SUITE(TestFace, FaceFixture<>)
BOOST_AUTO_TEST_SUITE(Consumer)
@@ -572,7 +601,7 @@
advanceClocks(25_ms, 4);
}
-BOOST_FIXTURE_TEST_CASE(SetInterestFilterFail, FacesNoRegistrationReplyFixture)
+BOOST_FIXTURE_TEST_CASE(SetInterestFilterFail, FaceFixture<NoPrefixRegReply>)
{
// don't enable registration reply
size_t nRegFailed = 0;
@@ -588,7 +617,7 @@
BOOST_CHECK_EQUAL(nRegFailed, 1);
}
-BOOST_FIXTURE_TEST_CASE(SetInterestFilterFailWithoutSuccessCallback, FacesNoRegistrationReplyFixture)
+BOOST_FIXTURE_TEST_CASE(SetInterestFilterFailWithoutSuccessCallback, FaceFixture<NoPrefixRegReply>)
{
// don't enable registration reply
size_t nRegFailed = 0;
@@ -603,36 +632,40 @@
BOOST_CHECK_EQUAL(nRegFailed, 1);
}
-BOOST_AUTO_TEST_CASE(RegisterUnregisterPrefix)
+BOOST_AUTO_TEST_CASE(RegisterUnregisterPrefixFunc)
{
- size_t nRegSuccesses = 0;
- const RegisteredPrefixId* regPrefixId =
- face.registerPrefix("/Hello/World",
- bind([&nRegSuccesses] { ++nRegSuccesses; }),
- bind([] { BOOST_FAIL("Unexpected registerPrefix failure"); }));
+ const RegisteredPrefixId* regPrefixId = nullptr;
+ BOOST_CHECK(runPrefixReg([&] (const auto& success, const auto& failure) {
+ regPrefixId = face.registerPrefix("/Hello/World", success, failure);
+ }));
- advanceClocks(25_ms, 4);
- BOOST_CHECK_EQUAL(nRegSuccesses, 1);
-
- size_t nUnregSuccesses = 0;
- face.unregisterPrefix(regPrefixId,
- bind([&nUnregSuccesses] { ++nUnregSuccesses; }),
- bind([] { BOOST_FAIL("Unexpected unregisterPrefix failure"); }));
-
- advanceClocks(25_ms, 4);
- BOOST_CHECK_EQUAL(nUnregSuccesses, 1);
+ BOOST_CHECK(runPrefixUnreg([&] (const auto& success, const auto& failure) {
+ face.unregisterPrefix(regPrefixId, success, failure);
+ }));
}
-BOOST_FIXTURE_TEST_CASE(RegisterUnregisterPrefixFail, FacesNoRegistrationReplyFixture)
+BOOST_FIXTURE_TEST_CASE(RegisterUnregisterPrefixFail, FaceFixture<NoPrefixRegReply>)
{
- // don't enable registration reply
- size_t nRegFailures = 0;
- face.registerPrefix("/Hello/World",
- bind([] { BOOST_FAIL("Unexpected registerPrefix success"); }),
- bind([&nRegFailures] { ++nRegFailures; }));
+ BOOST_CHECK(!runPrefixReg([&] (const auto& success, const auto& failure) {
+ face.registerPrefix("/Hello/World", success, failure);
+ this->advanceClocks(5_s, 20); // wait for command timeout
+ }));
+}
+BOOST_AUTO_TEST_CASE(RegisterUnregisterPrefixHandle)
+{
+ RegisteredPrefixHandle hdl;
+ BOOST_CHECK(!runPrefixUnreg([&] (const auto& success, const auto& failure) {
+ // despite the "undefined behavior" warning, we try not to crash, but no API guarantee for this
+ hdl.unregister(success, failure);
+ }));
- advanceClocks(5000_ms, 20);
- BOOST_CHECK_EQUAL(nRegFailures, 1);
+ BOOST_CHECK(runPrefixReg([&] (const auto& success, const auto& failure) {
+ hdl = face.registerPrefix("/Hello/World", success, failure);
+ }));
+
+ BOOST_CHECK(runPrefixUnreg([&] (const auto& success, const auto& failure) {
+ hdl.unregister(success, failure);
+ }));
}
BOOST_AUTO_TEST_CASE(SimilarFilters)
@@ -729,7 +762,7 @@
BOOST_CHECK_EQUAL(nInInterests, 2);
}
-BOOST_FIXTURE_TEST_CASE(SetInterestFilterNoReg, FacesNoRegistrationReplyFixture) // Bug 2318
+BOOST_FIXTURE_TEST_CASE(SetInterestFilterNoReg, FaceFixture<NoPrefixRegReply>) // Bug 2318
{
// This behavior is specific to DummyClientFace.
// Regular Face won't accept incoming packets until something is sent.