//========= Copyright Valve Corporation, All rights reserved. ============// // // Purpose: Unit test program // // $NoKeywords: $ //=============================================================================// #include "unitlib/unitlib.h" #include "appframework/IAppSystemGroup.h" #include "appframework/AppFramework.h" #include "tier0/dbg.h" #include #include "vstdlib/iprocessutils.h" #include "tier1/interface.h" #include "vstdlib/cvar.h" #if defined(POSIX) #include #elif defined(WIN32) #pragma warning (disable:4100) #include #endif static int g_TestResult = 0; SpewRetval_t UnitTestSpew( SpewType_t type, char const *pMsg ) { switch( type ) { case SPEW_WARNING: printf( "UnitTest Warning:\n" ); break; case SPEW_ASSERT: printf( "UnitTest Assert:\n" ); g_TestResult = 1; break; case SPEW_ERROR: printf( "UnitTest Error:\n" ); g_TestResult = 1; break; } printf( "%s", pMsg ); if ( Sys_IsDebuggerPresent() ) return ( type == SPEW_ASSERT || type == SPEW_ERROR ) ? SPEW_DEBUGGER : SPEW_CONTINUE; return SPEW_CONTINUE; } //----------------------------------------------------------------------------- // The application object //----------------------------------------------------------------------------- class CUnitTestApp : public CDefaultAppSystemGroup { public: // Methods of IApplication virtual bool Create(); virtual int Main(); virtual void Destroy(); private: }; DEFINE_CONSOLE_STEAM_APPLICATION_OBJECT( CUnitTestApp ); //----------------------------------------------------------------------------- // The application object //----------------------------------------------------------------------------- bool CUnitTestApp::Create() { // Install a special Spew handler that ignores all assertions and lets us // run for as long as possible SpewOutputFunc( UnitTestSpew ); // FIXME: This list of dlls should come from the unittests themselves AppSystemInfo_t appSystems[] = { // { "vstdlib.so", PROCESS_UTILS_INTERFACE_VERSION }, { "", "" } // Required to terminate the list }; if ( !AddSystems( appSystems ) ) return false; // Very simple... just iterate over all .DLLs in the current directory // see if they export UNITTEST_INTERFACE_VERSION. If not, then unload them // just as quick. // We may want to make this more sophisticated, giving it a search path, // or giving test DLLs special extensions, or statically linking the test DLLs // to this program. #ifdef WIN32 WIN32_FIND_DATA findFileData; HANDLE hFind= FindFirstFile("tests/*.dll", &findFileData); while (hFind != INVALID_HANDLE_VALUE) { static char path[2048]; snprintf(path, sizeof(path), "tests/%s", findFileData.cFileName); CSysModule* hLib = Sys_LoadModule(path); if ( hLib ) { CreateInterfaceFn factory = Sys_GetFactory( hLib ); if ( factory && factory( UNITTEST_INTERFACE_VERSION, NULL ) ) { AppModule_t module = LoadModule( factory ); AddSystem( module, UNITTEST_INTERFACE_VERSION ); } else { Sys_UnloadModule( hLib ); } } if (!FindNextFile( hFind, &findFileData )) break; } #elif POSIX DIR *d; struct dirent *dir; d = opendir("tests"); if (d) { while ((dir = readdir(d)) != NULL) { int len = strlen(dir->d_name); if( len > 2 && strcmp(dir->d_name+len-3, ".so") == 0) { static char path[2048]; snprintf(path, sizeof(path), "tests/%s", dir->d_name); CSysModule* hLib = Sys_LoadModule(path); if ( hLib ) { CreateInterfaceFn factory = Sys_GetFactory( hLib ); if ( factory && factory( UNITTEST_INTERFACE_VERSION, NULL ) ) { AppModule_t module = LoadModule( factory ); AddSystem( module, UNITTEST_INTERFACE_VERSION ); } else { Sys_UnloadModule( hLib ); } } } } closedir(d); } #else #error "Implement me!" #endif return true; } void CUnitTestApp::Destroy() { } //----------------------------------------------------------------------------- // The application object //----------------------------------------------------------------------------- int CUnitTestApp::Main() { printf( "Valve Software - unittest (%s)\n", __DATE__ ); int nTestCount = UnitTestCount(); for ( int i = 0; i < nTestCount; ++i ) { ITestCase* pTestCase = GetUnitTest(i); printf("Starting test %s....\n", pTestCase->GetName() ); pTestCase->RunTest(); } return g_TestResult; }