blob: 99d7e9020d9362c0bcd19d7e9910bc3b8d2ff780 [file] [log] [blame]
/** NDN-Atmos: Cataloging Service for distributed data originally developed
* for atmospheric science data
* Copyright (C) 2015 Colorado State University
*
* NDN-Atmos is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* NDN-Atmos is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with NDN-Atmos. If not, see <http://www.gnu.org/licenses/>.
**/
#include "publish/publish-adapter.hpp"
#include "boost-test.hpp"
#include "../../unit-test-time-fixture.hpp"
#include "util/config-file.hpp"
#include <boost/mpl/list.hpp>
#include <boost/thread.hpp>
#include <ndn-cxx/util/dummy-client-face.hpp>
#include <boost/property_tree/info_parser.hpp>
namespace atmos{
namespace tests{
using ndn::util::DummyClientFace;
using ndn::util::makeDummyClientFace;
class PublishAdapterTest : public publish::PublishAdapter<std::string>
{
public:
PublishAdapterTest(const std::shared_ptr<ndn::util::DummyClientFace>& face,
const std::shared_ptr<ndn::KeyChain>& keyChain,
std::shared_ptr<chronosync::Socket>& syncSocket)
: publish::PublishAdapter<std::string>(face, keyChain, syncSocket)
{
}
virtual
~PublishAdapterTest()
{
}
void
setDatabaseTable(const std::string& databaseTable)
{
m_databaseTable = databaseTable;
}
void
setTableFields(const std::vector<std::string>& tableFields)
{
m_tableColumns = tableFields;
}
const ndn::Name
getPrefix()
{
return m_prefix;
}
const ndn::Name
getSigningId()
{
return m_signingId;
}
const ndn::Name
getSyncPrefix()
{
return m_syncPrefix;
}
void
configAdapter(const util::ConfigSection& section,
const ndn::Name& prefix)
{
onConfig(section, false, std::string("test.txt"), prefix);
}
bool
testJson2Sql(std::stringstream& sqlString,
Json::Value& jsonValue,
util::DatabaseOperation operation)
{
return json2Sql(sqlString, jsonValue, operation);
}
bool
testName2Fields(std::stringstream& sqlString,
std::string& fileName)
{
return name2Fields(sqlString, fileName);
}
bool
testValidatePublicationChanges(const std::shared_ptr<const ndn::Data>& data)
{
return validatePublicationChanges(data);
}
};
class PublishAdapterFixture : public UnitTestTimeFixture
{
public:
PublishAdapterFixture()
: face(makeDummyClientFace(io))
, keyChain(new ndn::KeyChain())
, databaseTable("cmip5")
, publishAdapterTest1(face, keyChain, syncSocket)
, publishAdapterTest2(face, keyChain, syncSocket)
{
std::string cx("sha256"), c0("name"), c1("activity"), c2("product"), c3("organization");
std::string c4("model"), c5("experiment"), c6("frequency"), c7("modeling_realm");
std::string c8("variable_name"), c9("ensemble"), c10("time");
tableFields.push_back(cx);
tableFields.push_back(c0);
tableFields.push_back(c1);
tableFields.push_back(c2);
tableFields.push_back(c3);
tableFields.push_back(c4);
tableFields.push_back(c5);
tableFields.push_back(c6);
tableFields.push_back(c7);
tableFields.push_back(c8);
tableFields.push_back(c9);
tableFields.push_back(c10);
publishAdapterTest1.setDatabaseTable(databaseTable);
publishAdapterTest1.setTableFields(tableFields);
publishAdapterTest2.setDatabaseTable(databaseTable);
publishAdapterTest2.setTableFields(tableFields);
}
virtual
~PublishAdapterFixture()
{
}
protected:
void
initializePublishAdapterTest1()
{
util::ConfigSection section;
try {
std::stringstream ss;
ss << "database \
{ \
dbServer localhost \
dbName testdb \
dbUser testuser \
dbPasswd testpwd \
} \
sync \
{ \
prefix ndn:/ndn/broadcast1 \
}";
boost::property_tree::read_info(ss, section);
}
catch (boost::property_tree::info_parser_error &e) {
std::cout << "Failed to read config file " << e.what() << std::endl;
}
publishAdapterTest1.configAdapter(section, ndn::Name("/test"));
}
void
initializePublishAdapterTest2()
{
util::ConfigSection section;
try {
std::stringstream ss;
ss << "\
signingId /prefix/signingId \
database \
{ \
dbServer localhost \
dbName testdb \
dbUser testuser \
dbPasswd testpwd \
} \
sync \
{ \
}";
boost::property_tree::read_info(ss, section);
}
catch (boost::property_tree::info_parser_error &e) {
std::cout << "Failed to read config file " << e.what() << std::endl;;
}
publishAdapterTest2.configAdapter(section, ndn::Name("/test"));
}
protected:
std::shared_ptr<DummyClientFace> face;
std::shared_ptr<ndn::KeyChain> keyChain;
std::shared_ptr<chronosync::Socket> syncSocket;
std::vector<std::string> tableFields;
std::string databaseTable;
PublishAdapterTest publishAdapterTest1;
PublishAdapterTest publishAdapterTest2;
};
BOOST_FIXTURE_TEST_SUITE(PublishAdapterTestSuite, PublishAdapterFixture)
BOOST_AUTO_TEST_CASE(BasicPublishAdapterTest1)
{
BOOST_CHECK(publishAdapterTest1.getPrefix() == ndn::Name());
BOOST_CHECK(publishAdapterTest1.getSigningId() == ndn::Name());
BOOST_CHECK(publishAdapterTest1.getSyncPrefix() == ndn::Name());
}
BOOST_AUTO_TEST_CASE(BasicPublishAdapterTest2)
{
initializePublishAdapterTest1();
BOOST_CHECK(publishAdapterTest1.getPrefix() == ndn::Name("/test"));
BOOST_CHECK(publishAdapterTest1.getSigningId() == ndn::Name());
BOOST_CHECK(publishAdapterTest1.getSyncPrefix() == ndn::Name("ndn:/ndn/broadcast1"));
initializePublishAdapterTest2();
BOOST_CHECK(publishAdapterTest2.getPrefix() == ndn::Name("/test"));
BOOST_CHECK(publishAdapterTest2.getSigningId() == ndn::Name("/prefix/signingId"));
BOOST_CHECK(publishAdapterTest2.getSyncPrefix() ==
ndn::Name("ndn:/ndn-atmos/broadcast/chronosync"));
}
BOOST_AUTO_TEST_CASE(PublishAdapterName2FieldsNormalTest)
{
std::string testFileName1 = "/1/2/3/4/5/6/7/8/9/10";
std::stringstream ss;
std::string expectString1 = ",'1','2','3','4','5','6','7','8','9','10'";
BOOST_CHECK_EQUAL(publishAdapterTest1.testName2Fields(ss, testFileName1), true);
BOOST_CHECK_EQUAL(ss.str(), expectString1);
ss.str("");
ss.clear();
std::string testFileName2 = "ndn:/1/2/3/4/5/6/777/8/99999/10";
std::string expectString2 = ",'1','2','3','4','5','6','777','8','99999','10'";
BOOST_CHECK_EQUAL(publishAdapterTest1.testName2Fields(ss, testFileName2), true);
BOOST_CHECK_EQUAL(ss.str(), expectString2);
}
BOOST_AUTO_TEST_CASE(PublishAdapterName2FieldsFailureTest)
{
std::string testFileName1 = "/1/2/3/4/5/6/7/8/9/10/11";//too much components
std::stringstream ss;
BOOST_CHECK_EQUAL(publishAdapterTest1.testName2Fields(ss, testFileName1), false);
ss.str("");
ss.clear();
std::string testFileName2 = "1234567890";
BOOST_CHECK_EQUAL(publishAdapterTest1.testName2Fields(ss, testFileName2), false);
ss.str("");
ss.clear();
std::string testFileName3 = "ndn:/1/2/3/4/5"; //too little components
BOOST_CHECK_EQUAL(publishAdapterTest1.testName2Fields(ss, testFileName3), false);
}
BOOST_AUTO_TEST_CASE(PublishAdapterSqlStringNormalTest)
{
Json::Value testJson;
testJson["add"][0] = "/1/2/3/4/5/6/7/8/9/10";
testJson["add"][1] = "ndn:/a/b/c/d/eee/f/gg/h/iiii/j";
testJson["remove"][0] = "ndn:/1/2/3/4/5/6/7/8/9/10";
testJson["remove"][1] = "/a/b/c/d";
testJson["remove"][2] = "/test/for/remove";
std::stringstream ss;
std::string expectRes1 = "INSERT INTO cmip5 (sha256, name, activity, product, organization, \
model, experiment, frequency, modeling_realm, variable_name, ensemble, time) VALUES(\
'3738C9C0E0297DE7FE0EE538030597442DEEFF0F2C88778404D7B6E4BAD589F6','/1/2/3/4/5/6/7/8/9/10',\
'1','2','3','4','5','6','7','8','9','10'),\
('F93128EE9B7769105C6BDF6AA0FAA8CB4ED429395DDBC2CDDBFBA05F35B320FB','ndn:/a/b/c/d/eee/f/gg/h/iiii/j'\
,'a','b','c','d','eee','f','gg','h','iiii','j');";
BOOST_CHECK_EQUAL(publishAdapterTest1.testJson2Sql(ss, testJson, util::ADD), true);
BOOST_CHECK_EQUAL(ss.str(), expectRes1);
ss.str("");
ss.clear();
std::string expectRes2 = "DELETE FROM cmip5 WHERE name IN ('ndn:/1/2/3/4/5/6/7/8/9/10',\
'/a/b/c/d','/test/for/remove');";
BOOST_CHECK_EQUAL(publishAdapterTest1.testJson2Sql(ss, testJson, util::REMOVE), true);
BOOST_CHECK_EQUAL(ss.str(), expectRes2);
}
BOOST_AUTO_TEST_CASE(PublishAdapterSqlStringFailureTest)
{
Json::Value testJson;
testJson["add"][0] = "/1/2/3/4/5/6/7/8/9/10";
testJson["add"][1] = "/a/b/c/d/eee/f/gg/h/iiii/j/kkk"; //too much components
std::stringstream ss;
bool res = publishAdapterTest1.testJson2Sql(ss, testJson, util::REMOVE);
BOOST_CHECK(res == false);
}
BOOST_AUTO_TEST_CASE(PublishAdapterValidateDataTestSuccess)
{
ndn::Name dataName("/test/publisher/12345"); // data name must be prefix+nonce
Json::Value testJson;
testJson["add"][0] = "/test/publisher/1";
testJson["add"][1] = "/test/publisher/2";
testJson["remove"][0] = "/test/publisher/5";
Json::FastWriter fastWriter;
const std::string jsonMessage = fastWriter.write(testJson);
const char* payload = jsonMessage.c_str();
size_t payLoadLength = jsonMessage.size() + 1;
std::shared_ptr<ndn::Data> data = std::make_shared<ndn::Data>(dataName);
data->setContent(reinterpret_cast<const uint8_t*>(payload), payLoadLength);
data->setFreshnessPeriod(ndn::time::milliseconds(10000));
BOOST_CHECK_EQUAL(true, publishAdapterTest1.testValidatePublicationChanges(data));
ndn::Name dataName2("/"); // short data name
Json::Value testJson2;
testJson2["add"][0] = "/test/publisher2/1";
testJson2["remove"][0] = "/test/publisher/1/2/3";
const std::string jsonMessage2 = fastWriter.write(testJson2);
const char* payload2 = jsonMessage2.c_str();
size_t payLoadLength2 = jsonMessage2.size() + 1;
std::shared_ptr<ndn::Data> data2 = std::make_shared<ndn::Data>(dataName2);
data2->setContent(reinterpret_cast<const uint8_t*>(payload2), payLoadLength2);
data2->setFreshnessPeriod(ndn::time::milliseconds(10000));
BOOST_CHECK_EQUAL(true, publishAdapterTest1.testValidatePublicationChanges(data2));
}
BOOST_AUTO_TEST_CASE(PublishAdapterValidateDataTestFail)
{
ndn::Name dataName1("test/publisher2/12345"); // data name must be prefix+nonce
Json::Value testJson1;
testJson1["add"][0] = "/test/publisher2/1";
testJson1["remove"][0] = "/test/publisher/1/2/3";
testJson1["remove"][1] = "/test/publisher2/4";
Json::FastWriter fastWriter;
const std::string jsonMessage1 = fastWriter.write(testJson1);
const char* payload1 = jsonMessage1.c_str();
size_t payLoadLength1 = jsonMessage1.size() + 1;
std::shared_ptr<ndn::Data> data1 = std::make_shared<ndn::Data>(dataName1);
data1->setContent(reinterpret_cast<const uint8_t*>(payload1), payLoadLength1);
data1->setFreshnessPeriod(ndn::time::milliseconds(10000));
BOOST_CHECK_EQUAL(false, publishAdapterTest1.testValidatePublicationChanges(data1));
}
BOOST_AUTO_TEST_SUITE_END()
}//tests
}//atmos