blob: ed860af4a9e74abebb6271af86e43b53a2d1fd61 [file] [log] [blame]
Qiuhan Dingfb8c9e02015-01-30 14:04:55 -08001/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil -*- */
2/*
Junxiao Shi0c7f56a2016-07-14 15:27:14 +00003 * Copyright (c) 2012-2016 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");
79
Junxiao Shi0c7f56a2016-07-14 15:27:14 +000080 faces[0].reset(new DummyClientFace(io, {true, true}));
81 faces[1].reset(new DummyClientFace(io, {true, true}));
82 faces[2].reset(new DummyClientFace(io, {true, true}));
Qiuhan Dingfb8c9e02015-01-30 14:04:55 -080083
84 for (int i = 0; i < 3; i++) {
85 readInterestOffset[i] = 0;
86 readDataOffset[i] = 0;
87 }
88 }
89
90 void
91 passPacket()
92 {
93 for (int i = 0; i < 3; i++)
94 checkFace(i);
95 }
96
97 void
98 checkFace(int sender)
99 {
100 while (faces[sender]->sentInterests.size() > readInterestOffset[sender]) {
101 for (int i = 0; i < 3; i++) {
102 if (sender != i)
103 faces[i]->receive(faces[sender]->sentInterests[readInterestOffset[sender]]);
104 }
105 readInterestOffset[sender]++;
106 }
Junxiao Shi0c7f56a2016-07-14 15:27:14 +0000107 while (faces[sender]->sentData.size() > readDataOffset[sender]) {
Qiuhan Dingfb8c9e02015-01-30 14:04:55 -0800108 for (int i = 0; i < 3; i++) {
109 if (sender != i)
Junxiao Shi0c7f56a2016-07-14 15:27:14 +0000110 faces[i]->receive(faces[sender]->sentData[readDataOffset[sender]]);
Qiuhan Dingfb8c9e02015-01-30 14:04:55 -0800111 }
112 readDataOffset[sender]++;
113 }
114 }
115
Junxiao Shi0c7f56a2016-07-14 15:27:14 +0000116public:
Qiuhan Dingfb8c9e02015-01-30 14:04:55 -0800117 Name syncPrefix;
118 Name userPrefix[3];
119
Junxiao Shi0c7f56a2016-07-14 15:27:14 +0000120 std::unique_ptr<DummyClientFace> faces[3];
Qiuhan Dingfb8c9e02015-01-30 14:04:55 -0800121 shared_ptr<Handler> handler[3];
122
123 size_t readInterestOffset[3];
124 size_t readDataOffset[3];
125};
126
127BOOST_FIXTURE_TEST_SUITE(LogicTests, LogicFixture)
128
129void
130onUpdate(const vector<MissingDataInfo>& v)
131{
132}
133
134BOOST_AUTO_TEST_CASE(Constructor)
135{
136 Name syncPrefix("/ndn/broadcast/sync");
137 Name userPrefix("/user");
Junxiao Shi0c7f56a2016-07-14 15:27:14 +0000138 DummyClientFace face(io, {true, true});
139 BOOST_REQUIRE_NO_THROW(Logic(face, syncPrefix, userPrefix,
Qiuhan Dingfb8c9e02015-01-30 14:04:55 -0800140 bind(onUpdate, _1)));
141}
142
143BOOST_AUTO_TEST_CASE(TwoBasic)
144{
145 handler[0] = make_shared<Handler>(ref(*faces[0]), syncPrefix, userPrefix[0]);
146 advanceClocks(ndn::time::milliseconds(10), 10);
147
148 handler[1] = make_shared<Handler>(ref(*faces[1]), syncPrefix, userPrefix[1]);
149 advanceClocks(ndn::time::milliseconds(10), 10);
150
151 handler[0]->updateSeqNo(1);
152
153 for (int i = 0; i < 50; i++) {
154 advanceClocks(ndn::time::milliseconds(2), 10);
155 passPacket();
156 }
157 BOOST_CHECK_EQUAL(handler[1]->map[handler[0]->logic.getSessionName()], 1);
158 advanceClocks(ndn::time::milliseconds(10), 10);
159
160 handler[0]->updateSeqNo(2);
161
162 for (int i = 0; i < 50; i++) {
163 advanceClocks(ndn::time::milliseconds(2), 10);
164 passPacket();
165 }
166 BOOST_CHECK_EQUAL(handler[1]->map[handler[0]->logic.getSessionName()], 2);
167 advanceClocks(ndn::time::milliseconds(10), 10);
168
169 handler[1]->updateSeqNo(2);
170
171 for (int i = 0; i < 50; i++) {
172 advanceClocks(ndn::time::milliseconds(2), 10);
173 passPacket();
174 }
175 BOOST_CHECK_EQUAL(handler[0]->map[handler[1]->logic.getSessionName()], 2);
176}
177
178BOOST_AUTO_TEST_CASE(ThreeBasic)
179{
180 handler[0] = make_shared<Handler>(ref(*faces[0]), syncPrefix, userPrefix[0]);
181 advanceClocks(ndn::time::milliseconds(10), 10);
182
183 handler[1] = make_shared<Handler>(ref(*faces[1]), syncPrefix, userPrefix[1]);
184 advanceClocks(ndn::time::milliseconds(10), 10);
185
186 handler[2] = make_shared<Handler>(ref(*faces[2]), syncPrefix, userPrefix[2]);
187 advanceClocks(ndn::time::milliseconds(10), 20);
188
189 handler[0]->updateSeqNo(1);
190
191 for (int i = 0; i < 70; i++) {
192 advanceClocks(ndn::time::milliseconds(2), 10);
193 passPacket();
194 }
195 BOOST_CHECK_EQUAL(handler[1]->map[handler[0]->logic.getSessionName()], 1);
196 BOOST_CHECK_EQUAL(handler[2]->map[handler[0]->logic.getSessionName()], 1);
197
198 handler[1]->updateSeqNo(2);
199
200 for (int i = 0; i < 50; i++) {
201 advanceClocks(ndn::time::milliseconds(2), 10);
202 passPacket();
203 }
204 BOOST_CHECK_EQUAL(handler[0]->map[handler[1]->logic.getSessionName()], 2);
205 BOOST_CHECK_EQUAL(handler[2]->map[handler[1]->logic.getSessionName()], 2);
206
207 handler[2]->updateSeqNo(4);
208
209 for (int i = 0; i < 100; i++) {
210 advanceClocks(ndn::time::milliseconds(2), 10);
211 passPacket();
212 }
213 BOOST_CHECK_EQUAL(handler[0]->map[handler[2]->logic.getSessionName()], 4);
214 BOOST_CHECK_EQUAL(handler[1]->map[handler[2]->logic.getSessionName()], 4);
215}
216
217BOOST_AUTO_TEST_CASE(ResetRecover)
218{
219 handler[0] = make_shared<Handler>(ref(*faces[0]), syncPrefix, userPrefix[0]);
220 advanceClocks(ndn::time::milliseconds(10), 10);
221
222 handler[1] = make_shared<Handler>(ref(*faces[1]), syncPrefix, userPrefix[1]);
223 advanceClocks(ndn::time::milliseconds(10), 30);
224
225 handler[0]->updateSeqNo(1);
226
227 for (int i = 0; i < 50; i++) {
228 advanceClocks(ndn::time::milliseconds(2), 10);
229 passPacket();
230 }
231 BOOST_CHECK_EQUAL(handler[1]->map[handler[0]->logic.getSessionName()], 1);
232
233 handler[1]->updateSeqNo(2);
234
235 for (int i = 0; i < 50; i++) {
236 advanceClocks(ndn::time::milliseconds(2), 10);
237 passPacket();
238 }
239 BOOST_CHECK_EQUAL(handler[0]->map[handler[1]->logic.getSessionName()], 2);
240
241 advanceClocks(ndn::time::milliseconds(10), 10);
242 handler[2] = make_shared<Handler>(ref(*faces[2]), syncPrefix, userPrefix[2]);
243
244 for (int i = 0; i < 50; i++) {
245 advanceClocks(ndn::time::milliseconds(2), 10);
246 passPacket();
247 }
248 BOOST_CHECK_EQUAL(handler[1]->map[handler[0]->logic.getSessionName()], 1);
249 BOOST_CHECK_EQUAL(handler[0]->map[handler[1]->logic.getSessionName()], 2);
250
251 handler[2]->updateSeqNo(4);
252
253 for (int i = 0; i < 50; i++) {
254 advanceClocks(ndn::time::milliseconds(2), 10);
255 passPacket();
256 }
257 BOOST_CHECK_EQUAL(handler[1]->map[handler[2]->logic.getSessionName()], 4);
258 BOOST_CHECK_EQUAL(handler[0]->map[handler[2]->logic.getSessionName()], 4);
259}
260
261BOOST_AUTO_TEST_CASE(RecoverConflict)
262{
263 handler[0] = make_shared<Handler>(ref(*faces[0]), syncPrefix, userPrefix[0]);
264 advanceClocks(ndn::time::milliseconds(10), 10);
265
266 handler[1] = make_shared<Handler>(ref(*faces[1]), syncPrefix, userPrefix[1]);
267 advanceClocks(ndn::time::milliseconds(10), 10);
268
269 handler[2] = make_shared<Handler>(ref(*faces[2]), syncPrefix, userPrefix[2]);
270 advanceClocks(ndn::time::milliseconds(10), 30);
271
272 handler[0]->updateSeqNo(1);
273
274 for (int i = 0; i < 50; i++) {
275 advanceClocks(ndn::time::milliseconds(2), 10);
276 passPacket();
277 }
278 BOOST_CHECK_EQUAL(handler[1]->map[handler[0]->logic.getSessionName()], 1);
279 BOOST_CHECK_EQUAL(handler[2]->map[handler[0]->logic.getSessionName()], 1);
280
281 handler[1]->updateSeqNo(2);
282 handler[2]->updateSeqNo(4);
283
284 for (int i = 0; i < 75; i++) {
285 advanceClocks(ndn::time::milliseconds(2), 10);
286 passPacket();
287 }
288 BOOST_CHECK_EQUAL(handler[0]->map[handler[1]->logic.getSessionName()], 2);
289 BOOST_CHECK_EQUAL(handler[0]->map[handler[2]->logic.getSessionName()], 4);
290 BOOST_CHECK_EQUAL(handler[1]->map[handler[2]->logic.getSessionName()], 4);
291 BOOST_CHECK_EQUAL(handler[2]->map[handler[1]->logic.getSessionName()], 2);
292}
293
294BOOST_AUTO_TEST_CASE(MultipleUserUnderOneLogic)
295{
296 handler[0] = make_shared<Handler>(ref(*faces[0]), syncPrefix, userPrefix[0]);
297 advanceClocks(ndn::time::milliseconds(10), 10);
298
299 handler[1] = make_shared<Handler>(ref(*faces[1]), syncPrefix, userPrefix[2]);
300 advanceClocks(ndn::time::milliseconds(10), 10);
301
302 handler[0]->logic.addUserNode(userPrefix[1]);
303
304 for (int i = 0; i < 20; i++) {
305 advanceClocks(ndn::time::milliseconds(2), 10);
306 passPacket();
307 }
308
309 handler[0]->updateSeqNo(1);
310
311 for (int i = 0; i < 50; i++) {
312 advanceClocks(ndn::time::milliseconds(2), 10);
313 passPacket();
314 }
315 BOOST_CHECK_EQUAL(handler[1]->map[handler[0]->logic.getSessionName()], 1);
316
317 handler[0]->logic.updateSeqNo(2, userPrefix[1]);
318
319 for (int i = 0; i < 50; i++) {
320 advanceClocks(ndn::time::milliseconds(2), 10);
321 passPacket();
322 }
323 BOOST_CHECK_EQUAL(handler[1]->map[handler[0]->logic.getSessionName(userPrefix[1])], 2);
324
325 handler[1]->updateSeqNo(4);
326
327 for (int i = 0; i < 50; i++) {
328 advanceClocks(ndn::time::milliseconds(2), 10);
329 passPacket();
330 }
331 BOOST_CHECK_EQUAL(handler[0]->map[handler[1]->logic.getSessionName()], 4);
332
333 handler[0]->logic.removeUserNode(userPrefix[0]);
334
335 for (int i = 0; i < 100; i++) {
336 advanceClocks(ndn::time::milliseconds(2), 10);
337 passPacket();
338 }
339 BOOST_CHECK_EQUAL(handler[1]->logic.getSessionNames().size(), 2);
340}
341
342BOOST_AUTO_TEST_SUITE_END()
343
344} // namespace test
345} // namespace chronosync