From 5575a7679d786a95cc7d2d882016aa06b8e6d78b Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Thu, 23 Aug 2007 17:52:33 +0200 Subject: [PATCH] wrapper for cmdline parsing, finished testsuite-runner, solved shutdown-memoryleak --- SConstruct | 9 +- src/common/appconfig.cpp | 19 ++- src/common/appconfig.hpp | 52 ++++---- src/common/cmdline.cpp | 85 +++++++++++++ src/common/cmdline.hpp | 70 +++++++++++ src/common/test/run.hpp | 3 +- src/common/test/suite.cpp | 95 ++++++++------ src/common/test/suite.hpp | 8 +- src/common/test/testoption.cpp | 119 +++++++++--------- src/common/test/testoption.hpp | 39 +++--- src/common/util.hpp | 46 ++++++- src/nobugcfg.h | 3 +- tests/50components.tests | 30 +++++ .../common/test/cmdlinewrappertest.cpp | 96 ++++++++++++++ .../components/common/test/testoptiontest.cpp | 15 ++- tests/components/mainsuite.cpp | 11 +- wiki/index.html | 4 +- 17 files changed, 534 insertions(+), 170 deletions(-) create mode 100644 src/common/cmdline.cpp create mode 100644 src/common/cmdline.hpp create mode 100644 tests/components/common/test/cmdlinewrappertest.cpp diff --git a/SConstruct b/SConstruct index 8c7a7781c..bfb239f2e 100644 --- a/SConstruct +++ b/SConstruct @@ -61,7 +61,7 @@ def setupBasicEnvironment(): , SRCDIR=SRCDIR , BINDIR=BINDIR , CPPPATH=["#"+SRCDIR] # used to find includes, "#" means always absolute to build-root - , CPPDEFINES=['-DCINELERRA_VERSION=\\"%s\\"' % VERSION ] # note: make it a list to append further defines + , CPPDEFINES=['-DCINELERRA_VERSION='+VERSION ] # note: it's a list to append further defines , CCFLAGS='-Wall' ) @@ -184,7 +184,7 @@ def configurePlatform(env): if not conf.CheckCXXHeader('tr1/memory'): print 'We rely on the std::tr1 proposed standard extension for shared_ptr.' - Exit(1) + Exit(1) if not conf.CheckCXXHeader('boost/config.hpp'): print 'We need the C++ boost-lib.' @@ -194,7 +194,10 @@ def configurePlatform(env): print 'We need boost::shared_ptr (shared_ptr.hpp).' Exit(1) if not conf.CheckLibWithHeader('boost_program_options-mt','boost/program_options.hpp','C++'): - print 'We need boost::program_options (also the corresponding binary lib).' + print 'We need boost::program_options (including binary lib for linking).' + Exit(1) + if not conf.CheckLibWithHeader('boost_regex-mt','boost/regex.hpp','C++'): + print 'We need the boost regular expression lib (incl. binary lib for linking).' Exit(1) diff --git a/src/common/appconfig.cpp b/src/common/appconfig.cpp index 769cde604..1d1cec4e1 100644 --- a/src/common/appconfig.cpp +++ b/src/common/appconfig.cpp @@ -30,6 +30,7 @@ #undef NOBUG_INIT_DEFS_ + using util::isnil; namespace cinelerra @@ -41,10 +42,10 @@ namespace cinelerra * Appconfig::instance() probably already has been called * by another compilation unit. This is ugliy, but preferable * to beeing dependant on inclusion order of headers. */ - Appconfig* Appconfig::theApp_ ; +// scoped_ptr Appconfig::theApp_; #ifndef CINELERRA_VERSION -#define CINELERRA_VERSION "3++devel" +#define CINELERRA_VERSION 3++devel #endif @@ -61,32 +62,30 @@ namespace cinelerra ////////// INFO(config, "Basic application configuration triggered."); - (*configParam_)["version"] = CINELERRA_VERSION; + (*configParam_)["version"] = STRINGIFY (CINELERRA_VERSION); } - - - + + + /** access the configuation value for a given key. * @return empty string for unknown keys, else the corresponding configuration value */ const string & Appconfig::get (const string & key) throw() { - try { const string& val = (*instance().configParam_)[key]; WARN_IF( isnil(val), config, "undefined config parameter \"%s\" requested.", key.c_str()); return val; - } catch (...) { ERROR(config, "error while accessing configuration parameter \"%s\".", key.c_str()); - } - } + throw cinelerra::error::Fatal (); + } } diff --git a/src/common/appconfig.hpp b/src/common/appconfig.hpp index 9cf20f9f9..488ac2ba8 100644 --- a/src/common/appconfig.hpp +++ b/src/common/appconfig.hpp @@ -38,48 +38,50 @@ #include #include -#include +#include #include "nobugcfg.h" -using std::string; -using std::auto_ptr; - - - namespace cinelerra { + using std::string; + using boost::scoped_ptr; /** * Singleton to hold inevitable global flags and constants * and for performing early (static) global initialization tasks. + * Appconfig services are available already from static + * initialsation code. + * @warning don't use Appconfig in destuctors. */ class Appconfig { private: - - /** holds the single instance and triggers initialization */ - static Appconfig* theApp_; - - /** perform initialization on first access. - * A call is placed in static initialization code - * included via cinelerra.h (see below), - * thus it will happen rather early. - */ - Appconfig () ; - + * @see #instance() for Lifecycle */ + Appconfig (); + + Appconfig (const Appconfig&); ///< copy prohibited, not implemented + ~Appconfig () throw() {}; ///< deletion prohibited + friend void boost::checked_delete(Appconfig*); + public: + /** get the (single) Appconfig instance. + * Implemented as Meyers singleton. + * @warning don't use it in destruction code! + */ static Appconfig& instance() { - if (!theApp_) theApp_ = new Appconfig (); + static scoped_ptr theApp_ (0); + if (!theApp_) theApp_.reset (new Appconfig ()); return *theApp_; } - + + /** access the configuation value for a given key. * @return empty string for unknown keys, config value else * @todo do we need such a facility? @@ -89,10 +91,11 @@ namespace cinelerra private: typedef std::map Configmap; - typedef auto_ptr PConfig; + typedef std::auto_ptr PConfig; /** @TODO the following is just placeholder code! - * Appconfig could do such things if necessary. + * Appconfig could do such things if necessary, + * or provide similar "allways available" services. */ PConfig configParam_; @@ -100,12 +103,5 @@ namespace cinelerra - - namespace - { - /** "magic code" to cause early static initialization */ - Appconfig& init (Appconfig::instance ()); - } - } // namespace cinelerra #endif diff --git a/src/common/cmdline.cpp b/src/common/cmdline.cpp new file mode 100644 index 000000000..4ab1b5131 --- /dev/null +++ b/src/common/cmdline.cpp @@ -0,0 +1,85 @@ +/* + Cmdline - abstraction of the usual commandline, a sequence of strings + + Copyright (C) CinelerraCV + 2007, Christian Thaeter + + 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., 675 Mass Ave, Cambridge, MA 02139, USA. + +* *****************************************************/ + + + +#include "common/cmdline.hpp" +#include "common/util.hpp" +#include "nobugcfg.h" + +#include +#include + +using boost::algorithm::split; +using boost::algorithm::join; +using boost::algorithm::is_any_of; +using boost::algorithm::token_compress_on; + + + +#include + +namespace util + { + + /** create as a tokenized copy of the current commandline. + * Note that argv[0] is allways ignored. */ + Cmdline::Cmdline (int argc, char* argv[]) + : vector (noneg(argc-1)) + { + for (int i=1; ipush_back(ss); + it = match[0].second; + } + + } + + + /** conversion to string by joining the tokens */ + Cmdline::operator string () const + { + return join(*this," "); + } + + + +} // namespace cinelerra diff --git a/src/common/cmdline.hpp b/src/common/cmdline.hpp new file mode 100644 index 000000000..f05605b01 --- /dev/null +++ b/src/common/cmdline.hpp @@ -0,0 +1,70 @@ +/* + CMDLINE.hpp - abstraction of the usual commandline, a sequence of strings + + Copyright (C) CinelerraCV + 2007, Christian Thaeter + + 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., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + + +#ifndef UTIL_CMDLINE_H +#define UTIL_CMDLINE_H + +#include +#include +#include + + + +namespace util + { + using std::string; + using std::vector; + using std::ostream; + + typedef vector VectS; + + + /** + * Abstraction of the usual "int argc, int** argv"-Commandline, + * to be able to treat it as a vector of strings. Inherits from + * vector, but provides convienient conversions to + * string (joining delimited by space)... + */ + class Cmdline : public VectS + { + public: + Cmdline (int argc, char* argv[]); + explicit Cmdline (const string cmdline); + + operator string () const; + VectS& operator= (const VectS& source) { return VectS::operator= (source); } + + // inherited ctors + template + Cmdline (In first, In last) : VectS (first,last) {} + Cmdline () : VectS () {} + + }; + + /** for outputting Cmdline objects */ + inline ostream& operator<< (ostream& os, const Cmdline& cmdL) { return os << (string (cmdL)); } + + + +} // namespace util +#endif diff --git a/src/common/test/run.hpp b/src/common/test/run.hpp index 79fae255f..668f29645 100644 --- a/src/common/test/run.hpp +++ b/src/common/test/run.hpp @@ -29,6 +29,7 @@ #include #include "common/test/suite.hpp" +#include "common/util.hpp" namespace test @@ -94,7 +95,5 @@ using ::test::Launch; /** Register _TEST_CLASS_ to be invoked in some test suites (groups) _GROUPS_ */ \ Launch<_TEST_CLASS_> run_##_TEST_CLASS_##_(STRINGIFY(_TEST_CLASS_), _GROUPS_); -#define STRINGIFY(TOKEN) __STRINFY(TOKEN) -#define __STRINFY(TOKEN) #TOKEN #endif diff --git a/src/common/test/suite.cpp b/src/common/test/suite.cpp index ee3596c29..df592dec0 100644 --- a/src/common/test/suite.cpp +++ b/src/common/test/suite.cpp @@ -27,7 +27,9 @@ #include #include #include +#include +#include "common/cmdline.hpp" #include "common/test/suite.hpp" #include "common/test/run.hpp" #include "common/error.hpp" @@ -42,8 +44,10 @@ namespace test using std::vector; using std::auto_ptr; using std::tr1::shared_ptr; + using boost::algorithm::trim; using util::isnil; + using util::contains; typedef map TestMap; typedef shared_ptr PTestMap; @@ -129,57 +133,78 @@ namespace test //throw "empty testsuite"; /////////// TODO Errorhandling! } +#define VALID(test,testID) \ + ASSERT ((test), "NULL testcase laucher for test '%s' found in testsuite '%s'", groupID_.c_str(),testID.c_str()); + /** run all testcases contained in this Suite. - * The first argument in the commandline, if present, will select - * one single testcase with a matching ID. + * The first argument in the commandline, if present, + * will select one single testcase with a matching ID. + * In case of invoking a single testcase, the given cmdline + * will be forwarded to the testcase, after removind the + * testcaseID from cmdline[0]. Otherwise, every testcase + * in this suite is invoked with a empty cmdline vector. + * @param cmdline ref to the vector of commandline tokens */ void - Suite::run (int argc, char* argv[]) + Suite::run (Arg cmdline) { - PTestMap tests = testcases.getGroup(groupID_); if (!tests) - throw cinelerra::error::Invalid (); + throw cinelerra::error::Invalid (); ///////// TODO: pass error description - if (argc >= 2) + if (0 < cmdline.size()) { - if (Launcher* test = (*tests)[argv[1]]) + string& testID (cmdline[0]); + trim(testID); + if ( contains (*tests, testID)) { - // first cmdline argument denotes a valid - // testcase registered in this group: - // go ahead and invoke just this test. - if (argc > 2) - { // pass additional cmdline as vector - FIXME("use Optparser"); - vector arglist(argc-2); - for ( int i=2; irun(arglist); - } - else - FIXME("use Optparser"); - vector nix; - (*test)()->run(nix); // without additional argumens - + // first cmdline argument denotes a valid testcase registered in + // this group: invoke just this test with the remaining cmdline + Launcher* test = (*tests)[testID]; + cmdline.erase (cmdline.begin()); + VALID (test,testID); + (*test)()->run(cmdline); return; - } - } + } } // no test-ID was specified. // instantiiate all tests cases and execute them. for ( TestMap::iterator i=tests->begin(); i!=tests->end(); ++i ) - if (i->second) - { - std::cout << " ----------"<< i->first<< "----------\n"; - Launcher& test = *(i->second); - FIXME("use Optparser"); - vector nix; - test()->run(nix); // without cmdline arguments - } + { + std::cout << "\n ----------"<< i->first<< "----------\n"; + Launcher* test = (i->second); + VALID (test, i->first); + (*test)()->run(cmdline); // actually no cmdline arguments + } + } + + + /** print to stdout an ennumeration of all testcases in this suite, + * in a format suitable for use with Cehteh's ./test.sh + */ + void + Suite::describe () + { + util::Cmdline noCmdline(""); + PTestMap tests = testcases.getGroup(groupID_); + ASSERT (tests); + std::cout << "TESTING \"Component Test Suite: " << groupID_ << "\" ./test-components\n\n"; + + for ( TestMap::iterator i=tests->begin(); i!=tests->end(); ++i ) + { + string key (i->first); + std::cout << "\n\n"; + std::cout << "TEST \""<second); + VALID (test, i->first); + (*test)()->run(noCmdline); // run it to insert test generated output + std::cout << "END\n"; + } + + + } diff --git a/src/common/test/suite.hpp b/src/common/test/suite.hpp index addd13e07..acf9d270e 100644 --- a/src/common/test/suite.hpp +++ b/src/common/test/suite.hpp @@ -24,6 +24,7 @@ #ifndef TESTHELPER_SUITE_H #define TESTHELPER_SUITE_H +#include #include @@ -35,11 +36,13 @@ namespace test // Forward decls needed for run.hpp class Test; class Launcher; + + typedef std::vector & Arg; /** * Enables running a collection of tests. - * In internal registration service #enroll() is provided + * An internal registration service #enroll() is provided * for the individual Test - inscances to be recognized as * testcases. The groupID passed to the constructor selects * all testcases declared as belonging to this Group. @@ -50,7 +53,8 @@ namespace test public: Suite (string groupID); - void run (int argc, char* argv[]); + void run (Arg cmdline); + void describe (); static void enroll (Launcher *test, string testID, string groups); static const string ALLGROUP; diff --git a/src/common/test/testoption.cpp b/src/common/test/testoption.cpp index 2e1e4686e..4e78dee19 100644 --- a/src/common/test/testoption.cpp +++ b/src/common/test/testoption.cpp @@ -21,28 +21,23 @@ * *****************************************************/ -//#include -//#include -//#include -//#include -//#include - #include "common/test/testoption.hpp" #include "common/test/suite.hpp" -//#include "common/util.hpp" #include "nobugcfg.h" #include "common/error.hpp" + +typedef boost::program_options::options_description Syntax; +typedef boost::program_options::variables_map VarMap; + +namespace op = boost::program_options; + +using util::VectS; + namespace test { -// using std::map; -// using std::auto_ptr; -// using std::tr1::shared_ptr; - -// using util::isnil; - /** set up an options parser to use the current commandline. @@ -52,69 +47,81 @@ namespace test * --group * \endcode */ - TestOption::TestOption (int argc, const char* argv[]) - : vm(), cmdline() + TestOption::TestOption (util::Cmdline& cmdline) + : syntax("Run a collection of test cases. Supported parameters"), + parameters() { - cmdline.reserve (10); - parseOptions (argc,argv); + syntax.add_options() + ("help,h", "produce help message") + ("group,g", op::value()->default_value(Suite::ALLGROUP), + "the group (selection) of testcases to execute") + ("describe", op::bool_switch(), + "ennumerate all testcases in this Suite in a format usable with ./test.sh.") + ("id", op::value(), + "an individual testcase to be called.\nIf not specified, run all.") + ; + + // the testcase-ID is really an positional parameter + op::positional_options_description posopt; + posopt.add("id", -1); + + op::parsed_options parsed = + op::command_line_parser (cmdline) + .options (syntax) + .positional(posopt) + .allow_unregistered() + .run(); + + op::store (parsed, parameters); + op::notify(parameters); + + // remove all recognized options from original cmdline vector + cmdline = op::collect_unrecognized(parsed.options, op::include_positional); + + if (parameters.count("help")) + std::cerr << *this; } - /** variant of the ctor taking a "fake" cmdline */ - TestOption::TestOption (string line) - : vm(), cmdline() - { - cmdline.reserve (10); - const char* fakeArg[3] = {"test", line.c_str() }; -// fakeArg[1] = line.c_str(); - parseOptions (1,fakeArg); - } - - - /** do the comandline parsing for the ctors */ - void TestOption::parseOptions (int argc, const char* argv[]) - { - TODO("define options"); - UNIMPLEMENTED("actual commandline parsing!!"); - } /** @return the Tests-Group as given on cmdline, or Suite::ALLGROUP as default */ - const string & + const string TestOption::getTestgroup () { - FIXME("actual commandline parsing!!"); - return Suite::ALLGROUP; + ASSERT (parameters.count ("group")); + return parameters["group"].as(); } - string booooh = "boooh!"; - /** @return ID of a single test to run, empty if not specified + /** @return ID of a single test to run, empty string if not specified */ - const string & + const string TestOption::getTestID () { - UNIMPLEMENTED("actual commandline parsing"); - return booooh; + if (parameters.count ("id") && + parameters["id"].as().size() > 0) + return parameters["id"].as()[0]; + else + return string (); + } + + /** @return \c true if --describe switch was given */ + const bool + TestOption::getDescribe () + { + return parameters["describe"].as(); } - /** gather all remaining unknown cmd line tokens into a vector. - * @Note: the actual vector remains a member of this object, but isn't const + + /** forward the accummulated help messages from all + * contained option defintions to the outputstream */ - vector& - TestOption::remainingCmdline () + ostream& + operator<< (ostream& os, const TestOption& to) { - UNIMPLEMENTED("get unknown remaining options"); - return cmdline; - } - - - /** */ - TestOption::operator string const () - { - UNIMPLEMENTED("convert the remaining Cmndline to string"); - return 0; + return os << to.syntax; } diff --git a/src/common/test/testoption.hpp b/src/common/test/testoption.hpp index c0aa073cb..2006a7d19 100644 --- a/src/common/test/testoption.hpp +++ b/src/common/test/testoption.hpp @@ -24,47 +24,50 @@ #ifndef TESTHELPER_TESTOPTION_H #define TESTHELPER_TESTOPTION_H +#include "common/cmdline.hpp" + #include -#include +#include #include +#include namespace test { using std::string; - using std::vector; + using std::ostream; - typedef boost::program_options::variables_map VarMap; /** * Support for selecting and configuring testcases * via commandline arguments. A preconfigured wrapper * around boost::program_options, with the ability - * to tolerate unknown options and get an vector - * of everything remaining in the commandline after - * parsing the known options. + * to tolerate unknown options. The commandline + * to be parsed is taken wrapped into a Cmdline + * instance; after parsing this commandline + * vector will contain only the remaining + * unrecognized parts. */ - class TestOption + class TestOption : private boost::noncopyable { public: - TestOption (int argc, const char* argv[]); - explicit TestOption (string cmdline); - const string& getTestgroup (); - const string& getTestID (); - vector& remainingCmdline (); - - operator string const (); + TestOption (util::Cmdline& cmdline); + const string getTestgroup (); + const string getTestID (); + const bool getDescribe (); private: - VarMap vm; - vector cmdline; + boost::program_options::options_description syntax; + boost::program_options::variables_map parameters; - void parseOptions (int argc, const char* argv[]); + friend ostream& operator<< (ostream&, const TestOption&); }; - + /** for outputting the help messages. */ + ostream& operator<< (ostream& os, const TestOption& to); + } // namespace test #endif diff --git a/src/common/util.hpp b/src/common/util.hpp index f0a8bfc2f..622084b84 100644 --- a/src/common/util.hpp +++ b/src/common/util.hpp @@ -1,5 +1,5 @@ /* - TIME.hpp - unified representation of a time point, including conversion functions + UTIL.hpp - collection of small helper functions used "everywhere" Copyright (C) CinelerraCV 2007, Christian Thaeter @@ -34,20 +34,54 @@ namespace util /** a family of util functions providing a "no value whatsoever" test */ - inline bool isnil(const string& val) + inline bool isnil(const string& val) { return 0 == val.length(); } - - inline bool isnil(const string* pval) + + inline bool isnil(const string* pval) { return !pval || 0 == pval->length(); } - - inline bool isnil(const char* pval) + + inline bool isnil(const char* pval) { return !pval || 0 == std::strlen(pval); } + + /** cut a numeric value to be >=0 */ + template + inline NUM noneg (NUM val) + { + return (0 + inline bool contains (MAP& map, typename MAP::key_type& key) + { + return map.find(key) != map.end(); + } + + /** shortcut for operating on all elements of a container. + * Isn't this already defined somewhere? It's so obvious.. + */ + template + inline Oper + for_each (Container& c, Oper& doIt) + { + return std::for_each (c.begin(),c.end(), doIt); + } + + } // namespace util + + /* some common macro definitions */ + +/** this macro wraps its parameter into a cstring literal */ +#define STRINGIFY(TOKEN) __STRNGFY(TOKEN) +#define __STRNGFY(TOKEN) #TOKEN + + #endif /*UTIL_HPP_*/ diff --git a/src/nobugcfg.h b/src/nobugcfg.h index c89a284af..fc2ce4622 100644 --- a/src/nobugcfg.h +++ b/src/nobugcfg.h @@ -75,7 +75,8 @@ NOBUG_CPP_DEFINE_FLAG(config); NOBUG_CPP_DEFINE_FLAG(test); - +#include "common/error.hpp" + #endif /* ===================== (End) C++-Part ============= */ diff --git a/tests/50components.tests b/tests/50components.tests index 99e575ad0..033aaf2d5 100644 --- a/tests/50components.tests +++ b/tests/50components.tests @@ -10,6 +10,36 @@ out: This is how the world ends... return: 0 END +TEST "Cmdline Wrapper" CmdlineWrapper_test < +out: wrapping cmdline: +out: ... +out: --> +out: wrapping cmdline:spam... +out: 0|spam| +out: -->spam +out: wrapping cmdline: +out: spam... +out: 0|spam| +out: -->spam +out: wrapping cmdline:eat more spam... +out: 0|eat| +out: 1|more| +out: 2|spam| +out: -->eat more spam +out: wrapping cmdline: oo _O()O_ ä + €... +out: 0|oo| +out: 1|_O()O_| +out: 2|ä| +out: 3|+| +out: 4|€| +out: -->oo _O()O_ ä + € +out: wrapping cmdline:... +out: --> +out: Standard Cmdlineformat: one two +END + TEST "Parseoption" TestOption_test < + + 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., 675 Mass Ave, Cambridge, MA 02139, USA. + +* *****************************************************/ + + +#include "nobugcfg.h" + +#include "common/test/run.hpp" +#include "common/cmdline.hpp" +#include "common/util.hpp" + +#include +#include + +#include + +using namespace boost::lambda; +using std::cout; + + + +namespace util + { + namespace test + { + + + class CmdlineWrapper_test : public Test + { + virtual void run (Arg arg) + { + testLine(""); + testLine("\n\t "); + testLine("spam"); + testLine("\nspam"); + testLine("eat more spam"); + testLine(" oo _O()O_ ä + €"); + testLine("\0\too\0\to\0o\t\0oo"); + + testStandardCmdlineformat(); + } + + void testLine (const string cmdline) + { + cout << "wrapping cmdline:" << cmdline << "..." << "\n"; + + int i=0; + Cmdline theCmdline (cmdline); + for_each(theCmdline, (cout << var(i)++ << "|" << _1 << "|\n")); + cout << "-->" << theCmdline << "\n"; + + // consistency checks + std::ostringstream output; + output << theCmdline; + ENSURE (output.str() == string(theCmdline)); + + i=0; + string token; + std::istringstream input(theCmdline); + while (input >> token) + ENSURE (token == theCmdline[i++]); + } + + void testStandardCmdlineformat() + { + char* fakeArg[3] = {"CMD", "one ", "two"}; + Cmdline theCmdline(3, fakeArg); + cout << "Standard Cmdlineformat:" << theCmdline << "\n"; + } + }; + + LAUNCHER (CmdlineWrapper_test, "unit common"); + + + } // namespace test + +} // namespace util + diff --git a/tests/components/common/test/testoptiontest.cpp b/tests/components/common/test/testoptiontest.cpp index b34cbe0e8..0738e91e0 100644 --- a/tests/components/common/test/testoptiontest.cpp +++ b/tests/components/common/test/testoptiontest.cpp @@ -26,7 +26,9 @@ #include "common/test/testoption.hpp" #include "common/util.hpp" +using util::Cmdline; using util::isnil; +using std::endl; namespace test { @@ -47,13 +49,14 @@ namespace test void doIt (const string cmdline) { - std::cout << "Testing invocation with cmdline: " << cmdline << "..." << std::endl; + std::cout << "Testing invocation with cmdline: " << cmdline << "..." << endl; - TestOption optparser (cmdline); + Cmdline args(cmdline); + TestOption optparser (args); const string testID = optparser.getTestID(); - std::cout << "--> Testgroup=" << optparser.getTestgroup() << std::endl; - std::cout << "--> Test-ID =" << (isnil(testID)? testID : "--missing--") << std::endl; - std::cout << "--> remaining=" << string(optparser) << std::endl; + std::cout << "--> Testgroup=" << optparser.getTestgroup() << endl; + std::cout << "--> Test-ID =" << (isnil(testID)? "--missing--" : testID ) << endl; + std::cout << "--> remaining=" << args << endl; } void noOptions() { doIt (""); } @@ -63,7 +66,7 @@ namespace test void groupFilter1() { doIt (" SingleTestID --group TestGroupID"); } void groupFilter2() { doIt (" --group TestGroupID SingleTestID "); } void additionalCmd() { doIt (" --group TestGroupID SingleTestID spam eggs"); } - void additionalCmd2() { doIt ("\t\tSingleTestID spam --group TestGroupID \t eggs"); } + void additionalCmd2() { doIt ("\t\tSingleTestID spam --group TestGroupID \t --eggs"); } }; diff --git a/tests/components/mainsuite.cpp b/tests/components/mainsuite.cpp index 3264ad7de..c0de8a8ac 100644 --- a/tests/components/mainsuite.cpp +++ b/tests/components/mainsuite.cpp @@ -22,6 +22,7 @@ #include "common/test/suite.hpp" +#include "common/test/testoption.hpp" /** run all tests or any single test specified in the first * cmd line argument. @@ -29,7 +30,13 @@ */ int main (int argc, char* argv[]) { - test::Suite suite (test::Suite::ALLGROUP); - suite.run(argc,argv); + util::Cmdline args (argc,argv); + test::TestOption optparser (args); + test::Suite suite (optparser.getTestgroup()); + + if (optparser.getDescribe()) + suite.describe(); + else + suite.run (args); return 0; } diff --git a/wiki/index.html b/wiki/index.html index e5f155086..22d424583 100755 --- a/wiki/index.html +++ b/wiki/index.html @@ -747,7 +747,7 @@ config.macros.timeline.handler = function(place,macroName,params,wikifier,paramS } //}}} -
+
for __Building__
 * gcc (4.1), glibc6 (2.3), libstdc++6 (4.1)
 * [[build system|BuildSystem]] dependencies: SCons (0.96.90), Python (2.3)
@@ -758,6 +758,8 @@ config.macros.timeline.handler = function(place,macroName,params,wikifier,paramS
 ** libboost-dev (=1.34.1-2)
 ** libboost-program-options-dev (=1.34.1-2)
 ** libboost-program-options1.34.1 (=1.34.1-2) ''NOTE: binary dependency''
+** libboost-regex-dev (=1.34.1-2)
+** libboost-regex1.34.1 (=1.34.1-2) ''binary..''
 //usually, newer versions are OK//
 
 for __Running__