tests: move integrated tests into unit tests
Change-Id: Ifed29e53091ca430582b1c2e7f3514e02d7c8d14
diff --git a/src/logic.cpp b/src/logic.cpp
index 0c5b87a..e0c0501 100644
--- a/src/logic.cpp
+++ b/src/logic.cpp
@@ -121,14 +121,15 @@
}
void
-Logic::reset()
+Logic::reset(bool isOnInterest)
{
m_isInReset = true;
m_state.reset();
m_log.clear();
- sendResetInterest();
+ if (!isOnInterest)
+ sendResetInterest();
// reset outstanding interest name, so that data for previous interest will be dropped.
if (m_outstandingInterestId != 0) {
@@ -173,7 +174,7 @@
sessionName.appendNumber(ndn::time::toUnixTimestamp(ndn::time::system_clock::now()).count());
m_nodeList[userPrefix].sessionName = sessionName;
m_nodeList[userPrefix].seqNo = 0;
- reset();
+ reset(false);
}
}
@@ -193,7 +194,7 @@
m_defaultSigningId = DEFAULT_NAME;
}
}
- reset();
+ reset(false);
}
}
@@ -459,7 +460,7 @@
Logic::processResetInterest(const Interest& interest)
{
_LOG_DEBUG_ID(">> Logic::processResetInterest");
- reset();
+ reset(true);
}
void
diff --git a/src/logic.hpp b/src/logic.hpp
index e8ea4f6..b7bfbdf 100644
--- a/src/logic.hpp
+++ b/src/logic.hpp
@@ -126,9 +126,13 @@
~Logic();
- /// @brief Reset the sync tree (and restart synchronization again)
+ /**
+ * @brief Reset the sync tree (and restart synchronization again)
+ *
+ * @param isOnInterest a flag that tells whether the reset is called by reset interest.
+ */
void
- reset();
+ reset(bool isOnInterest = false);
/**
* @brief Set user prefix
diff --git a/src/socket.cpp b/src/socket.cpp
index 695f758..7356f73 100644
--- a/src/socket.cpp
+++ b/src/socket.cpp
@@ -30,8 +30,8 @@
namespace chronosync {
-const ndn::Name Socket::DEFAULT_PREFIX;
const ndn::Name Socket::DEFAULT_NAME;
+const ndn::Name Socket::DEFAULT_PREFIX;
const ndn::shared_ptr<ndn::Validator> Socket::DEFAULT_VALIDATOR;
Socket::Socket(const Name& syncPrefix,
@@ -46,12 +46,30 @@
, m_signingId(signingId)
, m_validator(validator)
{
+ if (m_userPrefix != DEFAULT_NAME)
+ m_registeredPrefixList[m_userPrefix] =
+ m_face.setInterestFilter(m_userPrefix,
+ bind(&Socket::onInterest, this, _1, _2),
+ [] (const Name& prefix, const std::string& msg) {});
}
void
Socket::addSyncNode(const Name& prefix, const Name& signingId)
{
+ if (prefix == DEFAULT_NAME)
+ return;
+
+ auto itr = m_registeredPrefixList.find(prefix);
+ if (itr != m_registeredPrefixList.end())
+ return;
+
+ if (m_userPrefix == DEFAULT_NAME)
+ m_userPrefix = prefix;
m_logic.addUserNode(prefix, signingId);
+ m_registeredPrefixList[prefix] =
+ m_face.setInterestFilter(prefix,
+ bind(&Socket::onInterest, this, _1, _2),
+ [] (const Name& prefix, const std::string& msg) {});
}
void
@@ -79,7 +97,7 @@
else
m_keyChain.signByIdentity(*data, m_signingId);
- m_face.put(*data);
+ m_ims.insert(*data);
m_logic.updateSeqNo(newSeq, prefix);
}
@@ -126,6 +144,15 @@
}
void
+Socket::onInterest(const Name& prefix, const Interest& interest)
+{
+ shared_ptr<const Data>data = m_ims.find(interest);
+ if (static_cast<bool>(data)) {
+ m_face.put(*data);
+ }
+}
+
+void
Socket::onData(const Interest& interest, Data& data,
const ndn::OnDataValidated& onValidated,
const ndn::OnDataValidationFailed& onFailed)
diff --git a/src/socket.hpp b/src/socket.hpp
index 3e09c79..6987003 100644
--- a/src/socket.hpp
+++ b/src/socket.hpp
@@ -26,6 +26,8 @@
#define CHRONOSYNC_SOCKET_HPP
#include <ndn-cxx/face.hpp>
+#include <ndn-cxx/util/in-memory-storage-persistent.hpp>
+#include <unordered_map>
#include "logic.hpp"
@@ -140,6 +142,9 @@
private:
void
+ onInterest(const Name& prefix, const Interest& interest);
+
+ void
onData(const Interest& interest, Data& data,
const ndn::OnDataValidated& dataCallback,
const ndn::OnDataValidationFailed& failCallback);
@@ -159,6 +164,7 @@
static const ndn::shared_ptr<ndn::Validator> DEFAULT_VALIDATOR;
private:
+ typedef std::unordered_map<ndn::Name, const ndn::RegisteredPrefixId*> RegisteredPrefixList;
Name m_userPrefix;
ndn::Face& m_face;
@@ -168,6 +174,9 @@
ndn::Name m_signingId;
ndn::KeyChain m_keyChain;
ndn::shared_ptr<ndn::Validator> m_validator;
+
+ RegisteredPrefixList m_registeredPrefixList;
+ ndn::util::InMemoryStoragePersistent m_ims;
};
} // namespace chronosync
diff --git a/tests/integrated-tests/test-logic.cpp b/tests/integrated-tests/test-logic.cpp
deleted file mode 100644
index 031280a..0000000
--- a/tests/integrated-tests/test-logic.cpp
+++ /dev/null
@@ -1,301 +0,0 @@
-/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil -*- */
-/*
- * Copyright (c) 2012-2014 University of California, Los Angeles
- *
- * This file is part of ChronoSync, synchronization library for distributed realtime
- * applications for NDN.
- *
- * ChronoSync is free software: you can redistribute it and/or modify it under the terms
- * of the GNU General Public License as published by the Free Software Foundation, either
- * version 3 of the License, or (at your option) any later version.
- *
- * ChronoSync 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * ChronoSync, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#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)
- {
- for (size_t i = 0; i < v.size(); i++) {
- update(v[i].session, v[i].high, v[i].low);
- }
- }
-
- void
- update(const Name& p, const SeqNo& high, const SeqNo& low)
- {
- map[p] = high;
- }
-
- void
- updateSeqNo(const SeqNo& seqNo)
- {
- logic.updateSeqNo(seqNo);
- }
-
- 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");
-
- faces[0] = make_shared<ndn::Face>(ref(io));
- faces[1] = make_shared<ndn::Face>(ref(io));
- faces[2] = make_shared<ndn::Face>(ref(io));
- }
-
- Name syncPrefix;
- Name userPrefix[3];
-
- boost::asio::io_service io;
- shared_ptr<ndn::Face> faces[3];
- ndn::Scheduler scheduler;
- shared_ptr<Handler> handler[3];
-};
-
-BOOST_FIXTURE_TEST_SUITE(LogicTests, LogicFixture)
-
-void
-onUpdate(const vector<MissingDataInfo>& v)
-{
-}
-
-BOOST_AUTO_TEST_CASE(Constructor)
-{
- Name syncPrefix("/ndn/broadcast/sync");
- Name userPrefix("/user");
- ndn::Face face;
- BOOST_REQUIRE_NO_THROW(Logic(face, syncPrefix, userPrefix,
- bind(onUpdate, _1)));
-}
-
-BOOST_AUTO_TEST_CASE(TwoBasic)
-{
- scheduler.scheduleEvent(ndn::time::milliseconds(100),
- [this] { handler[0] = make_shared<Handler>(ref(*faces[0]), syncPrefix, userPrefix[0]); });
-
- scheduler.scheduleEvent(ndn::time::milliseconds(200),
- [this] { handler[1] = make_shared<Handler>(ref(*faces[1]), syncPrefix, userPrefix[1]); });
-
- scheduler.scheduleEvent(ndn::time::milliseconds(300), [this] { handler[0]->updateSeqNo(1); });
-
- scheduler.scheduleEvent(ndn::time::milliseconds(1000),
- [this] { BOOST_CHECK_EQUAL(handler[1]->map[handler[0]->logic.getSessionName()], 1); });
-
- scheduler.scheduleEvent(ndn::time::milliseconds(1100), [this] { handler[0]->updateSeqNo(2); });
-
- scheduler.scheduleEvent(ndn::time::milliseconds(1800),
- [this] { BOOST_CHECK_EQUAL(handler[1]->map[handler[0]->logic.getSessionName()], 2); });
-
- scheduler.scheduleEvent(ndn::time::milliseconds(1900), [this] { handler[1]->updateSeqNo(2); });
-
- scheduler.scheduleEvent(ndn::time::milliseconds(2600),
- [this] { BOOST_CHECK_EQUAL(handler[0]->map[handler[1]->logic.getSessionName()], 2); });
-
- scheduler.scheduleEvent(ndn::time::milliseconds(2800), [this] { io.stop(); });
-
- io.run();
-}
-
-BOOST_AUTO_TEST_CASE(ThreeBasic)
-{
- scheduler.scheduleEvent(ndn::time::milliseconds(100),
- [this] { handler[0] = make_shared<Handler>(ref(*faces[0]), syncPrefix, userPrefix[0]); });
-
- scheduler.scheduleEvent(ndn::time::milliseconds(200),
- [this] { handler[1] = make_shared<Handler>(ref(*faces[1]), syncPrefix, userPrefix[1]); });
-
- scheduler.scheduleEvent(ndn::time::milliseconds(300),
- [this] { handler[2] = make_shared<Handler>(ref(*faces[2]), syncPrefix, userPrefix[2]); });
-
- 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(1450),
- [this] { BOOST_CHECK_EQUAL(handler[2]->map[handler[0]->logic.getSessionName()], 1); });
-
- scheduler.scheduleEvent(ndn::time::milliseconds(1500), [this] { handler[1]->updateSeqNo(2); });
-
- scheduler.scheduleEvent(ndn::time::milliseconds(2400),
- [this] { BOOST_CHECK_EQUAL(handler[0]->map[handler[1]->logic.getSessionName()], 2); });
-
- scheduler.scheduleEvent(ndn::time::milliseconds(2450),
- [this] { BOOST_CHECK_EQUAL(handler[2]->map[handler[1]->logic.getSessionName()], 2); });
-
- scheduler.scheduleEvent(ndn::time::milliseconds(2500), [this] { handler[2]->updateSeqNo(4); });
-
- scheduler.scheduleEvent(ndn::time::milliseconds(4400),
- [this] { BOOST_CHECK_EQUAL(handler[0]->map[handler[2]->logic.getSessionName()], 4); });
-
- scheduler.scheduleEvent(ndn::time::milliseconds(4450),
- [this] { BOOST_CHECK_EQUAL(handler[1]->map[handler[2]->logic.getSessionName()], 4); });
-
- scheduler.scheduleEvent(ndn::time::milliseconds(4500), [this] { io.stop(); });
-
- io.run();
-}
-
-BOOST_AUTO_TEST_CASE(ResetRecover)
-{
- scheduler.scheduleEvent(ndn::time::milliseconds(100),
- [this] { handler[0] = make_shared<Handler>(ref(*faces[0]), syncPrefix, userPrefix[0]); });
-
- scheduler.scheduleEvent(ndn::time::milliseconds(200),
- [this] { handler[1] = make_shared<Handler>(ref(*faces[1]), syncPrefix, 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[1]->updateSeqNo(2); });
-
- scheduler.scheduleEvent(ndn::time::milliseconds(2400),
- [this] { BOOST_CHECK_EQUAL(handler[0]->map[handler[1]->logic.getSessionName()], 2); });
-
- scheduler.scheduleEvent(ndn::time::milliseconds(2500),
- [this] { handler[2] = make_shared<Handler>(ref(*faces[2]), syncPrefix, userPrefix[2]); });
-
- scheduler.scheduleEvent(ndn::time::milliseconds(3000),
- [this] { BOOST_CHECK_EQUAL(handler[1]->map[handler[0]->logic.getSessionName()], 1); });
-
- scheduler.scheduleEvent(ndn::time::milliseconds(3050),
- [this] { BOOST_CHECK_EQUAL(handler[0]->map[handler[1]->logic.getSessionName()], 2); });
-
- scheduler.scheduleEvent(ndn::time::milliseconds(3100), [this] { handler[2]->updateSeqNo(4); });
-
- scheduler.scheduleEvent(ndn::time::milliseconds(4000),
- [this] { BOOST_CHECK_EQUAL(handler[1]->map[handler[2]->logic.getSessionName()], 4); });
-
- scheduler.scheduleEvent(ndn::time::milliseconds(4050),
- [this] { BOOST_CHECK_EQUAL(handler[0]->map[handler[2]->logic.getSessionName()], 4); });
-
-
- scheduler.scheduleEvent(ndn::time::milliseconds(4500), [this] { io.stop(); });
-
- io.run();
-}
-
-BOOST_AUTO_TEST_CASE(RecoverConflict)
-{
- 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[1]); });
-
- scheduler.scheduleEvent(ndn::time::milliseconds(100),
- [this] { handler[2] = make_shared<Handler>(ref(*faces[2]), syncPrefix, userPrefix[2]); });
-
- 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(1400),
- [this] { BOOST_CHECK_EQUAL(handler[2]->map[handler[0]->logic.getSessionName()], 1); });
-
- scheduler.scheduleEvent(ndn::time::milliseconds(1500), [this] { handler[1]->updateSeqNo(2); });
-
- scheduler.scheduleEvent(ndn::time::milliseconds(1500), [this] { handler[2]->updateSeqNo(4); });
-
- scheduler.scheduleEvent(ndn::time::milliseconds(2400),
- [this] { BOOST_CHECK_EQUAL(handler[0]->map[handler[1]->logic.getSessionName()], 2); });
-
- scheduler.scheduleEvent(ndn::time::milliseconds(2450),
- [this] { BOOST_CHECK_EQUAL(handler[0]->map[handler[2]->logic.getSessionName()], 4); });
-
- scheduler.scheduleEvent(ndn::time::milliseconds(2500),
- [this] { BOOST_CHECK_EQUAL(handler[1]->map[handler[2]->logic.getSessionName()], 4); });
-
- scheduler.scheduleEvent(ndn::time::milliseconds(2550),
- [this] { BOOST_CHECK_EQUAL(handler[2]->map[handler[1]->logic.getSessionName()], 2); });
-
- 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()
-
-} // namespace test
-} // namespace chronosync
diff --git a/tests/integrated-tests/test-socket.cpp b/tests/integrated-tests/test-socket.cpp
deleted file mode 100644
index d06c19d..0000000
--- a/tests/integrated-tests/test-socket.cpp
+++ /dev/null
@@ -1,333 +0,0 @@
-/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil -*- */
-/*
- * Copyright (c) 2012-2014 University of California, Los Angeles
- *
- * This file is part of ChronoSync, synchronization library for distributed realtime
- * applications for NDN.
- *
- * ChronoSync is free software: you can redistribute it and/or modify it under the terms
- * of the GNU General Public License as published by the Free Software Foundation, either
- * version 3 of the License, or (at your option) any later version.
- *
- * ChronoSync 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * ChronoSync, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "socket.hpp"
-
-#include "boost-test.hpp"
-
-namespace chronosync {
-namespace test {
-
-using std::string;
-using std::vector;
-using std::map;
-
-/**
- * @brief Emulate an app that use the Socket class
- *
- * The app has two types of data set: one is simply string while the other is integer array.
- * For each type of data set, the app has a specific fetching strategy.
- */
-class SocketTestApp : noncopyable
-{
-public:
- SocketTestApp(const Name& syncPrefix,
- const Name& userPrefix,
- ndn::Face& face,
- bool isNum)
- : sum(0)
- , socket(syncPrefix,
- userPrefix,
- face,
- isNum ? bind(&SocketTestApp::fetchNumbers, this, _1) :
- bind(&SocketTestApp::fetchAll, this, _1))
- {
- }
-
- void
- set(const shared_ptr<const Data>& dataPacket)
- {
- // std::cerr << "set Data" << std::endl;
- Name dataName(dataPacket->getName());
- string str2(reinterpret_cast<const char*>(dataPacket->getContent().value()),
- dataPacket->getContent().value_size());
- data.insert(make_pair(dataName, str2));
- }
-
- void
- set(Name name, const char* buf, int len)
- {
- string str2(buf, len);
- data.insert(make_pair(name, str2));
- }
-
- void
- setNum(const shared_ptr<const Data>& dataPacket)
- {
- // std::cerr << "setNum Data" << std::endl;
- size_t n = dataPacket->getContent().value_size() / 4;
- const uint32_t* numbers = reinterpret_cast<const uint32_t*>(dataPacket->getContent().value());
- for (size_t i = 0; i < n; i++) {
- sum += numbers[i];
- }
- }
-
- void
- setNum(Name name, const uint8_t* buf, int len)
- {
- BOOST_ASSERT(len >= 4);
-
- int n = len / 4;
- const uint32_t* numbers = reinterpret_cast<const uint32_t*>(buf);
- for (int i = 0; i < n; i++) {
- sum += numbers[i];
- }
- }
-
- void
- fetchAll(const vector<MissingDataInfo>& v)
- {
- // std::cerr << "fetchAll" << std::endl;
- for (int i = 0; i < v.size(); i++) {
- for(SeqNo s = v[i].low; s <= v[i].high; ++s) {
- socket.fetchData(v[i].session, s, [this] (const shared_ptr<const Data>& dataPacket) {
- this->set(dataPacket);
- });
- }
- }
- }
-
- void
- fetchNumbers(const vector<MissingDataInfo> &v)
- {
- // std::cerr << "fetchNumbers" << std::endl;
- for (int i = 0; i < v.size(); i++) {
- for(SeqNo s = v[i].low; s <= v[i].high; ++s) {
- socket.fetchData(v[i].session, s, [this] (const shared_ptr<const Data>& dataPacket) {
- this->setNum(dataPacket);
- });
- }
- }
- }
-
- string
- toString()
- {
- string str = "\n";
- for (map<Name, string>::iterator it = data.begin(); it != data.end(); ++it) {
- str += "<";
- str += it->first.toUri();
- str += "|";
- str += it->second;
- str += ">";
- str += "\n";
- }
-
- return str;
- }
-
- map<ndn::Name, string> data;
- uint32_t sum;
- Socket socket;
-};
-
-class SocketFixture
-{
-public:
- SocketFixture()
- : syncPrefix("/ndn/broadcast/sync")
- , scheduler(io)
- {
- syncPrefix.appendVersion();
- userPrefix[0] = Name("/user0");
- userPrefix[1] = Name("/user1");
- userPrefix[2] = Name("/user2");
-
- faces[0] = make_shared<ndn::Face>(ref(io));
- faces[1] = make_shared<ndn::Face>(ref(io));
- faces[2] = make_shared<ndn::Face>(ref(io));
- }
-
- void
- createSocket(size_t idx, bool isNum)
- {
- app[idx] = make_shared<SocketTestApp>(syncPrefix, userPrefix[idx], ref(*faces[idx]), isNum);
- sessionName[idx] = app[idx]->socket.getLogic().getSessionName();
- }
-
- void
- publishAppData(size_t idx, const string& data)
- {
- app[idx]->socket.publishData(reinterpret_cast<const uint8_t*>(data.c_str()), data.size(),
- ndn::time::milliseconds(1000));
- }
-
- void
- setAppData(size_t idx, SeqNo seqNo, const string& data)
- {
- Name dataName = sessionName[idx];
- dataName.appendNumber(seqNo);
- app[idx]->set(dataName, data.c_str(), data.size());
- }
-
- void
- publishAppNum(size_t idx, const uint8_t* buf, size_t size)
- {
- app[idx]->socket.publishData(buf, size, ndn::time::milliseconds(1000));
- }
-
- void
- setAppNum(size_t idx, SeqNo seqNo, const uint8_t* buf, size_t size)
- {
- Name dataName = sessionName[idx];
- dataName.appendNumber(seqNo);
- app[idx]->setNum(dataName, buf, size);
- }
-
- void
- check(int round)
- {
- BOOST_CHECK_EQUAL(app[0]->toString(), app[1]->toString());
- BOOST_CHECK_EQUAL(app[0]->toString(), app[2]->toString());
- }
-
- void
- check2Num(int num)
- {
- BOOST_CHECK_EQUAL(app[0]->sum, app[1]->sum);
- BOOST_CHECK_EQUAL(app[1]->sum, num);
- }
-
- void
- terminate()
- {
- io.stop();
- }
-
- Name syncPrefix;
- Name userPrefix[3];
- Name sessionName[3];
-
- boost::asio::io_service io;
- shared_ptr<ndn::Face> faces[3];
- ndn::Scheduler scheduler;
- shared_ptr<SocketTestApp> app[3];
-};
-
-
-
-BOOST_FIXTURE_TEST_SUITE(SocketTests, SocketFixture)
-
-BOOST_AUTO_TEST_CASE(BasicData)
-{
- scheduler.scheduleEvent(ndn::time::milliseconds(0),
- bind(&SocketFixture::createSocket, this, 0, false));
-
- scheduler.scheduleEvent(ndn::time::milliseconds(50),
- bind(&SocketFixture::createSocket, this, 1, false));
-
- scheduler.scheduleEvent(ndn::time::milliseconds(100),
- bind(&SocketFixture::createSocket, this, 2, false));
-
- string data0 = "Very funny Scotty, now beam down my clothes";
- scheduler.scheduleEvent(ndn::time::milliseconds(150),
- bind(&SocketFixture::publishAppData, this, 0, data0));
- scheduler.scheduleEvent(ndn::time::milliseconds(1150),
- bind(&SocketFixture::setAppData, this, 0, 1, data0));
- scheduler.scheduleEvent(ndn::time::milliseconds(1160),
- bind(&SocketFixture::check, this, 1));
-
- string data1 = "Yes, give me that ketchup";
- string data2 = "Don't look conspicuous, it draws fire";
- scheduler.scheduleEvent(ndn::time::milliseconds(1170),
- bind(&SocketFixture::publishAppData, this, 0, data1));
- scheduler.scheduleEvent(ndn::time::milliseconds(1180),
- bind(&SocketFixture::publishAppData, this, 0, data2));
- scheduler.scheduleEvent(ndn::time::milliseconds(2150),
- bind(&SocketFixture::setAppData, this, 0, 2, data1));
- scheduler.scheduleEvent(ndn::time::milliseconds(2160),
- bind(&SocketFixture::setAppData, this, 0, 3, data2));
- scheduler.scheduleEvent(ndn::time::milliseconds(2170),
- bind(&SocketFixture::check, this, 2));
-
- string data3 = "You surf the Internet, I surf the real world";
- string data4 = "I got a fortune cookie once that said 'You like Chinese food'";
- string data5 = "Real men wear pink. Why? Because their wives make them";
- scheduler.scheduleEvent(ndn::time::milliseconds(3180),
- bind(&SocketFixture::publishAppData, this, 2, data3));
- scheduler.scheduleEvent(ndn::time::milliseconds(3200),
- bind(&SocketFixture::publishAppData, this, 1, data4));
- scheduler.scheduleEvent(ndn::time::milliseconds(3210),
- bind(&SocketFixture::publishAppData, this, 1, data5));
- scheduler.scheduleEvent(ndn::time::milliseconds(4710),
- bind(&SocketFixture::setAppData, this, 2, 1, data3));
- scheduler.scheduleEvent(ndn::time::milliseconds(4720),
- bind(&SocketFixture::setAppData, this, 1, 1, data4));
- scheduler.scheduleEvent(ndn::time::milliseconds(4730),
- bind(&SocketFixture::setAppData, this, 1, 2, data5));
- scheduler.scheduleEvent(ndn::time::milliseconds(4800),
- bind(&SocketFixture::check, this, 3));
-
- // not sure weither this is simultanous data generation from multiple sources
- string data6 = "Shakespeare says: 'Prose before hos.'";
- string data7 = "Pick good people, talent never wears out";
- scheduler.scheduleEvent(ndn::time::milliseconds(5500),
- bind(&SocketFixture::publishAppData, this, 0, data6));
- scheduler.scheduleEvent(ndn::time::milliseconds(5500),
- bind(&SocketFixture::publishAppData, this, 1, data7));
- scheduler.scheduleEvent(ndn::time::milliseconds(6800),
- bind(&SocketFixture::setAppData, this, 0, 4, data6));
- scheduler.scheduleEvent(ndn::time::milliseconds(6800),
- bind(&SocketFixture::setAppData, this, 1, 3, data7));
- scheduler.scheduleEvent(ndn::time::milliseconds(6900),
- bind(&SocketFixture::check, this, 4));
-
- scheduler.scheduleEvent(ndn::time::milliseconds(7000),
- bind(&SocketFixture::terminate, this));
-
- io.run();
-}
-
-BOOST_AUTO_TEST_CASE(BasicNumber)
-{
- scheduler.scheduleEvent(ndn::time::milliseconds(0),
- bind(&SocketFixture::createSocket, this, 0, true));
- scheduler.scheduleEvent(ndn::time::milliseconds(50),
- bind(&SocketFixture::createSocket, this, 1, true));
-
- uint32_t num1[5] = {0, 1, 2, 3, 4};
- uint8_t* buf1 = reinterpret_cast<uint8_t*>(num1);
- size_t size1 = sizeof(num1);
- scheduler.scheduleEvent(ndn::time::milliseconds(100),
- bind(&SocketFixture::publishAppNum, this, 0, buf1, size1));
- scheduler.scheduleEvent(ndn::time::milliseconds(150),
- bind(&SocketFixture::setAppNum, this, 0, 0, buf1, size1));
- scheduler.scheduleEvent(ndn::time::milliseconds(1000),
- bind(&SocketFixture::check2Num, this, 10));
-
- uint32_t num2[5] = {9, 7, 2, 1, 1};
- uint8_t* buf2 = reinterpret_cast<uint8_t*>(num2);
- size_t size2 = sizeof(num2);
- scheduler.scheduleEvent(ndn::time::milliseconds(1100),
- bind(&SocketFixture::publishAppNum, this, 1, buf2, size2));
- scheduler.scheduleEvent(ndn::time::milliseconds(1150),
- bind(&SocketFixture::setAppNum, this, 1, 0, buf2, size2));
- scheduler.scheduleEvent(ndn::time::milliseconds(2000),
- bind(&SocketFixture::check2Num, this, 30));
-
- scheduler.scheduleEvent(ndn::time::milliseconds(7000),
- bind(&SocketFixture::terminate, this));
-
- io.run();
-}
-
-BOOST_AUTO_TEST_SUITE_END()
-
-} // namespace test
-} // namespace chronosync
diff --git a/tests/unit-tests/test-logic.cpp b/tests/unit-tests/test-logic.cpp
new file mode 100644
index 0000000..53a6f57
--- /dev/null
+++ b/tests/unit-tests/test-logic.cpp
@@ -0,0 +1,344 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2012-2014 University of California, Los Angeles
+ *
+ * This file is part of ChronoSync, synchronization library for distributed realtime
+ * applications for NDN.
+ *
+ * ChronoSync is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU General Public License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * ChronoSync 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * ChronoSync, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "logic.hpp"
+#include "../unit-test-time-fixture.hpp"
+#include <ndn-cxx/util/dummy-client-face.hpp>
+#include "boost-test.hpp"
+
+namespace chronosync {
+namespace test {
+
+using std::vector;
+using ndn::util::DummyClientFace;
+using ndn::util::makeDummyClientFace;
+
+class Handler
+{
+public:
+ Handler(DummyClientFace& face,
+ const Name& syncPrefix,
+ const Name& userPrefix)
+ : logic(face,
+ syncPrefix,
+ userPrefix,
+ bind(&Handler::onUpdate, this, _1))
+ {
+ }
+
+ void
+ onUpdate(const vector<MissingDataInfo>& v)
+ {
+ for (size_t i = 0; i < v.size(); i++) {
+ update(v[i].session, v[i].high, v[i].low);
+ }
+ }
+
+ void
+ update(const Name& p, const SeqNo& high, const SeqNo& low)
+ {
+ map[p] = high;
+ }
+
+ void
+ updateSeqNo(const SeqNo& seqNo)
+ {
+ logic.updateSeqNo(seqNo);
+ }
+
+ Logic logic;
+ std::map<Name, SeqNo> map;
+};
+
+class LogicFixture : public ndn::tests::UnitTestTimeFixture
+{
+public:
+ LogicFixture()
+ : syncPrefix("/ndn/broadcast/sync")
+ {
+ syncPrefix.appendVersion();
+ userPrefix[0] = Name("/user0");
+ userPrefix[1] = Name("/user1");
+ userPrefix[2] = Name("/user2");
+
+ faces[0] = makeDummyClientFace(ref(io), {true, true});
+ faces[1] = makeDummyClientFace(ref(io), {true, true});
+ faces[2] = makeDummyClientFace(ref(io), {true, true});
+
+ for (int i = 0; i < 3; i++) {
+ readInterestOffset[i] = 0;
+ readDataOffset[i] = 0;
+ }
+ }
+
+ void
+ passPacket()
+ {
+ for (int i = 0; i < 3; i++)
+ checkFace(i);
+ }
+
+ void
+ checkFace(int sender)
+ {
+ while (faces[sender]->sentInterests.size() > readInterestOffset[sender]) {
+ for (int i = 0; i < 3; i++) {
+ if (sender != i)
+ faces[i]->receive(faces[sender]->sentInterests[readInterestOffset[sender]]);
+ }
+ readInterestOffset[sender]++;
+ }
+ while (faces[sender]->sentDatas.size() > readDataOffset[sender]) {
+ for (int i = 0; i < 3; i++) {
+ if (sender != i)
+ faces[i]->receive(faces[sender]->sentDatas[readDataOffset[sender]]);
+ }
+ readDataOffset[sender]++;
+ }
+ }
+
+ Name syncPrefix;
+ Name userPrefix[3];
+
+ shared_ptr<DummyClientFace> faces[3];
+ shared_ptr<Handler> handler[3];
+
+ size_t readInterestOffset[3];
+ size_t readDataOffset[3];
+};
+
+BOOST_FIXTURE_TEST_SUITE(LogicTests, LogicFixture)
+
+void
+onUpdate(const vector<MissingDataInfo>& v)
+{
+}
+
+BOOST_AUTO_TEST_CASE(Constructor)
+{
+ Name syncPrefix("/ndn/broadcast/sync");
+ Name userPrefix("/user");
+ shared_ptr<DummyClientFace> face = makeDummyClientFace(ref(io), {true, true});
+ BOOST_REQUIRE_NO_THROW(Logic(ref(*face), syncPrefix, userPrefix,
+ bind(onUpdate, _1)));
+}
+
+BOOST_AUTO_TEST_CASE(TwoBasic)
+{
+ handler[0] = make_shared<Handler>(ref(*faces[0]), syncPrefix, userPrefix[0]);
+ advanceClocks(ndn::time::milliseconds(10), 10);
+
+ handler[1] = make_shared<Handler>(ref(*faces[1]), syncPrefix, userPrefix[1]);
+ advanceClocks(ndn::time::milliseconds(10), 10);
+
+ handler[0]->updateSeqNo(1);
+
+ for (int i = 0; i < 50; i++) {
+ advanceClocks(ndn::time::milliseconds(2), 10);
+ passPacket();
+ }
+ BOOST_CHECK_EQUAL(handler[1]->map[handler[0]->logic.getSessionName()], 1);
+ advanceClocks(ndn::time::milliseconds(10), 10);
+
+ handler[0]->updateSeqNo(2);
+
+ for (int i = 0; i < 50; i++) {
+ advanceClocks(ndn::time::milliseconds(2), 10);
+ passPacket();
+ }
+ BOOST_CHECK_EQUAL(handler[1]->map[handler[0]->logic.getSessionName()], 2);
+ advanceClocks(ndn::time::milliseconds(10), 10);
+
+ handler[1]->updateSeqNo(2);
+
+ for (int i = 0; i < 50; i++) {
+ advanceClocks(ndn::time::milliseconds(2), 10);
+ passPacket();
+ }
+ BOOST_CHECK_EQUAL(handler[0]->map[handler[1]->logic.getSessionName()], 2);
+}
+
+BOOST_AUTO_TEST_CASE(ThreeBasic)
+{
+ handler[0] = make_shared<Handler>(ref(*faces[0]), syncPrefix, userPrefix[0]);
+ advanceClocks(ndn::time::milliseconds(10), 10);
+
+ handler[1] = make_shared<Handler>(ref(*faces[1]), syncPrefix, userPrefix[1]);
+ advanceClocks(ndn::time::milliseconds(10), 10);
+
+ handler[2] = make_shared<Handler>(ref(*faces[2]), syncPrefix, userPrefix[2]);
+ advanceClocks(ndn::time::milliseconds(10), 20);
+
+ handler[0]->updateSeqNo(1);
+
+ for (int i = 0; i < 70; i++) {
+ advanceClocks(ndn::time::milliseconds(2), 10);
+ passPacket();
+ }
+ BOOST_CHECK_EQUAL(handler[1]->map[handler[0]->logic.getSessionName()], 1);
+ BOOST_CHECK_EQUAL(handler[2]->map[handler[0]->logic.getSessionName()], 1);
+
+ handler[1]->updateSeqNo(2);
+
+ for (int i = 0; i < 50; i++) {
+ advanceClocks(ndn::time::milliseconds(2), 10);
+ passPacket();
+ }
+ BOOST_CHECK_EQUAL(handler[0]->map[handler[1]->logic.getSessionName()], 2);
+ BOOST_CHECK_EQUAL(handler[2]->map[handler[1]->logic.getSessionName()], 2);
+
+ handler[2]->updateSeqNo(4);
+
+ for (int i = 0; i < 100; i++) {
+ advanceClocks(ndn::time::milliseconds(2), 10);
+ passPacket();
+ }
+ BOOST_CHECK_EQUAL(handler[0]->map[handler[2]->logic.getSessionName()], 4);
+ BOOST_CHECK_EQUAL(handler[1]->map[handler[2]->logic.getSessionName()], 4);
+}
+
+BOOST_AUTO_TEST_CASE(ResetRecover)
+{
+ handler[0] = make_shared<Handler>(ref(*faces[0]), syncPrefix, userPrefix[0]);
+ advanceClocks(ndn::time::milliseconds(10), 10);
+
+ handler[1] = make_shared<Handler>(ref(*faces[1]), syncPrefix, userPrefix[1]);
+ advanceClocks(ndn::time::milliseconds(10), 30);
+
+ handler[0]->updateSeqNo(1);
+
+ for (int i = 0; i < 50; i++) {
+ advanceClocks(ndn::time::milliseconds(2), 10);
+ passPacket();
+ }
+ BOOST_CHECK_EQUAL(handler[1]->map[handler[0]->logic.getSessionName()], 1);
+
+ handler[1]->updateSeqNo(2);
+
+ for (int i = 0; i < 50; i++) {
+ advanceClocks(ndn::time::milliseconds(2), 10);
+ passPacket();
+ }
+ BOOST_CHECK_EQUAL(handler[0]->map[handler[1]->logic.getSessionName()], 2);
+
+ advanceClocks(ndn::time::milliseconds(10), 10);
+ handler[2] = make_shared<Handler>(ref(*faces[2]), syncPrefix, userPrefix[2]);
+
+ for (int i = 0; i < 50; i++) {
+ advanceClocks(ndn::time::milliseconds(2), 10);
+ passPacket();
+ }
+ BOOST_CHECK_EQUAL(handler[1]->map[handler[0]->logic.getSessionName()], 1);
+ BOOST_CHECK_EQUAL(handler[0]->map[handler[1]->logic.getSessionName()], 2);
+
+ handler[2]->updateSeqNo(4);
+
+ for (int i = 0; i < 50; i++) {
+ advanceClocks(ndn::time::milliseconds(2), 10);
+ passPacket();
+ }
+ BOOST_CHECK_EQUAL(handler[1]->map[handler[2]->logic.getSessionName()], 4);
+ BOOST_CHECK_EQUAL(handler[0]->map[handler[2]->logic.getSessionName()], 4);
+}
+
+BOOST_AUTO_TEST_CASE(RecoverConflict)
+{
+ handler[0] = make_shared<Handler>(ref(*faces[0]), syncPrefix, userPrefix[0]);
+ advanceClocks(ndn::time::milliseconds(10), 10);
+
+ handler[1] = make_shared<Handler>(ref(*faces[1]), syncPrefix, userPrefix[1]);
+ advanceClocks(ndn::time::milliseconds(10), 10);
+
+ handler[2] = make_shared<Handler>(ref(*faces[2]), syncPrefix, userPrefix[2]);
+ advanceClocks(ndn::time::milliseconds(10), 30);
+
+ handler[0]->updateSeqNo(1);
+
+ for (int i = 0; i < 50; i++) {
+ advanceClocks(ndn::time::milliseconds(2), 10);
+ passPacket();
+ }
+ BOOST_CHECK_EQUAL(handler[1]->map[handler[0]->logic.getSessionName()], 1);
+ BOOST_CHECK_EQUAL(handler[2]->map[handler[0]->logic.getSessionName()], 1);
+
+ handler[1]->updateSeqNo(2);
+ handler[2]->updateSeqNo(4);
+
+ for (int i = 0; i < 75; i++) {
+ advanceClocks(ndn::time::milliseconds(2), 10);
+ passPacket();
+ }
+ BOOST_CHECK_EQUAL(handler[0]->map[handler[1]->logic.getSessionName()], 2);
+ BOOST_CHECK_EQUAL(handler[0]->map[handler[2]->logic.getSessionName()], 4);
+ BOOST_CHECK_EQUAL(handler[1]->map[handler[2]->logic.getSessionName()], 4);
+ BOOST_CHECK_EQUAL(handler[2]->map[handler[1]->logic.getSessionName()], 2);
+}
+
+BOOST_AUTO_TEST_CASE(MultipleUserUnderOneLogic)
+{
+ handler[0] = make_shared<Handler>(ref(*faces[0]), syncPrefix, userPrefix[0]);
+ advanceClocks(ndn::time::milliseconds(10), 10);
+
+ handler[1] = make_shared<Handler>(ref(*faces[1]), syncPrefix, userPrefix[2]);
+ advanceClocks(ndn::time::milliseconds(10), 10);
+
+ handler[0]->logic.addUserNode(userPrefix[1]);
+
+ for (int i = 0; i < 20; i++) {
+ advanceClocks(ndn::time::milliseconds(2), 10);
+ passPacket();
+ }
+
+ handler[0]->updateSeqNo(1);
+
+ for (int i = 0; i < 50; i++) {
+ advanceClocks(ndn::time::milliseconds(2), 10);
+ passPacket();
+ }
+ BOOST_CHECK_EQUAL(handler[1]->map[handler[0]->logic.getSessionName()], 1);
+
+ handler[0]->logic.updateSeqNo(2, userPrefix[1]);
+
+ for (int i = 0; i < 50; i++) {
+ advanceClocks(ndn::time::milliseconds(2), 10);
+ passPacket();
+ }
+ BOOST_CHECK_EQUAL(handler[1]->map[handler[0]->logic.getSessionName(userPrefix[1])], 2);
+
+ handler[1]->updateSeqNo(4);
+
+ for (int i = 0; i < 50; i++) {
+ advanceClocks(ndn::time::milliseconds(2), 10);
+ passPacket();
+ }
+ BOOST_CHECK_EQUAL(handler[0]->map[handler[1]->logic.getSessionName()], 4);
+
+ handler[0]->logic.removeUserNode(userPrefix[0]);
+
+ for (int i = 0; i < 100; i++) {
+ advanceClocks(ndn::time::milliseconds(2), 10);
+ passPacket();
+ }
+ BOOST_CHECK_EQUAL(handler[1]->logic.getSessionNames().size(), 2);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
+
+} // namespace test
+} // namespace chronosync
diff --git a/tests/unit-tests/test-multiple-user.cpp b/tests/unit-tests/test-multiple-user.cpp
index 44209e8..7effecc 100644
--- a/tests/unit-tests/test-multiple-user.cpp
+++ b/tests/unit-tests/test-multiple-user.cpp
@@ -50,11 +50,11 @@
std::map<Name, SeqNo> map;
};
-class LogicFixture
+class MultiUserFixture
{
public:
- LogicFixture()
+ MultiUserFixture()
: syncPrefix("/ndn/broadcast/sync")
, scheduler(io)
{
@@ -75,7 +75,7 @@
shared_ptr<Handler> handler;
};
-BOOST_FIXTURE_TEST_SUITE(LogicTests, LogicFixture)
+BOOST_FIXTURE_TEST_SUITE(MultiUserTests, MultiUserFixture)
BOOST_AUTO_TEST_CASE(ThreeUserNode)
{
diff --git a/tests/unit-tests/test-socket.cpp b/tests/unit-tests/test-socket.cpp
new file mode 100644
index 0000000..5bfcecf
--- /dev/null
+++ b/tests/unit-tests/test-socket.cpp
@@ -0,0 +1,359 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2012-2014 University of California, Los Angeles
+ *
+ * This file is part of ChronoSync, synchronization library for distributed realtime
+ * applications for NDN.
+ *
+ * ChronoSync is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU General Public License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * ChronoSync 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * ChronoSync, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "socket.hpp"
+#include "../unit-test-time-fixture.hpp"
+#include <ndn-cxx/util/dummy-client-face.hpp>
+#include "boost-test.hpp"
+
+namespace chronosync {
+namespace test {
+
+using std::string;
+using std::vector;
+using std::map;
+using ndn::util::DummyClientFace;
+using ndn::util::makeDummyClientFace;
+
+
+/**
+ * @brief Emulate an app that use the Socket class
+ *
+ * The app has two types of data set: one is simply string while the other is integer array.
+ * For each type of data set, the app has a specific fetching strategy.
+ */
+class SocketTestApp : noncopyable
+{
+public:
+ SocketTestApp(const Name& syncPrefix,
+ const Name& userPrefix,
+ DummyClientFace& face,
+ bool isNum)
+ : sum(0)
+ , socket(syncPrefix,
+ userPrefix,
+ face,
+ isNum ? bind(&SocketTestApp::fetchNumbers, this, _1) :
+ bind(&SocketTestApp::fetchAll, this, _1))
+ {
+ }
+
+ void
+ set(const shared_ptr<const Data>& dataPacket)
+ {
+ // std::cerr << "set Data" << std::endl;
+ Name dataName(dataPacket->getName());
+ string str2(reinterpret_cast<const char*>(dataPacket->getContent().value()),
+ dataPacket->getContent().value_size());
+ data.insert(make_pair(dataName, str2));
+ }
+
+ void
+ set(Name name, const char* buf, int len)
+ {
+ string str2(buf, len);
+ data.insert(make_pair(name, str2));
+ }
+
+ void
+ setNum(const shared_ptr<const Data>& dataPacket)
+ {
+ // std::cerr << "setNum Data" << std::endl;
+ size_t n = dataPacket->getContent().value_size() / 4;
+ const uint32_t* numbers = reinterpret_cast<const uint32_t*>(dataPacket->getContent().value());
+ for (size_t i = 0; i < n; i++) {
+ sum += numbers[i];
+ }
+ }
+
+ void
+ setNum(Name name, const uint8_t* buf, int len)
+ {
+ BOOST_ASSERT(len >= 4);
+
+ int n = len / 4;
+ const uint32_t* numbers = reinterpret_cast<const uint32_t*>(buf);
+ for (int i = 0; i < n; i++) {
+ sum += numbers[i];
+ }
+ }
+
+ void
+ fetchAll(const vector<MissingDataInfo>& v)
+ {
+ // std::cerr << "fetchAll" << std::endl;
+ for (int i = 0; i < v.size(); i++) {
+ for(SeqNo s = v[i].low; s <= v[i].high; ++s) {
+ socket.fetchData(v[i].session, s, [this] (const shared_ptr<const Data>& dataPacket) {
+ this->set(dataPacket);
+ });
+ }
+ }
+ }
+
+ void
+ fetchNumbers(const vector<MissingDataInfo> &v)
+ {
+ // std::cerr << "fetchNumbers" << std::endl;
+ for (int i = 0; i < v.size(); i++) {
+ for(SeqNo s = v[i].low; s <= v[i].high; ++s) {
+ socket.fetchData(v[i].session, s, [this] (const shared_ptr<const Data>& dataPacket) {
+ this->setNum(dataPacket);
+ });
+ }
+ }
+ }
+
+ string
+ toString()
+ {
+ string str = "\n";
+ for (map<Name, string>::iterator it = data.begin(); it != data.end(); ++it) {
+ str += "<";
+ str += it->first.toUri();
+ str += "|";
+ str += it->second;
+ str += ">";
+ str += "\n";
+ }
+
+ return str;
+ }
+
+ map<ndn::Name, string> data;
+ uint32_t sum;
+ Socket socket;
+};
+
+class SocketFixture : public ndn::tests::UnitTestTimeFixture
+{
+public:
+ SocketFixture()
+ : syncPrefix("/ndn/broadcast/sync")
+ {
+ syncPrefix.appendVersion();
+ userPrefix[0] = Name("/user0");
+ userPrefix[1] = Name("/user1");
+ userPrefix[2] = Name("/user2");
+
+ faces[0] = makeDummyClientFace(ref(io), {true, true});
+ faces[1] = makeDummyClientFace(ref(io), {true, true});
+ faces[2] = makeDummyClientFace(ref(io), {true, true});
+
+ for (int i = 0; i < 3; i++) {
+ readInterestOffset[i] = 0;
+ readDataOffset[i] = 0;
+ }
+ }
+
+ void
+ passPacket()
+ {
+ for (int i = 0; i < 3; i++)
+ checkFace(i);
+ }
+
+ void
+ checkFace(int sender)
+ {
+ while (faces[sender]->sentInterests.size() > readInterestOffset[sender]) {
+ for (int i = 0; i < 3; i++) {
+ if (sender != i)
+ faces[i]->receive(faces[sender]->sentInterests[readInterestOffset[sender]]);
+ }
+ readInterestOffset[sender]++;
+ }
+ while (faces[sender]->sentDatas.size() > readDataOffset[sender]) {
+ for (int i = 0; i < 3; i++) {
+ if (sender != i)
+ faces[i]->receive(faces[sender]->sentDatas[readDataOffset[sender]]);
+ }
+ readDataOffset[sender]++;
+ }
+ }
+
+ void
+ createSocket(size_t idx, bool isNum)
+ {
+ app[idx] = make_shared<SocketTestApp>(syncPrefix, userPrefix[idx], ref(*faces[idx]), isNum);
+ sessionName[idx] = app[idx]->socket.getLogic().getSessionName();
+ }
+
+ void
+ publishAppData(size_t idx, const string& data)
+ {
+ app[idx]->socket.publishData(reinterpret_cast<const uint8_t*>(data.c_str()), data.size(),
+ ndn::time::milliseconds(1000));
+ }
+
+ void
+ setAppData(size_t idx, SeqNo seqNo, const string& data)
+ {
+ Name dataName = sessionName[idx];
+ dataName.appendNumber(seqNo);
+ app[idx]->set(dataName, data.c_str(), data.size());
+ }
+
+ void
+ publishAppNum(size_t idx, const uint8_t* buf, size_t size)
+ {
+ app[idx]->socket.publishData(buf, size, ndn::time::milliseconds(1000));
+ }
+
+ void
+ setAppNum(size_t idx, SeqNo seqNo, const uint8_t* buf, size_t size)
+ {
+ Name dataName = sessionName[idx];
+ dataName.appendNumber(seqNo);
+ app[idx]->setNum(dataName, buf, size);
+ }
+
+ Name syncPrefix;
+ Name userPrefix[3];
+ Name sessionName[3];
+
+ shared_ptr<DummyClientFace> faces[3];
+ shared_ptr<SocketTestApp> app[3];
+
+ size_t readInterestOffset[3];
+ size_t readDataOffset[3];
+};
+
+
+
+BOOST_FIXTURE_TEST_SUITE(SocketTests, SocketFixture)
+
+BOOST_AUTO_TEST_CASE(BasicData)
+{
+ createSocket(0, false);
+ advanceClocks(ndn::time::milliseconds(10), 5);
+ createSocket(1, false);
+ advanceClocks(ndn::time::milliseconds(10), 5);
+ createSocket(2, false);
+ advanceClocks(ndn::time::milliseconds(10), 5);
+
+ string data0 = "Very funny Scotty, now beam down my clothes";
+ publishAppData(0, data0);
+
+ for (int i = 0; i < 50; i++) {
+ advanceClocks(ndn::time::milliseconds(2), 10);
+ passPacket();
+ }
+ setAppData(0, 1, data0);
+
+ advanceClocks(ndn::time::milliseconds(10), 1);
+ BOOST_CHECK_EQUAL(app[0]->toString(), app[1]->toString());
+ BOOST_CHECK_EQUAL(app[0]->toString(), app[2]->toString());
+
+ string data1 = "Yes, give me that ketchup";
+ string data2 = "Don't look conspicuous, it draws fire";
+ publishAppData(0, data1);
+ advanceClocks(ndn::time::milliseconds(10), 1);
+ publishAppData(0, data2);
+
+ for (int i = 0; i < 50; i++) {
+ advanceClocks(ndn::time::milliseconds(2), 10);
+ passPacket();
+ }
+ setAppData(0, 2, data1);
+ advanceClocks(ndn::time::milliseconds(10), 1);
+ setAppData(0, 3, data2);
+
+ advanceClocks(ndn::time::milliseconds(10), 1);
+ BOOST_CHECK_EQUAL(app[0]->toString(), app[1]->toString());
+ BOOST_CHECK_EQUAL(app[0]->toString(), app[2]->toString());
+
+ string data3 = "You surf the Internet, I surf the real world";
+ string data4 = "I got a fortune cookie once that said 'You like Chinese food'";
+ string data5 = "Real men wear pink. Why? Because their wives make them";
+ publishAppData(2, data3);
+ advanceClocks(ndn::time::milliseconds(10), 2);
+ publishAppData(1, data4);
+ advanceClocks(ndn::time::milliseconds(10), 1);
+ publishAppData(1, data5);
+
+ for (int i = 0; i < 100; i++) {
+ advanceClocks(ndn::time::milliseconds(2), 10);
+ passPacket();
+ }
+ setAppData(2, 1, data3);
+ advanceClocks(ndn::time::milliseconds(10), 1);
+ setAppData(1, 1, data4);
+ advanceClocks(ndn::time::milliseconds(10), 1);
+ setAppData(1, 2, data5);
+
+ advanceClocks(ndn::time::milliseconds(10), 7);
+ BOOST_CHECK_EQUAL(app[0]->toString(), app[1]->toString());
+ BOOST_CHECK_EQUAL(app[0]->toString(), app[2]->toString());
+
+ string data6 = "Shakespeare says: 'Prose before hos.'";
+ string data7 = "Pick good people, talent never wears out";
+ publishAppData(0, data6);
+ publishAppData(1, data7);
+
+ for (int i = 0; i < 100; i++) {
+ advanceClocks(ndn::time::milliseconds(2), 10);
+ passPacket();
+ }
+ setAppData(0, 4, data6);
+ setAppData(1, 3, data7);
+
+ BOOST_CHECK_EQUAL(app[0]->toString(), app[1]->toString());
+ BOOST_CHECK_EQUAL(app[0]->toString(), app[2]->toString());
+}
+
+BOOST_AUTO_TEST_CASE(BasicNumber)
+{
+ createSocket(0, true);
+ advanceClocks(ndn::time::milliseconds(10), 5);
+ createSocket(1, true);
+ advanceClocks(ndn::time::milliseconds(10), 5);
+
+ uint32_t num1[5] = {0, 1, 2, 3, 4};
+ uint8_t* buf1 = reinterpret_cast<uint8_t*>(num1);
+ size_t size1 = sizeof(num1);
+ publishAppNum(0, buf1, size1);
+ advanceClocks(ndn::time::milliseconds(10), 5);
+ setAppNum(0, 0, buf1, size1);
+
+ for (int i = 0; i < 100; i++) {
+ advanceClocks(ndn::time::milliseconds(2), 10);
+ passPacket();
+ }
+ BOOST_CHECK_EQUAL(app[0]->sum, app[1]->sum);
+ BOOST_CHECK_EQUAL(app[1]->sum, 10);
+
+ uint32_t num2[5] = {9, 7, 2, 1, 1};
+ uint8_t* buf2 = reinterpret_cast<uint8_t*>(num2);
+ size_t size2 = sizeof(num2);
+ publishAppNum(1, buf2, size2);
+ setAppNum(1, 0, buf2, size2);
+
+ for (int i = 0; i < 50; i++) {
+ advanceClocks(ndn::time::milliseconds(2), 10);
+ passPacket();
+ }
+ BOOST_CHECK_EQUAL(app[0]->sum, app[1]->sum);
+ BOOST_CHECK_EQUAL(app[1]->sum, 30);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
+
+} // namespace test
+} // namespace chronosync