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 <numeric>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
|
|
||||||
#include <boost/core/demangle.hpp>
|
|
||||||
#include <boost/lexical_cast.hpp>
|
|
||||||
|
|
||||||
#include <Alepha/function_traits.h>
|
#include <Alepha/function_traits.h>
|
||||||
#include <Alepha/template_for_each.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/evaluation_helpers.h>
|
||||||
#include <Alepha/Utility/TupleAdapter.h>
|
#include <Alepha/Utility/TupleAdapter.h>
|
||||||
|
#include <Alepha/Utility/fancyTypeName.h>
|
||||||
|
|
||||||
#include <Alepha/Reflection/tuplizeAggregate.h>
|
#include <Alepha/Reflection/tuplizeAggregate.h>
|
||||||
|
|
||||||
@ -84,7 +82,7 @@ namespace Alepha::Hydrogen::Testing ::detail:: TableTest_m
|
|||||||
}
|
}
|
||||||
catch( const std::exception &ex )
|
catch( const std::exception &ex )
|
||||||
{
|
{
|
||||||
return ErrorMessage{ typeid( ex ).name() };
|
return ErrorMessage{ Utility::fancyTypeName( typeid( ex ) ) };
|
||||||
}
|
}
|
||||||
catch( ... )
|
catch( ... )
|
||||||
{
|
{
|
||||||
@ -127,7 +125,7 @@ namespace Alepha::Hydrogen::Testing ::detail:: TableTest_m
|
|||||||
}
|
}
|
||||||
catch( const std::exception &ex )
|
catch( const std::exception &ex )
|
||||||
{
|
{
|
||||||
return ErrorMessage{ typeid( ex ).name() };
|
return ErrorMessage{ Utility::fancyTypeName( typeid( ex ) ) };
|
||||||
}
|
}
|
||||||
catch( ... )
|
catch( ... )
|
||||||
{
|
{
|
||||||
@ -160,13 +158,26 @@ namespace Alepha::Hydrogen::Testing ::detail:: TableTest_m
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
std::ignore= invoker();
|
try
|
||||||
breakpoint();
|
{
|
||||||
return { TestResult::Failed, std::nullopt };
|
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();
|
std::ignore= invoker();
|
||||||
return { TestResult::Passed, std::nullopt };
|
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( ... )
|
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
|
try
|
||||||
{
|
{
|
||||||
invoker();
|
try
|
||||||
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 )
|
|
||||||
{
|
{
|
||||||
oss << "expected message did not match." << std::endl;
|
invoker();
|
||||||
streamDebugging< outputMode >( oss, witness, expected );
|
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 )
|
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= [=]
|
auto invoker= [=]
|
||||||
{
|
{
|
||||||
breakpoint();
|
breakpoint();
|
||||||
|
@ -50,12 +50,17 @@ namespace
|
|||||||
{ "Negative case", { -10, -20 }, -30 },
|
{ "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 <=
|
"Can we use Aggregates with universal cases, correctly?"_test <=
|
||||||
TableTest
|
TableTest
|
||||||
<
|
<
|
||||||
[]( const int x )
|
[]( 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 };
|
return Aggregate{ x, x, x };
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
@ -66,16 +71,19 @@ namespace
|
|||||||
{ "Ignore exceptions case (`std::type_identity< void >`)", { 42 }, std::type_identity< void >{} },
|
{ "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 runtime_error", { -42 }, std::type_identity< std::runtime_error >{} },
|
||||||
{ "Expect exception type exception", { -42 }, std::type_identity< std::exception >{} },
|
{ "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. */
|
/* These cases should fail, but we don't want to fail them in normal builds. */
|
||||||
#if 0
|
#if 0
|
||||||
{ "Failing: Basic value case", { -42 }, { 42, 42, 42 } },
|
{ "Basic value case", { -42 }, { 42, 42, 42 } },
|
||||||
{ "Failing: Ignore exceptions case (`std::nothrow`)", { -42 }, std::nothrow },
|
{ "Ignore exceptions case (`std::nothrow`)", { -42 }, std::nothrow },
|
||||||
{ "Failing: Ignore exceptions case (`std::type_identity< void >`)", { -42 }, std::type_identity< void >{} },
|
{ "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 >{} },
|
{ "Expect exception type runtime_error", { 42 }, std::type_identity< std::runtime_error >{} },
|
||||||
{ "Failing: Expect exception type exception", { 42 }, std::type_identity< std::exception >{} },
|
{ "Expect exception type exception", { 42 }, std::type_identity< std::exception >{} },
|
||||||
{ "Failing: 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." } },
|
||||||
|
{ "Expect exception value specific (wrong)", { -42 }, std::logic_error{ "Cannot be negative." } },
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -7,7 +7,7 @@ static_assert( __cplusplus > 2020'99 );
|
|||||||
namespace Alepha::Hydrogen::Utility::detail::fancyTypeName_m
|
namespace Alepha::Hydrogen::Utility::detail::fancyTypeName_m
|
||||||
{
|
{
|
||||||
std::string
|
std::string
|
||||||
fancyTypeName( const std::type_index idx )
|
exports::fancyTypeName( const std::type_index idx )
|
||||||
{
|
{
|
||||||
return boost::core::demangle( idx.name() );
|
return boost::core::demangle( idx.name() );
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user