blob: 8ff0486a0a2afbd2f8cab2d60da3f174763cbda2 [file] [log] [blame]
Chengyu Fanc7b87ad2015-07-09 16:44:37 -06001/** NDN-Atmos: Cataloging Service for distributed data originally developed
2 * for atmospheric science data
3 * Copyright (C) 2015 Colorado State University
4 *
5 * NDN-Atmos is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * NDN-Atmos is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with NDN-Atmos. If not, see <http://www.gnu.org/licenses/>.
17**/
18
19#include "publish/publish-adapter.hpp"
20#include "boost-test.hpp"
21#include "../../unit-test-time-fixture.hpp"
22#include "util/config-file.hpp"
23
24#include <boost/mpl/list.hpp>
25#include <boost/thread.hpp>
26#include <ndn-cxx/util/dummy-client-face.hpp>
27#include <boost/property_tree/info_parser.hpp>
28
29namespace atmos{
30namespace tests{
31 using ndn::util::DummyClientFace;
32 using ndn::util::makeDummyClientFace;
33
34 class PublishAdapterTest : public publish::PublishAdapter<std::string>
35 {
36 public:
37 PublishAdapterTest(const std::shared_ptr<ndn::util::DummyClientFace>& face,
38 const std::shared_ptr<ndn::KeyChain>& keyChain)
39 : publish::PublishAdapter<std::string>(face, keyChain)
40 {
41 }
42
43 virtual
44 ~PublishAdapterTest()
45 {
46 }
47
Chengyu Fanf4c747a2015-08-18 13:56:01 -060048 void
49 setDatabaseTable(const std::string& databaseTable)
50 {
51 m_databaseTable = databaseTable;
52 }
53
54 void
55 setTableFields(const std::vector<std::string>& tableFields)
Chengyu Fan46398212015-08-11 11:23:13 -060056 {
57 m_tableColumns = tableFields;
58 }
59
Chengyu Fanc7b87ad2015-07-09 16:44:37 -060060 const ndn::Name
61 getPrefix()
62 {
63 return m_prefix;
64 }
65
66 const ndn::Name
67 getSigningId()
68 {
69 return m_signingId;
70 }
71
72 const ndn::Name
73 getSyncPrefix()
74 {
75 return m_syncPrefix;
76 }
77
78 void
79 configAdapter(const util::ConfigSection& section,
80 const ndn::Name& prefix)
81 {
82 onConfig(section, false, std::string("test.txt"), prefix);
83 }
84
85 bool
Chengyu Fan46398212015-08-11 11:23:13 -060086 testJson2Sql(std::stringstream& sqlString,
87 Json::Value& jsonValue,
88 util::DatabaseOperation operation)
89 {
90 return json2Sql(sqlString, jsonValue, operation);
91 }
92
93 bool
94 testName2Fields(std::stringstream& sqlString,
95 std::string& fileName)
96 {
97 return name2Fields(sqlString, fileName);
98 }
99
100 bool
Chengyu Fanc7b87ad2015-07-09 16:44:37 -0600101 testValidatePublicationChanges(const std::shared_ptr<const ndn::Data>& data)
102 {
103 return validatePublicationChanges(data);
104 }
105 };
106
107 class PublishAdapterFixture : public UnitTestTimeFixture
108 {
109 public:
110 PublishAdapterFixture()
111 : face(makeDummyClientFace(io))
112 , keyChain(new ndn::KeyChain())
Chengyu Fanf4c747a2015-08-18 13:56:01 -0600113 , databaseTable("cmip5")
Chengyu Fanc7b87ad2015-07-09 16:44:37 -0600114 , publishAdapterTest1(face, keyChain)
115 , publishAdapterTest2(face, keyChain)
116 {
Chengyu Fan46398212015-08-11 11:23:13 -0600117 std::string cx("sha256"), c0("name"), c1("activity"), c2("product"), c3("organization");
118 std::string c4("model"), c5("experiment"), c6("frequency"), c7("modeling_realm");
119 std::string c8("variable_name"), c9("ensemble"), c10("time");
120 tableFields.push_back(cx);
121 tableFields.push_back(c0);
122 tableFields.push_back(c1);
123 tableFields.push_back(c2);
124 tableFields.push_back(c3);
125 tableFields.push_back(c4);
126 tableFields.push_back(c5);
127 tableFields.push_back(c6);
128 tableFields.push_back(c7);
129 tableFields.push_back(c8);
130 tableFields.push_back(c9);
131 tableFields.push_back(c10);
Chengyu Fanf4c747a2015-08-18 13:56:01 -0600132 publishAdapterTest1.setDatabaseTable(databaseTable);
133 publishAdapterTest1.setTableFields(tableFields);
134 publishAdapterTest2.setDatabaseTable(databaseTable);
135 publishAdapterTest2.setTableFields(tableFields);
Chengyu Fanc7b87ad2015-07-09 16:44:37 -0600136 }
137
138 virtual
139 ~PublishAdapterFixture()
140 {
141 }
142
143 protected:
144 void
145 initializePublishAdapterTest1()
146 {
147 util::ConfigSection section;
148 try {
149 std::stringstream ss;
150 ss << "database \
151 { \
152 dbServer localhost \
153 dbName testdb \
154 dbUser testuser \
155 dbPasswd testpwd \
156 } \
157 sync \
158 { \
159 prefix ndn:/ndn/broadcast1 \
160 }";
161 boost::property_tree::read_info(ss, section);
162 }
163 catch (boost::property_tree::info_parser_error &e) {
164 std::cout << "Failed to read config file " << e.what() << std::endl;
165 }
Chengyu Fanf4c747a2015-08-18 13:56:01 -0600166
Chengyu Fanc7b87ad2015-07-09 16:44:37 -0600167 publishAdapterTest1.configAdapter(section, ndn::Name("/test"));
168 }
169
170 void
171 initializePublishAdapterTest2()
172 {
173 util::ConfigSection section;
174 try {
175 std::stringstream ss;
176 ss << "\
177 signingId /prefix/signingId \
178 database \
179 { \
180 dbServer localhost \
181 dbName testdb \
182 dbUser testuser \
183 dbPasswd testpwd \
184 } \
185 sync \
186 { \
187 }";
188 boost::property_tree::read_info(ss, section);
189 }
190 catch (boost::property_tree::info_parser_error &e) {
191 std::cout << "Failed to read config file " << e.what() << std::endl;;
192 }
Chengyu Fanf4c747a2015-08-18 13:56:01 -0600193
Chengyu Fanc7b87ad2015-07-09 16:44:37 -0600194 publishAdapterTest2.configAdapter(section, ndn::Name("/test"));
195 }
196
197 protected:
198 std::shared_ptr<DummyClientFace> face;
199 std::shared_ptr<ndn::KeyChain> keyChain;
Chengyu Fanf4c747a2015-08-18 13:56:01 -0600200 std::vector<std::string> tableFields;
201 std::string databaseTable;
Chengyu Fanc7b87ad2015-07-09 16:44:37 -0600202 PublishAdapterTest publishAdapterTest1;
203 PublishAdapterTest publishAdapterTest2;
204 };
205
206 BOOST_FIXTURE_TEST_SUITE(PublishAdapterTestSuite, PublishAdapterFixture)
207
208 BOOST_AUTO_TEST_CASE(BasicPublishAdapterTest1)
209 {
210 BOOST_CHECK(publishAdapterTest1.getPrefix() == ndn::Name());
211 BOOST_CHECK(publishAdapterTest1.getSigningId() == ndn::Name());
212 BOOST_CHECK(publishAdapterTest1.getSyncPrefix() == ndn::Name());
213 }
214
215 BOOST_AUTO_TEST_CASE(BasicPublishAdapterTest2)
216 {
217 initializePublishAdapterTest1();
218 BOOST_CHECK(publishAdapterTest1.getPrefix() == ndn::Name("/test"));
219 BOOST_CHECK(publishAdapterTest1.getSigningId() == ndn::Name());
220 BOOST_CHECK(publishAdapterTest1.getSyncPrefix() == ndn::Name("ndn:/ndn/broadcast1"));
221
222 initializePublishAdapterTest2();
223 BOOST_CHECK(publishAdapterTest2.getPrefix() == ndn::Name("/test"));
224 BOOST_CHECK(publishAdapterTest2.getSigningId() == ndn::Name("/prefix/signingId"));
225 BOOST_CHECK(publishAdapterTest2.getSyncPrefix() ==
226 ndn::Name("ndn:/ndn-atmos/broadcast/chronosync"));
227 }
228
Chengyu Fan46398212015-08-11 11:23:13 -0600229 BOOST_AUTO_TEST_CASE(PublishAdapterName2FieldsNormalTest)
230 {
231 std::string testFileName1 = "/1/2/3/4/5/6/7/8/9/10";
232 std::stringstream ss;
233 std::string expectString1 = ",'1','2','3','4','5','6','7','8','9','10'";
234 BOOST_CHECK_EQUAL(publishAdapterTest1.testName2Fields(ss, testFileName1), true);
235 BOOST_CHECK_EQUAL(ss.str(), expectString1);
236
237 ss.str("");
238 ss.clear();
239 std::string testFileName2 = "ndn:/1/2/3/4/5/6/777/8/99999/10";
240 std::string expectString2 = ",'1','2','3','4','5','6','777','8','99999','10'";
241 BOOST_CHECK_EQUAL(publishAdapterTest1.testName2Fields(ss, testFileName2), true);
242 BOOST_CHECK_EQUAL(ss.str(), expectString2);
243 }
244
245 BOOST_AUTO_TEST_CASE(PublishAdapterName2FieldsFailureTest)
246 {
247 std::string testFileName1 = "/1/2/3/4/5/6/7/8/9/10/11";//too much components
248 std::stringstream ss;
249 BOOST_CHECK_EQUAL(publishAdapterTest1.testName2Fields(ss, testFileName1), false);
250
251 ss.str("");
252 ss.clear();
253 std::string testFileName2 = "1234567890";
254 BOOST_CHECK_EQUAL(publishAdapterTest1.testName2Fields(ss, testFileName2), false);
255
256 ss.str("");
257 ss.clear();
258 std::string testFileName3 = "ndn:/1/2/3/4/5"; //too little components
259 BOOST_CHECK_EQUAL(publishAdapterTest1.testName2Fields(ss, testFileName3), false);
260 }
261
262 BOOST_AUTO_TEST_CASE(PublishAdapterSqlStringNormalTest)
263 {
264 Json::Value testJson;
265 testJson["add"][0] = "/1/2/3/4/5/6/7/8/9/10";
266 testJson["add"][1] = "ndn:/a/b/c/d/eee/f/gg/h/iiii/j";
267 testJson["remove"][0] = "ndn:/1/2/3/4/5/6/7/8/9/10";
268 testJson["remove"][1] = "/a/b/c/d";
269 testJson["remove"][2] = "/test/for/remove";
270
271 std::stringstream ss;
272 std::string expectRes1 = "INSERT INTO cmip5 (sha256, name, activity, product, organization, \
273model, experiment, frequency, modeling_realm, variable_name, ensemble, time) VALUES(\
274'3738C9C0E0297DE7FE0EE538030597442DEEFF0F2C88778404D7B6E4BAD589F6','/1/2/3/4/5/6/7/8/9/10',\
275'1','2','3','4','5','6','7','8','9','10'),\
276('F93128EE9B7769105C6BDF6AA0FAA8CB4ED429395DDBC2CDDBFBA05F35B320FB','ndn:/a/b/c/d/eee/f/gg/h/iiii/j'\
277,'a','b','c','d','eee','f','gg','h','iiii','j');";
278 BOOST_CHECK_EQUAL(publishAdapterTest1.testJson2Sql(ss, testJson, util::ADD), true);
279 BOOST_CHECK_EQUAL(ss.str(), expectRes1);
280
281 ss.str("");
282 ss.clear();
Chengyu Fan71b712b2015-09-09 22:13:56 -0600283 std::string expectRes2 = "DELETE FROM cmip5 WHERE name IN ('ndn:/1/2/3/4/5/6/7/8/9/10',\
Chengyu Fan46398212015-08-11 11:23:13 -0600284'/a/b/c/d','/test/for/remove');";
285 BOOST_CHECK_EQUAL(publishAdapterTest1.testJson2Sql(ss, testJson, util::REMOVE), true);
286 BOOST_CHECK_EQUAL(ss.str(), expectRes2);
287 }
288
289 BOOST_AUTO_TEST_CASE(PublishAdapterSqlStringFailureTest)
290 {
291 Json::Value testJson;
292 testJson["add"][0] = "/1/2/3/4/5/6/7/8/9/10";
293 testJson["add"][1] = "/a/b/c/d/eee/f/gg/h/iiii/j/kkk"; //too much components
294 std::stringstream ss;
295 bool res = publishAdapterTest1.testJson2Sql(ss, testJson, util::REMOVE);
296 BOOST_CHECK(res == false);
297 }
298
Chengyu Fanc7b87ad2015-07-09 16:44:37 -0600299 BOOST_AUTO_TEST_CASE(PublishAdapterValidateDataTestSuccess)
300 {
301 ndn::Name dataName("/test/publisher/12345"); // data name must be prefix+nonce
302 Json::Value testJson;
303 testJson["add"][0] = "/test/publisher/1";
304 testJson["add"][1] = "/test/publisher/2";
305 testJson["remove"][0] = "/test/publisher/5";
306
307 Json::FastWriter fastWriter;
308 const std::string jsonMessage = fastWriter.write(testJson);
309 const char* payload = jsonMessage.c_str();
310 size_t payLoadLength = jsonMessage.size() + 1;
311
312 std::shared_ptr<ndn::Data> data = std::make_shared<ndn::Data>(dataName);
313 data->setContent(reinterpret_cast<const uint8_t*>(payload), payLoadLength);
314 data->setFreshnessPeriod(ndn::time::milliseconds(10000));
315
316 BOOST_CHECK_EQUAL(true, publishAdapterTest1.testValidatePublicationChanges(data));
317
318 ndn::Name dataName2("/"); // short data name
319 Json::Value testJson2;
320 testJson2["add"][0] = "/test/publisher2/1";
321 testJson2["remove"][0] = "/test/publisher/1/2/3";
322
323 const std::string jsonMessage2 = fastWriter.write(testJson2);
324 const char* payload2 = jsonMessage2.c_str();
325 size_t payLoadLength2 = jsonMessage2.size() + 1;
326
327 std::shared_ptr<ndn::Data> data2 = std::make_shared<ndn::Data>(dataName2);
328 data2->setContent(reinterpret_cast<const uint8_t*>(payload2), payLoadLength2);
329 data2->setFreshnessPeriod(ndn::time::milliseconds(10000));
330 BOOST_CHECK_EQUAL(true, publishAdapterTest1.testValidatePublicationChanges(data2));
331 }
332
333 BOOST_AUTO_TEST_CASE(PublishAdapterValidateDataTestFail)
334 {
335 ndn::Name dataName1("test/publisher2/12345"); // data name must be prefix+nonce
336 Json::Value testJson1;
337 testJson1["add"][0] = "/test/publisher2/1";
338 testJson1["remove"][0] = "/test/publisher/1/2/3";
339 testJson1["remove"][1] = "/test/publisher2/4";
340
341 Json::FastWriter fastWriter;
342 const std::string jsonMessage1 = fastWriter.write(testJson1);
343 const char* payload1 = jsonMessage1.c_str();
344 size_t payLoadLength1 = jsonMessage1.size() + 1;
345
346 std::shared_ptr<ndn::Data> data1 = std::make_shared<ndn::Data>(dataName1);
347 data1->setContent(reinterpret_cast<const uint8_t*>(payload1), payLoadLength1);
348 data1->setFreshnessPeriod(ndn::time::milliseconds(10000));
349
350 BOOST_CHECK_EQUAL(false, publishAdapterTest1.testValidatePublicationChanges(data1));
351 }
352
353 BOOST_AUTO_TEST_SUITE_END()
354
355}//tests
356}//atmos