//===- OmptTesterStandalone.cpp - Standalone unit testing impl. -*- 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' ompTest unit testing core /// implementation, defining the general test suite and test case execution. /// //===----------------------------------------------------------------------===// #include "OmptTesterStandalone.h" #include "OmptCallbackHandler.h" #include #include #include #include #include #include #include #include using namespace omptest; Error TestCase::exec() { Error E; E.Fail = false; if (IsDisabled) return E; OmptCallbackHandler::get().subscribe(SequenceAsserter.get()); OmptCallbackHandler::get().subscribe(SetAsserter.get()); OmptCallbackHandler::get().subscribe(EventReporter.get()); execImpl(); // Actively flush potential in-flight trace records flush_traced_devices(); // We remove subscribers to not be notified of events after our test case // finished. OmptCallbackHandler::get().clearSubscribers(); omptest::AssertState SequenceResultState = SequenceAsserter->checkState(); omptest::AssertState SetResultState = SetAsserter->checkState(); bool AnyFail = SequenceResultState == omptest::AssertState::Fail || SetResultState == omptest::AssertState::Fail; bool AllPass = SequenceResultState == omptest::AssertState::Pass && SetResultState == omptest::AssertState::Pass; if (ExpectedState == omptest::AssertState::Pass && AnyFail) E.Fail = true; else if (ExpectedState == omptest::AssertState::Fail && AllPass) E.Fail = true; if (AnyFail) ResultState = omptest::AssertState::Fail; return E; } TestSuite::TestSuite(TestSuite &&O) { Name = O.Name; TestCases.swap(O.TestCases); } void TestSuite::setup() {} void TestSuite::teardown() {} TestSuite::TestCaseVec::iterator TestSuite::begin() { return TestCases.begin(); } TestSuite::TestCaseVec::iterator TestSuite::end() { return TestCases.end(); } TestRegistrar &TestRegistrar::get() { static TestRegistrar TR; return TR; } std::vector TestRegistrar::getTestSuites() { std::vector TSs; for (auto &[k, v] : Tests) TSs.emplace_back(std::move(v)); return TSs; } void TestRegistrar::addCaseToSuite(TestCase *TC, const std::string &TSName) { // Search the test suites for a matching name auto It = std::find_if(Tests.begin(), Tests.end(), [&](const auto &P) { return P.first == TSName; }); if (It != Tests.end()) { // Test suite exists: add the test case It->second.TestCases.emplace_back(TC); } else { // Test suite does not exist: construct it and add the test case TestSuite TS(TSName); TS.TestCases.emplace_back(TC); // Move and emplace the suite Tests.emplace_back(TSName, std::move(TS)); } } Registerer::Registerer(TestCase *TC, const std::string SuiteName) { std::cout << "Adding " << TC->Name << " to " << SuiteName << std::endl; TestRegistrar::get().addCaseToSuite(TC, SuiteName); } int Runner::run() { int ErrorCount = 0; for (auto &TS : TestSuites) { std::cout << "\n======\nExecuting for " << TS.Name << std::endl; TS.setup(); for (auto &TC : TS) { std::cout << "\nExecuting " << TC->Name << std::endl; if (Error Err = TC->exec()) { reportError(Err); abortOrKeepGoing(); ++ErrorCount; } } TS.teardown(); } printSummary(); return ErrorCount; } void Runner::reportError(const Error &Err) {} void Runner::abortOrKeepGoing() {} void Runner::printSummary() { std::cout << "\n====== SUMMARY\n"; for (auto &TS : TestSuites) { std::cout << " - " << TS.Name; for (auto &TC : TS) { std::string Result; if (TC->IsDisabled) { Result = "-#-#-"; } else if (TC->ResultState == TC->ExpectedState) { if (TC->ResultState == omptest::AssertState::Pass) Result = "PASS"; else if (TC->ResultState == omptest::AssertState::Fail) Result = "XFAIL"; } else { if (TC->ResultState == omptest::AssertState::Fail) Result = "FAIL"; else if (TC->ResultState == omptest::AssertState::Pass) Result = "UPASS"; } std::cout << "\n " << std::setw(5) << Result << " : " << TC->Name; } std::cout << std::endl; } }