blob: 031280aeb722bd44a12558a0581ac6cfa48758ee [file] [log] [blame]
Yingdi Yuf7ede412014-08-30 20:37:52 -07001/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil -*- */
2/*
3 * Copyright (c) 2012-2014 University of California, Los Angeles
4 *
5 * This file is part of ChronoSync, synchronization library for distributed realtime
6 * applications for NDN.
7 *
8 * ChronoSync is free software: you can redistribute it and/or modify it under the terms
9 * of the GNU General Public License as published by the Free Software Foundation, either
10 * version 3 of the License, or (at your option) any later version.
11 *
12 * ChronoSync is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
13 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14 * PURPOSE. See the GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along with
17 * ChronoSync, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#include "logic.hpp"
21
22#include "boost-test.hpp"
23
24namespace chronosync {
25namespace test {
26
27using std::vector;
28
29class Handler
30{
31public:
32 Handler(ndn::Face& face,
33 const Name& syncPrefix,
34 const Name& userPrefix)
35 : logic(face,
36 syncPrefix,
37 userPrefix,
38 bind(&Handler::onUpdate, this, _1))
39 {
40 }
41
42 void
43 onUpdate(const vector<MissingDataInfo>& v)
44 {
45 for (size_t i = 0; i < v.size(); i++) {
46 update(v[i].session, v[i].high, v[i].low);
47 }
48 }
49
50 void
51 update(const Name& p, const SeqNo& high, const SeqNo& low)
52 {
53 map[p] = high;
54 }
55
56 void
57 updateSeqNo(const SeqNo& seqNo)
58 {
59 logic.updateSeqNo(seqNo);
60 }
61
Yingdi Yuf7ede412014-08-30 20:37:52 -070062 Logic logic;
63 std::map<Name, SeqNo> map;
64};
65
66class LogicFixture
67{
68public:
69 LogicFixture()
70 : syncPrefix("/ndn/broadcast/sync")
71 , scheduler(io)
72 {
73 syncPrefix.appendVersion();
74 userPrefix[0] = Name("/user0");
75 userPrefix[1] = Name("/user1");
76 userPrefix[2] = Name("/user2");
77
78 faces[0] = make_shared<ndn::Face>(ref(io));
79 faces[1] = make_shared<ndn::Face>(ref(io));
80 faces[2] = make_shared<ndn::Face>(ref(io));
81 }
82
Yingdi Yuf7ede412014-08-30 20:37:52 -070083 Name syncPrefix;
84 Name userPrefix[3];
85
86 boost::asio::io_service io;
87 shared_ptr<ndn::Face> faces[3];
88 ndn::Scheduler scheduler;
89 shared_ptr<Handler> handler[3];
90};
91
92BOOST_FIXTURE_TEST_SUITE(LogicTests, LogicFixture)
93
94void
95onUpdate(const vector<MissingDataInfo>& v)
96{
97}
98
99BOOST_AUTO_TEST_CASE(Constructor)
100{
101 Name syncPrefix("/ndn/broadcast/sync");
102 Name userPrefix("/user");
103 ndn::Face face;
104 BOOST_REQUIRE_NO_THROW(Logic(face, syncPrefix, userPrefix,
105 bind(onUpdate, _1)));
106}
107
108BOOST_AUTO_TEST_CASE(TwoBasic)
109{
110 scheduler.scheduleEvent(ndn::time::milliseconds(100),
Qiuhan Ding8c095fd2014-11-19 17:38:32 -0800111 [this] { handler[0] = make_shared<Handler>(ref(*faces[0]), syncPrefix, userPrefix[0]); });
Yingdi Yuf7ede412014-08-30 20:37:52 -0700112
113 scheduler.scheduleEvent(ndn::time::milliseconds(200),
Qiuhan Ding8c095fd2014-11-19 17:38:32 -0800114 [this] { handler[1] = make_shared<Handler>(ref(*faces[1]), syncPrefix, userPrefix[1]); });
Yingdi Yuf7ede412014-08-30 20:37:52 -0700115
Qiuhan Ding8c095fd2014-11-19 17:38:32 -0800116 scheduler.scheduleEvent(ndn::time::milliseconds(300), [this] { handler[0]->updateSeqNo(1); });
Yingdi Yuf7ede412014-08-30 20:37:52 -0700117
118 scheduler.scheduleEvent(ndn::time::milliseconds(1000),
Qiuhan Ding8c095fd2014-11-19 17:38:32 -0800119 [this] { BOOST_CHECK_EQUAL(handler[1]->map[handler[0]->logic.getSessionName()], 1); });
Yingdi Yuf7ede412014-08-30 20:37:52 -0700120
Qiuhan Ding8c095fd2014-11-19 17:38:32 -0800121 scheduler.scheduleEvent(ndn::time::milliseconds(1100), [this] { handler[0]->updateSeqNo(2); });
Yingdi Yuf7ede412014-08-30 20:37:52 -0700122
123 scheduler.scheduleEvent(ndn::time::milliseconds(1800),
Qiuhan Ding8c095fd2014-11-19 17:38:32 -0800124 [this] { BOOST_CHECK_EQUAL(handler[1]->map[handler[0]->logic.getSessionName()], 2); });
Yingdi Yuf7ede412014-08-30 20:37:52 -0700125
Qiuhan Ding8c095fd2014-11-19 17:38:32 -0800126 scheduler.scheduleEvent(ndn::time::milliseconds(1900), [this] { handler[1]->updateSeqNo(2); });
Yingdi Yuf7ede412014-08-30 20:37:52 -0700127
128 scheduler.scheduleEvent(ndn::time::milliseconds(2600),
Qiuhan Ding8c095fd2014-11-19 17:38:32 -0800129 [this] { BOOST_CHECK_EQUAL(handler[0]->map[handler[1]->logic.getSessionName()], 2); });
Yingdi Yuf7ede412014-08-30 20:37:52 -0700130
Qiuhan Ding8c095fd2014-11-19 17:38:32 -0800131 scheduler.scheduleEvent(ndn::time::milliseconds(2800), [this] { io.stop(); });
Yingdi Yuf7ede412014-08-30 20:37:52 -0700132
133 io.run();
134}
135
136BOOST_AUTO_TEST_CASE(ThreeBasic)
137{
138 scheduler.scheduleEvent(ndn::time::milliseconds(100),
Qiuhan Ding8c095fd2014-11-19 17:38:32 -0800139 [this] { handler[0] = make_shared<Handler>(ref(*faces[0]), syncPrefix, userPrefix[0]); });
Yingdi Yuf7ede412014-08-30 20:37:52 -0700140
141 scheduler.scheduleEvent(ndn::time::milliseconds(200),
Qiuhan Ding8c095fd2014-11-19 17:38:32 -0800142 [this] { handler[1] = make_shared<Handler>(ref(*faces[1]), syncPrefix, userPrefix[1]); });
Yingdi Yuf7ede412014-08-30 20:37:52 -0700143
144 scheduler.scheduleEvent(ndn::time::milliseconds(300),
Qiuhan Ding8c095fd2014-11-19 17:38:32 -0800145 [this] { handler[2] = make_shared<Handler>(ref(*faces[2]), syncPrefix, userPrefix[2]); });
Yingdi Yuf7ede412014-08-30 20:37:52 -0700146
Qiuhan Ding8c095fd2014-11-19 17:38:32 -0800147 scheduler.scheduleEvent(ndn::time::milliseconds(500), [this] { handler[0]->updateSeqNo(1); });
Yingdi Yuf7ede412014-08-30 20:37:52 -0700148
149 scheduler.scheduleEvent(ndn::time::milliseconds(1400),
Qiuhan Ding8c095fd2014-11-19 17:38:32 -0800150 [this] { BOOST_CHECK_EQUAL(handler[1]->map[handler[0]->logic.getSessionName()], 1); });
Yingdi Yuf7ede412014-08-30 20:37:52 -0700151
152 scheduler.scheduleEvent(ndn::time::milliseconds(1450),
Qiuhan Ding8c095fd2014-11-19 17:38:32 -0800153 [this] { BOOST_CHECK_EQUAL(handler[2]->map[handler[0]->logic.getSessionName()], 1); });
Yingdi Yuf7ede412014-08-30 20:37:52 -0700154
Qiuhan Ding8c095fd2014-11-19 17:38:32 -0800155 scheduler.scheduleEvent(ndn::time::milliseconds(1500), [this] { handler[1]->updateSeqNo(2); });
Yingdi Yuf7ede412014-08-30 20:37:52 -0700156
157 scheduler.scheduleEvent(ndn::time::milliseconds(2400),
Qiuhan Ding8c095fd2014-11-19 17:38:32 -0800158 [this] { BOOST_CHECK_EQUAL(handler[0]->map[handler[1]->logic.getSessionName()], 2); });
Yingdi Yuf7ede412014-08-30 20:37:52 -0700159
160 scheduler.scheduleEvent(ndn::time::milliseconds(2450),
Qiuhan Ding8c095fd2014-11-19 17:38:32 -0800161 [this] { BOOST_CHECK_EQUAL(handler[2]->map[handler[1]->logic.getSessionName()], 2); });
Yingdi Yuf7ede412014-08-30 20:37:52 -0700162
Qiuhan Ding8c095fd2014-11-19 17:38:32 -0800163 scheduler.scheduleEvent(ndn::time::milliseconds(2500), [this] { handler[2]->updateSeqNo(4); });
Yingdi Yuf7ede412014-08-30 20:37:52 -0700164
165 scheduler.scheduleEvent(ndn::time::milliseconds(4400),
Qiuhan Ding8c095fd2014-11-19 17:38:32 -0800166 [this] { BOOST_CHECK_EQUAL(handler[0]->map[handler[2]->logic.getSessionName()], 4); });
Yingdi Yuf7ede412014-08-30 20:37:52 -0700167
168 scheduler.scheduleEvent(ndn::time::milliseconds(4450),
Qiuhan Ding8c095fd2014-11-19 17:38:32 -0800169 [this] { BOOST_CHECK_EQUAL(handler[1]->map[handler[2]->logic.getSessionName()], 4); });
Yingdi Yuf7ede412014-08-30 20:37:52 -0700170
Qiuhan Ding8c095fd2014-11-19 17:38:32 -0800171 scheduler.scheduleEvent(ndn::time::milliseconds(4500), [this] { io.stop(); });
Yingdi Yuf7ede412014-08-30 20:37:52 -0700172
173 io.run();
174}
175
176BOOST_AUTO_TEST_CASE(ResetRecover)
177{
178 scheduler.scheduleEvent(ndn::time::milliseconds(100),
Qiuhan Ding8c095fd2014-11-19 17:38:32 -0800179 [this] { handler[0] = make_shared<Handler>(ref(*faces[0]), syncPrefix, userPrefix[0]); });
Yingdi Yuf7ede412014-08-30 20:37:52 -0700180
181 scheduler.scheduleEvent(ndn::time::milliseconds(200),
Qiuhan Ding8c095fd2014-11-19 17:38:32 -0800182 [this] { handler[1] = make_shared<Handler>(ref(*faces[1]), syncPrefix, userPrefix[1]); });
Yingdi Yuf7ede412014-08-30 20:37:52 -0700183
Qiuhan Ding8c095fd2014-11-19 17:38:32 -0800184 scheduler.scheduleEvent(ndn::time::milliseconds(500), [this] { handler[0]->updateSeqNo(1); });
Yingdi Yuf7ede412014-08-30 20:37:52 -0700185
186 scheduler.scheduleEvent(ndn::time::milliseconds(1400),
Qiuhan Ding8c095fd2014-11-19 17:38:32 -0800187 [this] { BOOST_CHECK_EQUAL(handler[1]->map[handler[0]->logic.getSessionName()], 1); });
Yingdi Yuf7ede412014-08-30 20:37:52 -0700188
Qiuhan Ding8c095fd2014-11-19 17:38:32 -0800189 scheduler.scheduleEvent(ndn::time::milliseconds(1500), [this] { handler[1]->updateSeqNo(2); });
Yingdi Yuf7ede412014-08-30 20:37:52 -0700190
191 scheduler.scheduleEvent(ndn::time::milliseconds(2400),
Qiuhan Ding8c095fd2014-11-19 17:38:32 -0800192 [this] { BOOST_CHECK_EQUAL(handler[0]->map[handler[1]->logic.getSessionName()], 2); });
Yingdi Yuf7ede412014-08-30 20:37:52 -0700193
194 scheduler.scheduleEvent(ndn::time::milliseconds(2500),
Qiuhan Ding8c095fd2014-11-19 17:38:32 -0800195 [this] { handler[2] = make_shared<Handler>(ref(*faces[2]), syncPrefix, userPrefix[2]); });
Yingdi Yuf7ede412014-08-30 20:37:52 -0700196
197 scheduler.scheduleEvent(ndn::time::milliseconds(3000),
Qiuhan Ding8c095fd2014-11-19 17:38:32 -0800198 [this] { BOOST_CHECK_EQUAL(handler[1]->map[handler[0]->logic.getSessionName()], 1); });
Yingdi Yuf7ede412014-08-30 20:37:52 -0700199
200 scheduler.scheduleEvent(ndn::time::milliseconds(3050),
Qiuhan Ding8c095fd2014-11-19 17:38:32 -0800201 [this] { BOOST_CHECK_EQUAL(handler[0]->map[handler[1]->logic.getSessionName()], 2); });
Yingdi Yuf7ede412014-08-30 20:37:52 -0700202
Qiuhan Ding8c095fd2014-11-19 17:38:32 -0800203 scheduler.scheduleEvent(ndn::time::milliseconds(3100), [this] { handler[2]->updateSeqNo(4); });
Yingdi Yuf7ede412014-08-30 20:37:52 -0700204
205 scheduler.scheduleEvent(ndn::time::milliseconds(4000),
Qiuhan Ding8c095fd2014-11-19 17:38:32 -0800206 [this] { BOOST_CHECK_EQUAL(handler[1]->map[handler[2]->logic.getSessionName()], 4); });
Yingdi Yuf7ede412014-08-30 20:37:52 -0700207
208 scheduler.scheduleEvent(ndn::time::milliseconds(4050),
Qiuhan Ding8c095fd2014-11-19 17:38:32 -0800209 [this] { BOOST_CHECK_EQUAL(handler[0]->map[handler[2]->logic.getSessionName()], 4); });
Yingdi Yuf7ede412014-08-30 20:37:52 -0700210
211
Qiuhan Ding8c095fd2014-11-19 17:38:32 -0800212 scheduler.scheduleEvent(ndn::time::milliseconds(4500), [this] { io.stop(); });
Yingdi Yuf7ede412014-08-30 20:37:52 -0700213
214 io.run();
215}
216
217BOOST_AUTO_TEST_CASE(RecoverConflict)
218{
219 scheduler.scheduleEvent(ndn::time::milliseconds(0),
Qiuhan Ding8c095fd2014-11-19 17:38:32 -0800220 [this] { handler[0] = make_shared<Handler>(ref(*faces[0]), syncPrefix, userPrefix[0]); });
Yingdi Yuf7ede412014-08-30 20:37:52 -0700221
222 scheduler.scheduleEvent(ndn::time::milliseconds(50),
Qiuhan Ding8c095fd2014-11-19 17:38:32 -0800223 [this] { handler[1] = make_shared<Handler>(ref(*faces[1]), syncPrefix, userPrefix[1]); });
Yingdi Yuf7ede412014-08-30 20:37:52 -0700224
225 scheduler.scheduleEvent(ndn::time::milliseconds(100),
Qiuhan Ding8c095fd2014-11-19 17:38:32 -0800226 [this] { handler[2] = make_shared<Handler>(ref(*faces[2]), syncPrefix, userPrefix[2]); });
Yingdi Yuf7ede412014-08-30 20:37:52 -0700227
Qiuhan Ding8c095fd2014-11-19 17:38:32 -0800228 scheduler.scheduleEvent(ndn::time::milliseconds(500), [this] { handler[0]->updateSeqNo(1); });
Yingdi Yuf7ede412014-08-30 20:37:52 -0700229
230 scheduler.scheduleEvent(ndn::time::milliseconds(1400),
Qiuhan Ding8c095fd2014-11-19 17:38:32 -0800231 [this] { BOOST_CHECK_EQUAL(handler[1]->map[handler[0]->logic.getSessionName()], 1); });
Yingdi Yuf7ede412014-08-30 20:37:52 -0700232
233 scheduler.scheduleEvent(ndn::time::milliseconds(1400),
Qiuhan Ding8c095fd2014-11-19 17:38:32 -0800234 [this] { BOOST_CHECK_EQUAL(handler[2]->map[handler[0]->logic.getSessionName()], 1); });
Yingdi Yuf7ede412014-08-30 20:37:52 -0700235
Qiuhan Ding8c095fd2014-11-19 17:38:32 -0800236 scheduler.scheduleEvent(ndn::time::milliseconds(1500), [this] { handler[1]->updateSeqNo(2); });
Yingdi Yuf7ede412014-08-30 20:37:52 -0700237
Qiuhan Ding8c095fd2014-11-19 17:38:32 -0800238 scheduler.scheduleEvent(ndn::time::milliseconds(1500), [this] { handler[2]->updateSeqNo(4); });
Yingdi Yuf7ede412014-08-30 20:37:52 -0700239
240 scheduler.scheduleEvent(ndn::time::milliseconds(2400),
Qiuhan Ding8c095fd2014-11-19 17:38:32 -0800241 [this] { BOOST_CHECK_EQUAL(handler[0]->map[handler[1]->logic.getSessionName()], 2); });
Yingdi Yuf7ede412014-08-30 20:37:52 -0700242
243 scheduler.scheduleEvent(ndn::time::milliseconds(2450),
Qiuhan Ding8c095fd2014-11-19 17:38:32 -0800244 [this] { BOOST_CHECK_EQUAL(handler[0]->map[handler[2]->logic.getSessionName()], 4); });
Yingdi Yuf7ede412014-08-30 20:37:52 -0700245
246 scheduler.scheduleEvent(ndn::time::milliseconds(2500),
Qiuhan Ding8c095fd2014-11-19 17:38:32 -0800247 [this] { BOOST_CHECK_EQUAL(handler[1]->map[handler[2]->logic.getSessionName()], 4); });
Yingdi Yuf7ede412014-08-30 20:37:52 -0700248
249 scheduler.scheduleEvent(ndn::time::milliseconds(2550),
Qiuhan Ding8c095fd2014-11-19 17:38:32 -0800250 [this] { BOOST_CHECK_EQUAL(handler[2]->map[handler[1]->logic.getSessionName()], 2); });
Yingdi Yuf7ede412014-08-30 20:37:52 -0700251
Qiuhan Ding8c095fd2014-11-19 17:38:32 -0800252 scheduler.scheduleEvent(ndn::time::milliseconds(4500), [this] { io.stop(); });
Yingdi Yuf7ede412014-08-30 20:37:52 -0700253
254 io.run();
255}
256
Qiuhan Ding8c095fd2014-11-19 17:38:32 -0800257BOOST_AUTO_TEST_CASE(MultipleUserUnderOneLogic)
258{
259 scheduler.scheduleEvent(ndn::time::milliseconds(0),
260 [this] { handler[0] = make_shared<Handler>(ref(*faces[0]), syncPrefix, userPrefix[0]); });
261
262 scheduler.scheduleEvent(ndn::time::milliseconds(50),
263 [this] { handler[1] = make_shared<Handler>(ref(*faces[1]), syncPrefix, userPrefix[2]); });
264
265 scheduler.scheduleEvent(ndn::time::milliseconds(100),
266 [this] { handler[0]->logic.addUserNode(userPrefix[1]); });
267
268 scheduler.scheduleEvent(ndn::time::milliseconds(500), [this] { handler[0]->updateSeqNo(1); });
269
270 scheduler.scheduleEvent(ndn::time::milliseconds(1400),
271 [this] { BOOST_CHECK_EQUAL(handler[1]->map[handler[0]->logic.getSessionName()], 1); });
272
273 scheduler.scheduleEvent(ndn::time::milliseconds(1500),
274 [this] { handler[0]->logic.updateSeqNo(2, userPrefix[1]); });
275
276 scheduler.scheduleEvent(ndn::time::milliseconds(2400),
277 [this] {
278 Name sessionName = handler[0]->logic.getSessionName(userPrefix[1]);
279 BOOST_CHECK_EQUAL(handler[1]->map[sessionName], 2);
280 });
281
282 scheduler.scheduleEvent(ndn::time::milliseconds(2500), [this] { handler[1]->updateSeqNo(4); });
283
284 scheduler.scheduleEvent(ndn::time::milliseconds(3200),
285 [this] { BOOST_CHECK_EQUAL(handler[0]->map[handler[1]->logic.getSessionName()], 4); });
286
287 scheduler.scheduleEvent(ndn::time::milliseconds(3300),
288 [this] { handler[0]->logic.removeUserNode(userPrefix[0]); });
289
290 scheduler.scheduleEvent(ndn::time::milliseconds(4500),
291 [this] { BOOST_CHECK_EQUAL(handler[1]->logic.getSessionNames().size(), 2); });
292
293 scheduler.scheduleEvent(ndn::time::milliseconds(5000), [this] { io.stop(); });
294
295 io.run();
296}
Yingdi Yuf7ede412014-08-30 20:37:52 -0700297
298BOOST_AUTO_TEST_SUITE_END()
299
300} // namespace test
301} // namespace chronosync