You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
270 lines
8.7 KiB
270 lines
8.7 KiB
//========= Copyright Valve Corporation, All rights reserved. ============// |
|
// |
|
// Purpose: |
|
// |
|
// $NoKeywords: $ |
|
// |
|
//=============================================================================// |
|
|
|
#ifndef UNITLIB_H |
|
#define UNITLIB_H |
|
|
|
#ifdef _WIN32 |
|
#pragma once |
|
#endif |
|
|
|
#include "tier0/platform.h" |
|
#include "tier1/interface.h" |
|
#include "appframework/IAppSystem.h" |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Usage model for the UnitTest library |
|
// |
|
// The general methodology here is that clients are expected to create unit |
|
// test DLLs that statically link to the unit test DLL and which implement |
|
// tests of various libraries. The unit test application will dynamically |
|
// load all DLLs in a directory, which causes them to install their test cases |
|
// into the unit test system. The application then runs through all tests and |
|
// executes them all, displaying the results. |
|
// |
|
// *** NOTE: The test suites are compiled in both debug and release builds, |
|
// even though it's expected to only be useful in debug builds. This is because |
|
// I couldn't come up with a good way of disabling the code in release builds. |
|
// (The only options I could come up with would still compile in the functions, |
|
// just not install them into the unit test library, or would make it so that |
|
// you couldn't step through the unit test code). |
|
// |
|
// Even though this is the case, there's no reason not to add test cases |
|
// directly into your shipping DLLs, as long as you surround the code with |
|
// #ifdef _DEBUG. To error check a project to make sure it's not compiling |
|
// in unit tests in Release build, just don't link in unitlib.lib in Release. |
|
// You can of course also put your test suites into separate DLLs. |
|
// |
|
// All tests inherit from the ITestCase interface. There are two major kinds |
|
// of tests; the first is a single test case meant to run a piece of |
|
// code and check its results match expected values using the Assert macros. |
|
// The second kind is a test suite which is simply a list of other tests. |
|
// |
|
// The following classes and macros are used to easily create unit test cases |
|
// and suites: |
|
// |
|
// Use DEFINE_TESTSUITE to define a particular test suite, and DEFINE_TESTCASE |
|
// to add as many test cases as you like to that test suite, as follows: |
|
// |
|
// DEFINE_TESTSUITE( VectorTestSuite ) |
|
// |
|
// DEFINE_TESTCASE( VectorAdditionTest, VectorTestSuite ) |
|
// { |
|
// .. test code here .. |
|
// } |
|
// |
|
// Note that the definition of the test suite can occur in a different file |
|
// as the test case. A link error will occur if the test suite to which a |
|
// test case is added has not been defined. |
|
// |
|
// To create a test case that is not part of a suite, use... |
|
// |
|
// DEFINE_TESTCASE_NOSUITE( VectorAdditionTest ) |
|
// { |
|
// .. test code here .. |
|
// } |
|
// |
|
// You can also create a suite which is a child of another suite using |
|
// |
|
// DEFINE_SUBSUITE( VectorTestSuite, MathTestSuite ) |
|
// |
|
//----------------------------------------------------------------------------- |
|
|
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// dll export stuff |
|
//----------------------------------------------------------------------------- |
|
|
|
#ifdef UNITLIB_DLL_EXPORT |
|
#define UNITLIB_INTERFACE DLL_EXPORT |
|
#define UNITLIB_CLASS_INTERFACE DLL_CLASS_EXPORT |
|
#define UNITLIB_GLOBAL_INTERFACE DLL_GLOBAL_EXPORT |
|
#else |
|
#define UNITLIB_INTERFACE DLL_IMPORT |
|
#define UNITLIB_CLASS_INTERFACE DLL_CLASS_IMPORT |
|
#define UNITLIB_GLOBAL_INTERFACE DLL_GLOBAL_IMPORT |
|
#endif |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// All unit test libraries can be asked for a unit test |
|
// AppSystem to perform connection |
|
//----------------------------------------------------------------------------- |
|
#define UNITTEST_INTERFACE_VERSION "UnitTestV001" |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// |
|
// NOTE: All classes and interfaces below you shouldn't use directly. |
|
// Use the DEFINE_TESTSUITE and DEFINE_TESTCASE macros instead. |
|
// |
|
//----------------------------------------------------------------------------- |
|
|
|
//----------------------------------------------------------------------------- |
|
// Test case + suite interface |
|
//----------------------------------------------------------------------------- |
|
class ITestCase |
|
{ |
|
public: |
|
// This returns the test name |
|
virtual char const* GetName() = 0; |
|
|
|
// This runs the test |
|
virtual void RunTest() = 0; |
|
}; |
|
|
|
class ITestSuite : public ITestCase |
|
{ |
|
public: |
|
// Add a test to the suite... |
|
virtual void AddTest( ITestCase* pTest ) = 0; |
|
}; |
|
|
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// This is the main function exported by the unit test library used by |
|
// unit test DLLs to install their test cases into a list to be run |
|
//----------------------------------------------------------------------------- |
|
UNITLIB_INTERFACE void UnitTestInstallTestCase( ITestCase* pTest ); |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// These are the methods used by the unit test running program to run all tests |
|
//----------------------------------------------------------------------------- |
|
UNITLIB_INTERFACE int UnitTestCount(); |
|
UNITLIB_INTERFACE ITestCase* GetUnitTest( int i ); |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Helper for unit test DLLs to expose IAppSystems |
|
//----------------------------------------------------------------------------- |
|
#define USE_UNITTEST_APPSYSTEM( _className ) \ |
|
static _className s_UnitTest ## _className; \ |
|
EXPOSE_SINGLE_INTERFACE_GLOBALVAR( _className, IAppSystem, UNITTEST_INTERFACE_VERSION, s_UnitTest ## _className ); |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Base class for test cases |
|
//----------------------------------------------------------------------------- |
|
class UNITLIB_CLASS_INTERFACE CTestCase : public ITestCase |
|
{ |
|
public: |
|
CTestCase( char const* pName, ITestSuite* pParent = 0 ); |
|
~CTestCase(); |
|
|
|
// Returns the test name |
|
char const* GetName(); |
|
|
|
private: |
|
char* m_pName; |
|
}; |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Test suite class |
|
//----------------------------------------------------------------------------- |
|
class UNITLIB_CLASS_INTERFACE CTestSuite : public ITestSuite |
|
{ |
|
public: |
|
CTestSuite( char const* pName, ITestSuite* pParent = 0 ); |
|
~CTestSuite(); |
|
|
|
// This runs the test |
|
void RunTest(); |
|
|
|
// Add a test to the suite... |
|
void AddTest( ITestCase* pTest ); |
|
|
|
// Returns the test name |
|
char const* GetName(); |
|
|
|
protected: |
|
int m_TestCount; |
|
ITestCase** m_ppTestCases; |
|
char* m_pName; |
|
}; |
|
|
|
#define TESTSUITE_CLASS( _suite ) \ |
|
class CTS ## _suite : public CTestSuite \ |
|
{ \ |
|
public: \ |
|
CTS ## _suite(); \ |
|
}; |
|
|
|
#define TESTSUITE_ACCESSOR( _suite ) \ |
|
CTS ## _suite* GetTS ## _suite() \ |
|
{ \ |
|
static CTS ## _suite s_TS ## _suite; \ |
|
return &s_TS ## _suite; \ |
|
} |
|
|
|
#define FWD_DECLARE_TESTSUITE( _suite ) \ |
|
class CTS ## _suite; \ |
|
CTS ## _suite* GetTS ## _suite(); |
|
|
|
#define DEFINE_TESTSUITE( _suite ) \ |
|
TESTSUITE_CLASS( _suite ) \ |
|
TESTSUITE_ACCESSOR( _suite ) \ |
|
CTS ## _suite::CTS ## _suite() : CTestSuite( #_suite ) {} |
|
|
|
#define DEFINE_SUBSUITE( _suite, _parent ) \ |
|
TESTSUITE_CLASS( _suite ) \ |
|
TESTSUITE_ACCESSOR( _suite ) \ |
|
FWD_DECLARE_TESTSUITE( _parent ) \ |
|
CTS ## _suite::CTS ## _suite() : CTestSuite( #_suite, GetTS ## _parent() ) {} |
|
|
|
#define TESTCASE_CLASS( _case ) \ |
|
class CTC ## _case : public CTestCase \ |
|
{ \ |
|
public: \ |
|
CTC ## _case (); \ |
|
void RunTest(); \ |
|
}; |
|
|
|
#define DEFINE_TESTCASE_NOSUITE( _case ) \ |
|
TESTCASE_CLASS( _case ) \ |
|
CTC ## _case::CTC ## _case () : CTestCase( #_case ) {} \ |
|
\ |
|
CTC ## _case s_TC ## _case; \ |
|
\ |
|
void CTC ## _case ::RunTest() |
|
|
|
#define DEFINE_TESTCASE( _case, _suite ) \ |
|
TESTCASE_CLASS( _case ) \ |
|
FWD_DECLARE_TESTSUITE( _suite ) \ |
|
CTC ## _case::CTC ## _case () : CTestCase( #_case, GetTS ## _suite() ) {} \ |
|
\ |
|
CTC ## _case s_TC ## _case; \ |
|
\ |
|
void CTC ## _case ::RunTest() |
|
|
|
|
|
#define _Shipping_AssertMsg( _exp, _msg, _executeExp, _bFatal ) \ |
|
do { \ |
|
if (!(_exp)) \ |
|
{ \ |
|
_SpewInfo( SPEW_ASSERT, __TFILE__, __LINE__ ); \ |
|
SpewRetval_t ret = _SpewMessage(_msg); \ |
|
_executeExp; \ |
|
if ( ret == SPEW_DEBUGGER) \ |
|
{ \ |
|
if ( !ShouldUseNewAssertDialog() || DoNewAssertDialog( __TFILE__, __LINE__, _msg ) ) \ |
|
DebuggerBreak(); \ |
|
if ( _bFatal ) \ |
|
_ExitOnFatalAssert( __TFILE__, __LINE__ ); \ |
|
} \ |
|
} \ |
|
} while (0) |
|
|
|
#define Shipping_Assert( _exp ) _Shipping_AssertMsg( _exp, _T("Assertion Failed: ") _T(#_exp), ((void)0), false ) |
|
|
|
|
|
#endif // UNITLIB_H
|
|
|