| // Copyright 2024 The Pigweed Authors |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); you may not |
| // use this file except in compliance with the License. You may obtain a copy of |
| // the License at |
| // |
| // https://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
| // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
| // License for the specific language governing permissions and limitations under |
| // the License. |
| #pragma once |
| |
| #include <string_view> |
| |
| #include "pw_json/builder.h" |
| #include "pw_unit_test/event_handler.h" |
| #include "pw_unit_test/internal/test_record_trie.h" |
| |
| namespace pw::unit_test { |
| namespace json_impl { |
| |
| inline constexpr const char* kSkipMacroIndicator = "(test skipped)"; |
| |
| } // namespace json_impl |
| |
| /// Predefined event handler implementation that outputs a test record (or |
| /// summary) in Chromium JSON Test Results Format. To use it, register the event |
| /// handler, call the ``RUN_ALL_TESTS`` macro, then extract the test record json |
| /// as a string using the ``GetTestRecordJsonString`` method. If you only want |
| /// to extract the failing tests, set the `failing_results_only` parameter to |
| /// true. See ``pw::unit_test::EventHandler`` for explanations of emitted |
| /// events. |
| /// @see |
| /// https://chromium.googlesource.com/chromium/src/+/refs/heads/main/docs/testing/json_test_results_format.md |
| /// @warning This event handler uses dynamic allocation |
| /// (`new`/`delete`/`std::string`) to generate the test record json. |
| class TestRecordEventHandler : public EventHandler { |
| public: |
| /// Constructor for the event handler. Have to seconds_since_epoch since |
| /// calling std::time(nullptr) in pigweed is not supported. |
| /// |
| /// @param[in] seconds_since_epoch Seconds since epoch. Used in the test |
| /// record as the seconds since epoch for the start of the test run. |
| TestRecordEventHandler(int64_t seconds_since_epoch) |
| : seconds_since_epoch_(seconds_since_epoch) {} |
| |
| /// Called when a test case completes. Record the test case result in the test |
| /// record trie. |
| /// |
| /// @param[in] test_case Test case that ended. |
| /// |
| /// @param[in] result Result of the test case. |
| void TestCaseEnd(const TestCase& test_case, TestResult result) override { |
| test_record_trie_.AddTestResult(test_case, result); |
| } |
| |
| /// Called after all tests are run. Save the run tests summary for later use. |
| /// |
| /// @param[in] summary A test run summary. Contains counts of each test result |
| /// type. |
| void RunAllTestsEnd(const RunTestsSummary& summary) override { |
| run_tests_summary_ = summary; |
| } |
| |
| /// Called after each expect/assert statement within a test case with the |
| /// result of the expectation. |
| /// |
| /// We usually expect all tests to PASS. However, if the |
| /// GTEST_SKIP macro is used, the test is expected to be skipped and the |
| /// expectation expression is replaced with "(test skipped)" |
| /// |
| /// @param[in] test_case Test case that the expect statement lies in. |
| /// |
| /// @param[in] expectation Current expectation being checked for the test |
| /// case. |
| void TestCaseExpect(const TestCase& test_case, |
| const TestExpectation& expectation) override { |
| // TODO: b/329688428 - Check for test skips directly rather than doing a |
| // string comparison |
| if (std::string_view(json_impl::kSkipMacroIndicator) == |
| expectation.expression) { |
| test_record_trie_.AddTestResultExpectation(test_case, |
| TestResult::kSkipped); |
| } |
| } |
| |
| /// Converts the test record trie into a json string and returns it. |
| /// |
| /// @param[in] max_json_buffer_size The max size (in bytes) of the buffer to |
| /// allocate for the json string. |
| /// |
| /// @param[in] failing_results_only If true, the outputted test record will |
| /// only contain the failing tests. |
| /// |
| /// @returns The test record json as a string. |
| std::string GetTestRecordJsonString(size_t max_json_buffer_size, |
| bool failing_results_only = false) { |
| return test_record_trie_.GetTestRecordJsonString(run_tests_summary_, |
| seconds_since_epoch_, |
| max_json_buffer_size, |
| failing_results_only); |
| } |
| |
| void RunAllTestsStart() override {} |
| void TestProgramStart(const ProgramSummary&) override {} |
| void EnvironmentsSetUpEnd() override {} |
| void TestSuiteStart(const TestSuite&) override {} |
| void TestSuiteEnd(const TestSuite&) override {} |
| void EnvironmentsTearDownEnd() override {} |
| void TestProgramEnd(const ProgramSummary&) override {} |
| void TestCaseStart(const TestCase&) override {} |
| void TestCaseDisabled(const TestCase&) override {} |
| |
| private: |
| // Seconds since epoch from the start of the test run. |
| int64_t seconds_since_epoch_; |
| |
| // A summary of the test run. Set once RunAllTestsEnd is called and used when |
| // the consumer of this event handler wants to generate the test record json |
| // string. |
| RunTestsSummary run_tests_summary_; |
| |
| // The entrypoint for interacting with the test record trie. |
| json_impl::TestRecordTrie test_record_trie_; |
| }; |
| |
| } // namespace pw::unit_test |