blob: 596575586c8fe50981ca37c591552402756e9d0f [file] [log] [blame]
Alexei Frolov80246792020-11-05 21:12:45 -08001// Copyright 2020 The Pigweed Authors
2//
3// Licensed under the Apache License, Version 2.0 (the "License"); you may not
4// use this file except in compliance with the License. You may obtain a copy of
5// the License at
6//
7// https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12// License for the specific language governing permissions and limitations under
13// the License.
14
15#include "pw_unit_test/unit_test_service.h"
16
Alexei Frolov47a43042021-04-06 14:19:55 -070017#include "pw_containers/vector.h"
Alexei Frolov80246792020-11-05 21:12:45 -080018#include "pw_log/log.h"
19#include "pw_protobuf/decoder.h"
20#include "pw_unit_test/framework.h"
21
22namespace pw::unit_test {
23
Wyatt Hepler8e756e32021-11-18 09:59:27 -080024void UnitTestService::Run(ConstByteSpan request, RawServerWriter& writer) {
Alexei Frolov80246792020-11-05 21:12:45 -080025 writer_ = std::move(writer);
26 verbose_ = false;
27
Alexei Frolov47a43042021-04-06 14:19:55 -070028 // List of test suite names to run. The string views in this vector point to
29 // data in the raw protobuf request message, so it is only valid for the
30 // duration of this function.
31 pw::Vector<std::string_view, 16> suites_to_run;
32
Alexei Frolov80246792020-11-05 21:12:45 -080033 protobuf::Decoder decoder(request);
34
35 Status status;
36 while ((status = decoder.Next()).ok()) {
37 switch (static_cast<TestRunRequest::Fields>(decoder.FieldNumber())) {
38 case TestRunRequest::Fields::REPORT_PASSED_EXPECTATIONS:
Adrien Larbanetd1ca56c2021-06-10 14:20:45 +000039 decoder.ReadBool(&verbose_)
40 .IgnoreError(); // TODO(pwbug/387): Handle Status properly
Alexei Frolov80246792020-11-05 21:12:45 -080041 break;
Alexei Frolov47a43042021-04-06 14:19:55 -070042
43 case TestRunRequest::Fields::TEST_SUITE: {
44 std::string_view suite_name;
45 if (!decoder.ReadString(&suite_name).ok()) {
46 break;
47 }
48
49 if (!suites_to_run.full()) {
50 suites_to_run.push_back(suite_name);
51 } else {
Wyatt Hepler81017fe2021-08-02 17:46:41 -070052 PW_LOG_ERROR("Maximum of %u test suite filters supported",
53 static_cast<unsigned>(suites_to_run.max_size()));
Adrien Larbanetd1ca56c2021-06-10 14:20:45 +000054 writer_.Finish(Status::InvalidArgument())
55 .IgnoreError(); // TODO(pwbug/387): Handle Status properly
Alexei Frolov47a43042021-04-06 14:19:55 -070056 return;
57 }
58
59 break;
60 }
Alexei Frolov80246792020-11-05 21:12:45 -080061 }
62 }
63
64 if (status != Status::OutOfRange()) {
Adrien Larbanetd1ca56c2021-06-10 14:20:45 +000065 writer_.Finish(status)
66 .IgnoreError(); // TODO(pwbug/387): Handle Status properly
Alexei Frolov80246792020-11-05 21:12:45 -080067 return;
68 }
69
Alexei Frolov47a43042021-04-06 14:19:55 -070070 PW_LOG_INFO("Starting unit test run");
Alexei Frolov80246792020-11-05 21:12:45 -080071
Alexei Frolov47a43042021-04-06 14:19:55 -070072 RegisterEventHandler(&handler_);
73 SetTestSuitesToRun(suites_to_run);
74 PW_LOG_DEBUG("%u test suite filters applied",
75 static_cast<unsigned>(suites_to_run.size()));
76
Alexei Frolov80246792020-11-05 21:12:45 -080077 RUN_ALL_TESTS();
Alexei Frolov47a43042021-04-06 14:19:55 -070078
79 RegisterEventHandler(nullptr);
80 SetTestSuitesToRun({});
81
82 PW_LOG_INFO("Unit test run complete");
Alexei Frolov80246792020-11-05 21:12:45 -080083
Adrien Larbanetd1ca56c2021-06-10 14:20:45 +000084 writer_.Finish().IgnoreError(); // TODO(pwbug/387): Handle Status properly
Alexei Frolov80246792020-11-05 21:12:45 -080085}
86
87void UnitTestService::WriteTestRunStart() {
88 // Write out the key for the start field (even though the message is empty).
Armando Montanez32988e02021-05-21 11:56:09 -070089 WriteEvent(
90 [&](Event::StreamEncoder& event) { event.GetTestRunStartEncoder(); });
Alexei Frolov80246792020-11-05 21:12:45 -080091}
92
93void UnitTestService::WriteTestRunEnd(const RunTestsSummary& summary) {
Armando Montanez32988e02021-05-21 11:56:09 -070094 WriteEvent([&](Event::StreamEncoder& event) {
95 TestRunEnd::StreamEncoder test_run_end = event.GetTestRunEndEncoder();
Adrien Larbanetd1ca56c2021-06-10 14:20:45 +000096 test_run_end.WritePassed(summary.passed_tests)
97 .IgnoreError(); // TODO(pwbug/387): Handle Status properly
98 test_run_end.WriteFailed(summary.failed_tests)
99 .IgnoreError(); // TODO(pwbug/387): Handle Status properly
100 test_run_end.WriteSkipped(summary.skipped_tests)
101 .IgnoreError(); // TODO(pwbug/387): Handle Status properly
102 test_run_end.WriteDisabled(summary.disabled_tests)
103 .IgnoreError(); // TODO(pwbug/387): Handle Status properly
Alexei Frolov80246792020-11-05 21:12:45 -0800104 });
105}
106
107void UnitTestService::WriteTestCaseStart(const TestCase& test_case) {
Armando Montanez32988e02021-05-21 11:56:09 -0700108 WriteEvent([&](Event::StreamEncoder& event) {
109 TestCaseDescriptor::StreamEncoder descriptor =
110 event.GetTestCaseStartEncoder();
Adrien Larbanetd1ca56c2021-06-10 14:20:45 +0000111 descriptor.WriteSuiteName(test_case.suite_name)
112 .IgnoreError(); // TODO(pwbug/387): Handle Status properly
113 descriptor.WriteTestName(test_case.test_name)
114 .IgnoreError(); // TODO(pwbug/387): Handle Status properly
115 descriptor.WriteFileName(test_case.file_name)
116 .IgnoreError(); // TODO(pwbug/387): Handle Status properly
Alexei Frolov80246792020-11-05 21:12:45 -0800117 });
118}
119
120void UnitTestService::WriteTestCaseEnd(TestResult result) {
Armando Montanez32988e02021-05-21 11:56:09 -0700121 WriteEvent([&](Event::StreamEncoder& event) {
Adrien Larbanetd1ca56c2021-06-10 14:20:45 +0000122 event.WriteTestCaseEnd(static_cast<TestCaseResult>(result))
123 .IgnoreError(); // TODO(pwbug/387): Handle Status properly
Alexei Frolov80246792020-11-05 21:12:45 -0800124 });
125}
126
127void UnitTestService::WriteTestCaseDisabled(const TestCase& test_case) {
Armando Montanez32988e02021-05-21 11:56:09 -0700128 WriteEvent([&](Event::StreamEncoder& event) {
129 TestCaseDescriptor::StreamEncoder descriptor =
130 event.GetTestCaseDisabledEncoder();
Adrien Larbanetd1ca56c2021-06-10 14:20:45 +0000131 descriptor.WriteSuiteName(test_case.suite_name)
132 .IgnoreError(); // TODO(pwbug/387): Handle Status properly
133 descriptor.WriteTestName(test_case.test_name)
134 .IgnoreError(); // TODO(pwbug/387): Handle Status properly
135 descriptor.WriteFileName(test_case.file_name)
136 .IgnoreError(); // TODO(pwbug/387): Handle Status properly
Alexei Frolov80246792020-11-05 21:12:45 -0800137 });
138}
139
140void UnitTestService::WriteTestCaseExpectation(
141 const TestExpectation& expectation) {
142 if (!verbose_ && expectation.success) {
143 return;
144 }
145
Armando Montanez32988e02021-05-21 11:56:09 -0700146 WriteEvent([&](Event::StreamEncoder& event) {
147 TestCaseExpectation::StreamEncoder test_case_expectation =
Alexei Frolov80246792020-11-05 21:12:45 -0800148 event.GetTestCaseExpectationEncoder();
Adrien Larbanetd1ca56c2021-06-10 14:20:45 +0000149 test_case_expectation.WriteExpression(expectation.expression)
150 .IgnoreError(); // TODO(pwbug/387): Handle Status properly
151 test_case_expectation
152 .WriteEvaluatedExpression(expectation.evaluated_expression)
153 .IgnoreError(); // TODO(pwbug/387): Handle Status properly
154 test_case_expectation.WriteLineNumber(expectation.line_number)
155 .IgnoreError(); // TODO(pwbug/387): Handle Status properly
156 test_case_expectation.WriteSuccess(expectation.success)
157 .IgnoreError(); // TODO(pwbug/387): Handle Status properly
Alexei Frolov80246792020-11-05 21:12:45 -0800158 });
159}
160
161} // namespace pw::unit_test