Testing environment
Change-Id: I431214b62e7cc8793db80a05fe854849b4c6df5b
diff --git a/tests/block-literal.hpp b/tests/block-literal.hpp
new file mode 100644
index 0000000..d36675e
--- /dev/null
+++ b/tests/block-literal.hpp
@@ -0,0 +1,68 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2013-2018 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library 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 Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#ifndef NAC_TESTS_BLOCK_LITERAL_HPP
+#define NAC_TESTS_BLOCK_LITERAL_HPP
+
+#include <ndn-cxx/encoding/block.hpp>
+#include <ndn-cxx/encoding/buffer-stream.hpp>
+#include <ndn-cxx/security/transform.hpp>
+
+namespace ndn {
+namespace nac {
+namespace tests {
+
+/** \brief Construct a \c Block from hexadecimal \p input.
+ * \param input a string containing hexadecimal bytes and comments.
+ * 0-9 and upper-case A-F are input; all other characters are comments.
+ * \param len length of \p input.
+ * \throw security::transform::Error input has odd number of hexadecimal digits.
+ * \throw tlv::Error input cannot be parsed into valid \c Block.
+ *
+ * Example
+ * \code
+ * Block nameBlock = "0706 080141 080142"_block;
+ * Block nackBlock = "FD032005 reason(no-route)=FD03210196"_block;
+ * \endcode
+ */
+inline Block
+operator "" _block(const char* input, std::size_t len)
+{
+ namespace t = ndn::security::transform;
+ t::StepSource ss;
+ OBufferStream os;
+ ss >> t::hexDecode() >> t::streamSink(os);
+
+ for (const char* end = input + len; input != end; ++input) {
+ if (std::strchr("0123456789ABCDEF", *input) != nullptr) {
+ ss.write(reinterpret_cast<const uint8_t*>(input), 1);
+ }
+ }
+ ss.end();
+
+ return Block(os.buf());
+}
+
+} // namespace tests
+} // namespace nac
+} // namespace ndn
+
+#endif // NAC_TESTS_BLOCK_LITERAL_HPP
diff --git a/tests/boost-multi-log-formatter.hpp b/tests/boost-multi-log-formatter.hpp
new file mode 100644
index 0000000..ae37416
--- /dev/null
+++ b/tests/boost-multi-log-formatter.hpp
@@ -0,0 +1,214 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2015 Regents of the University of California.
+ *
+ * Based on work by Martin Ba (http://stackoverflow.com/a/26718189)
+ *
+ * This file is distributed under the Boost Software License, Version 1.0.
+ * (See http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef NDN_TESTS_BOOST_MULTI_LOG_FORMATTER_HPP
+#define NDN_TESTS_BOOST_MULTI_LOG_FORMATTER_HPP
+
+#include <boost/version.hpp>
+
+#if BOOST_VERSION >= 105900
+#include <boost/test/unit_test_parameters.hpp>
+#else
+#include <boost/test/detail/unit_test_parameters.hpp>
+#endif // BOOST_VERSION >= 105900
+
+#include <boost/test/unit_test_log_formatter.hpp>
+#include <boost/test/output/compiler_log_formatter.hpp>
+#include <boost/test/output/xml_log_formatter.hpp>
+
+namespace boost {
+namespace unit_test {
+namespace output {
+
+/**
+ * @brief Log formatter for Boost.Test that outputs the logging to multiple formatters
+ *
+ * The log formatter is designed to output to one or multiple formatters at the same time. For
+ * example, one HRF formatter can output to the standard output, while XML formatter output to
+ * the file.
+ *
+ * Usage:
+ *
+ * // Call in init_unit_test_suite: (this will override the --log_format parameter)
+ * auto formatter = new boost::unit_test::output::multi_log_formatter; // same as already configured logger
+ *
+ * // Prepare and add additional logger(s)
+ * formatter.add(std::make_shared<boost::unit_test::output::xml_log_formatter>(),
+ * std::make_shared<std::ofstream>("out.xml"));
+ *
+ * boost::unit_test::unit_test_log.set_formatter(formatter);
+ *
+ * @note Calling `boost::unit_test::unit_test_log.set_stream(...)` will change the stream for
+ * the original logger.
+ */
+class multi_log_formatter : public unit_test_log_formatter
+{
+public:
+ /**
+ * @brief Create instance of the logger, based on the configured logger instance
+ */
+ multi_log_formatter()
+ {
+ auto format =
+#if BOOST_VERSION > 105900
+ runtime_config::get<output_format>(runtime_config::LOG_FORMAT);
+#else
+ runtime_config::log_format();
+#endif // BOOST_VERSION > 105900
+
+ switch (format) {
+ default:
+#if BOOST_VERSION >= 105900
+ case OF_CLF:
+#else
+ case CLF:
+#endif // BOOST_VERSION >= 105900
+ m_loggers.push_back({std::make_shared<compiler_log_formatter>(), nullptr});
+ break;
+#if BOOST_VERSION >= 105900
+ case OF_XML:
+#else
+ case XML:
+#endif // BOOST_VERSION >= 105900
+ m_loggers.push_back({std::make_shared<xml_log_formatter>(), nullptr});
+ break;
+ }
+ }
+
+ void
+ add(std::shared_ptr<unit_test_log_formatter> formatter, std::shared_ptr<std::ostream> os)
+ {
+ m_loggers.push_back({formatter, os});
+ }
+
+ // Formatter interface
+ void
+ log_start(std::ostream& os, counter_t test_cases_amount)
+ {
+ for (auto& l : m_loggers)
+ l.logger->log_start(l.os == nullptr ? os : *l.os, test_cases_amount);
+ }
+
+ void
+ log_finish(std::ostream& os)
+ {
+ for (auto& l : m_loggers)
+ l.logger->log_finish(l.os == nullptr ? os : *l.os);
+ }
+
+ void
+ log_build_info(std::ostream& os)
+ {
+ for (auto& l : m_loggers)
+ l.logger->log_build_info(l.os == nullptr ? os : *l.os);
+ }
+
+ void
+ test_unit_start(std::ostream& os, const test_unit& tu)
+ {
+ for (auto& l : m_loggers)
+ l.logger->test_unit_start(l.os == nullptr ? os : *l.os, tu);
+ }
+
+ void
+ test_unit_finish(std::ostream& os, const test_unit& tu, unsigned long elapsed)
+ {
+ for (auto& l : m_loggers)
+ l.logger->test_unit_finish(l.os == nullptr ? os : *l.os, tu, elapsed);
+ }
+
+ void
+ test_unit_skipped(std::ostream& os, const test_unit& tu)
+ {
+ for (auto& l : m_loggers)
+ l.logger->test_unit_skipped(l.os == nullptr ? os : *l.os, tu);
+ }
+
+#if BOOST_VERSION >= 105900
+ void
+ log_exception_start(std::ostream& os, const log_checkpoint_data& lcd, const execution_exception& ex)
+ {
+ for (auto& l : m_loggers)
+ l.logger->log_exception_start(l.os == nullptr ? os : *l.os, lcd, ex);
+ }
+
+ void
+ log_exception_finish(std::ostream& os)
+ {
+ for (auto& l : m_loggers)
+ l.logger->log_exception_finish(l.os == nullptr ? os : *l.os);
+ }
+#else
+ void
+ log_exception(std::ostream& os, const log_checkpoint_data& lcd, const execution_exception& ex)
+ {
+ for (auto& l : m_loggers)
+ l.logger->log_exception(l.os == nullptr ? os : *l.os, lcd, ex);
+ }
+#endif // BOOST_VERSION >= 105900
+
+ void
+ log_entry_start(std::ostream& os, const log_entry_data& entry_data, log_entry_types let)
+ {
+ for (auto& l : m_loggers)
+ l.logger->log_entry_start(l.os == nullptr ? os : *l.os, entry_data, let);
+ }
+
+ void
+ log_entry_value(std::ostream& os, const_string value)
+ {
+ for (auto& l : m_loggers)
+ l.logger->log_entry_value(l.os == nullptr ? os : *l.os, value);
+ }
+
+ void
+ log_entry_finish(std::ostream& os)
+ {
+ for (auto& l : m_loggers)
+ l.logger->log_entry_finish(l.os == nullptr ? os : *l.os);
+ }
+
+#if BOOST_VERSION >= 105900
+ void
+ entry_context_start(std::ostream& os, log_level level)
+ {
+ for (auto& l : m_loggers)
+ l.logger->entry_context_start(l.os == nullptr ? os : *l.os, level);
+ }
+
+ void
+ log_entry_context(std::ostream& os, const_string value)
+ {
+ for (auto& l : m_loggers)
+ l.logger->log_entry_context(l.os == nullptr ? os : *l.os, value);
+ }
+
+ void
+ entry_context_finish(std::ostream& os)
+ {
+ for (auto& l : m_loggers)
+ l.logger->entry_context_finish(l.os == nullptr ? os : *l.os);
+ }
+#endif // BOOST_VERSION >= 105900
+
+private:
+ struct LoggerInfo
+ {
+ std::shared_ptr<unit_test_log_formatter> logger;
+ std::shared_ptr<std::ostream> os;
+ };
+ std::vector<LoggerInfo> m_loggers;
+};
+
+} // namespace output
+} // namespace unit_test
+} // namespace boost
+
+#endif // NDN_TESTS_BOOST_MULTI_LOG_FORMATTER_HPP
diff --git a/tests/boost-test.hpp b/tests/boost-test.hpp
new file mode 100644
index 0000000..a19590e
--- /dev/null
+++ b/tests/boost-test.hpp
@@ -0,0 +1,31 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014-2018, Regents of the University of California
+ *
+ * NAC library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * NAC library 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 Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of NAC library authors and contributors.
+ */
+
+#ifndef NDN_NAC_TESTS_BOOST_TEST_HPP
+#define NDN_NAC_TESTS_BOOST_TEST_HPP
+
+// suppress warnings from Boost.Test
+#pragma GCC system_header
+#pragma clang system_header
+
+#include <boost/concept_check.hpp>
+#include <boost/test/output_test_stream.hpp>
+#include <boost/test/unit_test.hpp>
+
+#endif // NDN_NAC_TESTS_BOOST_TEST_HPP
diff --git a/tests/dummy-forwarder.cpp b/tests/dummy-forwarder.cpp
new file mode 100644
index 0000000..ff34fb2
--- /dev/null
+++ b/tests/dummy-forwarder.cpp
@@ -0,0 +1,72 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014-2018, Regents of the University of California
+ *
+ * NAC library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * NAC library 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 Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of NAC library authors and contributors.
+ */
+
+#include "dummy-forwarder.hpp"
+
+#include <boost/asio/io_service.hpp>
+
+namespace ndn {
+namespace nac {
+namespace tests {
+
+DummyForwarder::DummyForwarder(boost::asio::io_service& io, KeyChain& keyChain)
+ : m_io(io)
+ , m_keyChain(keyChain)
+{
+}
+
+Face&
+DummyForwarder::addFace()
+{
+ auto face = std::make_shared<util::DummyClientFace>(m_io, m_keyChain, util::
+ DummyClientFace::Options{true, true});
+ face->onSendInterest.connect([this, face] (const Interest& interest) {
+ for (auto& otherFace : m_faces) {
+ if (&*face == &*otherFace) {
+ continue;
+ }
+ otherFace->receive(interest);
+ }
+ });
+
+ face->onSendData.connect([this, face] (const Data& data) {
+ for (auto& otherFace : m_faces) {
+ if (&*face == &*otherFace) {
+ continue;
+ }
+ otherFace->receive(data);
+ }
+ });
+
+ face->onSendNack.connect([this, face] (const lp::Nack& nack) {
+ for (auto& otherFace : m_faces) {
+ if (&*face == &*otherFace) {
+ continue;
+ }
+ otherFace->receive(nack);
+ }
+ });
+
+ m_faces.push_back(face);
+ return *face;
+}
+
+} // namespace tests
+} // namespace nac
+} // namespace ndn
diff --git a/tests/dummy-forwarder.hpp b/tests/dummy-forwarder.hpp
new file mode 100644
index 0000000..e4f5fd8
--- /dev/null
+++ b/tests/dummy-forwarder.hpp
@@ -0,0 +1,63 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014-2018, Regents of the University of California
+ *
+ * NAC library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * NAC library 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 Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of NAC library authors and contributors.
+ */
+
+#include <ndn-cxx/interest.hpp>
+#include <ndn-cxx/data.hpp>
+#include <ndn-cxx/lp/nack.hpp>
+#include <ndn-cxx/util/dummy-client-face.hpp>
+#include <ndn-cxx/security/key-chain.hpp>
+
+#ifndef NAC_TESTS_TEST_DUMMY_FORWARDER_HPP
+#define NAC_TESTS_TEST_DUMMY_FORWARDER_HPP
+
+namespace ndn {
+namespace nac {
+namespace tests {
+
+/**
+ * @brief Very basic implementation of the dummy forwarder
+ *
+ * Interests expressed by any added face, will be forwarded to all other faces.
+ * Similarly, any pushed data, will be pushed to all other faces.
+ */
+class DummyForwarder
+{
+public:
+ DummyForwarder(boost::asio::io_service& io, KeyChain& keyChain);
+
+ Face&
+ addFace();
+
+ Face&
+ getFace(size_t nFace)
+ {
+ return *m_faces.at(nFace);
+ }
+
+private:
+ boost::asio::io_service& m_io;
+ KeyChain& m_keyChain;
+ std::vector<shared_ptr<util::DummyClientFace>> m_faces;
+};
+
+} // namespace tests
+} // namespace nac
+} // namespace ndn
+
+#endif // NAC_TESTS_TEST_DUMMY_FORWARDER_HPP
diff --git a/tests/identity-management-fixture.cpp b/tests/identity-management-fixture.cpp
new file mode 100644
index 0000000..f8b9c35
--- /dev/null
+++ b/tests/identity-management-fixture.cpp
@@ -0,0 +1,132 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014-2018, Regents of the University of California
+ *
+ * NAC library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * NAC library 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 Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of NAC library authors and contributors.
+ */
+
+#include "identity-management-fixture.hpp"
+
+#include <ndn-cxx/util/io.hpp>
+#include <ndn-cxx/security/v2/additional-description.hpp>
+
+#include <boost/filesystem.hpp>
+
+namespace ndn {
+namespace nac {
+namespace tests {
+
+namespace v2 = security::v2;
+
+IdentityManagementFixture::IdentityManagementFixture()
+ : m_keyChain("pib-memory:", "tpm-memory:")
+{
+}
+
+IdentityManagementFixture::~IdentityManagementFixture()
+{
+ boost::system::error_code ec;
+ for (const auto& certFile : m_certFiles) {
+ boost::filesystem::remove(certFile, ec); // ignore error
+ }
+}
+
+security::Identity
+IdentityManagementFixture::addIdentity(const Name& identityName, const KeyParams& params)
+{
+ auto identity = m_keyChain.createIdentity(identityName, params);
+ m_identities.insert(identityName);
+ return identity;
+}
+
+bool
+IdentityManagementFixture::saveIdentityCertificate(const security::Identity& identity,
+ const std::string& filename)
+{
+ try {
+ auto cert = identity.getDefaultKey().getDefaultCertificate();
+ return saveCertToFile(cert, filename);
+ }
+ catch (const security::Pib::Error&) {
+ return false;
+ }
+}
+
+security::Identity
+IdentityManagementFixture::addSubCertificate(const Name& subIdentityName,
+ const security::Identity& issuer, const KeyParams& params)
+{
+ auto subIdentity = addIdentity(subIdentityName, params);
+
+ v2::Certificate request = subIdentity.getDefaultKey().getDefaultCertificate();
+
+ request.setName(request.getKeyName().append("parent").appendVersion());
+
+ SignatureInfo info;
+ info.setValidityPeriod(security::ValidityPeriod(time::system_clock::now(),
+ time::system_clock::now() + time::days(7300)));
+
+ v2::AdditionalDescription description;
+ description.set("type", "sub-certificate");
+ info.appendTypeSpecificTlv(description.wireEncode());
+
+ m_keyChain.sign(request, signingByIdentity(issuer).setSignatureInfo(info));
+ m_keyChain.setDefaultCertificate(subIdentity.getDefaultKey(), request);
+
+ return subIdentity;
+}
+
+v2::Certificate
+IdentityManagementFixture::addCertificate(const security::Key& key, const std::string& issuer)
+{
+ Name certificateName = key.getName();
+ certificateName
+ .append(issuer)
+ .appendVersion();
+ v2::Certificate certificate;
+ certificate.setName(certificateName);
+
+ // set metainfo
+ certificate.setContentType(tlv::ContentType_Key);
+ certificate.setFreshnessPeriod(time::hours(1));
+
+ // set content
+ certificate.setContent(key.getPublicKey().data(), key.getPublicKey().size());
+
+ // set signature-info
+ SignatureInfo info;
+ info.setValidityPeriod(security::ValidityPeriod(time::system_clock::now(),
+ time::system_clock::now() + time::days(10)));
+
+ m_keyChain.sign(certificate, signingByKey(key).setSignatureInfo(info));
+ return certificate;
+}
+
+bool
+IdentityManagementFixture::saveCertToFile(const Data& obj, const std::string& filename)
+{
+ m_certFiles.insert(filename);
+ try {
+ io::save(obj, filename);
+ return true;
+ }
+ catch (const io::Error&) {
+ return false;
+ }
+}
+
+} // namespace tests
+} // namespace nac
+} // namespace ndn
diff --git a/tests/identity-management-fixture.hpp b/tests/identity-management-fixture.hpp
new file mode 100644
index 0000000..96cbc7f
--- /dev/null
+++ b/tests/identity-management-fixture.hpp
@@ -0,0 +1,95 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014-2018, Regents of the University of California
+ *
+ * NAC library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * NAC library 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 Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of NAC library authors and contributors.
+ */
+
+#ifndef NAC_TESTS_IDENTITY_MANAGEMENT_FIXTURE_HPP
+#define NAC_TESTS_IDENTITY_MANAGEMENT_FIXTURE_HPP
+
+#include "boost-test.hpp"
+
+#include <ndn-cxx/security/v2/key-chain.hpp>
+#include <ndn-cxx/security/signing-helpers.hpp>
+
+#include <vector>
+
+namespace ndn {
+namespace nac {
+namespace tests {
+
+/**
+ * @brief A test suite level fixture to help with identity management
+ *
+ * Test cases in the suite can use this fixture to create identities. Identities,
+ * certificates, and saved certificates are automatically removed during test teardown.
+ */
+class IdentityManagementFixture
+{
+public:
+ IdentityManagementFixture();
+
+ ~IdentityManagementFixture();
+
+ /**
+ * @brief Add identity @p identityName
+ * @return name of the created self-signed certificate
+ */
+ security::Identity
+ addIdentity(const Name& identityName, const KeyParams& params = security::v2::KeyChain::getDefaultKeyParams());
+
+ /**
+ * @brief Save identity certificate to a file
+ * @param identity identity
+ * @param filename file name, should be writable
+ * @return whether successful
+ */
+ bool
+ saveIdentityCertificate(const security::Identity& identity, const std::string& filename);
+
+ /**
+ * @brief Issue a certificate for \p subIdentityName signed by \p issuer
+ *
+ * If identity does not exist, it is created.
+ * A new key is generated as the default key for identity.
+ * A default certificate for the key is signed by the issuer using its default certificate.
+ *
+ * @return the sub identity
+ */
+ security::Identity
+ addSubCertificate(const Name& subIdentityName, const security::Identity& issuer,
+ const KeyParams& params = security::v2::KeyChain::getDefaultKeyParams());
+
+ /**
+ * @brief Add a self-signed certificate to @p key with issuer ID @p issuer
+ */
+ security::v2::Certificate
+ addCertificate(const security::Key& key, const std::string& issuer);
+
+ bool
+ saveCertToFile(const Data& obj, const std::string& filename);
+
+protected:
+ security::v2::KeyChain m_keyChain;
+ std::set<Name> m_identities;
+ std::set<std::string> m_certFiles;
+};
+
+} // namespace tests
+} // namespace nac
+} // namespace ndn
+
+#endif // NAC_TESTS_IDENTITY_MANAGEMENT_FIXTURE_HPP
diff --git a/tests/main.cpp b/tests/main.cpp
new file mode 100644
index 0000000..cef5c60
--- /dev/null
+++ b/tests/main.cpp
@@ -0,0 +1,110 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014-2018, Regents of the University of California
+ *
+ * NAC library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * NAC library 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 Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of NAC library authors and contributors.
+ */
+
+#define BOOST_TEST_MODULE NAC Tests
+#define BOOST_TEST_DYN_LINK
+#define BOOST_TEST_ALTERNATIVE_INIT_API
+
+#include <boost/version.hpp>
+
+#if BOOST_VERSION >= 106200
+// Boost.Test v3.3 (Boost 1.62) natively supports multi-logger output
+#include "boost-test.hpp"
+#else
+#define BOOST_TEST_NO_MAIN
+#include "boost-test.hpp"
+
+#include "boost-multi-log-formatter.hpp"
+
+#include <boost/program_options/options_description.hpp>
+#include <boost/program_options/variables_map.hpp>
+#include <boost/program_options/parsers.hpp>
+
+#include <fstream>
+#include <iostream>
+
+static bool
+init_tests()
+{
+ init_unit_test();
+
+ namespace po = boost::program_options;
+ namespace ut = boost::unit_test;
+
+ po::options_description extraOptions;
+ std::string logger;
+ std::string outputFile = "-";
+ extraOptions.add_options()
+ ("log_format2", po::value<std::string>(&logger), "Type of second log formatter: HRF or XML")
+ ("log_sink2", po::value<std::string>(&outputFile)->default_value(outputFile), "Second log sink, - for stdout")
+ ;
+ po::variables_map vm;
+ try {
+ po::store(po::command_line_parser(ut::framework::master_test_suite().argc,
+ ut::framework::master_test_suite().argv)
+ .options(extraOptions)
+ .run(),
+ vm);
+ po::notify(vm);
+ }
+ catch (const std::exception& e) {
+ std::cerr << "ERROR: " << e.what() << "\n"
+ << extraOptions << std::endl;
+ return false;
+ }
+
+ if (vm.count("log_format2") == 0) {
+ // second logger is not configured
+ return true;
+ }
+
+ std::shared_ptr<ut::unit_test_log_formatter> formatter;
+ if (logger == "XML") {
+ formatter = std::make_shared<ut::output::xml_log_formatter>();
+ }
+ else if (logger == "HRF") {
+ formatter = std::make_shared<ut::output::compiler_log_formatter>();
+ }
+ else {
+ std::cerr << "ERROR: only HRF or XML log formatter can be specified" << std::endl;
+ return false;
+ }
+
+ std::shared_ptr<std::ostream> output;
+ if (outputFile == "-") {
+ output = std::shared_ptr<std::ostream>(&std::cout, std::bind([]{}));
+ }
+ else {
+ output = std::make_shared<std::ofstream>(outputFile.c_str());
+ }
+
+ auto multiFormatter = new ut::output::multi_log_formatter;
+ multiFormatter->add(formatter, output);
+ ut::unit_test_log.set_formatter(multiFormatter);
+
+ return true;
+}
+
+int
+main(int argc, char* argv[])
+{
+ return ::boost::unit_test::unit_test_main(&init_tests, argc, argv);
+}
+
+#endif // BOOST_VERSION >= 106200
diff --git a/tests/tests-common.hpp b/tests/tests-common.hpp
new file mode 100644
index 0000000..40130c8
--- /dev/null
+++ b/tests/tests-common.hpp
@@ -0,0 +1,36 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014-2018, Regents of the University of California
+ *
+ * NAC library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * NAC library 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 Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of NAC library authors and contributors.
+ */
+
+#ifndef NAC_TESTS_TEST_COMMON_HPP
+#define NAC_TESTS_TEST_COMMON_HPP
+
+#include "boost-test.hpp"
+#include "unit-test-common-fixtures.hpp"
+#include "identity-management-fixture.hpp"
+#include "block-literal.hpp"
+
+namespace ndn {
+namespace nac {
+namespace tests {
+
+} // namespace tests
+} // namespace nac
+} // namespace ndn
+
+#endif // NAC_TESTS_TEST_COMMON_HPP
diff --git a/tests/unit-test-common-fixtures.cpp b/tests/unit-test-common-fixtures.cpp
new file mode 100644
index 0000000..f001ef7
--- /dev/null
+++ b/tests/unit-test-common-fixtures.cpp
@@ -0,0 +1,75 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014-2018, Regents of the University of California
+ *
+ * NAC library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * NAC library 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 Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of NAC library authors and contributors.
+ */
+
+#include "tests-common.hpp"
+
+namespace ndn {
+namespace nac {
+namespace tests {
+
+BaseFixture::BaseFixture()
+{
+}
+
+UnitTestTimeFixture::UnitTestTimeFixture()
+ : steadyClock(make_shared<time::UnitTestSteadyClock>())
+ , systemClock(make_shared<time::UnitTestSystemClock>())
+{
+ time::setCustomClocks(steadyClock, systemClock);
+}
+
+UnitTestTimeFixture::~UnitTestTimeFixture()
+{
+ time::setCustomClocks(nullptr, nullptr);
+}
+
+void
+UnitTestTimeFixture::advanceClocks(const time::nanoseconds& tick, size_t nTicks)
+{
+ this->advanceClocks(tick, tick * nTicks);
+}
+
+void
+UnitTestTimeFixture::advanceClocks(const time::nanoseconds& tick, const time::nanoseconds& total)
+{
+ BOOST_ASSERT(tick > time::nanoseconds::zero());
+ BOOST_ASSERT(total >= time::nanoseconds::zero());
+
+ time::nanoseconds remaining = total;
+ while (remaining > time::nanoseconds::zero()) {
+ if (remaining >= tick) {
+ steadyClock->advance(tick);
+ systemClock->advance(tick);
+ remaining -= tick;
+ }
+ else {
+ steadyClock->advance(remaining);
+ systemClock->advance(remaining);
+ remaining = time::nanoseconds::zero();
+ }
+
+ if (m_io.stopped())
+ m_io.reset();
+ m_io.poll();
+ }
+}
+
+} // namespace tests
+} // namespace nac
+} // namespace ndn
diff --git a/tests/unit-test-common-fixtures.hpp b/tests/unit-test-common-fixtures.hpp
new file mode 100644
index 0000000..03ba0f5
--- /dev/null
+++ b/tests/unit-test-common-fixtures.hpp
@@ -0,0 +1,92 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014-2018, Regents of the University of California
+ *
+ * NAC library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * NAC library 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 Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of NAC library authors and contributors.
+ */
+
+#ifndef NAC_TESTS_UNIT_TEST_COMMON_FIXTURES_HPP
+#define NAC_TESTS_UNIT_TEST_COMMON_FIXTURES_HPP
+
+#include "boost-test.hpp"
+#include "identity-management-fixture.hpp"
+
+#include <boost/asio.hpp>
+#include <ndn-cxx/util/time-unit-test-clock.hpp>
+
+namespace ndn {
+namespace nac {
+namespace tests {
+
+/** \brief base test fixture
+ *
+ * Every test case should be based on this fixture,
+ * to have per test case io_service initialization.
+ */
+class BaseFixture : public IdentityManagementFixture
+{
+protected:
+ BaseFixture();
+
+protected:
+ /** \brief reference to global io_service
+ */
+ boost::asio::io_service m_io;
+};
+
+/** \brief a base test fixture that overrides steady clock and system clock
+ */
+class UnitTestTimeFixture : public BaseFixture
+{
+protected:
+ UnitTestTimeFixture();
+
+ ~UnitTestTimeFixture();
+
+ /** \brief advance steady and system clocks
+ *
+ * Clocks are advanced in increments of \p tick for \p nTicks ticks.
+ * After each tick, global io_service is polled to process pending I/O events.
+ *
+ * Exceptions thrown during I/O events are propagated to the caller.
+ * Clock advancing would stop in case of an exception.
+ */
+ void
+ advanceClocks(const time::nanoseconds& tick, size_t nTicks = 1);
+
+ /** \brief advance steady and system clocks
+ *
+ * Clocks are advanced in increments of \p tick for \p total time.
+ * The last increment might be shorter than \p tick.
+ * After each tick, global io_service is polled to process pending I/O events.
+ *
+ * Exceptions thrown during I/O events are propagated to the caller.
+ * Clock advancing would stop in case of an exception.
+ */
+ void
+ advanceClocks(const time::nanoseconds& tick, const time::nanoseconds& total);
+
+protected:
+ shared_ptr<time::UnitTestSteadyClock> steadyClock;
+ shared_ptr<time::UnitTestSystemClock> systemClock;
+
+ friend class LimitedIo;
+};
+
+} // namespace tests
+} // namespace nac
+} // namespace ndn
+
+#endif // NAC_TESTS_UNIT_TEST_COMMON_FIXTURES_HPP
diff --git a/tests/wscript b/tests/wscript
new file mode 100644
index 0000000..a32e9d8
--- /dev/null
+++ b/tests/wscript
@@ -0,0 +1,21 @@
+# -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
+from waflib import Utils
+
+top = '..'
+
+def build(bld):
+ bld.objects(
+ target='tests-main',
+ source='main.cpp',
+ use='libndn-nac')
+
+ config_path = 'TMP_TESTS_PATH="%s"' % bld.bldnode.make_node('tmp-files')
+
+ bld.program(
+ target='../unit-tests',
+ name='unit-tests',
+ source=bld.path.ant_glob('**/*.cpp', excl='main.cpp'),
+ use='libndn-nac tests-main',
+ includes=['.'],
+ install_path=None,
+ defines=[config_path])
diff --git a/wscript b/wscript
index d0c3075..8931c7a 100644
--- a/wscript
+++ b/wscript
@@ -62,9 +62,9 @@
includes = ['src', '.'],
export_includes=['src', '.'])
- # # Unit tests
- # if bld.env['WITH_TESTS']:
- # bld.recurse('tests')
+ # Unit tests
+ if bld.env['WITH_TESTS']:
+ bld.recurse('tests')
bld.install_files(
dest = "%s/ndn-nac" % bld.env['INCLUDEDIR'],