blob: 0c478ec8d31b72e136e32a2ea71d61bc1e2244c4 [file] [log] [blame]
Qiuhan Dingfb8c9e02015-01-30 14:04:55 -08001/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil -*- */
2/*
Ashlesh Gawande8d1347a2017-04-03 19:10:28 -05003 * 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 "socket.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::string;
29using std::vector;
30using std::map;
31using ndn::util::DummyClientFace;
Qiuhan Dingfb8c9e02015-01-30 14:04:55 -080032
33
34/**
35 * @brief Emulate an app that use the Socket class
36 *
37 * The app has two types of data set: one is simply string while the other is integer array.
38 * For each type of data set, the app has a specific fetching strategy.
39 */
40class SocketTestApp : noncopyable
41{
42public:
43 SocketTestApp(const Name& syncPrefix,
44 const Name& userPrefix,
45 DummyClientFace& face,
46 bool isNum)
47 : sum(0)
48 , socket(syncPrefix,
49 userPrefix,
50 face,
51 isNum ? bind(&SocketTestApp::fetchNumbers, this, _1) :
52 bind(&SocketTestApp::fetchAll, this, _1))
53 {
54 }
55
56 void
57 set(const shared_ptr<const Data>& dataPacket)
58 {
59 // std::cerr << "set Data" << std::endl;
60 Name dataName(dataPacket->getName());
61 string str2(reinterpret_cast<const char*>(dataPacket->getContent().value()),
62 dataPacket->getContent().value_size());
63 data.insert(make_pair(dataName, str2));
64 }
65
66 void
67 set(Name name, const char* buf, int len)
68 {
69 string str2(buf, len);
70 data.insert(make_pair(name, str2));
71 }
72
73 void
74 setNum(const shared_ptr<const Data>& dataPacket)
75 {
76 // std::cerr << "setNum Data" << std::endl;
77 size_t n = dataPacket->getContent().value_size() / 4;
78 const uint32_t* numbers = reinterpret_cast<const uint32_t*>(dataPacket->getContent().value());
79 for (size_t i = 0; i < n; i++) {
80 sum += numbers[i];
81 }
82 }
83
84 void
85 setNum(Name name, const uint8_t* buf, int len)
86 {
87 BOOST_ASSERT(len >= 4);
88
89 int n = len / 4;
90 const uint32_t* numbers = reinterpret_cast<const uint32_t*>(buf);
91 for (int i = 0; i < n; i++) {
92 sum += numbers[i];
93 }
94 }
95
96 void
97 fetchAll(const vector<MissingDataInfo>& v)
98 {
99 // std::cerr << "fetchAll" << std::endl;
Yingdi Yu372697f2015-02-09 14:42:39 -0800100 for (size_t i = 0; i < v.size(); i++) {
Qiuhan Dingfb8c9e02015-01-30 14:04:55 -0800101 for(SeqNo s = v[i].low; s <= v[i].high; ++s) {
102 socket.fetchData(v[i].session, s, [this] (const shared_ptr<const Data>& dataPacket) {
103 this->set(dataPacket);
104 });
105 }
106 }
107 }
108
109 void
Ashlesh Gawande8d1347a2017-04-03 19:10:28 -0500110 fetchNumbers(const vector<MissingDataInfo>& v)
Qiuhan Dingfb8c9e02015-01-30 14:04:55 -0800111 {
112 // std::cerr << "fetchNumbers" << std::endl;
Yingdi Yu372697f2015-02-09 14:42:39 -0800113 for (size_t i = 0; i < v.size(); i++) {
Qiuhan Dingfb8c9e02015-01-30 14:04:55 -0800114 for(SeqNo s = v[i].low; s <= v[i].high; ++s) {
115 socket.fetchData(v[i].session, s, [this] (const shared_ptr<const Data>& dataPacket) {
116 this->setNum(dataPacket);
117 });
118 }
119 }
120 }
121
122 string
123 toString()
124 {
125 string str = "\n";
126 for (map<Name, string>::iterator it = data.begin(); it != data.end(); ++it) {
127 str += "<";
128 str += it->first.toUri();
129 str += "|";
130 str += it->second;
131 str += ">";
132 str += "\n";
133 }
134
135 return str;
136 }
137
Junxiao Shi0c7f56a2016-07-14 15:27:14 +0000138public:
Qiuhan Dingfb8c9e02015-01-30 14:04:55 -0800139 map<ndn::Name, string> data;
140 uint32_t sum;
141 Socket socket;
142};
143
144class SocketFixture : public ndn::tests::UnitTestTimeFixture
145{
146public:
147 SocketFixture()
148 : syncPrefix("/ndn/broadcast/sync")
149 {
150 syncPrefix.appendVersion();
151 userPrefix[0] = Name("/user0");
152 userPrefix[1] = Name("/user1");
153 userPrefix[2] = Name("/user2");
154
Junxiao Shi0c7f56a2016-07-14 15:27:14 +0000155 faces[0].reset(new DummyClientFace(io, {true, true}));
156 faces[1].reset(new DummyClientFace(io, {true, true}));
157 faces[2].reset(new DummyClientFace(io, {true, true}));
Qiuhan Dingfb8c9e02015-01-30 14:04:55 -0800158
159 for (int i = 0; i < 3; i++) {
160 readInterestOffset[i] = 0;
161 readDataOffset[i] = 0;
162 }
163 }
164
165 void
166 passPacket()
167 {
168 for (int i = 0; i < 3; i++)
169 checkFace(i);
170 }
171
172 void
173 checkFace(int sender)
174 {
175 while (faces[sender]->sentInterests.size() > readInterestOffset[sender]) {
176 for (int i = 0; i < 3; i++) {
177 if (sender != i)
178 faces[i]->receive(faces[sender]->sentInterests[readInterestOffset[sender]]);
179 }
180 readInterestOffset[sender]++;
181 }
Junxiao Shi0c7f56a2016-07-14 15:27:14 +0000182 while (faces[sender]->sentData.size() > readDataOffset[sender]) {
Qiuhan Dingfb8c9e02015-01-30 14:04:55 -0800183 for (int i = 0; i < 3; i++) {
184 if (sender != i)
Junxiao Shi0c7f56a2016-07-14 15:27:14 +0000185 faces[i]->receive(faces[sender]->sentData[readDataOffset[sender]]);
Qiuhan Dingfb8c9e02015-01-30 14:04:55 -0800186 }
187 readDataOffset[sender]++;
188 }
189 }
190
191 void
192 createSocket(size_t idx, bool isNum)
193 {
194 app[idx] = make_shared<SocketTestApp>(syncPrefix, userPrefix[idx], ref(*faces[idx]), isNum);
195 sessionName[idx] = app[idx]->socket.getLogic().getSessionName();
196 }
197
198 void
199 publishAppData(size_t idx, const string& data)
200 {
201 app[idx]->socket.publishData(reinterpret_cast<const uint8_t*>(data.c_str()), data.size(),
202 ndn::time::milliseconds(1000));
203 }
204
205 void
Ashlesh Gawande8d1347a2017-04-03 19:10:28 -0500206 publishAppData(size_t idx, const string& data, SeqNo seqNo)
207 {
208 app[idx]->socket.publishData(reinterpret_cast<const uint8_t*>(data.c_str()), data.size(),
209 ndn::time::milliseconds(1000), seqNo);
210 }
211
212 void
Qiuhan Dingfb8c9e02015-01-30 14:04:55 -0800213 setAppData(size_t idx, SeqNo seqNo, const string& data)
214 {
215 Name dataName = sessionName[idx];
216 dataName.appendNumber(seqNo);
217 app[idx]->set(dataName, data.c_str(), data.size());
218 }
219
220 void
221 publishAppNum(size_t idx, const uint8_t* buf, size_t size)
222 {
223 app[idx]->socket.publishData(buf, size, ndn::time::milliseconds(1000));
224 }
225
226 void
227 setAppNum(size_t idx, SeqNo seqNo, const uint8_t* buf, size_t size)
228 {
229 Name dataName = sessionName[idx];
230 dataName.appendNumber(seqNo);
231 app[idx]->setNum(dataName, buf, size);
232 }
233
Junxiao Shi0c7f56a2016-07-14 15:27:14 +0000234public:
Qiuhan Dingfb8c9e02015-01-30 14:04:55 -0800235 Name syncPrefix;
236 Name userPrefix[3];
237 Name sessionName[3];
238
Junxiao Shi0c7f56a2016-07-14 15:27:14 +0000239 std::unique_ptr<DummyClientFace> faces[3];
Qiuhan Dingfb8c9e02015-01-30 14:04:55 -0800240 shared_ptr<SocketTestApp> app[3];
241
242 size_t readInterestOffset[3];
243 size_t readDataOffset[3];
244};
245
246
247
248BOOST_FIXTURE_TEST_SUITE(SocketTests, SocketFixture)
249
250BOOST_AUTO_TEST_CASE(BasicData)
251{
252 createSocket(0, false);
253 advanceClocks(ndn::time::milliseconds(10), 5);
254 createSocket(1, false);
255 advanceClocks(ndn::time::milliseconds(10), 5);
256 createSocket(2, false);
257 advanceClocks(ndn::time::milliseconds(10), 5);
258
259 string data0 = "Very funny Scotty, now beam down my clothes";
260 publishAppData(0, data0);
261
262 for (int i = 0; i < 50; i++) {
263 advanceClocks(ndn::time::milliseconds(2), 10);
264 passPacket();
265 }
266 setAppData(0, 1, data0);
267
268 advanceClocks(ndn::time::milliseconds(10), 1);
269 BOOST_CHECK_EQUAL(app[0]->toString(), app[1]->toString());
270 BOOST_CHECK_EQUAL(app[0]->toString(), app[2]->toString());
271
272 string data1 = "Yes, give me that ketchup";
273 string data2 = "Don't look conspicuous, it draws fire";
274 publishAppData(0, data1);
275 advanceClocks(ndn::time::milliseconds(10), 1);
276 publishAppData(0, data2);
277
278 for (int i = 0; i < 50; i++) {
279 advanceClocks(ndn::time::milliseconds(2), 10);
280 passPacket();
281 }
282 setAppData(0, 2, data1);
283 advanceClocks(ndn::time::milliseconds(10), 1);
284 setAppData(0, 3, data2);
285
286 advanceClocks(ndn::time::milliseconds(10), 1);
287 BOOST_CHECK_EQUAL(app[0]->toString(), app[1]->toString());
288 BOOST_CHECK_EQUAL(app[0]->toString(), app[2]->toString());
289
290 string data3 = "You surf the Internet, I surf the real world";
291 string data4 = "I got a fortune cookie once that said 'You like Chinese food'";
292 string data5 = "Real men wear pink. Why? Because their wives make them";
293 publishAppData(2, data3);
294 advanceClocks(ndn::time::milliseconds(10), 2);
295 publishAppData(1, data4);
296 advanceClocks(ndn::time::milliseconds(10), 1);
297 publishAppData(1, data5);
298
299 for (int i = 0; i < 100; i++) {
300 advanceClocks(ndn::time::milliseconds(2), 10);
301 passPacket();
302 }
303 setAppData(2, 1, data3);
304 advanceClocks(ndn::time::milliseconds(10), 1);
305 setAppData(1, 1, data4);
306 advanceClocks(ndn::time::milliseconds(10), 1);
307 setAppData(1, 2, data5);
308
309 advanceClocks(ndn::time::milliseconds(10), 7);
310 BOOST_CHECK_EQUAL(app[0]->toString(), app[1]->toString());
311 BOOST_CHECK_EQUAL(app[0]->toString(), app[2]->toString());
312
313 string data6 = "Shakespeare says: 'Prose before hos.'";
314 string data7 = "Pick good people, talent never wears out";
315 publishAppData(0, data6);
316 publishAppData(1, data7);
317
318 for (int i = 0; i < 100; i++) {
319 advanceClocks(ndn::time::milliseconds(2), 10);
320 passPacket();
321 }
322 setAppData(0, 4, data6);
323 setAppData(1, 3, data7);
324
325 BOOST_CHECK_EQUAL(app[0]->toString(), app[1]->toString());
326 BOOST_CHECK_EQUAL(app[0]->toString(), app[2]->toString());
327}
328
329BOOST_AUTO_TEST_CASE(BasicNumber)
330{
331 createSocket(0, true);
332 advanceClocks(ndn::time::milliseconds(10), 5);
333 createSocket(1, true);
334 advanceClocks(ndn::time::milliseconds(10), 5);
335
336 uint32_t num1[5] = {0, 1, 2, 3, 4};
337 uint8_t* buf1 = reinterpret_cast<uint8_t*>(num1);
338 size_t size1 = sizeof(num1);
339 publishAppNum(0, buf1, size1);
340 advanceClocks(ndn::time::milliseconds(10), 5);
341 setAppNum(0, 0, buf1, size1);
342
343 for (int i = 0; i < 100; i++) {
344 advanceClocks(ndn::time::milliseconds(2), 10);
345 passPacket();
346 }
347 BOOST_CHECK_EQUAL(app[0]->sum, app[1]->sum);
348 BOOST_CHECK_EQUAL(app[1]->sum, 10);
349
350 uint32_t num2[5] = {9, 7, 2, 1, 1};
351 uint8_t* buf2 = reinterpret_cast<uint8_t*>(num2);
352 size_t size2 = sizeof(num2);
353 publishAppNum(1, buf2, size2);
354 setAppNum(1, 0, buf2, size2);
355
356 for (int i = 0; i < 50; i++) {
357 advanceClocks(ndn::time::milliseconds(2), 10);
358 passPacket();
359 }
360 BOOST_CHECK_EQUAL(app[0]->sum, app[1]->sum);
361 BOOST_CHECK_EQUAL(app[1]->sum, 30);
362}
363
Ashlesh Gawande8d1347a2017-04-03 19:10:28 -0500364BOOST_AUTO_TEST_CASE(BasicDataWithAppSeq)
365{
366 createSocket(0, false);
367 advanceClocks(ndn::time::milliseconds(10), 5);
368 createSocket(1, false);
369 advanceClocks(ndn::time::milliseconds(10), 5);
370 createSocket(2, false);
371 advanceClocks(ndn::time::milliseconds(10), 5);
372
373 string data0 = "Very funny Scotty, now beam down my clothes";
374 publishAppData(0, data0, 100);
375
376 for (int i = 0; i < 50; i++) {
377 advanceClocks(ndn::time::milliseconds(2), 10);
378 passPacket();
379 }
380 setAppData(0, 100, data0);
381
382 advanceClocks(ndn::time::milliseconds(10), 1);
383 BOOST_CHECK_EQUAL(app[0]->toString(), app[1]->toString());
384 BOOST_CHECK_EQUAL(app[0]->toString(), app[2]->toString());
385
386 string data1 = "Yes, give me that ketchup";
387 string data2 = "Don't look conspicuous, it draws fire";
388 publishAppData(0, data1, 200);
389 advanceClocks(ndn::time::milliseconds(10), 1);
390 publishAppData(0, data2, 300);
391
392 for (int i = 0; i < 50; i++) {
393 advanceClocks(ndn::time::milliseconds(2), 10);
394 passPacket();
395 }
396 setAppData(0, 200, data1);
397 advanceClocks(ndn::time::milliseconds(10), 1);
398 setAppData(0, 300, data2);
399
400 advanceClocks(ndn::time::milliseconds(10), 1);
401 BOOST_CHECK_EQUAL(app[0]->toString(), app[1]->toString());
402 BOOST_CHECK_EQUAL(app[0]->toString(), app[2]->toString());
403
404 string data3 = "You surf the Internet, I surf the real world";
405 string data4 = "I got a fortune cookie once that said 'You like Chinese food'";
406 string data5 = "Real men wear pink. Why? Because their wives make them";
407 publishAppData(2, data3, 100);
408 advanceClocks(ndn::time::milliseconds(10), 2);
409 publishAppData(1, data4, 100);
410 advanceClocks(ndn::time::milliseconds(10), 1);
411 publishAppData(1, data5, 200);
412
413 for (int i = 0; i < 100; i++) {
414 advanceClocks(ndn::time::milliseconds(2), 10);
415 passPacket();
416 }
417 setAppData(2, 100, data3);
418 advanceClocks(ndn::time::milliseconds(10), 1);
419 setAppData(1, 100, data4);
420 advanceClocks(ndn::time::milliseconds(10), 1);
421 setAppData(1, 200, data5);
422
423 advanceClocks(ndn::time::milliseconds(10), 7);
424 BOOST_CHECK_EQUAL(app[0]->toString(), app[1]->toString());
425 BOOST_CHECK_EQUAL(app[0]->toString(), app[2]->toString());
426
427 string data6 = "Shakespeare says: 'Prose before hos.'";
428 string data7 = "Pick good people, talent never wears out";
429 publishAppData(0, data6, 500);
430 publishAppData(1, data7, 300);
431
432 for (int i = 0; i < 100; i++) {
433 advanceClocks(ndn::time::milliseconds(2), 10);
434 passPacket();
435 }
436 setAppData(0, 500, data6);
437 setAppData(1, 300, data7);
438
439 BOOST_CHECK_EQUAL(app[0]->toString(), app[1]->toString());
440 BOOST_CHECK_EQUAL(app[0]->toString(), app[2]->toString());
441}
442
Qiuhan Dingfb8c9e02015-01-30 14:04:55 -0800443BOOST_AUTO_TEST_SUITE_END()
444
445} // namespace test
446} // namespace chronosync