2021-04-24 23:53:23 -06:00
/*
* Copyright ( c ) 2018 - 2020 , Andreas Kling < kling @ serenityos . org >
* Copyright ( c ) 2021 , Andrew Kaster < akaster @ serenityos . org >
*
* SPDX - License - Identifier : BSD - 2 - Clause
*/
# pragma once
# include <AK/Assertions.h>
# include <AK/CheckedFormatString.h>
2021-07-17 18:29:28 +02:00
# include <AK/Math.h>
2021-05-07 04:38:56 -07:00
# include <LibTest/CrashTest.h>
2023-10-24 00:35:15 +02:00
# include <LibTest/Randomized/RandomnessSource.h>
2023-10-24 00:19:04 +02:00
# include <LibTest/TestResult.h>
2021-04-24 23:53:23 -06:00
namespace AK {
template < typename . . . Parameters >
2022-04-01 20:58:27 +03:00
void warnln ( CheckedFormatString < Parameters . . . > & & fmtstr , Parameters const & . . . ) ;
2021-04-24 23:53:23 -06:00
}
namespace Test {
2023-10-24 00:19:04 +02:00
// Declare helpers so that we can call them from VERIFY in included headers
// the setter for TestResult is already declared in TestResult.h
TestResult current_test_result ( ) ;
2023-10-24 00:35:15 +02:00
Randomized : : RandomnessSource & randomness_source ( ) ;
void set_randomness_source ( Randomized : : RandomnessSource ) ;
2021-04-24 23:53:23 -06:00
}
# define EXPECT_EQ(a, b) \
do { \
auto lhs = ( a ) ; \
auto rhs = ( b ) ; \
if ( lhs ! = rhs ) { \
: : AK : : warnln ( " \033 [31;1mFAIL \033 [0m: {}:{}: EXPECT_EQ({}, {}) failed with lhs={} and rhs={} " , __FILE__ , __LINE__ , # a , # b , FormatIfSupported { lhs } , FormatIfSupported { rhs } ) ; \
2023-10-24 00:19:04 +02:00
: : Test : : set_current_test_result ( : : Test : : TestResult : : Failed ) ; \
2021-04-24 23:53:23 -06:00
} \
} while ( false )
2021-10-23 02:49:13 +02:00
# define EXPECT_EQ_TRUTH(a, b) \
do { \
auto lhs = ( a ) ; \
auto rhs = ( b ) ; \
bool ltruth = static_cast < bool > ( lhs ) ; \
bool rtruth = static_cast < bool > ( rhs ) ; \
if ( ltruth ! = rtruth ) { \
: : AK : : warnln ( " \033 [31;1mFAIL \033 [0m: {}:{}: EXPECT_EQ_TRUTH({}, {}) failed with lhs={} ({}) and rhs={} ({}) " , \
__FILE__ , __LINE__ , # a , # b , FormatIfSupported { lhs } , ltruth , FormatIfSupported { rhs } , rtruth ) ; \
2023-10-24 00:19:04 +02:00
: : Test : : set_current_test_result ( : : Test : : TestResult : : Failed ) ; \
2021-10-23 02:49:13 +02:00
} \
} while ( false )
2021-04-24 23:53:23 -06:00
// If you're stuck and `EXPECT_EQ` seems to refuse to print anything useful,
// try this: It'll spit out a nice compiler error telling you why it doesn't print.
# define EXPECT_EQ_FORCE(a, b) \
do { \
auto lhs = ( a ) ; \
auto rhs = ( b ) ; \
if ( lhs ! = rhs ) { \
: : AK : : warnln ( " \033 [31;1mFAIL \033 [0m: {}:{}: EXPECT_EQ({}, {}) failed with lhs={} and rhs={} " , __FILE__ , __LINE__ , # a , # b , lhs , rhs ) ; \
2023-10-24 00:19:04 +02:00
: : Test : : set_current_test_result ( : : Test : : TestResult : : Failed ) ; \
2021-04-24 23:53:23 -06:00
} \
} while ( false )
2021-04-28 19:53:24 -07:00
# define EXPECT_NE(a, b) \
do { \
auto lhs = ( a ) ; \
auto rhs = ( b ) ; \
if ( lhs = = rhs ) { \
: : AK : : warnln ( " \033 [31;1mFAIL \033 [0m: {}:{}: EXPECT_NE({}, {}) failed with lhs={} and rhs={} " , __FILE__ , __LINE__ , # a , # b , FormatIfSupported { lhs } , FormatIfSupported { rhs } ) ; \
2023-10-24 00:19:04 +02:00
: : Test : : set_current_test_result ( : : Test : : TestResult : : Failed ) ; \
2021-04-28 19:53:24 -07:00
} \
} while ( false )
2021-04-24 23:53:23 -06:00
# define EXPECT(x) \
do { \
if ( ! ( x ) ) { \
: : AK : : warnln ( " \033 [31;1mFAIL \033 [0m: {}:{}: EXPECT({}) failed " , __FILE__ , __LINE__ , # x ) ; \
2023-10-24 00:19:04 +02:00
: : Test : : set_current_test_result ( : : Test : : TestResult : : Failed ) ; \
2021-04-24 23:53:23 -06:00
} \
} while ( false )
2023-04-29 15:15:19 -04:00
# define EXPECT_APPROXIMATE_WITH_ERROR(a, b, err) \
2021-04-24 23:53:23 -06:00
do { \
auto expect_close_lhs = a ; \
auto expect_close_rhs = b ; \
auto expect_close_diff = static_cast < double > ( expect_close_lhs ) - static_cast < double > ( expect_close_rhs ) ; \
2023-04-29 15:15:19 -04:00
if ( AK : : fabs ( expect_close_diff ) > ( err ) ) { \
2021-04-24 23:53:23 -06:00
: : AK : : warnln ( " \033 [31;1mFAIL \033 [0m: {}:{}: EXPECT_APPROXIMATE({}, {}) " \
" failed with lhs={}, rhs={}, (lhs-rhs)={} " , \
__FILE__ , __LINE__ , # a , # b , expect_close_lhs , expect_close_rhs , expect_close_diff ) ; \
2023-10-24 00:19:04 +02:00
: : Test : : set_current_test_result ( : : Test : : TestResult : : Failed ) ; \
2021-04-24 23:53:23 -06:00
} \
} while ( false )
2021-04-27 02:36:48 -07:00
2023-04-29 15:15:19 -04:00
# define EXPECT_APPROXIMATE(a, b) EXPECT_APPROXIMATE_WITH_ERROR(a, b, 0.0000005)
2021-04-27 02:36:48 -07:00
# define FAIL(message) \
do { \
: : AK : : warnln ( " \033 [31;1mFAIL \033 [0m: {}:{}: {} " , __FILE__ , __LINE__ , message ) ; \
2023-10-24 00:19:04 +02:00
: : Test : : set_current_test_result ( : : Test : : TestResult : : Failed ) ; \
2021-04-27 02:36:48 -07:00
} while ( false )
2021-05-07 04:38:56 -07:00
// To use, specify the lambda to execute in a sub process and verify it exits:
// EXPECT_CRASH("This should fail", []{
// return Test::Crash::Failure::DidNotCrash;
// });
2023-10-24 00:19:04 +02:00
# define EXPECT_CRASH(test_message, test_func) \
do { \
Test : : Crash crash ( test_message , test_func ) ; \
if ( ! crash . run ( ) ) \
: : Test : : set_current_test_result ( : : Test : : TestResult : : Failed ) ; \
2021-05-07 04:38:56 -07:00
} while ( false )
2021-12-17 18:12:47 +01:00
2023-10-24 00:19:04 +02:00
# define EXPECT_CRASH_WITH_SIGNAL(test_message, signal, test_func) \
do { \
Test : : Crash crash ( test_message , test_func , ( signal ) ) ; \
if ( ! crash . run ( ) ) \
: : Test : : set_current_test_result ( : : Test : : TestResult : : Failed ) ; \
2021-12-17 18:12:47 +01:00
} while ( false )
2021-12-15 00:47:43 +01:00
2023-10-24 00:19:04 +02:00
# define EXPECT_NO_CRASH(test_message, test_func) \
do { \
Test : : Crash crash ( test_message , test_func , 0 ) ; \
if ( ! crash . run ( ) ) \
: : Test : : set_current_test_result ( : : Test : : TestResult : : Failed ) ; \
2021-12-15 00:47:43 +01:00
} while ( false )
2023-04-05 20:23:26 +02:00
# define TRY_OR_FAIL(expression) \
( { \
/* Ignore -Wshadow to allow nesting the macro. */ \
AK_IGNORE_DIAGNOSTIC ( " -Wshadow " , \
auto & & _temporary_result = ( expression ) ) ; \
static_assert ( ! : : AK : : Detail : : IsLvalueReference < decltype ( _temporary_result . release_value ( ) ) > , \
" Do not return a reference from a fallible expression " ) ; \
if ( _temporary_result . is_error ( ) ) [ [ unlikely ] ] { \
FAIL ( _temporary_result . release_error ( ) ) ; \
return ; \
} \
_temporary_result . release_value ( ) ; \
} )