Added Neil Salter's osgUtx library into the distribution, have put all the
orignal seperate headers and source into include/osg/UnitTestFrameWork and src/osg/UnitTestFramework.cpp respectively. I have done this to keep the include and source directories focused on the scene graph rather than the test framework. Have added a very simple unit test to Vec3.cpp, which are optionally compiled in with the OSG_COMPILE_UNIT_TESTS define, which is only currently defined in debug builds under unix. It should be fine to add it in under Windows project files as well. Finally, a new demo app osgunittests runs the tests and reports success or failure of the tests.
This commit is contained in:
parent
bff4728eac
commit
7d6197441e
@ -2,6 +2,10 @@ echo osgversion
|
||||
osgversion
|
||||
more memleaks.log
|
||||
|
||||
echo osgunittests
|
||||
osgunittests
|
||||
more memleaks.log
|
||||
|
||||
echo sgv osgcool.osg
|
||||
sgv osgcool.osg
|
||||
more memleaks.log
|
||||
|
@ -93,7 +93,7 @@ ifeq ($(COMPILER),gnu)
|
||||
INC += -I/usr/local/glut-3.7/include
|
||||
DEF += -W -Wall -fPIC -fpermissive
|
||||
OPTF = -O2
|
||||
DBGF = -g
|
||||
DBGF = -g -DOSG_COMPILE_UNIT_TESTS
|
||||
SHARED = -shared -fPIC
|
||||
ifeq ($(ARCH),64)
|
||||
ARCHARGS = -m64
|
||||
@ -127,7 +127,7 @@ else
|
||||
INC +=
|
||||
DEF += -features=extensions
|
||||
OPTF = -xO4
|
||||
DBGF = -g
|
||||
DBGF = -g -DOSG_COMPILE_UNIT_TESTS
|
||||
SHARED = -G
|
||||
ifeq ($(ARCH),64)
|
||||
ARCHARGS = -xarch=v9
|
||||
@ -166,7 +166,7 @@ ifeq ($(OS),IRIX)
|
||||
-DEBUG:woff=1682 -DEBUG:woff=3303\
|
||||
-MDupdate $(MAKEDEPEND)
|
||||
OPTF = -O2
|
||||
DBGF = -g
|
||||
DBGF = -g -DOSG_COMPILE_UNIT_TESTS
|
||||
SHARED = -shared
|
||||
ARCH = 32
|
||||
ifeq ($(ARCH),64)
|
||||
@ -216,7 +216,7 @@ endif
|
||||
INC +=
|
||||
DEF += -W -Wall
|
||||
OPTF = -O2
|
||||
DBGF = -g -DOSG_USE_MEMORY_MANAGER
|
||||
DBGF = -g -DOSG_COMPILE_UNIT_TESTS -DOSG_USE_MEMORY_MANAGER
|
||||
SHARED = -shared
|
||||
ARCHARGS =
|
||||
LINKARGS = -L/usr/X11R6/lib
|
||||
@ -250,7 +250,7 @@ ifeq ($(OS),FreeBSD)
|
||||
INC += -I/usr/local/include -I/usr/X11R6/include
|
||||
DEF += -W -Wall
|
||||
OPTF = -O2
|
||||
DBGF = -g
|
||||
DBGF = -g -DOSG_COMPILE_UNIT_TESTS
|
||||
SHARED = -shared
|
||||
ARCHARGS =
|
||||
LINKARGS = -L/usr/X11R6/lib -L/usr/local/lib -rpath /usr/local/lib
|
||||
@ -274,7 +274,7 @@ ifeq ($(OS),Darwin)
|
||||
INC += -I/usr/include
|
||||
DEF += -Wall -D__DARWIN_OSX__
|
||||
OPTF = -O2
|
||||
DBGF = -g
|
||||
DBGF = -g -DOSG_COMPILE_UNIT_TESTS
|
||||
DEPARG = -M $(DEF)
|
||||
SHARED = -shared
|
||||
ARCHARGS =
|
||||
@ -316,7 +316,7 @@ ifeq ($(OS),CYGWIN)
|
||||
INC +=
|
||||
DEF += -DWIN32 -W -Wall
|
||||
OPTF = -O2
|
||||
DBGF = -g
|
||||
DBGF = -g -DOSG_COMPILE_UNIT_TESTS
|
||||
SHARED = -shared\
|
||||
-Wl,--export-all-symbols \
|
||||
-Wl,--output-def,lib$(TARGET_BASENAME).def \
|
||||
@ -381,7 +381,7 @@ ifeq ($(OS),MINGW)
|
||||
DEF += -DWIN32 -Wall
|
||||
# -W
|
||||
OPTF = -O2
|
||||
DBGF = -g
|
||||
DBGF = -g -DOSG_COMPILE_UNIT_TESTS
|
||||
SHARED = -shared\
|
||||
-Wl,--export-all-symbols \
|
||||
-Wl,--output-def,lib$(TARGET_BASENAME).def \
|
||||
@ -457,7 +457,7 @@ ifeq ($(OS),HP-UX)
|
||||
OPTF = -O2
|
||||
# gcc 3.1 uses DWARF as default, my GDB might not yet support this...
|
||||
# at least I've got problems everywhere
|
||||
DBGF = -g -gstabs+
|
||||
DBGF = -g -gstabs+ -DOSG_COMPILE_UNIT_TESTS
|
||||
SHARED = -shared -fPIC
|
||||
ARCH = 32
|
||||
ifeq ($(ARCH),64)
|
||||
|
@ -93,6 +93,7 @@ DEMOS_DIRS = \
|
||||
osgtexture1D\
|
||||
osgtexture2D\
|
||||
osgtexture3D\
|
||||
osgunittests\
|
||||
osgviews\
|
||||
osgversion\
|
||||
sgv
|
||||
|
95
VisualStudio/Demos/osgunittests/osgunittests.dsp
Normal file
95
VisualStudio/Demos/osgunittests/osgunittests.dsp
Normal file
@ -0,0 +1,95 @@
|
||||
# Microsoft Developer Studio Project File - Name="Demo osgunittests" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Console Application" 0x0103
|
||||
|
||||
CFG=Demo osgunittests - Win32 Release
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "osgunittests.mak".
|
||||
!MESSAGE
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "osgunittests.mak" CFG="Demo osgunittests - Win32 Release"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "Demo osgunittests - Win32 Release" (based on "Win32 (x86) Console Application")
|
||||
!MESSAGE "Demo osgunittests - Win32 Debug" (based on "Win32 (x86) Console Application")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
# PROP AllowPerConfigDependencies 0
|
||||
# PROP Scc_ProjName ""
|
||||
# PROP Scc_LocalPath ""
|
||||
CPP=cl.exe
|
||||
RSC=rc.exe
|
||||
|
||||
!IF "$(CFG)" == "Demo osgunittests - Win32 Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "Release"
|
||||
# PROP BASE Intermediate_Dir "Release"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "Release"
|
||||
# PROP Intermediate_Dir "Release"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD CPP /nologo /MD /W3 /GR /GX /O2 /I "../../../include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD BASE RSC /l 0x809 /d "NDEBUG"
|
||||
# ADD RSC /l 0x809 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
|
||||
# ADD LINK32 /nologo /subsystem:console /pdb:none /machine:I386 /out:"../../../bin/osgunittests.exe" /libpath:"../../../lib"
|
||||
|
||||
!ELSEIF "$(CFG)" == "Demo osgunittests - Win32 Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "Debug"
|
||||
# PROP BASE Intermediate_Dir "Debug"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "Debug"
|
||||
# PROP Intermediate_Dir "Debug"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD CPP /nologo /MDd /W3 /Gm /vd0 /GR /GX /Zi /Od /I "../../../include" /D "_CONSOLE" /D "_MBCS" /D "FL_DLL" /D "WIN32" /D "_DEBUG" /FR /YX /FD /c
|
||||
# ADD BASE RSC /l 0x809 /d "_DEBUG"
|
||||
# ADD RSC /l 0x809 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
|
||||
# ADD LINK32 /nologo /subsystem:console /debug /machine:I386 /nodefaultlib:"libcmt" /out:"../../../bin/osgunittestsd.exe" /pdbtype:sept /libpath:"../../../lib"
|
||||
# SUBTRACT LINK32 /incremental:no
|
||||
|
||||
!ENDIF
|
||||
|
||||
# Begin Target
|
||||
|
||||
# Name "Demo osgunittests - Win32 Release"
|
||||
# Name "Demo osgunittests - Win32 Debug"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\src\Demos\osgunittests\osgunittests.cpp
|
||||
# End Source File
|
||||
# End Target
|
||||
# Begin Group "Resource Files"
|
||||
|
||||
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
|
||||
# End Group
|
||||
# End Project
|
@ -279,6 +279,27 @@ Package=<4>
|
||||
|
||||
###############################################################################
|
||||
|
||||
Project: "Demo osgconv"=.\Demos\osgunittests\osgunittests.dsp - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<4>
|
||||
{{{
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name Core osg
|
||||
End Project Dependency
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name Core osgDB
|
||||
End Project Dependency
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name Core osgUtil
|
||||
End Project Dependency
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
Project: "Demo osgcopy"=.\Demos\osgcopy\osgcopy.dsp - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
|
@ -413,6 +413,14 @@ SOURCE=..\..\src\osg\BlendFunc.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\src\osg\UnitTestFramework.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\src\osg\Vec3.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\src\osg\Version.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
@ -805,6 +813,10 @@ SOURCE=..\..\Include\Osg\Types
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Include\Osg\UnitTestFramework
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Include\Osg\Vec2
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
565
include/osg/UnitTestFramework
Normal file
565
include/osg/UnitTestFramework
Normal file
@ -0,0 +1,565 @@
|
||||
//C++ header - Open Scene Graph - Copyright (C) 1998-2002 Robert Osfield
|
||||
//Distributed under the terms of the GNU Library General Public License (LGPL)
|
||||
//as published by the Free Software Foundation.
|
||||
|
||||
#ifndef OSG_UNITTESTFRAMEWORK
|
||||
#define OSG_UNITTESTFRAMEWORK 1
|
||||
|
||||
#include <osg/Export>
|
||||
#include <osg/Referenced>
|
||||
#include <osg/ref_ptr>
|
||||
#include <osg/Timer>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <list>
|
||||
#include <fstream>
|
||||
|
||||
namespace osgUtx{
|
||||
|
||||
class TestVisitor;
|
||||
|
||||
/**
|
||||
Test, an abstract base class, is the Composite pattern's \em component
|
||||
class for our graph of test cases, and defines the basic interface
|
||||
for all Test components. It is a referent, and may be pointed
|
||||
to by an osg::ref_ptr.
|
||||
*/
|
||||
class SG_EXPORT Test: public osg::Referenced
|
||||
{
|
||||
public:
|
||||
|
||||
typedef TestVisitor Visitor; // Test is redundant
|
||||
|
||||
Test( const string& sName ) : _name( sName ) {}
|
||||
|
||||
const std::string& name() const { return _name; }
|
||||
|
||||
virtual bool accept( Visitor& ) = 0;
|
||||
|
||||
private:
|
||||
|
||||
std::string _name;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
TestContext wraps up information which is passed to tests as they are run,
|
||||
and may contain test-specific information or 'global' test objects, such
|
||||
as an output stream for verbose output during the running of tests.
|
||||
|
||||
\todo Improve the output stream code by providing a filtering stream.
|
||||
*/
|
||||
class SG_EXPORT TestContext
|
||||
{
|
||||
public:
|
||||
|
||||
TestContext();
|
||||
|
||||
bool shouldStop() { return false; }
|
||||
bool isVerbose() { return true; }
|
||||
|
||||
enum TraceLevel{
|
||||
Off, ///< All tracing turned off
|
||||
Results, ///< Output results only
|
||||
Full ///< Full test diagnostic output
|
||||
};
|
||||
|
||||
void setTraceLevel(TraceLevel tl);
|
||||
TraceLevel getTraceLevel() const;
|
||||
|
||||
std::ostream& tout(TraceLevel tl=Full) const;
|
||||
|
||||
private:
|
||||
|
||||
TestContext(const TestContext&);
|
||||
TestContext operator=(const TestContext&);
|
||||
|
||||
#ifndef DOXYGEN_SHOULD_SKIP_THIS
|
||||
|
||||
class TraceStream{
|
||||
|
||||
public:
|
||||
TraceStream(std::ostream& o=cout, TraceLevel tl=Results);
|
||||
~TraceStream();
|
||||
|
||||
void setTraceLevel(TraceLevel tl);
|
||||
TraceLevel getTraceLevel() const;
|
||||
|
||||
std::ostream& stream(TraceLevel tl);
|
||||
|
||||
private:
|
||||
|
||||
TraceLevel _traceLevel;
|
||||
std::ostream* _outputStreamPtr;
|
||||
std::ofstream _nullStream;
|
||||
};
|
||||
|
||||
#endif /* DOXYGEN_SHOULD_SKIP_THIS */
|
||||
|
||||
mutable TraceStream _tout;
|
||||
|
||||
};
|
||||
|
||||
|
||||
class TestSuite;
|
||||
class TestCase;
|
||||
|
||||
/**
|
||||
Visits while maintaining the current hierarchical context. Also allows
|
||||
the traversal to be short-cicuited at any point during the visitation.
|
||||
*/
|
||||
class TestVisitor
|
||||
{
|
||||
public:
|
||||
|
||||
//..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 Composite
|
||||
virtual bool visitLeave( TestSuite* ) { return true; }
|
||||
protected:
|
||||
|
||||
TestVisitor() {}
|
||||
TestVisitor( const TestVisitor& ) {}
|
||||
virtual ~TestVisitor() {}
|
||||
};
|
||||
|
||||
/**
|
||||
TestCase, is the supplies the interface for a Composite pattern's
|
||||
\em leaf class, though it is not a leaf in itself.
|
||||
*/
|
||||
class TestCase : public Test
|
||||
{
|
||||
public:
|
||||
|
||||
typedef TestContext Context; // Test in TestContext? is redundant
|
||||
|
||||
TestCase( const std::string& sName ) : Test( sName ) {}
|
||||
|
||||
virtual bool accept( Visitor& v ) { return v.visit( this ); }
|
||||
|
||||
virtual void run( const Context& ) = 0; // Subclass OSGUTX_EXPORT Responsibility
|
||||
};
|
||||
|
||||
/**
|
||||
Base class catchable for the exception's which may be thrown to
|
||||
indicate problems during the run of a TestCase.
|
||||
*/
|
||||
class TestX
|
||||
{
|
||||
public:
|
||||
|
||||
TestX(const std::string& s):_what(s) {}
|
||||
virtual ~TestX() {}
|
||||
|
||||
const std::string& what() const { return _what; }
|
||||
|
||||
private:
|
||||
std::string _what;
|
||||
};
|
||||
|
||||
/**
|
||||
A TestFailureX indicates a failure in the tested component.
|
||||
*/
|
||||
class TestFailureX: public TestX
|
||||
{
|
||||
public:
|
||||
TestFailureX(const std::string& s):TestX(s) {}
|
||||
};
|
||||
|
||||
/**
|
||||
A TestErrorX indicates an error while testing a component,
|
||||
which prevents the test from being run; it does not indicate
|
||||
a problem with the component, but rather a problem during the
|
||||
run which prevents the component from being tested.
|
||||
*/
|
||||
class TestErrorX: public TestX
|
||||
{
|
||||
public:
|
||||
TestErrorX(const std::string& s):TestX(s) {}
|
||||
};
|
||||
|
||||
/**
|
||||
TestCase_ is a class template for a leaf TestCase, which allows TestFixture
|
||||
classes to be easily collected into the tree of tests, and have their public
|
||||
test methods called. It is worth noting that, for a given TestCase_, an
|
||||
instance of the test fixture class will be constructed pior to the
|
||||
test method being called, and destructed afterwards. This prevents 'leakage'
|
||||
of information from one test case to the next.
|
||||
*/
|
||||
template< typename FixtureT >
|
||||
class TestCase_ : public TestCase
|
||||
{
|
||||
typedef void (FixtureT::*TestMethodPtr)( const Context& );
|
||||
|
||||
public:
|
||||
|
||||
// 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 );
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
TestMethodPtr _pTestMethod;
|
||||
};
|
||||
|
||||
/**
|
||||
A TestSuite is the \em composite component of the Composite pattern,
|
||||
and allows aggregation of Tests into hierarchies.
|
||||
*/
|
||||
class SG_EXPORT TestSuite : public Test
|
||||
{
|
||||
public:
|
||||
|
||||
TestSuite( const std::string& name );
|
||||
|
||||
/** 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);
|
||||
|
||||
virtual bool accept( Test::Visitor& v );
|
||||
|
||||
private:
|
||||
|
||||
typedef std::vector< osg::ref_ptr<Test> > Tests;
|
||||
Tests _tests; // Collection of Suites and/or Cases
|
||||
};
|
||||
|
||||
/**
|
||||
TestGraph is a singleton providing central access to the tree of tests;
|
||||
primarily, it provides access to the root suite.
|
||||
*/
|
||||
class TestGraph
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
static TestGraph& instance();
|
||||
|
||||
/**
|
||||
@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.
|
||||
|
||||
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.
|
||||
|
||||
|
||||
@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(
|
||||
list<std::string>::iterator it,
|
||||
list<std::string>::iterator end,
|
||||
TestSuite* tsuite, bool createIfNecessary);
|
||||
|
||||
TestGraph();
|
||||
|
||||
TestGraph(const TestGraph&);
|
||||
TestGraph& operator=(const TestGraph&);
|
||||
|
||||
osg::ref_ptr<TestSuite> root_;
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
Maintains a string that when accessed in the "visit" member, returns the
|
||||
current qualified TestSuite path.
|
||||
*/
|
||||
class SG_EXPORT TestQualifier : public TestVisitor
|
||||
{
|
||||
enum { SEPCHAR = '.' };
|
||||
|
||||
public:
|
||||
|
||||
// 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 );
|
||||
|
||||
// Provide read-only access to the current qualifier
|
||||
const string& currentPath() const;
|
||||
|
||||
private:
|
||||
|
||||
std::string _path; // Current qualifier
|
||||
};
|
||||
|
||||
/**
|
||||
QualifiedTestPrinter prints to standard output a list of fully
|
||||
qualified tests.
|
||||
*/
|
||||
class SG_EXPORT QualifiedTestPrinter : public TestQualifier
|
||||
{
|
||||
public:
|
||||
|
||||
|
||||
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.
|
||||
*/
|
||||
class SG_EXPORT TestRecord
|
||||
{
|
||||
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);
|
||||
|
||||
// Default copy construction and assignment are OK
|
||||
|
||||
// FIXME: Add accessors?
|
||||
|
||||
private:
|
||||
|
||||
// Onlye a TestReport can create a TestRecord
|
||||
friend class TestReport;
|
||||
TestRecord(const string& name);
|
||||
|
||||
enum Result{
|
||||
Success,Failure,Error
|
||||
};
|
||||
|
||||
friend std::ostream& operator<<(std::ostream& o,const TestRecord& tr);
|
||||
|
||||
static osg::Timer timer_; // To time tests
|
||||
|
||||
std::string name_;
|
||||
osg::Timer_t start_;
|
||||
osg::Timer_t stop_;
|
||||
Result result_;
|
||||
std::string problem_;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
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
|
||||
*/
|
||||
class SG_EXPORT TestReport
|
||||
{
|
||||
public:
|
||||
|
||||
TestRecord& createRecord(const string& s){
|
||||
_records.push_back(TestRecord(s));
|
||||
return _records.back();
|
||||
}
|
||||
|
||||
private:
|
||||
list<TestRecord> _records;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
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.
|
||||
*/
|
||||
class SG_EXPORT TestRunner : public TestQualifier
|
||||
{
|
||||
public:
|
||||
|
||||
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 string& sQualifiedName );
|
||||
|
||||
bool visitEnter( TestSuite* pSuite );
|
||||
bool visit( TestCase* pTest );
|
||||
bool visitLeave( TestSuite* pSuite );
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
void perform( TestCase* pTest );
|
||||
|
||||
private:
|
||||
|
||||
TestReport _db; // Results
|
||||
TestContext& _ctx; // The Global Testing Context
|
||||
std::vector<std::string> _tests; // Specified Tests
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
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 );
|
||||
|
||||
|
||||
|
||||
/**
|
||||
Adds a test case to a suite object being created in a TestSuite singleton function.
|
||||
@see OSGUTX_BEGIN_TESTSUITE, OSGUTX_END_TESTSUITE
|
||||
*/
|
||||
#define OSGUTX_ADD_TESTCASE( 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(); \
|
||||
}
|
||||
|
||||
/** Define a TestSuite accessor */
|
||||
#define OSGUTX_TESTSUITE( tsuite ) \
|
||||
tsuite##_TestSuite()
|
||||
|
||||
|
||||
/**
|
||||
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() );
|
||||
|
||||
|
||||
/** Autoregister a testsuite with the root suite at startup */
|
||||
#define OSGUTX_AUTOREGISTER_TESTSUITE( tsuite ) \
|
||||
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 );
|
||||
|
||||
namespace osgUtx{
|
||||
|
||||
/**
|
||||
A helper struct to perform automatic registration at program startup; not for
|
||||
direct use, it should be used via the following macros. (It's a secret agent :-)
|
||||
|
||||
@see OSGUTX_AUTOREGISTER_TESTSUITE, OSGUTX_AUTOREGISTER_TESTSUITE_AT
|
||||
*/
|
||||
struct TestSuiteAutoRegistrationAgent
|
||||
{
|
||||
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 );
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
regSuite->add(tsuite);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
OSGUTX_TEST_F is a convenience macro, analogous to assert(), which will
|
||||
throw an osgUtx::TestFailureX if \em expr evaluates to false; this should be
|
||||
used to test for failure in a given test, as opposed to an actual error
|
||||
in the test owing to some other reason than the tested code being faulty.
|
||||
|
||||
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__<<ends; \
|
||||
throw osgUtx::TestFailureX(ss.str()); \
|
||||
}
|
||||
|
||||
/**
|
||||
OSGUTX_TEST_E is a convenience macro, analogous to assert(), which will
|
||||
throw an osgUtx::TestErrorX if \em expr evaluates to false; this should be
|
||||
used to test for an error in a given test, as opposed to a failure
|
||||
in the tested code.
|
||||
|
||||
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__<<ends; \
|
||||
throw osgUtx::TestErrorX(ss.str()); \
|
||||
}
|
||||
|
||||
|
||||
#endif // OSG_UNITTESTFRAMEWORK
|
16
src/Demos/osgunittests/Makefile
Normal file
16
src/Demos/osgunittests/Makefile
Normal file
@ -0,0 +1,16 @@
|
||||
TOPDIR = ../../..
|
||||
include $(TOPDIR)/Make/makedefs
|
||||
|
||||
CXXFILES =\
|
||||
osgunittests.cpp\
|
||||
|
||||
LIBS += $(OSG_LIBS) $(GLUT_LIB) $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS)
|
||||
|
||||
INSTFILES = \
|
||||
$(CXXFILES)\
|
||||
Makefile.inst=Makefile
|
||||
|
||||
EXEC = osgunittests
|
||||
|
||||
include $(TOPDIR)/Make/makerules
|
||||
|
12
src/Demos/osgunittests/Makefile.inst
Normal file
12
src/Demos/osgunittests/Makefile.inst
Normal file
@ -0,0 +1,12 @@
|
||||
TOPDIR = ../..
|
||||
include $(TOPDIR)/Make/makedefs
|
||||
|
||||
CXXFILES =\
|
||||
osgunittests.cpp\
|
||||
|
||||
LIBS += $(OSG_LIBS) $(GLUT_LIB) $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS)
|
||||
|
||||
EXEC = osgunittests
|
||||
|
||||
|
||||
include $(TOPDIR)/Make/makerules
|
23
src/Demos/osgunittests/osgunittests.cpp
Normal file
23
src/Demos/osgunittests/osgunittests.cpp
Normal file
@ -0,0 +1,23 @@
|
||||
#include <osg/UnitTestFramework>
|
||||
|
||||
|
||||
int main( int /*argc*/, char** /*argv*/ )
|
||||
{
|
||||
// cout<<"***** Qualified Tests ******"<<endl;
|
||||
//
|
||||
// osgUtx::QualifiedTestPrinter printer;
|
||||
// osgUtx::TestGraph::instance().root()->accept( printer );
|
||||
//
|
||||
|
||||
cout<<endl;
|
||||
cout<<"****** Running tests ******"<<endl;
|
||||
|
||||
// Global Data or Context
|
||||
osgUtx::TestContext ctx;
|
||||
osgUtx::TestRunner runner( ctx );
|
||||
runner.specify("root");
|
||||
|
||||
osgUtx::TestGraph::instance().root()->accept( runner );
|
||||
|
||||
return 0;
|
||||
}
|
@ -82,7 +82,9 @@ CXXFILES =\
|
||||
TextureCubeMap.cpp\
|
||||
Timer.cpp\
|
||||
Transform.cpp\
|
||||
UnitTestFramework.cpp\
|
||||
Version.cpp\
|
||||
Vec3.cpp\
|
||||
Viewport.cpp\
|
||||
|
||||
DEF += -DSG_LIBRARY
|
||||
|
383
src/osg/UnitTestFramework.cpp
Normal file
383
src/osg/UnitTestFramework.cpp
Normal file
@ -0,0 +1,383 @@
|
||||
#include <osg/UnitTestFramework>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace osgUtx
|
||||
{
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TestContext::TestContext()
|
||||
{
|
||||
}
|
||||
|
||||
void TestContext::setTraceLevel(TraceLevel tl)
|
||||
{
|
||||
_tout.setTraceLevel(tl);
|
||||
}
|
||||
|
||||
TestContext::TraceLevel TestContext::getTraceLevel() const
|
||||
{
|
||||
return _tout.getTraceLevel();
|
||||
}
|
||||
|
||||
std::ostream& TestContext::tout(TraceLevel tl=Full) const
|
||||
{
|
||||
return _tout.stream(tl);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
TestContext::TraceStream::TraceStream(std::ostream& o, TraceLevel tl):
|
||||
_traceLevel(tl),
|
||||
_outputStreamPtr(&o),
|
||||
#if defined(WIN32) && !(defined(__CYGWIN__) || defined(__MINGW32__))
|
||||
_nullStream("nul")
|
||||
#else
|
||||
_nullStream("/dev/null")
|
||||
#endif
|
||||
{
|
||||
}
|
||||
|
||||
TestContext::TraceStream::~TraceStream()
|
||||
{
|
||||
_nullStream.close();
|
||||
}
|
||||
|
||||
void TestContext::TraceStream::setTraceLevel(TraceLevel tl)
|
||||
{
|
||||
_traceLevel = tl;
|
||||
}
|
||||
|
||||
TestContext::TraceLevel TestContext::TraceStream::getTraceLevel() const
|
||||
{
|
||||
return _traceLevel;
|
||||
}
|
||||
|
||||
std::ostream& TestContext::TraceStream::stream(TestContext::TraceLevel tl)
|
||||
{
|
||||
if(_traceLevel >= tl){
|
||||
return *_outputStreamPtr;
|
||||
}
|
||||
return _nullStream;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TestGraph& TestGraph::instance()
|
||||
{
|
||||
static TestGraph instance_;
|
||||
return instance_;
|
||||
}
|
||||
|
||||
TestSuite* TestGraph::root()
|
||||
{
|
||||
return root_.get();
|
||||
}
|
||||
|
||||
TestSuite* TestGraph::suite(const std::string& path, TestSuite* tsuite, bool createIfNecessary)
|
||||
{
|
||||
using namespace std;
|
||||
|
||||
list<string> pathComponents;
|
||||
|
||||
string::const_iterator it1 = path.begin();
|
||||
string::const_iterator it2 = it1;
|
||||
|
||||
// Dissect the path into it's constituent components
|
||||
do{
|
||||
|
||||
while( *it2 != '.' && it2 != path.end() ) ++it2;
|
||||
|
||||
// Consider a check for "" empty strings?
|
||||
pathComponents.push_back( string(it1,it2) );
|
||||
|
||||
if( it2 != path.end()) ++it2;
|
||||
|
||||
it1 = it2;
|
||||
|
||||
}while( it2 != path.end());
|
||||
|
||||
return suite(pathComponents.begin(), pathComponents.end(),
|
||||
tsuite, createIfNecessary);
|
||||
|
||||
}
|
||||
|
||||
TestSuite* TestGraph::suite(
|
||||
list<std::string>::iterator it,
|
||||
list<std::string>::iterator end,
|
||||
TestSuite* tsuite, bool createIfNecessary)
|
||||
{
|
||||
using namespace std;
|
||||
|
||||
if( ! tsuite) tsuite = root();
|
||||
|
||||
// Make sure these tie up
|
||||
if(*it != tsuite->name()) return 0;
|
||||
|
||||
++it;
|
||||
if(it == end) return tsuite;
|
||||
|
||||
Test* child = tsuite->findChild(*it);
|
||||
|
||||
if(child){
|
||||
|
||||
// We've found a child with the right name. But is it a
|
||||
// test suite?
|
||||
|
||||
if(TestSuite* childSuite = dynamic_cast<TestSuite*>(child)){
|
||||
return suite(it, end, childSuite, createIfNecessary);
|
||||
}
|
||||
|
||||
// We could return 0 here, to indicate that someone is
|
||||
// trying to add a TestSuite named 'xxx' to a suite with a
|
||||
// Test already named 'xxx'. But we don't enforce uniqueness
|
||||
// the other way round, so we don't do it this way round
|
||||
// either. Carry on as normal, and create a TestSuite of
|
||||
// the same name if createIfNecessary is true.
|
||||
|
||||
}
|
||||
|
||||
if(createIfNecessary){
|
||||
|
||||
TestSuite* childSuite = new TestSuite(*it);
|
||||
tsuite->add(childSuite);
|
||||
return suite(it, end, childSuite, createIfNecessary);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
TestGraph::TestGraph(): root_(new TestSuite("root"))
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool TestQualifier::visitEnter( TestSuite* pSuite )
|
||||
{
|
||||
_path.append( pSuite->name() );
|
||||
_path += SEPCHAR;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Leaving a composite: Pop its name from the Path
|
||||
bool TestQualifier::visitLeave( TestSuite* pSuite )
|
||||
{
|
||||
assert( _path.rfind( pSuite->name() + static_cast<const char>(SEPCHAR))
|
||||
== _path.size() - pSuite->name().size() - 1);
|
||||
|
||||
_path.erase( _path.size() - pSuite->name().size() -1 );
|
||||
return true;
|
||||
}
|
||||
|
||||
// Provide read-only access to the current qualifier
|
||||
const string& TestQualifier::currentPath() const
|
||||
{
|
||||
return _path;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
osg::Timer TestRecord::timer_;
|
||||
|
||||
void TestRecord::start()
|
||||
{
|
||||
start_ = timer_.tick();
|
||||
}
|
||||
|
||||
void TestRecord::stop()
|
||||
{
|
||||
stop_ = timer_.tick();
|
||||
}
|
||||
|
||||
void TestRecord::log(const TestFailureX& e)
|
||||
{
|
||||
stop();
|
||||
result_ = Failure;
|
||||
problem_ = e.what();
|
||||
}
|
||||
|
||||
void TestRecord::log(const TestErrorX& e)
|
||||
{
|
||||
stop();
|
||||
result_ = Error;
|
||||
problem_ = e.what();
|
||||
}
|
||||
|
||||
void TestRecord::log(const std::exception& e)
|
||||
{
|
||||
stop();
|
||||
result_ = Error;
|
||||
problem_ = e.what();
|
||||
}
|
||||
|
||||
void TestRecord::log(const std::string& s)
|
||||
{
|
||||
stop();
|
||||
result_ = Error;
|
||||
problem_ = s;
|
||||
}
|
||||
|
||||
TestRecord::TestRecord(const string& name):
|
||||
name_(name),
|
||||
start_(0),
|
||||
stop_(0),
|
||||
result_(Success),
|
||||
problem_("No problem")
|
||||
{
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& o,const TestRecord& tr)
|
||||
{
|
||||
if(tr.result_ == TestRecord::Success) o<<"pass";
|
||||
else if(tr.result_ == TestRecord::Failure) o<<"fail";
|
||||
else o<<"error";
|
||||
|
||||
o<<"\t"<<tr.name_;
|
||||
|
||||
|
||||
//o<<tr.start_<<'\t'<<tr.stop_<<'\t'<<TestRecord::timer_.delta_s(tr.start_,tr.stop_);
|
||||
|
||||
// Just print out the duration
|
||||
o<<'\t'<<TestRecord::timer_.delta_s(tr.start_,tr.stop_)<<'s';
|
||||
|
||||
if(tr.result_ != TestRecord::Success){
|
||||
o<<'\t'<<tr.problem_;
|
||||
}
|
||||
|
||||
return o;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TestRunner::TestRunner( TestContext& ctx ) : _ctx( ctx )
|
||||
{
|
||||
}
|
||||
|
||||
void TestRunner::specify( const string& sQualifiedName )
|
||||
{
|
||||
_tests.push_back( sQualifiedName );
|
||||
}
|
||||
|
||||
bool TestRunner::visitEnter( TestSuite* pSuite )
|
||||
{
|
||||
TestQualifier::visitEnter( pSuite );
|
||||
return !_ctx.shouldStop();
|
||||
}
|
||||
|
||||
#ifndef DOXYGEN_SHOULD_SKIP_THIS
|
||||
|
||||
namespace{
|
||||
|
||||
struct isSpecified{
|
||||
|
||||
const std::string& pTestName_;
|
||||
|
||||
isSpecified(const std::string& s): pTestName_(s) {}
|
||||
|
||||
bool operator()(const std::string& specifiedTest){
|
||||
return pTestName_.find(specifiedTest) == 0;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif /* DOXYGEN_SHOULD_SKIP_THIS */
|
||||
|
||||
bool TestRunner::visit( TestCase* pTest )
|
||||
{
|
||||
if ( std::find_if(_tests.begin(),_tests.end(),
|
||||
isSpecified(currentPath() + pTest->name() ) ) != _tests.end()) perform( pTest );
|
||||
|
||||
return !_ctx.shouldStop();
|
||||
}
|
||||
|
||||
bool TestRunner::visitLeave( TestSuite* pSuite )
|
||||
{
|
||||
TestQualifier::visitLeave( pSuite );
|
||||
return !_ctx.shouldStop();
|
||||
}
|
||||
|
||||
void TestRunner::perform( TestCase* pTest )
|
||||
{
|
||||
TestRecord& record = _db.createRecord( currentPath() + pTest->name() );
|
||||
|
||||
try
|
||||
{
|
||||
record.start();
|
||||
pTest->run( _ctx );
|
||||
record.stop();
|
||||
}
|
||||
|
||||
catch ( const TestFailureX& e )
|
||||
{
|
||||
record.log( e );
|
||||
}
|
||||
catch ( const TestErrorX& e )
|
||||
{
|
||||
record.log( e );
|
||||
}
|
||||
catch ( const std::exception& e )
|
||||
{
|
||||
record.log( e );
|
||||
}
|
||||
catch ( ... )
|
||||
{
|
||||
record.log( "Unknown" );
|
||||
}
|
||||
|
||||
|
||||
_ctx.tout(TestContext::Results) << record << std::endl;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TestSuite::TestSuite( const std::string& name ) : Test( name )
|
||||
{
|
||||
}
|
||||
|
||||
void TestSuite::add( Test* pTest )
|
||||
{
|
||||
_tests.push_back( pTest );
|
||||
}
|
||||
|
||||
Test* TestSuite::findChild(const std::string& name)
|
||||
{
|
||||
for(Tests::iterator it = _tests.begin();
|
||||
it != _tests.end();
|
||||
++it){
|
||||
|
||||
if ((*it)->name() == name) return (*it).get();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool TestSuite::accept( Test::Visitor& v )
|
||||
{
|
||||
if ( v.visitEnter( this ) )
|
||||
{
|
||||
Tests::iterator end = _tests.end();
|
||||
for ( Tests::iterator at = _tests.begin(); at != end; ++at )
|
||||
if ( !(*at)->accept( v ) )
|
||||
break;
|
||||
}
|
||||
|
||||
return v.visitLeave( this ); // continue with siblings?
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool QualifiedTestPrinter::visit( TestCase* pTest )
|
||||
{
|
||||
std::cout << currentPath() + pTest->name() << std::endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
};
|
70
src/osg/Vec3.cpp
Normal file
70
src/osg/Vec3.cpp
Normal file
@ -0,0 +1,70 @@
|
||||
// Vec3 is implemented entirely in the header. This .cpp file just
|
||||
// contains utx test code
|
||||
|
||||
#ifdef OSG_COMPILE_UNIT_TESTS
|
||||
|
||||
#include <osg/Vec3>
|
||||
#include <osg/UnitTestFramework>
|
||||
|
||||
#include <sstream>
|
||||
|
||||
namespace osg
|
||||
{
|
||||
|
||||
class Vec3TestFixture
|
||||
{
|
||||
public:
|
||||
|
||||
Vec3TestFixture();
|
||||
|
||||
void testAddition(const osgUtx::TestContext& ctx);
|
||||
void testSubtraction(const osgUtx::TestContext& ctx);
|
||||
void testScalarMultiplication(const osgUtx::TestContext& ctx);
|
||||
void testDotProduct(const osgUtx::TestContext& ctx);
|
||||
|
||||
private:
|
||||
|
||||
// Some convenience variables for use in the tests
|
||||
Vec3 v1_, v2_, v3_;
|
||||
|
||||
};
|
||||
|
||||
Vec3TestFixture::Vec3TestFixture():
|
||||
v1_(1.0f, 1.0f, 1.0f),
|
||||
v2_(2.0f, 2.0f, 2.0f),
|
||||
v3_(3.0f, 3.0f, 3.0f)
|
||||
{
|
||||
}
|
||||
|
||||
void Vec3TestFixture::testAddition(const osgUtx::TestContext&)
|
||||
{
|
||||
OSGUTX_TEST_F( v1_ + v2_ == v3_ )
|
||||
}
|
||||
|
||||
void Vec3TestFixture::testSubtraction(const osgUtx::TestContext&)
|
||||
{
|
||||
OSGUTX_TEST_F( v3_ - v1_ == v2_ )
|
||||
}
|
||||
|
||||
void Vec3TestFixture::testScalarMultiplication(const osgUtx::TestContext&)
|
||||
{
|
||||
OSGUTX_TEST_F( v1_ * 3 == v3_ )
|
||||
}
|
||||
|
||||
void Vec3TestFixture::testDotProduct(const osgUtx::TestContext&)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
OSGUTX_BEGIN_TESTSUITE(Vec3)
|
||||
OSGUTX_ADD_TESTCASE(Vec3TestFixture, testAddition)
|
||||
OSGUTX_ADD_TESTCASE(Vec3TestFixture, testSubtraction)
|
||||
OSGUTX_ADD_TESTCASE(Vec3TestFixture, testScalarMultiplication)
|
||||
OSGUTX_ADD_TESTCASE(Vec3TestFixture, testDotProduct)
|
||||
OSGUTX_END_TESTSUITE
|
||||
|
||||
OSGUTX_AUTOREGISTER_TESTSUITE_AT(Vec3, root.osg)
|
||||
|
||||
}
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user