diff --git a/Testing/TableTest.h b/Testing/TableTest.h new file mode 100644 index 0000000..c33560d --- /dev/null +++ b/Testing/TableTest.h @@ -0,0 +1,117 @@ +static_assert( __cplusplus > 201700, "C++17 Required" ); + +#pragma once + +#include + +#include +#include + +#include +#include + +namespace Alepha::Hydrogen::Testing +{ + inline namespace exports { inline namespace table_test {} } + + namespace detail::table_test + { + inline namespace exports + { + template< auto > struct TableTest; + } + + using namespace Utility::exports::evaluation; + + template< typename RetVal, typename ... Args, RetVal (*function)( Args... ) > + struct exports::TableTest< function > + { + using args_type= std::tuple< Args... >; + + struct Cases + { + using TestDescription= std::tuple< std::string, args_type, RetVal >; + + std::vector< TestDescription > tests; + + explicit + Cases( std::initializer_list< TestDescription > initList ) + : tests( initList ) {} + + int + operator() () const + { + int failureCount= 0; + for( const auto &[ comment, params, expected ]: tests ) + { + if( std::apply( function, params ) != expected ) + { + std::cout << " FAILURE: " << comment << std::endl; + ++failureCount; + } + else std::cout << " SUCCESS: " << comment << std::endl; + } + + return failureCount; + } + }; + + struct VectorCases; + }; + + template< typename RetVal, typename ... Args, RetVal (*function)( Args... ) > + struct TableTest< function >::VectorCases + { + static_assert( sizeof...( Args ) == 1 ); + static_assert( Meta::is_vector_v< RetVal > ); + static_assert( Meta::is_vector_v< std::tuple_element_t< 0, std::tuple< Args... > > > ); + + using TestDescription= std::tuple< std::string, + std::vector< std::pair< typename std::tuple_element_t< 0, std::tuple< Args... > >::value_type, typename RetVal::value_type > > >; + + std::vector< TestDescription > tests; + + explicit + VectorCases( std::initializer_list< TestDescription > initList ) + : tests( initList ) {} + + int + operator() () const + { + int failureCount= 0; + for( const auto &[ comment, productions ]: tests ) + { + const auto expected= evaluate <=[&] + { + std::vector< RetVal > rv; + std::transform( begin( productions ), end( productions ), back_inserter( rv ), + []( const auto &prod ) { return prod.second; } ); + return rv; + }; + + const auto params= evaluate <=[&] + { + std::vector< RetVal > rv; + std::transform( begin( productions ), end( productions ), back_inserter( rv ), + []( const auto &prod ) { return prod.first; } ); + return rv; + }; + + if( std::apply( function, std::tuple{ params } ) != expected ) + { + std::cout << " FAILURE: " << comment << std::endl; + ++failureCount; + } + else std::cout << " SUCCESS: " << comment << std::endl; + } + + return failureCount; + } + }; + } + + namespace exports::table_test + { + using namespace detail::table_test::exports; + } +} diff --git a/Testing/test.cc b/Testing/test.cc index 716f172..b0752e4 100644 --- a/Testing/test.cc +++ b/Testing/test.cc @@ -1,9 +1,12 @@ +static_assert( __cplusplus > 201700, "C++17 Required" ); + #include +#include #include namespace { - namespace UnitTest= Alepha::Testing::exports::testing; + namespace UnitTest= Alepha::Testing::exports; } int @@ -14,8 +17,9 @@ main( const int argcnt, const char *const *const argvec ) namespace { - using namespace UnitTest::literals; using namespace Alepha::Utility::exports::evaluation; + using namespace UnitTest::literals; + using UnitTest::TableTest; auto registration= enroll <=[] { @@ -25,4 +29,11 @@ namespace auto named1= "named.basic.success"_test <= []{}; auto named2= -"named.basic.failure"_test <=[]{ return 1; }; + + int identity( int a ){ return a; } + auto namedTable1= "named.table.success"_test <=TableTest< identity >::Cases + { + { "smoke", { 1 }, 1 }, + //{ "fail", { 2 }, 1 }, + }; }