blob: dbcaf45836e6b3bce3221a74ae65c28eb0e43972 [file] [log] [blame]
Josh Haberman35a1cc72015-04-01 17:23:48 -07001// Protocol Buffers - Google's data interchange format
2// Copyright 2008 Google Inc. All rights reserved.
Josh Haberman35a1cc72015-04-01 17:23:48 -07003//
Joshua Haberman8a4bfd62023-09-08 19:26:10 -07004// Use of this source code is governed by a BSD-style
5// license that can be found in the LICENSE file or at
6// https://developers.google.com/open-source/licenses/bsd
Josh Haberman35a1cc72015-04-01 17:23:48 -07007
Josh Haberman4e63b522015-04-14 13:45:39 -07008#include "conformance_test.h"
Joshua Habermanf1ce60e2016-12-03 11:51:25 -05009
Rafi Kamal58d44202019-11-11 17:06:56 -080010#include <stdarg.h>
11
Mike Kruskal39752aa2023-10-17 16:58:29 -070012#include <cstddef>
13#include <cstdint>
Rafi Kamal58d44202019-11-11 17:06:56 -080014#include <fstream>
Mike Kruskal39752aa2023-10-17 16:58:29 -070015#include <memory>
Rafi Kamal58d44202019-11-11 17:06:56 -080016#include <string>
17
Mike Kruskal15954172022-09-09 10:42:19 -070018#include "google/protobuf/util/field_comparator.h"
Mike Kruskal15954172022-09-09 10:42:19 -070019#include "google/protobuf/util/message_differencer.h"
Mike Kruskal39752aa2023-10-17 16:58:29 -070020#include "absl/log/absl_check.h"
Mike Kruskala9f1ea62023-01-24 21:49:33 -080021#include "absl/log/absl_log.h"
Mike Kruskale99b2812022-09-23 14:27:46 -070022#include "absl/strings/str_cat.h"
23#include "absl/strings/str_format.h"
Mike Kruskal2166cce2022-12-21 20:38:13 -080024#include "absl/strings/string_view.h"
Mike Kruskalca4b0632022-08-11 20:55:01 -070025#include "conformance/conformance.pb.h"
Mike Kruskal32bea522022-10-06 16:48:39 -070026#include "conformance/conformance.pb.h"
Mike Kruskalbdeacc72023-03-14 15:49:23 -070027#include "google/protobuf/descriptor_legacy.h"
Protobuf Team Bot0287cf42023-08-22 07:26:58 -070028#include "google/protobuf/message.h"
29#include "google/protobuf/text_format.h"
Feng Xiaoe841bac2015-12-11 17:09:20 -080030
Josh Haberman35a1cc72015-04-01 17:23:48 -070031using conformance::ConformanceRequest;
32using conformance::ConformanceResponse;
Josh Habermanb0500b32015-07-10 16:36:59 -070033using conformance::WireFormat;
Feng Xiaoe841bac2015-12-11 17:09:20 -080034using google::protobuf::util::DefaultFieldComparator;
Josh Habermanb0500b32015-07-10 16:36:59 -070035using google::protobuf::util::MessageDifferencer;
Josh Haberman35a1cc72015-04-01 17:23:48 -070036using std::string;
37
Paul Yanga9bb6562019-07-26 10:05:14 -070038namespace {
39
Mike Kruskal39752aa2023-10-17 16:58:29 -070040static std::string ToOctString(const std::string& binary_string) {
41 std::string oct_string;
Paul Yanga9bb6562019-07-26 10:05:14 -070042 for (size_t i = 0; i < binary_string.size(); i++) {
43 uint8_t c = binary_string.at(i);
44 uint8_t high = c / 64;
45 uint8_t mid = (c % 64) / 8;
46 uint8_t low = c % 8;
47 oct_string.push_back('\\');
48 oct_string.push_back('0' + high);
49 oct_string.push_back('0' + mid);
50 oct_string.push_back('0' + low);
51 }
52 return oct_string;
53}
54
Mike Kruskal2166cce2022-12-21 20:38:13 -080055template <typename SetT>
56bool CheckSetEmpty(const SetT& set_to_check, absl::string_view write_to_file,
57 absl::string_view msg, absl::string_view output_dir,
58 std::string* output) {
59 if (set_to_check.empty()) return true;
60
61 absl::StrAppendFormat(output, "\n");
62 absl::StrAppendFormat(output, "%s\n\n", msg);
63 for (absl::string_view v : set_to_check) {
64 absl::StrAppendFormat(output, " %s\n", v);
65 }
66 absl::StrAppendFormat(output, "\n");
67
68 if (!write_to_file.empty()) {
69 std::string full_filename;
70 absl::string_view filename = write_to_file;
71 if (!output_dir.empty()) {
72 full_filename = std::string(output_dir);
73 if (*output_dir.rbegin() != '/') {
74 full_filename.push_back('/');
75 }
76 absl::StrAppend(&full_filename, write_to_file);
77 filename = full_filename;
78 }
79 std::ofstream os{std::string(filename)};
80 if (os) {
81 for (absl::string_view v : set_to_check) {
82 os << v << "\n";
83 }
84 } else {
85 absl::StrAppendFormat(output, "Failed to open file: %s\n", filename);
86 }
87 }
88
89 return false;
90}
91
Rafi Kamal4f02f052019-08-22 16:14:22 -070092} // namespace
Paul Yanga9bb6562019-07-26 10:05:14 -070093
Josh Haberman4e63b522015-04-14 13:45:39 -070094namespace google {
95namespace protobuf {
96
Paul Yang26eeec92018-07-09 14:29:23 -070097ConformanceTestSuite::ConformanceRequestSetting::ConformanceRequestSetting(
Mike Kruskal2166cce2022-12-21 20:38:13 -080098 ConformanceLevel level, conformance::WireFormat input_format,
Feng Xiao6bbe1972018-08-08 17:00:41 -070099 conformance::WireFormat output_format,
Mike Kruskal2166cce2022-12-21 20:38:13 -0800100 conformance::TestCategory test_category, const Message& prototype_message,
Mike Kruskal39752aa2023-10-17 16:58:29 -0700101 const std::string& test_name, const std::string& input)
Feng Xiao6bbe1972018-08-08 17:00:41 -0700102 : level_(level),
103 input_format_(input_format),
104 output_format_(output_format),
105 prototype_message_(prototype_message),
Hao Nguyen2f864fd2019-03-20 11:45:01 -0700106 prototype_message_for_compare_(prototype_message.New()),
Feng Xiao6bbe1972018-08-08 17:00:41 -0700107 test_name_(test_name) {
Paul Yang26eeec92018-07-09 14:29:23 -0700108 switch (input_format) {
109 case conformance::PROTOBUF: {
110 request_.set_protobuf_payload(input);
Paul Yang26eeec92018-07-09 14:29:23 -0700111 break;
112 }
113
114 case conformance::JSON: {
115 request_.set_json_payload(input);
Paul Yang26eeec92018-07-09 14:29:23 -0700116 break;
117 }
118
Paul Yangcecba292018-12-14 16:05:03 -0800119 case conformance::JSPB: {
120 request_.set_jspb_payload(input);
121 break;
122 }
123
Yilun Chongcb95a7f2019-01-11 11:40:52 -0800124 case conformance::TEXT_FORMAT: {
125 request_.set_text_payload(input);
126 break;
127 }
128
Paul Yang26eeec92018-07-09 14:29:23 -0700129 default:
Mike Kruskala9f1ea62023-01-24 21:49:33 -0800130 ABSL_LOG(FATAL) << "Unspecified input format";
Paul Yang26eeec92018-07-09 14:29:23 -0700131 }
132
Feng Xiao6bbe1972018-08-08 17:00:41 -0700133 request_.set_test_category(test_category);
Paul Yang26eeec92018-07-09 14:29:23 -0700134
Feng Xiao6bbe1972018-08-08 17:00:41 -0700135 request_.set_message_type(prototype_message.GetDescriptor()->full_name());
Paul Yang26eeec92018-07-09 14:29:23 -0700136 request_.set_requested_output_format(output_format);
137}
138
Rafi Kamal58d44202019-11-11 17:06:56 -0800139std::unique_ptr<Message>
140ConformanceTestSuite::ConformanceRequestSetting::NewTestMessage() const {
141 return std::unique_ptr<Message>(prototype_message_for_compare_->New());
Feng Xiao6bbe1972018-08-08 17:00:41 -0700142}
143
Mike Kruskal28e573e2023-10-17 17:26:08 -0700144std::string
145ConformanceTestSuite::ConformanceRequestSetting::GetSyntaxIdentifier() const {
Mike Kruskalbdeacc72023-03-14 15:49:23 -0700146 switch (FileDescriptorLegacy(prototype_message_.GetDescriptor()->file())
147 .syntax()) {
148 case FileDescriptorLegacy::Syntax::SYNTAX_PROTO3:
Mike Kruskal28e573e2023-10-17 17:26:08 -0700149 return "Proto3";
Mike Kruskalbdeacc72023-03-14 15:49:23 -0700150 case FileDescriptorLegacy::Syntax::SYNTAX_PROTO2:
Mike Kruskal28e573e2023-10-17 17:26:08 -0700151 return "Proto2";
Mike Kruskala2ba8bc2023-10-18 13:12:07 -0700152 case FileDescriptorLegacy::Syntax::SYNTAX_EDITIONS: {
153 std::string id = "Editions";
154 if (prototype_message_.GetDescriptor()->name() == "TestAllTypesProto2") {
155 absl::StrAppend(&id, "_Proto2");
156 } else if (prototype_message_.GetDescriptor()->name() ==
157 "TestAllTypesProto3") {
158 absl::StrAppend(&id, "_Proto3");
159 }
160 return id;
161 }
Mike Kruskal63895852023-03-03 14:48:13 -0800162 default:
Mike Kruskal28e573e2023-10-17 17:26:08 -0700163 return "Unknown";
Mike Kruskal63895852023-03-03 14:48:13 -0800164 }
Mike Kruskal28e573e2023-10-17 17:26:08 -0700165}
Feng Xiao6bbe1972018-08-08 17:00:41 -0700166
Mike Kruskal28e573e2023-10-17 17:26:08 -0700167string ConformanceTestSuite::ConformanceRequestSetting::GetTestName() const {
168 return absl::StrCat(ConformanceLevelToString(level_), ".",
169 GetSyntaxIdentifier(), ".",
Rafi Kamal58d44202019-11-11 17:06:56 -0800170 InputFormatString(input_format_), ".", test_name_, ".",
171 OutputFormatString(output_format_));
Feng Xiao6bbe1972018-08-08 17:00:41 -0700172}
173
Mike Kruskal39752aa2023-10-17 16:58:29 -0700174std::string
Mike Kruskal2166cce2022-12-21 20:38:13 -0800175ConformanceTestSuite::ConformanceRequestSetting::ConformanceLevelToString(
176 ConformanceLevel level) const {
Feng Xiao6bbe1972018-08-08 17:00:41 -0700177 switch (level) {
Mike Kruskal2166cce2022-12-21 20:38:13 -0800178 case REQUIRED:
179 return "Required";
180 case RECOMMENDED:
181 return "Recommended";
Paul Yang26eeec92018-07-09 14:29:23 -0700182 }
Mike Kruskala9f1ea62023-01-24 21:49:33 -0800183 ABSL_LOG(FATAL) << "Unknown value: " << level;
Feng Xiao6bbe1972018-08-08 17:00:41 -0700184 return "";
185}
186
Mike Kruskal39752aa2023-10-17 16:58:29 -0700187std::string ConformanceTestSuite::ConformanceRequestSetting::InputFormatString(
Mike Kruskal2166cce2022-12-21 20:38:13 -0800188 conformance::WireFormat format) const {
Feng Xiao6bbe1972018-08-08 17:00:41 -0700189 switch (format) {
190 case conformance::PROTOBUF:
191 return "ProtobufInput";
192 case conformance::JSON:
193 return "JsonInput";
Yilun Chongcb95a7f2019-01-11 11:40:52 -0800194 case conformance::TEXT_FORMAT:
195 return "TextFormatInput";
Feng Xiao6bbe1972018-08-08 17:00:41 -0700196 default:
Mike Kruskala9f1ea62023-01-24 21:49:33 -0800197 ABSL_LOG(FATAL) << "Unspecified output format";
Feng Xiao6bbe1972018-08-08 17:00:41 -0700198 }
199 return "";
200}
201
Mike Kruskal39752aa2023-10-17 16:58:29 -0700202std::string ConformanceTestSuite::ConformanceRequestSetting::OutputFormatString(
Mike Kruskal2166cce2022-12-21 20:38:13 -0800203 conformance::WireFormat format) const {
Feng Xiao6bbe1972018-08-08 17:00:41 -0700204 switch (format) {
205 case conformance::PROTOBUF:
206 return "ProtobufOutput";
207 case conformance::JSON:
208 return "JsonOutput";
Yilun Chongcb95a7f2019-01-11 11:40:52 -0800209 case conformance::TEXT_FORMAT:
210 return "TextFormatOutput";
Feng Xiao6bbe1972018-08-08 17:00:41 -0700211 default:
Mike Kruskala9f1ea62023-01-24 21:49:33 -0800212 ABSL_LOG(FATAL) << "Unspecified output format";
Feng Xiao6bbe1972018-08-08 17:00:41 -0700213 }
214 return "";
215}
216
Mike Kruskal32bea522022-10-06 16:48:39 -0700217void ConformanceTestSuite::TruncateDebugPayload(string* payload) {
218 if (payload != nullptr && payload->size() > 200) {
219 payload->resize(200);
220 payload->append("...(truncated)");
221 }
222}
223
Mike Kruskal39752aa2023-10-17 16:58:29 -0700224ConformanceRequest ConformanceTestSuite::TruncateRequest(
Mike Kruskal32bea522022-10-06 16:48:39 -0700225 const ConformanceRequest& request) {
226 ConformanceRequest debug_request(request);
227 switch (debug_request.payload_case()) {
228 case ConformanceRequest::kProtobufPayload:
229 TruncateDebugPayload(debug_request.mutable_protobuf_payload());
230 break;
231 case ConformanceRequest::kJsonPayload:
232 TruncateDebugPayload(debug_request.mutable_json_payload());
233 break;
234 case ConformanceRequest::kTextPayload:
235 TruncateDebugPayload(debug_request.mutable_text_payload());
236 break;
237 case ConformanceRequest::kJspbPayload:
238 TruncateDebugPayload(debug_request.mutable_jspb_payload());
239 break;
240 default:
241 // Do nothing.
242 break;
243 }
244 return debug_request;
245}
246
Mike Kruskal39752aa2023-10-17 16:58:29 -0700247ConformanceResponse ConformanceTestSuite::TruncateResponse(
Mike Kruskal32bea522022-10-06 16:48:39 -0700248 const ConformanceResponse& response) {
249 ConformanceResponse debug_response(response);
250 switch (debug_response.result_case()) {
251 case ConformanceResponse::kProtobufPayload:
252 TruncateDebugPayload(debug_response.mutable_protobuf_payload());
253 break;
254 case ConformanceResponse::kJsonPayload:
255 TruncateDebugPayload(debug_response.mutable_json_payload());
256 break;
257 case ConformanceResponse::kTextPayload:
258 TruncateDebugPayload(debug_response.mutable_text_payload());
259 break;
260 case ConformanceResponse::kJspbPayload:
261 TruncateDebugPayload(debug_response.mutable_jspb_payload());
262 break;
263 default:
264 // Do nothing.
265 break;
266 }
267 return debug_response;
268}
269
Mike Kruskal39752aa2023-10-17 16:58:29 -0700270void ConformanceTestSuite::ReportSuccess(const std::string& test_name) {
Josh Habermand2b67382015-06-03 12:04:35 -0700271 if (expected_to_fail_.erase(test_name) != 0) {
Mike Kruskale99b2812022-09-23 14:27:46 -0700272 absl::StrAppendFormat(
273 &output_,
274 "ERROR: test %s is in the failure list, but test succeeded. "
275 "Remove it from the failure list.\n",
276 test_name);
Josh Habermand2b67382015-06-03 12:04:35 -0700277 unexpected_succeeding_tests_.insert(test_name);
278 }
Josh Haberman4e63b522015-04-14 13:45:39 -0700279 successes_++;
280}
281
Mike Kruskal39752aa2023-10-17 16:58:29 -0700282void ConformanceTestSuite::ReportFailure(const std::string& test_name,
Bo Yangcc8ca5b2016-09-19 13:45:07 -0700283 ConformanceLevel level,
Josh Habermanb0500b32015-07-10 16:36:59 -0700284 const ConformanceRequest& request,
285 const ConformanceResponse& response,
Mike Kruskale99b2812022-09-23 14:27:46 -0700286 absl::string_view message) {
Josh Habermand2b67382015-06-03 12:04:35 -0700287 if (expected_to_fail_.erase(test_name) == 1) {
Josh Habermanb0500b32015-07-10 16:36:59 -0700288 expected_failures_++;
Mike Kruskal2166cce2022-12-21 20:38:13 -0800289 if (!verbose_) return;
Bo Yangcc8ca5b2016-09-19 13:45:07 -0700290 } else if (level == RECOMMENDED && !enforce_recommended_) {
Mike Kruskale99b2812022-09-23 14:27:46 -0700291 absl::StrAppendFormat(&output_, "WARNING, test=%s: ", test_name);
Josh Habermand2b67382015-06-03 12:04:35 -0700292 } else {
Mike Kruskale99b2812022-09-23 14:27:46 -0700293 absl::StrAppendFormat(&output_, "ERROR, test=%s: ", test_name);
Josh Habermand2b67382015-06-03 12:04:35 -0700294 unexpected_failing_tests_.insert(test_name);
295 }
Mike Kruskal32bea522022-10-06 16:48:39 -0700296
297 absl::StrAppendFormat(&output_, "%s, request=%s, response=%s\n", message,
298 TruncateRequest(request).ShortDebugString(),
299 TruncateResponse(response).ShortDebugString());
Josh Habermanb0500b32015-07-10 16:36:59 -0700300}
301
Mike Kruskal39752aa2023-10-17 16:58:29 -0700302void ConformanceTestSuite::ReportSkip(const std::string& test_name,
Josh Habermanb0500b32015-07-10 16:36:59 -0700303 const ConformanceRequest& request,
304 const ConformanceResponse& response) {
305 if (verbose_) {
Mike Kruskale99b2812022-09-23 14:27:46 -0700306 absl::StrAppendFormat(
307 &output_, "SKIPPED, test=%s request=%s, response=%s\n", test_name,
308 request.ShortDebugString(), response.ShortDebugString());
Josh Habermanb0500b32015-07-10 16:36:59 -0700309 }
310 skipped_.insert(test_name);
Josh Haberman4e63b522015-04-14 13:45:39 -0700311}
312
Josh Habermanb0500b32015-07-10 16:36:59 -0700313void ConformanceTestSuite::RunValidInputTest(
Paul Yang26eeec92018-07-09 14:29:23 -0700314 const ConformanceRequestSetting& setting,
Mike Kruskal39752aa2023-10-17 16:58:29 -0700315 const std::string& equivalent_text_format) {
Rafi Kamal58d44202019-11-11 17:06:56 -0800316 std::unique_ptr<Message> reference_message(setting.NewTestMessage());
Mike Kruskala9f1ea62023-01-24 21:49:33 -0800317 ABSL_CHECK(TextFormat::ParseFromString(equivalent_text_format,
Mike Kruskala02c9022022-12-08 12:15:31 -0800318 reference_message.get()))
Rafi Kamal58d44202019-11-11 17:06:56 -0800319 << "Failed to parse data for test case: " << setting.GetTestName()
320 << ", data: " << equivalent_text_format;
Mike Kruskal39752aa2023-10-17 16:58:29 -0700321 const std::string equivalent_wire_format =
322 reference_message->SerializeAsString();
Paul Yang26eeec92018-07-09 14:29:23 -0700323 RunValidBinaryInputTest(setting, equivalent_wire_format);
Paul Yang23adfeb2017-10-26 14:41:43 -0700324}
325
326void ConformanceTestSuite::RunValidBinaryInputTest(
Paul Yang26eeec92018-07-09 14:29:23 -0700327 const ConformanceRequestSetting& setting,
Mike Kruskal39752aa2023-10-17 16:58:29 -0700328 const std::string& equivalent_wire_format, bool require_same_wire_format) {
Paul Yangcecba292018-12-14 16:05:03 -0800329 const ConformanceRequest& request = setting.GetRequest();
330 ConformanceResponse response;
331 RunTest(setting.GetTestName(), request, &response);
Rafi Kamal4f02f052019-08-22 16:14:22 -0700332 VerifyResponse(setting, equivalent_wire_format, response, true,
333 require_same_wire_format);
Paul Yangcecba292018-12-14 16:05:03 -0800334}
335
336void ConformanceTestSuite::VerifyResponse(
337 const ConformanceRequestSetting& setting,
Mike Kruskal39752aa2023-10-17 16:58:29 -0700338 const std::string& equivalent_wire_format,
339 const ConformanceResponse& response, bool need_report_success,
340 bool require_same_wire_format) {
Rafi Kamal58d44202019-11-11 17:06:56 -0800341 std::unique_ptr<Message> test_message(setting.NewTestMessage());
Paul Yangcecba292018-12-14 16:05:03 -0800342 const ConformanceRequest& request = setting.GetRequest();
Mike Kruskal39752aa2023-10-17 16:58:29 -0700343 const std::string& test_name = setting.GetTestName();
Paul Yang26eeec92018-07-09 14:29:23 -0700344 ConformanceLevel level = setting.GetLevel();
Rafi Kamal58d44202019-11-11 17:06:56 -0800345 std::unique_ptr<Message> reference_message = setting.NewTestMessage();
Paul Yangcecba292018-12-14 16:05:03 -0800346
Mike Kruskala9f1ea62023-01-24 21:49:33 -0800347 ABSL_CHECK(reference_message->ParseFromString(equivalent_wire_format))
Rafi Kamal58d44202019-11-11 17:06:56 -0800348 << "Failed to parse wire data for test case: " << test_name;
Josh Habermanb0500b32015-07-10 16:36:59 -0700349
Josh Habermanb0500b32015-07-10 16:36:59 -0700350 switch (response.result_case()) {
Thomas Van Lentenac3df392016-08-11 09:44:07 -0400351 case ConformanceResponse::RESULT_NOT_SET:
Bo Yange3f06892016-09-19 17:29:57 -0700352 ReportFailure(test_name, level, request, response,
Thomas Van Lentenac3df392016-08-11 09:44:07 -0400353 "Response didn't have any field in the Response.");
354 return;
355
Josh Habermanb0500b32015-07-10 16:36:59 -0700356 case ConformanceResponse::kParseError:
Mike Kruskal32bea522022-10-06 16:48:39 -0700357 case ConformanceResponse::kTimeoutError:
Josh Habermanb0500b32015-07-10 16:36:59 -0700358 case ConformanceResponse::kRuntimeError:
Feng Xiaoe841bac2015-12-11 17:09:20 -0800359 case ConformanceResponse::kSerializeError:
Bo Yange3f06892016-09-19 17:29:57 -0700360 ReportFailure(test_name, level, request, response,
Thomas Van Lentenac3df392016-08-11 09:44:07 -0400361 "Failed to parse input or produce output.");
Josh Habermanb0500b32015-07-10 16:36:59 -0700362 return;
363
364 case ConformanceResponse::kSkipped:
365 ReportSkip(test_name, request, response);
366 return;
367
Feng Xiaoe841bac2015-12-11 17:09:20 -0800368 default:
Rafi Kamal58d44202019-11-11 17:06:56 -0800369 if (!ParseResponse(response, setting, test_message.get())) return;
Josh Habermanb0500b32015-07-10 16:36:59 -0700370 }
371
372 MessageDifferencer differencer;
Feng Xiaoe841bac2015-12-11 17:09:20 -0800373 DefaultFieldComparator field_comparator;
374 field_comparator.set_treat_nan_as_equal(true);
375 differencer.set_field_comparator(&field_comparator);
Mike Kruskal39752aa2023-10-17 16:58:29 -0700376 std::string differences;
Josh Habermanb0500b32015-07-10 16:36:59 -0700377 differencer.ReportDifferencesToString(&differences);
378
Paul Yanga9bb6562019-07-26 10:05:14 -0700379 bool check = false;
380
381 if (require_same_wire_format) {
Mike Kruskala9f1ea62023-01-24 21:49:33 -0800382 ABSL_DCHECK_EQ(response.result_case(),
Mike Kruskala02c9022022-12-08 12:15:31 -0800383 ConformanceResponse::kProtobufPayload);
Mike Kruskal39752aa2023-10-17 16:58:29 -0700384 const std::string& protobuf_payload = response.protobuf_payload();
Paul Yanga9bb6562019-07-26 10:05:14 -0700385 check = equivalent_wire_format == protobuf_payload;
Mike Kruskala3c8e2d2022-08-24 10:46:33 -0700386 differences = absl::StrCat("Expect: ", ToOctString(equivalent_wire_format),
Rafi Kamal58d44202019-11-11 17:06:56 -0800387 ", but got: ", ToOctString(protobuf_payload));
Paul Yanga9bb6562019-07-26 10:05:14 -0700388 } else {
389 check = differencer.Compare(*reference_message, *test_message);
390 }
391
Jisi Liu759245a2017-07-25 11:52:33 -0700392 if (check) {
Paul Yangcecba292018-12-14 16:05:03 -0800393 if (need_report_success) {
394 ReportSuccess(test_name);
395 }
Josh Habermanb0500b32015-07-10 16:36:59 -0700396 } else {
Mike Kruskale99b2812022-09-23 14:27:46 -0700397 ReportFailure(
398 test_name, level, request, response,
399 absl::StrCat("Output was not equivalent to reference message: ",
400 differences));
Josh Habermanb0500b32015-07-10 16:36:59 -0700401 }
402}
Feng Xiao6bbe1972018-08-08 17:00:41 -0700403
Mike Kruskal39752aa2023-10-17 16:58:29 -0700404void ConformanceTestSuite::RunTest(const std::string& test_name,
Feng Xiao6bbe1972018-08-08 17:00:41 -0700405 const ConformanceRequest& request,
406 ConformanceResponse* response) {
407 if (test_names_.insert(test_name).second == false) {
Mike Kruskala9f1ea62023-01-24 21:49:33 -0800408 ABSL_LOG(FATAL) << "Duplicated test name: " << test_name;
Jisi Liu759245a2017-07-25 11:52:33 -0700409 }
Josh Haberman4e63b522015-04-14 13:45:39 -0700410
Mike Kruskal39752aa2023-10-17 16:58:29 -0700411 std::string serialized_request;
412 std::string serialized_response;
Feng Xiao6bbe1972018-08-08 17:00:41 -0700413 request.SerializeToString(&serialized_request);
Josh Haberman4e63b522015-04-14 13:45:39 -0700414
Feng Xiao6bbe1972018-08-08 17:00:41 -0700415 runner_->RunTest(test_name, serialized_request, &serialized_response);
416
417 if (!response->ParseFromString(serialized_response)) {
418 response->Clear();
419 response->set_runtime_error("response proto could not be parsed.");
420 }
421
422 if (verbose_) {
Mike Kruskale99b2812022-09-23 14:27:46 -0700423 absl::StrAppendFormat(
424 &output_, "conformance test: name=%s, request=%s, response=%s\n",
Mike Kruskal32bea522022-10-06 16:48:39 -0700425 test_name, TruncateRequest(request).ShortDebugString(),
426 TruncateResponse(*response).ShortDebugString());
Josh Haberman4e63b522015-04-14 13:45:39 -0700427 }
428}
429
Mike Kruskal39752aa2023-10-17 16:58:29 -0700430std::string ConformanceTestSuite::WireFormatToString(WireFormat wire_format) {
Paul Yangcecba292018-12-14 16:05:03 -0800431 switch (wire_format) {
432 case conformance::PROTOBUF:
433 return "PROTOBUF";
434 case conformance::JSON:
435 return "JSON";
436 case conformance::JSPB:
437 return "JSPB";
Yilun Chongcb95a7f2019-01-11 11:40:52 -0800438 case conformance::TEXT_FORMAT:
439 return "TEXT_FORMAT";
Paul Yangcecba292018-12-14 16:05:03 -0800440 case conformance::UNSPECIFIED:
441 return "UNSPECIFIED";
442 default:
Mike Kruskala9f1ea62023-01-24 21:49:33 -0800443 ABSL_LOG(FATAL) << "unknown wire type: " << wire_format;
Paul Yangcecba292018-12-14 16:05:03 -0800444 }
445 return "";
446}
447
Yilun Chongd8c25012019-02-22 18:13:33 +0800448void ConformanceTestSuite::AddExpectedFailedTest(const std::string& test_name) {
449 expected_to_fail_.insert(test_name);
450}
451
Yilun Chong0adb74c2019-01-08 15:06:30 -0800452bool ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner,
Mike Kruskal39752aa2023-10-17 16:58:29 -0700453 std::string* output,
454 const std::string& filename,
Yilun Chong0adb74c2019-01-08 15:06:30 -0800455 conformance::FailureSet* failure_list) {
Josh Haberman4e63b522015-04-14 13:45:39 -0700456 runner_ = runner;
Josh Haberman4e63b522015-04-14 13:45:39 -0700457 successes_ = 0;
Josh Habermanb0500b32015-07-10 16:36:59 -0700458 expected_failures_ = 0;
459 skipped_.clear();
Josh Habermand2b67382015-06-03 12:04:35 -0700460 test_names_.clear();
461 unexpected_failing_tests_.clear();
462 unexpected_succeeding_tests_.clear();
Josh Habermanb0500b32015-07-10 16:36:59 -0700463
464 output_ = "\nCONFORMANCE TEST BEGIN ====================================\n\n";
Josh Haberman35a1cc72015-04-01 17:23:48 -0700465
Yilun Chong0adb74c2019-01-08 15:06:30 -0800466 failure_list_filename_ = filename;
467 expected_to_fail_.clear();
Mike Kruskal39752aa2023-10-17 16:58:29 -0700468 for (const std::string& failure : failure_list->failure()) {
Yilun Chongd8c25012019-02-22 18:13:33 +0800469 AddExpectedFailedTest(failure);
Yilun Chong0adb74c2019-01-08 15:06:30 -0800470 }
Feng Xiao6bbe1972018-08-08 17:00:41 -0700471 RunSuiteImpl();
Paul Yang26eeec92018-07-09 14:29:23 -0700472
Feng Xiaoe841bac2015-12-11 17:09:20 -0800473 bool ok = true;
Mike Kruskal2166cce2022-12-21 20:38:13 -0800474 if (!CheckSetEmpty(
475 expected_to_fail_, "nonexistent_tests.txt",
476 absl::StrCat("These tests were listed in the failure list, but they "
477 "don't exist. Remove them from the failure list by "
478 "running:\n"
479 " ./update_failure_list.py ",
480 failure_list_filename_,
481 " --remove nonexistent_tests.txt"),
482 output_dir_, &output_)) {
Feng Xiaoe841bac2015-12-11 17:09:20 -0800483 ok = false;
484 }
Mike Kruskal2166cce2022-12-21 20:38:13 -0800485 if (!CheckSetEmpty(
486 unexpected_failing_tests_, "failing_tests.txt",
487 absl::StrCat("These tests failed. If they can't be fixed right now, "
488 "you can add them to the failure list so the overall "
489 "suite can succeed. Add them to the failure list by "
490 "running:\n"
491 " ./update_failure_list.py ",
492 failure_list_filename_, " --add failing_tests.txt"),
493 output_dir_, &output_)) {
Josh Habermanef7894e2016-05-16 12:45:02 -0700494 ok = false;
495 }
Mike Kruskal2166cce2022-12-21 20:38:13 -0800496 if (!CheckSetEmpty(
497 unexpected_succeeding_tests_, "succeeding_tests.txt",
498 absl::StrCat("These tests succeeded, even though they were listed in "
499 "the failure list. Remove them from the failure list "
500 "by running:\n"
501 " ./update_failure_list.py ",
502 failure_list_filename_,
503 " --remove succeeding_tests.txt"),
504 output_dir_, &output_)) {
Feng Xiaoe841bac2015-12-11 17:09:20 -0800505 ok = false;
506 }
507
Josh Haberman325392d2015-08-17 12:30:49 -0700508 if (verbose_) {
Josh Habermanef7894e2016-05-16 12:45:02 -0700509 CheckSetEmpty(skipped_, "",
Josh Haberman325392d2015-08-17 12:30:49 -0700510 "These tests were skipped (probably because support for some "
Mike Kruskal2166cce2022-12-21 20:38:13 -0800511 "features is not implemented)",
512 output_dir_, &output_);
Josh Haberman325392d2015-08-17 12:30:49 -0700513 }
Josh Habermanb0500b32015-07-10 16:36:59 -0700514
Mike Kruskale99b2812022-09-23 14:27:46 -0700515 absl::StrAppendFormat(&output_,
516 "CONFORMANCE SUITE %s: %d successes, %zu skipped, "
517 "%d expected failures, %zu unexpected failures.\n",
518 ok ? "PASSED" : "FAILED", successes_, skipped_.size(),
519 expected_failures_, unexpected_failing_tests_.size());
520 absl::StrAppendFormat(&output_, "\n");
Josh Habermanb0500b32015-07-10 16:36:59 -0700521
Josh Haberman4e63b522015-04-14 13:45:39 -0700522 output->assign(output_);
Josh Habermand2b67382015-06-03 12:04:35 -0700523
524 return ok;
Josh Haberman35a1cc72015-04-01 17:23:48 -0700525}
Josh Haberman4e63b522015-04-14 13:45:39 -0700526
527} // namespace protobuf
528} // namespace google