Skip to content

Commit

Permalink
pw_unit_test: C++14-compatible printf-based event handler
Browse files Browse the repository at this point in the history
- Restructure existing unit test event handlers to share code for
  GoogleTest-style output.
- Create a C++14-compatible event handler that uses printf for output.

Change-Id: Iea1c87c83fe47fc0d09153e25eef674b23e1facc
Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/96204
Reviewed-by: Alexei Frolov <[email protected]>
Commit-Queue: Auto-Submit <[email protected]>
Pigweed-Auto-Submit: Wyatt Hepler <[email protected]>
  • Loading branch information
255 authored and CQ Bot Account committed May 31, 2022
1 parent d869e26 commit bb5fb4e
Show file tree
Hide file tree
Showing 14 changed files with 372 additions and 121 deletions.
2 changes: 1 addition & 1 deletion pw_build/pigweed.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ def pw_cc_library(**kwargs):

def pw_cc_test(**kwargs):
kwargs["deps"] = kwargs.get("deps", []) + \
["@pigweed//pw_unit_test:main"]
["@pigweed//pw_unit_test:simple_printing_main"]

# TODO(pwbug/440): Remove this implicit dependency once we have a better
# way to handle the facades without introducing a circular dependency into
Expand Down
2 changes: 1 addition & 1 deletion pw_build/pigweed.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -522,7 +522,7 @@ function(pw_set_module_config NAME LIBRARY)
set("${NAME}" "${LIBRARY}" CACHE STRING "Config for ${NAME}" FORCE)
endfunction(pw_set_module_config)

