blob: 342af4c8abe076f23d6c8e3ff8d2c49f649c76d0 [file] [log] [blame]
Qiuhan Dingfb8c9e02015-01-30 14:04:55 -08001/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil -*- */
2/*
Sonu Mishra4d3a2e02017-01-18 20:27:51 -08003 * Copyright (c) 2012-2017 University of California, Los Angeles
Qiuhan Dingfb8c9e02015-01-30 14:04:55 -08004 *
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#include "../unit-test-time-fixture.hpp"
22#include <ndn-cxx/util/dummy-client-face.hpp>
23#include "boost-test.hpp"
24
25namespace chronosync {
26namespace test {
27
28using std::vector;
29using ndn::util::DummyClientFace;
Qiuhan Dingfb8c9e02015-01-30 14:04:55 -080030
31class Handler
32{
33public:
34 Handler(DummyClientFace& face,
35 const Name& syncPrefix,
36 const Name& userPrefix)
37 : logic(face,
38 syncPrefix,
39 userPrefix,
40 bind(&Handler::onUpdate, this, _1))
41 {
42 }
43
44 void
45 onUpdate(const vector<MissingDataInfo>& v)
46 {
47 for (size_t i = 0; i < v.size(); i++) {
48 update(v[i].session, v[i].high, v[i].low);
49 }
50 }
51
52 void
53 update(const Name& p, const SeqNo& high, const SeqNo& low)
54 {
55 map[p] = high;
56 }
57
58 void
59 updateSeqNo(const SeqNo& seqNo)
60 {
61 logic.updateSeqNo(seqNo);
62 }
63
Junxiao Shi0c7f56a2016-07-14 15:27:14 +000064public:
Qiuhan Dingfb8c9e02015-01-30 14:04:55 -080065 Logic logic;
66 std::map<Name, SeqNo> map;
67};
68
69class LogicFixture : public ndn::tests::UnitTestTimeFixture
70{
71public:
72 LogicFixture()
73 : syncPrefix("/ndn/broadcast/sync")
74 {
75 syncPrefix.appendVersion();
76 userPrefix[0] = Name("/user0");
77 userPrefix[1] = Name("/user1");
78 userPrefix[2] = Name("/user2");
Sonu Mishra4d3a2e02017-01-18 20:27:51 -080079 userPrefix[3] = Name("/user3");
Qiuhan Dingfb8c9e02015-01-30 14:04:55 -080080
Junxiao Shi0c7f56a2016-07-14 15:27:14 +000081 faces[0].reset(new DummyClientFace(io, {true, true}));
82 faces[1].reset(new DummyClientFace(io, {true, true}));
83 faces[2].reset(new DummyClientFace(io, {true, true}));
Sonu Mishra4d3a2e02017-01-18 20:27:51 -080084 faces[3].reset(new DummyClientFace(io, {true, true}));
Qiuhan Dingfb8c9e02015-01-30 14:04:55 -080085
Sonu Mishra4d3a2e02017-01-18 20:27:51 -080086 for (int i = 0; i < 4; i++) {
Qiuhan Dingfb8c9e02015-01-30 14:04:55 -080087 readInterestOffset[i] = 0;
88 readDataOffset[i] = 0;
89 }
90 }
91
92 void
93 passPacket()
94 {
Sonu Mishra4d3a2e02017-01-18 20:27:51 -080095 for (int i = 0; i < 4; i++)
Qiuhan Dingfb8c9e02015-01-30 14:04:55 -080096 checkFace(i);
97 }
98
99 void
100 checkFace(int sender)
101 {
102 while (faces[sender]->sentInterests.size() > readInterestOffset[sender]) {
Sonu Mishra4d3a2e02017-01-18 20:27:51 -0800103 for (int i = 0; i < 4; i++) {
Qiuhan Dingfb8c9e02015-01-30 14:04:55 -0800104 if (sender != i)
105 faces[i]->receive(faces[sender]->sentInterests[readInterestOffset[sender]]);
106 }
107 readInterestOffset[sender]++;
108 }
Junxiao Shi0c7f56a2016-07-14 15:27:14 +0000109 while (faces[sender]->sentData.size() > readDataOffset[sender]) {
Sonu Mishra4d3a2e02017-01-18 20:27:51 -0800110 for (int i = 0; i < 4; i++) {
Qiuhan Dingfb8c9e02015-01-30 14:04:55 -0800111 if (sender != i)
Junxiao Shi0c7f56a2016-07-14 15:27:14 +0000112 faces[i]->receive(faces[sender]->sentData[readDataOffset[sender]]);
Qiuhan Dingfb8c9e02015-01-30 14:04:55 -0800113 }
114 readDataOffset[sender]++;
115 }
116 }
117
Junxiao Shi0c7f56a2016-07-14 15:27:14 +0000118public:
Qiuhan Dingfb8c9e02015-01-30 14:04:55 -0800119 Name syncPrefix;
Sonu Mishra4d3a2e02017-01-18 20:27:51 -0800120 Name userPrefix[4];
Qiuhan Dingfb8c9e02015-01-30 14:04:55 -0800121
Sonu Mishra4d3a2e02017-01-18 20:27:51 -0800122 std::unique_ptr<DummyClientFace> faces[4];
123 shared_ptr<Handler> handler[4];
Qiuhan Dingfb8c9e02015-01-30 14:04:55 -0800124
Sonu Mishra4d3a2e02017-01-18 20:27:51 -0800125 size_t readInterestOffset[4];
126 size_t readDataOffset[4];
Qiuhan Dingfb8c9e02015-01-30 14:04:55 -0800127};
128
129BOOST_FIXTURE_TEST_SUITE(LogicTests, LogicFixture)
130
131void
132onUpdate(const vector<MissingDataInfo>& v)
133{
134}
135
136BOOST_AUTO_TEST_CASE(Constructor)
137{
138 Name syncPrefix("/ndn/broadcast/sync");
139 Name userPrefix("/user");
Junxiao Shi0c7f56a2016-07-14 15:27:14 +0000140 DummyClientFace face(io, {true, true});
141 BOOST_REQUIRE_NO_THROW(Logic(face, syncPrefix, userPrefix,
Qiuhan Dingfb8c9e02015-01-30 14:04:55 -0800142 bind(onUpdate, _1)));
143}
144
145BOOST_AUTO_TEST_CASE(TwoBasic)
146{
147 handler[0] = make_shared<Handler>(ref(*faces[0]), syncPrefix, userPrefix[0]);
148 advanceClocks(ndn::time::milliseconds(10), 10);
149
150 handler[1] = make_shared<Handler>(ref(*faces[1]), syncPrefix, userPrefix[1]);
151 advanceClocks(ndn::time::milliseconds(10), 10);
152
153 handler[0]->updateSeqNo(1);
154
155 for (int i = 0; i < 50; i++) {
156 advanceClocks(ndn::time::milliseconds(2), 10);
157 passPacket();
158 }
159 BOOST_CHECK_EQUAL(handler[1]->map[handler[0]->logic.getSessionName()], 1);
160 advanceClocks(ndn::time::milliseconds(10), 10);
161
162 handler[0]->updateSeqNo(2);
163
164 for (int i = 0; i < 50; i++) {
165 advanceClocks(ndn::time::milliseconds(2), 10);
166 passPacket();
167 }
168 BOOST_CHECK_EQUAL(handler[1]->map[handler[0]->logic.getSessionName()], 2);
169 advanceClocks(ndn::time::milliseconds(10), 10);
170
171 handler[1]->updateSeqNo(2);
172
173 for (int i = 0; i < 50; i++) {
174 advanceClocks(ndn::time::milliseconds(2), 10);
175 passPacket();
176 }
177 BOOST_CHECK_EQUAL(handler[0]->map[handler[1]->logic.getSessionName()], 2);
178}
179
180BOOST_AUTO_TEST_CASE(ThreeBasic)
181{
182 handler[0] = make_shared<Handler>(ref(*faces[0]), syncPrefix, userPrefix[0]);
183 advanceClocks(ndn::time::milliseconds(10), 10);
184
185 handler[1] = make_shared<Handler>(ref(*faces[1]), syncPrefix, userPrefix[1]);
186 advanceClocks(ndn::time::milliseconds(10), 10);
187
188 handler[2] = make_shared<Handler>(ref(*faces[2]), syncPrefix, userPrefix[2]);
189 advanceClocks(ndn::time::milliseconds(10), 20);
190
191 handler[0]->updateSeqNo(1);
192
193 for (int i = 0; i < 70; i++) {
194 advanceClocks(ndn::time::milliseconds(2), 10);
195 passPacket();
196 }
197 BOOST_CHECK_EQUAL(handler[1]->map[handler[0]->logic.getSessionName()], 1);
198 BOOST_CHECK_EQUAL(handler[2]->map[handler[0]->logic.getSessionName()], 1);
199
200 handler[1]->updateSeqNo(2);
201
202 for (int i = 0; i < 50; i++) {
203 advanceClocks(ndn::time::milliseconds(2), 10);
204 passPacket();
205 }
206 BOOST_CHECK_EQUAL(handler[0]->map[handler[1]->logic.getSessionName()], 2);
207 BOOST_CHECK_EQUAL(handler[2]->map[handler[1]->logic.getSessionName()], 2);
208
209 handler[2]->updateSeqNo(4);
210
211 for (int i = 0; i < 100; i++) {
212 advanceClocks(ndn::time::milliseconds(2), 10);
213 passPacket();
214 }
215 BOOST_CHECK_EQUAL(handler[0]->map[handler[2]->logic.getSessionName()], 4);
216 BOOST_CHECK_EQUAL(handler[1]->map[handler[2]->logic.getSessionName()], 4);
217}
218
219BOOST_AUTO_TEST_CASE(ResetRecover)
220{
221 handler[0] = make_shared<Handler>(ref(*faces[0]), syncPrefix, userPrefix[0]);
222 advanceClocks(ndn::time::milliseconds(10), 10);
223
224 handler[1] = make_shared<Handler>(ref(*faces[1]), syncPrefix, userPrefix[1]);
225 advanceClocks(ndn::time::milliseconds(10), 30);
226
227 handler[0]->updateSeqNo(1);
228
229 for (int i = 0; i < 50; i++) {
230 advanceClocks(ndn::time::milliseconds(2), 10);
231 passPacket();
232 }
233 BOOST_CHECK_EQUAL(handler[1]->map[handler[0]->logic.getSessionName()], 1);
234
235 handler[1]->updateSeqNo(2);
236
237 for (int i = 0; i < 50; i++) {
238 advanceClocks(ndn::time::milliseconds(2), 10);
239 passPacket();
240 }
241 BOOST_CHECK_EQUAL(handler[0]->map[handler[1]->logic.getSessionName()], 2);
242
243 advanceClocks(ndn::time::milliseconds(10), 10);
244 handler[2] = make_shared<Handler>(ref(*faces[2]), syncPrefix, userPrefix[2]);
245
246 for (int i = 0; i < 50; i++) {
247 advanceClocks(ndn::time::milliseconds(2), 10);
248 passPacket();
249 }
Sonu Mishra4d3a2e02017-01-18 20:27:51 -0800250 BOOST_CHECK_EQUAL(handler[2]->map[handler[0]->logic.getSessionName()], 1);
251 BOOST_CHECK_EQUAL(handler[2]->map[handler[1]->logic.getSessionName()], 2);
Qiuhan Dingfb8c9e02015-01-30 14:04:55 -0800252
253 handler[2]->updateSeqNo(4);
254
255 for (int i = 0; i < 50; i++) {
256 advanceClocks(ndn::time::milliseconds(2), 10);
257 passPacket();
258 }
259 BOOST_CHECK_EQUAL(handler[1]->map[handler[2]->logic.getSessionName()], 4);
260 BOOST_CHECK_EQUAL(handler[0]->map[handler[2]->logic.getSessionName()], 4);
261}
262
263BOOST_AUTO_TEST_CASE(RecoverConflict)
264{
265 handler[0] = make_shared<Handler>(ref(*faces[0]), syncPrefix, userPrefix[0]);
266 advanceClocks(ndn::time::milliseconds(10), 10);
267
268 handler[1] = make_shared<Handler>(ref(*faces[1]), syncPrefix, userPrefix[1]);
269 advanceClocks(ndn::time::milliseconds(10), 10);
270
271 handler[2] = make_shared<Handler>(ref(*faces[2]), syncPrefix, userPrefix[2]);
272 advanceClocks(ndn::time::milliseconds(10), 30);
273
274 handler[0]->updateSeqNo(1);
275
276 for (int i = 0; i < 50; i++) {
277 advanceClocks(ndn::time::milliseconds(2), 10);
278 passPacket();
279 }
280 BOOST_CHECK_EQUAL(handler[1]->map[handler[0]->logic.getSessionName()], 1);
281 BOOST_CHECK_EQUAL(handler[2]->map[handler[0]->logic.getSessionName()], 1);
282
283 handler[1]->updateSeqNo(2);
284 handler[2]->updateSeqNo(4);
285
286 for (int i = 0; i < 75; i++) {
287 advanceClocks(ndn::time::milliseconds(2), 10);
288 passPacket();
289 }
290 BOOST_CHECK_EQUAL(handler[0]->map[handler[1]->logic.getSessionName()], 2);
291 BOOST_CHECK_EQUAL(handler[0]->map[handler[2]->logic.getSessionName()], 4);
292 BOOST_CHECK_EQUAL(handler[1]->map[handler[2]->logic.getSessionName()], 4);
293 BOOST_CHECK_EQUAL(handler[2]->map[handler[1]->logic.getSessionName()], 2);
294}
295
Sonu Mishra4d3a2e02017-01-18 20:27:51 -0800296BOOST_AUTO_TEST_CASE(PartitionRecover)
297{
298 handler[0] = make_shared<Handler>(ref(*faces[0]), syncPrefix, userPrefix[0]);
299 advanceClocks(ndn::time::milliseconds(10), 10);
300
301 handler[1] = make_shared<Handler>(ref(*faces[1]), syncPrefix, userPrefix[1]);
302 advanceClocks(ndn::time::milliseconds(10), 10);
303
304 handler[2] = make_shared<Handler>(ref(*faces[2]), syncPrefix, userPrefix[2]);
305 advanceClocks(ndn::time::milliseconds(10), 10);
306
307 handler[3] = make_shared<Handler>(ref(*faces[3]), syncPrefix, userPrefix[3]);
308 advanceClocks(ndn::time::milliseconds(10), 30);
309
310 handler[0]->updateSeqNo(1);
311
312 for (int i = 0; i < 50; i++) {
313 advanceClocks(ndn::time::milliseconds(2), 10);
314 passPacket();
315 }
316 BOOST_CHECK_EQUAL(handler[1]->map[handler[0]->logic.getSessionName()], 1);
317 BOOST_CHECK_EQUAL(handler[2]->map[handler[0]->logic.getSessionName()], 1);
318 BOOST_CHECK_EQUAL(handler[3]->map[handler[0]->logic.getSessionName()], 1);
319
320 handler[2]->updateSeqNo(2);
321
322 for (int i = 0; i < 50; i++) {
323 advanceClocks(ndn::time::milliseconds(2), 10);
324 passPacket();
325 }
326 BOOST_CHECK_EQUAL(handler[0]->map[handler[2]->logic.getSessionName()], 2);
327 BOOST_CHECK_EQUAL(handler[1]->map[handler[2]->logic.getSessionName()], 2);
328 BOOST_CHECK_EQUAL(handler[3]->map[handler[2]->logic.getSessionName()], 2);
329
330 // Network Partition start
331
332 handler[1]->updateSeqNo(3);
333
334 for (int i = 0; i < 50; i++) {
335 advanceClocks(ndn::time::milliseconds(2), 10);
336 passPacket();
337 }
338 BOOST_CHECK_EQUAL(handler[0]->map[handler[1]->logic.getSessionName()], 3);
339 handler[2]->map[handler[1]->logic.getSessionName()] = 0;
340 handler[3]->map[handler[1]->logic.getSessionName()] = 0;
341
342 handler[3]->updateSeqNo(4);
343
344 for (int i = 0; i < 50; i++) {
345 advanceClocks(ndn::time::milliseconds(2), 10);
346 passPacket();
347 }
348 BOOST_CHECK_EQUAL(handler[2]->map[handler[3]->logic.getSessionName()], 4);
349 handler[0]->map[handler[3]->logic.getSessionName()] = 0;
350 handler[1]->map[handler[3]->logic.getSessionName()] = 0;
351
352 // Network partition over
353
354 handler[0]->updateSeqNo(5);
355
356 for (int i = 0; i < 50; i++) {
357 advanceClocks(ndn::time::milliseconds(2), 10);
358 passPacket();
359 }
360 BOOST_CHECK_EQUAL(handler[1]->map[handler[0]->logic.getSessionName()], 5);
361 BOOST_CHECK_EQUAL(handler[2]->map[handler[0]->logic.getSessionName()], 5);
362 BOOST_CHECK_EQUAL(handler[3]->map[handler[0]->logic.getSessionName()], 5);
363
364 handler[2]->updateSeqNo(6);
365
366 for (int i = 0; i < 50; i++) {
367 advanceClocks(ndn::time::milliseconds(2), 10);
368 passPacket();
369 }
370 BOOST_CHECK_EQUAL(handler[0]->map[handler[2]->logic.getSessionName()], 6);
371 BOOST_CHECK_EQUAL(handler[1]->map[handler[2]->logic.getSessionName()], 6);
372 BOOST_CHECK_EQUAL(handler[3]->map[handler[2]->logic.getSessionName()], 6);
373}
374
Qiuhan Dingfb8c9e02015-01-30 14:04:55 -0800375BOOST_AUTO_TEST_CASE(MultipleUserUnderOneLogic)
376{
377 handler[0] = make_shared<Handler>(ref(*faces[0]), syncPrefix, userPrefix[0]);
378 advanceClocks(ndn::time::milliseconds(10), 10);
379
380 handler[1] = make_shared<Handler>(ref(*faces[1]), syncPrefix, userPrefix[2]);
381 advanceClocks(ndn::time::milliseconds(10), 10);
382
383 handler[0]->logic.addUserNode(userPrefix[1]);
384
385 for (int i = 0; i < 20; i++) {
386 advanceClocks(ndn::time::milliseconds(2), 10);
387 passPacket();
388 }
389
390 handler[0]->updateSeqNo(1);
391
392 for (int i = 0; i < 50; i++) {
393 advanceClocks(ndn::time::milliseconds(2), 10);
394 passPacket();
395 }
396 BOOST_CHECK_EQUAL(handler[1]->map[handler[0]->logic.getSessionName()], 1);
397
398 handler[0]->logic.updateSeqNo(2, userPrefix[1]);
399
400 for (int i = 0; i < 50; i++) {
401 advanceClocks(ndn::time::milliseconds(2), 10);
402 passPacket();
403 }
404 BOOST_CHECK_EQUAL(handler[1]->map[handler[0]->logic.getSessionName(userPrefix[1])], 2);
405
406 handler[1]->updateSeqNo(4);
407
408 for (int i = 0; i < 50; i++) {
409 advanceClocks(ndn::time::milliseconds(2), 10);
410 passPacket();
411 }
412 BOOST_CHECK_EQUAL(handler[0]->map[handler[1]->logic.getSessionName()], 4);
413
414 handler[0]->logic.removeUserNode(userPrefix[0]);
415
416 for (int i = 0; i < 100; i++) {
417 advanceClocks(ndn::time::milliseconds(2), 10);
418 passPacket();
419 }
420 BOOST_CHECK_EQUAL(handler[1]->logic.getSessionNames().size(), 2);
421}
422
423BOOST_AUTO_TEST_SUITE_END()
424
425} // namespace test
426} // namespace chronosync