logic: allow manipulating multiple nodes in single logic
Change-Id: Iaa2a2b08e891d41c9aa71c13ffc531bef406b6d8
diff --git a/src/logic.cpp b/src/logic.cpp
index 4c3fc55..08ed60e 100644
--- a/src/logic.cpp
+++ b/src/logic.cpp
@@ -50,6 +50,7 @@
#endif
const ndn::Name Logic::DEFAULT_NAME;
+const ndn::Name Logic::EMPTY_NAME;
const ndn::shared_ptr<ndn::Validator> Logic::DEFAULT_VALIDATOR;
const time::steady_clock::Duration Logic::DEFAULT_RESET_TIMER = time::seconds(0);
const time::steady_clock::Duration Logic::DEFAULT_CANCEL_RESET_TIMER = time::milliseconds(500);
@@ -62,9 +63,9 @@
Logic::Logic(ndn::Face& face,
const Name& syncPrefix,
- const Name& userPrefix,
+ const Name& defaultUserPrefix,
const UpdateCallback& onUpdate,
- const Name& signingId,
+ const Name& defaultSigningId,
ndn::shared_ptr<ndn::Validator> validator,
const time::steady_clock::Duration& resetTimer,
const time::steady_clock::Duration& cancelResetTimer,
@@ -73,7 +74,7 @@
const time::milliseconds& syncReplyFreshness)
: m_face(face)
, m_syncPrefix(syncPrefix)
- , m_userPrefix(userPrefix)
+ , m_defaultUserPrefix(defaultUserPrefix)
, m_interestTable(m_face.getIoService())
, m_outstandingInterestId(0)
, m_isInReset(false)
@@ -88,7 +89,7 @@
, m_resetInterestLifetime(resetInterestLifetime)
, m_syncInterestLifetime(syncInterestLifetime)
, m_syncReplyFreshness(syncReplyFreshness)
- , m_signingId(signingId)
+ , m_defaultSigningId(defaultSigningId)
, m_validator(validator)
{
#ifdef _DEBUG
@@ -97,6 +98,9 @@
_LOG_DEBUG_ID(">> Logic::Logic");
+ addUserNode(m_defaultUserPrefix, m_defaultSigningId);
+
+
m_syncReset = m_syncPrefix;
m_syncReset.append("reset");
@@ -106,7 +110,6 @@
bind(&Logic::onSyncInterest, this, _1, _2),
bind(&Logic::onSyncRegisterFailed, this, _1, _2));
- setUserPrefix(m_userPrefix);
_LOG_DEBUG_ID("<< Logic::Logic");
}
@@ -144,56 +147,132 @@
}
void
-Logic::setUserPrefix(const Name& userPrefix)
+Logic::setDefaultUserPrefix(const Name& defaultUserPrefix)
{
- m_userPrefix = userPrefix;
-
- m_sessionName = m_userPrefix;
- m_sessionName.appendNumber(ndn::time::toUnixTimestamp(ndn::time::system_clock::now()).count());
-
- m_seqNo = 0;
-
- reset();
+ if (defaultUserPrefix != EMPTY_NAME) {
+ if (m_nodeList.find(defaultUserPrefix) != m_nodeList.end()) {
+ m_defaultUserPrefix = defaultUserPrefix;
+ m_defaultSigningId = m_nodeList[defaultUserPrefix].signingId;
+ }
+ }
}
void
-Logic::updateSeqNo(const SeqNo& seqNo)
+Logic::addUserNode(const Name& userPrefix, const Name& signingId)
{
- _LOG_DEBUG_ID(">> Logic::updateSeqNo");
- _LOG_DEBUG_ID("seqNo: " << seqNo << " m_seqNo: " << m_seqNo);
- if (seqNo < m_seqNo || seqNo == 0)
+ if (userPrefix == EMPTY_NAME)
return;
+ if (m_defaultUserPrefix == EMPTY_NAME) {
+ m_defaultUserPrefix = userPrefix;
+ m_defaultSigningId = signingId;
+ }
+ if (m_nodeList.find(userPrefix) == m_nodeList.end()) {
+ m_nodeList[userPrefix].userPrefix = userPrefix;
+ m_nodeList[userPrefix].signingId = signingId;
+ Name sessionName = userPrefix;
+ sessionName.appendNumber(ndn::time::toUnixTimestamp(ndn::time::system_clock::now()).count());
+ m_nodeList[userPrefix].sessionName = sessionName;
+ m_nodeList[userPrefix].seqNo = 0;
+ reset();
+ }
+}
- m_seqNo = seqNo;
-
- _LOG_DEBUG_ID("updateSeqNo: m_seqNo " << m_seqNo);
-
- if (!m_isInReset) {
- _LOG_DEBUG_ID("updateSeqNo: not in Reset ");
- ndn::ConstBufferPtr previousRoot = m_state.getRootDigest();
- {
- using namespace CryptoPP;
-
- std::string hash;
- StringSource(previousRoot->buf(), previousRoot->size(), true,
- new HexEncoder(new StringSink(hash), false));
- _LOG_DEBUG_ID("Hash: " << hash);
+void
+Logic::removeUserNode(const Name& userPrefix)
+{
+ auto userNode = m_nodeList.find(userPrefix);
+ if (userNode != m_nodeList.end()) {
+ m_nodeList.erase(userNode);
+ if (m_defaultUserPrefix == userPrefix) {
+ if (!m_nodeList.empty()) {
+ m_defaultUserPrefix = m_nodeList.begin()->second.userPrefix;
+ m_defaultSigningId = m_nodeList.begin()->second.signingId;
+ }
+ else {
+ m_defaultUserPrefix = EMPTY_NAME;
+ m_defaultSigningId = DEFAULT_NAME;
+ }
}
+ reset();
+ }
+}
- bool isInserted = false;
- bool isUpdated = false;
- SeqNo oldSeq;
- boost::tie(isInserted, isUpdated, oldSeq) = m_state.update(m_sessionName, seqNo);
+const Name&
+Logic::getSessionName(Name prefix)
+{
+ if (prefix == EMPTY_NAME)
+ prefix = m_defaultUserPrefix;
+ auto node = m_nodeList.find(prefix);
+ if (node != m_nodeList.end())
+ return node->second.sessionName;
+ else
+ throw Error("Refer to non-existent node:" + prefix.toUri());
+}
- _LOG_DEBUG_ID("Insert: " << std::boolalpha << isInserted);
- _LOG_DEBUG_ID("Updated: " << std::boolalpha << isUpdated);
- if (isInserted || isUpdated) {
- DiffStatePtr commit = make_shared<DiffState>();
- commit->update(m_sessionName, seqNo);
- commit->setRootDigest(m_state.getRootDigest());
- insertToDiffLog(commit, previousRoot);
+const SeqNo&
+Logic::getSeqNo(Name prefix)
+{
+ if (prefix == EMPTY_NAME)
+ prefix = m_defaultUserPrefix;
+ auto node = m_nodeList.find(prefix);
+ if (node != m_nodeList.end())
+ return node->second.seqNo;
+ else
+ throw Logic::Error("Refer to non-existent node:" + prefix.toUri());
- satisfyPendingSyncInterests(commit);
+}
+
+void
+Logic::updateSeqNo(const SeqNo& seqNo, const Name &updatePrefix)
+{
+ Name prefix;
+ if (updatePrefix == EMPTY_NAME) {
+ if (m_defaultUserPrefix == EMPTY_NAME)
+ return;
+ prefix = m_defaultUserPrefix;
+ }
+ else
+ prefix = updatePrefix;
+
+ auto it = m_nodeList.find(prefix);
+ if (it != m_nodeList.end()) {
+ NodeInfo& node = it->second;
+ _LOG_DEBUG_ID(">> Logic::updateSeqNo");
+ _LOG_DEBUG_ID("seqNo: " << seqNo << " m_seqNo: " << node.seqNo);
+ if (seqNo < node.seqNo || seqNo == 0)
+ return;
+
+ node.seqNo = seqNo;
+ _LOG_DEBUG_ID("updateSeqNo: m_seqNo " << node.seqNo);
+
+ if (!m_isInReset) {
+ _LOG_DEBUG_ID("updateSeqNo: not in Reset ");
+ ndn::ConstBufferPtr previousRoot = m_state.getRootDigest();
+ {
+ using namespace CryptoPP;
+
+ std::string hash;
+ StringSource(previousRoot->buf(), previousRoot->size(), true,
+ new HexEncoder(new StringSink(hash), false));
+ _LOG_DEBUG_ID("Hash: " << hash);
+ }
+
+ bool isInserted = false;
+ bool isUpdated = false;
+ SeqNo oldSeq;
+ boost::tie(isInserted, isUpdated, oldSeq) = m_state.update(node.sessionName,
+ node.seqNo);
+
+ _LOG_DEBUG_ID("Insert: " << std::boolalpha << isInserted);
+ _LOG_DEBUG_ID("Updated: " << std::boolalpha << isUpdated);
+ if (isInserted || isUpdated) {
+ DiffStatePtr commit = make_shared<DiffState>();
+ commit->update(node.sessionName, node.seqNo);
+ commit->setRootDigest(m_state.getRootDigest());
+ insertToDiffLog(commit, previousRoot);
+
+ satisfyPendingSyncInterests(prefix, commit);
+ }
}
}
}
@@ -341,7 +420,7 @@
// If the digest of incoming interest is an "empty" digest
if (digest == EMPTY_DIGEST) {
_LOG_DEBUG_ID("Poor guy, he knows nothing");
- sendSyncData(name, m_state);
+ sendSyncData(m_defaultUserPrefix, name, m_state);
return;
}
@@ -349,7 +428,7 @@
// If the digest of incoming interest can be found from the log
if (stateIter != m_log.end()) {
_LOG_DEBUG_ID("It is ok, you are so close");
- sendSyncData(name, *(*stateIter)->diff());
+ sendSyncData(m_defaultUserPrefix, name, *(*stateIter)->diff());
return;
}
@@ -370,7 +449,7 @@
// OK, nobody is helping us, just tell the truth.
_LOG_DEBUG_ID("OK, nobody is helping us, just tell the truth");
m_interestTable.erase(digest);
- sendSyncData(name, m_state);
+ sendSyncData(m_defaultUserPrefix, name, m_state);
}
_LOG_DEBUG_ID("<< Logic::processSyncInterest");
@@ -389,7 +468,6 @@
const Block& syncReplyBlock)
{
_LOG_DEBUG_ID(">> Logic::processSyncData");
-
DiffStatePtr commit = make_shared<DiffState>();
ndn::ConstBufferPtr previousRoot = m_state.getRootDigest();
@@ -411,7 +489,6 @@
bool isUpdated = false;
SeqNo oldSeq;
boost::tie(isInserted, isUpdated, oldSeq) = m_state.update(info, seq);
-
if (isInserted || isUpdated) {
commit->update(info, seq);
@@ -451,7 +528,7 @@
}
void
-Logic::satisfyPendingSyncInterests(ConstDiffStatePtr commit)
+Logic::satisfyPendingSyncInterests(const Name& updatedPrefix, ConstDiffStatePtr commit)
{
_LOG_DEBUG_ID(">> Logic::satisfyPendingSyncInterests");
try {
@@ -459,11 +536,10 @@
for (InterestTable::const_iterator it = m_interestTable.begin();
it != m_interestTable.end(); it++) {
ConstUnsatisfiedInterestPtr request = *it;
-
if (request->isUnknown)
- sendSyncData(request->interest->getName(), m_state);
+ sendSyncData(updatedPrefix, request->interest->getName(), m_state);
else
- sendSyncData(request->interest->getName(), *commit);
+ sendSyncData(updatedPrefix, request->interest->getName(), *commit);
}
m_interestTable.clear();
}
@@ -548,17 +624,18 @@
}
void
-Logic::sendSyncData(const Name& name, const State& state)
+Logic::sendSyncData(const Name& nodePrefix, const Name& name, const State& state)
{
_LOG_DEBUG_ID(">> Logic::sendSyncData");
shared_ptr<Data> syncReply = make_shared<Data>(name);
syncReply->setContent(state.wireEncode());
syncReply->setFreshnessPeriod(m_syncReplyFreshness);
-
- if (m_signingId.empty())
+ if (m_nodeList.find(nodePrefix) == m_nodeList.end())
+ return;
+ if (m_nodeList[nodePrefix].signingId.empty())
m_keyChain.sign(*syncReply);
else
- m_keyChain.signByIdentity(*syncReply, m_signingId);
+ m_keyChain.signByIdentity(*syncReply, m_nodeList[nodePrefix].signingId);
m_face.put(*syncReply);
@@ -589,7 +666,9 @@
return;
m_isInReset = false;
- updateSeqNo(m_seqNo);
+ for (const auto& node : m_nodeList) {
+ updateSeqNo(node.second.seqNo, node.first);
+ }
_LOG_DEBUG_ID("<< Logic::cancelReset");
}
diff --git a/src/logic.hpp b/src/logic.hpp
index acca168..e8ea4f6 100644
--- a/src/logic.hpp
+++ b/src/logic.hpp
@@ -27,7 +27,7 @@
#include "boost-header.h"
#include <memory>
-#include <map>
+#include <unordered_map>
#include <ndn-cxx/face.hpp>
#include <ndn-cxx/util/scheduler.hpp>
@@ -48,6 +48,14 @@
* Instances of this class is usually used as elements of some containers
* such as std::vector, thus it is copyable.
*/
+class NodeInfo {
+public:
+ Name userPrefix;
+ Name signingId;
+ Name sessionName;
+ SeqNo seqNo;
+};
+
class MissingDataInfo
{
public:
@@ -73,6 +81,17 @@
class Logic : noncopyable
{
public:
+ class Error : public std::runtime_error
+ {
+ public:
+ explicit
+ Error(const std::string& what)
+ : std::runtime_error(what)
+ {
+ }
+ };
+
+public:
static const time::steady_clock::Duration DEFAULT_RESET_TIMER;
static const time::steady_clock::Duration DEFAULT_CANCEL_RESET_TIMER;
static const time::milliseconds DEFAULT_RESET_INTEREST_LIFETIME;
@@ -83,8 +102,9 @@
* @brief Constructor
*
* @param syncPrefix The prefix of the sync group
- * @param userPrefix The prefix of the user who owns the session
+ * @param defaultUserPrefix The prefix of the first user added to this session
* @param onUpdate The callback function to handle state updates
+ * @param defaultSigningId The signing Id of the default user
* @param validator The validator for packet validation
* @param resetTimer The timer to periodically send Reset Interest
* @param syncReplyFreshness The FreshnessPeriod of sync reply
@@ -94,9 +114,9 @@
*/
Logic(ndn::Face& face,
const Name& syncPrefix,
- const Name& userPrefix,
+ const Name& defaultUserPrefix,
const UpdateCallback& onUpdate,
- const Name& signingId = DEFAULT_NAME,
+ const Name& defaultSigningId = DEFAULT_NAME,
ndn::shared_ptr<ndn::Validator> validator = DEFAULT_VALIDATOR,
const time::steady_clock::Duration& resetTimer = DEFAULT_RESET_TIMER,
const time::steady_clock::Duration& cancelResetTimer = DEFAULT_CANCEL_RESET_TIMER,
@@ -113,36 +133,67 @@
/**
* @brief Set user prefix
*
- * This method will also change the session name and trigger reset.
+ * This method will also change the default user and signing Id of that user.
*
- * @param userPrefix The prefix of user.
+ * @param defaultUserPrefix The prefix of user.
*/
void
- setUserPrefix(const Name& userPrefix);
+ setDefaultUserPrefix(const Name& defaultUserPrefix);
- /// @brief Get the name of the local session.
+ /// @brief Get the name of default user.
const Name&
- getSessionName() const
+ getDefaultUserPrefix() const
{
- return m_sessionName;
+ return m_defaultUserPrefix;
}
- /// @brief Get current seqNo of the local session.
+ /**
+ * @brief Add user node into the local session.
+ *
+ * This method also reset after adding
+ *
+ * @param userPrefix prefix of the added node
+ * @param signingId signing Id of the added node
+ */
+ void
+ addUserNode(const Name& userPrefix, const Name& signingId = DEFAULT_NAME);
+
+ /// @brief remove the node from the local session
+ void
+ removeUserNode(const Name& userPrefix);
+
+ /**
+ * @brief Get the name of the local session.
+ *
+ * This method gets the session name according to prefix, if prefix is not specified,
+ * it returns the session name of default user.
+ *
+ * @param prefix prefix of the node
+ */
+ const Name&
+ getSessionName(Name prefix = EMPTY_NAME);
+
+ /**
+ * @brief Get current seqNo of the local session.
+ *
+ * This method gets the seqNo according to prefix, if prefix is not specified,
+ * it returns the seqNo of default user.
+ *
+ * @param prefix prefix of the node
+ */
const SeqNo&
- getSeqNo() const
- {
- return m_seqNo;
- }
+ getSeqNo(Name prefix = EMPTY_NAME);
/**
* @brief Update the seqNo of the local session
*
- * The method updates the existing seqNo with the supplied seqNo.
+ * The method updates the existing seqNo with the supplied seqNo and prefix.
*
* @param seq The new seqNo.
+ * @param updatePrefix The prefix of node to update.
*/
void
- updateSeqNo(const SeqNo& seq);
+ updateSeqNo(const SeqNo& seq, const Name& updatePrefix = EMPTY_NAME);
/// @brief Get root digest of current sync tree
ndn::ConstBufferPtr
@@ -168,6 +219,7 @@
return m_state;
}
+
private:
/**
* @brief Callback to handle Sync Interest
@@ -304,7 +356,7 @@
* @param commit The diff.
*/
void
- satisfyPendingSyncInterests(ConstDiffStatePtr commit);
+ satisfyPendingSyncInterests(const Name& updatedPrefix, ConstDiffStatePtr commit);
/// @brief Helper method to send normal Sync Interest
void
@@ -316,7 +368,7 @@
/// @brief Helper method to send Sync Reply
void
- sendSyncData(const Name& name, const State& state);
+ sendSyncData(const Name& nodePrefix, const Name& name, const State& state);
/**
* @brief Unset reset status
@@ -332,9 +384,11 @@
public:
static const ndn::Name DEFAULT_NAME;
+ static const ndn::Name EMPTY_NAME;
static const ndn::shared_ptr<ndn::Validator> DEFAULT_VALIDATOR;
private:
+ typedef std::unordered_map<ndn::Name, NodeInfo> NodeList;
static const ndn::ConstBufferPtr EMPTY_DIGEST;
static const ndn::name::Component RESET_COMPONENT;
@@ -344,11 +398,10 @@
Name m_syncPrefix;
const ndn::RegisteredPrefixId* m_syncRegisteredPrefixId;
Name m_syncReset;
- Name m_userPrefix;
+ Name m_defaultUserPrefix;
// State
- Name m_sessionName;
- SeqNo m_seqNo;
+ NodeList m_nodeList;
State m_state;
DiffStateContainer m_log;
InterestTable m_interestTable;
@@ -382,10 +435,11 @@
time::milliseconds m_syncReplyFreshness;
// Security
- ndn::Name m_signingId;
+ ndn::Name m_defaultSigningId;
ndn::KeyChain m_keyChain;
ndn::shared_ptr<ndn::Validator> m_validator;
+
#ifdef _DEBUG
int m_instanceId;
static int m_instanceCounter;
diff --git a/tests/integrated-tests/test-logic.cpp b/tests/integrated-tests/test-logic.cpp
index 088b8fb..031280a 100644
--- a/tests/integrated-tests/test-logic.cpp
+++ b/tests/integrated-tests/test-logic.cpp
@@ -59,12 +59,6 @@
logic.updateSeqNo(seqNo);
}
- void
- check(const Name& sessionName, const SeqNo& seqNo)
- {
- BOOST_CHECK_EQUAL(map[sessionName], seqNo);
- }
-
Logic logic;
std::map<Name, SeqNo> map;
};
@@ -86,30 +80,6 @@
faces[2] = make_shared<ndn::Face>(ref(io));
}
- void
- createHandler(size_t idx)
- {
- handler[idx] = make_shared<Handler>(ref(*faces[idx]), syncPrefix, userPrefix[idx]);
- }
-
- void
- updateSeqNo(size_t idx, const SeqNo& seqNo)
- {
- handler[idx]->updateSeqNo(seqNo);
- }
-
- void
- checkSeqNo(size_t sIdx, size_t dIdx, const SeqNo& seqNo)
- {
- handler[sIdx]->check(handler[dIdx]->logic.getSessionName(), seqNo);
- }
-
- void
- terminate()
- {
- io.stop();
- }
-
Name syncPrefix;
Name userPrefix[3];
@@ -138,31 +108,27 @@
BOOST_AUTO_TEST_CASE(TwoBasic)
{
scheduler.scheduleEvent(ndn::time::milliseconds(100),
- bind(&LogicFixture::createHandler, this, 0));
+ [this] { handler[0] = make_shared<Handler>(ref(*faces[0]), syncPrefix, userPrefix[0]); });
scheduler.scheduleEvent(ndn::time::milliseconds(200),
- bind(&LogicFixture::createHandler, this, 1));
+ [this] { handler[1] = make_shared<Handler>(ref(*faces[1]), syncPrefix, userPrefix[1]); });
- scheduler.scheduleEvent(ndn::time::milliseconds(300),
- bind(&LogicFixture::updateSeqNo, this, 0, 1));
+ scheduler.scheduleEvent(ndn::time::milliseconds(300), [this] { handler[0]->updateSeqNo(1); });
scheduler.scheduleEvent(ndn::time::milliseconds(1000),
- bind(&LogicFixture::checkSeqNo, this, 1, 0, 1));
+ [this] { BOOST_CHECK_EQUAL(handler[1]->map[handler[0]->logic.getSessionName()], 1); });
- scheduler.scheduleEvent(ndn::time::milliseconds(1100),
- bind(&LogicFixture::updateSeqNo, this, 0, 2));
+ scheduler.scheduleEvent(ndn::time::milliseconds(1100), [this] { handler[0]->updateSeqNo(2); });
scheduler.scheduleEvent(ndn::time::milliseconds(1800),
- bind(&LogicFixture::checkSeqNo, this, 1, 0, 2));
+ [this] { BOOST_CHECK_EQUAL(handler[1]->map[handler[0]->logic.getSessionName()], 2); });
- scheduler.scheduleEvent(ndn::time::milliseconds(1900),
- bind(&LogicFixture::updateSeqNo, this, 1, 2));
+ scheduler.scheduleEvent(ndn::time::milliseconds(1900), [this] { handler[1]->updateSeqNo(2); });
scheduler.scheduleEvent(ndn::time::milliseconds(2600),
- bind(&LogicFixture::checkSeqNo, this, 0, 1, 2));
+ [this] { BOOST_CHECK_EQUAL(handler[0]->map[handler[1]->logic.getSessionName()], 2); });
- scheduler.scheduleEvent(ndn::time::milliseconds(2800),
- bind(&LogicFixture::terminate, this));
+ scheduler.scheduleEvent(ndn::time::milliseconds(2800), [this] { io.stop(); });
io.run();
}
@@ -170,43 +136,39 @@
BOOST_AUTO_TEST_CASE(ThreeBasic)
{
scheduler.scheduleEvent(ndn::time::milliseconds(100),
- bind(&LogicFixture::createHandler, this, 0));
+ [this] { handler[0] = make_shared<Handler>(ref(*faces[0]), syncPrefix, userPrefix[0]); });
scheduler.scheduleEvent(ndn::time::milliseconds(200),
- bind(&LogicFixture::createHandler, this, 1));
+ [this] { handler[1] = make_shared<Handler>(ref(*faces[1]), syncPrefix, userPrefix[1]); });
scheduler.scheduleEvent(ndn::time::milliseconds(300),
- bind(&LogicFixture::createHandler, this, 2));
+ [this] { handler[2] = make_shared<Handler>(ref(*faces[2]), syncPrefix, userPrefix[2]); });
- scheduler.scheduleEvent(ndn::time::milliseconds(500),
- bind(&LogicFixture::updateSeqNo, this, 0, 1));
+ scheduler.scheduleEvent(ndn::time::milliseconds(500), [this] { handler[0]->updateSeqNo(1); });
scheduler.scheduleEvent(ndn::time::milliseconds(1400),
- bind(&LogicFixture::checkSeqNo, this, 1, 0, 1));
+ [this] { BOOST_CHECK_EQUAL(handler[1]->map[handler[0]->logic.getSessionName()], 1); });
scheduler.scheduleEvent(ndn::time::milliseconds(1450),
- bind(&LogicFixture::checkSeqNo, this, 2, 0, 1));
+ [this] { BOOST_CHECK_EQUAL(handler[2]->map[handler[0]->logic.getSessionName()], 1); });
- scheduler.scheduleEvent(ndn::time::milliseconds(1500),
- bind(&LogicFixture::updateSeqNo, this, 1, 2));
+ scheduler.scheduleEvent(ndn::time::milliseconds(1500), [this] { handler[1]->updateSeqNo(2); });
scheduler.scheduleEvent(ndn::time::milliseconds(2400),
- bind(&LogicFixture::checkSeqNo, this, 0, 1, 2));
+ [this] { BOOST_CHECK_EQUAL(handler[0]->map[handler[1]->logic.getSessionName()], 2); });
scheduler.scheduleEvent(ndn::time::milliseconds(2450),
- bind(&LogicFixture::checkSeqNo, this, 2, 1, 2));
+ [this] { BOOST_CHECK_EQUAL(handler[2]->map[handler[1]->logic.getSessionName()], 2); });
- scheduler.scheduleEvent(ndn::time::milliseconds(2500),
- bind(&LogicFixture::updateSeqNo, this, 2, 4));
+ scheduler.scheduleEvent(ndn::time::milliseconds(2500), [this] { handler[2]->updateSeqNo(4); });
scheduler.scheduleEvent(ndn::time::milliseconds(4400),
- bind(&LogicFixture::checkSeqNo, this, 0, 2, 4));
+ [this] { BOOST_CHECK_EQUAL(handler[0]->map[handler[2]->logic.getSessionName()], 4); });
scheduler.scheduleEvent(ndn::time::milliseconds(4450),
- bind(&LogicFixture::checkSeqNo, this, 1, 2, 4));
+ [this] { BOOST_CHECK_EQUAL(handler[1]->map[handler[2]->logic.getSessionName()], 4); });
- scheduler.scheduleEvent(ndn::time::milliseconds(4500),
- bind(&LogicFixture::terminate, this));
+ scheduler.scheduleEvent(ndn::time::milliseconds(4500), [this] { io.stop(); });
io.run();
}
@@ -214,44 +176,40 @@
BOOST_AUTO_TEST_CASE(ResetRecover)
{
scheduler.scheduleEvent(ndn::time::milliseconds(100),
- bind(&LogicFixture::createHandler, this, 0));
+ [this] { handler[0] = make_shared<Handler>(ref(*faces[0]), syncPrefix, userPrefix[0]); });
scheduler.scheduleEvent(ndn::time::milliseconds(200),
- bind(&LogicFixture::createHandler, this, 1));
+ [this] { handler[1] = make_shared<Handler>(ref(*faces[1]), syncPrefix, userPrefix[1]); });
- scheduler.scheduleEvent(ndn::time::milliseconds(500),
- bind(&LogicFixture::updateSeqNo, this, 0, 1));
+ scheduler.scheduleEvent(ndn::time::milliseconds(500), [this] { handler[0]->updateSeqNo(1); });
scheduler.scheduleEvent(ndn::time::milliseconds(1400),
- bind(&LogicFixture::checkSeqNo, this, 1, 0, 1));
+ [this] { BOOST_CHECK_EQUAL(handler[1]->map[handler[0]->logic.getSessionName()], 1); });
- scheduler.scheduleEvent(ndn::time::milliseconds(1500),
- bind(&LogicFixture::updateSeqNo, this, 1, 2));
+ scheduler.scheduleEvent(ndn::time::milliseconds(1500), [this] { handler[1]->updateSeqNo(2); });
scheduler.scheduleEvent(ndn::time::milliseconds(2400),
- bind(&LogicFixture::checkSeqNo, this, 0, 1, 2));
+ [this] { BOOST_CHECK_EQUAL(handler[0]->map[handler[1]->logic.getSessionName()], 2); });
scheduler.scheduleEvent(ndn::time::milliseconds(2500),
- bind(&LogicFixture::createHandler, this, 2));
+ [this] { handler[2] = make_shared<Handler>(ref(*faces[2]), syncPrefix, userPrefix[2]); });
scheduler.scheduleEvent(ndn::time::milliseconds(3000),
- bind(&LogicFixture::checkSeqNo, this, 1, 0, 1));
+ [this] { BOOST_CHECK_EQUAL(handler[1]->map[handler[0]->logic.getSessionName()], 1); });
scheduler.scheduleEvent(ndn::time::milliseconds(3050),
- bind(&LogicFixture::checkSeqNo, this, 0, 1, 2));
+ [this] { BOOST_CHECK_EQUAL(handler[0]->map[handler[1]->logic.getSessionName()], 2); });
- scheduler.scheduleEvent(ndn::time::milliseconds(3100),
- bind(&LogicFixture::updateSeqNo, this, 2, 4));
+ scheduler.scheduleEvent(ndn::time::milliseconds(3100), [this] { handler[2]->updateSeqNo(4); });
scheduler.scheduleEvent(ndn::time::milliseconds(4000),
- bind(&LogicFixture::checkSeqNo, this, 1, 2, 4));
+ [this] { BOOST_CHECK_EQUAL(handler[1]->map[handler[2]->logic.getSessionName()], 4); });
scheduler.scheduleEvent(ndn::time::milliseconds(4050),
- bind(&LogicFixture::checkSeqNo, this, 0, 2, 4));
+ [this] { BOOST_CHECK_EQUAL(handler[0]->map[handler[2]->logic.getSessionName()], 4); });
- scheduler.scheduleEvent(ndn::time::milliseconds(4500),
- bind(&LogicFixture::terminate, this));
+ scheduler.scheduleEvent(ndn::time::milliseconds(4500), [this] { io.stop(); });
io.run();
}
@@ -259,47 +217,83 @@
BOOST_AUTO_TEST_CASE(RecoverConflict)
{
scheduler.scheduleEvent(ndn::time::milliseconds(0),
- bind(&LogicFixture::createHandler, this, 0));
+ [this] { handler[0] = make_shared<Handler>(ref(*faces[0]), syncPrefix, userPrefix[0]); });
scheduler.scheduleEvent(ndn::time::milliseconds(50),
- bind(&LogicFixture::createHandler, this, 1));
+ [this] { handler[1] = make_shared<Handler>(ref(*faces[1]), syncPrefix, userPrefix[1]); });
scheduler.scheduleEvent(ndn::time::milliseconds(100),
- bind(&LogicFixture::createHandler, this, 2));
+ [this] { handler[2] = make_shared<Handler>(ref(*faces[2]), syncPrefix, userPrefix[2]); });
- scheduler.scheduleEvent(ndn::time::milliseconds(500),
- bind(&LogicFixture::updateSeqNo, this, 0, 1));
+ scheduler.scheduleEvent(ndn::time::milliseconds(500), [this] { handler[0]->updateSeqNo(1); });
scheduler.scheduleEvent(ndn::time::milliseconds(1400),
- bind(&LogicFixture::checkSeqNo, this, 1, 0, 1));
+ [this] { BOOST_CHECK_EQUAL(handler[1]->map[handler[0]->logic.getSessionName()], 1); });
scheduler.scheduleEvent(ndn::time::milliseconds(1400),
- bind(&LogicFixture::checkSeqNo, this, 2, 0, 1));
+ [this] { BOOST_CHECK_EQUAL(handler[2]->map[handler[0]->logic.getSessionName()], 1); });
- scheduler.scheduleEvent(ndn::time::milliseconds(1500),
- bind(&LogicFixture::updateSeqNo, this, 1, 2));
+ scheduler.scheduleEvent(ndn::time::milliseconds(1500), [this] { handler[1]->updateSeqNo(2); });
- scheduler.scheduleEvent(ndn::time::milliseconds(1500),
- bind(&LogicFixture::updateSeqNo, this, 2, 4));
+ scheduler.scheduleEvent(ndn::time::milliseconds(1500), [this] { handler[2]->updateSeqNo(4); });
scheduler.scheduleEvent(ndn::time::milliseconds(2400),
- bind(&LogicFixture::checkSeqNo, this, 0, 1, 2));
+ [this] { BOOST_CHECK_EQUAL(handler[0]->map[handler[1]->logic.getSessionName()], 2); });
scheduler.scheduleEvent(ndn::time::milliseconds(2450),
- bind(&LogicFixture::checkSeqNo, this, 0, 2, 4));
+ [this] { BOOST_CHECK_EQUAL(handler[0]->map[handler[2]->logic.getSessionName()], 4); });
scheduler.scheduleEvent(ndn::time::milliseconds(2500),
- bind(&LogicFixture::checkSeqNo, this, 1, 2, 4));
+ [this] { BOOST_CHECK_EQUAL(handler[1]->map[handler[2]->logic.getSessionName()], 4); });
scheduler.scheduleEvent(ndn::time::milliseconds(2550),
- bind(&LogicFixture::checkSeqNo, this, 2, 1, 2));
+ [this] { BOOST_CHECK_EQUAL(handler[2]->map[handler[1]->logic.getSessionName()], 2); });
- scheduler.scheduleEvent(ndn::time::milliseconds(4500),
- bind(&LogicFixture::terminate, this));
+ scheduler.scheduleEvent(ndn::time::milliseconds(4500), [this] { io.stop(); });
io.run();
}
+BOOST_AUTO_TEST_CASE(MultipleUserUnderOneLogic)
+{
+ scheduler.scheduleEvent(ndn::time::milliseconds(0),
+ [this] { handler[0] = make_shared<Handler>(ref(*faces[0]), syncPrefix, userPrefix[0]); });
+
+ scheduler.scheduleEvent(ndn::time::milliseconds(50),
+ [this] { handler[1] = make_shared<Handler>(ref(*faces[1]), syncPrefix, userPrefix[2]); });
+
+ scheduler.scheduleEvent(ndn::time::milliseconds(100),
+ [this] { handler[0]->logic.addUserNode(userPrefix[1]); });
+
+ scheduler.scheduleEvent(ndn::time::milliseconds(500), [this] { handler[0]->updateSeqNo(1); });
+
+ scheduler.scheduleEvent(ndn::time::milliseconds(1400),
+ [this] { BOOST_CHECK_EQUAL(handler[1]->map[handler[0]->logic.getSessionName()], 1); });
+
+ scheduler.scheduleEvent(ndn::time::milliseconds(1500),
+ [this] { handler[0]->logic.updateSeqNo(2, userPrefix[1]); });
+
+ scheduler.scheduleEvent(ndn::time::milliseconds(2400),
+ [this] {
+ Name sessionName = handler[0]->logic.getSessionName(userPrefix[1]);
+ BOOST_CHECK_EQUAL(handler[1]->map[sessionName], 2);
+ });
+
+ scheduler.scheduleEvent(ndn::time::milliseconds(2500), [this] { handler[1]->updateSeqNo(4); });
+
+ scheduler.scheduleEvent(ndn::time::milliseconds(3200),
+ [this] { BOOST_CHECK_EQUAL(handler[0]->map[handler[1]->logic.getSessionName()], 4); });
+
+ scheduler.scheduleEvent(ndn::time::milliseconds(3300),
+ [this] { handler[0]->logic.removeUserNode(userPrefix[0]); });
+
+ scheduler.scheduleEvent(ndn::time::milliseconds(4500),
+ [this] { BOOST_CHECK_EQUAL(handler[1]->logic.getSessionNames().size(), 2); });
+
+ scheduler.scheduleEvent(ndn::time::milliseconds(5000), [this] { io.stop(); });
+
+ io.run();
+}
BOOST_AUTO_TEST_SUITE_END()
diff --git a/tests/unit-tests/test-multiple-user.cpp b/tests/unit-tests/test-multiple-user.cpp
new file mode 100644
index 0000000..44209e8
--- /dev/null
+++ b/tests/unit-tests/test-multiple-user.cpp
@@ -0,0 +1,104 @@
+#include "logic.hpp"
+
+#include "boost-test.hpp"
+
+namespace chronosync {
+namespace test {
+
+using std::vector;
+
+
+class Handler
+{
+public:
+ Handler(ndn::Face& face,
+ const Name& syncPrefix,
+ const Name& userPrefix)
+ : logic(face,
+ syncPrefix,
+ userPrefix,
+ bind(&Handler::onUpdate, this, _1))
+ {
+ }
+
+ void
+ onUpdate(const vector<MissingDataInfo>& v)
+ {
+
+ }
+
+ void
+ updateSeqNo(const SeqNo& seqNo)
+ {
+ logic.updateSeqNo(seqNo);
+ }
+
+ void
+ addUserNode(const Name& prefix)
+ {
+ logic.addUserNode(prefix);
+ }
+
+ void
+ removeUserNode(const Name& prefix)
+ {
+ logic.removeUserNode(prefix);
+ }
+
+
+ Logic logic;
+ std::map<Name, SeqNo> map;
+};
+
+class LogicFixture
+{
+public:
+
+ LogicFixture()
+ : syncPrefix("/ndn/broadcast/sync")
+ , scheduler(io)
+ {
+ syncPrefix.appendVersion();
+ userPrefix[0] = Name("/user0");
+ userPrefix[1] = Name("/user1");
+ userPrefix[2] = Name("/user2");
+
+ face = make_shared<ndn::Face>(ref(io));
+ }
+
+ Name syncPrefix;
+ Name userPrefix[3];
+
+ boost::asio::io_service io;
+ shared_ptr<ndn::Face> face;
+ ndn::Scheduler scheduler;
+ shared_ptr<Handler> handler;
+};
+
+BOOST_FIXTURE_TEST_SUITE(LogicTests, LogicFixture)
+
+BOOST_AUTO_TEST_CASE(ThreeUserNode)
+{
+ handler = make_shared<Handler>(ref(*face), syncPrefix, userPrefix[0]);
+ handler->addUserNode(userPrefix[1]);
+ handler->addUserNode(userPrefix[2]);
+ handler->removeUserNode(userPrefix[0]);
+
+ handler->logic.setDefaultUserPrefix(userPrefix[1]);
+ handler->updateSeqNo(1);
+ BOOST_CHECK_EQUAL(handler->logic.getSeqNo(userPrefix[1]), 1);
+
+ handler->logic.updateSeqNo(2, userPrefix[2]);
+ handler->logic.setDefaultUserPrefix(userPrefix[2]);
+
+ BOOST_CHECK_EQUAL(handler->logic.getSeqNo(), 2);
+
+ BOOST_REQUIRE_THROW(handler->logic.getSeqNo(userPrefix[0]), Logic::Error);
+ BOOST_REQUIRE_THROW(handler->logic.getSessionName(userPrefix[0]), Logic::Error);
+
+}
+
+BOOST_AUTO_TEST_SUITE_END()
+
+} // namespace test
+} // namespace chronosync