forked from Alepha/Alepha
Testing improvements.
This commit is contained in:
36
Testing/TableTest.cc
Normal file
36
Testing/TableTest.cc
Normal file
@ -0,0 +1,36 @@
|
||||
static_assert( __cplusplus > 2020'99 );
|
||||
|
||||
#include "TableTest.h"
|
||||
|
||||
namespace Alepha::Hydrogen::Testing::detail::TableTest_m
|
||||
{
|
||||
int
|
||||
UniversalCasesBase::operator() () const
|
||||
{
|
||||
int failureCount= 0;
|
||||
for( const auto &[ comment, checker ]: tests )
|
||||
{
|
||||
const auto [result, supplement]= checker( comment );
|
||||
if( result == TestResult::Failed )
|
||||
{
|
||||
++failureCount;
|
||||
std::cout << " " << C::testFail << "FAILED CASE" << resetStyle << ": " << comment << std::endl;
|
||||
if( supplement.has_value() )
|
||||
{
|
||||
std::cout << " " << C::testWarn << "DETAILS" << resetStyle << ": " << supplement.value() << std::endl;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << " " << C::testPass << "PASSED CASE" << resetStyle << ": " << comment << std::endl;
|
||||
if( supplement.has_value() )
|
||||
{
|
||||
std::cout << " " << C::testWarn << "INFO: " << resetStyle << ": " << supplement.value() << std::endl;
|
||||
}
|
||||
}
|
||||
breakpoint();
|
||||
}
|
||||
|
||||
return failureCount;
|
||||
}
|
||||
}
|
@ -15,9 +15,6 @@ static_assert( __cplusplus > 2020'99 );
|
||||
#include <numeric>
|
||||
#include <iomanip>
|
||||
|
||||
#include <boost/core/demangle.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
|
||||
#include <Alepha/function_traits.h>
|
||||
#include <Alepha/template_for_each.h>
|
||||
|
||||
@ -25,6 +22,7 @@ static_assert( __cplusplus > 2020'99 );
|
||||
|
||||
#include <Alepha/Utility/evaluation_helpers.h>
|
||||
#include <Alepha/Utility/TupleAdapter.h>
|
||||
#include <Alepha/Utility/fancyTypeName.h>
|
||||
|
||||
#include <Alepha/Reflection/tuplizeAggregate.h>
|
||||
|
||||
@ -84,7 +82,7 @@ namespace Alepha::Hydrogen::Testing ::detail:: TableTest_m
|
||||
}
|
||||
catch( const std::exception &ex )
|
||||
{
|
||||
return ErrorMessage{ typeid( ex ).name() };
|
||||
return ErrorMessage{ Utility::fancyTypeName( typeid( ex ) ) };
|
||||
}
|
||||
catch( ... )
|
||||
{
|
||||
@ -127,7 +125,7 @@ namespace Alepha::Hydrogen::Testing ::detail:: TableTest_m
|
||||
}
|
||||
catch( const std::exception &ex )
|
||||
{
|
||||
return ErrorMessage{ typeid( ex ).name() };
|
||||
return ErrorMessage{ Utility::fancyTypeName( typeid( ex ) ) };
|
||||
}
|
||||
catch( ... )
|
||||
{
|
||||
@ -160,13 +158,26 @@ namespace Alepha::Hydrogen::Testing ::detail:: TableTest_m
|
||||
{
|
||||
try
|
||||
{
|
||||
std::ignore= invoker();
|
||||
breakpoint();
|
||||
return { TestResult::Failed, std::nullopt };
|
||||
try
|
||||
{
|
||||
std::ignore= invoker();
|
||||
breakpoint();
|
||||
return { TestResult::Failed, IOStreams::String() << "No exception was thrown, but " << Utility::fancyTypeName< T >() << " expected." };
|
||||
}
|
||||
catch( const T & )
|
||||
{
|
||||
return { TestResult::Passed, std::nullopt };
|
||||
}
|
||||
}
|
||||
catch( const T & )
|
||||
catch( const std::exception &ex )
|
||||
{
|
||||
return { TestResult::Passed, std::nullopt };
|
||||
return { TestResult::Failed, IOStreams::String() << "Incorrect exception type " << Utility::fancyTypeName( typeid( ex ) ) << " was thrown, but "
|
||||
<< Utility::fancyTypeName< T >() << " was expected." };
|
||||
}
|
||||
catch( ... )
|
||||
{
|
||||
return { TestResult::Failed, IOStreams::String() << "Incorrect exception type (<Unknown>) was thrown, but "
|
||||
<< Utility::fancyTypeName< T >() << " was expected." };
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -183,9 +194,15 @@ namespace Alepha::Hydrogen::Testing ::detail:: TableTest_m
|
||||
std::ignore= invoker();
|
||||
return { TestResult::Passed, std::nullopt };
|
||||
}
|
||||
catch( const std::exception &ex )
|
||||
{
|
||||
return { TestResult::Failed, IOStreams::String() << "Exception type " << Utility::fancyTypeName( typeid( ex ) ) << " was thrown, but "
|
||||
"no exception was expected." };
|
||||
}
|
||||
catch( ... )
|
||||
{
|
||||
return { TestResult::Failed, std::nullopt };
|
||||
return { TestResult::Failed, IOStreams::String() << "Exception type (<Unknown>) was thrown, but "
|
||||
"no exception was expected." };
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -198,21 +215,34 @@ namespace Alepha::Hydrogen::Testing ::detail:: TableTest_m
|
||||
{
|
||||
try
|
||||
{
|
||||
invoker();
|
||||
return { TestResult::Failed,
|
||||
IOStreams::String{} << "expected exception `" << typeid( T ).name() << "` wasn't thrown." };
|
||||
}
|
||||
catch( const T &ex )
|
||||
{
|
||||
const std::string witness= ex.what();
|
||||
const TestResult rv= witness == expected ? TestResult::Passed : TestResult::Failed;
|
||||
std::ostringstream oss;
|
||||
if( rv == TestResult::Failed )
|
||||
try
|
||||
{
|
||||
oss << "expected message did not match." << std::endl;
|
||||
streamDebugging< outputMode >( oss, witness, expected );
|
||||
invoker();
|
||||
return { TestResult::Failed,
|
||||
IOStreams::String{} << "expected exception `" << Utility::fancyTypeName< T >() << "` wasn't thrown." };
|
||||
}
|
||||
return { rv, oss.str().empty() ? std::optional< std::string >{} : std::move( oss ).str() };
|
||||
catch( const T &ex )
|
||||
{
|
||||
const std::string witness= ex.what();
|
||||
const TestResult rv= witness == expected ? TestResult::Passed : TestResult::Failed;
|
||||
std::ostringstream oss;
|
||||
if( rv == TestResult::Failed )
|
||||
{
|
||||
oss << "expected message did not match." << std::endl;
|
||||
streamDebugging< outputMode >( oss, witness, expected );
|
||||
}
|
||||
return { rv, oss.str().empty() ? std::optional< std::string >{} : std::move( oss ).str() };
|
||||
}
|
||||
}
|
||||
catch( const std::exception &ex )
|
||||
{
|
||||
return { TestResult::Failed, IOStreams::String() << "Incorrect exception type " << Utility::fancyTypeName( typeid( ex ) ) << " was thrown, but "
|
||||
<< Utility::fancyTypeName< T >() << " was expected." };
|
||||
}
|
||||
catch( ... )
|
||||
{
|
||||
return { TestResult::Failed, IOStreams::String() << "Incorrect exception type (<Unknown>) was thrown, but "
|
||||
<< Utility::fancyTypeName< T >() << " was expected." };
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -303,7 +333,7 @@ namespace Alepha::Hydrogen::Testing ::detail:: TableTest_m
|
||||
{
|
||||
for( const auto [ comment, params, handler ]: initList )
|
||||
{
|
||||
if( C::debugCaseTypes ) std::cerr << boost::core::demangle( typeid( params ).name() ) << std::endl;
|
||||
if( C::debugCaseTypes ) std::cerr << Utility::fancyTypeName( typeid( params ) ) << std::endl;
|
||||
auto invoker= [=]
|
||||
{
|
||||
breakpoint();
|
||||
|
@ -50,12 +50,17 @@ namespace
|
||||
{ "Negative case", { -10, -20 }, -30 },
|
||||
};
|
||||
|
||||
struct DerivedError : std::runtime_error
|
||||
{
|
||||
using std::runtime_error::runtime_error;
|
||||
};
|
||||
|
||||
"Can we use Aggregates with universal cases, correctly?"_test <=
|
||||
TableTest
|
||||
<
|
||||
[]( const int x )
|
||||
{
|
||||
if( x < 0 ) throw std::runtime_error{ "Cannot be negative." };
|
||||
if( x < 0 ) throw DerivedError{ "Cannot be negative." };
|
||||
return Aggregate{ x, x, x };
|
||||
}
|
||||
>
|
||||
@ -66,16 +71,19 @@ namespace
|
||||
{ "Ignore exceptions case (`std::type_identity< void >`)", { 42 }, std::type_identity< void >{} },
|
||||
{ "Expect exception type runtime_error", { -42 }, std::type_identity< std::runtime_error >{} },
|
||||
{ "Expect exception type exception", { -42 }, std::type_identity< std::exception >{} },
|
||||
{ "Expect exception value specific", { -42 }, std::runtime_error{ "Cannot be negative." } },
|
||||
{ "Expect exception value specific", { -42 }, DerivedError{ "Cannot be negative." } },
|
||||
{ "Expect exception value specific (loose)", { -42 }, std::runtime_error{ "Cannot be negative." } },
|
||||
|
||||
/* These cases should fail, but we don't want to fail them in normal builds. */
|
||||
#if 0
|
||||
{ "Failing: Basic value case", { -42 }, { 42, 42, 42 } },
|
||||
{ "Failing: Ignore exceptions case (`std::nothrow`)", { -42 }, std::nothrow },
|
||||
{ "Failing: Ignore exceptions case (`std::type_identity< void >`)", { -42 }, std::type_identity< void >{} },
|
||||
{ "Failing: Expect exception type runtime_error", { 42 }, std::type_identity< std::runtime_error >{} },
|
||||
{ "Failing: Expect exception type exception", { 42 }, std::type_identity< std::exception >{} },
|
||||
{ "Failing: Expect exception value specific", { 42 }, std::runtime_error{ "Cannot be negative." } },
|
||||
{ "Basic value case", { -42 }, { 42, 42, 42 } },
|
||||
{ "Ignore exceptions case (`std::nothrow`)", { -42 }, std::nothrow },
|
||||
{ "Ignore exceptions case (`std::type_identity< void >`)", { -42 }, std::type_identity< void >{} },
|
||||
{ "Expect exception type runtime_error", { 42 }, std::type_identity< std::runtime_error >{} },
|
||||
{ "Expect exception type exception", { 42 }, std::type_identity< std::exception >{} },
|
||||
{ "Expect exception value specific", { 42 }, DerivedError{ "Cannot be negative." } },
|
||||
{ "Expect exception value specific (loose)", { 42 }, std::runtime_error{ "Cannot be negative." } },
|
||||
{ "Expect exception value specific (wrong)", { -42 }, std::logic_error{ "Cannot be negative." } },
|
||||
#endif
|
||||
};
|
||||
};
|
||||
|
@ -7,7 +7,7 @@ static_assert( __cplusplus > 2020'99 );
|
||||
namespace Alepha::Hydrogen::Utility::detail::fancyTypeName_m
|
||||
{
|
||||
std::string
|
||||
fancyTypeName( const std::type_index idx )
|
||||
exports::fancyTypeName( const std::type_index idx )
|
||||
{
|
||||
return boost::core::demangle( idx.name() );
|
||||
}
|
||||
|
Reference in New Issue
Block a user