forked from Alepha/Alepha
This probably needs to be expanded upon. The basic functionality added is to permit a test expectation clause to be a function which takes some kind of exception type. That function can then perform any arbitrary checks and analyses it needs to confirm that the exception which was caught passes muster for that test case.
101 lines
3.2 KiB
C++
101 lines
3.2 KiB
C++
static_assert( __cplusplus > 2020'99 );
|
|
|
|
#include <Alepha/Testing/TableTest.h>
|
|
|
|
#include <Alepha/Testing/test.h>
|
|
#include <Alepha/Utility/evaluation_helpers.h>
|
|
|
|
#include <Alepha/IOStreams/delimiters.h>
|
|
#include <Alepha/IOStreams/OStreamable.h>
|
|
|
|
#include <Alepha/comparisons.h>
|
|
|
|
|
|
namespace
|
|
{
|
|
using namespace Alepha::Testing::exports;
|
|
using namespace Alepha::Utility::exports::evaluation_helpers_m;
|
|
|
|
int
|
|
add( int a, int b )
|
|
{
|
|
return a + b;
|
|
}
|
|
|
|
auto basic_test= "basic_test"_test <=[]
|
|
{
|
|
return 0;
|
|
};
|
|
|
|
auto test= "addition.two.test"_test <=TableTest< add >::Cases
|
|
{
|
|
{ "Basic Smoke Test", { 2, 2 }, 4 },
|
|
{ "Lefthand identity", { 0, 25 }, 25 },
|
|
{ "Righthand identity", { 25, 0 }, 25 },
|
|
};
|
|
|
|
template< typename= Alepha::Capabilities< Alepha::IOStreams::OStreamable, Alepha::comparable > >
|
|
struct Aggregate_core
|
|
{
|
|
int x, y, z;
|
|
|
|
friend bool operator == ( Aggregate_core, Aggregate_core ) noexcept= default;
|
|
};
|
|
using Aggregate= Aggregate_core<>;
|
|
|
|
auto alltests= enroll <=[]
|
|
{
|
|
"addition.two.local"_test <=TableTest< add >::Cases
|
|
{
|
|
{ "Negative case", { -10, -20 }, -30 },
|
|
};
|
|
|
|
struct DerivedError : std::runtime_error
|
|
{
|
|
using std::runtime_error::runtime_error;
|
|
|
|
std::optional< int > value_;
|
|
|
|
explicit DerivedError( const std::string &s, int value_ ) : std::runtime_error{ s }, value_( value_ ) {}
|
|
|
|
int value() const { return value_.value(); }
|
|
};
|
|
|
|
"Can we use Aggregates with universal cases, correctly?"_test <=
|
|
TableTest
|
|
<
|
|
[]( const int x )
|
|
{
|
|
if( x < 0 ) throw DerivedError{ "Cannot be negative.", x };
|
|
return Aggregate{ x, x, x };
|
|
}
|
|
>
|
|
::UniversalCases
|
|
{
|
|
{ "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 (loose)", { -42 },
|
|
[]( const DerivedError &e )
|
|
{
|
|
return e.value() == -42;
|
|
} },
|
|
|
|
/* These cases should fail, but we don't want to fail them in normal builds. */
|
|
/* A few different ways of disabling these tests are shown below. */
|
|
{ Skip <="Basic value case", { -42 }, { 42, 42, 42 } },
|
|
{ !!Disable <="Ignore exceptions case (`std::nothrow`)", { -42 }, std::nothrow },
|
|
{ -Enable <="Ignore exceptions case (`std::type_identity< void >`)", { -42 }, std::type_identity< void >{} },
|
|
{ -"Expect exception type runtime_error"_case, { 42 }, std::type_identity< std::runtime_error >{} },
|
|
{ Disable <="Expect exception type exception", { 42 }, std::type_identity< std::exception >{} },
|
|
{ !"Expect exception value specific"_case, { 42 }, DerivedError{ "Cannot be negative." } },
|
|
{ Skip <="Expect exception value specific (loose)", { 42 }, std::runtime_error{ "Cannot be negative." } },
|
|
{ Skip <="Expect exception value specific (wrong)", { -42 }, std::logic_error{ "Cannot be negative." } },
|
|
};
|
|
};
|
|
}
|