Merge branch 'master' of git.irl.cs.ucla.edu:ndn/sync
diff --git a/doc/doxygen.conf b/doc/doxygen.conf
index 0989ca5..5408411 100644
--- a/doc/doxygen.conf
+++ b/doc/doxygen.conf
@@ -568,7 +568,7 @@
# directories like "/usr/src/myproject". Separate the files or directories
# with spaces.
-INPUT = model helper
+INPUT = doc model helper
# This tag can be used to specify the character encoding of the source files
# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
diff --git a/doc/doxygen_boost_dummy.h b/doc/doxygen_boost_dummy.h
new file mode 100644
index 0000000..6a409cc
--- /dev/null
+++ b/doc/doxygen_boost_dummy.h
@@ -0,0 +1 @@
+namespace boost { template<class T> class shared_ptr { T *dummy; }; }
diff --git a/model/sync-digest.cc b/model/sync-digest.cc
index 5ff9418..621b52b 100644
--- a/model/sync-digest.cc
+++ b/model/sync-digest.cc
@@ -120,6 +120,12 @@
EVP_MD_CTX_destroy (m_context);
}
+bool
+Digest::empty () const
+{
+ return m_buffer == 0;
+}
+
void
Digest::reset ()
{
@@ -154,7 +160,8 @@
if (m_buffer == 0)
finalize ();
- BOOST_ASSERT (sizeof (std::size_t) <= m_hashLength);
+ if (sizeof (std::size_t) > m_hashLength)
+ throw DigestCalculationError () << errinfo_at_line (__LINE__);
// just getting first sizeof(std::size_t) bytes
// not ideal, but should work pretty well
@@ -162,13 +169,10 @@
}
bool
-Digest::operator == (Digest &digest)
+Digest::operator == (const Digest &digest) const
{
- if (m_buffer == 0)
- finalize ();
-
- if (digest.m_buffer == 0)
- digest.finalize ();
+ if (m_buffer == 0 || digest.m_buffer == 0)
+ throw DigestCalculationError () << errinfo_at_line (__LINE__);
BOOST_ASSERT (m_hashLength == digest.m_hashLength);
@@ -221,6 +225,10 @@
{
string str;
is >> str; // read string first
+
+ if (str.size () == 0)
+ throw DigestCalculationError () << errinfo_at_line (__LINE__);
+
// uint8_t padding = (3 - str.size () % 3) % 3;
// for (uint8_t i = 0; i < padding; i++) str.push_back ('=');
diff --git a/model/sync-digest.h b/model/sync-digest.h
index f5c83f6..52072d2 100644
--- a/model/sync-digest.h
+++ b/model/sync-digest.h
@@ -42,6 +42,12 @@
Digest ();
/**
+ * @brief Check if digest is empty
+ */
+ bool
+ empty () const;
+
+ /**
* @brief Reset digest to the initial state
*/
void
@@ -55,18 +61,29 @@
/**
* @brief Obtain a short version of the hash (just first sizeof(size_t) bytes
*
- * Side effect: Finalize will be called on `this'
+ * Side effect: finalize() will be called on `this'
*/
std::size_t
getHash ();
/**
+ * @brief Finalize digest. All subsequent calls to "operator <<" will fire an exception
+ */
+ void
+ finalize ();
+
+ /**
* @brief Compare two full digests
*
* Side effect: Finalize will be called on `this' and `digest'
*/
bool
- operator == (Digest &digest);
+ operator == (const Digest &digest) const;
+
+ bool
+ operator != (const Digest &digest) const
+ { return ! (*this == digest); }
+
/**
* @brief Add existing digest to digest calculation
@@ -84,31 +101,18 @@
inline Digest &
operator << (const std::string &str);
+ /**
+ * @brief Add uint32_t value to digest calculation
+ * @param value uint32_t value to put into digest
+ */
inline Digest &
operator << (uint32_t value);
- // /**
- // * @brief Add integer to digest calculation
- // * @param value the value to add to the digest
- // */
- // template<class INT>
- // inline Digest &
- // operator << (INT value);
-
private:
- /**
- * @brief Disabled copy operator
- */
Digest &
operator = (Digest &digest) { return *this; }
/**
- * @brief Finalize digest. All subsequent calls to "operator <<" will fire an exception
- */
- void
- finalize ();
-
- /**
* @brief Add size bytes of buffer to the hash
*/
void
diff --git a/model/sync-full-leaf.cc b/model/sync-full-leaf.cc
index f575056..ee1d3dc 100644
--- a/model/sync-full-leaf.cc
+++ b/model/sync-full-leaf.cc
@@ -37,7 +37,8 @@
FullLeaf::updateDigest ()
{
m_digest.reset ();
- m_digest << getInfo ().getDigest () << getSeq ().getDigest ();
+ m_digest << getInfo ().getDigest () << *getSeq ().getDigest ();
+ m_digest.finalize ();
}
// from Leaf
diff --git a/model/sync-full-state.cc b/model/sync-full-state.cc
index dcc4399..7e4a30f 100644
--- a/model/sync-full-state.cc
+++ b/model/sync-full-state.cc
@@ -91,7 +91,7 @@
LeafContainer::iterator item = m_leaves.find (*info);
if (item == m_leaves.end ())
{
- m_leaves.insert (make_shared<Leaf> (info, cref (seq)));
+ m_leaves.insert (make_shared<FullLeaf> (info, cref (seq)));
}
else
{
diff --git a/model/sync-leaf.cc b/model/sync-leaf.cc
index 6ff48bc..6480480 100644
--- a/model/sync-leaf.cc
+++ b/model/sync-leaf.cc
@@ -30,6 +30,10 @@
{
}
+Leaf::~Leaf ()
+{
+}
+
void
Leaf::setSeq (const SeqNo &seq)
{
diff --git a/model/sync-leaf.h b/model/sync-leaf.h
index c4da60c..037e4a5 100644
--- a/model/sync-leaf.h
+++ b/model/sync-leaf.h
@@ -41,7 +41,7 @@
* @param seq Initial sequence number of the pointer
*/
Leaf (NameInfoConstPtr info, const SeqNo &seq);
- virtual ~Leaf () { }
+ virtual ~Leaf ();
/**
* @brief Get name of the leaf
diff --git a/model/sync-seq-no.cc b/model/sync-seq-no.cc
new file mode 100644
index 0000000..31db4ae
--- /dev/null
+++ b/model/sync-seq-no.cc
@@ -0,0 +1,39 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2012 University of California, Los Angeles
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Zhenkai Zhu <zhenkai@cs.ucla.edu>
+ * 卞超轶 Chaoyi Bian <bcy@pku.edu.cn>
+ * Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#include "sync-seq-no.h"
+#include <boost/make_shared.hpp>
+
+using namespace boost;
+
+namespace Sync {
+
+DigestConstPtr
+SeqNo::getDigest () const
+{
+ DigestPtr digest = make_shared<Digest> ();
+ *digest << m_session << m_seq;
+ digest->finalize ();
+ return digest;
+}
+
+} // Sync
diff --git a/model/sync-seq-no.h b/model/sync-seq-no.h
index fb9e6b8..354a1b6 100644
--- a/model/sync-seq-no.h
+++ b/model/sync-seq-no.h
@@ -29,14 +29,35 @@
namespace Sync {
/**
+ * @ingroup sync
* @brief Sequence number abstraction
- *
- *
*/
class SeqNo
{
public:
/**
+ * @brief Copy constructor
+ * @param seq sequence number object to copy from
+ */
+ SeqNo (const SeqNo &seq)
+ {
+ *this = seq;
+ }
+
+ /**
+ * @brief Assignment operator
+ * @param seq sequence number object to copy from
+ */
+ SeqNo &
+ operator = (const SeqNo &seq)
+ {
+ m_session = seq.m_session;
+ m_seq = seq.m_seq;
+
+ return *this;
+ }
+
+ /**
* @brief Constructor with just sequence number. Session assumed to be zero
* @param seq Sequence number
*/
@@ -55,7 +76,12 @@
, m_seq (seq)
{ }
- inline Digest
+ /**
+ * @brief Get sequence number digest
+ *
+ * Digest will be calculated every time it is requested
+ */
+ DigestConstPtr
getDigest () const;
/**
@@ -82,18 +108,17 @@
return m_session == seq.m_session && m_seq == seq.m_seq;
}
- SeqNo &
- operator = (const SeqNo &seq)
- {
- m_session = seq.m_session;
- m_seq = seq.m_seq;
+ /**
+ * @brief Get session id
+ */
+ uint32_t getSession () const
+ { return m_session; }
- return *this;
- }
-
-private:
- inline void
- updateDigest ();
+ /**
+ * @brief Get sequence number
+ */
+ uint32_t getSeq () const
+ { return m_seq; }
private:
/**
@@ -112,26 +137,8 @@
* For now, wrapping sequence number after max to zero is not supported
*/
uint32_t m_seq;
-
- Digest m_digest;
};
-
-void
-SeqNo::updateDigest ()
-{
- m_digest.reset ();
- m_digest << m_session << m_seq;
-}
-
-Digest
-SeqNo::getDigest () const
-{
- Digest digest;
- return digest;
-}
-
-
} // Sync
#endif // SYNC_SEQ_NO_H
diff --git a/test/test.cc b/test/test.cc
new file mode 100644
index 0000000..55745d9
--- /dev/null
+++ b/test/test.cc
@@ -0,0 +1,25 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2012 University of California, Los Angeles
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Zhenkai Zhu <zhenkai@cs.ucla.edu>
+ * 卞超轶 Chaoyi Bian <bcy@pku.edu.cn>
+ * Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#define BOOST_TEST_MODULE Digest
+#include <boost/test/unit_test.hpp>
+
diff --git a/test/test_digest.cc b/test/test_digest.cc
new file mode 100644
index 0000000..a1ae6a3
--- /dev/null
+++ b/test/test_digest.cc
@@ -0,0 +1,99 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2012 University of California, Los Angeles
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Zhenkai Zhu <zhenkai@cs.ucla.edu>
+ * 卞超轶 Chaoyi Bian <bcy@pku.edu.cn>
+ * Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#include <boost/test/unit_test.hpp>
+#include <boost/test/output_test_stream.hpp>
+using boost::test_tools::output_test_stream;
+
+#include "../model/sync-digest.h"
+#include <iostream>
+#include <sstream>
+
+using namespace Sync;
+using namespace std;
+using namespace boost;
+
+BOOST_AUTO_TEST_SUITE(DigestTestSuite)
+
+BOOST_AUTO_TEST_CASE (BasicTest)
+{
+ Digest d0;
+ BOOST_REQUIRE (d0.empty ());
+}
+
+BOOST_AUTO_TEST_CASE (DigestGenerationTest)
+{
+ Digest d1;
+ BOOST_CHECK_NO_THROW (d1 << "1\n");
+
+ // without explicit finalizing, Digest will not be complete and printing out will cause assert
+ BOOST_CHECK (d1.empty ());
+
+ // fix hash
+ BOOST_CHECK_NO_THROW (d1.getHash ());
+ BOOST_CHECK (!d1.empty ());
+ BOOST_CHECK (d1 == d1);
+
+ BOOST_CHECK_THROW (d1 << "2", DigestCalculationError);
+
+ output_test_stream output;
+ BOOST_CHECK_NO_THROW (output << d1);
+ BOOST_CHECK (output.check_length (40,false) );
+ BOOST_CHECK (output.is_equal ("e5fa44f2b31c1fb553b6021e7360d07d5d91ff5e", true));
+}
+
+BOOST_AUTO_TEST_CASE (DigestComparison)
+{
+ Digest d1;
+ BOOST_CHECK_NO_THROW (d1 << "1\n");
+ BOOST_CHECK_THROW (d1 == d1, DigestCalculationError);
+ BOOST_CHECK_NO_THROW (d1.getHash ());
+ BOOST_CHECK (d1 == d1);
+
+ Digest d2;
+ BOOST_CHECK_NO_THROW (d2 << "2\n");
+ BOOST_CHECK_NO_THROW (d2.getHash ());
+ BOOST_CHECK (d1 != d2);
+
+ Digest d3;
+ istringstream is (string ("e5fa44f2b31c1fb553b6021e7360d07d5d91ff5e")); //real sha-1 for "1\n"
+ BOOST_CHECK_NO_THROW (is >> d3);
+ BOOST_CHECK (!d3.empty ());
+ BOOST_CHECK (d3 == d1);
+ BOOST_CHECK (d3 != d2);
+
+ istringstream is2 (string ("25fa44f2b31c1fb553b6021e7360d07d5d91ff5e")); // some fake hash
+ BOOST_CHECK_THROW (is2 >> d3, DigestCalculationError); // >> can be used only once
+
+ Digest d4;
+ BOOST_CHECK_THROW (is2 >> d4, DigestCalculationError); // is2 is now empty. empty >> is not allowed
+
+ istringstream is3 (string ("25fa44f2b31c1fb553b6021e7360d07d5d91ff5e")); // some fake hash
+ BOOST_CHECK_NO_THROW (is3 >> d4);
+
+ BOOST_CHECK (d4 != d1);
+ BOOST_CHECK (d4 != d2);
+ BOOST_CHECK (d4 != d3);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
+
diff --git a/test/test_leaf.cc b/test/test_leaf.cc
new file mode 100644
index 0000000..d2c8289
--- /dev/null
+++ b/test/test_leaf.cc
@@ -0,0 +1,99 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2012 University of California, Los Angeles
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Zhenkai Zhu <zhenkai@cs.ucla.edu>
+ * 卞超轶 Chaoyi Bian <bcy@pku.edu.cn>
+ * Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#include <boost/test/unit_test.hpp>
+#include <boost/test/output_test_stream.hpp>
+using boost::test_tools::output_test_stream;
+
+#include <boost/make_shared.hpp>
+
+#include "../model/sync-full-leaf.h"
+#include "../model/sync-diff-leaf.h"
+#include "../model/sync-std-name-info.h"
+
+using namespace Sync;
+using namespace std;
+using namespace boost;
+
+BOOST_AUTO_TEST_SUITE(LeafTestSuite)
+
+BOOST_AUTO_TEST_CASE (LeafBase)
+{
+ NameInfoConstPtr name = StdNameInfo::FindOrCreate ("/test/name");
+ BOOST_CHECK (name != 0);
+
+ // find the same name
+ BOOST_CHECK (name.get () == StdNameInfo::FindOrCreate ("/test/name").get ());
+ BOOST_CHECK_EQUAL (name.use_count (), 2);
+
+ BOOST_CHECK_NO_THROW (DiffLeaf x (name, SeqNo (12)));
+ BOOST_CHECK_EQUAL (name.use_count (), 2);
+
+ BOOST_CHECK_NO_THROW (DiffLeaf x (name));
+ BOOST_CHECK_EQUAL (name.use_count (), 2);
+
+ DiffLeaf updateLeaf (name, SeqNo (12));
+ BOOST_CHECK_EQUAL (name.use_count (), 3);
+
+ DiffLeaf removeLeaf (name);
+ BOOST_CHECK_EQUAL (name.use_count (), 4);
+
+ BOOST_CHECK_EQUAL (updateLeaf.getOperation (), UPDATE);
+ BOOST_CHECK_EQUAL (updateLeaf.getSeq ().getSession (), 0);
+ BOOST_CHECK_EQUAL (updateLeaf.getSeq ().getSeq (), 12);
+
+ BOOST_CHECK_EQUAL (removeLeaf.getOperation (), REMOVE);
+ BOOST_CHECK_EQUAL (removeLeaf.getSeq ().getSession (), 0);
+ BOOST_CHECK_EQUAL (removeLeaf.getSeq ().getSeq (), 0);
+
+ BOOST_REQUIRE_NO_THROW (FullLeaf x (name, SeqNo (12)));
+ FullLeaf fullLeaf (name, SeqNo (12));
+ BOOST_CHECK_EQUAL (name.use_count (), 5);
+}
+
+BOOST_AUTO_TEST_CASE (LeafDigest)
+{
+ BOOST_CHECK_EQUAL (StdNameInfo::FindOrCreate ("/test/name").use_count (), 2);
+ NameInfoConstPtr name = StdNameInfo::FindOrCreate ("/test/name");
+ FullLeaf fullLeaf (name, SeqNo (12));
+
+ // fullLeafDigest = hash ( hash(name), hash (session, seqNo) )
+
+ // Digest manualDigest;
+
+ // Digest manualNameDigest;
+ // manualNameDigest << "/test/name";
+ // manualNameDigest.finalize ();
+
+ // Digest manualSeqNoDigest;
+ // manualSeqNoDigest << 0 << 12;
+ // manualSeqNoDigest.finalize ();
+
+ // manualDigest << manualNameDigest << manualSeqNoDigest;
+ // manualDigest.finalize ();
+
+ output_test_stream output;
+ output << fullLeaf.getDigest ();
+ BOOST_CHECK (output.is_equal ("991f8cf6262dfe0f519c63f6e9b92fe69e741a9b", true));
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/test/testapp.cc b/test/testapp.cc
deleted file mode 100644
index 51921d5..0000000
--- a/test/testapp.cc
+++ /dev/null
@@ -1,99 +0,0 @@
-/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil -*- */
-/*
- * Copyright (c) 2012 University of California, Los Angeles
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation;
- *
- * This program 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 this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * Author: Zhenkai Zhu <zhenkai@cs.ucla.edu>
- * 卞超轶 Chaoyi Bian <bcy@pku.edu.cn>
- * Alexander Afanasyev <alexander.afanasyev@ucla.edu>
- */
-
-#include "../model/sync-digest.h"
-#include <boost/lexical_cast.hpp>
-#include <iostream>
-#include <sstream>
-
-using namespace Sync;
-using namespace std;
-using namespace boost;
-
-int
-main (int argc, char **argv)
-{
- Digest test;
- test << "1\n";
-
- // try
- // {
- // cout << "Trying to print without explicit getHash() call: ";
- // cout << test;
- // cout << "Failed (should be asserted)\n";
- // }
- // catch (...)
- // {
- // cout << "OK (exception)\n";
- // }
-
- // without explicit finalizing, Digest will not be complete and printing out will cause assert
- test.getHash ();
-
- try
- {
- cout << "Hash for '1' is " << test << std::endl;
- }
- catch (...)
- {
- cout << "Hash calculation failed\n";
- }
-
- try
- {
- cout << "Trying to add data to hash after finalizing: ";
- test << "2"; // should cause an assert
- cout << "Failed (should be asserted)\n";
- }
- catch (...)
- {
- cout << "OK (exception)\n";
- }
-
- Digest test2;
-// #ifdef DIGEST_BASE64
-// string testString = "sCYyTGkEsqnLS4jW1hyB0Q==";
-// #else
- string testString = lexical_cast<string> (test); //"b026324c6904b2a9cb4b88d6d61c81d1";
-// #endif
- cout << "Hash from string: " << testString << "\n";
- istringstream is (testString);
- is >> test2;
-
- cout << "Result from hash: " << test2 << "\n";
-
- cout << "Compare two hashes: " << (test == test2) << "\n";
-
- Digest test3;
- if (testString[0] != '1')
- testString[0] = '1';
- else
- testString[0] = '2';
-
- istringstream is2(testString);
- is2 >> test3;
-
- cout << "Hash from string: " << test3 << "\n";
- cout << "Compare two hashes: " << (test == test3) << "\n";
-
- return 0;
-}
diff --git a/wscript b/wscript
index 1fc4e84..3ace7da 100644
--- a/wscript
+++ b/wscript
@@ -13,11 +13,12 @@
conf.load("compiler_cxx")
conf.check_cfg(atleast_pkgconfig_version='0.20')
conf.check_cfg(package='openssl', args=['--cflags', '--libs'], uselib_store='SSL')
+ conf.check_cfg(package='libxml-2.0', args=['--cflags', '--libs'], uselib_store='XML')
conf.define ('STANDALONE', 1)
# conf.define ('DIGEST_BASE64', 1) # base64 is not working and probably will not work at all
conf.load('boost')
- conf.check_boost(lib='system iostreams')
+ conf.check_boost(lib='system iostreams test')
conf.load('doxygen')
@@ -26,14 +27,17 @@
features=['cxx', 'cxxshlib'],
source = bld.path.ant_glob(['model/sync-*.cc',
'helper/sync-*.cc']),
- uselib = 'BOOST BOOST_IOSTREAMS SSL'
+ uselib = 'BOOST BOOST_IOSTREAMS SSL XML'
)
- bld.program (target="testapp",
- source = "test/testapp.cc",
+ # Unit tests
+ bld.program (target="unit-tests",
+ source = bld.path.ant_glob(['test/**/*.cc']),
features=['cxx', 'cxxprogram'],
- use = 'sync')
+ use = 'BOOST_TEST sync')
+
+# doxygen docs
from waflib.Build import BuildContext
class doxy (BuildContext):
cmd = "doxygen"