Josh Haberman | 35a1cc7 | 2015-04-01 17:23:48 -0700 | [diff] [blame] | 1 | // Protocol Buffers - Google's data interchange format |
| 2 | // Copyright 2008 Google Inc. All rights reserved. |
Josh Haberman | 35a1cc7 | 2015-04-01 17:23:48 -0700 | [diff] [blame] | 3 | // |
Joshua Haberman | 8a4bfd6 | 2023-09-08 19:26:10 -0700 | [diff] [blame] | 4 | // 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 Haberman | 35a1cc7 | 2015-04-01 17:23:48 -0700 | [diff] [blame] | 7 | |
Josh Haberman | 4e63b52 | 2015-04-14 13:45:39 -0700 | [diff] [blame] | 8 | #include "conformance_test.h" |
Joshua Haberman | f1ce60e | 2016-12-03 11:51:25 -0500 | [diff] [blame] | 9 | |
Rafi Kamal | 58d4420 | 2019-11-11 17:06:56 -0800 | [diff] [blame] | 10 | #include <stdarg.h> |
| 11 | |
Mike Kruskal | 39752aa | 2023-10-17 16:58:29 -0700 | [diff] [blame] | 12 | #include <cstddef> |
| 13 | #include <cstdint> |
Rafi Kamal | 58d4420 | 2019-11-11 17:06:56 -0800 | [diff] [blame] | 14 | #include <fstream> |
Mike Kruskal | 39752aa | 2023-10-17 16:58:29 -0700 | [diff] [blame] | 15 | #include <memory> |
Rafi Kamal | 58d4420 | 2019-11-11 17:06:56 -0800 | [diff] [blame] | 16 | #include <string> |
| 17 | |
Mike Kruskal | 1595417 | 2022-09-09 10:42:19 -0700 | [diff] [blame] | 18 | #include "google/protobuf/util/field_comparator.h" |
Mike Kruskal | 1595417 | 2022-09-09 10:42:19 -0700 | [diff] [blame] | 19 | #include "google/protobuf/util/message_differencer.h" |
Mike Kruskal | 39752aa | 2023-10-17 16:58:29 -0700 | [diff] [blame] | 20 | #include "absl/log/absl_check.h" |
Mike Kruskal | a9f1ea6 | 2023-01-24 21:49:33 -0800 | [diff] [blame] | 21 | #include "absl/log/absl_log.h" |
Mike Kruskal | e99b281 | 2022-09-23 14:27:46 -0700 | [diff] [blame] | 22 | #include "absl/strings/str_cat.h" |
| 23 | #include "absl/strings/str_format.h" |
Mike Kruskal | 2166cce | 2022-12-21 20:38:13 -0800 | [diff] [blame] | 24 | #include "absl/strings/string_view.h" |
Mike Kruskal | ca4b063 | 2022-08-11 20:55:01 -0700 | [diff] [blame] | 25 | #include "conformance/conformance.pb.h" |
Mike Kruskal | 32bea52 | 2022-10-06 16:48:39 -0700 | [diff] [blame] | 26 | #include "conformance/conformance.pb.h" |
Mike Kruskal | bdeacc7 | 2023-03-14 15:49:23 -0700 | [diff] [blame] | 27 | #include "google/protobuf/descriptor_legacy.h" |
Protobuf Team Bot | 0287cf4 | 2023-08-22 07:26:58 -0700 | [diff] [blame] | 28 | #include "google/protobuf/message.h" |
| 29 | #include "google/protobuf/text_format.h" |
Feng Xiao | e841bac | 2015-12-11 17:09:20 -0800 | [diff] [blame] | 30 | |
Josh Haberman | 35a1cc7 | 2015-04-01 17:23:48 -0700 | [diff] [blame] | 31 | using conformance::ConformanceRequest; |
| 32 | using conformance::ConformanceResponse; |
Josh Haberman | b0500b3 | 2015-07-10 16:36:59 -0700 | [diff] [blame] | 33 | using conformance::WireFormat; |
Feng Xiao | e841bac | 2015-12-11 17:09:20 -0800 | [diff] [blame] | 34 | using google::protobuf::util::DefaultFieldComparator; |
Josh Haberman | b0500b3 | 2015-07-10 16:36:59 -0700 | [diff] [blame] | 35 | using google::protobuf::util::MessageDifferencer; |
Josh Haberman | 35a1cc7 | 2015-04-01 17:23:48 -0700 | [diff] [blame] | 36 | using std::string; |
| 37 | |
Paul Yang | a9bb656 | 2019-07-26 10:05:14 -0700 | [diff] [blame] | 38 | namespace { |
| 39 | |
Mike Kruskal | 39752aa | 2023-10-17 16:58:29 -0700 | [diff] [blame] | 40 | static std::string ToOctString(const std::string& binary_string) { |
| 41 | std::string oct_string; |
Paul Yang | a9bb656 | 2019-07-26 10:05:14 -0700 | [diff] [blame] | 42 | 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 Kruskal | 2166cce | 2022-12-21 20:38:13 -0800 | [diff] [blame] | 55 | template <typename SetT> |
| 56 | bool 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 Kamal | 4f02f05 | 2019-08-22 16:14:22 -0700 | [diff] [blame] | 92 | } // namespace |
Paul Yang | a9bb656 | 2019-07-26 10:05:14 -0700 | [diff] [blame] | 93 | |
Josh Haberman | 4e63b52 | 2015-04-14 13:45:39 -0700 | [diff] [blame] | 94 | namespace google { |
| 95 | namespace protobuf { |
| 96 | |
Paul Yang | 26eeec9 | 2018-07-09 14:29:23 -0700 | [diff] [blame] | 97 | ConformanceTestSuite::ConformanceRequestSetting::ConformanceRequestSetting( |
Mike Kruskal | 2166cce | 2022-12-21 20:38:13 -0800 | [diff] [blame] | 98 | ConformanceLevel level, conformance::WireFormat input_format, |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 99 | conformance::WireFormat output_format, |
Mike Kruskal | 2166cce | 2022-12-21 20:38:13 -0800 | [diff] [blame] | 100 | conformance::TestCategory test_category, const Message& prototype_message, |
Mike Kruskal | 39752aa | 2023-10-17 16:58:29 -0700 | [diff] [blame] | 101 | const std::string& test_name, const std::string& input) |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 102 | : level_(level), |
| 103 | input_format_(input_format), |
| 104 | output_format_(output_format), |
| 105 | prototype_message_(prototype_message), |
Hao Nguyen | 2f864fd | 2019-03-20 11:45:01 -0700 | [diff] [blame] | 106 | prototype_message_for_compare_(prototype_message.New()), |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 107 | test_name_(test_name) { |
Paul Yang | 26eeec9 | 2018-07-09 14:29:23 -0700 | [diff] [blame] | 108 | switch (input_format) { |
| 109 | case conformance::PROTOBUF: { |
| 110 | request_.set_protobuf_payload(input); |
Paul Yang | 26eeec9 | 2018-07-09 14:29:23 -0700 | [diff] [blame] | 111 | break; |
| 112 | } |
| 113 | |
| 114 | case conformance::JSON: { |
| 115 | request_.set_json_payload(input); |
Paul Yang | 26eeec9 | 2018-07-09 14:29:23 -0700 | [diff] [blame] | 116 | break; |
| 117 | } |
| 118 | |
Paul Yang | cecba29 | 2018-12-14 16:05:03 -0800 | [diff] [blame] | 119 | case conformance::JSPB: { |
| 120 | request_.set_jspb_payload(input); |
| 121 | break; |
| 122 | } |
| 123 | |
Yilun Chong | cb95a7f | 2019-01-11 11:40:52 -0800 | [diff] [blame] | 124 | case conformance::TEXT_FORMAT: { |
| 125 | request_.set_text_payload(input); |
| 126 | break; |
| 127 | } |
| 128 | |
Paul Yang | 26eeec9 | 2018-07-09 14:29:23 -0700 | [diff] [blame] | 129 | default: |
Mike Kruskal | a9f1ea6 | 2023-01-24 21:49:33 -0800 | [diff] [blame] | 130 | ABSL_LOG(FATAL) << "Unspecified input format"; |
Paul Yang | 26eeec9 | 2018-07-09 14:29:23 -0700 | [diff] [blame] | 131 | } |
| 132 | |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 133 | request_.set_test_category(test_category); |
Paul Yang | 26eeec9 | 2018-07-09 14:29:23 -0700 | [diff] [blame] | 134 | |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 135 | request_.set_message_type(prototype_message.GetDescriptor()->full_name()); |
Paul Yang | 26eeec9 | 2018-07-09 14:29:23 -0700 | [diff] [blame] | 136 | request_.set_requested_output_format(output_format); |
| 137 | } |
| 138 | |
Rafi Kamal | 58d4420 | 2019-11-11 17:06:56 -0800 | [diff] [blame] | 139 | std::unique_ptr<Message> |
| 140 | ConformanceTestSuite::ConformanceRequestSetting::NewTestMessage() const { |
| 141 | return std::unique_ptr<Message>(prototype_message_for_compare_->New()); |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 142 | } |
| 143 | |
Mike Kruskal | 28e573e | 2023-10-17 17:26:08 -0700 | [diff] [blame] | 144 | std::string |
| 145 | ConformanceTestSuite::ConformanceRequestSetting::GetSyntaxIdentifier() const { |
Mike Kruskal | bdeacc7 | 2023-03-14 15:49:23 -0700 | [diff] [blame] | 146 | switch (FileDescriptorLegacy(prototype_message_.GetDescriptor()->file()) |
| 147 | .syntax()) { |
| 148 | case FileDescriptorLegacy::Syntax::SYNTAX_PROTO3: |
Mike Kruskal | 28e573e | 2023-10-17 17:26:08 -0700 | [diff] [blame] | 149 | return "Proto3"; |
Mike Kruskal | bdeacc7 | 2023-03-14 15:49:23 -0700 | [diff] [blame] | 150 | case FileDescriptorLegacy::Syntax::SYNTAX_PROTO2: |
Mike Kruskal | 28e573e | 2023-10-17 17:26:08 -0700 | [diff] [blame] | 151 | return "Proto2"; |
Mike Kruskal | a2ba8bc | 2023-10-18 13:12:07 -0700 | [diff] [blame] | 152 | 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 Kruskal | 6389585 | 2023-03-03 14:48:13 -0800 | [diff] [blame] | 162 | default: |
Mike Kruskal | 28e573e | 2023-10-17 17:26:08 -0700 | [diff] [blame] | 163 | return "Unknown"; |
Mike Kruskal | 6389585 | 2023-03-03 14:48:13 -0800 | [diff] [blame] | 164 | } |
Mike Kruskal | 28e573e | 2023-10-17 17:26:08 -0700 | [diff] [blame] | 165 | } |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 166 | |
Mike Kruskal | 28e573e | 2023-10-17 17:26:08 -0700 | [diff] [blame] | 167 | string ConformanceTestSuite::ConformanceRequestSetting::GetTestName() const { |
| 168 | return absl::StrCat(ConformanceLevelToString(level_), ".", |
| 169 | GetSyntaxIdentifier(), ".", |
Rafi Kamal | 58d4420 | 2019-11-11 17:06:56 -0800 | [diff] [blame] | 170 | InputFormatString(input_format_), ".", test_name_, ".", |
| 171 | OutputFormatString(output_format_)); |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 172 | } |
| 173 | |
Mike Kruskal | 39752aa | 2023-10-17 16:58:29 -0700 | [diff] [blame] | 174 | std::string |
Mike Kruskal | 2166cce | 2022-12-21 20:38:13 -0800 | [diff] [blame] | 175 | ConformanceTestSuite::ConformanceRequestSetting::ConformanceLevelToString( |
| 176 | ConformanceLevel level) const { |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 177 | switch (level) { |
Mike Kruskal | 2166cce | 2022-12-21 20:38:13 -0800 | [diff] [blame] | 178 | case REQUIRED: |
| 179 | return "Required"; |
| 180 | case RECOMMENDED: |
| 181 | return "Recommended"; |
Paul Yang | 26eeec9 | 2018-07-09 14:29:23 -0700 | [diff] [blame] | 182 | } |
Mike Kruskal | a9f1ea6 | 2023-01-24 21:49:33 -0800 | [diff] [blame] | 183 | ABSL_LOG(FATAL) << "Unknown value: " << level; |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 184 | return ""; |
| 185 | } |
| 186 | |
Mike Kruskal | 39752aa | 2023-10-17 16:58:29 -0700 | [diff] [blame] | 187 | std::string ConformanceTestSuite::ConformanceRequestSetting::InputFormatString( |
Mike Kruskal | 2166cce | 2022-12-21 20:38:13 -0800 | [diff] [blame] | 188 | conformance::WireFormat format) const { |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 189 | switch (format) { |
| 190 | case conformance::PROTOBUF: |
| 191 | return "ProtobufInput"; |
| 192 | case conformance::JSON: |
| 193 | return "JsonInput"; |
Yilun Chong | cb95a7f | 2019-01-11 11:40:52 -0800 | [diff] [blame] | 194 | case conformance::TEXT_FORMAT: |
| 195 | return "TextFormatInput"; |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 196 | default: |
Mike Kruskal | a9f1ea6 | 2023-01-24 21:49:33 -0800 | [diff] [blame] | 197 | ABSL_LOG(FATAL) << "Unspecified output format"; |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 198 | } |
| 199 | return ""; |
| 200 | } |
| 201 | |
Mike Kruskal | 39752aa | 2023-10-17 16:58:29 -0700 | [diff] [blame] | 202 | std::string ConformanceTestSuite::ConformanceRequestSetting::OutputFormatString( |
Mike Kruskal | 2166cce | 2022-12-21 20:38:13 -0800 | [diff] [blame] | 203 | conformance::WireFormat format) const { |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 204 | switch (format) { |
| 205 | case conformance::PROTOBUF: |
| 206 | return "ProtobufOutput"; |
| 207 | case conformance::JSON: |
| 208 | return "JsonOutput"; |
Yilun Chong | cb95a7f | 2019-01-11 11:40:52 -0800 | [diff] [blame] | 209 | case conformance::TEXT_FORMAT: |
| 210 | return "TextFormatOutput"; |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 211 | default: |
Mike Kruskal | a9f1ea6 | 2023-01-24 21:49:33 -0800 | [diff] [blame] | 212 | ABSL_LOG(FATAL) << "Unspecified output format"; |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 213 | } |
| 214 | return ""; |
| 215 | } |
| 216 | |
Mike Kruskal | 32bea52 | 2022-10-06 16:48:39 -0700 | [diff] [blame] | 217 | void ConformanceTestSuite::TruncateDebugPayload(string* payload) { |
| 218 | if (payload != nullptr && payload->size() > 200) { |
| 219 | payload->resize(200); |
| 220 | payload->append("...(truncated)"); |
| 221 | } |
| 222 | } |
| 223 | |
Mike Kruskal | 39752aa | 2023-10-17 16:58:29 -0700 | [diff] [blame] | 224 | ConformanceRequest ConformanceTestSuite::TruncateRequest( |
Mike Kruskal | 32bea52 | 2022-10-06 16:48:39 -0700 | [diff] [blame] | 225 | 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 Kruskal | 39752aa | 2023-10-17 16:58:29 -0700 | [diff] [blame] | 247 | ConformanceResponse ConformanceTestSuite::TruncateResponse( |
Mike Kruskal | 32bea52 | 2022-10-06 16:48:39 -0700 | [diff] [blame] | 248 | 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 Kruskal | 39752aa | 2023-10-17 16:58:29 -0700 | [diff] [blame] | 270 | void ConformanceTestSuite::ReportSuccess(const std::string& test_name) { |
Josh Haberman | d2b6738 | 2015-06-03 12:04:35 -0700 | [diff] [blame] | 271 | if (expected_to_fail_.erase(test_name) != 0) { |
Mike Kruskal | e99b281 | 2022-09-23 14:27:46 -0700 | [diff] [blame] | 272 | 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 Haberman | d2b6738 | 2015-06-03 12:04:35 -0700 | [diff] [blame] | 277 | unexpected_succeeding_tests_.insert(test_name); |
| 278 | } |
Josh Haberman | 4e63b52 | 2015-04-14 13:45:39 -0700 | [diff] [blame] | 279 | successes_++; |
| 280 | } |
| 281 | |
Mike Kruskal | 39752aa | 2023-10-17 16:58:29 -0700 | [diff] [blame] | 282 | void ConformanceTestSuite::ReportFailure(const std::string& test_name, |
Bo Yang | cc8ca5b | 2016-09-19 13:45:07 -0700 | [diff] [blame] | 283 | ConformanceLevel level, |
Josh Haberman | b0500b3 | 2015-07-10 16:36:59 -0700 | [diff] [blame] | 284 | const ConformanceRequest& request, |
| 285 | const ConformanceResponse& response, |
Mike Kruskal | e99b281 | 2022-09-23 14:27:46 -0700 | [diff] [blame] | 286 | absl::string_view message) { |
Josh Haberman | d2b6738 | 2015-06-03 12:04:35 -0700 | [diff] [blame] | 287 | if (expected_to_fail_.erase(test_name) == 1) { |
Josh Haberman | b0500b3 | 2015-07-10 16:36:59 -0700 | [diff] [blame] | 288 | expected_failures_++; |
Mike Kruskal | 2166cce | 2022-12-21 20:38:13 -0800 | [diff] [blame] | 289 | if (!verbose_) return; |
Bo Yang | cc8ca5b | 2016-09-19 13:45:07 -0700 | [diff] [blame] | 290 | } else if (level == RECOMMENDED && !enforce_recommended_) { |
Mike Kruskal | e99b281 | 2022-09-23 14:27:46 -0700 | [diff] [blame] | 291 | absl::StrAppendFormat(&output_, "WARNING, test=%s: ", test_name); |
Josh Haberman | d2b6738 | 2015-06-03 12:04:35 -0700 | [diff] [blame] | 292 | } else { |
Mike Kruskal | e99b281 | 2022-09-23 14:27:46 -0700 | [diff] [blame] | 293 | absl::StrAppendFormat(&output_, "ERROR, test=%s: ", test_name); |
Josh Haberman | d2b6738 | 2015-06-03 12:04:35 -0700 | [diff] [blame] | 294 | unexpected_failing_tests_.insert(test_name); |
| 295 | } |
Mike Kruskal | 32bea52 | 2022-10-06 16:48:39 -0700 | [diff] [blame] | 296 | |
| 297 | absl::StrAppendFormat(&output_, "%s, request=%s, response=%s\n", message, |
| 298 | TruncateRequest(request).ShortDebugString(), |
| 299 | TruncateResponse(response).ShortDebugString()); |
Josh Haberman | b0500b3 | 2015-07-10 16:36:59 -0700 | [diff] [blame] | 300 | } |
| 301 | |
Mike Kruskal | 39752aa | 2023-10-17 16:58:29 -0700 | [diff] [blame] | 302 | void ConformanceTestSuite::ReportSkip(const std::string& test_name, |
Josh Haberman | b0500b3 | 2015-07-10 16:36:59 -0700 | [diff] [blame] | 303 | const ConformanceRequest& request, |
| 304 | const ConformanceResponse& response) { |
| 305 | if (verbose_) { |
Mike Kruskal | e99b281 | 2022-09-23 14:27:46 -0700 | [diff] [blame] | 306 | absl::StrAppendFormat( |
| 307 | &output_, "SKIPPED, test=%s request=%s, response=%s\n", test_name, |
| 308 | request.ShortDebugString(), response.ShortDebugString()); |
Josh Haberman | b0500b3 | 2015-07-10 16:36:59 -0700 | [diff] [blame] | 309 | } |
| 310 | skipped_.insert(test_name); |
Josh Haberman | 4e63b52 | 2015-04-14 13:45:39 -0700 | [diff] [blame] | 311 | } |
| 312 | |
Josh Haberman | b0500b3 | 2015-07-10 16:36:59 -0700 | [diff] [blame] | 313 | void ConformanceTestSuite::RunValidInputTest( |
Paul Yang | 26eeec9 | 2018-07-09 14:29:23 -0700 | [diff] [blame] | 314 | const ConformanceRequestSetting& setting, |
Mike Kruskal | 39752aa | 2023-10-17 16:58:29 -0700 | [diff] [blame] | 315 | const std::string& equivalent_text_format) { |
Rafi Kamal | 58d4420 | 2019-11-11 17:06:56 -0800 | [diff] [blame] | 316 | std::unique_ptr<Message> reference_message(setting.NewTestMessage()); |
Mike Kruskal | a9f1ea6 | 2023-01-24 21:49:33 -0800 | [diff] [blame] | 317 | ABSL_CHECK(TextFormat::ParseFromString(equivalent_text_format, |
Mike Kruskal | a02c902 | 2022-12-08 12:15:31 -0800 | [diff] [blame] | 318 | reference_message.get())) |
Rafi Kamal | 58d4420 | 2019-11-11 17:06:56 -0800 | [diff] [blame] | 319 | << "Failed to parse data for test case: " << setting.GetTestName() |
| 320 | << ", data: " << equivalent_text_format; |
Mike Kruskal | 39752aa | 2023-10-17 16:58:29 -0700 | [diff] [blame] | 321 | const std::string equivalent_wire_format = |
| 322 | reference_message->SerializeAsString(); |
Paul Yang | 26eeec9 | 2018-07-09 14:29:23 -0700 | [diff] [blame] | 323 | RunValidBinaryInputTest(setting, equivalent_wire_format); |
Paul Yang | 23adfeb | 2017-10-26 14:41:43 -0700 | [diff] [blame] | 324 | } |
| 325 | |
| 326 | void ConformanceTestSuite::RunValidBinaryInputTest( |
Paul Yang | 26eeec9 | 2018-07-09 14:29:23 -0700 | [diff] [blame] | 327 | const ConformanceRequestSetting& setting, |
Mike Kruskal | 39752aa | 2023-10-17 16:58:29 -0700 | [diff] [blame] | 328 | const std::string& equivalent_wire_format, bool require_same_wire_format) { |
Paul Yang | cecba29 | 2018-12-14 16:05:03 -0800 | [diff] [blame] | 329 | const ConformanceRequest& request = setting.GetRequest(); |
| 330 | ConformanceResponse response; |
| 331 | RunTest(setting.GetTestName(), request, &response); |
Rafi Kamal | 4f02f05 | 2019-08-22 16:14:22 -0700 | [diff] [blame] | 332 | VerifyResponse(setting, equivalent_wire_format, response, true, |
| 333 | require_same_wire_format); |
Paul Yang | cecba29 | 2018-12-14 16:05:03 -0800 | [diff] [blame] | 334 | } |
| 335 | |
| 336 | void ConformanceTestSuite::VerifyResponse( |
| 337 | const ConformanceRequestSetting& setting, |
Mike Kruskal | 39752aa | 2023-10-17 16:58:29 -0700 | [diff] [blame] | 338 | const std::string& equivalent_wire_format, |
| 339 | const ConformanceResponse& response, bool need_report_success, |
| 340 | bool require_same_wire_format) { |
Rafi Kamal | 58d4420 | 2019-11-11 17:06:56 -0800 | [diff] [blame] | 341 | std::unique_ptr<Message> test_message(setting.NewTestMessage()); |
Paul Yang | cecba29 | 2018-12-14 16:05:03 -0800 | [diff] [blame] | 342 | const ConformanceRequest& request = setting.GetRequest(); |
Mike Kruskal | 39752aa | 2023-10-17 16:58:29 -0700 | [diff] [blame] | 343 | const std::string& test_name = setting.GetTestName(); |
Paul Yang | 26eeec9 | 2018-07-09 14:29:23 -0700 | [diff] [blame] | 344 | ConformanceLevel level = setting.GetLevel(); |
Rafi Kamal | 58d4420 | 2019-11-11 17:06:56 -0800 | [diff] [blame] | 345 | std::unique_ptr<Message> reference_message = setting.NewTestMessage(); |
Paul Yang | cecba29 | 2018-12-14 16:05:03 -0800 | [diff] [blame] | 346 | |
Mike Kruskal | a9f1ea6 | 2023-01-24 21:49:33 -0800 | [diff] [blame] | 347 | ABSL_CHECK(reference_message->ParseFromString(equivalent_wire_format)) |
Rafi Kamal | 58d4420 | 2019-11-11 17:06:56 -0800 | [diff] [blame] | 348 | << "Failed to parse wire data for test case: " << test_name; |
Josh Haberman | b0500b3 | 2015-07-10 16:36:59 -0700 | [diff] [blame] | 349 | |
Josh Haberman | b0500b3 | 2015-07-10 16:36:59 -0700 | [diff] [blame] | 350 | switch (response.result_case()) { |
Thomas Van Lenten | ac3df39 | 2016-08-11 09:44:07 -0400 | [diff] [blame] | 351 | case ConformanceResponse::RESULT_NOT_SET: |
Bo Yang | e3f0689 | 2016-09-19 17:29:57 -0700 | [diff] [blame] | 352 | ReportFailure(test_name, level, request, response, |
Thomas Van Lenten | ac3df39 | 2016-08-11 09:44:07 -0400 | [diff] [blame] | 353 | "Response didn't have any field in the Response."); |
| 354 | return; |
| 355 | |
Josh Haberman | b0500b3 | 2015-07-10 16:36:59 -0700 | [diff] [blame] | 356 | case ConformanceResponse::kParseError: |
Mike Kruskal | 32bea52 | 2022-10-06 16:48:39 -0700 | [diff] [blame] | 357 | case ConformanceResponse::kTimeoutError: |
Josh Haberman | b0500b3 | 2015-07-10 16:36:59 -0700 | [diff] [blame] | 358 | case ConformanceResponse::kRuntimeError: |
Feng Xiao | e841bac | 2015-12-11 17:09:20 -0800 | [diff] [blame] | 359 | case ConformanceResponse::kSerializeError: |
Bo Yang | e3f0689 | 2016-09-19 17:29:57 -0700 | [diff] [blame] | 360 | ReportFailure(test_name, level, request, response, |
Thomas Van Lenten | ac3df39 | 2016-08-11 09:44:07 -0400 | [diff] [blame] | 361 | "Failed to parse input or produce output."); |
Josh Haberman | b0500b3 | 2015-07-10 16:36:59 -0700 | [diff] [blame] | 362 | return; |
| 363 | |
| 364 | case ConformanceResponse::kSkipped: |
| 365 | ReportSkip(test_name, request, response); |
| 366 | return; |
| 367 | |
Feng Xiao | e841bac | 2015-12-11 17:09:20 -0800 | [diff] [blame] | 368 | default: |
Rafi Kamal | 58d4420 | 2019-11-11 17:06:56 -0800 | [diff] [blame] | 369 | if (!ParseResponse(response, setting, test_message.get())) return; |
Josh Haberman | b0500b3 | 2015-07-10 16:36:59 -0700 | [diff] [blame] | 370 | } |
| 371 | |
| 372 | MessageDifferencer differencer; |
Feng Xiao | e841bac | 2015-12-11 17:09:20 -0800 | [diff] [blame] | 373 | DefaultFieldComparator field_comparator; |
| 374 | field_comparator.set_treat_nan_as_equal(true); |
| 375 | differencer.set_field_comparator(&field_comparator); |
Mike Kruskal | 39752aa | 2023-10-17 16:58:29 -0700 | [diff] [blame] | 376 | std::string differences; |
Josh Haberman | b0500b3 | 2015-07-10 16:36:59 -0700 | [diff] [blame] | 377 | differencer.ReportDifferencesToString(&differences); |
| 378 | |
Paul Yang | a9bb656 | 2019-07-26 10:05:14 -0700 | [diff] [blame] | 379 | bool check = false; |
| 380 | |
| 381 | if (require_same_wire_format) { |
Mike Kruskal | a9f1ea6 | 2023-01-24 21:49:33 -0800 | [diff] [blame] | 382 | ABSL_DCHECK_EQ(response.result_case(), |
Mike Kruskal | a02c902 | 2022-12-08 12:15:31 -0800 | [diff] [blame] | 383 | ConformanceResponse::kProtobufPayload); |
Mike Kruskal | 39752aa | 2023-10-17 16:58:29 -0700 | [diff] [blame] | 384 | const std::string& protobuf_payload = response.protobuf_payload(); |
Paul Yang | a9bb656 | 2019-07-26 10:05:14 -0700 | [diff] [blame] | 385 | check = equivalent_wire_format == protobuf_payload; |
Mike Kruskal | a3c8e2d | 2022-08-24 10:46:33 -0700 | [diff] [blame] | 386 | differences = absl::StrCat("Expect: ", ToOctString(equivalent_wire_format), |
Rafi Kamal | 58d4420 | 2019-11-11 17:06:56 -0800 | [diff] [blame] | 387 | ", but got: ", ToOctString(protobuf_payload)); |
Paul Yang | a9bb656 | 2019-07-26 10:05:14 -0700 | [diff] [blame] | 388 | } else { |
| 389 | check = differencer.Compare(*reference_message, *test_message); |
| 390 | } |
| 391 | |
Jisi Liu | 759245a | 2017-07-25 11:52:33 -0700 | [diff] [blame] | 392 | if (check) { |
Paul Yang | cecba29 | 2018-12-14 16:05:03 -0800 | [diff] [blame] | 393 | if (need_report_success) { |
| 394 | ReportSuccess(test_name); |
| 395 | } |
Josh Haberman | b0500b3 | 2015-07-10 16:36:59 -0700 | [diff] [blame] | 396 | } else { |
Mike Kruskal | e99b281 | 2022-09-23 14:27:46 -0700 | [diff] [blame] | 397 | ReportFailure( |
| 398 | test_name, level, request, response, |
| 399 | absl::StrCat("Output was not equivalent to reference message: ", |
| 400 | differences)); |
Josh Haberman | b0500b3 | 2015-07-10 16:36:59 -0700 | [diff] [blame] | 401 | } |
| 402 | } |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 403 | |
Mike Kruskal | 39752aa | 2023-10-17 16:58:29 -0700 | [diff] [blame] | 404 | void ConformanceTestSuite::RunTest(const std::string& test_name, |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 405 | const ConformanceRequest& request, |
| 406 | ConformanceResponse* response) { |
| 407 | if (test_names_.insert(test_name).second == false) { |
Mike Kruskal | a9f1ea6 | 2023-01-24 21:49:33 -0800 | [diff] [blame] | 408 | ABSL_LOG(FATAL) << "Duplicated test name: " << test_name; |
Jisi Liu | 759245a | 2017-07-25 11:52:33 -0700 | [diff] [blame] | 409 | } |
Josh Haberman | 4e63b52 | 2015-04-14 13:45:39 -0700 | [diff] [blame] | 410 | |
Mike Kruskal | 39752aa | 2023-10-17 16:58:29 -0700 | [diff] [blame] | 411 | std::string serialized_request; |
| 412 | std::string serialized_response; |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 413 | request.SerializeToString(&serialized_request); |
Josh Haberman | 4e63b52 | 2015-04-14 13:45:39 -0700 | [diff] [blame] | 414 | |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 415 | 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 Kruskal | e99b281 | 2022-09-23 14:27:46 -0700 | [diff] [blame] | 423 | absl::StrAppendFormat( |
| 424 | &output_, "conformance test: name=%s, request=%s, response=%s\n", |
Mike Kruskal | 32bea52 | 2022-10-06 16:48:39 -0700 | [diff] [blame] | 425 | test_name, TruncateRequest(request).ShortDebugString(), |
| 426 | TruncateResponse(*response).ShortDebugString()); |
Josh Haberman | 4e63b52 | 2015-04-14 13:45:39 -0700 | [diff] [blame] | 427 | } |
| 428 | } |
| 429 | |
Mike Kruskal | 39752aa | 2023-10-17 16:58:29 -0700 | [diff] [blame] | 430 | std::string ConformanceTestSuite::WireFormatToString(WireFormat wire_format) { |
Paul Yang | cecba29 | 2018-12-14 16:05:03 -0800 | [diff] [blame] | 431 | 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 Chong | cb95a7f | 2019-01-11 11:40:52 -0800 | [diff] [blame] | 438 | case conformance::TEXT_FORMAT: |
| 439 | return "TEXT_FORMAT"; |
Paul Yang | cecba29 | 2018-12-14 16:05:03 -0800 | [diff] [blame] | 440 | case conformance::UNSPECIFIED: |
| 441 | return "UNSPECIFIED"; |
| 442 | default: |
Mike Kruskal | a9f1ea6 | 2023-01-24 21:49:33 -0800 | [diff] [blame] | 443 | ABSL_LOG(FATAL) << "unknown wire type: " << wire_format; |
Paul Yang | cecba29 | 2018-12-14 16:05:03 -0800 | [diff] [blame] | 444 | } |
| 445 | return ""; |
| 446 | } |
| 447 | |
Yilun Chong | d8c2501 | 2019-02-22 18:13:33 +0800 | [diff] [blame] | 448 | void ConformanceTestSuite::AddExpectedFailedTest(const std::string& test_name) { |
| 449 | expected_to_fail_.insert(test_name); |
| 450 | } |
| 451 | |
Yilun Chong | 0adb74c | 2019-01-08 15:06:30 -0800 | [diff] [blame] | 452 | bool ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner, |
Mike Kruskal | 39752aa | 2023-10-17 16:58:29 -0700 | [diff] [blame] | 453 | std::string* output, |
| 454 | const std::string& filename, |
Yilun Chong | 0adb74c | 2019-01-08 15:06:30 -0800 | [diff] [blame] | 455 | conformance::FailureSet* failure_list) { |
Josh Haberman | 4e63b52 | 2015-04-14 13:45:39 -0700 | [diff] [blame] | 456 | runner_ = runner; |
Josh Haberman | 4e63b52 | 2015-04-14 13:45:39 -0700 | [diff] [blame] | 457 | successes_ = 0; |
Josh Haberman | b0500b3 | 2015-07-10 16:36:59 -0700 | [diff] [blame] | 458 | expected_failures_ = 0; |
| 459 | skipped_.clear(); |
Josh Haberman | d2b6738 | 2015-06-03 12:04:35 -0700 | [diff] [blame] | 460 | test_names_.clear(); |
| 461 | unexpected_failing_tests_.clear(); |
| 462 | unexpected_succeeding_tests_.clear(); |
Josh Haberman | b0500b3 | 2015-07-10 16:36:59 -0700 | [diff] [blame] | 463 | |
| 464 | output_ = "\nCONFORMANCE TEST BEGIN ====================================\n\n"; |
Josh Haberman | 35a1cc7 | 2015-04-01 17:23:48 -0700 | [diff] [blame] | 465 | |
Yilun Chong | 0adb74c | 2019-01-08 15:06:30 -0800 | [diff] [blame] | 466 | failure_list_filename_ = filename; |
| 467 | expected_to_fail_.clear(); |
Mike Kruskal | 39752aa | 2023-10-17 16:58:29 -0700 | [diff] [blame] | 468 | for (const std::string& failure : failure_list->failure()) { |
Yilun Chong | d8c2501 | 2019-02-22 18:13:33 +0800 | [diff] [blame] | 469 | AddExpectedFailedTest(failure); |
Yilun Chong | 0adb74c | 2019-01-08 15:06:30 -0800 | [diff] [blame] | 470 | } |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 471 | RunSuiteImpl(); |
Paul Yang | 26eeec9 | 2018-07-09 14:29:23 -0700 | [diff] [blame] | 472 | |
Feng Xiao | e841bac | 2015-12-11 17:09:20 -0800 | [diff] [blame] | 473 | bool ok = true; |
Mike Kruskal | 2166cce | 2022-12-21 20:38:13 -0800 | [diff] [blame] | 474 | 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 Xiao | e841bac | 2015-12-11 17:09:20 -0800 | [diff] [blame] | 483 | ok = false; |
| 484 | } |
Mike Kruskal | 2166cce | 2022-12-21 20:38:13 -0800 | [diff] [blame] | 485 | 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 Haberman | ef7894e | 2016-05-16 12:45:02 -0700 | [diff] [blame] | 494 | ok = false; |
| 495 | } |
Mike Kruskal | 2166cce | 2022-12-21 20:38:13 -0800 | [diff] [blame] | 496 | 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 Xiao | e841bac | 2015-12-11 17:09:20 -0800 | [diff] [blame] | 505 | ok = false; |
| 506 | } |
| 507 | |
Josh Haberman | 325392d | 2015-08-17 12:30:49 -0700 | [diff] [blame] | 508 | if (verbose_) { |
Josh Haberman | ef7894e | 2016-05-16 12:45:02 -0700 | [diff] [blame] | 509 | CheckSetEmpty(skipped_, "", |
Josh Haberman | 325392d | 2015-08-17 12:30:49 -0700 | [diff] [blame] | 510 | "These tests were skipped (probably because support for some " |
Mike Kruskal | 2166cce | 2022-12-21 20:38:13 -0800 | [diff] [blame] | 511 | "features is not implemented)", |
| 512 | output_dir_, &output_); |
Josh Haberman | 325392d | 2015-08-17 12:30:49 -0700 | [diff] [blame] | 513 | } |
Josh Haberman | b0500b3 | 2015-07-10 16:36:59 -0700 | [diff] [blame] | 514 | |
Mike Kruskal | e99b281 | 2022-09-23 14:27:46 -0700 | [diff] [blame] | 515 | 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 Haberman | b0500b3 | 2015-07-10 16:36:59 -0700 | [diff] [blame] | 521 | |
Josh Haberman | 4e63b52 | 2015-04-14 13:45:39 -0700 | [diff] [blame] | 522 | output->assign(output_); |
Josh Haberman | d2b6738 | 2015-06-03 12:04:35 -0700 | [diff] [blame] | 523 | |
| 524 | return ok; |
Josh Haberman | 35a1cc7 | 2015-04-01 17:23:48 -0700 | [diff] [blame] | 525 | } |
Josh Haberman | 4e63b52 | 2015-04-14 13:45:39 -0700 | [diff] [blame] | 526 | |
| 527 | } // namespace protobuf |
| 528 | } // namespace google |