void unit_test::run( std::map<std::string,std::function<void(void)>>::iterator &it ) { precondition( it != _tests.end(), "invalid test" ); // Make sure we are not already running... const std::string &n = it->first; if ( std::find( _running.begin(), _running.end(), n ) == _running.end() ) _running.emplace_back( n ); else throw_runtime( "recursive tests not allowed: {0}", infix_separated( ", ", _running ) ); on_scope_exit { _running.erase( std::remove( _running.begin(), _running.end(), n ), _running.end() ); }; // Already completed if ( _success.find( n ) != _success.end() ) return; if ( _failure.find( n ) != _failure.end() ) throw_runtime( "test '{0}' has failed", n ); // Run the test size_t failures = _failure.size(); try { it->second(); } catch ( std::exception &e ) { std::stringstream tmp; base::print_exception( tmp, e ); std::vector<std::string> lines; base::split( tmp.str(), '\n', std::back_inserter( lines ), true ); for ( auto &l: lines ) message( l ); failure( std::string( e.what() ) ); } if ( failures != _failure.size() ) _failure.insert( n ); else _success.insert( n ); }