set(pw_unit_test_MAIN pw_unit_test.main CACHE STRING
set(pw_unit_test_MAIN pw_unit_test.simple_printing_main CACHE STRING
"Implementation of a main function for ``pw_test`` unit test binaries.")

set(pw_unit_test_GOOGLETEST_BACKEND pw_unit_test.light CACHE STRING
Expand Down
58 changes: 43 additions & 15 deletions pw_unit_test/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,16 @@ pw_cc_library(
includes = ["public"],
)

pw_cc_library(
name = "googletest_style_event_handler",
srcs = ["googletest_style_event_handler.cc"],
hdrs = ["public/pw_unit_test/googletest_style_event_handler.h"],
deps = [
":event_handler",
"//pw_preprocessor",
],
)

pw_cc_library(
name = "simple_printing_event_handler",
srcs = ["simple_printing_event_handler.cc"],
Expand All @@ -76,11 +86,42 @@ pw_cc_library(
"public",
],
deps = [
":event_handler",
":googletest_style_event_handler",
"//pw_preprocessor",
],
)

pw_cc_library(
name = "simple_printing_main",
srcs = [
"simple_printing_main.cc",
],
deps = [
":pw_unit_test",
":simple_printing_event_handler",
"//pw_span",
"//pw_sys_io",
],
)

pw_cc_library(
name = "printf_event_handler",
hdrs = ["public/pw_unit_test/printf_event_handler.h"],
deps = [
":googletest_style_event_handler",
"//pw_preprocessor",
],
)

pw_cc_library(
name = "printf_main",
srcs = ["printf_main.cc"],
deps = [
":printf_event_handler",
":pw_unit_test",
],
)

pw_cc_library(
name = "logging_event_handler",
srcs = [
Expand All @@ -93,7 +134,7 @@ pw_cc_library(
"public",
],
deps = [
":event_handler",
":googletest_style_event_handler",
"//pw_log",
],
)
Expand All @@ -109,19 +150,6 @@ pw_cc_binary(
],
)

pw_cc_library(
name = "main",
srcs = [
"simple_printing_main.cc",
],
deps = [
":pw_unit_test",
":simple_printing_event_handler",
"//pw_span",
"//pw_sys_io",
],
)

proto_library(
name = "unit_test_proto",
srcs = ["pw_unit_test_proto/unit_test.proto"],
Expand Down
33 changes: 29 additions & 4 deletions pw_unit_test/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -93,10 +93,20 @@ pw_source_set("event_handler") {
public = [ "public/pw_unit_test/event_handler.h" ]
}

# Unit test event handler that provides GoogleTest-style output.
pw_source_set("googletest_style_event_handler") {
public_deps = [
":event_handler",
dir_pw_preprocessor,
]
public = [ "public/pw_unit_test/googletest_style_event_handler.h" ]
sources = [ "googletest_style_event_handler.cc" ]
}

# Library providing an event handler which outputs human-readable text.
pw_source_set("simple_printing_event_handler") {
public_deps = [
":event_handler",
":googletest_style_event_handler",
"$dir_pw_preprocessor",
]
public = [ "public/pw_unit_test/simple_printing_event_handler.h" ]
Expand All @@ -115,12 +125,27 @@ pw_source_set("simple_printing_main") {
sources = [ "simple_printing_main.cc" ]
}

pw_source_set("printf_event_handler") {
public_deps = [
":googletest_style_event_handler",
dir_pw_preprocessor,
]
public = [ "public/pw_unit_test/printf_event_handler.h" ]
}

pw_source_set("printf_main") {
deps = [
":printf_event_handler",
":pw_unit_test",
]
sources = [ "printf_main.cc" ]
}

# Library providing an event handler which logs using pw_log.
pw_source_set("logging_event_handler") {
public_deps = [
":event_handler",
"$dir_pw_log",
"$dir_pw_preprocessor",
":googletest_style_event_handler",
dir_pw_log,
]
public = [ "public/pw_unit_test/logging_event_handler.h" ]
sources = [ "logging_event_handler.cc" ]
Expand Down
21 changes: 18 additions & 3 deletions pw_unit_test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -51,13 +51,28 @@ pw_add_module_library(pw_unit_test.static_library_support
pw_unit_test.light
)

pw_add_module_library(pw_unit_test.main
pw_add_module_library(pw_unit_test.event_handler
HEADERS
public/pw_unit_test/event_handler.h
)

pw_add_module_library(pw_unit_test.googletest_style_event_handler
PUBLIC_DEPS
pw_unit_test.event_handler
pw_preprocessor
HEADERS
public/pw_unit_test/googletest_style_event_handler.h
SOURCES
googletest_style_event_handler.cc
)

pw_add_module_library(pw_unit_test.simple_printing_main
SOURCES
simple_printing_main.cc
simple_printing_event_handler.cc
PUBLIC_DEPS
pw_unit_test
PRIVATE_DEPS
pw_unit_test
pw_unit_test.googletest_style_event_handler
pw_preprocessor
pw_string
pw_sys_io
Expand Down
31 changes: 25 additions & 6 deletions pw_unit_test/docs.rst
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,9 @@ the developer.
Predefined event handlers
-------------------------
Pigweed provides some standard event handlers upstream to simplify the process
of getting started using ``pw_unit_test``. All event handlers provide for
GoogleTest-style output.
of getting started using ``pw_unit_test:light``. All event handlers provide for
GoogleTest-style output using the shared
:cpp:class:`pw::unit_test::GoogleTestStyleEventHandler` base.

.. code-block::
Expand All @@ -90,10 +91,28 @@ GoogleTest-style output.
[==========] Done running all tests.
[ PASSED ] 8 test(s).
* ``SimplePrintingEventHandler``: An event handler that writes GoogleTest-style
output to a specified sink.
* ``LoggingEventHandler``: An event handler which uses the ``pw_log`` module to
output test results, to integrate with the system's existing logging setup.
.. cpp:namespace-push:: pw::unit_test

.. cpp:class:: GoogleTestStyleEventHandler

Provides GoogleTest-style output for ``pw_unit_test:light`` events. Must be
extended to define how to output the results.

.. cpp:class:: SimplePrintingEventHandler : public GoogleTestStyleEventHandler

An event handler that writes GoogleTest-style output to a specified sink.

.. cpp:class:: LoggingEventHandler : public GoogleTestStyleEventHandler

An event handler which uses the ``pw_log`` module to output test results, to
integrate with the system's existing logging setup.

.. cpp:class:: PrintfEventHandler : public GoogleTestStyleEventHandler

A C++14-compatible event handler that uses ``std::printf`` to output test
results.

.. cpp:namespace-pop::

Test filtering
==============
Expand Down
92 changes: 92 additions & 0 deletions pw_unit_test/googletest_style_event_handler.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
// Copyright 2022 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/googletest_style_event_handler.h"

#include <cstdarg>

namespace pw {
namespace unit_test {

// These must be declared here for C++14 compatibility.
constexpr const char GoogleTestStyleEventHandler::kRunAllTestsStart[];
constexpr const char GoogleTestStyleEventHandler::kRunAllTestsEnd[];

constexpr const char GoogleTestStyleEventHandler::kPassedSummary[];
constexpr const char GoogleTestStyleEventHandler::kSkippedSummary[];
constexpr const char GoogleTestStyleEventHandler::kFailedSummary[];

constexpr const char GoogleTestStyleEventHandler::kCaseStart[];
constexpr const char GoogleTestStyleEventHandler::kCaseOk[];
constexpr const char GoogleTestStyleEventHandler::kCaseFailed[];
constexpr const char GoogleTestStyleEventHandler::kCaseSkipped[];

void GoogleTestStyleEventHandler::RunAllTestsStart() {
WriteLine(kRunAllTestsStart);
}

void GoogleTestStyleEventHandler::RunAllTestsEnd(
const RunTestsSummary& run_tests_summary) {
WriteLine(kRunAllTestsEnd);
WriteLine(kPassedSummary, run_tests_summary.passed_tests);
if (run_tests_summary.skipped_tests) {
WriteLine(kSkippedSummary, run_tests_summary.skipped_tests);
}
if (run_tests_summary.failed_tests) {
WriteLine(kFailedSummary, run_tests_summary.failed_tests);
}
}

void GoogleTestStyleEventHandler::TestCaseStart(const TestCase& test_case) {
WriteLine(kCaseStart, test_case.suite_name, test_case.test_name);
}

void GoogleTestStyleEventHandler::TestCaseEnd(const TestCase& test_case,
TestResult result) {
// Use a switch with no default to detect changes in the test result enum.
switch (result) {
case TestResult::kSuccess:
WriteLine(kCaseOk, test_case.suite_name, test_case.test_name);
break;
case TestResult::kFailure:
WriteLine(kCaseFailed, test_case.suite_name, test_case.test_name);
break;
case TestResult::kSkipped:
WriteLine(kCaseSkipped, test_case.suite_name, test_case.test_name);
break;
}
}

void GoogleTestStyleEventHandler::TestCaseExpect(
const TestCase& test_case, const TestExpectation& expectation) {
if (!verbose_ && expectation.success) {
return;
}

const char* result = expectation.success ? "Success" : "Failure";
WriteLine("%s:%d: %s", test_case.file_name, expectation.line_number, result);
WriteLine(" Expected: %s", expectation.expression);

Write(" Actual: ");
WriteLine("%s", expectation.evaluated_expression);
}

void GoogleTestStyleEventHandler::TestCaseDisabled(const TestCase& test) {
if (verbose_) {
WriteLine("Skipping disabled test %s.%s", test.suite_name, test.test_name);
}
}

} // namespace unit_test
} // namespace pw
Loading

0 comments on commit bb5fb4e

Please sign in to comment.