Skip to content
Snippets Groups Projects
Commit 7e73fa32 authored by Imdad Sardharwalla's avatar Imdad Sardharwalla Committed by GitHub Enterprise
Browse files

REFORM-1168 Create additional test macros and rename existing ones (#66)

parent 19c6cfaa
Branches
No related tags found
1 merge request!14Merge latest changes to Base from ReForm
...@@ -63,6 +63,7 @@ int collect(const int _argc, const char* const* _argv) ...@@ -63,6 +63,7 @@ int collect(const int _argc, const char* const* _argv)
int framework_argc = _argc; int framework_argc = _argc;
// The first argument is the process name // The first argument is the process name
if (_argc > 0)
process_name_ = _argv[0]; process_name_ = _argv[0];
for (int i = 1; i < _argc; i++) for (int i = 1; i < _argc; i++)
......
...@@ -72,7 +72,7 @@ Condition condition; ...@@ -72,7 +72,7 @@ Condition condition;
}//Checksum }//Checksum
void check_condition( void record_condition(
const char* const _cndt, const Base::CodeLink& _lnk, const bool _rslt) const char* const _cndt, const Base::CodeLink& _lnk, const bool _rslt)
{ {
TEST(condition, record(_cndt, _lnk, _rslt)); TEST(condition, record(_cndt, _lnk, _rslt));
......
...@@ -43,18 +43,18 @@ extern Condition condition; ...@@ -43,18 +43,18 @@ extern Condition condition;
} // namespace Checksum } // namespace Checksum
void check_condition( void record_condition(
const char* const _cndt, const Base::CodeLink& _lnk, const bool _rslt); const char* const _cndt, const Base::CodeLink& _lnk, const bool _rslt);
} // namespace Test } // namespace Test
// Write a Condition checksum to record the outcome of CONDITION. // Write a Condition checksum to record the outcome of CONDITION.
#define CHECK_CONDITION(CONDITION) \ #define TEST_CONDITION_RECORD(CONDITION) \
::Test::check_condition(#CONDITION, BASE_CODELINK, CONDITION) ::Test::record_condition(#CONDITION, BASE_CODELINK, CONDITION)
#else // defined(TEST_ON) #else // defined(TEST_ON)
#define CHECK_CONDITION(CONDITION) #define TEST_CONDITION_RECORD(CONDITION)
#endif // defined(TEST_ON) #endif // defined(TEST_ON)
......
...@@ -26,61 +26,79 @@ void record_and_handle_unexpected( ...@@ -26,61 +26,79 @@ void record_and_handle_unexpected(
TEST(outcome, record(_call, _oc.ok(), _oc.error_description().c_str())); TEST(outcome, record(_call, _oc.ok(), _oc.error_description().c_str()));
if (_unexpected) if (_unexpected)
_oc.handle_unexpected(); _oc.unexpected_handler();
} }
} // namespace } // namespace
Outcome::Outcome(bool _ok, const std::string& _error_code, Outcome::Outcome() : ok_(true), error_code_("0"), error_message_("Success") {}
const std::string& _error_message,
const UnexpectedHandler& _unexpected_handler) Outcome::Outcome(
: ok_(_ok), error_code_(_error_code), error_message_(_error_message), bool _ok, const std::string& _error_code, const std::string& _error_message)
unexpected_handler_(_unexpected_handler) : ok_(_ok), error_code_(_error_code), error_message_(_error_message)
{ {
} }
Outcome::Outcome(bool _ok, const int _error_code, Outcome::Outcome(
const std::string& _error_message, bool _ok, const int _error_code, const std::string& _error_message)
const UnexpectedHandler& _unexpected_handler)
: ok_(_ok), error_code_(std::to_string(_error_code)), : ok_(_ok), error_code_(std::to_string(_error_code)),
error_message_(_error_message), unexpected_handler_(_unexpected_handler) error_message_(_error_message)
{
}
const std::string Outcome::error_description() const
{ {
return ok() ? error_message() : "[" + error_code() + "] " + error_message();
} }
void ignore_unstable_outcome(const char* const _call) Outcome::UnexpectedHandler Outcome::unexpected_handler = []
{
TEST_THROW_ERROR(TEST_OUTCOME_UNEXPECTED);
};
const Outcome& record_outcome(const char* const _call, const Outcome& _oc)
{ {
std::cout // Never call unexpected-outcome handler
<< "-----------------------\n" record_and_handle_unexpected(_call, _oc, false);
"Info: Unstable outcome from the following call has been ignored:" return _oc;
"\n\n " << _call << "\n\n"
"Replace IGNORE_UNSTABLE_OUTCOME() with CHECK_OUTCOME() once "
"the functionality is stable.\n"
"-----------------------"
<< std::endl;
} }
void check_outcome(const char* const _call, const Outcome& _oc) void expect_success(const char* const _call, const Outcome& _oc)
{ {
// Call unexpected-outcome handler if the call *failed* // Call unexpected-outcome handler if the call *failed*
record_and_handle_unexpected(_call, _oc, !_oc.ok()); record_and_handle_unexpected(_call, _oc, !_oc.ok());
} }
void expect_failed_outcome( void expect_outcome(
const char* const _call, const Outcome& _oc, const char* const _error_code) const char* const _call, const Outcome& _oc, const char* const _error_code)
{ {
// Call unexpected-outcome handler if the error code is not correct // Call unexpected-outcome handler if the error code is not correct
record_and_handle_unexpected(_call, _oc, _oc.error_code() != _error_code); record_and_handle_unexpected(_call, _oc, _oc.error_code() != _error_code);
} }
void expect_outcome(
const char* const _call, const Outcome& _oc, const int _error_code)
{
expect_outcome(_call, _oc, std::to_string(_error_code).c_str());
}
void expect_failure(const char* const _call, const Outcome& _oc) void expect_failure(const char* const _call, const Outcome& _oc)
{ {
// If _oc represents a failure, replace it with a generic failure outcome
auto oc = _oc.ok() ? _oc : Outcome(_oc.ok(), "FAILURE", "Failure");
// Call unexpected-outcome handler if the call *succeeds* // Call unexpected-outcome handler if the call *succeeds*
record_and_handle_unexpected(_call, _oc, _oc.ok()); record_and_handle_unexpected(_call, oc, oc.ok());
} }
const Outcome::UnexpectedHandler Outcome::default_unexpected_handler = [] void ignore_outcome(const char* const _call, const char* const _reason)
{ {
TEST_THROW_ERROR(TEST_OUTCOME_UNEXPECTED); // Write an "Ignored Outcome" checksum to the report
}; const auto message = std::string("[IGNORED] ") + _reason;
record_outcome(_call, Outcome(true, "", message.c_str()));
}
// Pass-through function for Test::Outcome
TEST_OUTCOME_ADD_TYPE(Test::Outcome) { return _oc; }
} // namespace Test } // namespace Test
......
...@@ -10,32 +10,55 @@ ...@@ -10,32 +10,55 @@
#include <functional> #include <functional>
#include <string> #include <string>
// If CALL is unstable on different platforms/architectures (it fails on some // Write an Outcome checksum to record the outcome of CALL. Returns the outcome.
// platforms/architectures but not others), use IGNORE_UNSTABLE_OUTCOME(CALL) #define TEST_OUTCOME_RECORD(CALL) \
// instead of CHECK_OUTCOME(CALL). This will prevent an unstable checksum being ::Test::record_outcome(#CALL, ::Test::Outcome::make(CALL))
// written for CALL and will write to stdout to note that this is happening.
#define IGNORE_UNSTABLE_OUTCOME(CALL) \ // If CALL *fails*, exit the current function and return the outcome.
(CALL); \ #define TEST_OUTCOME_RETURN(CALL) \
::Test::ignore_unstable_outcome(#CALL) { \
const auto oc = ::Test::Outcome::make(CALL); \
if (!oc.ok()) \
return oc; \
}
// Write an Outcome checksum to record the outcome of CALL. If CALL *fails*,
// exit the current function and return the outcome.
#define TEST_OUTCOME_RECORD_AND_RETURN(CALL) \
{ \
const auto oc = TEST_OUTCOME_RECORD(CALL); \
if (!oc.ok()) \
return oc; \
}
// Write an Outcome checksum to record the outcome of CALL. An // Write an Outcome checksum to record the outcome of CALL. An
// unexpected-outcome handler is called if CALL *fails*. // unexpected-outcome handler is called if CALL *fails*.
#define CHECK_OUTCOME(CALL) \ #define TEST_OUTCOME_SUCCESS(CALL) \
::Test::check_outcome(#CALL, ::Test::Outcome::make(CALL)) ::Test::expect_success(#CALL, ::Test::Outcome::make(CALL))
// Write an Outcome checksum to record the outcome of CALL. An // Write an Outcome checksum to record the outcome of CALL. An
// unexpected-outcome handler is called if the error code associated with the // unexpected-outcome handler is called if the error code associated with the
// outcome is not equal to ERROR_CODE. This is intended to be used for failures // outcome is not equal to ERROR_CODE.
// that occur by design. #define TEST_OUTCOME_EXPECT(CALL, ERROR_CODE) \
#define EXPECT_FAILED_OUTCOME(ERROR_CODE, CALL) \ ::Test::expect_outcome(#CALL, ::Test::Outcome::make(CALL), ERROR_CODE)
::Test::expect_failed_outcome(#CALL, ::Test::Outcome::make(CALL), #ERROR_CODE)
// Write an Outcome checksum to record the outcome of CALL. An // Write a success/failure Outcome checksum to record the outcome of CALL. An
// unexpected-outcome handler is called if CALL *succeeds*. This is intended to // unexpected-outcome handler is called if CALL *succeeds*.
// be used for failures that are caused by a known (but unresolved) bug. #define TEST_OUTCOME_FAILURE(CALL) \
#define EXPECT_FAILURE(CALL) \
::Test::expect_failure(#CALL, ::Test::Outcome::make(CALL)) ::Test::expect_failure(#CALL, ::Test::Outcome::make(CALL))
// Write an Outcome checksum to record that the outcome of CALL was ignored and
// the REASON why.
#define TEST_OUTCOME_IGNORE(CALL, REASON) \
(CALL); \
::Test::ignore_outcome(#CALL, REASON)
// Write an Outcome checksum to record that the outcome of CALL was ignored and
// that it is unstable (i.e. gives different outcomes on different
// platforms/architectures).
#define TEST_OUTCOME_IGNORE_UNSTABLE(CALL) \
TEST_OUTCOME_IGNORE(CALL, "Unstable outcome")
/* Use the following macro to add a new outcome type. It defines a /* Use the following macro to add a new outcome type. It defines a
* specialisation for Test::Outcome::make<TYPE>(const TYPE& _oc), and must * specialisation for Test::Outcome::make<TYPE>(const TYPE& _oc), and must
* return a Test::Outcome object. * return a Test::Outcome object.
...@@ -65,36 +88,37 @@ namespace Test ...@@ -65,36 +88,37 @@ namespace Test
/* A generic outcome class that is intended to be a wrapper for all other /* A generic outcome class that is intended to be a wrapper for all other
* outcome classes. It has the following member functions: * outcome classes. It has the following member functions:
* *
* - make<T>(): Creates an Outcome object from an object of type T. A * - constructor: Calling the constructor with no arguments creates a
* template specialisation should be added for each T * successful outcome.
*
* - make<T>(): Creates an Outcome object from an object of type T.
* A template specialisation should be added for each T
* that is required by the consuming project (see * that is required by the consuming project (see
* TEST_OUTCOME_ADD_TYPE() macro). * TEST_OUTCOME_ADD_TYPE() macro).
* *
* - ok(): Returns whether the outcome was a success; * - ok(): Returns whether the outcome was a success.
* *
* - error_code(): Returns the associated error code as a std::string&; * - error_code(): Returns the associated error code as a std::string&.
* *
* - error_message(): Returns the associated error message; * - error_message(): Returns the associated error message.
* *
* - error_description(): Returns a concatenation of the error code and error * - error_description(): Returns a concatenation of the error code and error
* message; * message.
* *
* - handle_unexpected(): A function that can be called if the outcome is not * It also contains the static variable unexpected_handler, a std::function that
* what was expected. * can be called if the outcome is not what was expected.
*/ */
class Outcome class Outcome
{ {
public: public:
typedef std::function<void()> UnexpectedHandler; typedef std::function<void()> UnexpectedHandler;
Outcome(); // Construct successful outcome
Outcome(bool _ok, const std::string& _error_code, Outcome(bool _ok, const std::string& _error_code,
const std::string& _error_message, const std::string& _error_message);
const UnexpectedHandler& _unexpected_handler =
default_unexpected_handler);
Outcome(bool _ok, const int _error_code, const std::string& _error_message, Outcome(bool _ok, const int _error_code, const std::string& _error_message);
const UnexpectedHandler& _unexpected_handler =
default_unexpected_handler);
template <class T> static Outcome make(const T& _oc); template <class T> static Outcome make(const T& _oc);
...@@ -104,31 +128,31 @@ public: ...@@ -104,31 +128,31 @@ public:
const std::string& error_message() const { return error_message_; } const std::string& error_message() const { return error_message_; }
const std::string error_description() const const std::string error_description() const;
{
return ok() ? error_message() : "[" + error_code() + "] " + error_message();
}
void handle_unexpected() const { unexpected_handler_(); }
static const UnexpectedHandler default_unexpected_handler; static UnexpectedHandler unexpected_handler;
private: private:
bool ok_; bool ok_;
std::string error_code_; std::string error_code_;
std::string error_message_; std::string error_message_;
UnexpectedHandler unexpected_handler_;
}; };
void ignore_unstable_outcome(const char* const _call); const Outcome& record_outcome(const char* const _call, const Outcome& _oc);
void check_outcome(const char* const _call, const Outcome& _oc); void expect_success(const char* const _call, const Outcome& _oc);
void expect_failed_outcome( void expect_outcome(
const char* const _call, const Outcome& _oc, const char* const _error_code); const char* const _call, const Outcome& _oc, const char* const _error_code);
void expect_outcome(
const char* const _call, const Outcome& _oc, const int _error_code);
void expect_failure(const char* const _call, const Outcome& _oc); void expect_failure(const char* const _call, const Outcome& _oc);
void ignore_outcome(const char* const _call, const char* const _reason);
} // namespace Test } // namespace Test
#endif // TEST_ON #endif // TEST_ON
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment