blob: d06c19d892a93ac4612ef75301827b6134f9e5c7 [file] [log] [blame]
Yingdi Yu31ad44c2014-08-28 14:55:42 -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 "socket.hpp"
21
22#include "boost-test.hpp"
23
24namespace chronosync {
25namespace test {
26
27using std::string;
28using std::vector;
29using std::map;
30
31/**
32 * @brief Emulate an app that use the Socket class
33 *
34 * The app has two types of data set: one is simply string while the other is integer array.
35 * For each type of data set, the app has a specific fetching strategy.
36 */
37class SocketTestApp : noncopyable
38{
39public:
40 SocketTestApp(const Name& syncPrefix,
41 const Name& userPrefix,
42 ndn::Face& face,
43 bool isNum)
44 : sum(0)
45 , socket(syncPrefix,
46 userPrefix,
47 face,
48 isNum ? bind(&SocketTestApp::fetchNumbers, this, _1) :
49 bind(&SocketTestApp::fetchAll, this, _1))
50 {
51 }
52
53 void
54 set(const shared_ptr<const Data>& dataPacket)
55 {
56 // std::cerr << "set Data" << std::endl;
57 Name dataName(dataPacket->getName());
58 string str2(reinterpret_cast<const char*>(dataPacket->getContent().value()),
59 dataPacket->getContent().value_size());
60 data.insert(make_pair(dataName, str2));
61 }
62
63 void
64 set(Name name, const char* buf, int len)
65 {
66 string str2(buf, len);
67 data.insert(make_pair(name, str2));
68 }
69
70 void
71 setNum(const shared_ptr<const Data>& dataPacket)
72 {
73 // std::cerr << "setNum Data" << std::endl;
74 size_t n = dataPacket->getContent().value_size() / 4;
75 const uint32_t* numbers = reinterpret_cast<const uint32_t*>(dataPacket->getContent().value());
76 for (size_t i = 0; i < n; i++) {
77 sum += numbers[i];
78 }
79 }
80
81 void
82 setNum(Name name, const uint8_t* buf, int len)
83 {
84 BOOST_ASSERT(len >= 4);
85
86 int n = len / 4;
87 const uint32_t* numbers = reinterpret_cast<const uint32_t*>(buf);
88 for (int i = 0; i < n; i++) {
89 sum += numbers[i];
90 }
91 }
92
93 void
94 fetchAll(const vector<MissingDataInfo>& v)
95 {
96 // std::cerr << "fetchAll" << std::endl;
97 for (int i = 0; i < v.size(); i++) {
98 for(SeqNo s = v[i].low; s <= v[i].high; ++s) {
Alexander Afanasyev3573e132014-11-18 10:15:34 -050099 socket.fetchData(v[i].session, s, [this] (const shared_ptr<const Data>& dataPacket) {
100 this->set(dataPacket);
101 });
Yingdi Yu31ad44c2014-08-28 14:55:42 -0700102 }
103 }
104 }
105
106 void
107 fetchNumbers(const vector<MissingDataInfo> &v)
108 {
109 // std::cerr << "fetchNumbers" << std::endl;
110 for (int i = 0; i < v.size(); i++) {
111 for(SeqNo s = v[i].low; s <= v[i].high; ++s) {
Alexander Afanasyev3573e132014-11-18 10:15:34 -0500112 socket.fetchData(v[i].session, s, [this] (const shared_ptr<const Data>& dataPacket) {
113 this->setNum(dataPacket);
114 });
Yingdi Yu31ad44c2014-08-28 14:55:42 -0700115 }
116 }
117 }
118
119 string
120 toString()
121 {
122 string str = "\n";
123 for (map<Name, string>::iterator it = data.begin(); it != data.end(); ++it) {
124 str += "<";
125 str += it->first.toUri();
126 str += "|";
127 str += it->second;
128 str += ">";
129 str += "\n";
130 }
131
132 return str;
133 }
134
135 map<ndn::Name, string> data;
136 uint32_t sum;
137 Socket socket;
138};
139
140class SocketFixture
141{
142public:
143 SocketFixture()
144 : syncPrefix("/ndn/broadcast/sync")
145 , scheduler(io)
146 {
147 syncPrefix.appendVersion();
148 userPrefix[0] = Name("/user0");
149 userPrefix[1] = Name("/user1");
150 userPrefix[2] = Name("/user2");
151
152 faces[0] = make_shared<ndn::Face>(ref(io));
153 faces[1] = make_shared<ndn::Face>(ref(io));
154 faces[2] = make_shared<ndn::Face>(ref(io));
155 }
156
157 void
158 createSocket(size_t idx, bool isNum)
159 {
160 app[idx] = make_shared<SocketTestApp>(syncPrefix, userPrefix[idx], ref(*faces[idx]), isNum);
161 sessionName[idx] = app[idx]->socket.getLogic().getSessionName();
162 }
163
164 void
165 publishAppData(size_t idx, const string& data)
166 {
167 app[idx]->socket.publishData(reinterpret_cast<const uint8_t*>(data.c_str()), data.size(),
168 ndn::time::milliseconds(1000));
169 }
170
171 void
172 setAppData(size_t idx, SeqNo seqNo, const string& data)
173 {
174 Name dataName = sessionName[idx];
175 dataName.appendNumber(seqNo);
176 app[idx]->set(dataName, data.c_str(), data.size());
177 }
178
179 void
180 publishAppNum(size_t idx, const uint8_t* buf, size_t size)
181 {
182 app[idx]->socket.publishData(buf, size, ndn::time::milliseconds(1000));
183 }
184
185 void
186 setAppNum(size_t idx, SeqNo seqNo, const uint8_t* buf, size_t size)
187 {
188 Name dataName = sessionName[idx];
189 dataName.appendNumber(seqNo);
190 app[idx]->setNum(dataName, buf, size);
191 }
192
193 void
194 check(int round)
195 {
196 BOOST_CHECK_EQUAL(app[0]->toString(), app[1]->toString());
197 BOOST_CHECK_EQUAL(app[0]->toString(), app[2]->toString());
198 }
199
200 void
201 check2Num(int num)
202 {
203 BOOST_CHECK_EQUAL(app[0]->sum, app[1]->sum);
204 BOOST_CHECK_EQUAL(app[1]->sum, num);
205 }
206
207 void
208 terminate()
209 {
210 io.stop();
211 }
212
213 Name syncPrefix;
214 Name userPrefix[3];
215 Name sessionName[3];
216
217 boost::asio::io_service io;
218 shared_ptr<ndn::Face> faces[3];
219 ndn::Scheduler scheduler;
220 shared_ptr<SocketTestApp> app[3];
221};
222
223
224
225BOOST_FIXTURE_TEST_SUITE(SocketTests, SocketFixture)
226
227BOOST_AUTO_TEST_CASE(BasicData)
228{
229 scheduler.scheduleEvent(ndn::time::milliseconds(0),
230 bind(&SocketFixture::createSocket, this, 0, false));
231
232 scheduler.scheduleEvent(ndn::time::milliseconds(50),
233 bind(&SocketFixture::createSocket, this, 1, false));
234
235 scheduler.scheduleEvent(ndn::time::milliseconds(100),
236 bind(&SocketFixture::createSocket, this, 2, false));
237
238 string data0 = "Very funny Scotty, now beam down my clothes";
239 scheduler.scheduleEvent(ndn::time::milliseconds(150),
240 bind(&SocketFixture::publishAppData, this, 0, data0));
241 scheduler.scheduleEvent(ndn::time::milliseconds(1150),
242 bind(&SocketFixture::setAppData, this, 0, 1, data0));
243 scheduler.scheduleEvent(ndn::time::milliseconds(1160),
244 bind(&SocketFixture::check, this, 1));
245
246 string data1 = "Yes, give me that ketchup";
247 string data2 = "Don't look conspicuous, it draws fire";
248 scheduler.scheduleEvent(ndn::time::milliseconds(1170),
249 bind(&SocketFixture::publishAppData, this, 0, data1));
250 scheduler.scheduleEvent(ndn::time::milliseconds(1180),
251 bind(&SocketFixture::publishAppData, this, 0, data2));
252 scheduler.scheduleEvent(ndn::time::milliseconds(2150),
253 bind(&SocketFixture::setAppData, this, 0, 2, data1));
254 scheduler.scheduleEvent(ndn::time::milliseconds(2160),
255 bind(&SocketFixture::setAppData, this, 0, 3, data2));
256 scheduler.scheduleEvent(ndn::time::milliseconds(2170),
257 bind(&SocketFixture::check, this, 2));
258
259 string data3 = "You surf the Internet, I surf the real world";
260 string data4 = "I got a fortune cookie once that said 'You like Chinese food'";
261 string data5 = "Real men wear pink. Why? Because their wives make them";
262 scheduler.scheduleEvent(ndn::time::milliseconds(3180),
263 bind(&SocketFixture::publishAppData, this, 2, data3));
264 scheduler.scheduleEvent(ndn::time::milliseconds(3200),
265 bind(&SocketFixture::publishAppData, this, 1, data4));
266 scheduler.scheduleEvent(ndn::time::milliseconds(3210),
267 bind(&SocketFixture::publishAppData, this, 1, data5));
268 scheduler.scheduleEvent(ndn::time::milliseconds(4710),
269 bind(&SocketFixture::setAppData, this, 2, 1, data3));
270 scheduler.scheduleEvent(ndn::time::milliseconds(4720),
271 bind(&SocketFixture::setAppData, this, 1, 1, data4));
272 scheduler.scheduleEvent(ndn::time::milliseconds(4730),
273 bind(&SocketFixture::setAppData, this, 1, 2, data5));
274 scheduler.scheduleEvent(ndn::time::milliseconds(4800),
275 bind(&SocketFixture::check, this, 3));
276
277 // not sure weither this is simultanous data generation from multiple sources
278 string data6 = "Shakespeare says: 'Prose before hos.'";
279 string data7 = "Pick good people, talent never wears out";
280 scheduler.scheduleEvent(ndn::time::milliseconds(5500),
281 bind(&SocketFixture::publishAppData, this, 0, data6));
282 scheduler.scheduleEvent(ndn::time::milliseconds(5500),
283 bind(&SocketFixture::publishAppData, this, 1, data7));
284 scheduler.scheduleEvent(ndn::time::milliseconds(6800),
285 bind(&SocketFixture::setAppData, this, 0, 4, data6));
286 scheduler.scheduleEvent(ndn::time::milliseconds(6800),
287 bind(&SocketFixture::setAppData, this, 1, 3, data7));
288 scheduler.scheduleEvent(ndn::time::milliseconds(6900),
289 bind(&SocketFixture::check, this, 4));
290
291 scheduler.scheduleEvent(ndn::time::milliseconds(7000),
292 bind(&SocketFixture::terminate, this));
293
294 io.run();
295}
296
297BOOST_AUTO_TEST_CASE(BasicNumber)
298{
299 scheduler.scheduleEvent(ndn::time::milliseconds(0),
300 bind(&SocketFixture::createSocket, this, 0, true));
301 scheduler.scheduleEvent(ndn::time::milliseconds(50),
302 bind(&SocketFixture::createSocket, this, 1, true));
303
304 uint32_t num1[5] = {0, 1, 2, 3, 4};
305 uint8_t* buf1 = reinterpret_cast<uint8_t*>(num1);
306 size_t size1 = sizeof(num1);
307 scheduler.scheduleEvent(ndn::time::milliseconds(100),
308 bind(&SocketFixture::publishAppNum, this, 0, buf1, size1));
309 scheduler.scheduleEvent(ndn::time::milliseconds(150),
310 bind(&SocketFixture::setAppNum, this, 0, 0, buf1, size1));
311 scheduler.scheduleEvent(ndn::time::milliseconds(1000),
312 bind(&SocketFixture::check2Num, this, 10));
313
314 uint32_t num2[5] = {9, 7, 2, 1, 1};
315 uint8_t* buf2 = reinterpret_cast<uint8_t*>(num2);
316 size_t size2 = sizeof(num2);
317 scheduler.scheduleEvent(ndn::time::milliseconds(1100),
318 bind(&SocketFixture::publishAppNum, this, 1, buf2, size2));
319 scheduler.scheduleEvent(ndn::time::milliseconds(1150),
320 bind(&SocketFixture::setAppNum, this, 1, 0, buf2, size2));
321 scheduler.scheduleEvent(ndn::time::milliseconds(2000),
322 bind(&SocketFixture::check2Num, this, 30));
323
324 scheduler.scheduleEvent(ndn::time::milliseconds(7000),
325 bind(&SocketFixture::terminate, this));
326
327 io.run();
328}
329
330BOOST_AUTO_TEST_SUITE_END()
331
332} // namespace test
333} // namespace chronosync