Alexei Frolov | 8024679 | 2020-11-05 21:12:45 -0800 | [diff] [blame] | 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 | |
Alexei Frolov | 47a4304 | 2021-04-06 14:19:55 -0700 | [diff] [blame] | 17 | #include "pw_containers/vector.h" |
Alexei Frolov | 8024679 | 2020-11-05 21:12:45 -0800 | [diff] [blame] | 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 | |
Wyatt Hepler | 8e756e3 | 2021-11-18 09:59:27 -0800 | [diff] [blame] | 24 | void UnitTestService::Run(ConstByteSpan request, RawServerWriter& writer) { |
Alexei Frolov | 8024679 | 2020-11-05 21:12:45 -0800 | [diff] [blame] | 25 | writer_ = std::move(writer); |
| 26 | verbose_ = false; |
| 27 | |
Alexei Frolov | 47a4304 | 2021-04-06 14:19:55 -0700 | [diff] [blame] | 28 | // 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 Frolov | 8024679 | 2020-11-05 21:12:45 -0800 | [diff] [blame] | 33 | 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 Larbanet | d1ca56c | 2021-06-10 14:20:45 +0000 | [diff] [blame] | 39 | decoder.ReadBool(&verbose_) |
| 40 | .IgnoreError(); // TODO(pwbug/387): Handle Status properly |
Alexei Frolov | 8024679 | 2020-11-05 21:12:45 -0800 | [diff] [blame] | 41 | break; |
Alexei Frolov | 47a4304 | 2021-04-06 14:19:55 -0700 | [diff] [blame] | 42 | |
| 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 Hepler | 81017fe | 2021-08-02 17:46:41 -0700 | [diff] [blame] | 52 | PW_LOG_ERROR("Maximum of %u test suite filters supported", |
| 53 | static_cast<unsigned>(suites_to_run.max_size())); |
Adrien Larbanet | d1ca56c | 2021-06-10 14:20:45 +0000 | [diff] [blame] | 54 | writer_.Finish(Status::InvalidArgument()) |
| 55 | .IgnoreError(); // TODO(pwbug/387): Handle Status properly |
Alexei Frolov | 47a4304 | 2021-04-06 14:19:55 -0700 | [diff] [blame] | 56 | return; |
| 57 | } |
| 58 | |
| 59 | break; |
| 60 | } |
Alexei Frolov | 8024679 | 2020-11-05 21:12:45 -0800 | [diff] [blame] | 61 | } |
| 62 | } |
| 63 | |
| 64 | if (status != Status::OutOfRange()) { |
Adrien Larbanet | d1ca56c | 2021-06-10 14:20:45 +0000 | [diff] [blame] | 65 | writer_.Finish(status) |
| 66 | .IgnoreError(); // TODO(pwbug/387): Handle Status properly |
Alexei Frolov | 8024679 | 2020-11-05 21:12:45 -0800 | [diff] [blame] | 67 | return; |
| 68 | } |
| 69 | |
Alexei Frolov | 47a4304 | 2021-04-06 14:19:55 -0700 | [diff] [blame] | 70 | PW_LOG_INFO("Starting unit test run"); |
Alexei Frolov | 8024679 | 2020-11-05 21:12:45 -0800 | [diff] [blame] | 71 | |
Alexei Frolov | 47a4304 | 2021-04-06 14:19:55 -0700 | [diff] [blame] | 72 | 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 Frolov | 8024679 | 2020-11-05 21:12:45 -0800 | [diff] [blame] | 77 | RUN_ALL_TESTS(); |
Alexei Frolov | 47a4304 | 2021-04-06 14:19:55 -0700 | [diff] [blame] | 78 | |
| 79 | RegisterEventHandler(nullptr); |
| 80 | SetTestSuitesToRun({}); |
| 81 | |
| 82 | PW_LOG_INFO("Unit test run complete"); |
Alexei Frolov | 8024679 | 2020-11-05 21:12:45 -0800 | [diff] [blame] | 83 | |
Adrien Larbanet | d1ca56c | 2021-06-10 14:20:45 +0000 | [diff] [blame] | 84 | writer_.Finish().IgnoreError(); // TODO(pwbug/387): Handle Status properly |
Alexei Frolov | 8024679 | 2020-11-05 21:12:45 -0800 | [diff] [blame] | 85 | } |
| 86 | |
| 87 | void UnitTestService::WriteTestRunStart() { |
| 88 | // Write out the key for the start field (even though the message is empty). |
Armando Montanez | 32988e0 | 2021-05-21 11:56:09 -0700 | [diff] [blame] | 89 | WriteEvent( |
| 90 | [&](Event::StreamEncoder& event) { event.GetTestRunStartEncoder(); }); |
Alexei Frolov | 8024679 | 2020-11-05 21:12:45 -0800 | [diff] [blame] | 91 | } |
| 92 | |
| 93 | void UnitTestService::WriteTestRunEnd(const RunTestsSummary& summary) { |
Armando Montanez | 32988e0 | 2021-05-21 11:56:09 -0700 | [diff] [blame] | 94 | WriteEvent([&](Event::StreamEncoder& event) { |
| 95 | TestRunEnd::StreamEncoder test_run_end = event.GetTestRunEndEncoder(); |
Adrien Larbanet | d1ca56c | 2021-06-10 14:20:45 +0000 | [diff] [blame] | 96 | 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 Frolov | 8024679 | 2020-11-05 21:12:45 -0800 | [diff] [blame] | 104 | }); |
| 105 | } |
| 106 | |
| 107 | void UnitTestService::WriteTestCaseStart(const TestCase& test_case) { |
Armando Montanez | 32988e0 | 2021-05-21 11:56:09 -0700 | [diff] [blame] | 108 | WriteEvent([&](Event::StreamEncoder& event) { |
| 109 | TestCaseDescriptor::StreamEncoder descriptor = |
| 110 | event.GetTestCaseStartEncoder(); |
Adrien Larbanet | d1ca56c | 2021-06-10 14:20:45 +0000 | [diff] [blame] | 111 | 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 Frolov | 8024679 | 2020-11-05 21:12:45 -0800 | [diff] [blame] | 117 | }); |
| 118 | } |
| 119 | |
| 120 | void UnitTestService::WriteTestCaseEnd(TestResult result) { |
Armando Montanez | 32988e0 | 2021-05-21 11:56:09 -0700 | [diff] [blame] | 121 | WriteEvent([&](Event::StreamEncoder& event) { |
Adrien Larbanet | d1ca56c | 2021-06-10 14:20:45 +0000 | [diff] [blame] | 122 | event.WriteTestCaseEnd(static_cast<TestCaseResult>(result)) |
| 123 | .IgnoreError(); // TODO(pwbug/387): Handle Status properly |
Alexei Frolov | 8024679 | 2020-11-05 21:12:45 -0800 | [diff] [blame] | 124 | }); |
| 125 | } |
| 126 | |
| 127 | void UnitTestService::WriteTestCaseDisabled(const TestCase& test_case) { |
Armando Montanez | 32988e0 | 2021-05-21 11:56:09 -0700 | [diff] [blame] | 128 | WriteEvent([&](Event::StreamEncoder& event) { |
| 129 | TestCaseDescriptor::StreamEncoder descriptor = |
| 130 | event.GetTestCaseDisabledEncoder(); |
Adrien Larbanet | d1ca56c | 2021-06-10 14:20:45 +0000 | [diff] [blame] | 131 | 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 Frolov | 8024679 | 2020-11-05 21:12:45 -0800 | [diff] [blame] | 137 | }); |
| 138 | } |
| 139 | |
| 140 | void UnitTestService::WriteTestCaseExpectation( |
| 141 | const TestExpectation& expectation) { |
| 142 | if (!verbose_ && expectation.success) { |
| 143 | return; |
| 144 | } |
| 145 | |
Armando Montanez | 32988e0 | 2021-05-21 11:56:09 -0700 | [diff] [blame] | 146 | WriteEvent([&](Event::StreamEncoder& event) { |
| 147 | TestCaseExpectation::StreamEncoder test_case_expectation = |
Alexei Frolov | 8024679 | 2020-11-05 21:12:45 -0800 | [diff] [blame] | 148 | event.GetTestCaseExpectationEncoder(); |
Adrien Larbanet | d1ca56c | 2021-06-10 14:20:45 +0000 | [diff] [blame] | 149 | 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 Frolov | 8024679 | 2020-11-05 21:12:45 -0800 | [diff] [blame] | 158 | }); |
| 159 | } |
| 160 | |
| 161 | } // namespace pw::unit_test |