Skip to content

Commit

Permalink
pw_unit_test: Add multi event handler and tests for it
Browse files Browse the repository at this point in the history
Change-Id: Ic770c7d2d8a3d9680b94bf95af141ba7aa8184ff
Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/188911
Reviewed-by: Wyatt Hepler <hepler@google.com>
Commit-Queue: Samuel Liu <slliu@google.com>
Presubmit-Verified: CQ Bot Account <pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com>
  • Loading branch information
samliu000 authored and CQ Bot Account committed Jan 26, 2024
1 parent 894c1ef commit 6b853a8
Show file tree
Hide file tree
Showing 6 changed files with 319 additions and 0 deletions.
22 changes: 22 additions & 0 deletions pw_unit_test/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,28 @@ pw_cc_binary(
],
)

cc_library(
name = "multi_event_handler",
hdrs = [
"public/pw_unit_test/multi_event_handler.h",
],
includes = [
"public",
],
deps = [
":event_handler",
],
)

pw_cc_test(
name = "multi_event_handler_test",
srcs = ["multi_event_handler_test.cc"],
deps = [
":multi_event_handler",
":pw_unit_test",
],
)

proto_library(
name = "unit_test_proto",
srcs = ["pw_unit_test_proto/unit_test.proto"],
Expand Down
16 changes: 16 additions & 0 deletions pw_unit_test/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,21 @@ pw_source_set("logging_main") {
sources = [ "logging_main.cc" ]
}

# Library providing an event handler adapter that allows for multiple
# event handlers to be registered for a given test run
pw_source_set("multi_event_handler") {
public_deps = [ ":event_handler" ]
public = [ "public/pw_unit_test/multi_event_handler.h" ]
}

pw_test("multi_event_handler_test") {
sources = [ "multi_event_handler_test.cc" ]
deps = [
":multi_event_handler",
":pw_unit_test",
]
}

config("rpc_service_backend_light") {
include_dirs = [ "rpc_light_public" ]
}
Expand Down Expand Up @@ -379,6 +394,7 @@ pw_test_group("tests") {
":framework_test",
":framework_light_test",
":static_library_support_test",
":multi_event_handler_test",
]
if (dir_pw_third_party_googletest != "") {
tests += [ ":googletest_test_matchers_test" ]
Expand Down
18 changes: 18 additions & 0 deletions pw_unit_test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -175,3 +175,21 @@ pw_add_library(pw_unit_test.logging_main STATIC
pw_unit_test.logging_event_handler
pw_unit_test
)

pw_add_library(pw_unit_test.multi_event_handler INTERFACE
HEADERS
public/pw_unit_test/multi_event_handler.h
PUBLIC_INCLUDES
public
PUBLIC_DEPS
pw_unit_test.event_handler
)

pw_add_test(pw_unit_test.multi_event_handler_test
SOURCES
multi_event_handler_test.cc
PRIVATE_DEPS
pw_unit_test.multi_event_handler
GROUPS
pw_unit_test
)
7 changes: 7 additions & 0 deletions pw_unit_test/docs.rst
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,13 @@ GoogleTest-style output using the shared

Event handler that uses ``std::printf`` to output test results.

.. cpp:class:: MultiEventHandler : public GoogleTestStyleEventHandler

An event handler adapter that allows you to register multiple event handlers
for a test run. To use it, create a MultiEventHandler object by passing
in the event handlers you want to use into the constructor. Then, register
the MultiEventHandler object as the test run's event handler.

.. cpp:namespace-pop::

Test filtering
Expand Down
155 changes: 155 additions & 0 deletions pw_unit_test/multi_event_handler_test.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
// 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.

#include "pw_unit_test/multi_event_handler.h"

#include "pw_unit_test/framework.h"

namespace pw::unit_test {
namespace {

// Fake event handler that keeps track of how many times its functions were
// invoked
class FakeEventHandler : public EventHandler {
public:
struct {
int TestProgramStart = 0;
int EnvironmentsSetUpEnd = 0;
int TestSuiteStart = 0;
int TestSuiteEnd = 0;
int EnvironmentsTearDownEnd = 0;
int TestProgramEnd = 0;
int RunAllTestsStart = 0;
int RunAllTestsEnd = 0;
int TestCaseStart = 0;
int TestCaseEnd = 0;
int TestCaseExpect = 0;
int TestCaseDisabled = 0;
} function_invocation_counts;

void TestProgramStart(const ProgramSummary&) override {
function_invocation_counts.TestProgramStart++;
}
void EnvironmentsSetUpEnd() override {
function_invocation_counts.EnvironmentsSetUpEnd++;
}
void TestSuiteStart(const TestSuite&) override {
function_invocation_counts.TestSuiteStart++;
}
void TestSuiteEnd(const TestSuite&) override {
function_invocation_counts.TestSuiteEnd++;
}
void EnvironmentsTearDownEnd() override {
function_invocation_counts.EnvironmentsTearDownEnd++;
}
void TestProgramEnd(const ProgramSummary&) override {
function_invocation_counts.TestProgramEnd++;
}
void RunAllTestsStart() override {
function_invocation_counts.RunAllTestsStart++;
}
void RunAllTestsEnd(const RunTestsSummary&) override {
function_invocation_counts.RunAllTestsEnd++;
}
void TestCaseStart(const TestCase&) override {
function_invocation_counts.TestCaseStart++;
}
void TestCaseEnd(const TestCase&, TestResult) override {
function_invocation_counts.TestCaseEnd++;
}
void TestCaseExpect(const TestCase&, const TestExpectation&) override {
function_invocation_counts.TestCaseExpect++;
}
void TestCaseDisabled(const TestCase&) override {
function_invocation_counts.TestCaseDisabled++;
}
};

// Helper method for ensuring all methods of an event handler were called x
// number of times
void AssertFunctionInvocationCounts(FakeEventHandler handler,
int num_invocations) {
ASSERT_EQ(handler.function_invocation_counts.TestProgramStart,
num_invocations);
ASSERT_EQ(handler.function_invocation_counts.EnvironmentsSetUpEnd,
num_invocations);
ASSERT_EQ(handler.function_invocation_counts.TestSuiteStart, num_invocations);
ASSERT_EQ(handler.function_invocation_counts.TestSuiteEnd, num_invocations);
ASSERT_EQ(handler.function_invocation_counts.EnvironmentsTearDownEnd,
num_invocations);
ASSERT_EQ(handler.function_invocation_counts.TestProgramEnd, num_invocations);
ASSERT_EQ(handler.function_invocation_counts.RunAllTestsStart,
num_invocations);
ASSERT_EQ(handler.function_invocation_counts.RunAllTestsEnd, num_invocations);
ASSERT_EQ(handler.function_invocation_counts.TestCaseStart, num_invocations);
ASSERT_EQ(handler.function_invocation_counts.TestCaseEnd, num_invocations);
ASSERT_EQ(handler.function_invocation_counts.TestCaseExpect, num_invocations);
ASSERT_EQ(handler.function_invocation_counts.TestCaseDisabled,
num_invocations);
}

TEST(AllEventHandlerMethodsCalled, InvokeMethodMultipleTimes) {
FakeEventHandler h1;
FakeEventHandler h2;
MultiEventHandler<2> multi_handler(h1, h2);

ASSERT_EQ(h1.function_invocation_counts.TestCaseStart, 0);
ASSERT_EQ(h2.function_invocation_counts.TestCaseEnd, 0);

TestCase test_case{};
TestResult test_result = TestResult::kSuccess;
multi_handler.TestCaseStart(test_case);
multi_handler.TestCaseStart(test_case);
multi_handler.TestCaseStart(test_case);
multi_handler.TestCaseEnd(test_case, test_result);
multi_handler.TestCaseEnd(test_case, test_result);
multi_handler.TestCaseEnd(test_case, test_result);

ASSERT_EQ(h1.function_invocation_counts.TestCaseStart, 3);
ASSERT_EQ(h2.function_invocation_counts.TestCaseEnd, 3);
}

TEST(AllEventHandlerMethodsCalled, InvokeAllEventHandlerMethods) {
FakeEventHandler h1;
FakeEventHandler h2;
MultiEventHandler<2> multi_handler(h1, h2);

AssertFunctionInvocationCounts(h1, 0);
AssertFunctionInvocationCounts(h2, 0);

ProgramSummary program_summary{};
TestSuite test_suite{};
TestCase test_case{};
RunTestsSummary run_test_summary{};
TestExpectation expectation{};
TestResult test_result = TestResult::kSuccess;
multi_handler.TestProgramStart(program_summary);
multi_handler.EnvironmentsSetUpEnd();
multi_handler.TestSuiteStart(test_suite);
multi_handler.TestSuiteEnd(test_suite);
multi_handler.EnvironmentsTearDownEnd();
multi_handler.TestProgramEnd(program_summary);
multi_handler.RunAllTestsStart();
multi_handler.RunAllTestsEnd(run_test_summary);
multi_handler.TestCaseStart(test_case);
multi_handler.TestCaseEnd(test_case, test_result);
multi_handler.TestCaseExpect(test_case, expectation);
multi_handler.TestCaseDisabled(test_case);

AssertFunctionInvocationCounts(h1, 1);
AssertFunctionInvocationCounts(h2, 1);
}

} // namespace
} // namespace pw::unit_test
101 changes: 101 additions & 0 deletions pw_unit_test/public/pw_unit_test/multi_event_handler.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
// 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 <array>
#include <cstddef>

#include "pw_unit_test/event_handler.h"

namespace pw::unit_test {

// An event handler adapter that allows for multiple event handlers to be
// registered and used during test runs
template <size_t kNumHandlers>
class MultiEventHandler : public EventHandler {
public:
template <
typename... EventHandlers,
typename = std::enable_if_t<sizeof...(EventHandlers) == kNumHandlers>>
constexpr MultiEventHandler(EventHandlers&... event_handlers)
: event_handlers_{&event_handlers...} {}

void TestProgramStart(const ProgramSummary& program_summary) override {
for (EventHandler* event_handler : event_handlers_) {
event_handler->TestProgramStart(program_summary);
}
}
void EnvironmentsSetUpEnd() override {
for (EventHandler* event_handler : event_handlers_) {
event_handler->EnvironmentsSetUpEnd();
}
}
void TestSuiteStart(const TestSuite& test_suite) override {
for (EventHandler* event_handler : event_handlers_) {
event_handler->TestSuiteStart(test_suite);
}
}
void TestSuiteEnd(const TestSuite& test_suite) override {
for (EventHandler* event_handler : event_handlers_) {
event_handler->TestSuiteEnd(test_suite);
}
}
void EnvironmentsTearDownEnd() override {
for (EventHandler* event_handler : event_handlers_) {
event_handler->EnvironmentsTearDownEnd();
}
}
void TestProgramEnd(const ProgramSummary& program_summary) override {
for (EventHandler* event_handler : event_handlers_) {
event_handler->TestProgramEnd(program_summary);
}
}
void RunAllTestsStart() override {
for (EventHandler* event_handler : event_handlers_) {
event_handler->RunAllTestsStart();
}
}
void RunAllTestsEnd(const RunTestsSummary& run_tests_summary) override {
for (EventHandler* event_handler : event_handlers_) {
event_handler->RunAllTestsEnd(run_tests_summary);
}
}
void TestCaseStart(const TestCase& test_case) override {
for (EventHandler* event_handler : event_handlers_) {
event_handler->TestCaseStart(test_case);
}
}
void TestCaseEnd(const TestCase& test_case, TestResult result) override {
for (EventHandler* event_handler : event_handlers_) {
event_handler->TestCaseEnd(test_case, result);
}
}
void TestCaseExpect(const TestCase& test_case,
const TestExpectation& expectation) override {
for (EventHandler* event_handler : event_handlers_) {
event_handler->TestCaseExpect(test_case, expectation);
}
}
void TestCaseDisabled(const TestCase& test_case) override {
for (EventHandler* event_handler : event_handlers_) {
event_handler->TestCaseDisabled(test_case);
}
}

private:
static_assert(kNumHandlers > 0);
std::array<EventHandler*, kNumHandlers> event_handlers_;
};

} // namespace pw::unit_test

0 comments on commit 6b853a8

Please sign in to comment.