blob: 18d3a08fae6b538783946d7a85d22f4861f443d9 [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{
Chengyu Fanc7b87ad2015-07-09 16:44:37 -060031
32 class PublishAdapterTest : public publish::PublishAdapter<std::string>
33 {
34 public:
Chengyu Fanca4d40d2016-08-22 13:47:08 -060035 PublishAdapterTest(std::shared_ptr<ndn::util::DummyClientFace>& face,
Chengyu Fancfb80c72015-10-19 16:50:04 -060036 const std::shared_ptr<ndn::KeyChain>& keyChain,
37 std::shared_ptr<chronosync::Socket>& syncSocket)
38 : publish::PublishAdapter<std::string>(face, keyChain, syncSocket)
Chengyu Fanc7b87ad2015-07-09 16:44:37 -060039 {
40 }
41
42 virtual
43 ~PublishAdapterTest()
44 {
45 }
46
Chengyu Fanf4c747a2015-08-18 13:56:01 -060047 void
48 setDatabaseTable(const std::string& databaseTable)
49 {
50 m_databaseTable = databaseTable;
51 }
52
53 void
54 setTableFields(const std::vector<std::string>& tableFields)
Chengyu Fan46398212015-08-11 11:23:13 -060055 {
56 m_tableColumns = tableFields;
57 }
58
Chengyu Fanc7b87ad2015-07-09 16:44:37 -060059 const ndn::Name
60 getPrefix()
61 {
62 return m_prefix;
63 }
64
65 const ndn::Name
66 getSigningId()
67 {
68 return m_signingId;
69 }
70
71 const ndn::Name
72 getSyncPrefix()
73 {
74 return m_syncPrefix;
75 }
76
77 void
78 configAdapter(const util::ConfigSection& section,
79 const ndn::Name& prefix)
80 {
81 onConfig(section, false, std::string("test.txt"), prefix);
82 }
83
84 bool
Chengyu Fan46398212015-08-11 11:23:13 -060085 testJson2Sql(std::stringstream& sqlString,
86 Json::Value& jsonValue,
87 util::DatabaseOperation operation)
88 {
89 return json2Sql(sqlString, jsonValue, operation);
90 }
91
92 bool
93 testName2Fields(std::stringstream& sqlString,
94 std::string& fileName)
95 {
96 return name2Fields(sqlString, fileName);
97 }
98
99 bool
Chengyu Fanc7b87ad2015-07-09 16:44:37 -0600100 testValidatePublicationChanges(const std::shared_ptr<const ndn::Data>& data)
101 {
102 return validatePublicationChanges(data);
103 }
104 };
105
106 class PublishAdapterFixture : public UnitTestTimeFixture
107 {
108 public:
109 PublishAdapterFixture()
Chengyu Fanca4d40d2016-08-22 13:47:08 -0600110 : face(std::make_shared<ndn::util::DummyClientFace>(io))
Chengyu Fanc7b87ad2015-07-09 16:44:37 -0600111 , keyChain(new ndn::KeyChain())
Chengyu Fanf4c747a2015-08-18 13:56:01 -0600112 , databaseTable("cmip5")
Chengyu Fancfb80c72015-10-19 16:50:04 -0600113 , publishAdapterTest1(face, keyChain, syncSocket)
114 , publishAdapterTest2(face, keyChain, syncSocket)
Chengyu Fanc7b87ad2015-07-09 16:44:37 -0600115 {
Chengyu Fan46398212015-08-11 11:23:13 -0600116 std::string cx("sha256"), c0("name"), c1("activity"), c2("product"), c3("organization");
117 std::string c4("model"), c5("experiment"), c6("frequency"), c7("modeling_realm");
118 std::string c8("variable_name"), c9("ensemble"), c10("time");
119 tableFields.push_back(cx);
120 tableFields.push_back(c0);
121 tableFields.push_back(c1);
122 tableFields.push_back(c2);
123 tableFields.push_back(c3);
124 tableFields.push_back(c4);
125 tableFields.push_back(c5);
126 tableFields.push_back(c6);
127 tableFields.push_back(c7);
128 tableFields.push_back(c8);
129 tableFields.push_back(c9);
130 tableFields.push_back(c10);
Chengyu Fanf4c747a2015-08-18 13:56:01 -0600131 publishAdapterTest1.setDatabaseTable(databaseTable);
132 publishAdapterTest1.setTableFields(tableFields);
133 publishAdapterTest2.setDatabaseTable(databaseTable);
134 publishAdapterTest2.setTableFields(tableFields);
Chengyu Fanc7b87ad2015-07-09 16:44:37 -0600135 }
136
137 virtual
138 ~PublishAdapterFixture()
139 {
140 }
141
142 protected:
143 void
144 initializePublishAdapterTest1()
145 {
146 util::ConfigSection section;
147 try {
148 std::stringstream ss;
149 ss << "database \
150 { \
151 dbServer localhost \
152 dbName testdb \
153 dbUser testuser \
154 dbPasswd testpwd \
155 } \
156 sync \
157 { \
158 prefix ndn:/ndn/broadcast1 \
159 }";
160 boost::property_tree::read_info(ss, section);
161 }
162 catch (boost::property_tree::info_parser_error &e) {
163 std::cout << "Failed to read config file " << e.what() << std::endl;
164 }
Chengyu Fanf4c747a2015-08-18 13:56:01 -0600165
Chengyu Fanc7b87ad2015-07-09 16:44:37 -0600166 publishAdapterTest1.configAdapter(section, ndn::Name("/test"));
167 }
168
169 void
170 initializePublishAdapterTest2()
171 {
172 util::ConfigSection section;
173 try {
174 std::stringstream ss;
175 ss << "\
176 signingId /prefix/signingId \
177 database \
178 { \
179 dbServer localhost \
180 dbName testdb \
181 dbUser testuser \
182 dbPasswd testpwd \
183 } \
184 sync \
185 { \
186 }";
187 boost::property_tree::read_info(ss, section);
188 }
189 catch (boost::property_tree::info_parser_error &e) {
190 std::cout << "Failed to read config file " << e.what() << std::endl;;
191 }
Chengyu Fanf4c747a2015-08-18 13:56:01 -0600192
Chengyu Fanc7b87ad2015-07-09 16:44:37 -0600193 publishAdapterTest2.configAdapter(section, ndn::Name("/test"));
194 }
195
196 protected:
Chengyu Fanca4d40d2016-08-22 13:47:08 -0600197 std::shared_ptr<ndn::util::DummyClientFace> face;
Chengyu Fanc7b87ad2015-07-09 16:44:37 -0600198 std::shared_ptr<ndn::KeyChain> keyChain;
Chengyu Fancfb80c72015-10-19 16:50:04 -0600199 std::shared_ptr<chronosync::Socket> syncSocket;
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