wrapper for cmdline parsing, finished testsuite-runner, solved shutdown-memoryleak
This commit is contained in:
parent
91d04f7019
commit
5575a7679d
17 changed files with 534 additions and 170 deletions
|
|
@ -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)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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 ();
|
||||
} }
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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
85
src/common/cmdline.cpp
Normal 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
70
src/common/cmdline.hpp
Normal 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
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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";
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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_*/
|
||||
|
|
|
|||
|
|
@ -75,7 +75,8 @@
|
|||
NOBUG_CPP_DEFINE_FLAG(config);
|
||||
NOBUG_CPP_DEFINE_FLAG(test);
|
||||
|
||||
|
||||
#include "common/error.hpp"
|
||||
|
||||
|
||||
#endif /* ===================== (End) C++-Part ============= */
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
96
tests/components/common/test/cmdlinewrappertest.cpp
Normal file
96
tests/components/common/test/cmdlinewrappertest.cpp
Normal 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
|
||||
|
||||
|
|
@ -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"); }
|
||||
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
Loading…
Reference in a new issue