blob: 189ee272dc20e17394b40ddced902affe6e21583 [file] [log] [blame]
Shuo Chenca329182014-03-19 18:05:18 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
3 * Copyright (c) 2014, Regents of the University of California.
4 *
5 * This file is part of NDN repo-ng (Next generation of NDN repository).
6 * See AUTHORS.md for complete list of repo-ng authors and contributors.
7 *
8 * repo-ng 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,
10 * either version 3 of the License, or (at your option) any later version.
11 *
12 * repo-ng 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 * repo-ng, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#include "handles/write-handle.hpp"
21#include "handles/delete-handle.hpp"
22#include "storage/storage-handle.hpp"
23#include "storage/sqlite-handle.hpp"
24
25#include "../sqlite-fixture.hpp"
26#include "../dataset-fixtures.hpp"
27
28#include <ndn-cxx/util/command-interest-generator.hpp>
29
30#include <boost/test/unit_test.hpp>
31
32namespace repo {
33namespace tests {
34
35using ndn::time::milliseconds;
36using ndn::time::seconds;
37using ndn::EventId;
38namespace random=ndn::random;
39
40//All the test cases in this test suite should be run at once.
41BOOST_AUTO_TEST_SUITE(TestBasicCommandInsertDelete)
42
43const static uint8_t content[8] = {3, 1, 4, 1, 5, 9, 2, 6};
44
45template<class Dataset>
46class Fixture : public SqliteFixture, public Dataset
47{
48public:
49 Fixture()
50 : scheduler(repoFace.getIoService())
51 , writeHandle(repoFace, *handle, keyChain, scheduler, validator)
52 , deleteHandle(repoFace, *handle, keyChain, scheduler, validator)
53 , insertFace(repoFace.getIoService())
54 , deleteFace(repoFace.getIoService())
55 {
56 validator.addInterestRule("^<>",
57 *keyChain.getCertificate(keyChain.getDefaultCertificateName()));
58 writeHandle.listen(Name("/repo/command"));
59 deleteHandle.listen(Name("/repo/command"));
60 }
61
62 ~Fixture()
63 {
64 repoFace.getIoService().stop();
65 }
66
67 void
68 scheduleInsertEvent();
69
70 void
71 scheduleDeleteEvent();
72
73 void
74 onInsertInterest(const Interest& interest);
75
76 void
77 onRegisterFailed(const std::string& reason);
78
79 void
80 delayedInterest();
81
82 void
83 stopFaceProcess();
84
85
86 void
87 onInsertData(const Interest& interest, Data& data);
88
89 void
90 onDeleteData(const Interest& interest, Data& data);
91
92 void
93 onInsertTimeout(const Interest& interest);
94
95 void
96 onDeleteTimeout(const Interest& interest);
97
98 void
99 sendInsertInterest(const Interest& interest);
100
101 void
102 sendDeleteInterest(const Interest& deleteInterest);
103
104 void
105 checkInsertOK(const Interest& interest);
106
107 void
108 checkDeleteOK(const Interest& interest);
109
110public:
111 Face repoFace;
112 Scheduler scheduler;
113 CommandInterestValidator validator;
114 KeyChain keyChain;
115 ndn::CommandInterestGenerator generator;
116 WriteHandle writeHandle;
117 DeleteHandle deleteHandle;
118 Face insertFace;
119 Face deleteFace;
120 std::map<Name, EventId> insertEvents;
121};
122
123template<class T> void
124Fixture<T>::onInsertInterest(const Interest& interest)
125{
126 Data data(Name(interest.getName()));
127 data.setContent(content, sizeof(content));
128 data.setFreshnessPeriod(milliseconds(0));
129 keyChain.sign(data);
130 insertFace.put(data);
131
132 std::map<Name, EventId>::iterator event = insertEvents.find(interest.getName());
133 if (event != insertEvents.end()) {
134 scheduler.cancelEvent(event->second);
135 insertEvents.erase(event);
136 }
137 // schedule an event 50ms later to check whether insert is OK
138 scheduler.scheduleEvent(milliseconds(50),
139 bind(&Fixture<T>::checkInsertOK, this, interest));
140
141}
142
143
144template<class T> void
145Fixture<T>::onRegisterFailed(const std::string& reason)
146{
147 BOOST_ERROR("ERROR: Failed to register prefix in local hub's daemon" + reason);
148}
149
150template<class T> void
151Fixture<T>::delayedInterest()
152{
153 BOOST_ERROR("Fetching interest does not come. It may be satisfied in CS or something is wrong");
154}
155
156template<class T> void
157Fixture<T>::stopFaceProcess()
158{
159 repoFace.getIoService().stop();
160}
161
162template<class T> void
163Fixture<T>::onInsertData(const Interest& interest, Data& data)
164{
165 RepoCommandResponse response;
166 response.wireDecode(data.getContent().blockFromValue());
167 int statusCode = response.getStatusCode();
168 BOOST_CHECK_EQUAL(statusCode, 100);
169}
170
171template<class T> void
172Fixture<T>::onDeleteData(const Interest& interest, Data& data)
173{
174 RepoCommandResponse response;
175 response.wireDecode(data.getContent().blockFromValue());
176 int statusCode = response.getStatusCode();
177 BOOST_CHECK_EQUAL(statusCode, 200);
178
179 //schedlute an event to check whether delete is OK.
180 scheduler.scheduleEvent(milliseconds(100),
181 bind(&Fixture<T>::checkDeleteOK, this, interest));
182}
183
184template<class T> void
185Fixture<T>::onInsertTimeout(const Interest& interest)
186{
187 BOOST_ERROR("Inserert command timeout");
188}
189
190template<class T> void
191Fixture<T>::onDeleteTimeout(const Interest& interest)
192{
193 BOOST_ERROR("delete command timeout");
194}
195
196template<class T> void
197Fixture<T>::sendInsertInterest(const Interest& insertInterest)
198{
199 insertFace.expressInterest(insertInterest,
200 bind(&Fixture<T>::onInsertData, this, _1, _2),
201 bind(&Fixture<T>::onInsertTimeout, this, _1));
202}
203
204template<class T> void
205Fixture<T>::sendDeleteInterest(const Interest& deleteInterest)
206{
207 deleteFace.expressInterest(deleteInterest,
208 bind(&Fixture<T>::onDeleteData, this, _1, _2),
209 bind(&Fixture<T>::onDeleteTimeout, this, _1));
210}
211
212template<class T> void
213Fixture<T>::checkInsertOK(const Interest& interest)
214{
215 Data data;
216 BOOST_TEST_MESSAGE(interest);
217 BOOST_CHECK_EQUAL(handle->readData(interest, data), true);
218 int rc = memcmp(data.getContent().value(), content, sizeof(content));
219 BOOST_CHECK_EQUAL(rc, 0);
220}
221
222template<class T> void
223Fixture<T>::checkDeleteOK(const Interest& interest)
224{
225 Data data;
226 BOOST_CHECK_EQUAL(handle->readData(interest, data), false);
227}
228
229
230template<class T> void
231Fixture<T>::scheduleInsertEvent()
232{
233 int timeCount = 1;
234 for (typename T::DataContainer::iterator i = this->data.begin();
235 i != this->data.end(); ++i) {
236 Name insertCommandName("/repo/command/insert");
237 RepoCommandParameter insertParameter;
238 insertParameter.setName(Name((*i)->getName())
239 .appendNumber(random::generateWord64()));
240
241 insertCommandName.append(insertParameter.wireEncode());
242 Interest insertInterest(insertCommandName);
243 generator.generateWithIdentity(insertInterest, keyChain.getDefaultIdentity());
244 //schedule a job to express insertInterest every 50ms
245 scheduler.scheduleEvent(milliseconds(timeCount * 50 + 1000),
246 bind(&Fixture<T>::sendInsertInterest, this, insertInterest));
247 //schedule what to do when interest timeout
248
249 EventId delayEventId = scheduler.scheduleEvent(milliseconds(5000 + timeCount * 50),
250 bind(&Fixture<T>::delayedInterest, this));
251 insertEvents[insertParameter.getName()] = delayEventId;
252
253 //The delayEvent will be canceled in onInsertInterest
254 insertFace.setInterestFilter(insertParameter.getName(),
255 bind(&Fixture<T>::onInsertInterest, this, _2),
Wentao Shang91fb4f22014-05-20 10:55:22 -0700256 ndn::RegisterPrefixSuccessCallback(),
Shuo Chenca329182014-03-19 18:05:18 -0700257 bind(&Fixture<T>::onRegisterFailed, this, _2));
258 timeCount++;
259 }
260}
261
262
263template<class T> void
264Fixture<T>::scheduleDeleteEvent()
265{
266 int timeCount = 1;
267 for (typename T::DataContainer::iterator i = this->data.begin();
268 i != this->data.end(); ++i) {
269 Name deleteCommandName("/repo/command/delete");
270 RepoCommandParameter deleteParameter;
271 static boost::random::mt19937_64 gen;
272 static boost::random::uniform_int_distribution<uint64_t> dist(0, 0xFFFFFFFFFFFFFFFFLL);
273 deleteParameter.setProcessId(dist(gen));
274 deleteParameter.setName((*i)->getName());
275 deleteCommandName.append(deleteParameter.wireEncode());
276 Interest deleteInterest(deleteCommandName);
277 generator.generateWithIdentity(deleteInterest, keyChain.getDefaultIdentity());
278 scheduler.scheduleEvent(milliseconds(4000 + timeCount * 50),
279 bind(&Fixture<T>::sendDeleteInterest, this, deleteInterest));
280 timeCount++;
281 }
282}
283
284BOOST_FIXTURE_TEST_CASE_TEMPLATE(InsertDelete, T, DatasetFixtures, Fixture<T>)
285{
286 // schedule events
287 this->scheduler.scheduleEvent(seconds(0),
288 bind(&Fixture<T>::scheduleInsertEvent, this));
289 this->scheduler.scheduleEvent(seconds(10),
290 bind(&Fixture<T>::scheduleDeleteEvent, this));
291
292 // schedule an event to terminate IO
293 this->scheduler.scheduleEvent(seconds(20),
294 bind(&Fixture<T>::stopFaceProcess, this));
295 this->repoFace.getIoService().run();
296}
297
298BOOST_AUTO_TEST_SUITE_END()
299
300} //namespace tests
301} //namespace repo