//===- OmptTesterStandalone.h - Standalone header variant -------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// /// /// \file /// This file represents the 'standalone' header variant, defining the actual /// test classes and their behavior (it does not have external dependencies). /// //===----------------------------------------------------------------------===// #ifndef OPENMP_TOOLS_OMPTEST_INCLUDE_OMPTTESTERSTANDALONE_H #define OPENMP_TOOLS_OMPTEST_INCLUDE_OMPTTESTERSTANDALONE_H #include "OmptAssertEvent.h" #include "OmptAsserter.h" #include "OmptTesterGlobals.h" #include #include // Forward declarations. namespace omptest { struct OmptEventAsserter; class OmptEventReporter; class OmptSequencedAsserter; } // namespace omptest struct Error { operator bool() { return Fail; } bool Fail; }; /// A pretty crude test case abstraction struct TestCase { TestCase(const std::string &name) : IsDisabled(name.rfind("DISABLED_", 0) == 0), Name(name) {} TestCase(const std::string &name, const omptest::AssertState &expected) : IsDisabled(name.rfind("DISABLED_", 0) == 0), Name(name), ExpectedState(expected) {} virtual ~TestCase() = default; Error exec(); virtual void execImpl() { assert(false && "Allocating base class"); } bool IsDisabled{false}; std::string Name; omptest::AssertState ExpectedState{omptest::AssertState::Pass}; omptest::AssertState ResultState{omptest::AssertState::Pass}; std::unique_ptr SequenceAsserter = std::make_unique(); std::unique_ptr SetAsserter = std::make_unique(); std::unique_ptr EventReporter = std::make_unique(); }; /// A pretty crude test suite abstraction struct TestSuite { using TestCaseVec = std::vector>; TestSuite() = default; TestSuite(const std::string &TSName) : Name(TSName) {} TestSuite(const TestSuite &O) = delete; TestSuite(TestSuite &&O); void setup(); void teardown(); TestCaseVec::iterator begin(); TestCaseVec::iterator end(); std::string Name; TestCaseVec TestCases; }; /// Static class used to register all test cases and provide them to the driver class TestRegistrar { public: static TestRegistrar &get(); static std::vector getTestSuites(); static void addCaseToSuite(TestCase *TC, const std::string &TSName); private: TestRegistrar() = default; TestRegistrar(const TestRegistrar &o) = delete; TestRegistrar operator=(const TestRegistrar &o) = delete; // Keep tests in order 'of appearance', i.e. top -> bottom. // This effectively mimicks the (observed) behavior of GoogleTest. // Avoid maps as they do not have corresponding order guarantees. static std::vector> Tests; }; /// Hack to register test cases struct Registerer { Registerer(TestCase *TC, const std::string SuiteName); }; /// Eventually executes all test suites and cases, should contain logic to skip /// stuff if needed struct Runner { Runner() : TestSuites(TestRegistrar::get().getTestSuites()) {} int run(); void reportError(const Error &Err); void abortOrKeepGoing(); // Print an execution summary of all testsuites and their corresponding // testcases. void printSummary(); std::vector TestSuites; }; /// MACROS TO DEFINE A TESTSUITE + TESTCASE (like GoogleTest does) #define XQUOTE(str) QUOTE(str) #define QUOTE(str) #str #define TEST_TEMPLATE(SuiteName, CaseName, ExpectedState) \ struct SuiteName##_##CaseName : public TestCase { \ SuiteName##_##CaseName() \ : TestCase(XQUOTE(CaseName), omptest::AssertState::ExpectedState) {} \ virtual void execImpl() override; \ }; \ static Registerer R_##SuiteName##CaseName(new SuiteName##_##CaseName(), \ #SuiteName); \ void SuiteName##_##CaseName::execImpl() #define TEST(SuiteName, CaseName) \ TEST_TEMPLATE(SuiteName, CaseName, /*ExpectedState=*/Pass) #define TEST_XFAIL(SuiteName, CaseName) \ TEST_TEMPLATE(SuiteName, CaseName, /*ExpectedState=*/Fail) #endif