From 7e73fa323cfeb19911d646d79342442f1c358559 Mon Sep 17 00:00:00 2001 From: Imdad Sardharwalla <imdad.sardharwalla@autodesk.com> Date: Tue, 19 Oct 2021 11:29:35 +0100 Subject: [PATCH] REFORM-1168 Create additional test macros and rename existing ones (#66) --- Test/TestArgs.cc | 3 +- Test/TestChecksumCondition.cc | 2 +- Test/TestChecksumCondition.hh | 8 +-- Test/TestOutcome.cc | 68 ++++++++++++-------- Test/TestOutcome.hh | 116 ++++++++++++++++++++-------------- 5 files changed, 120 insertions(+), 77 deletions(-) diff --git a/Test/TestArgs.cc b/Test/TestArgs.cc index 0ccdcbe..9ee435b 100755 --- a/Test/TestArgs.cc +++ b/Test/TestArgs.cc @@ -63,7 +63,8 @@ int collect(const int _argc, const char* const* _argv) int framework_argc = _argc; // The first argument is the process name - process_name_ = _argv[0]; + if (_argc > 0) + process_name_ = _argv[0]; for (int i = 1; i < _argc; i++) { diff --git a/Test/TestChecksumCondition.cc b/Test/TestChecksumCondition.cc index 0fa8905..b22c749 100644 --- a/Test/TestChecksumCondition.cc +++ b/Test/TestChecksumCondition.cc @@ -72,7 +72,7 @@ Condition condition; }//Checksum -void check_condition( +void record_condition( const char* const _cndt, const Base::CodeLink& _lnk, const bool _rslt) { TEST(condition, record(_cndt, _lnk, _rslt)); diff --git a/Test/TestChecksumCondition.hh b/Test/TestChecksumCondition.hh index 2ef2177..64e911e 100644 --- a/Test/TestChecksumCondition.hh +++ b/Test/TestChecksumCondition.hh @@ -43,18 +43,18 @@ extern Condition condition; } // namespace Checksum -void check_condition( +void record_condition( const char* const _cndt, const Base::CodeLink& _lnk, const bool _rslt); } // namespace Test // Write a Condition checksum to record the outcome of CONDITION. -#define CHECK_CONDITION(CONDITION) \ - ::Test::check_condition(#CONDITION, BASE_CODELINK, CONDITION) +#define TEST_CONDITION_RECORD(CONDITION) \ + ::Test::record_condition(#CONDITION, BASE_CODELINK, CONDITION) #else // defined(TEST_ON) -#define CHECK_CONDITION(CONDITION) +#define TEST_CONDITION_RECORD(CONDITION) #endif // defined(TEST_ON) diff --git a/Test/TestOutcome.cc b/Test/TestOutcome.cc index 41f2ee9..5f38b50 100755 --- a/Test/TestOutcome.cc +++ b/Test/TestOutcome.cc @@ -26,61 +26,79 @@ void record_and_handle_unexpected( TEST(outcome, record(_call, _oc.ok(), _oc.error_description().c_str())); if (_unexpected) - _oc.handle_unexpected(); + _oc.unexpected_handler(); } } // namespace -Outcome::Outcome(bool _ok, const std::string& _error_code, - const std::string& _error_message, - const UnexpectedHandler& _unexpected_handler) - : ok_(_ok), error_code_(_error_code), error_message_(_error_message), - unexpected_handler_(_unexpected_handler) +Outcome::Outcome() : ok_(true), error_code_("0"), error_message_("Success") {} + +Outcome::Outcome( + bool _ok, const std::string& _error_code, const std::string& _error_message) + : ok_(_ok), error_code_(_error_code), error_message_(_error_message) { } -Outcome::Outcome(bool _ok, const int _error_code, - const std::string& _error_message, - const UnexpectedHandler& _unexpected_handler) +Outcome::Outcome( + bool _ok, const int _error_code, const std::string& _error_message) : 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 - << "-----------------------\n" - "Info: Unstable outcome from the following call has been ignored:" - "\n\n " << _call << "\n\n" - "Replace IGNORE_UNSTABLE_OUTCOME() with CHECK_OUTCOME() once " - "the functionality is stable.\n" - "-----------------------" - << std::endl; + // Never call unexpected-outcome handler + record_and_handle_unexpected(_call, _oc, false); + return _oc; } -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* 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) { // Call unexpected-outcome handler if the error code is not correct 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) { + // 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* - 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 diff --git a/Test/TestOutcome.hh b/Test/TestOutcome.hh index a01dbed..bc7628f 100755 --- a/Test/TestOutcome.hh +++ b/Test/TestOutcome.hh @@ -10,32 +10,55 @@ #include <functional> #include <string> -// If CALL is unstable on different platforms/architectures (it fails on some -// platforms/architectures but not others), use IGNORE_UNSTABLE_OUTCOME(CALL) -// instead of CHECK_OUTCOME(CALL). This will prevent an unstable checksum being -// written for CALL and will write to stdout to note that this is happening. -#define IGNORE_UNSTABLE_OUTCOME(CALL) \ - (CALL); \ - ::Test::ignore_unstable_outcome(#CALL) +// Write an Outcome checksum to record the outcome of CALL. Returns the outcome. +#define TEST_OUTCOME_RECORD(CALL) \ + ::Test::record_outcome(#CALL, ::Test::Outcome::make(CALL)) + +// If CALL *fails*, exit the current function and return the outcome. +#define TEST_OUTCOME_RETURN(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 // unexpected-outcome handler is called if CALL *fails*. -#define CHECK_OUTCOME(CALL) \ - ::Test::check_outcome(#CALL, ::Test::Outcome::make(CALL)) +#define TEST_OUTCOME_SUCCESS(CALL) \ + ::Test::expect_success(#CALL, ::Test::Outcome::make(CALL)) // Write an Outcome checksum to record the outcome of CALL. An // 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 -// that occur by design. -#define EXPECT_FAILED_OUTCOME(ERROR_CODE, CALL) \ - ::Test::expect_failed_outcome(#CALL, ::Test::Outcome::make(CALL), #ERROR_CODE) +// outcome is not equal to ERROR_CODE. +#define TEST_OUTCOME_EXPECT(CALL, ERROR_CODE) \ + ::Test::expect_outcome(#CALL, ::Test::Outcome::make(CALL), ERROR_CODE) -// Write an Outcome checksum to record the outcome of CALL. An -// unexpected-outcome handler is called if CALL *succeeds*. This is intended to -// be used for failures that are caused by a known (but unresolved) bug. -#define EXPECT_FAILURE(CALL) \ +// Write a success/failure Outcome checksum to record the outcome of CALL. An +// unexpected-outcome handler is called if CALL *succeeds*. +#define TEST_OUTCOME_FAILURE(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 * specialisation for Test::Outcome::make<TYPE>(const TYPE& _oc), and must * return a Test::Outcome object. @@ -57,7 +80,7 @@ * expected. */ #define TEST_OUTCOME_ADD_TYPE(TYPE) \ - template <> ::Test::Outcome Test::Outcome::make<TYPE>(const TYPE& _oc) + template <>::Test::Outcome Test::Outcome::make<TYPE>(const TYPE& _oc) namespace Test { @@ -65,36 +88,37 @@ namespace Test /* A generic outcome class that is intended to be a wrapper for all other * outcome classes. It has the following member functions: * - * - 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 - * TEST_OUTCOME_ADD_TYPE() macro). + * - constructor: Calling the constructor with no arguments creates a + * successful outcome. * - * - ok(): Returns whether the outcome was a success; + * - 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 + * TEST_OUTCOME_ADD_TYPE() macro). * - * - error_code(): Returns the associated error code as a std::string&; + * - ok(): Returns whether the outcome was a success. * - * - error_message(): Returns the associated error message; + * - error_code(): Returns the associated error code as a std::string&. * - * - error_description(): Returns a concatenation of the error code and error - * message; + * - error_message(): Returns the associated error message. * - * - handle_unexpected(): A function that can be called if the outcome is not - * what was expected. + * - error_description(): Returns a concatenation of the error code and error + * message. + * + * It also contains the static variable unexpected_handler, a std::function that + * can be called if the outcome is not what was expected. */ class Outcome { public: typedef std::function<void()> UnexpectedHandler; + Outcome(); // Construct successful outcome + Outcome(bool _ok, const std::string& _error_code, - const std::string& _error_message, - const UnexpectedHandler& _unexpected_handler = - default_unexpected_handler); + const std::string& _error_message); - Outcome(bool _ok, const int _error_code, const std::string& _error_message, - const UnexpectedHandler& _unexpected_handler = - default_unexpected_handler); + Outcome(bool _ok, const int _error_code, const std::string& _error_message); template <class T> static Outcome make(const T& _oc); @@ -104,31 +128,31 @@ public: const std::string& error_message() const { return error_message_; } - const std::string error_description() const - { - return ok() ? error_message() : "[" + error_code() + "] " + error_message(); - } - - void handle_unexpected() const { unexpected_handler_(); } + const std::string error_description() const; - static const UnexpectedHandler default_unexpected_handler; + static UnexpectedHandler unexpected_handler; private: bool ok_; std::string error_code_; 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); +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 ignore_outcome(const char* const _call, const char* const _reason); + } // namespace Test #endif // TEST_ON -- GitLab