|
|
|
|
@@ -18,12 +18,13 @@
|
|
|
|
|
#include <osg/Referenced>
|
|
|
|
|
#include <osg/ref_ptr>
|
|
|
|
|
#include <osg/Timer>
|
|
|
|
|
#include <osg/Notify>
|
|
|
|
|
|
|
|
|
|
#include <string>
|
|
|
|
|
#include <vector>
|
|
|
|
|
#include <list>
|
|
|
|
|
#include <fstream>
|
|
|
|
|
#include <iostream>
|
|
|
|
|
#include <ostream>
|
|
|
|
|
|
|
|
|
|
namespace osgUtx{
|
|
|
|
|
|
|
|
|
|
@@ -39,19 +40,19 @@ class SG_EXPORT Test: public osg::Referenced
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
|
|
|
|
|
typedef TestVisitor Visitor; // Test is redundant
|
|
|
|
|
typedef TestVisitor Visitor; // Test is redundant
|
|
|
|
|
|
|
|
|
|
Test( const std::string& sName ) : _name( sName ) {}
|
|
|
|
|
Test( const std::string& sName ) : _name( sName ) {}
|
|
|
|
|
|
|
|
|
|
const std::string& name() const { return _name; }
|
|
|
|
|
const std::string& name() const { return _name; }
|
|
|
|
|
|
|
|
|
|
virtual bool accept( Visitor& ) = 0;
|
|
|
|
|
virtual bool accept( Visitor& ) = 0;
|
|
|
|
|
|
|
|
|
|
protected:
|
|
|
|
|
|
|
|
|
|
virtual ~Test() {}
|
|
|
|
|
|
|
|
|
|
std::string _name;
|
|
|
|
|
std::string _name;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@@ -66,50 +67,50 @@ class SG_EXPORT TestContext
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
|
|
|
|
|
TestContext();
|
|
|
|
|
TestContext();
|
|
|
|
|
|
|
|
|
|
bool shouldStop() { return false; }
|
|
|
|
|
bool isVerbose() { return true; }
|
|
|
|
|
bool shouldStop() { return false; }
|
|
|
|
|
bool isVerbose() { return true; }
|
|
|
|
|
|
|
|
|
|
enum TraceLevel{
|
|
|
|
|
Off, ///< All tracing turned off
|
|
|
|
|
Results, ///< Output results only
|
|
|
|
|
Full ///< Full test diagnostic output
|
|
|
|
|
};
|
|
|
|
|
enum TraceLevel{
|
|
|
|
|
Off, ///< All tracing turned off
|
|
|
|
|
Results, ///< Output results only
|
|
|
|
|
Full ///< Full test diagnostic output
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
void setTraceLevel(TraceLevel tl);
|
|
|
|
|
TraceLevel getTraceLevel() const;
|
|
|
|
|
void setTraceLevel(TraceLevel tl);
|
|
|
|
|
TraceLevel getTraceLevel() const;
|
|
|
|
|
|
|
|
|
|
std::ostream& tout(TraceLevel tl=Full) const;
|
|
|
|
|
std::ostream& tout(TraceLevel tl=Full) const;
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
|
|
|
|
|
TestContext(const TestContext&);
|
|
|
|
|
TestContext operator=(const TestContext&);
|
|
|
|
|
TestContext(const TestContext&);
|
|
|
|
|
TestContext operator=(const TestContext&);
|
|
|
|
|
|
|
|
|
|
#ifndef DOXYGEN_SHOULD_SKIP_THIS
|
|
|
|
|
|
|
|
|
|
class SG_EXPORT TraceStream{
|
|
|
|
|
class SG_EXPORT TraceStream{
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
TraceStream(std::ostream& o=std::cout, TraceLevel tl=Results);
|
|
|
|
|
~TraceStream();
|
|
|
|
|
public:
|
|
|
|
|
TraceStream(std::ostream& o=osg::notify(osg::NOTICE), TraceLevel tl=Results);
|
|
|
|
|
~TraceStream();
|
|
|
|
|
|
|
|
|
|
void setTraceLevel(TraceLevel tl);
|
|
|
|
|
TraceLevel getTraceLevel() const;
|
|
|
|
|
void setTraceLevel(TraceLevel tl);
|
|
|
|
|
TraceLevel getTraceLevel() const;
|
|
|
|
|
|
|
|
|
|
std::ostream& stream(TraceLevel tl);
|
|
|
|
|
std::ostream& stream(TraceLevel tl);
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
private:
|
|
|
|
|
|
|
|
|
|
TraceLevel _traceLevel;
|
|
|
|
|
std::ostream* _outputStreamPtr;
|
|
|
|
|
std::ofstream _nullStream;
|
|
|
|
|
};
|
|
|
|
|
TraceLevel _traceLevel;
|
|
|
|
|
std::ostream* _outputStreamPtr;
|
|
|
|
|
std::ofstream _nullStream;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
#endif /* DOXYGEN_SHOULD_SKIP_THIS */
|
|
|
|
|
|
|
|
|
|
mutable TraceStream _tout;
|
|
|
|
|
mutable TraceStream _tout;
|
|
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
@@ -125,20 +126,20 @@ class TestVisitor
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
|
|
|
|
|
//..Should we enter this node and its children?
|
|
|
|
|
virtual bool visitEnter( TestSuite* ) { return true; }
|
|
|
|
|
//..Should we enter this node and its children?
|
|
|
|
|
virtual bool visitEnter( TestSuite* ) { return true; }
|
|
|
|
|
|
|
|
|
|
//..Returns true to continue to next Leaf
|
|
|
|
|
virtual bool visit( TestCase* ) = 0;
|
|
|
|
|
//..Returns true to continue to next Leaf
|
|
|
|
|
virtual bool visit( TestCase* ) = 0;
|
|
|
|
|
|
|
|
|
|
//..Returns true to continue to next Composite
|
|
|
|
|
virtual bool visitLeave( TestSuite* ) { return true; }
|
|
|
|
|
//..Returns true to continue to next Composite
|
|
|
|
|
virtual bool visitLeave( TestSuite* ) { return true; }
|
|
|
|
|
|
|
|
|
|
protected:
|
|
|
|
|
|
|
|
|
|
TestVisitor() {}
|
|
|
|
|
TestVisitor( const TestVisitor& ) {}
|
|
|
|
|
virtual ~TestVisitor() {}
|
|
|
|
|
TestVisitor() {}
|
|
|
|
|
TestVisitor( const TestVisitor& ) {}
|
|
|
|
|
virtual ~TestVisitor() {}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
@@ -149,13 +150,13 @@ class TestCase : public Test
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
|
|
|
|
|
typedef TestContext Context; // Test in TestContext? is redundant
|
|
|
|
|
typedef TestContext Context; // Test in TestContext? is redundant
|
|
|
|
|
|
|
|
|
|
TestCase( const std::string& sName ) : Test( sName ) {}
|
|
|
|
|
TestCase( const std::string& sName ) : Test( sName ) {}
|
|
|
|
|
|
|
|
|
|
virtual bool accept( Visitor& v ) { return v.visit( this ); }
|
|
|
|
|
virtual bool accept( Visitor& v ) { return v.visit( this ); }
|
|
|
|
|
|
|
|
|
|
virtual void run( const Context& ) = 0; // Subclass OSGUTX_EXPORT Responsibility
|
|
|
|
|
virtual void run( const Context& ) = 0; // Subclass OSGUTX_EXPORT Responsibility
|
|
|
|
|
|
|
|
|
|
protected:
|
|
|
|
|
|
|
|
|
|
@@ -170,13 +171,13 @@ class TestX
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
|
|
|
|
|
TestX(const std::string& s):_what(s) {}
|
|
|
|
|
virtual ~TestX() {}
|
|
|
|
|
TestX(const std::string& s):_what(s) {}
|
|
|
|
|
virtual ~TestX() {}
|
|
|
|
|
|
|
|
|
|
const std::string& what() const { return _what; }
|
|
|
|
|
const std::string& what() const { return _what; }
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
std::string _what;
|
|
|
|
|
std::string _what;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
@@ -185,7 +186,7 @@ A TestFailureX indicates a failure in the tested component.
|
|
|
|
|
class TestFailureX: public TestX
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
TestFailureX(const std::string& s):TestX(s) {}
|
|
|
|
|
TestFailureX(const std::string& s):TestX(s) {}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
@@ -197,7 +198,7 @@ run which prevents the component from being tested.
|
|
|
|
|
class TestErrorX: public TestX
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
TestErrorX(const std::string& s):TestX(s) {}
|
|
|
|
|
TestErrorX(const std::string& s):TestX(s) {}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
@@ -211,28 +212,28 @@ of information from one test case to the next.
|
|
|
|
|
template< typename FixtureT >
|
|
|
|
|
class TestCase_ : public TestCase
|
|
|
|
|
{
|
|
|
|
|
typedef void (FixtureT::*TestMethodPtr)( const Context& );
|
|
|
|
|
typedef void (FixtureT::*TestMethodPtr)( const Context& );
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
|
|
|
|
|
// Constructor adds the TestMethod pointer
|
|
|
|
|
TestCase_( const std::string& sName, TestMethodPtr pTestMethod ) :
|
|
|
|
|
TestCase( sName ),
|
|
|
|
|
_pTestMethod( pTestMethod )
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
// Constructor adds the TestMethod pointer
|
|
|
|
|
TestCase_( const std::string& sName, TestMethodPtr pTestMethod ) :
|
|
|
|
|
TestCase( sName ),
|
|
|
|
|
_pTestMethod( pTestMethod )
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Create a TestFixture instance and invoke TestMethod?
|
|
|
|
|
virtual void run( const Context& ctx )
|
|
|
|
|
{
|
|
|
|
|
( FixtureT().*_pTestMethod )( ctx );
|
|
|
|
|
}
|
|
|
|
|
// Create a TestFixture instance and invoke TestMethod?
|
|
|
|
|
virtual void run( const Context& ctx )
|
|
|
|
|
{
|
|
|
|
|
( FixtureT().*_pTestMethod )( ctx );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected:
|
|
|
|
|
|
|
|
|
|
virtual ~TestCase_() {}
|
|
|
|
|
|
|
|
|
|
TestMethodPtr _pTestMethod;
|
|
|
|
|
TestMethodPtr _pTestMethod;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
@@ -243,24 +244,24 @@ class SG_EXPORT TestSuite : public Test
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
|
|
|
|
|
TestSuite( const std::string& name );
|
|
|
|
|
TestSuite( const std::string& name );
|
|
|
|
|
|
|
|
|
|
/** Adds a Test to the suite. */
|
|
|
|
|
void add( Test* pTest );
|
|
|
|
|
/** Adds a Test to the suite. */
|
|
|
|
|
void add( Test* pTest );
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
@returns The immediate child denoted by name, or 0 if not found.
|
|
|
|
|
*/
|
|
|
|
|
Test* findChild(const std::string& name);
|
|
|
|
|
/**
|
|
|
|
|
@returns The immediate child denoted by name, or 0 if not found.
|
|
|
|
|
*/
|
|
|
|
|
Test* findChild(const std::string& name);
|
|
|
|
|
|
|
|
|
|
virtual bool accept( Test::Visitor& v );
|
|
|
|
|
virtual bool accept( Test::Visitor& v );
|
|
|
|
|
|
|
|
|
|
protected:
|
|
|
|
|
|
|
|
|
|
virtual ~TestSuite() {}
|
|
|
|
|
|
|
|
|
|
typedef std::vector< osg::ref_ptr<Test> > Tests;
|
|
|
|
|
Tests _tests; // Collection of Suites and/or Cases
|
|
|
|
|
typedef std::vector< osg::ref_ptr<Test> > Tests;
|
|
|
|
|
Tests _tests; // Collection of Suites and/or Cases
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
@@ -272,54 +273,54 @@ class SG_EXPORT TestGraph
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
|
|
|
|
|
static TestGraph& instance();
|
|
|
|
|
static TestGraph& instance();
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
@return a pointer to the root TestSuite.
|
|
|
|
|
*/
|
|
|
|
|
TestSuite* root();
|
|
|
|
|
/**
|
|
|
|
|
@return a pointer to the root TestSuite.
|
|
|
|
|
*/
|
|
|
|
|
TestSuite* root();
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
A utility function for accessing an arbitrary quite by pathname, relative to
|
|
|
|
|
the suite 'tsuite' (defaults to root if null), and with the option of creating
|
|
|
|
|
the \em TestSuite designated by \em path, if it does not already exist.
|
|
|
|
|
/**
|
|
|
|
|
A utility function for accessing an arbitrary quite by pathname, relative to
|
|
|
|
|
the suite 'tsuite' (defaults to root if null), and with the option of creating
|
|
|
|
|
the \em TestSuite designated by \em path, if it does not already exist.
|
|
|
|
|
|
|
|
|
|
This method may return 0 if the suite either cannot be found (and createIfNecssary
|
|
|
|
|
is 0), or the first component of \em path is not the same as the name of the
|
|
|
|
|
TestSuite \em tsuite.
|
|
|
|
|
This method may return 0 if the suite either cannot be found (and createIfNecssary
|
|
|
|
|
is 0), or the first component of \em path is not the same as the name of the
|
|
|
|
|
TestSuite \em tsuite.
|
|
|
|
|
|
|
|
|
|
This was written to aid the auto-registration of tests at specific points in
|
|
|
|
|
the test tree, where the tests' AutoRegistrationAgents may be distributed across
|
|
|
|
|
several files, and cannot be guaranteed to run in a given order. E.g. You cannot
|
|
|
|
|
register a test "root.osg.MyTest" unless you know that the the suite "root.osg"
|
|
|
|
|
already exists.
|
|
|
|
|
|
|
|
|
|
This was written to aid the auto-registration of tests at specific points in
|
|
|
|
|
the test tree, where the tests' AutoRegistrationAgents may be distributed across
|
|
|
|
|
several files, and cannot be guaranteed to run in a given order. E.g. You cannot
|
|
|
|
|
register a test "root.osg.MyTest" unless you know that the the suite "root.osg"
|
|
|
|
|
already exists.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@param path The name of the TestSuite to return.
|
|
|
|
|
@param tsuite The suite to 'start from'. Path is relative to this
|
|
|
|
|
suite (defaults to root suite).
|
|
|
|
|
@param createIfNecessary Optionally create the TestSuite(s) denoted by path if
|
|
|
|
|
they do not exist.
|
|
|
|
|
*/
|
|
|
|
|
TestSuite* suite(const std::string& path, TestSuite* tsuite = 0,bool createIfNecessary = false);
|
|
|
|
|
@param path The name of the TestSuite to return.
|
|
|
|
|
@param tsuite The suite to 'start from'. Path is relative to this
|
|
|
|
|
suite (defaults to root suite).
|
|
|
|
|
@param createIfNecessary Optionally create the TestSuite(s) denoted by path if
|
|
|
|
|
they do not exist.
|
|
|
|
|
*/
|
|
|
|
|
TestSuite* suite(const std::string& path, TestSuite* tsuite = 0,bool createIfNecessary = false);
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
Does the same job as the version of suite listed above, but the path
|
|
|
|
|
is passed in as components in a list, represented by the iterator parameters.
|
|
|
|
|
*/
|
|
|
|
|
TestSuite* suite(
|
|
|
|
|
std::list<std::string>::iterator it,
|
|
|
|
|
std::list<std::string>::iterator end,
|
|
|
|
|
TestSuite* tsuite, bool createIfNecessary);
|
|
|
|
|
/**
|
|
|
|
|
Does the same job as the version of suite listed above, but the path
|
|
|
|
|
is passed in as components in a list, represented by the iterator parameters.
|
|
|
|
|
*/
|
|
|
|
|
TestSuite* suite(
|
|
|
|
|
std::list<std::string>::iterator it,
|
|
|
|
|
std::list<std::string>::iterator end,
|
|
|
|
|
TestSuite* tsuite, bool createIfNecessary);
|
|
|
|
|
|
|
|
|
|
TestGraph();
|
|
|
|
|
TestGraph();
|
|
|
|
|
|
|
|
|
|
TestGraph(const TestGraph&);
|
|
|
|
|
TestGraph& operator=(const TestGraph&);
|
|
|
|
|
TestGraph(const TestGraph&);
|
|
|
|
|
TestGraph& operator=(const TestGraph&);
|
|
|
|
|
|
|
|
|
|
osg::ref_ptr<TestSuite> root_;
|
|
|
|
|
osg::ref_ptr<TestSuite> root_;
|
|
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
@@ -330,22 +331,22 @@ current qualified TestSuite path.
|
|
|
|
|
*/
|
|
|
|
|
class SG_EXPORT TestQualifier : public TestVisitor
|
|
|
|
|
{
|
|
|
|
|
enum { SEPCHAR = '.' };
|
|
|
|
|
enum { SEPCHAR = '.' };
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
|
|
|
|
|
// Entering a composite: Push its name on the Path
|
|
|
|
|
virtual bool visitEnter( TestSuite* pSuite );
|
|
|
|
|
// Entering a composite: Push its name on the Path
|
|
|
|
|
virtual bool visitEnter( TestSuite* pSuite );
|
|
|
|
|
|
|
|
|
|
// Leaving a composite: Pop its name from the Path
|
|
|
|
|
virtual bool visitLeave( TestSuite* pSuite );
|
|
|
|
|
// Leaving a composite: Pop its name from the Path
|
|
|
|
|
virtual bool visitLeave( TestSuite* pSuite );
|
|
|
|
|
|
|
|
|
|
// Provide read-only access to the current qualifier
|
|
|
|
|
const std::string& currentPath() const;
|
|
|
|
|
// Provide read-only access to the current qualifier
|
|
|
|
|
const std::string& currentPath() const;
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
|
|
|
|
|
std::string _path; // Current qualifier
|
|
|
|
|
std::string _path; // Current qualifier
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
@@ -357,50 +358,50 @@ class SG_EXPORT QualifiedTestPrinter : public TestQualifier
|
|
|
|
|
public:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
virtual bool visit( TestCase* pTest );
|
|
|
|
|
virtual bool visit( TestCase* pTest );
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
A TestRecord records the output of a given test case, i.e. its start/stop time,
|
|
|
|
|
its result, and a textual description of any problems.
|
|
|
|
|
|
|
|
|
|
\todo Consider adding accessor methods if necessary, to get the details
|
|
|
|
|
stored in the TestRecord.
|
|
|
|
|
\todo Consider adding accessor methods if necessary, to get the details
|
|
|
|
|
stored in the TestRecord.
|
|
|
|
|
*/
|
|
|
|
|
class SG_EXPORT TestRecord
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
public:
|
|
|
|
|
|
|
|
|
|
void start();
|
|
|
|
|
void stop();
|
|
|
|
|
void log(const TestFailureX& e);
|
|
|
|
|
void log(const TestErrorX& e);
|
|
|
|
|
void log(const std::exception& e);
|
|
|
|
|
void log(const std::string& s);
|
|
|
|
|
void start();
|
|
|
|
|
void stop();
|
|
|
|
|
void log(const TestFailureX& e);
|
|
|
|
|
void log(const TestErrorX& e);
|
|
|
|
|
void log(const std::exception& e);
|
|
|
|
|
void log(const std::string& s);
|
|
|
|
|
|
|
|
|
|
// Default copy construction and assignment are OK
|
|
|
|
|
// Default copy construction and assignment are OK
|
|
|
|
|
|
|
|
|
|
// FIXME: Add accessors?
|
|
|
|
|
// FIXME: Add accessors?
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
private:
|
|
|
|
|
|
|
|
|
|
// Onlye a TestReport can create a TestRecord
|
|
|
|
|
friend class TestReport;
|
|
|
|
|
TestRecord(const std::string& name);
|
|
|
|
|
// Onlye a TestReport can create a TestRecord
|
|
|
|
|
friend class TestReport;
|
|
|
|
|
TestRecord(const std::string& name);
|
|
|
|
|
|
|
|
|
|
enum Result{
|
|
|
|
|
Success,Failure,Error
|
|
|
|
|
};
|
|
|
|
|
enum Result{
|
|
|
|
|
Success,Failure,Error
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
friend std::ostream& operator<<(std::ostream& o,const TestRecord& tr);
|
|
|
|
|
friend std::ostream& operator<<(std::ostream& o,const TestRecord& tr);
|
|
|
|
|
|
|
|
|
|
static osg::Timer timer_; // To time tests
|
|
|
|
|
static osg::Timer timer_; // To time tests
|
|
|
|
|
|
|
|
|
|
std::string name_;
|
|
|
|
|
osg::Timer_t start_;
|
|
|
|
|
osg::Timer_t stop_;
|
|
|
|
|
Result result_;
|
|
|
|
|
std::string problem_;
|
|
|
|
|
std::string name_;
|
|
|
|
|
osg::Timer_t start_;
|
|
|
|
|
osg::Timer_t stop_;
|
|
|
|
|
Result result_;
|
|
|
|
|
std::string problem_;
|
|
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
@@ -408,20 +409,20 @@ class SG_EXPORT TestRecord
|
|
|
|
|
A TestReport represents the complete set of results (TestRecords) for a
|
|
|
|
|
given test run.
|
|
|
|
|
|
|
|
|
|
\todo Add support for printing the test report in various formats:
|
|
|
|
|
e.g. text, XML, CSV
|
|
|
|
|
\todo Add support for printing the test report in various formats:
|
|
|
|
|
e.g. text, XML, CSV
|
|
|
|
|
*/
|
|
|
|
|
class SG_EXPORT TestReport
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
|
|
|
|
|
TestRecord& createRecord(const std::string& s){
|
|
|
|
|
_records.push_back(TestRecord(s));
|
|
|
|
|
return _records.back();
|
|
|
|
|
}
|
|
|
|
|
TestRecord& createRecord(const std::string& s){
|
|
|
|
|
_records.push_back(TestRecord(s));
|
|
|
|
|
return _records.back();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
std::list<TestRecord> _records;
|
|
|
|
|
std::list<TestRecord> _records;
|
|
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
@@ -435,37 +436,37 @@ private:
|
|
|
|
|
A TestRunner is a visitor which will run specified tests as it traverses the
|
|
|
|
|
test graph.
|
|
|
|
|
|
|
|
|
|
\todo Consider an accessor method to get at the TestReport if necessary.
|
|
|
|
|
\todo Consider an accessor method to get at the TestReport if necessary.
|
|
|
|
|
*/
|
|
|
|
|
class SG_EXPORT TestRunner : public TestQualifier
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
|
|
|
|
|
TestRunner( TestContext& ctx );
|
|
|
|
|
TestRunner( TestContext& ctx );
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
Tests may be specified by partial names. E.g. specifiying "root"
|
|
|
|
|
will run all tests below root, i.e. all tests.
|
|
|
|
|
Specifiying "root.osg" will run all tests below \em root.osg.
|
|
|
|
|
Specifying "root.osg.de" will run all tests (and suites) below
|
|
|
|
|
\em root.osg with names beginning with the \em de.
|
|
|
|
|
*/
|
|
|
|
|
void specify( const std::string& sQualifiedName );
|
|
|
|
|
/**
|
|
|
|
|
Tests may be specified by partial names. E.g. specifiying "root"
|
|
|
|
|
will run all tests below root, i.e. all tests.
|
|
|
|
|
Specifiying "root.osg" will run all tests below \em root.osg.
|
|
|
|
|
Specifying "root.osg.de" will run all tests (and suites) below
|
|
|
|
|
\em root.osg with names beginning with the \em de.
|
|
|
|
|
*/
|
|
|
|
|
void specify( const std::string& sQualifiedName );
|
|
|
|
|
|
|
|
|
|
bool visitEnter( TestSuite* pSuite );
|
|
|
|
|
bool visit( TestCase* pTest );
|
|
|
|
|
bool visitLeave( TestSuite* pSuite );
|
|
|
|
|
bool visitEnter( TestSuite* pSuite );
|
|
|
|
|
bool visit( TestCase* pTest );
|
|
|
|
|
bool visitLeave( TestSuite* pSuite );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
protected:
|
|
|
|
|
|
|
|
|
|
void perform( TestCase* pTest );
|
|
|
|
|
void perform( TestCase* pTest );
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
|
|
|
|
|
TestReport _db; // Results
|
|
|
|
|
TestContext& _ctx; // The Global Testing Context
|
|
|
|
|
std::vector<std::string> _tests; // Specified Tests
|
|
|
|
|
TestReport _db; // Results
|
|
|
|
|
TestContext& _ctx; // The Global Testing Context
|
|
|
|
|
std::vector<std::string> _tests; // Specified Tests
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
@@ -475,11 +476,11 @@ Starts a TestSuite singleton function
|
|
|
|
|
@see OSGUTX_ADD_TESTCASE, OSGUTX_END_TESTSUITE
|
|
|
|
|
*/
|
|
|
|
|
#define OSGUTX_BEGIN_TESTSUITE( tsuite ) \
|
|
|
|
|
osgUtx::TestSuite* tsuite##_TestSuite() \
|
|
|
|
|
{ \
|
|
|
|
|
static osg::ref_ptr<osgUtx::TestSuite> s_suite = 0; \
|
|
|
|
|
if ( s_suite == 0 ) { \
|
|
|
|
|
s_suite = new osgUtx::TestSuite( #tsuite );
|
|
|
|
|
osgUtx::TestSuite* tsuite##_TestSuite() \
|
|
|
|
|
{ \
|
|
|
|
|
static osg::ref_ptr<osgUtx::TestSuite> s_suite = 0; \
|
|
|
|
|
if ( s_suite == 0 ) { \
|
|
|
|
|
s_suite = new osgUtx::TestSuite( #tsuite );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@@ -488,21 +489,21 @@ Adds a test case to a suite object being created in a TestSuite singleton functi
|
|
|
|
|
@see OSGUTX_BEGIN_TESTSUITE, OSGUTX_END_TESTSUITE
|
|
|
|
|
*/
|
|
|
|
|
#define OSGUTX_ADD_TESTCASE( tfixture, tmethod ) \
|
|
|
|
|
s_suite->add( new osgUtx::TestCase_<tfixture>( \
|
|
|
|
|
#tmethod, &tfixture::tmethod ) );
|
|
|
|
|
s_suite->add( new osgUtx::TestCase_<tfixture>( \
|
|
|
|
|
#tmethod, &tfixture::tmethod ) );
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
Ends a TestSuite singleton function
|
|
|
|
|
@see OSGUTX_BEGIN_TESTSUITE, OSGUTX_ADD_TESTCASE
|
|
|
|
|
*/
|
|
|
|
|
#define OSGUTX_END_TESTSUITE \
|
|
|
|
|
} \
|
|
|
|
|
return s_suite.get(); \
|
|
|
|
|
}
|
|
|
|
|
} \
|
|
|
|
|
return s_suite.get(); \
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** Define a TestSuite accessor */
|
|
|
|
|
#define OSGUTX_TESTSUITE( tsuite ) \
|
|
|
|
|
tsuite##_TestSuite()
|
|
|
|
|
tsuite##_TestSuite()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
@@ -510,16 +511,16 @@ Adds a suite to a suite - allows composition of test suites.
|
|
|
|
|
@see OSGUTX_BEGIN_TESTSUITE, OSGUTX_END_TESTSUITE
|
|
|
|
|
*/
|
|
|
|
|
#define OSGUTX_ADD_TESTSUITE( childSuite ) \
|
|
|
|
|
s_suite->add( childSuite##_TestSuite() );
|
|
|
|
|
s_suite->add( childSuite##_TestSuite() );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** Autoregister a testsuite with the root suite at startup */
|
|
|
|
|
#define OSGUTX_AUTOREGISTER_TESTSUITE( tsuite ) \
|
|
|
|
|
static osgUtx::TestSuiteAutoRegistrationAgent tsuite##_autoRegistrationObj__( tsuite##_TestSuite() );
|
|
|
|
|
static osgUtx::TestSuiteAutoRegistrationAgent tsuite##_autoRegistrationObj__( tsuite##_TestSuite() );
|
|
|
|
|
|
|
|
|
|
/** Auto register a testsuite with at designated point in the suite graph at startup */
|
|
|
|
|
#define OSGUTX_AUTOREGISTER_TESTSUITE_AT( tsuite , path ) \
|
|
|
|
|
static osgUtx::TestSuiteAutoRegistrationAgent tsuite##_autoRegistrationObj__( tsuite##_TestSuite(), #path );
|
|
|
|
|
static osgUtx::TestSuiteAutoRegistrationAgent tsuite##_autoRegistrationObj__( tsuite##_TestSuite(), #path );
|
|
|
|
|
|
|
|
|
|
namespace osgUtx{
|
|
|
|
|
|
|
|
|
|
@@ -531,21 +532,21 @@ direct use, it should be used via the following macros. (It's a secret agent :-)
|
|
|
|
|
*/
|
|
|
|
|
struct TestSuiteAutoRegistrationAgent
|
|
|
|
|
{
|
|
|
|
|
TestSuiteAutoRegistrationAgent(TestSuite* tsuite, const char* path = 0)
|
|
|
|
|
{
|
|
|
|
|
if( ! path ) path = "root";
|
|
|
|
|
TestSuiteAutoRegistrationAgent(TestSuite* tsuite, const char* path = 0)
|
|
|
|
|
{
|
|
|
|
|
if( ! path ) path = "root";
|
|
|
|
|
|
|
|
|
|
// Find the suite named in 'path', create it if necessary
|
|
|
|
|
TestSuite *regSuite = osgUtx::TestGraph::instance().suite( path, 0, true );
|
|
|
|
|
// Find the suite named in 'path', create it if necessary
|
|
|
|
|
TestSuite *regSuite = osgUtx::TestGraph::instance().suite( path, 0, true );
|
|
|
|
|
|
|
|
|
|
if(!regSuite){
|
|
|
|
|
std::cerr<<"Warning, unable to register test suite named \""<<tsuite->name()<<"\" at "
|
|
|
|
|
<<path<<", falling back to root suite."<<std::endl;
|
|
|
|
|
regSuite = osgUtx::TestGraph::instance().root();
|
|
|
|
|
}
|
|
|
|
|
if(!regSuite){
|
|
|
|
|
osg::notify(osg::WARN)<<"Warning, unable to register test suite named \""<<tsuite->name()<<"\" at "
|
|
|
|
|
<<path<<", falling back to root suite."<<std::endl;
|
|
|
|
|
regSuite = osgUtx::TestGraph::instance().root();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
regSuite->add(tsuite);
|
|
|
|
|
}
|
|
|
|
|
regSuite->add(tsuite);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
@@ -560,11 +561,11 @@ The exception will indicate the file and line number of the failed expression,
|
|
|
|
|
along with expression itself.
|
|
|
|
|
*/
|
|
|
|
|
#define OSGUTX_TEST_F( expr ) \
|
|
|
|
|
if( !(expr) ){ \
|
|
|
|
|
std::stringstream ss; \
|
|
|
|
|
ss<< #expr <<" failure: "<<__FILE__<<", line "<<__LINE__<<std::ends; \
|
|
|
|
|
throw osgUtx::TestFailureX(ss.str()); \
|
|
|
|
|
}
|
|
|
|
|
if( !(expr) ){ \
|
|
|
|
|
std::stringstream ss; \
|
|
|
|
|
ss<< #expr <<" failure: "<<__FILE__<<", line "<<__LINE__<<std::ends; \
|
|
|
|
|
throw osgUtx::TestFailureX(ss.str()); \
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
OSGUTX_TEST_E is a convenience macro, analogous to assert(), which will
|
|
|
|
|
@@ -576,11 +577,11 @@ The exception will indicate the file and line number of the failed expression,
|
|
|
|
|
along with expression itself.
|
|
|
|
|
*/
|
|
|
|
|
#define OSGUTX_TEST_E( expr ) \
|
|
|
|
|
if( !(expr) ){ \
|
|
|
|
|
std::stringstream ss; \
|
|
|
|
|
ss<< #expr <<" error: "<<__FILE__<<", line "<<__LINE__<<std::ends; \
|
|
|
|
|
throw osgUtx::TestErrorX(ss.str()); \
|
|
|
|
|
}
|
|
|
|
|
if( !(expr) ){ \
|
|
|
|
|
std::stringstream ss; \
|
|
|
|
|
ss<< #expr <<" error: "<<__FILE__<<", line "<<__LINE__<<std::ends; \
|
|
|
|
|
throw osgUtx::TestErrorX(ss.str()); \
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#endif // OSG_UNITTESTFRAMEWORK
|
|
|
|
|
|