• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // 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 
17 #include "pw_containers/vector.h"
18 #include "pw_log/log.h"
19 #include "pw_protobuf/decoder.h"
20 #include "pw_unit_test/framework.h"
21 
22 namespace pw::unit_test {
23 
Run(ServerContext &,ConstByteSpan request,RawServerWriter & writer)24 void UnitTestService::Run(ServerContext&,
25                           ConstByteSpan request,
26                           RawServerWriter& writer) {
27   writer_ = std::move(writer);
28   verbose_ = false;
29 
30   // List of test suite names to run. The string views in this vector point to
31   // data in the raw protobuf request message, so it is only valid for the
32   // duration of this function.
33   pw::Vector<std::string_view, 16> suites_to_run;
34 
35   protobuf::Decoder decoder(request);
36 
37   Status status;
38   while ((status = decoder.Next()).ok()) {
39     switch (static_cast<TestRunRequest::Fields>(decoder.FieldNumber())) {
40       case TestRunRequest::Fields::REPORT_PASSED_EXPECTATIONS:
41         decoder.ReadBool(&verbose_);
42         break;
43 
44       case TestRunRequest::Fields::TEST_SUITE: {
45         std::string_view suite_name;
46         if (!decoder.ReadString(&suite_name).ok()) {
47           break;
48         }
49 
50         if (!suites_to_run.full()) {
51           suites_to_run.push_back(suite_name);
52         } else {
53           PW_LOG_ERROR("Maximum of %d test suite filters supported",
54                        suites_to_run.max_size());
55           writer_.Finish(Status::InvalidArgument());
56           return;
57         }
58 
59         break;
60       }
61     }
62   }
63 
64   if (status != Status::OutOfRange()) {
65     writer_.Finish(status);
66     return;
67   }
68 
69   PW_LOG_INFO("Starting unit test run");
70 
71   RegisterEventHandler(&handler_);
72   SetTestSuitesToRun(suites_to_run);
73   PW_LOG_DEBUG("%u test suite filters applied",
74                static_cast<unsigned>(suites_to_run.size()));
75 
76   RUN_ALL_TESTS();
77 
78   RegisterEventHandler(nullptr);
79   SetTestSuitesToRun({});
80 
81   PW_LOG_INFO("Unit test run complete");
82 
83   writer_.Finish();
84 }
85 
WriteTestRunStart()86 void UnitTestService::WriteTestRunStart() {
87   // Write out the key for the start field (even though the message is empty).
88   WriteEvent([&](Event::Encoder& event) { event.GetTestRunStartEncoder(); });
89 }
90 
WriteTestRunEnd(const RunTestsSummary & summary)91 void UnitTestService::WriteTestRunEnd(const RunTestsSummary& summary) {
92   WriteEvent([&](Event::Encoder& event) {
93     TestRunEnd::Encoder test_run_end = event.GetTestRunEndEncoder();
94     test_run_end.WritePassed(summary.passed_tests);
95     test_run_end.WriteFailed(summary.failed_tests);
96     test_run_end.WriteSkipped(summary.skipped_tests);
97     test_run_end.WriteDisabled(summary.disabled_tests);
98   });
99 }
100 
WriteTestCaseStart(const TestCase & test_case)101 void UnitTestService::WriteTestCaseStart(const TestCase& test_case) {
102   WriteEvent([&](Event::Encoder& event) {
103     TestCaseDescriptor::Encoder descriptor = event.GetTestCaseStartEncoder();
104     descriptor.WriteSuiteName(test_case.suite_name);
105     descriptor.WriteTestName(test_case.test_name);
106     descriptor.WriteFileName(test_case.file_name);
107   });
108 }
109 
WriteTestCaseEnd(TestResult result)110 void UnitTestService::WriteTestCaseEnd(TestResult result) {
111   WriteEvent([&](Event::Encoder& event) {
112     event.WriteTestCaseEnd(static_cast<TestCaseResult>(result));
113   });
114 }
115 
WriteTestCaseDisabled(const TestCase & test_case)116 void UnitTestService::WriteTestCaseDisabled(const TestCase& test_case) {
117   WriteEvent([&](Event::Encoder& event) {
118     TestCaseDescriptor::Encoder descriptor = event.GetTestCaseDisabledEncoder();
119     descriptor.WriteSuiteName(test_case.suite_name);
120     descriptor.WriteTestName(test_case.test_name);
121     descriptor.WriteFileName(test_case.file_name);
122   });
123 }
124 
WriteTestCaseExpectation(const TestExpectation & expectation)125 void UnitTestService::WriteTestCaseExpectation(
126     const TestExpectation& expectation) {
127   if (!verbose_ && expectation.success) {
128     return;
129   }
130 
131   WriteEvent([&](Event::Encoder& event) {
132     TestCaseExpectation::Encoder test_case_expectation =
133         event.GetTestCaseExpectationEncoder();
134     test_case_expectation.WriteExpression(expectation.expression);
135     test_case_expectation.WriteEvaluatedExpression(
136         expectation.evaluated_expression);
137     test_case_expectation.WriteLineNumber(expectation.line_number);
138     test_case_expectation.WriteSuccess(expectation.success);
139   });
140 }
141 
142 }  // namespace pw::unit_test
143