From aa2c51cbff7950392f0574723772c6dc0afb9c0a Mon Sep 17 00:00:00 2001 From: g0dil <g0dil@wiback.org> Date: Wed, 21 May 2008 21:41:58 +0000 Subject: [PATCH] Utils: Document new utilities Console: Implement LinkNode --- Console/Config.cc | 7 +-- Console/Config.test.cc | 34 ++++++++++++++ Console/Executor.cc | 22 +++++++-- Console/Executor.hh | 3 +- Console/Executor.test.cc | 11 +++-- Console/Node.cc | 12 ++++- Console/Node.cci | 54 ++++++++++++++++++++++ Console/Node.hh | 74 ++++++++++++++++++++++-------- Console/Node.test.cc | 26 +++++------ Console/ScopedDirectory.cci | 6 +++ Console/ScopedDirectory.hh | 1 + Console/Server.cci | 2 +- Utils/Backtrace.hh | 19 ++++++++ Utils/Mainpage.dox | 16 ++++++- Console/Node.ct => Utils/Range.cti | 33 ++++++------- Utils/Range.hh | 66 ++++++++++++++++++++++++++ Utils/String.hh | 5 ++ Utils/auto_unit_test.hh | 36 +++++++++++++++ Utils/preprocessor.hh | 2 +- 19 files changed, 357 insertions(+), 72 deletions(-) rename Console/Node.ct => Utils/Range.cti (57%) create mode 100644 Utils/Range.hh diff --git a/Console/Config.cc b/Console/Config.cc index afb365feb..3d2200b37 100644 --- a/Console/Config.cc +++ b/Console/Config.cc @@ -82,11 +82,8 @@ prefix_ void senf::console::ConfigFile::policyCallback(DirectoryNode::ptr restri { if (dir.hasChild(name)) { GenericNode & item (dir.get(name)); - if (restrict && ! item.isChildOf(*restrict)) { - DirectoryNode * itemdir (dynamic_cast<DirectoryNode*>(&item)); - if (! itemdir || ! restrict->isChildOf(*itemdir)) - throw Executor::IgnoreCommandException(); - } + if (restrict && ! item.isChildOf(*restrict) && ! item.isDirectory()) + throw Executor::IgnoreCommandException(); if (parsed(item)) throw Executor::IgnoreCommandException(); } diff --git a/Console/Config.test.cc b/Console/Config.test.cc index 2215ccecb..df3383b15 100644 --- a/Console/Config.test.cc +++ b/Console/Config.test.cc @@ -168,6 +168,40 @@ BOOST_AUTO_UNIT_TEST(configFileSkipGroup) } } +BOOST_AUTO_UNIT_TEST(configRestrictAndLink) +{ + TempFile cfgf ("test.cfg"); + cfgf << "dir1/fun1 10;\n" + << "link1 { dir3 { fun2; } fun1 5; }" + << TempFile::close; + + senf::console::ScopedDirectory<> dir1; + senf::console::root().add("dir1", dir1); + dir1.add("fun1",&fun1); + + senf::console::ScopedDirectory<> dir2; + dir1.add("dir2", dir2); + + dir2.mkdir("dir3").add("fun2", &fun2); + dir2.add("fun1", &fun1); + + senf::console::ScopedDirectory<> dir4; + senf::console::root().add("dir4", dir4); + dir4.link("link1", dir2); + + { + senf::console::ConfigFile cfg (cfgf.name(), dir4); + + var1 = 0; + var2 = false; + SENF_CHECK_NO_THROW( cfg.parse(dir2["dir3"]) ); + BOOST_CHECK_EQUAL( var1, 0 ); + BOOST_CHECK_EQUAL( var2, true ); + + BOOST_CHECK_THROW( cfg.parse(), senf::console::SyntaxErrorException ); + } +} + ///////////////////////////////cc.e//////////////////////////////////////// #undef prefix_ diff --git a/Console/Executor.cc b/Console/Executor.cc index d40f69ddc..d5f56fbdc 100644 --- a/Console/Executor.cc +++ b/Console/Executor.cc @@ -28,7 +28,11 @@ // Custom includes #include <boost/utility.hpp> +#include <boost/range/iterator_range.hpp> +#include <boost/bind.hpp> #include "../Utils/senfassert.hh" +#include "../Utils/Range.hh" +#include "../Utils/String.hh" //#include "Executor.mpp" #define prefix_ @@ -57,6 +61,18 @@ prefix_ senf::console::DirectoryNode & senf::console::Executor::cwd() return * cwd_.back().lock(); } +prefix_ std::string senf::console::Executor::cwdPath() + const +{ + if (skipping()) + return ""; + return "/" + senf::stringJoin( + senf::make_transform_range( + boost::make_iterator_range(boost::next(cwd_.begin()), cwd_.end()), + boost::bind(&DirectoryNode::name, boost::bind(&DirectoryNode::weak_ptr::lock, _1))), + "/" ); +} + prefix_ void senf::console::Executor::execute(std::ostream & output, ParseCommandInfo const & command) { @@ -122,13 +138,13 @@ prefix_ void senf::console::Executor::execute(std::ostream & output, } } catch (InvalidPathException &) { - output << "invalid path" << std::endl; + throw SyntaxErrorException("invalid path"); } catch (InvalidDirectoryException &) { - output << "invalid directory" << std::endl; + throw SyntaxErrorException("invalid directory"); } catch (InvalidCommandException &) { - output << "invalid command" << std::endl; + throw SyntaxErrorException("invalid command"); } catch (IgnoreCommandException &) {} } diff --git a/Console/Executor.hh b/Console/Executor.hh index f771e3b6c..882792a80 100644 --- a/Console/Executor.hh +++ b/Console/Executor.hh @@ -91,7 +91,8 @@ namespace console { /**< Output will be written to \a output. Same as execute(). */ DirectoryNode & cwd() const; ///< Current working directory - bool skipping() const; + std::string cwdPath() const; ///< Return pathname of current directory + bool skipping() const; ///< \c true, if currently skipping a directory group bool autocd() const; ///< Get current autocd status /**< if autocd is enabled, specifying a directory name as diff --git a/Console/Executor.test.cc b/Console/Executor.test.cc index 0e751f173..36f9dcfb2 100644 --- a/Console/Executor.test.cc +++ b/Console/Executor.test.cc @@ -62,7 +62,8 @@ BOOST_AUTO_UNIT_TEST(executor) parser.parse("cd dir1", &setCommand); executor(os, commands.back()); BOOST_CHECK_EQUAL( commands.back().builtin(), senf::console::ParseCommandInfo::BuiltinCD ); - BOOST_CHECK( &executor.cwd() == &senf::console::root()["dir1"] ); + BOOST_CHECK( executor.cwd() == senf::console::root()["dir1"] ); + BOOST_CHECK_EQUAL( executor.cwdPath(), "/dir1" ); BOOST_CHECK_EQUAL( os.str(), "" ); } @@ -78,10 +79,10 @@ BOOST_AUTO_UNIT_TEST(executor) { std::stringstream os; parser.parse("cd dir1", &setCommand); - executor(os, commands.back()); + BOOST_CHECK_THROW( executor(os, commands.back()), senf::console::SyntaxErrorException ); BOOST_CHECK_EQUAL( commands.back().builtin(), senf::console::ParseCommandInfo::BuiltinCD ); BOOST_CHECK( &executor.cwd() == &senf::console::root()["dir2"] ); - BOOST_CHECK_EQUAL( os.str(), "invalid directory\n" ); + BOOST_CHECK_EQUAL( os.str(), "" ); } { @@ -112,9 +113,9 @@ BOOST_AUTO_UNIT_TEST(executor) { std::stringstream os; parser.parse("ls dir3", &setCommand); - executor(os, commands.back()); + BOOST_CHECK_THROW( executor(os, commands.back()), senf::console::SyntaxErrorException ); BOOST_CHECK_EQUAL( commands.back().builtin(), senf::console::ParseCommandInfo::BuiltinLS ); - BOOST_CHECK_EQUAL( os.str(), "invalid directory\n" ); + BOOST_CHECK_EQUAL( os.str(), "" ); } { diff --git a/Console/Node.cc b/Console/Node.cc index 3e1666705..42086bb05 100644 --- a/Console/Node.cc +++ b/Console/Node.cc @@ -88,6 +88,16 @@ prefix_ bool senf::console::GenericNode::isChildOf(DirectoryNode & parent) return node; } +/////////////////////////////////////////////////////////////////////////// +// senf::console::LinkNode + +prefix_ void senf::console::LinkNode::v_help(std::ostream & os) + const +{ + os << "link to "; + follow().help(os); +} + /////////////////////////////////////////////////////////////////////////// //senf::console::DirectoryNode @@ -127,7 +137,7 @@ prefix_ void senf::console::DirectoryNode::add(GenericNode::ptr node) } prefix_ senf::console::GenericNode & -senf::console::DirectoryNode::get(std::string const & name) +senf::console::DirectoryNode::getLink(std::string const & name) const { ChildMap::const_iterator i (children_.find(name)); diff --git a/Console/Node.cci b/Console/Node.cci index 108902a2c..242881fd8 100644 --- a/Console/Node.cci +++ b/Console/Node.cci @@ -96,6 +96,45 @@ prefix_ bool senf::console::GenericNode::operator!=(GenericNode & other) return this != & other; } +prefix_ bool senf::console::GenericNode::isDirectory() + const +{ + return dynamic_cast<DirectoryNode const *>(this); +} + +prefix_ bool senf::console::GenericNode::isLink() + const +{ + return dynamic_cast<LinkNode const *>(this); +} + +prefix_ bool senf::console::GenericNode::isCommand() + const +{ + return dynamic_cast<CommandNode const *>(this); +} + +/////////////////////////////////////////////////////////////////////////// +// senf::console::LinkNode + +prefix_ senf::console::LinkNode::ptr senf::console::LinkNode::create(GenericNode & node) +{ + GenericNode::ptr p (node.thisptr()); + while ( p->isLink() ) + p = dynamic_cast<LinkNode&>(*p).follow().thisptr(); + return ptr(new LinkNode(*p)); +} + +prefix_ senf::console::GenericNode & senf::console::LinkNode::follow() + const +{ + return *node_; +} + +prefix_ senf::console::LinkNode::LinkNode(GenericNode & node) + : node_ (node.thisptr()) +{} + /////////////////////////////////////////////////////////////////////////// // senf::console::DirectoryNode @@ -111,6 +150,16 @@ prefix_ bool senf::console::DirectoryNode::hasChild(std::string const & name) return i != children_.end(); } +prefix_ senf::console::GenericNode & +senf::console::DirectoryNode::get(std::string const & name) + const +{ + GenericNode & node (getLink(name)); + return node.isLink() + ? dynamic_cast<LinkNode&>(node).follow() + : node; +} + prefix_ senf::console::DirectoryNode & senf::console::DirectoryNode::getDirectory(std::string const & name) const @@ -165,6 +214,11 @@ senf::console::DirectoryNode::completions(std::string const & s) children_.lower_bound(s + "\xff")); } +prefix_ void senf::console::DirectoryNode::link(std::string const & name, GenericNode & target) +{ + add(name, LinkNode::create(target)); +} + prefix_ senf::console::DirectoryNode::DirectoryNode() {} diff --git a/Console/Node.hh b/Console/Node.hh index ca57da107..939113b42 100644 --- a/Console/Node.hh +++ b/Console/Node.hh @@ -215,6 +215,7 @@ namespace senf { namespace console { + class LinkNode; class DirectoryNode; class CommandNode; @@ -288,6 +289,10 @@ namespace console { bool operator!= (GenericNode & other) const; /// \c true, if this and \a other are different nodes + bool isDirectory() const; ///< \c true, if this is a drectory node + bool isLink() const; ///< \c true, if this is a link node + bool isCommand() const; ///< \c true, if this is a command node + protected: GenericNode(); @@ -310,6 +315,47 @@ namespace console { friend class DirectoryNode; }; + /** \brief Config/console tree link node + + A LinkNode references another node and provides an additional alias name for that node. A + LinkNode works like a mixture of UNIX symlinks and hardlinks: It is an explicit link like a + UNIX symlink but references another node directly (not via it's path) like a UNIX + hardlink. Therefore, a LinkNode works across chroot(). + */ + class LinkNode + : public GenericNode + { + public: + /////////////////////////////////////////////////////////////////////////// + // Types + + typedef boost::shared_ptr<LinkNode> ptr; + typedef boost::shared_ptr<LinkNode const> cptr; + typedef boost::weak_ptr<LinkNode> weak_ptr; + + /////////////////////////////////////////////////////////////////////////// + ///\name Structors and default members + ///@{ + + static ptr create(GenericNode & node); ///< Create new link node. + /**< You should normally use DirectoryNode::link() to + create a link node. */ + + ///@} + /////////////////////////////////////////////////////////////////////////// + + GenericNode & follow() const; ///< Access the referenced node + + protected: + + private: + explicit LinkNode(GenericNode & node); + + virtual void v_help(std::ostream &) const; + + GenericNode::ptr node_; + }; + class SimpleCommandNode; /** \brief Internal: Node creation helper traits @@ -445,6 +491,10 @@ namespace console { ///< Get child node /**< \throws UnknownNodeNameException if a child \a name does not exist */ + GenericNode & getLink(std::string const & name) const; + ///< Get child node without dereferencing links + /**< \throws UnknownNodeNameException if a child \a name + does not exist */ DirectoryNode & getDirectory(std::string const & name) const; ///< Get directory child node @@ -488,28 +538,12 @@ namespace console { ///< Return iterator range of completions for \a s /**< The returned range is sorted by child name. */ + void link(std::string const & name, GenericNode & target); + ///\} /////////////////////////////////////////////////////////////////////////// - template <class ForwardRange> - GenericNode & traverse(ForwardRange const & range, bool autocomplete=false, - DirectoryNode & root = root()); - ///< Traverse node path starting at this node - /**< The <tt>ForwardRange::value_type</tt> must be - (convertible to) std::string. Each range element - constitutes a step along the node traversal. - - If the range starts with an empty element, the - traversal is started at the root() node, otherwise it - is started at \a this node. The traversal supports '.', - '..' and ignores further empty elements. - - If \a autocomplete is set to \c true, invalid path - components which can be uniquely completed will be - completed automatically while traversing the tree. */ - - DirectoryNode & doc(std::string const & doc); - ///< Set node documentation + DirectoryNode & doc(std::string const & doc); ///< Set node documentation ptr thisptr(); cptr thisptr() const; @@ -668,7 +702,7 @@ BOOST_TYPEOF_REGISTER_TYPE(senf::console::SimpleCommandNode) ///////////////////////////////hh.e//////////////////////////////////////// #include "Node.cci" -#include "Node.ct" +//#include "Node.ct" #include "Node.cti" #endif diff --git a/Console/Node.test.cc b/Console/Node.test.cc index 0e0668d88..cab82e35e 100644 --- a/Console/Node.test.cc +++ b/Console/Node.test.cc @@ -37,7 +37,7 @@ #define prefix_ ///////////////////////////////cc.p//////////////////////////////////////// -BOOST_AUTO_UNIT_TEST(gnericNode) +BOOST_AUTO_UNIT_TEST(genericNode) { senf::console::GenericNode & node ( senf::console::root().mkdir("dir1").mkdir("dir2").doc("help info")); @@ -107,19 +107,6 @@ BOOST_AUTO_UNIT_TEST(directoryNode) completions, completions+sizeof(completions)/sizeof(completions[0]) ); - char const * const path[] = { "..", "dir2", "dir3" }; - BOOST_CHECK( &senf::console::root()["dir1"].traverse( boost::make_iterator_range( - path, - path+sizeof(path)/sizeof(path[0])) ) - == &senf::console::root()["dir2"]["dir3"] ); - - char const * const incompletePath[] = { "d" }; - BOOST_CHECK( &senf::console::root()["dir2"].traverse( boost::make_iterator_range( - incompletePath, - incompletePath+sizeof(incompletePath)/sizeof(incompletePath[0])), - true ) - == &senf::console::root()["dir2"]["dir3"] ); - p->doc("test doc"); std::stringstream ss; p->help(ss); @@ -132,6 +119,17 @@ BOOST_AUTO_UNIT_TEST(directoryNode) BOOST_CHECK_EQUAL( senf::console::root().children().size(), 0u ); } +BOOST_AUTO_UNIT_TEST(linkNode) +{ + senf::console::root().mkdir("dir1"); + senf::console::root().link("link1", senf::console::root()["dir1"]); + + BOOST_CHECK( senf::console::root()["dir1"] == senf::console::root()["link1"] ); + + senf::console::root().remove("dir1"); + senf::console::root().remove("link1"); +} + namespace { struct Functor { void operator()(std::ostream & os, senf::console::ParseCommandInfo const &) { diff --git a/Console/ScopedDirectory.cci b/Console/ScopedDirectory.cci index c94e1c0e5..6f868b70c 100644 --- a/Console/ScopedDirectory.cci +++ b/Console/ScopedDirectory.cci @@ -98,6 +98,12 @@ senf::console::ScopedDirectoryBase::mkdir(std::string const & name) return node().mkdir(name); } +prefix_ void senf::console::ScopedDirectoryBase::link(std::string const & name, + GenericNode & target) +{ + return node().link(name, target); +} + prefix_ senf::console::DirectoryNode::ChildrenRange senf::console::ScopedDirectoryBase::children() const diff --git a/Console/ScopedDirectory.hh b/Console/ScopedDirectory.hh index 89da74ba2..04a33ec33 100644 --- a/Console/ScopedDirectory.hh +++ b/Console/ScopedDirectory.hh @@ -83,6 +83,7 @@ namespace console { CommandNode & operator()(std::string const & name) const; GenericNode & get(std::string const & name) const; DirectoryNode & mkdir(std::string const & name); + void link(std::string const & name, GenericNode & node); DirectoryNode::ChildrenRange children() const; DirectoryNode & doc(std::string const & doc); diff --git a/Console/Server.cci b/Console/Server.cci index b68443977..78387d614 100644 --- a/Console/Server.cci +++ b/Console/Server.cci @@ -139,7 +139,7 @@ prefix_ std::string const & senf::console::Client::name() prefix_ std::string senf::console::Client::promptString() const { - return name_ + ":" + executor_.cwd().path() + "$ "; + return name_ + ":" + executor_.cwdPath() + "$ "; } prefix_ senf::console::Client & senf::console::Client::get(std::ostream & os) diff --git a/Utils/Backtrace.hh b/Utils/Backtrace.hh index 4861a3b6c..ccc1d9768 100644 --- a/Utils/Backtrace.hh +++ b/Utils/Backtrace.hh @@ -33,8 +33,27 @@ ///////////////////////////////hh.p//////////////////////////////////////// namespace senf { + /** \defgroup backtraces Backtrace formatting and parsing + These functions help format and barse backtrace information as returned by the glibc + ::backtrace function. + */ + + /** \brief Formnat a given backtrace + + This functions will write \a backtrace formatted to \a os. This includes demangling symbol + names and interpreting some additional kernel symbols. + + \ingroup backtraces + */ void formatBacktrace(std::ostream & os, void ** backtrace, unsigned numEntries); + + /** \brief Write a backtrace to \a os + + backtrace() will write a backtrace of the current call stack to \a os. + + \ingroup backtraces + */ void backtrace(std::ostream & os, unsigned numEntries); } diff --git a/Utils/Mainpage.dox b/Utils/Mainpage.dox index cc20df80a..3c0c53f78 100644 --- a/Utils/Mainpage.dox +++ b/Utils/Mainpage.dox @@ -99,13 +99,27 @@ namespace senf { specification</td></tr> <tr><td>\ref utils_tags</td><td>Miscellaneous type tags</td></tr> + + <tr><td>stringJoin()</td><td>Utility to join a string range into + a single string (with separator)</td><?tr> + + <tr><td>make_transform_range()</td><td>\c boost::make_transform_iterator() with support for + ranges</td></tr> + + <tr><td>\ref backtraces</td><td>Utilities to parse and format backtrace information as provided + by the GNU libc</td></tr> </table> - \section compatibility Compatibility + + \section testing Correctness and testing <table class="listing"> <tr><td>\ref auto_unit_test.hh</td><td>Boost auto unit test compatibility across Boost versions 1.33 and 1.34</td></tr> + + <tr><td>\ref SENF_ASSERT()</td><td>SENF specific assertion macro</td></tr> + + <tr><td>\ref unittest</td><td>Additional unit test extension for Boost.Test</td></tr> </table> */ diff --git a/Console/Node.ct b/Utils/Range.cti similarity index 57% rename from Console/Node.ct rename to Utils/Range.cti index c9516c034..0444e4251 100644 --- a/Console/Node.ct +++ b/Utils/Range.cti @@ -21,34 +21,27 @@ // 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. /** \file - \brief Node non-inline template implementation */ + \brief Range inline template implementation */ -#include "Node.ih" +//#include "Range.ih" // Custom includes -#include <boost/range.hpp> -#define prefix_ -///////////////////////////////ct.p//////////////////////////////////////// +#define prefix_ inline +///////////////////////////////cti.p/////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////// -// senf::console::DirectoryNode - -template <class ForwardRange> -prefix_ senf::console::GenericNode & -senf::console::DirectoryNode::traverse(ForwardRange const & range, bool autocomplete, - DirectoryNode & root) +template <class Range, class Fn> +prefix_ boost::iterator_range< + boost::transform_iterator< Fn, + typename boost::range_const_iterator<Range>::type > > +senf::make_transform_range(Range const & range, Fn const & fn) { - typedef typename boost::range_const_iterator<ForwardRange>::type const_iterator; - detail::NodeTraverser traverser (root, *this, autocomplete); - const_iterator i (boost::begin(range)); - const_iterator const i_end (boost::end(range)); - for (; i != i_end; ++i) - traverser( *i ); - return traverser.node(); + return boost::make_iterator_range( + boost::make_transform_iterator(boost::begin(range), fn), + boost::make_transform_iterator(boost::end(range), fn) ); } -///////////////////////////////ct.e//////////////////////////////////////// +///////////////////////////////cti.e/////////////////////////////////////// #undef prefix_ diff --git a/Utils/Range.hh b/Utils/Range.hh new file mode 100644 index 000000000..db6d63eb8 --- /dev/null +++ b/Utils/Range.hh @@ -0,0 +1,66 @@ +// $Id$ +// +// Copyright (C) 2008 +// Fraunhofer Institute for Open Communication Systems (FOKUS) +// Competence Center NETwork research (NET), St. Augustin, GERMANY +// Stefan Bund <g0dil@berlios.de> +// +// This program 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 2 of the License, or +// (at your option) any later version. +// +// 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. + +/** \file + \brief Range public header */ + +#ifndef HH_Range_ +#define HH_Range_ 1 + +// Custom includes +#include <boost/range/iterator_range.hpp> +#include <boost/iterator/transform_iterator.hpp> + +//#include "Range.mpp" +///////////////////////////////hh.p//////////////////////////////////////// + +namespace senf { + + /** \brief Make a \c boost::iterator_range from \c boost::trasform_iterator + + This helper is like \c boost::make_transform_iterator, however for ranges instead of + iterators. + */ + template <class Range, class Fn> + boost::iterator_range< + boost::transform_iterator< Fn, + typename boost::range_const_iterator<Range>::type > > + make_transform_range(Range const & range, Fn const & fn); + +} + +///////////////////////////////hh.e//////////////////////////////////////// +//#include "Range.cci" +//#include "Range.ct" +#include "Range.cti" +#endif + + +// Local Variables: +// mode: c++ +// fill-column: 100 +// comment-column: 40 +// c-file-style: "senf" +// indent-tabs-mode: nil +// ispell-local-dictionary: "american" +// compile-command: "scons -u test" +// End: diff --git a/Utils/String.hh b/Utils/String.hh index 0b8028f42..1bdf93ebc 100644 --- a/Utils/String.hh +++ b/Utils/String.hh @@ -34,6 +34,11 @@ namespace senf { + /** \brief Join string range with separator into single string + + This utility will build string by joining all elements of \a range into a single string + using \a sep as separator. The \a range may contain values of any streamable type. + */ template <class ForwardReadableRange> std::string stringJoin(ForwardReadableRange const & range, std::string sep); diff --git a/Utils/auto_unit_test.hh b/Utils/auto_unit_test.hh index a12669225..b2e60ae5a 100644 --- a/Utils/auto_unit_test.hh +++ b/Utils/auto_unit_test.hh @@ -50,8 +50,44 @@ #include <boost/test/auto_unit_test.hpp> +/** \defgroup unittest Boost.Test extensions + + This module defines some additional extensions to Boost.Test + */ + +/** \brief Check for compile failure + + COMPILE_RAIL() is used to check, that a certain piece of code will produce a compile time + failure. + + \code + #ifdef COMPILE_CHECK + + COMPILE_FAIL(foo) + { + // fails to compile .... + int x = "foo"; + } + + COMPILE_FAIL(bar) + { ... } + + #endif + \endcode + + This check is performed by the extended unit-test builder in \c senfscons. + + \ingroup unittest + */ #define COMPILE_FAIL(n) void n() +/** \brief Show exception information + + \ref SENF_CHECK_NO_THROW() is an extension to \c BOOST_CHECK_NO_THROW() which will write out the + unabridged exception information when an exception is thrown in addition to signaling an error. + + \ingroup unittest + */ #define SENF_CHECK_NO_THROW(expr) \ BOOST_CHECK_NO_THROW( \ try { (void) expr ; } \ diff --git a/Utils/preprocessor.hh b/Utils/preprocessor.hh index 55a3fa824..0567d781e 100644 --- a/Utils/preprocessor.hh +++ b/Utils/preprocessor.hh @@ -34,7 +34,7 @@ //#include "preprocessor.mpp" ///////////////////////////////hh.p//////////////////////////////////////// -/** \defgroup senfpp Preprocessor meta programming macros +/** \defgroup senfpp Preprocessor meta programming preprocessor.hh provides some additional helper macros based on the Boost.Preprocessor library. */ -- GitLab