add logger
Change-Id: If41d6d94086ec9fffb954a52e1529ccfad7f42fe
diff --git a/tests/core/logger.t.cpp b/tests/core/logger.t.cpp
new file mode 100644
index 0000000..521be9b
--- /dev/null
+++ b/tests/core/logger.t.cpp
@@ -0,0 +1,335 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014, Regents of the University of California
+ *
+ * This file is part of NSL (NDN Signature Logger).
+ * See AUTHORS.md for complete list of NSL authors and contributors.
+ *
+ * NSL 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.
+ *
+ * NSL 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
+ * NSL, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of nsl authors and contributors.
+ */
+
+#include "logger.hpp"
+#include "identity-fixture.hpp"
+#include "db-fixture.hpp"
+#include <ndn-cxx/util/dummy-client-face.hpp>
+#include <ndn-cxx/util/io.hpp>
+
+#include "boost-test.hpp"
+
+namespace nsl {
+namespace tests {
+
+class LoggerFixture : public IdentityFixture
+ , public DbFixture
+{
+public:
+ LoggerFixture()
+ : face1(ndn::util::makeDummyClientFace(io, {true, true}))
+ , face2(ndn::util::makeDummyClientFace(io, {true, true}))
+ , readInterestOffset1(0)
+ , readDataOffset1(0)
+ , readInterestOffset2(0)
+ , readDataOffset2(0)
+ {
+ }
+
+ ~LoggerFixture()
+ {
+ }
+
+ bool
+ passPacket()
+ {
+ bool hasPassed = false;
+
+ checkFace(face1->sentInterests, readInterestOffset1, *face2, hasPassed);
+ checkFace(face1->sentDatas, readDataOffset1, *face2, hasPassed);
+ checkFace(face2->sentInterests, readInterestOffset2, *face1, hasPassed);
+ checkFace(face2->sentDatas, readDataOffset2, *face1, hasPassed);
+
+ return hasPassed;
+ }
+
+ template<typename Packet>
+ void
+ checkFace(std::vector<Packet>& receivedPackets,
+ size_t& readPacketOffset,
+ ndn::util::DummyClientFace& receiver,
+ bool& hasPassed)
+ {
+ while (receivedPackets.size() > readPacketOffset) {
+ receiver.receive(receivedPackets[readPacketOffset]);
+ readPacketOffset++;
+ hasPassed = true;
+ }
+ }
+
+ void
+ clear()
+ {
+ face1->sentDatas.clear();
+ face1->sentInterests.clear();
+ face2->sentDatas.clear();
+ face2->sentInterests.clear();
+
+ readInterestOffset1 = 0;
+ readDataOffset1 = 0;
+ readInterestOffset2 = 0;
+ readDataOffset2 = 0;
+ }
+
+public:
+ shared_ptr<ndn::util::DummyClientFace> face1;
+ shared_ptr<ndn::util::DummyClientFace> face2;
+
+ size_t readInterestOffset1;
+ size_t readDataOffset1;
+ size_t readInterestOffset2;
+ size_t readDataOffset2;
+};
+
+BOOST_FIXTURE_TEST_SUITE(TestLogger, LoggerFixture)
+
+const std::string CONFIG =
+ "logger-name /test/logger \n"
+ "policy \n"
+ "{ \n"
+ " rule \n"
+ " { \n"
+ " id \"Simple Rule\" \n"
+ " for data \n"
+ " checker \n"
+ " { \n"
+ " type customized \n"
+ " sig-type rsa-sha256 \n"
+ " key-locator \n"
+ " { \n"
+ " type name \n"
+ " hyper-relation \n"
+ " { \n"
+ " k-regex ^([^<KEY>]*)<KEY>(<>*)<><ID-CERT>$ \n"
+ " k-expand \\\\1\\\\2 \n"
+ " h-relation is-strict-prefix-of \n"
+ " p-regex ^(<>*)$ \n"
+ " p-expand \\\\1 \n"
+ " } \n"
+ " } \n"
+ " } \n"
+ " } \n"
+ "} \n"
+ "validator \n"
+ "{ \n"
+ " rule \n"
+ " { \n"
+ " id \"Request Rule\" \n"
+ " for interest \n"
+ " filter \n"
+ " { \n"
+ " type name \n"
+ " name /test/logger/log \n"
+ " relation is-strict-prefix-of \n"
+ " } \n"
+ " checker \n"
+ " { \n"
+ " type customized \n"
+ " sig-type rsa-sha256 \n"
+ " key-locator \n"
+ " { \n"
+ " type name \n"
+ " regex ^[^<KEY>]*<KEY><>*<><ID-CERT>$ \n"
+ " } \n"
+ " } \n"
+ " } \n"
+ " rule \n"
+ " { \n"
+ " id \"Simple Rule\" \n"
+ " for data \n"
+ " checker \n"
+ " { \n"
+ " type customized \n"
+ " sig-type rsa-sha256 \n"
+ " key-locator \n"
+ " { \n"
+ " type name \n"
+ " hyper-relation \n"
+ " { \n"
+ " k-regex ^([^<KEY>]*)<KEY>(<>*)<><ID-CERT>$ \n"
+ " k-expand \\\\1\\\\2 \n"
+ " h-relation is-strict-prefix-of \n"
+ " p-regex ^(<>*)$ \n"
+ " p-expand \\\\1 \n"
+ " } \n"
+ " } \n"
+ " } \n"
+ " } \n"
+ " trust-anchor \n"
+ " { \n"
+ " type file \n"
+ " file-name \"trust-anchor.cert\" \n"
+ " } \n"
+ "} \n";
+
+BOOST_AUTO_TEST_CASE(Basic)
+{
+ namespace fs = boost::filesystem;
+
+ fs::create_directory(fs::path(TEST_LOGGER_PATH));
+
+ fs::path configPath = fs::path(TEST_LOGGER_PATH) / "logger-test.conf";
+ std::ofstream os(configPath.c_str());
+ os << CONFIG;
+ os.close();
+
+ Name root("/ndn");
+ addIdentity(root);
+ auto rootCert = m_keyChain.getCertificate(m_keyChain.getDefaultCertificateNameForIdentity(root));
+ fs::path certPath = fs::path(TEST_LOGGER_PATH) / "trust-anchor.cert";
+ ndn::io::save(*rootCert, certPath.string());
+
+ Logger logger(*face1, configPath.string());
+
+ BOOST_CHECK_EQUAL(logger.getLoggerName(), Name("/test/logger"));
+ BOOST_CHECK_EQUAL(logger.getTreePrefix(), Name("/test/logger/tree"));
+ BOOST_CHECK_EQUAL(logger.getLeafPrefix(), Name("/test/logger/leaf"));
+ BOOST_CHECK_EQUAL(logger.getLogPrefix(), Name("/test/logger/log"));
+
+ advanceClocks(time::milliseconds(2), 100);
+
+ Timestamp rootTs = time::toUnixTimestamp(time::system_clock::now()).count() / 1000;
+ NonNegativeInteger rootSeqNo = logger.addSelfSignedCert(*rootCert, rootTs);
+ BOOST_CHECK_EQUAL(rootSeqNo, 0);
+
+ Name leafInterestName("/test/logger/leaf");
+ leafInterestName.appendNumber(0);
+ auto leafInterest = make_shared<Interest>(leafInterestName);
+
+ face1->receive(*leafInterest);
+ advanceClocks(time::milliseconds(2), 100);
+
+ BOOST_CHECK_EQUAL(face1->sentDatas.size(), 1);
+ BOOST_CHECK(leafInterestName.isPrefixOf(face1->sentDatas[0].getName()));
+
+ face1->sentDatas.clear();
+
+ Name treeInterestName("/test/logger/tree");
+ treeInterestName.appendNumber(0);
+ treeInterestName.appendNumber(0);
+ auto treeInterest = make_shared<Interest>(treeInterestName);
+
+ face1->receive(*treeInterest);
+ advanceClocks(time::milliseconds(2), 100);
+
+ BOOST_CHECK_EQUAL(face1->sentDatas.size(), 1);
+ BOOST_CHECK(treeInterestName.isPrefixOf(face1->sentDatas[0].getName()));
+
+ face1->sentDatas.clear();
+
+ Name tld("/ndn/tld");
+ Name tldKeyName = m_keyChain.generateRsaKeyPair(tld);
+ std::vector<ndn::CertificateSubjectDescription> subjectDescription;
+ auto tldCert =
+ m_keyChain.prepareUnsignedIdentityCertificate(tldKeyName, root,
+ time::system_clock::now(),
+ time::system_clock::now() + time::days(1),
+ subjectDescription);
+ m_keyChain.signByIdentity(*tldCert, root);
+ m_keyChain.addCertificate(*tldCert);
+
+ face2->setInterestFilter(tldCert->getName().getPrefix(-1),
+ [&] (const ndn::InterestFilter&, const Interest&) { face2->put(*tldCert); },
+ ndn::RegisterPrefixSuccessCallback(),
+ [] (const Name&, const std::string&) {});
+ advanceClocks(time::milliseconds(2), 100);
+ clear();
+
+ Name logInterestName("/test/logger/log");
+ logInterestName.append(tldCert->getFullName().wireEncode());
+ logInterestName.appendNumber(0);
+ auto logInterest = make_shared<Interest>(logInterestName);
+ m_keyChain.sign(*logInterest, tldCert->getName());
+
+ face1->receive(*logInterest);
+ do {
+ advanceClocks(time::milliseconds(2), 100);
+ } while (passPacket());
+ clear();
+
+ BOOST_CHECK_EQUAL(logger.getDb().getMaxLeafSeq(), 2);
+ auto leafResult1 = logger.getDb().getLeaf(1);
+ BOOST_CHECK(leafResult1.first != nullptr);
+ BOOST_CHECK(leafResult1.second != nullptr);
+
+
+
+ Name leafInterestName2("/test/logger/leaf");
+ leafInterestName2.appendNumber(1);
+ auto leafInterest2 = make_shared<Interest>(leafInterestName2);
+
+ face1->receive(*leafInterest2);
+ advanceClocks(time::milliseconds(2), 100);
+
+ BOOST_CHECK_EQUAL(face1->sentDatas.size(), 1);
+ BOOST_CHECK(leafInterestName2.isPrefixOf(face1->sentDatas[0].getName()));
+ clear();
+
+
+
+ Name treeInterestName2("/test/logger/tree");
+ treeInterestName2.appendNumber(1);
+ treeInterestName2.appendNumber(0);
+ auto treeInterest2 = make_shared<Interest>(treeInterestName2);
+
+ face1->receive(*treeInterest2);
+ advanceClocks(time::milliseconds(2), 100);
+
+ BOOST_CHECK_EQUAL(face1->sentDatas.size(), 1);
+ BOOST_CHECK(treeInterestName2.isPrefixOf(face1->sentDatas[0].getName()));
+ clear();
+
+
+ auto data = make_shared<Data>(Name("/ndn/tld/data"));
+ m_keyChain.sign(*data, tldCert->getName());
+
+ face2->setInterestFilter(data->getName(),
+ [&] (const ndn::InterestFilter&, const Interest&) { face2->put(*data); },
+ ndn::RegisterPrefixSuccessCallback(),
+ [] (const Name&, const std::string&) {});
+ advanceClocks(time::milliseconds(2), 100);
+ clear();
+
+ Name logInterestName2("/test/logger/log");
+ logInterestName2.append(data->getFullName().wireEncode());
+ logInterestName2.appendNumber(1);
+ auto logInterest2 = make_shared<Interest>(logInterestName2);
+ m_keyChain.sign(*logInterest2, tldCert->getName());
+
+ face1->receive(*logInterest2);
+ do {
+ advanceClocks(time::milliseconds(2), 100);
+ } while (passPacket());
+ clear();
+
+ BOOST_CHECK_EQUAL(logger.getDb().getMaxLeafSeq(), 3);
+ auto leafResult2 = logger.getDb().getLeaf(2);
+ BOOST_CHECK(leafResult2.first != nullptr);
+ BOOST_CHECK(leafResult2.second == nullptr);
+
+
+ fs::remove_all(fs::path(TEST_LOGGER_PATH));
+}
+
+BOOST_AUTO_TEST_SUITE_END()
+
+} // namespace tests
+} // namespace nsl