wrapper for cmdline parsing, finished testsuite-runner, solved shutdown-memoryleak

This commit is contained in:
Fischlurch 2007-08-23 17:52:33 +02:00
parent 91d04f7019
commit 5575a7679d
17 changed files with 534 additions and 170 deletions

View file

@ -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)

View file

@ -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> 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 ();
} }

View file

@ -38,48 +38,50 @@
#include <map>
#include <string>
#include <memory>
#include <boost/scoped_ptr.hpp>
#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>(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<Appconfig> 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<string,string> Configmap;
typedef auto_ptr<Configmap> PConfig;
typedef std::auto_ptr<Configmap> PConfig;
/** @TODO <b>the following is just placeholder code!</b>
* Appconfig <i>could</i> do such things if necessary.
* Appconfig <i>could</i> 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

85
src/common/cmdline.cpp Normal file
View file

@ -0,0 +1,85 @@
/*
Cmdline - abstraction of the usual commandline, a sequence of strings
Copyright (C) CinelerraCV
2007, Christian Thaeter <ct@pipapo.org>
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 <boost/regex.hpp>
#include <boost/algorithm/string.hpp>
using boost::algorithm::split;
using boost::algorithm::join;
using boost::algorithm::is_any_of;
using boost::algorithm::token_compress_on;
#include <iostream>
namespace util
{
/** create as a tokenized <i>copy</i> of the current commandline.
* Note that argv[0] is allways ignored. */
Cmdline::Cmdline (int argc, char* argv[])
: vector<string> (noneg(argc-1))
{
for (int i=1; i<argc; ++i)
{
ASSERT (argv[i]);
(*this)[i-1] = argv[i];
}
}
/** create by tokenizing a string
* (e.g. "fake" cmdline, separated by whitespace)
*/
Cmdline::Cmdline (const string cmdline)
{
boost::regex tokendef("[^ \r\n\t]+");
boost::smatch match;
string::const_iterator it = cmdline.begin();
string::const_iterator end = cmdline.end();
while (boost::regex_search(it, end, match, tokendef))
{
string ss(match[0]);
this->push_back(ss);
it = match[0].second;
}
}
/** conversion to string by joining the tokens */
Cmdline::operator string () const
{
return join(*this," ");
}
} // namespace cinelerra

70
src/common/cmdline.hpp Normal file
View file

@ -0,0 +1,70 @@
/*
CMDLINE.hpp - abstraction of the usual commandline, a sequence of strings
Copyright (C) CinelerraCV
2007, Christian Thaeter <ct@pipapo.org>
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 <vector>
#include <string>
#include <iostream>
namespace util
{
using std::string;
using std::vector;
using std::ostream;
typedef vector<string> VectS;
/**
* Abstraction of the usual "int argc, int** argv"-Commandline,
* to be able to treat it as a vector of strings. Inherits from
* vector<std::string>, 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 <class In>
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

View file

@ -29,6 +29,7 @@
#include <string>
#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

View file

@ -27,7 +27,9 @@
#include <tr1/memory>
#include <iostream>
#include <sstream>
#include <boost/algorithm/string.hpp>
#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<string, Launcher*> TestMap;
typedef shared_ptr<TestMap> 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<string> arglist(argc-2);
for ( int i=2; i<argc; ++i )
arglist.push_back(string(argv[i]));
// run single Testcase with provided arguments
(*test)()->run(arglist);
}
else
FIXME("use Optparser");
vector<string> 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<string> 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 \""<<key<<"\" "<<key<<" <<END\n";
Launcher* test = (i->second);
VALID (test, i->first);
(*test)()->run(noCmdline); // run it to insert test generated output
std::cout << "END\n";
}
}

View file

@ -24,6 +24,7 @@
#ifndef TESTHELPER_SUITE_H
#define TESTHELPER_SUITE_H
#include <vector>
#include <string>
@ -35,11 +36,13 @@ namespace test
// Forward decls needed for run.hpp
class Test;
class Launcher;
typedef std::vector<string> & 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;

View file

@ -21,28 +21,23 @@
* *****************************************************/
//#include <map>
//#include <memory>
//#include <tr1/memory>
//#include <iostream>
//#include <sstream>
#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 <groupID>
* \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<string>()->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<VectS>(),
"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>();
}
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<VectS>().size() > 0)
return parameters["id"].as<VectS>()[0];
else
return string ();
}
/** @return \c true if --describe switch was given */
const bool
TestOption::getDescribe ()
{
return parameters["describe"].as<bool>();
}
/** 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<string>&
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;
}

View file

@ -24,47 +24,50 @@
#ifndef TESTHELPER_TESTOPTION_H
#define TESTHELPER_TESTOPTION_H
#include "common/cmdline.hpp"
#include <string>
#include <vector>
#include <iostream>
#include <boost/program_options.hpp>
#include <boost/utility.hpp>
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<string>
* 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<string>& remainingCmdline ();
operator string const ();
TestOption (util::Cmdline& cmdline);
const string getTestgroup ();
const string getTestID ();
const bool getDescribe ();
private:
VarMap vm;
vector<string> 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

View file

@ -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 <ct@pipapo.org>
@ -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 <typename NUM>
inline NUM noneg (NUM val)
{
return (0<val? val : 0);
}
/** shortcut for containment test on a map */
template <typename MAP>
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 <typename Container, typename Oper>
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_*/

View file

@ -75,7 +75,8 @@
NOBUG_CPP_DEFINE_FLAG(config);
NOBUG_CPP_DEFINE_FLAG(test);
#include "common/error.hpp"
#endif /* ===================== (End) C++-Part ============= */

View file

@ -10,6 +10,36 @@ out: This is how the world ends...
return: 0
END
TEST "Cmdline Wrapper" CmdlineWrapper_test <<END
out: wrapping cmdline:...
out: -->
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 <<END
out: Testing invocation with cmdline: ...
return: 0

View file

@ -0,0 +1,96 @@
/*
Cmdlinewrapper(Test) - build vector of tokens from cmdline, various conversions
Copyright (C) CinelerraCV
2007, Christian Thaeter <ct@pipapo.org>
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 <iostream>
#include <sstream>
#include <boost/lambda/lambda.hpp>
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

View file

@ -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"); }
};

View file

@ -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;
}

View file

@ -747,7 +747,7 @@ config.macros.timeline.handler = function(place,macroName,params,wikifier,paramS
}
//}}}</pre>
</div>
<div title="BuildDependenceis" modifier="Ichthyostega" modified="200708191952" created="200708120103" tags="organization buildsys" changecount="6">
<div title="BuildDependenceis" modifier="Ichthyostega" modified="200708210341" created="200708120103" tags="organization buildsys" changecount="7">
<pre>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__</pre>