#include #include #include #include #include #include #include #include Bu::Blob getSuiteName( const Bu::Blob &bSuiteExec ) { Bu::Process proc( Bu::Process::StdOut, bSuiteExec.getData(), bSuiteExec.getData(), "--print-name", NULL ); Bu::String sResult = proc.readAll().trimWhitespace(); Bu::Blob bRet( sResult.getStr(), sResult.getSize() ); return bRet; } Bu::Json *runSuite( const Bu::Blob &bSuiteExec ) { Bu::Process proc( Bu::Process::StdOut, bSuiteExec.getData(), bSuiteExec.getData(), "--interop", NULL ); Bu::BlobBuilder bbReport; while( proc.isRunning() ) { int iRead = 0; char dRead[4096]; iRead = proc.read( dRead, 4096 ); if( iRead > 0 ) { bbReport.append( dRead, iRead ); } } Bu::Json *pReport = new Bu::Json(); pReport->parse( bbReport.getBlob() ); return pReport; } typedef Bu::List BlobList; BlobList getSuitePaths( const Bu::Blob &bDir ) { BlobList lPaths; DIR *dir = opendir( bDir.getData() ); if( dir == NULL ) { Bu::println("Could not open directory: %1").arg( bDir ); return lPaths; } struct dirent *de = NULL; while( (de = readdir( dir )) != NULL ) { if( de->d_type != DT_REG ) continue; Bu::BlobBuilder bbPath; bbPath.append( bDir ); bbPath.append("/"); bbPath.append( de->d_name ); Bu::Blob bPath = bbPath.getBlob(); if( access( bPath.getData(), X_OK ) != 0 ) continue; lPaths.append( bPath ); } closedir( dir ); return lPaths; } int main( int /*argc*/, char * /*argv*/[] ) { Bu::Blob bDir("unit"); BlobList lPaths = getSuitePaths( bDir ); int iNumLen = Bu::String("%1").arg( lPaths.getSize() ).end().getSize(); int iMaxSuiteName = 0; Bu::Hash hName; for( BlobList::iterator i = lPaths.begin(); i; i++ ) { Bu::Blob bSuiteName = getSuiteName( *i ); if( iMaxSuiteName < bSuiteName.getSize() ) iMaxSuiteName = bSuiteName.getSize(); hName.insert( *i, bSuiteName ); } Bu::List lReport; int iTest = 0; for( BlobList::iterator i = lPaths.begin(); i; i++ ) { iTest++; Bu::Blob bSuiteName = hName.get( *i ); Bu::print("\rRunning test suite [%1/%2]: %3") .arg( iTest, Bu::Fmt().width( iNumLen ).right() ) .arg( lPaths.getSize(), Bu::Fmt().width( iNumLen ) ) .arg( bSuiteName, Bu::Fmt().width( iMaxSuiteName ).fill(' ').left() ); Bu::sio << Bu::sio.flush; Bu::Json *pReport = runSuite( (*i) ); int iUnexpected = 0; int iTotal = 0; iTotal = (*pReport)["tests"].getSize(); for( int j = 0; j < iTotal; j++ ) { if( !((*pReport)["tests"][j]["expected"].getString() == (*pReport)["tests"][j]["result"].getString()) ) { iUnexpected++; } } if( iUnexpected == 0 ) { delete pReport; } else { lReport.append( pReport ); } } Bu::println("\rCompleted %1 unit test suites.%2") .arg( lPaths.getSize(), Bu::Fmt().width( iNumLen ) ) .arg( Bu::Blob(""), Bu::Fmt().width( iMaxSuiteName ).fill(' ').left() ); if( lReport.getSize() == 0 ) { Bu::println("\nNothing unexpected in unit tests."); } else { for( Bu::List::iterator i = lReport.begin(); i; i++ ) { Bu::println("\nUnexpected results in: %1") .arg( (**i)["suite"].getString().get() ); for( Bu::Json::iterator iTest = (**i)["tests"].begin(); iTest; iTest++ ) { if( (**iTest)["expected"].getString() == (**iTest)["result"].getString() ) { continue; } Bu::println(" %1: unexpected %2") .arg( (**iTest)["name"].getString().get() ) .arg( (**iTest)["result"].getString().get() ); if( (**iTest).has("fail") ) { if( (**iTest)["fail"].has("action") ) { Bu::println(" unitTest( %1 );") .arg( (**iTest)["fail"]["action"].getString().get() ); Bu::println(" at %1:%2") .arg( (**iTest)["fail"]["file"].getString().get() ) .arg( (int)(**iTest)["fail"]["line"].getNumber() ); } else if( (**iTest)["fail"].has("what") ) { Bu::println(" Unexpected exception: %1") .arg( (**iTest)["fail"]["what"].getString().get() ); } } else { Bu::println(" No further details."); } } delete *i; } } return 0; }