logic: allow manipulating multiple nodes in single logic

Change-Id: Iaa2a2b08e891d41c9aa71c13ffc531bef406b6d8
This commit is contained in:
Qiuhan Ding committed 2014-11-25 09:37:32 -08:00
1 parent 3573e131d2
commit 8c095fd188
4 files changed
+406 -175

No files matched your search

+137 -58
View File
@@ -50,6 +50,7 @@ int Logic::m_instanceCounter = 0;
#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 @@ const ndn::name::Component Logic::RESET_COMPONENT("reset");
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 @@ Logic::Logic(ndn::Face& face,
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 @@ Logic::Logic(ndn::Face& face,
, m_resetInterestLifetime(resetInterestLifetime)
, m_syncInterestLifetime(syncInterestLifetime)
, m_syncReplyFreshness(syncReplyFreshness)
, m_signingId(signingId)
, m_defaultSigningId(defaultSigningId)
, m_validator(validator)
{
#ifdef _DEBUG
@@ -97,6 +98,9 @@ Logic::Logic(ndn::Face& face,
_LOG_DEBUG_ID(">> Logic::Logic");
addUserNode(m_defaultUserPrefix, m_defaultSigningId);
m_syncReset = m_syncPrefix;
m_syncReset.append("reset");
@@ -106,7 +110,6 @@ Logic::Logic(ndn::Face& face,
bind(&Logic::onSyncInterest, this, _1, _2),
bind(&Logic::onSyncRegisterFailed, this, _1, _2));
setUserPrefix(m_userPrefix);
_LOG_DEBUG_ID("<< Logic::Logic");
}
@@ -144,56 +147,132 @@ Logic::reset()
}
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 @@ Logic::processSyncInterest(const shared_ptr<const Interest>& interest,
// 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 @@ Logic::processSyncInterest(const shared_ptr<const Interest>& interest,
// 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 @@ Logic::processSyncInterest(const shared_ptr<const Interest>& interest,
// 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 @@ Logic::processSyncData(const Name& name,
const Block& syncReplyBlock)
{
_LOG_DEBUG_ID(">> Logic::processSyncData");
DiffStatePtr commit = make_shared<DiffState>();
ndn::ConstBufferPtr previousRoot = m_state.getRootDigest();
@@ -411,7 +489,6 @@ Logic::processSyncData(const Name& name,
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 @@ Logic::processSyncData(const Name& name,
}
void
Logic::satisfyPendingSyncInterests(ConstDiffStatePtr commit)
Logic::satisfyPendingSyncInterests(const Name& updatedPrefix, ConstDiffStatePtr commit)
{
_LOG_DEBUG_ID(">> Logic::satisfyPendingSyncInterests");
try {
@@ -459,11 +536,10 @@ Logic::satisfyPendingSyncInterests(ConstDiffStatePtr commit)
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 @@ Logic::sendSyncInterest()
}
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 @@ Logic::cancelReset()
return;
m_isInReset = false;
updateSeqNo(m_seqNo);
for (const auto& node : m_nodeList) {
updateSeqNo(node.second.seqNo, node.first);
}
_LOG_DEBUG_ID("<< Logic::cancelReset");
}
+77 -23
View File
@@ -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 @@ namespace chronosync {
* 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:
@@ -72,6 +80,17 @@ typedef function<void(const std::vector<MissingDataInfo>&)> UpdateCallback;
*/
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;
@@ -83,8 +102,9 @@ public:
* @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 @@ public:
*/
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 @@ public:
/**
* @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 @@ CHRONOSYNC_PUBLIC_WITH_TESTS_ELSE_PRIVATE:
return m_state;
}
private:
/**
* @brief Callback to handle Sync Interest
@@ -304,7 +356,7 @@ private:
* @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 @@ private:
/// @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 @@ private:
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 @@ private:
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 @@ private:
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;
+88 -94
View File
@@ -59,12 +59,6 @@ public:
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 @@ public:
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(Constructor)
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(TwoBasic)
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(ThreeBasic)
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(ResetRecover)
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()
+104
View File
@@ -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