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