switch to ndn-cxx KeyChain v2
ValidatorConfig is temporarily disabled. All commands are
authorized without validation.
refs #4091
Change-Id: I4eea8cd954761424d2d084bda4e8510320b5fb46
diff --git a/tests/dataset-fixtures.hpp b/tests/dataset-fixtures.hpp
index f60526b..fbed46d 100644
--- a/tests/dataset-fixtures.hpp
+++ b/tests/dataset-fixtures.hpp
@@ -20,15 +20,14 @@
#ifndef REPO_TESTS_DATASET_FIXTURES_HPP
#define REPO_TESTS_DATASET_FIXTURES_HPP
-#include <ndn-cxx/security/key-chain.hpp>
+#include "identity-management-fixture.hpp"
#include <vector>
#include <boost/mpl/vector.hpp>
namespace repo {
namespace tests {
-
-class DatasetBase
+class DatasetBase : public virtual IdentityManagementFixture
{
public:
class Error : public std::runtime_error
@@ -57,13 +56,12 @@
if (map.count(name) > 0)
return map[name];
- static ndn::KeyChain keyChain;
static std::vector<uint8_t> content(1500, '-');
std::shared_ptr<ndn::Data> data = std::make_shared<ndn::Data>();
data->setName(name);
data->setContent(&content[0], content.size());
- keyChain.sign(*data);
+ m_keyChain.sign(*data);
map.insert(std::make_pair(name, data));
return data;
diff --git a/tests/identity-management-fixture.cpp b/tests/identity-management-fixture.cpp
new file mode 100644
index 0000000..e824246
--- /dev/null
+++ b/tests/identity-management-fixture.cpp
@@ -0,0 +1,82 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014-2017, Regents of the University of California.
+ *
+ * This file is part of NDN repo-ng (Next generation of NDN repository).
+ * See AUTHORS.md for complete list of repo-ng authors and contributors.
+ *
+ * repo-ng 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.
+ *
+ * repo-ng 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
+ * repo-ng, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "identity-management-fixture.hpp"
+#include <ndn-cxx/security/pib/identity.hpp>
+#include <ndn-cxx/security/pib/key.hpp>
+#include <ndn-cxx/security/pib/pib.hpp>
+#include <ndn-cxx/security/v2/certificate.hpp>
+#include <ndn-cxx/util/io.hpp>
+#include <boost/filesystem.hpp>
+
+namespace repo {
+namespace tests {
+
+IdentityManagementFixture::IdentityManagementFixture()
+ : m_keyChain("pib-memory:", "tpm-memory:")
+{
+ m_keyChain.createIdentity("/DEFAULT");
+}
+
+IdentityManagementFixture::~IdentityManagementFixture()
+{
+ boost::system::error_code ec;
+ for (const auto& certFile : m_certFiles) {
+ boost::filesystem::remove(certFile, ec); // ignore error
+ }
+}
+
+bool
+IdentityManagementFixture::addIdentity(const Name& identity, const ndn::KeyParams& params)
+{
+ try {
+ m_keyChain.createIdentity(identity, params);
+ return true;
+ }
+ catch (const std::runtime_error&) {
+ return false;
+ }
+}
+
+bool
+IdentityManagementFixture::saveIdentityCertificate(const Name& identity, const std::string& filename, bool wantAdd)
+{
+ ndn::security::v2::Certificate cert;
+ try {
+ cert = m_keyChain.getPib().getIdentity(identity).getDefaultKey().getDefaultCertificate();
+ }
+ catch (const ndn::security::Pib::Error&) {
+ if (wantAdd && this->addIdentity(identity)) {
+ return this->saveIdentityCertificate(identity, filename, false);
+ }
+ return false;
+ }
+
+ m_certFiles.push_back(filename);
+ try {
+ ndn::io::save(cert, filename);
+ return true;
+ }
+ catch (const ndn::io::Error&) {
+ return false;
+ }
+}
+
+} // namespace tests
+} // namespace repo
diff --git a/tests/identity-management-fixture.hpp b/tests/identity-management-fixture.hpp
new file mode 100644
index 0000000..300c53a
--- /dev/null
+++ b/tests/identity-management-fixture.hpp
@@ -0,0 +1,66 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014-2017, Regents of the University of California.
+ *
+ * This file is part of NDN repo-ng (Next generation of NDN repository).
+ * See AUTHORS.md for complete list of repo-ng authors and contributors.
+ *
+ * repo-ng 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.
+ *
+ * repo-ng 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
+ * repo-ng, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef REPO_TESTS_IDENTITY_MANAGEMENT_FIXTURE_HPP
+#define REPO_TESTS_IDENTITY_MANAGEMENT_FIXTURE_HPP
+
+#include "common.hpp"
+#include <ndn-cxx/security/key-chain.hpp>
+
+namespace repo {
+namespace tests {
+
+/** \brief a fixture providing an in-memory KeyChain
+ */
+class IdentityManagementFixture : noncopyable
+{
+public:
+ IdentityManagementFixture();
+
+ /** \brief deletes saved certificate files
+ */
+ ~IdentityManagementFixture();
+
+ /** \brief add identity
+ * \return whether successful
+ */
+ bool
+ addIdentity(const Name& identity,
+ const ndn::KeyParams& params = ndn::KeyChain::getDefaultKeyParams());
+
+ /** \brief save identity certificate to a file
+ * \param identity identity name
+ * \param filename file name, should be writable
+ * \param wantAdd if true, add new identity when necessary
+ * \return whether successful
+ */
+ bool
+ saveIdentityCertificate(const Name& identity, const std::string& filename, bool wantAdd = false);
+
+protected:
+ ndn::KeyChain m_keyChain;
+
+private:
+ std::vector<std::string> m_certFiles;
+};
+
+} // namespace tests
+} // namespace repo
+
+#endif // REPO_TESTS_IDENTITY_MANAGEMENT_FIXTURE_HPP
diff --git a/tests/integrated/command-fixture.cpp b/tests/integrated/command-fixture.cpp
new file mode 100644
index 0000000..be800e2
--- /dev/null
+++ b/tests/integrated/command-fixture.cpp
@@ -0,0 +1,34 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014-2017, Regents of the University of California.
+ *
+ * This file is part of NDN repo-ng (Next generation of NDN repository).
+ * See AUTHORS.md for complete list of repo-ng authors and contributors.
+ *
+ * repo-ng 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.
+ *
+ * repo-ng 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
+ * repo-ng, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "command-fixture.hpp"
+
+namespace repo {
+namespace tests {
+
+CommandFixture::CommandFixture()
+ : scheduler(repoFace.getIoService())
+ , keyChain(m_keyChain)
+{
+ this->saveIdentityCertificate(keyChain.getPib().getDefaultIdentity().getName(),
+ "tests/integrated/insert-delete-test.cert");
+}
+
+} // namespace tests
+} // namespace repo
diff --git a/tests/integrated/command-fixture.hpp b/tests/integrated/command-fixture.hpp
new file mode 100644
index 0000000..341e00c
--- /dev/null
+++ b/tests/integrated/command-fixture.hpp
@@ -0,0 +1,46 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014-2017, Regents of the University of California.
+ *
+ * This file is part of NDN repo-ng (Next generation of NDN repository).
+ * See AUTHORS.md for complete list of repo-ng authors and contributors.
+ *
+ * repo-ng 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.
+ *
+ * repo-ng 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
+ * repo-ng, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef REPO_TESTS_INTEGRATED_COMMAND_FIXTURE_HPP
+#define REPO_TESTS_INTEGRATED_COMMAND_FIXTURE_HPP
+
+#include "../identity-management-fixture.hpp"
+#include <ndn-cxx/security/validator-null.hpp>
+
+namespace repo {
+namespace tests {
+
+class CommandFixture : public virtual IdentityManagementFixture
+{
+protected:
+ CommandFixture();
+
+protected:
+ Face repoFace;
+ Scheduler scheduler;
+ KeyChain& keyChain;
+
+ /// \todo #4091 switch to ValidatorPolicyConf and load insert-delete-validator-config.conf
+ ndn::ValidatorNull validator;
+};
+
+} // namespace tests
+} // namespace repo
+
+#endif // REPO_TESTS_INTEGRATED_COMMAND_FIXTURE_HPP
diff --git a/tests/integrated/test-basic-command-insert-delete.cpp b/tests/integrated/test-basic-command-insert-delete.cpp
index f9e58e3..775a16d 100644
--- a/tests/integrated/test-basic-command-insert-delete.cpp
+++ b/tests/integrated/test-basic-command-insert-delete.cpp
@@ -21,13 +21,12 @@
#include "handles/delete-handle.hpp"
#include "storage/sqlite-storage.hpp"
#include "storage/repo-storage.hpp"
-#include "common.hpp"
+#include "command-fixture.hpp"
#include "../repo-storage-fixture.hpp"
#include "../dataset-fixtures.hpp"
#include <ndn-cxx/util/random.hpp>
-#include <ndn-cxx/util/io.hpp>
#include <boost/preprocessor/comparison/not_equal.hpp>
#include <boost/test/unit_test.hpp>
#include <fstream>
@@ -46,13 +45,11 @@
const static uint8_t content[8] = {3, 1, 4, 1, 5, 9, 2, 6};
template<class Dataset>
-class Fixture : public RepoStorageFixture, public Dataset
+class Fixture : public CommandFixture, public RepoStorageFixture, public Dataset
{
public:
Fixture()
- : scheduler(repoFace.getIoService())
- , validator(repoFace)
- , writeHandle(repoFace, *handle, keyChain, scheduler, validator)
+ : writeHandle(repoFace, *handle, keyChain, scheduler, validator)
, deleteHandle(repoFace, *handle, keyChain, scheduler, validator)
, insertFace(repoFace.getIoService())
, deleteFace(repoFace.getIoService())
@@ -61,14 +58,6 @@
deleteHandle.listen(Name("/repo/command"));
}
- ~Fixture()
- {
- repoFace.getIoService().stop();
- }
-
- void
- generateDefaultCertificateFile();
-
void
scheduleInsertEvent();
@@ -85,10 +74,6 @@
delayedInterest();
void
- stopFaceProcess();
-
-
- void
onInsertData(const Interest& interest, const Data& data);
void
@@ -113,10 +98,6 @@
checkDeleteOk(const Interest& interest);
public:
- Face repoFace;
- Scheduler scheduler;
- ValidatorConfig validator;
- KeyChain keyChain;
WriteHandle writeHandle;
DeleteHandle deleteHandle;
Face insertFace;
@@ -124,29 +105,13 @@
std::map<Name, EventId> insertEvents;
};
-template<class T> void
-Fixture<T>::generateDefaultCertificateFile()
-{
- Name defaultIdentity = keyChain.getDefaultIdentity();
- Name defaultKeyname = keyChain.getDefaultKeyNameForIdentity(defaultIdentity);
- Name defaultCertficateName = keyChain.getDefaultCertificateNameForKey(defaultKeyname);
- shared_ptr<ndn::IdentityCertificate> defaultCertficate =
- keyChain.getCertificate(defaultCertficateName);
- //test-integrated should run in root directory of repo-ng.
- //certificate file should be removed after tests for security issue.
- std::fstream certificateFile("tests/integrated/insert-delete-test.cert",
- std::ios::out | std::ios::binary | std::ios::trunc);
- ndn::io::save(*defaultCertficate, certificateFile);
- certificateFile.close();
-}
-
template<class T> void
Fixture<T>::onInsertInterest(const Interest& interest)
{
Data data(Name(interest.getName()));
data.setContent(content, sizeof(content));
data.setFreshnessPeriod(milliseconds(0));
- keyChain.signByIdentity(data, keyChain.getDefaultIdentity());
+ keyChain.sign(data);
insertFace.put(data);
std::map<Name, EventId>::iterator event = insertEvents.find(interest.getName());
if (event != insertEvents.end()) {
@@ -173,12 +138,6 @@
}
template<class T> void
-Fixture<T>::stopFaceProcess()
-{
- repoFace.getIoService().stop();
-}
-
-template<class T> void
Fixture<T>::onInsertData(const Interest& interest, const Data& data)
{
RepoCommandResponse response;
@@ -265,7 +224,7 @@
insertCommandName.append(insertParameter.wireEncode());
Interest insertInterest(insertCommandName);
- keyChain.signByIdentity(insertInterest, keyChain.getDefaultIdentity());
+ keyChain.sign(insertInterest);
//schedule a job to express insertInterest every 50ms
scheduler.scheduleEvent(milliseconds(timeCount * 50 + 1000),
bind(&Fixture<T>::sendInsertInterest, this, insertInterest));
@@ -298,7 +257,7 @@
deleteParameter.setName((*i)->getName());
deleteCommandName.append(deleteParameter.wireEncode());
Interest deleteInterest(deleteCommandName);
- keyChain.signByIdentity(deleteInterest, keyChain.getDefaultIdentity());
+ keyChain.sign(deleteInterest);
scheduler.scheduleEvent(milliseconds(4000 + timeCount * 50),
bind(&Fixture<T>::sendDeleteInterest, this, deleteInterest));
timeCount++;
@@ -313,19 +272,13 @@
BOOST_FIXTURE_TEST_CASE_TEMPLATE(InsertDelete, T, Datasets, Fixture<T>)
{
- this->generateDefaultCertificateFile();
- this->validator.load("tests/integrated/insert-delete-validator-config.conf");
-
// schedule events
this->scheduler.scheduleEvent(seconds(0),
bind(&Fixture<T>::scheduleInsertEvent, this));
this->scheduler.scheduleEvent(seconds(10),
bind(&Fixture<T>::scheduleDeleteEvent, this));
- // schedule an event to terminate IO
- this->scheduler.scheduleEvent(seconds(30),
- bind(&Fixture<T>::stopFaceProcess, this));
- this->repoFace.getIoService().run();
+ this->repoFace.processEvents(seconds(30));
}
BOOST_AUTO_TEST_SUITE_END()
diff --git a/tests/integrated/test-basic-command-watch.cpp b/tests/integrated/test-basic-command-watch.cpp
index 8c4c13e..8b8f327 100644
--- a/tests/integrated/test-basic-command-watch.cpp
+++ b/tests/integrated/test-basic-command-watch.cpp
@@ -19,13 +19,12 @@
#include "handles/watch-handle.hpp"
#include "storage/sqlite-storage.hpp"
-#include "common.hpp"
+#include "command-fixture.hpp"
#include "../repo-storage-fixture.hpp"
#include "../dataset-fixtures.hpp"
#include <ndn-cxx/util/random.hpp>
-#include <ndn-cxx/util/io.hpp>
#include <boost/test/unit_test.hpp>
#include <fstream>
@@ -44,26 +43,16 @@
const static uint8_t content[8] = {3, 1, 4, 1, 5, 9, 2, 6};
template<class Dataset>
-class Fixture : public RepoStorageFixture, public Dataset
+class Fixture : public CommandFixture, public RepoStorageFixture, public Dataset
{
public:
Fixture()
- : scheduler(repoFace.getIoService())
- , validator(repoFace)
- , watchHandle(repoFace, *handle, keyChain, scheduler, validator)
+ : watchHandle(repoFace, *handle, keyChain, scheduler, validator)
, watchFace(repoFace.getIoService())
{
watchHandle.listen(Name("/repo/command"));
}
- ~Fixture()
- {
- repoFace.getIoService().stop();
- }
-
- void
- generateDefaultCertificateFile();
-
void
scheduleWatchEvent();
@@ -77,9 +66,6 @@
delayedInterest();
void
- stopFaceProcess();
-
- void
onWatchData(const Interest& interest, const Data& data);
void
@@ -98,38 +84,18 @@
checkWatchOk(const Interest& interest);
public:
- Face repoFace;
- Scheduler scheduler;
- ValidatorConfig validator;
- KeyChain keyChain;
WatchHandle watchHandle;
Face watchFace;
std::map<Name, EventId> watchEvents;
};
-template<class T> void
-Fixture<T>::generateDefaultCertificateFile()
-{
- Name defaultIdentity = keyChain.getDefaultIdentity();
- Name defaultKeyname = keyChain.getDefaultKeyNameForIdentity(defaultIdentity);
- Name defaultCertficateName = keyChain.getDefaultCertificateNameForKey(defaultKeyname);
- shared_ptr<ndn::IdentityCertificate> defaultCertficate =
- keyChain.getCertificate(defaultCertficateName);
- //test-integrated should run in root directory of repo-ng.
- //certificate file should be removed after tests for security issue.
- std::fstream certificateFile("tests/integrated/insert-delete-test.cert",
- std::ios::out | std::ios::binary | std::ios::trunc);
- ndn::io::save(*defaultCertficate, certificateFile);
- certificateFile.close();
-}
-
template<class T> void
Fixture<T>::onWatchInterest(const Interest& interest)
{
shared_ptr<Data> data = make_shared<Data>(Name(interest.getName()).appendNumber(random::generateWord64()+100));
data->setContent(content, sizeof(content));
data->setFreshnessPeriod(milliseconds(0));
- keyChain.signByIdentity(*data, keyChain.getDefaultIdentity());
+ keyChain.sign(*data);
watchFace.put(*data);
// schedule an event 50ms later to check whether watch is Ok
@@ -152,12 +118,6 @@
}
template<class T> void
-Fixture<T>::stopFaceProcess()
-{
- repoFace.getIoService().stop();
-}
-
-template<class T> void
Fixture<T>::onWatchData(const Interest& interest, const Data& data)
{
RepoCommandResponse response;
@@ -226,7 +186,7 @@
watchParameter.setWatchTimeout(milliseconds(1000000000));
watchCommandName.append(watchParameter.wireEncode());
Interest watchInterest(watchCommandName);
- keyChain.signByIdentity(watchInterest, keyChain.getDefaultIdentity());
+ keyChain.sign(watchInterest);
//schedule a job to express watchInterest
scheduler.scheduleEvent(milliseconds(1000),
bind(&Fixture<T>::sendWatchStartInterest, this, watchInterest));
@@ -235,7 +195,7 @@
RepoCommandParameter watchStopParameter;
watchStopName.append(watchStopParameter.wireEncode());
Interest watchStopInterest(watchStopName);
- keyChain.signByIdentity(watchStopInterest, keyChain.getDefaultIdentity());
+ keyChain.sign(watchStopInterest);
// scheduler.scheduleEvent(milliseconds(10000),
// bind(&Fixture<T>::sendWatchStopInterest, this, watchStopInterest));
@@ -250,17 +210,11 @@
BOOST_FIXTURE_TEST_CASE_TEMPLATE(WatchDelete, T, Dataset, Fixture<T>)
{
- this->generateDefaultCertificateFile();
- this->validator.load("tests/integrated/insert-delete-validator-config.conf");
-
// schedule events
this->scheduler.scheduleEvent(seconds(0),
bind(&Fixture<T>::scheduleWatchEvent, this));
- // schedule an event to terminate IO
- this->scheduler.scheduleEvent(seconds(500),
- bind(&Fixture<T>::stopFaceProcess, this));
- this->repoFace.getIoService().run();
+ this->repoFace.processEvents(seconds(500));
}
BOOST_AUTO_TEST_SUITE_END()
diff --git a/tests/integrated/test-basic-interest-read.cpp b/tests/integrated/test-basic-interest-read.cpp
index 79a7e8f..eb412e8 100644
--- a/tests/integrated/test-basic-interest-read.cpp
+++ b/tests/integrated/test-basic-interest-read.cpp
@@ -81,12 +81,6 @@
}
void
- stopFaceProcess()
- {
- repoFace.getIoService().stop();
- }
-
- void
onReadData(const ndn::Interest& interest, const ndn::Data& data)
{
int rc = memcmp(data.getContent().value(), content, sizeof(content));
@@ -137,10 +131,7 @@
this->scheduler.scheduleEvent(ndn::time::seconds(0),
bind(&BasicInterestReadFixture<T>::scheduleReadEvent, this));
- // schedule an event to terminate IO
- this->scheduler.scheduleEvent(ndn::time::seconds(20),
- bind(&BasicInterestReadFixture<T>::stopFaceProcess, this));
- this->repoFace.getIoService().run();
+ this->repoFace.processEvents(ndn::time::seconds(20));
}
diff --git a/tests/unit/index.cpp b/tests/unit/index.cpp
index ca96536..7a04c36 100644
--- a/tests/unit/index.cpp
+++ b/tests/unit/index.cpp
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
- * Copyright (c) 2014, Regents of the University of California.
+ * Copyright (c) 2014-2017, Regents of the University of California.
*
* This file is part of NDN repo-ng (Next generation of NDN repository).
* See AUTHORS.md for complete list of repo-ng authors and contributors.
@@ -18,10 +18,14 @@
*/
#include "storage/index.hpp"
+#include <ndn-cxx/security/signing-helpers.hpp>
+#include <ndn-cxx/util/crypto.hpp>
+#include <ndn-cxx/util/random.hpp>
#include "../sqlite-fixture.hpp"
#include "../dataset-fixtures.hpp"
+#include <boost/mpl/push_back.hpp>
#include <boost/test/unit_test.hpp>
#include <iostream>
@@ -43,7 +47,7 @@
{
shared_ptr<Data> data = make_shared<Data>(name);
data->setContent(reinterpret_cast<const uint8_t*>(&id), sizeof(id));
- m_keyChain.signWithSha256(*data);
+ m_keyChain.sign(*data, ndn::signingWithSha256());
data->wireEncode();
m_index.insert(*data, id);
diff --git a/tests/unit/repo-storage.cpp b/tests/unit/repo-storage.cpp
index 61632ad..1caecf1 100644
--- a/tests/unit/repo-storage.cpp
+++ b/tests/unit/repo-storage.cpp
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
- * Copyright (c) 2014, Regents of the University of California.
+ * Copyright (c) 2014-2017, Regents of the University of California.
*
* This file is part of NDN repo-ng (Next generation of NDN repository).
* See AUTHORS.md for complete list of repo-ng authors and contributors.
@@ -22,6 +22,7 @@
#include "../dataset-fixtures.hpp"
#include "../repo-storage-fixture.hpp"
+#include <boost/mpl/push_back.hpp>
#include <boost/test/unit_test.hpp>
#include <iostream>
#include <string.h>