Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 1 | // Protocol Buffers - Google's data interchange format |
| 2 | // Copyright 2008 Google Inc. All rights reserved. |
| 3 | // https://developers.google.com/protocol-buffers/ |
| 4 | // |
| 5 | // Redistribution and use in source and binary forms, with or without |
| 6 | // modification, are permitted provided that the following conditions are |
| 7 | // met: |
| 8 | // |
| 9 | // * Redistributions of source code must retain the above copyright |
| 10 | // notice, this list of conditions and the following disclaimer. |
| 11 | // * Redistributions in binary form must reproduce the above |
| 12 | // copyright notice, this list of conditions and the following disclaimer |
| 13 | // in the documentation and/or other materials provided with the |
| 14 | // distribution. |
| 15 | // * Neither the name of Google Inc. nor the names of its |
| 16 | // contributors may be used to endorse or promote products derived from |
| 17 | // this software without specific prior written permission. |
| 18 | // |
| 19 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| 20 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| 21 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| 22 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| 23 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| 24 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| 25 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 26 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 27 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 28 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 29 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 30 | |
Paul Yang | cecba29 | 2018-12-14 16:05:03 -0800 | [diff] [blame] | 31 | #include "binary_json_conformance_suite.h" |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 32 | |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 33 | #include <google/protobuf/text_format.h> |
Rafi Kamal | 58d4420 | 2019-11-11 17:06:56 -0800 | [diff] [blame] | 34 | #include <google/protobuf/wire_format_lite.h> |
Paul Yang | cecba29 | 2018-12-14 16:05:03 -0800 | [diff] [blame] | 35 | #include <google/protobuf/util/json_util.h> |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 36 | #include <google/protobuf/util/type_resolver_util.h> |
Rafi Kamal | 58d4420 | 2019-11-11 17:06:56 -0800 | [diff] [blame] | 37 | #include "third_party/jsoncpp/json.h" |
| 38 | #include "conformance_test.h" |
| 39 | #include <google/protobuf/test_messages_proto2.pb.h> |
| 40 | #include <google/protobuf/test_messages_proto3.pb.h> |
| 41 | #include <google/protobuf/stubs/status.h> |
| 42 | |
| 43 | namespace proto2_messages = protobuf_test_messages::proto2; |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 44 | |
| 45 | using conformance::ConformanceRequest; |
| 46 | using conformance::ConformanceResponse; |
Paul Yang | cecba29 | 2018-12-14 16:05:03 -0800 | [diff] [blame] | 47 | using conformance::WireFormat; |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 48 | using google::protobuf::Descriptor; |
| 49 | using google::protobuf::FieldDescriptor; |
| 50 | using google::protobuf::Message; |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 51 | using google::protobuf::TextFormat; |
Rafi Kamal | 58d4420 | 2019-11-11 17:06:56 -0800 | [diff] [blame] | 52 | using google::protobuf::internal::WireFormatLite; |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 53 | using google::protobuf::util::NewTypeResolverForDescriptorPool; |
Rafi Kamal | 58d4420 | 2019-11-11 17:06:56 -0800 | [diff] [blame] | 54 | using proto2_messages::TestAllTypesProto2; |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 55 | using protobuf_test_messages::proto3::TestAllTypesProto3; |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 56 | using std::string; |
| 57 | |
| 58 | namespace { |
| 59 | |
| 60 | static const char kTypeUrlPrefix[] = "type.googleapis.com"; |
| 61 | |
| 62 | static string GetTypeUrl(const Descriptor* message) { |
| 63 | return string(kTypeUrlPrefix) + "/" + message->full_name(); |
| 64 | } |
| 65 | |
| 66 | /* Routines for building arbitrary protos *************************************/ |
| 67 | |
| 68 | // We would use CodedOutputStream except that we want more freedom to build |
| 69 | // arbitrary protos (even invalid ones). |
| 70 | |
| 71 | const string empty; |
| 72 | |
| 73 | string cat(const string& a, const string& b, |
| 74 | const string& c = empty, |
| 75 | const string& d = empty, |
| 76 | const string& e = empty, |
| 77 | const string& f = empty, |
| 78 | const string& g = empty, |
| 79 | const string& h = empty, |
| 80 | const string& i = empty, |
| 81 | const string& j = empty, |
| 82 | const string& k = empty, |
| 83 | const string& l = empty) { |
| 84 | string ret; |
| 85 | ret.reserve(a.size() + b.size() + c.size() + d.size() + e.size() + f.size() + |
| 86 | g.size() + h.size() + i.size() + j.size() + k.size() + l.size()); |
| 87 | ret.append(a); |
| 88 | ret.append(b); |
| 89 | ret.append(c); |
| 90 | ret.append(d); |
| 91 | ret.append(e); |
| 92 | ret.append(f); |
| 93 | ret.append(g); |
| 94 | ret.append(h); |
| 95 | ret.append(i); |
| 96 | ret.append(j); |
| 97 | ret.append(k); |
| 98 | ret.append(l); |
| 99 | return ret; |
| 100 | } |
| 101 | |
| 102 | // The maximum number of bytes that it takes to encode a 64-bit varint. |
| 103 | #define VARINT_MAX_LEN 10 |
| 104 | |
| 105 | size_t vencode64(uint64_t val, int over_encoded_bytes, char *buf) { |
| 106 | if (val == 0) { buf[0] = 0; return 1; } |
| 107 | size_t i = 0; |
| 108 | while (val) { |
| 109 | uint8_t byte = val & 0x7fU; |
| 110 | val >>= 7; |
| 111 | if (val || over_encoded_bytes) byte |= 0x80U; |
| 112 | buf[i++] = byte; |
| 113 | } |
| 114 | while (over_encoded_bytes--) { |
| 115 | assert(i < 10); |
| 116 | uint8_t byte = over_encoded_bytes ? 0x80 : 0; |
| 117 | buf[i++] = byte; |
| 118 | } |
| 119 | return i; |
| 120 | } |
| 121 | |
| 122 | string varint(uint64_t x) { |
| 123 | char buf[VARINT_MAX_LEN]; |
| 124 | size_t len = vencode64(x, 0, buf); |
| 125 | return string(buf, len); |
| 126 | } |
| 127 | |
| 128 | // Encodes a varint that is |extra| bytes longer than it needs to be, but still |
| 129 | // valid. |
| 130 | string longvarint(uint64_t x, int extra) { |
| 131 | char buf[VARINT_MAX_LEN]; |
| 132 | size_t len = vencode64(x, extra, buf); |
| 133 | return string(buf, len); |
| 134 | } |
| 135 | |
| 136 | // TODO: proper byte-swapping for big-endian machines. |
| 137 | string fixed32(void *data) { return string(static_cast<char*>(data), 4); } |
| 138 | string fixed64(void *data) { return string(static_cast<char*>(data), 8); } |
| 139 | |
| 140 | string delim(const string& buf) { return cat(varint(buf.size()), buf); } |
| 141 | string u32(uint32_t u32) { return fixed32(&u32); } |
| 142 | string u64(uint64_t u64) { return fixed64(&u64); } |
| 143 | string flt(float f) { return fixed32(&f); } |
| 144 | string dbl(double d) { return fixed64(&d); } |
| 145 | string zz32(int32_t x) { return varint(WireFormatLite::ZigZagEncode32(x)); } |
| 146 | string zz64(int64_t x) { return varint(WireFormatLite::ZigZagEncode64(x)); } |
| 147 | |
| 148 | string tag(uint32_t fieldnum, char wire_type) { |
| 149 | return varint((fieldnum << 3) | wire_type); |
| 150 | } |
| 151 | |
Paul Yang | ce942bc | 2019-09-03 10:47:32 -0700 | [diff] [blame] | 152 | string GetDefaultValue(FieldDescriptor::Type type) { |
| 153 | switch (type) { |
| 154 | case FieldDescriptor::TYPE_INT32: |
| 155 | case FieldDescriptor::TYPE_INT64: |
| 156 | case FieldDescriptor::TYPE_UINT32: |
| 157 | case FieldDescriptor::TYPE_UINT64: |
| 158 | case FieldDescriptor::TYPE_ENUM: |
| 159 | case FieldDescriptor::TYPE_BOOL: |
| 160 | return varint(0); |
| 161 | case FieldDescriptor::TYPE_SINT32: |
| 162 | return zz32(0); |
| 163 | case FieldDescriptor::TYPE_SINT64: |
| 164 | return zz64(0); |
| 165 | case FieldDescriptor::TYPE_FIXED32: |
| 166 | case FieldDescriptor::TYPE_SFIXED32: |
| 167 | return u32(0); |
| 168 | case FieldDescriptor::TYPE_FIXED64: |
| 169 | case FieldDescriptor::TYPE_SFIXED64: |
| 170 | return u64(0); |
| 171 | case FieldDescriptor::TYPE_FLOAT: |
| 172 | return flt(0); |
| 173 | case FieldDescriptor::TYPE_DOUBLE: |
| 174 | return dbl(0); |
| 175 | case FieldDescriptor::TYPE_STRING: |
| 176 | case FieldDescriptor::TYPE_BYTES: |
| 177 | case FieldDescriptor::TYPE_MESSAGE: |
| 178 | return delim(""); |
Rafi Kamal | 6c92f9d | 2019-10-11 12:05:46 -0700 | [diff] [blame] | 179 | default: |
| 180 | return ""; |
Paul Yang | ce942bc | 2019-09-03 10:47:32 -0700 | [diff] [blame] | 181 | } |
| 182 | return ""; |
| 183 | } |
| 184 | |
| 185 | string GetNonDefaultValue(FieldDescriptor::Type type) { |
| 186 | switch (type) { |
| 187 | case FieldDescriptor::TYPE_INT32: |
| 188 | case FieldDescriptor::TYPE_INT64: |
| 189 | case FieldDescriptor::TYPE_UINT32: |
| 190 | case FieldDescriptor::TYPE_UINT64: |
| 191 | case FieldDescriptor::TYPE_ENUM: |
| 192 | case FieldDescriptor::TYPE_BOOL: |
| 193 | return varint(1); |
| 194 | case FieldDescriptor::TYPE_SINT32: |
| 195 | return zz32(1); |
| 196 | case FieldDescriptor::TYPE_SINT64: |
| 197 | return zz64(1); |
| 198 | case FieldDescriptor::TYPE_FIXED32: |
| 199 | case FieldDescriptor::TYPE_SFIXED32: |
| 200 | return u32(1); |
| 201 | case FieldDescriptor::TYPE_FIXED64: |
| 202 | case FieldDescriptor::TYPE_SFIXED64: |
| 203 | return u64(1); |
| 204 | case FieldDescriptor::TYPE_FLOAT: |
| 205 | return flt(1); |
| 206 | case FieldDescriptor::TYPE_DOUBLE: |
| 207 | return dbl(1); |
| 208 | case FieldDescriptor::TYPE_STRING: |
| 209 | case FieldDescriptor::TYPE_BYTES: |
| 210 | return delim("a"); |
| 211 | case FieldDescriptor::TYPE_MESSAGE: |
| 212 | return delim(cat(tag(1, WireFormatLite::WIRETYPE_VARINT), varint(1234))); |
Rafi Kamal | 6c92f9d | 2019-10-11 12:05:46 -0700 | [diff] [blame] | 213 | default: |
| 214 | return ""; |
Paul Yang | ce942bc | 2019-09-03 10:47:32 -0700 | [diff] [blame] | 215 | } |
| 216 | return ""; |
| 217 | } |
| 218 | |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 219 | #define UNKNOWN_FIELD 666 |
| 220 | |
Paul Yang | 0c4b607 | 2019-08-02 14:35:44 -0700 | [diff] [blame] | 221 | enum class Packed { |
Adam Cozzette | 9faf5a7 | 2021-08-25 13:55:16 -0700 | [diff] [blame] | 222 | kUnspecified = 0, |
| 223 | kTrue = 1, |
| 224 | kFalse = 2, |
Paul Yang | 0c4b607 | 2019-08-02 14:35:44 -0700 | [diff] [blame] | 225 | }; |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 226 | |
Rafi Kamal | 4f02f05 | 2019-08-22 16:14:22 -0700 | [diff] [blame] | 227 | const FieldDescriptor* GetFieldForType(FieldDescriptor::Type type, |
| 228 | bool repeated, bool is_proto3, |
Adam Cozzette | 9faf5a7 | 2021-08-25 13:55:16 -0700 | [diff] [blame] | 229 | Packed packed = Packed::kUnspecified) { |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 230 | const Descriptor* d = is_proto3 ? |
| 231 | TestAllTypesProto3().GetDescriptor() : TestAllTypesProto2().GetDescriptor(); |
| 232 | for (int i = 0; i < d->field_count(); i++) { |
| 233 | const FieldDescriptor* f = d->field(i); |
| 234 | if (f->type() == type && f->is_repeated() == repeated) { |
Adam Cozzette | 9faf5a7 | 2021-08-25 13:55:16 -0700 | [diff] [blame] | 235 | if ((packed == Packed::kTrue && !f->is_packed()) || |
| 236 | (packed == Packed::kFalse && f->is_packed())) { |
Paul Yang | 0c4b607 | 2019-08-02 14:35:44 -0700 | [diff] [blame] | 237 | continue; |
| 238 | } |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 239 | return f; |
| 240 | } |
| 241 | } |
Paul Yang | 0c4b607 | 2019-08-02 14:35:44 -0700 | [diff] [blame] | 242 | |
| 243 | string packed_string = ""; |
| 244 | const string repeated_string = repeated ? "Repeated " : "Singular "; |
| 245 | const string proto_string = is_proto3 ? "Proto3" : "Proto2"; |
Adam Cozzette | 9faf5a7 | 2021-08-25 13:55:16 -0700 | [diff] [blame] | 246 | if (packed == Packed::kTrue) { |
Paul Yang | 0c4b607 | 2019-08-02 14:35:44 -0700 | [diff] [blame] | 247 | packed_string = "Packed "; |
| 248 | } |
Adam Cozzette | 9faf5a7 | 2021-08-25 13:55:16 -0700 | [diff] [blame] | 249 | if (packed == Packed::kFalse) { |
Paul Yang | 0c4b607 | 2019-08-02 14:35:44 -0700 | [diff] [blame] | 250 | packed_string = "Unpacked "; |
| 251 | } |
Rafi Kamal | 58d4420 | 2019-11-11 17:06:56 -0800 | [diff] [blame] | 252 | GOOGLE_LOG(FATAL) << "Couldn't find field with type: " << repeated_string.c_str() |
| 253 | << packed_string.c_str() << FieldDescriptor::TypeName(type) |
| 254 | << " for " << proto_string.c_str(); |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 255 | return nullptr; |
| 256 | } |
| 257 | |
Rafi Kamal | 6c92f9d | 2019-10-11 12:05:46 -0700 | [diff] [blame] | 258 | const FieldDescriptor* GetFieldForMapType(FieldDescriptor::Type key_type, |
| 259 | FieldDescriptor::Type value_type, |
| 260 | bool is_proto3) { |
| 261 | const Descriptor* d = is_proto3 ? TestAllTypesProto3().GetDescriptor() |
| 262 | : TestAllTypesProto2().GetDescriptor(); |
Paul Yang | ce942bc | 2019-09-03 10:47:32 -0700 | [diff] [blame] | 263 | for (int i = 0; i < d->field_count(); i++) { |
| 264 | const FieldDescriptor* f = d->field(i); |
| 265 | if (f->is_map()) { |
| 266 | const Descriptor* map_entry = f->message_type(); |
| 267 | const FieldDescriptor* key = map_entry->field(0); |
| 268 | const FieldDescriptor* value = map_entry->field(1); |
| 269 | if (key->type() == key_type && value->type() == value_type) { |
| 270 | return f; |
| 271 | } |
| 272 | } |
| 273 | } |
| 274 | |
| 275 | const string proto_string = is_proto3 ? "Proto3" : "Proto2"; |
| 276 | GOOGLE_LOG(FATAL) << "Couldn't find map field with type: " |
Rafi Kamal | 58d4420 | 2019-11-11 17:06:56 -0800 | [diff] [blame] | 277 | << FieldDescriptor::TypeName(key_type) << " and " |
| 278 | << FieldDescriptor::TypeName(key_type) << " for " |
| 279 | << proto_string.c_str(); |
Paul Yang | ce942bc | 2019-09-03 10:47:32 -0700 | [diff] [blame] | 280 | return nullptr; |
| 281 | } |
| 282 | |
Rafi Kamal | 6c92f9d | 2019-10-11 12:05:46 -0700 | [diff] [blame] | 283 | const FieldDescriptor* GetFieldForOneofType(FieldDescriptor::Type type, |
| 284 | bool is_proto3, |
| 285 | bool exclusive = false) { |
| 286 | const Descriptor* d = is_proto3 ? TestAllTypesProto3().GetDescriptor() |
| 287 | : TestAllTypesProto2().GetDescriptor(); |
Paul Yang | 7114d73 | 2019-09-09 13:31:53 -0700 | [diff] [blame] | 288 | for (int i = 0; i < d->field_count(); i++) { |
| 289 | const FieldDescriptor* f = d->field(i); |
| 290 | if (f->containing_oneof() && ((f->type() == type) ^ exclusive)) { |
| 291 | return f; |
| 292 | } |
| 293 | } |
| 294 | |
| 295 | const string proto_string = is_proto3 ? "Proto3" : "Proto2"; |
| 296 | GOOGLE_LOG(FATAL) << "Couldn't find oneof field with type: " |
Rafi Kamal | 58d4420 | 2019-11-11 17:06:56 -0800 | [diff] [blame] | 297 | << FieldDescriptor::TypeName(type) << " for " |
| 298 | << proto_string.c_str(); |
Paul Yang | 7114d73 | 2019-09-09 13:31:53 -0700 | [diff] [blame] | 299 | return nullptr; |
| 300 | } |
| 301 | |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 302 | string UpperCase(string str) { |
Abhishek Jain | 0ef575b | 2021-02-12 05:59:47 +0530 | [diff] [blame] | 303 | for (size_t i = 0; i < str.size(); i++) { |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 304 | str[i] = toupper(str[i]); |
| 305 | } |
| 306 | return str; |
| 307 | } |
| 308 | |
| 309 | std::unique_ptr<Message> NewTestMessage(bool is_proto3) { |
| 310 | std::unique_ptr<Message> prototype; |
| 311 | if (is_proto3) { |
| 312 | prototype.reset(new TestAllTypesProto3()); |
| 313 | } else { |
| 314 | prototype.reset(new TestAllTypesProto2()); |
| 315 | } |
| 316 | return prototype; |
| 317 | } |
| 318 | |
Paul Yang | 6c9d7ec | 2019-08-23 12:20:19 -0700 | [diff] [blame] | 319 | bool IsProto3Default(FieldDescriptor::Type type, const string& binary_data) { |
| 320 | switch (type) { |
| 321 | case FieldDescriptor::TYPE_DOUBLE: |
| 322 | return binary_data == dbl(0); |
| 323 | case FieldDescriptor::TYPE_FLOAT: |
| 324 | return binary_data == flt(0); |
| 325 | case FieldDescriptor::TYPE_BOOL: |
| 326 | case FieldDescriptor::TYPE_INT64: |
| 327 | case FieldDescriptor::TYPE_UINT64: |
| 328 | case FieldDescriptor::TYPE_INT32: |
| 329 | case FieldDescriptor::TYPE_UINT32: |
| 330 | case FieldDescriptor::TYPE_SINT32: |
| 331 | case FieldDescriptor::TYPE_SINT64: |
| 332 | case FieldDescriptor::TYPE_ENUM: |
| 333 | return binary_data == varint(0); |
| 334 | case FieldDescriptor::TYPE_FIXED64: |
| 335 | case FieldDescriptor::TYPE_SFIXED64: |
| 336 | return binary_data == u64(0); |
| 337 | case FieldDescriptor::TYPE_FIXED32: |
| 338 | case FieldDescriptor::TYPE_SFIXED32: |
| 339 | return binary_data == u32(0); |
| 340 | case FieldDescriptor::TYPE_STRING: |
| 341 | case FieldDescriptor::TYPE_BYTES: |
| 342 | return binary_data == delim(""); |
| 343 | default: |
| 344 | return false; |
| 345 | } |
| 346 | } |
| 347 | |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 348 | } // anonymous namespace |
| 349 | |
| 350 | namespace google { |
| 351 | namespace protobuf { |
| 352 | |
Paul Yang | cecba29 | 2018-12-14 16:05:03 -0800 | [diff] [blame] | 353 | bool BinaryAndJsonConformanceSuite::ParseJsonResponse( |
| 354 | const ConformanceResponse& response, |
| 355 | Message* test_message) { |
| 356 | string binary_protobuf; |
| 357 | util::Status status = |
| 358 | JsonToBinaryString(type_resolver_.get(), type_url_, |
| 359 | response.json_payload(), &binary_protobuf); |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 360 | |
Paul Yang | cecba29 | 2018-12-14 16:05:03 -0800 | [diff] [blame] | 361 | if (!status.ok()) { |
| 362 | return false; |
| 363 | } |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 364 | |
Paul Yang | cecba29 | 2018-12-14 16:05:03 -0800 | [diff] [blame] | 365 | if (!test_message->ParseFromString(binary_protobuf)) { |
Rafi Kamal | 58d4420 | 2019-11-11 17:06:56 -0800 | [diff] [blame] | 366 | GOOGLE_LOG(FATAL) << "INTERNAL ERROR: internal JSON->protobuf transcode " |
| 367 | << "yielded unparseable proto."; |
Paul Yang | cecba29 | 2018-12-14 16:05:03 -0800 | [diff] [blame] | 368 | return false; |
| 369 | } |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 370 | |
Paul Yang | cecba29 | 2018-12-14 16:05:03 -0800 | [diff] [blame] | 371 | return true; |
| 372 | } |
| 373 | |
| 374 | bool BinaryAndJsonConformanceSuite::ParseResponse( |
| 375 | const ConformanceResponse& response, |
| 376 | const ConformanceRequestSetting& setting, |
| 377 | Message* test_message) { |
| 378 | const ConformanceRequest& request = setting.GetRequest(); |
| 379 | WireFormat requested_output = request.requested_output_format(); |
| 380 | const string& test_name = setting.GetTestName(); |
| 381 | ConformanceLevel level = setting.GetLevel(); |
| 382 | |
| 383 | switch (response.result_case()) { |
| 384 | case ConformanceResponse::kProtobufPayload: { |
| 385 | if (requested_output != conformance::PROTOBUF) { |
Rafi Kamal | 58d4420 | 2019-11-11 17:06:56 -0800 | [diff] [blame] | 386 | ReportFailure(test_name, level, request, response, |
| 387 | StrCat("Test was asked for ", |
| 388 | WireFormatToString(requested_output), |
| 389 | " output but provided PROTOBUF instead.") |
| 390 | .c_str()); |
Paul Yang | cecba29 | 2018-12-14 16:05:03 -0800 | [diff] [blame] | 391 | return false; |
| 392 | } |
| 393 | |
| 394 | if (!test_message->ParseFromString(response.protobuf_payload())) { |
| 395 | ReportFailure(test_name, level, request, response, |
| 396 | "Protobuf output we received from test was unparseable."); |
| 397 | return false; |
| 398 | } |
| 399 | |
| 400 | break; |
| 401 | } |
| 402 | |
| 403 | case ConformanceResponse::kJsonPayload: { |
| 404 | if (requested_output != conformance::JSON) { |
Rafi Kamal | 58d4420 | 2019-11-11 17:06:56 -0800 | [diff] [blame] | 405 | ReportFailure(test_name, level, request, response, |
| 406 | StrCat("Test was asked for ", |
| 407 | WireFormatToString(requested_output), |
| 408 | " output but provided JSON instead.") |
| 409 | .c_str()); |
Paul Yang | cecba29 | 2018-12-14 16:05:03 -0800 | [diff] [blame] | 410 | return false; |
| 411 | } |
| 412 | |
| 413 | if (!ParseJsonResponse(response, test_message)) { |
| 414 | ReportFailure(test_name, level, request, response, |
| 415 | "JSON output we received from test was unparseable."); |
| 416 | return false; |
| 417 | } |
| 418 | |
| 419 | break; |
| 420 | } |
| 421 | |
| 422 | default: |
Rafi Kamal | 58d4420 | 2019-11-11 17:06:56 -0800 | [diff] [blame] | 423 | GOOGLE_LOG(FATAL) << test_name |
| 424 | << ": unknown payload type: " << response.result_case(); |
Paul Yang | cecba29 | 2018-12-14 16:05:03 -0800 | [diff] [blame] | 425 | } |
| 426 | |
| 427 | return true; |
| 428 | } |
| 429 | |
| 430 | void BinaryAndJsonConformanceSuite::ExpectParseFailureForProtoWithProtoVersion ( |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 431 | const string& proto, const string& test_name, ConformanceLevel level, |
| 432 | bool is_proto3) { |
| 433 | std::unique_ptr<Message> prototype = NewTestMessage(is_proto3); |
| 434 | // We don't expect output, but if the program erroneously accepts the protobuf |
| 435 | // we let it send its response as this. We must not leave it unspecified. |
| 436 | ConformanceRequestSetting setting( |
| 437 | level, conformance::PROTOBUF, conformance::PROTOBUF, |
| 438 | conformance::BINARY_TEST, |
| 439 | *prototype, test_name, proto); |
| 440 | |
| 441 | const ConformanceRequest& request = setting.GetRequest(); |
| 442 | ConformanceResponse response; |
Rafi Kamal | 58d4420 | 2019-11-11 17:06:56 -0800 | [diff] [blame] | 443 | string effective_test_name = StrCat( |
| 444 | setting.ConformanceLevelToString(level), |
| 445 | (is_proto3 ? ".Proto3" : ".Proto2"), ".ProtobufInput.", test_name); |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 446 | |
| 447 | RunTest(effective_test_name, request, &response); |
| 448 | if (response.result_case() == ConformanceResponse::kParseError) { |
| 449 | ReportSuccess(effective_test_name); |
| 450 | } else if (response.result_case() == ConformanceResponse::kSkipped) { |
| 451 | ReportSkip(effective_test_name, request, response); |
| 452 | } else { |
| 453 | ReportFailure(effective_test_name, level, request, response, |
| 454 | "Should have failed to parse, but didn't."); |
| 455 | } |
| 456 | } |
| 457 | |
| 458 | // Expect that this precise protobuf will cause a parse error. |
Paul Yang | cecba29 | 2018-12-14 16:05:03 -0800 | [diff] [blame] | 459 | void BinaryAndJsonConformanceSuite::ExpectParseFailureForProto( |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 460 | const string& proto, const string& test_name, ConformanceLevel level) { |
| 461 | ExpectParseFailureForProtoWithProtoVersion(proto, test_name, level, true); |
| 462 | ExpectParseFailureForProtoWithProtoVersion(proto, test_name, level, false); |
| 463 | } |
| 464 | |
| 465 | // Expect that this protobuf will cause a parse error, even if it is followed |
| 466 | // by valid protobuf data. We can try running this twice: once with this |
| 467 | // data verbatim and once with this data followed by some valid data. |
| 468 | // |
| 469 | // TODO(haberman): implement the second of these. |
Paul Yang | cecba29 | 2018-12-14 16:05:03 -0800 | [diff] [blame] | 470 | void BinaryAndJsonConformanceSuite::ExpectHardParseFailureForProto( |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 471 | const string& proto, const string& test_name, ConformanceLevel level) { |
| 472 | return ExpectParseFailureForProto(proto, test_name, level); |
| 473 | } |
| 474 | |
Paul Yang | cecba29 | 2018-12-14 16:05:03 -0800 | [diff] [blame] | 475 | void BinaryAndJsonConformanceSuite::RunValidJsonTest( |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 476 | const string& test_name, ConformanceLevel level, const string& input_json, |
| 477 | const string& equivalent_text_format) { |
| 478 | TestAllTypesProto3 prototype; |
| 479 | ConformanceRequestSetting setting1( |
| 480 | level, conformance::JSON, conformance::PROTOBUF, |
| 481 | conformance::JSON_TEST, |
| 482 | prototype, test_name, input_json); |
| 483 | RunValidInputTest(setting1, equivalent_text_format); |
| 484 | ConformanceRequestSetting setting2( |
| 485 | level, conformance::JSON, conformance::JSON, |
| 486 | conformance::JSON_TEST, |
| 487 | prototype, test_name, input_json); |
| 488 | RunValidInputTest(setting2, equivalent_text_format); |
| 489 | } |
| 490 | |
Paul Yang | cecba29 | 2018-12-14 16:05:03 -0800 | [diff] [blame] | 491 | void BinaryAndJsonConformanceSuite::RunValidJsonTestWithProtobufInput( |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 492 | const string& test_name, ConformanceLevel level, const TestAllTypesProto3& input, |
| 493 | const string& equivalent_text_format) { |
| 494 | ConformanceRequestSetting setting( |
| 495 | level, conformance::PROTOBUF, conformance::JSON, |
| 496 | conformance::JSON_TEST, |
| 497 | input, test_name, input.SerializeAsString()); |
| 498 | RunValidInputTest(setting, equivalent_text_format); |
| 499 | } |
| 500 | |
Paul Yang | cecba29 | 2018-12-14 16:05:03 -0800 | [diff] [blame] | 501 | void BinaryAndJsonConformanceSuite::RunValidJsonIgnoreUnknownTest( |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 502 | const string& test_name, ConformanceLevel level, const string& input_json, |
| 503 | const string& equivalent_text_format) { |
| 504 | TestAllTypesProto3 prototype; |
| 505 | ConformanceRequestSetting setting( |
| 506 | level, conformance::JSON, conformance::PROTOBUF, |
| 507 | conformance::JSON_IGNORE_UNKNOWN_PARSING_TEST, |
| 508 | prototype, test_name, input_json); |
| 509 | RunValidInputTest(setting, equivalent_text_format); |
| 510 | } |
| 511 | |
Paul Yang | cecba29 | 2018-12-14 16:05:03 -0800 | [diff] [blame] | 512 | void BinaryAndJsonConformanceSuite::RunValidProtobufTest( |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 513 | const string& test_name, ConformanceLevel level, |
| 514 | const string& input_protobuf, const string& equivalent_text_format, |
| 515 | bool is_proto3) { |
| 516 | std::unique_ptr<Message> prototype = NewTestMessage(is_proto3); |
| 517 | |
| 518 | ConformanceRequestSetting setting1( |
| 519 | level, conformance::PROTOBUF, conformance::PROTOBUF, |
| 520 | conformance::BINARY_TEST, |
| 521 | *prototype, test_name, input_protobuf); |
| 522 | RunValidInputTest(setting1, equivalent_text_format); |
| 523 | |
| 524 | if (is_proto3) { |
| 525 | ConformanceRequestSetting setting2( |
| 526 | level, conformance::PROTOBUF, conformance::JSON, |
| 527 | conformance::BINARY_TEST, |
| 528 | *prototype, test_name, input_protobuf); |
| 529 | RunValidInputTest(setting2, equivalent_text_format); |
| 530 | } |
| 531 | } |
| 532 | |
Paul Yang | cecba29 | 2018-12-14 16:05:03 -0800 | [diff] [blame] | 533 | void BinaryAndJsonConformanceSuite::RunValidBinaryProtobufTest( |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 534 | const string& test_name, ConformanceLevel level, |
| 535 | const string& input_protobuf, bool is_proto3) { |
Rafi Kamal | 4f02f05 | 2019-08-22 16:14:22 -0700 | [diff] [blame] | 536 | RunValidBinaryProtobufTest(test_name, level, input_protobuf, input_protobuf, |
| 537 | is_proto3); |
Paul Yang | a9bb656 | 2019-07-26 10:05:14 -0700 | [diff] [blame] | 538 | } |
| 539 | |
| 540 | void BinaryAndJsonConformanceSuite::RunValidBinaryProtobufTest( |
| 541 | const string& test_name, ConformanceLevel level, |
Rafi Kamal | 4f02f05 | 2019-08-22 16:14:22 -0700 | [diff] [blame] | 542 | const string& input_protobuf, const string& expected_protobuf, |
Paul Yang | a9bb656 | 2019-07-26 10:05:14 -0700 | [diff] [blame] | 543 | bool is_proto3) { |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 544 | std::unique_ptr<Message> prototype = NewTestMessage(is_proto3); |
| 545 | ConformanceRequestSetting setting( |
| 546 | level, conformance::PROTOBUF, conformance::PROTOBUF, |
| 547 | conformance::BINARY_TEST, |
| 548 | *prototype, test_name, input_protobuf); |
Paul Yang | a9bb656 | 2019-07-26 10:05:14 -0700 | [diff] [blame] | 549 | RunValidBinaryInputTest(setting, expected_protobuf, true); |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 550 | } |
| 551 | |
Paul Yang | cecba29 | 2018-12-14 16:05:03 -0800 | [diff] [blame] | 552 | void BinaryAndJsonConformanceSuite::RunValidProtobufTestWithMessage( |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 553 | const string& test_name, ConformanceLevel level, const Message *input, |
| 554 | const string& equivalent_text_format, bool is_proto3) { |
| 555 | RunValidProtobufTest(test_name, level, input->SerializeAsString(), |
| 556 | equivalent_text_format, is_proto3); |
| 557 | } |
| 558 | |
Joshua Haberman | 2d80a70 | 2020-05-07 16:21:50 -0700 | [diff] [blame] | 559 | // According to proto JSON specification, JSON serializers follow more strict |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 560 | // rules than parsers (e.g., a serializer must serialize int32 values as JSON |
| 561 | // numbers while the parser is allowed to accept them as JSON strings). This |
Joshua Haberman | 2d80a70 | 2020-05-07 16:21:50 -0700 | [diff] [blame] | 562 | // method allows strict checking on a proto JSON serializer by inspecting |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 563 | // the JSON output directly. |
Paul Yang | cecba29 | 2018-12-14 16:05:03 -0800 | [diff] [blame] | 564 | void BinaryAndJsonConformanceSuite::RunValidJsonTestWithValidator( |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 565 | const string& test_name, ConformanceLevel level, const string& input_json, |
Joshua Haberman | 2d80a70 | 2020-05-07 16:21:50 -0700 | [diff] [blame] | 566 | const Validator& validator, bool is_proto3) { |
| 567 | std::unique_ptr<Message> prototype = NewTestMessage(is_proto3); |
| 568 | ConformanceRequestSetting setting(level, conformance::JSON, conformance::JSON, |
| 569 | conformance::JSON_TEST, *prototype, |
| 570 | test_name, input_json); |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 571 | const ConformanceRequest& request = setting.GetRequest(); |
| 572 | ConformanceResponse response; |
| 573 | string effective_test_name = |
| 574 | StrCat(setting.ConformanceLevelToString(level), |
Joshua Haberman | 2d80a70 | 2020-05-07 16:21:50 -0700 | [diff] [blame] | 575 | is_proto3 ? ".Proto3.JsonInput." : ".Proto2.JsonInput.", |
| 576 | test_name, ".Validator"); |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 577 | |
| 578 | RunTest(effective_test_name, request, &response); |
| 579 | |
| 580 | if (response.result_case() == ConformanceResponse::kSkipped) { |
| 581 | ReportSkip(effective_test_name, request, response); |
| 582 | return; |
| 583 | } |
| 584 | |
| 585 | if (response.result_case() != ConformanceResponse::kJsonPayload) { |
| 586 | ReportFailure(effective_test_name, level, request, response, |
| 587 | "Expected JSON payload but got type %d.", |
| 588 | response.result_case()); |
| 589 | return; |
| 590 | } |
| 591 | Json::Reader reader; |
| 592 | Json::Value value; |
| 593 | if (!reader.parse(response.json_payload(), value)) { |
| 594 | ReportFailure(effective_test_name, level, request, response, |
| 595 | "JSON payload cannot be parsed as valid JSON: %s", |
| 596 | reader.getFormattedErrorMessages().c_str()); |
| 597 | return; |
| 598 | } |
| 599 | if (!validator(value)) { |
| 600 | ReportFailure(effective_test_name, level, request, response, |
| 601 | "JSON payload validation failed."); |
| 602 | return; |
| 603 | } |
| 604 | ReportSuccess(effective_test_name); |
| 605 | } |
| 606 | |
Paul Yang | cecba29 | 2018-12-14 16:05:03 -0800 | [diff] [blame] | 607 | void BinaryAndJsonConformanceSuite::ExpectParseFailureForJson( |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 608 | const string& test_name, ConformanceLevel level, const string& input_json) { |
| 609 | TestAllTypesProto3 prototype; |
| 610 | // We don't expect output, but if the program erroneously accepts the protobuf |
| 611 | // we let it send its response as this. We must not leave it unspecified. |
| 612 | ConformanceRequestSetting setting( |
| 613 | level, conformance::JSON, conformance::JSON, |
| 614 | conformance::JSON_TEST, |
| 615 | prototype, test_name, input_json); |
| 616 | const ConformanceRequest& request = setting.GetRequest(); |
| 617 | ConformanceResponse response; |
Rafi Kamal | 58d4420 | 2019-11-11 17:06:56 -0800 | [diff] [blame] | 618 | string effective_test_name = StrCat( |
| 619 | setting.ConformanceLevelToString(level), ".Proto3.JsonInput.", test_name); |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 620 | |
| 621 | RunTest(effective_test_name, request, &response); |
| 622 | if (response.result_case() == ConformanceResponse::kParseError) { |
| 623 | ReportSuccess(effective_test_name); |
| 624 | } else if (response.result_case() == ConformanceResponse::kSkipped) { |
| 625 | ReportSkip(effective_test_name, request, response); |
| 626 | } else { |
| 627 | ReportFailure(effective_test_name, level, request, response, |
| 628 | "Should have failed to parse, but didn't."); |
| 629 | } |
| 630 | } |
| 631 | |
Paul Yang | cecba29 | 2018-12-14 16:05:03 -0800 | [diff] [blame] | 632 | void BinaryAndJsonConformanceSuite::ExpectSerializeFailureForJson( |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 633 | const string& test_name, ConformanceLevel level, const string& text_format) { |
| 634 | TestAllTypesProto3 payload_message; |
Rafi Kamal | 58d4420 | 2019-11-11 17:06:56 -0800 | [diff] [blame] | 635 | GOOGLE_CHECK(TextFormat::ParseFromString(text_format, &payload_message)) |
| 636 | << "Failed to parse: " << text_format; |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 637 | |
| 638 | TestAllTypesProto3 prototype; |
| 639 | ConformanceRequestSetting setting( |
| 640 | level, conformance::PROTOBUF, conformance::JSON, |
| 641 | conformance::JSON_TEST, |
| 642 | prototype, test_name, payload_message.SerializeAsString()); |
| 643 | const ConformanceRequest& request = setting.GetRequest(); |
| 644 | ConformanceResponse response; |
Rafi Kamal | 58d4420 | 2019-11-11 17:06:56 -0800 | [diff] [blame] | 645 | string effective_test_name = StrCat( |
| 646 | setting.ConformanceLevelToString(level), ".", test_name, ".JsonOutput"); |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 647 | |
| 648 | RunTest(effective_test_name, request, &response); |
| 649 | if (response.result_case() == ConformanceResponse::kSerializeError) { |
| 650 | ReportSuccess(effective_test_name); |
| 651 | } else if (response.result_case() == ConformanceResponse::kSkipped) { |
| 652 | ReportSkip(effective_test_name, request, response); |
| 653 | } else { |
| 654 | ReportFailure(effective_test_name, level, request, response, |
| 655 | "Should have failed to serialize, but didn't."); |
| 656 | } |
| 657 | } |
| 658 | |
Paul Yang | cecba29 | 2018-12-14 16:05:03 -0800 | [diff] [blame] | 659 | void BinaryAndJsonConformanceSuite::TestPrematureEOFForType( |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 660 | FieldDescriptor::Type type) { |
| 661 | // Incomplete values for each wire type. |
| 662 | static const string incompletes[6] = { |
| 663 | string("\x80"), // VARINT |
| 664 | string("abcdefg"), // 64BIT |
| 665 | string("\x80"), // DELIMITED (partial length) |
| 666 | string(), // START_GROUP (no value required) |
| 667 | string(), // END_GROUP (no value required) |
| 668 | string("abc") // 32BIT |
| 669 | }; |
| 670 | |
| 671 | const FieldDescriptor* field = GetFieldForType(type, false, true); |
| 672 | const FieldDescriptor* rep_field = GetFieldForType(type, true, true); |
| 673 | WireFormatLite::WireType wire_type = WireFormatLite::WireTypeForFieldType( |
| 674 | static_cast<WireFormatLite::FieldType>(type)); |
| 675 | const string& incomplete = incompletes[wire_type]; |
| 676 | const string type_name = |
| 677 | UpperCase(string(".") + FieldDescriptor::TypeName(type)); |
| 678 | |
| 679 | ExpectParseFailureForProto( |
| 680 | tag(field->number(), wire_type), |
| 681 | "PrematureEofBeforeKnownNonRepeatedValue" + type_name, REQUIRED); |
| 682 | |
| 683 | ExpectParseFailureForProto( |
| 684 | tag(rep_field->number(), wire_type), |
| 685 | "PrematureEofBeforeKnownRepeatedValue" + type_name, REQUIRED); |
| 686 | |
| 687 | ExpectParseFailureForProto( |
| 688 | tag(UNKNOWN_FIELD, wire_type), |
| 689 | "PrematureEofBeforeUnknownValue" + type_name, REQUIRED); |
| 690 | |
| 691 | ExpectParseFailureForProto( |
| 692 | cat( tag(field->number(), wire_type), incomplete ), |
| 693 | "PrematureEofInsideKnownNonRepeatedValue" + type_name, REQUIRED); |
| 694 | |
| 695 | ExpectParseFailureForProto( |
| 696 | cat( tag(rep_field->number(), wire_type), incomplete ), |
| 697 | "PrematureEofInsideKnownRepeatedValue" + type_name, REQUIRED); |
| 698 | |
| 699 | ExpectParseFailureForProto( |
| 700 | cat( tag(UNKNOWN_FIELD, wire_type), incomplete ), |
| 701 | "PrematureEofInsideUnknownValue" + type_name, REQUIRED); |
| 702 | |
| 703 | if (wire_type == WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { |
| 704 | ExpectParseFailureForProto( |
| 705 | cat( tag(field->number(), wire_type), varint(1) ), |
| 706 | "PrematureEofInDelimitedDataForKnownNonRepeatedValue" + type_name, |
| 707 | REQUIRED); |
| 708 | |
| 709 | ExpectParseFailureForProto( |
| 710 | cat( tag(rep_field->number(), wire_type), varint(1) ), |
| 711 | "PrematureEofInDelimitedDataForKnownRepeatedValue" + type_name, |
| 712 | REQUIRED); |
| 713 | |
| 714 | // EOF in the middle of delimited data for unknown value. |
| 715 | ExpectParseFailureForProto( |
| 716 | cat( tag(UNKNOWN_FIELD, wire_type), varint(1) ), |
| 717 | "PrematureEofInDelimitedDataForUnknownValue" + type_name, REQUIRED); |
| 718 | |
| 719 | if (type == FieldDescriptor::TYPE_MESSAGE) { |
| 720 | // Submessage ends in the middle of a value. |
| 721 | string incomplete_submsg = |
| 722 | cat( tag(WireFormatLite::TYPE_INT32, WireFormatLite::WIRETYPE_VARINT), |
| 723 | incompletes[WireFormatLite::WIRETYPE_VARINT] ); |
| 724 | ExpectHardParseFailureForProto( |
| 725 | cat( tag(field->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED), |
| 726 | varint(incomplete_submsg.size()), |
| 727 | incomplete_submsg ), |
| 728 | "PrematureEofInSubmessageValue" + type_name, REQUIRED); |
| 729 | } |
| 730 | } else if (type != FieldDescriptor::TYPE_GROUP) { |
| 731 | // Non-delimited, non-group: eligible for packing. |
| 732 | |
| 733 | // Packed region ends in the middle of a value. |
| 734 | ExpectHardParseFailureForProto( |
| 735 | cat(tag(rep_field->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED), |
| 736 | varint(incomplete.size()), incomplete), |
| 737 | "PrematureEofInPackedFieldValue" + type_name, REQUIRED); |
| 738 | |
| 739 | // EOF in the middle of packed region. |
| 740 | ExpectParseFailureForProto( |
| 741 | cat(tag(rep_field->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED), |
| 742 | varint(1)), |
| 743 | "PrematureEofInPackedField" + type_name, REQUIRED); |
| 744 | } |
| 745 | } |
| 746 | |
Paul Yang | cecba29 | 2018-12-14 16:05:03 -0800 | [diff] [blame] | 747 | void BinaryAndJsonConformanceSuite::TestValidDataForType( |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 748 | FieldDescriptor::Type type, |
| 749 | std::vector<std::pair<std::string, std::string>> values) { |
| 750 | for (int is_proto3 = 0; is_proto3 < 2; is_proto3++) { |
| 751 | const string type_name = |
| 752 | UpperCase(string(".") + FieldDescriptor::TypeName(type)); |
| 753 | WireFormatLite::WireType wire_type = WireFormatLite::WireTypeForFieldType( |
| 754 | static_cast<WireFormatLite::FieldType>(type)); |
| 755 | const FieldDescriptor* field = GetFieldForType(type, false, is_proto3); |
| 756 | const FieldDescriptor* rep_field = GetFieldForType(type, true, is_proto3); |
| 757 | |
Paul Yang | a9bb656 | 2019-07-26 10:05:14 -0700 | [diff] [blame] | 758 | // Test singular data for singular fields. |
Paul Yang | 2849a79 | 2019-07-24 12:26:40 -0700 | [diff] [blame] | 759 | for (size_t i = 0; i < values.size(); i++) { |
Rafi Kamal | 4f02f05 | 2019-08-22 16:14:22 -0700 | [diff] [blame] | 760 | string proto = cat(tag(field->number(), wire_type), values[i].first); |
Paul Yang | 6c9d7ec | 2019-08-23 12:20:19 -0700 | [diff] [blame] | 761 | // In proto3, default primitive fields should not be encoded. |
Paul Yang | a9bb656 | 2019-07-26 10:05:14 -0700 | [diff] [blame] | 762 | string expected_proto = |
Rafi Kamal | 6c92f9d | 2019-10-11 12:05:46 -0700 | [diff] [blame] | 763 | is_proto3 && IsProto3Default(field->type(), values[i].second) |
| 764 | ? "" |
| 765 | : cat(tag(field->number(), wire_type), values[i].second); |
Paul Yang | a9bb656 | 2019-07-26 10:05:14 -0700 | [diff] [blame] | 766 | std::unique_ptr<Message> test_message = NewTestMessage(is_proto3); |
| 767 | test_message->MergeFromString(expected_proto); |
| 768 | string text = test_message->DebugString(); |
| 769 | |
Rafi Kamal | 58d4420 | 2019-11-11 17:06:56 -0800 | [diff] [blame] | 770 | RunValidProtobufTest( |
| 771 | StrCat("ValidDataScalar", type_name, "[", i, "]"), REQUIRED, |
| 772 | proto, text, is_proto3); |
Paul Yang | 6c9d7ec | 2019-08-23 12:20:19 -0700 | [diff] [blame] | 773 | RunValidBinaryProtobufTest( |
Rafi Kamal | 58d4420 | 2019-11-11 17:06:56 -0800 | [diff] [blame] | 774 | StrCat("ValidDataScalarBinary", type_name, "[", i, "]"), |
| 775 | RECOMMENDED, proto, expected_proto, is_proto3); |
Paul Yang | 2849a79 | 2019-07-24 12:26:40 -0700 | [diff] [blame] | 776 | } |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 777 | |
Paul Yang | a9bb656 | 2019-07-26 10:05:14 -0700 | [diff] [blame] | 778 | // Test repeated data for singular fields. |
Paul Yang | 2849a79 | 2019-07-24 12:26:40 -0700 | [diff] [blame] | 779 | // For scalar message fields, repeated values are merged, which is tested |
| 780 | // separately. |
| 781 | if (type != FieldDescriptor::TYPE_MESSAGE) { |
Paul Yang | a9bb656 | 2019-07-26 10:05:14 -0700 | [diff] [blame] | 782 | string proto; |
| 783 | for (size_t i = 0; i < values.size(); i++) { |
| 784 | proto += cat(tag(field->number(), wire_type), values[i].first); |
| 785 | } |
| 786 | string expected_proto = |
| 787 | cat(tag(field->number(), wire_type), values.back().second); |
| 788 | std::unique_ptr<Message> test_message = NewTestMessage(is_proto3); |
| 789 | test_message->MergeFromString(expected_proto); |
| 790 | string text = test_message->DebugString(); |
| 791 | |
Paul Yang | 2849a79 | 2019-07-24 12:26:40 -0700 | [diff] [blame] | 792 | RunValidProtobufTest("RepeatedScalarSelectsLast" + type_name, REQUIRED, |
| 793 | proto, text, is_proto3); |
| 794 | } |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 795 | |
Paul Yang | a9bb656 | 2019-07-26 10:05:14 -0700 | [diff] [blame] | 796 | // Test repeated fields. |
| 797 | if (FieldDescriptor::IsTypePackable(type)) { |
Paul Yang | 0c4b607 | 2019-08-02 14:35:44 -0700 | [diff] [blame] | 798 | const FieldDescriptor* packed_field = |
Adam Cozzette | 9faf5a7 | 2021-08-25 13:55:16 -0700 | [diff] [blame] | 799 | GetFieldForType(type, true, is_proto3, Packed::kTrue); |
Paul Yang | 0c4b607 | 2019-08-02 14:35:44 -0700 | [diff] [blame] | 800 | const FieldDescriptor* unpacked_field = |
Adam Cozzette | 9faf5a7 | 2021-08-25 13:55:16 -0700 | [diff] [blame] | 801 | GetFieldForType(type, true, is_proto3, Packed::kFalse); |
Paul Yang | 0c4b607 | 2019-08-02 14:35:44 -0700 | [diff] [blame] | 802 | |
| 803 | string default_proto_packed; |
| 804 | string default_proto_unpacked; |
| 805 | string default_proto_packed_expected; |
| 806 | string default_proto_unpacked_expected; |
| 807 | string packed_proto_packed; |
| 808 | string packed_proto_unpacked; |
Paul Yang | a9bb656 | 2019-07-26 10:05:14 -0700 | [diff] [blame] | 809 | string packed_proto_expected; |
Paul Yang | 0c4b607 | 2019-08-02 14:35:44 -0700 | [diff] [blame] | 810 | string unpacked_proto_packed; |
| 811 | string unpacked_proto_unpacked; |
Paul Yang | a9bb656 | 2019-07-26 10:05:14 -0700 | [diff] [blame] | 812 | string unpacked_proto_expected; |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 813 | |
Paul Yang | a9bb656 | 2019-07-26 10:05:14 -0700 | [diff] [blame] | 814 | for (size_t i = 0; i < values.size(); i++) { |
Paul Yang | 0c4b607 | 2019-08-02 14:35:44 -0700 | [diff] [blame] | 815 | default_proto_unpacked += |
Paul Yang | a9bb656 | 2019-07-26 10:05:14 -0700 | [diff] [blame] | 816 | cat(tag(rep_field->number(), wire_type), values[i].first); |
Paul Yang | 0c4b607 | 2019-08-02 14:35:44 -0700 | [diff] [blame] | 817 | default_proto_unpacked_expected += |
Paul Yang | a9bb656 | 2019-07-26 10:05:14 -0700 | [diff] [blame] | 818 | cat(tag(rep_field->number(), wire_type), values[i].second); |
Paul Yang | 0c4b607 | 2019-08-02 14:35:44 -0700 | [diff] [blame] | 819 | default_proto_packed += values[i].first; |
| 820 | default_proto_packed_expected += values[i].second; |
| 821 | packed_proto_unpacked += |
| 822 | cat(tag(packed_field->number(), wire_type), values[i].first); |
| 823 | packed_proto_packed += values[i].first; |
Paul Yang | a9bb656 | 2019-07-26 10:05:14 -0700 | [diff] [blame] | 824 | packed_proto_expected += values[i].second; |
Paul Yang | 0c4b607 | 2019-08-02 14:35:44 -0700 | [diff] [blame] | 825 | unpacked_proto_unpacked += |
| 826 | cat(tag(unpacked_field->number(), wire_type), values[i].first); |
| 827 | unpacked_proto_packed += values[i].first; |
| 828 | unpacked_proto_expected += |
| 829 | cat(tag(unpacked_field->number(), wire_type), values[i].second); |
Paul Yang | a9bb656 | 2019-07-26 10:05:14 -0700 | [diff] [blame] | 830 | } |
Rafi Kamal | 4f02f05 | 2019-08-22 16:14:22 -0700 | [diff] [blame] | 831 | default_proto_packed = cat( |
| 832 | tag(rep_field->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED), |
| 833 | delim(default_proto_packed)); |
| 834 | default_proto_packed_expected = cat( |
| 835 | tag(rep_field->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED), |
| 836 | delim(default_proto_packed_expected)); |
| 837 | packed_proto_packed = cat(tag(packed_field->number(), |
| 838 | WireFormatLite::WIRETYPE_LENGTH_DELIMITED), |
| 839 | delim(packed_proto_packed)); |
Paul Yang | 0c4b607 | 2019-08-02 14:35:44 -0700 | [diff] [blame] | 840 | packed_proto_expected = |
| 841 | cat(tag(packed_field->number(), |
| 842 | WireFormatLite::WIRETYPE_LENGTH_DELIMITED), |
Paul Yang | a9bb656 | 2019-07-26 10:05:14 -0700 | [diff] [blame] | 843 | delim(packed_proto_expected)); |
Paul Yang | 0c4b607 | 2019-08-02 14:35:44 -0700 | [diff] [blame] | 844 | unpacked_proto_packed = |
| 845 | cat(tag(unpacked_field->number(), |
| 846 | WireFormatLite::WIRETYPE_LENGTH_DELIMITED), |
| 847 | delim(unpacked_proto_packed)); |
| 848 | |
Paul Yang | a9bb656 | 2019-07-26 10:05:14 -0700 | [diff] [blame] | 849 | std::unique_ptr<Message> test_message = NewTestMessage(is_proto3); |
Paul Yang | 0c4b607 | 2019-08-02 14:35:44 -0700 | [diff] [blame] | 850 | test_message->MergeFromString(default_proto_packed_expected); |
Paul Yang | a9bb656 | 2019-07-26 10:05:14 -0700 | [diff] [blame] | 851 | string text = test_message->DebugString(); |
| 852 | |
| 853 | // Ensures both packed and unpacked data can be parsed. |
| 854 | RunValidProtobufTest( |
Rafi Kamal | 58d4420 | 2019-11-11 17:06:56 -0800 | [diff] [blame] | 855 | StrCat("ValidDataRepeated", type_name, ".UnpackedInput"), |
| 856 | REQUIRED, default_proto_unpacked, text, is_proto3); |
Paul Yang | a9bb656 | 2019-07-26 10:05:14 -0700 | [diff] [blame] | 857 | RunValidProtobufTest( |
Rafi Kamal | 58d4420 | 2019-11-11 17:06:56 -0800 | [diff] [blame] | 858 | StrCat("ValidDataRepeated", type_name, ".PackedInput"), |
| 859 | REQUIRED, default_proto_packed, text, is_proto3); |
Paul Yang | a9bb656 | 2019-07-26 10:05:14 -0700 | [diff] [blame] | 860 | |
| 861 | // proto2 should encode as unpacked by default and proto3 should encode as |
| 862 | // packed by default. |
Rafi Kamal | 4f02f05 | 2019-08-22 16:14:22 -0700 | [diff] [blame] | 863 | string expected_proto = rep_field->is_packed() |
| 864 | ? default_proto_packed_expected |
| 865 | : default_proto_unpacked_expected; |
| 866 | RunValidBinaryProtobufTest(StrCat("ValidDataRepeated", type_name, |
Rafi Kamal | 58d4420 | 2019-11-11 17:06:56 -0800 | [diff] [blame] | 867 | ".UnpackedInput.DefaultOutput"), |
Rafi Kamal | 4f02f05 | 2019-08-22 16:14:22 -0700 | [diff] [blame] | 868 | RECOMMENDED, default_proto_unpacked, |
| 869 | expected_proto, is_proto3); |
Rafi Kamal | 4f02f05 | 2019-08-22 16:14:22 -0700 | [diff] [blame] | 870 | RunValidBinaryProtobufTest(StrCat("ValidDataRepeated", type_name, |
Rafi Kamal | 58d4420 | 2019-11-11 17:06:56 -0800 | [diff] [blame] | 871 | ".PackedInput.DefaultOutput"), |
| 872 | RECOMMENDED, default_proto_packed, |
| 873 | expected_proto, is_proto3); |
| 874 | RunValidBinaryProtobufTest(StrCat("ValidDataRepeated", type_name, |
| 875 | ".UnpackedInput.PackedOutput"), |
| 876 | RECOMMENDED, packed_proto_unpacked, |
| 877 | packed_proto_expected, is_proto3); |
| 878 | RunValidBinaryProtobufTest(StrCat("ValidDataRepeated", type_name, |
| 879 | ".PackedInput.PackedOutput"), |
| 880 | RECOMMENDED, packed_proto_packed, |
| 881 | packed_proto_expected, is_proto3); |
| 882 | RunValidBinaryProtobufTest(StrCat("ValidDataRepeated", type_name, |
| 883 | ".UnpackedInput.UnpackedOutput"), |
Rafi Kamal | 4f02f05 | 2019-08-22 16:14:22 -0700 | [diff] [blame] | 884 | RECOMMENDED, unpacked_proto_unpacked, |
| 885 | unpacked_proto_expected, is_proto3); |
Rafi Kamal | 58d4420 | 2019-11-11 17:06:56 -0800 | [diff] [blame] | 886 | RunValidBinaryProtobufTest(StrCat("ValidDataRepeated", type_name, |
| 887 | ".PackedInput.UnpackedOutput"), |
| 888 | RECOMMENDED, unpacked_proto_packed, |
| 889 | unpacked_proto_expected, is_proto3); |
Paul Yang | a9bb656 | 2019-07-26 10:05:14 -0700 | [diff] [blame] | 890 | } else { |
| 891 | string proto; |
| 892 | string expected_proto; |
| 893 | for (size_t i = 0; i < values.size(); i++) { |
| 894 | proto += cat(tag(rep_field->number(), wire_type), values[i].first); |
| 895 | expected_proto += |
| 896 | cat(tag(rep_field->number(), wire_type), values[i].second); |
| 897 | } |
| 898 | std::unique_ptr<Message> test_message = NewTestMessage(is_proto3); |
| 899 | test_message->MergeFromString(expected_proto); |
| 900 | string text = test_message->DebugString(); |
| 901 | |
Rafi Kamal | 58d4420 | 2019-11-11 17:06:56 -0800 | [diff] [blame] | 902 | RunValidProtobufTest(StrCat("ValidDataRepeated", type_name), |
| 903 | REQUIRED, proto, text, is_proto3); |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 904 | } |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 905 | } |
| 906 | } |
| 907 | |
Paul Yang | 2849a79 | 2019-07-24 12:26:40 -0700 | [diff] [blame] | 908 | void BinaryAndJsonConformanceSuite::TestValidDataForRepeatedScalarMessage() { |
| 909 | std::vector<std::string> values = { |
Rafi Kamal | 4f02f05 | 2019-08-22 16:14:22 -0700 | [diff] [blame] | 910 | delim(cat( |
| 911 | tag(2, WireFormatLite::WIRETYPE_LENGTH_DELIMITED), |
| 912 | delim(cat(tag(1, WireFormatLite::WIRETYPE_VARINT), varint(1234), |
Paul Yang | 2849a79 | 2019-07-24 12:26:40 -0700 | [diff] [blame] | 913 | tag(2, WireFormatLite::WIRETYPE_VARINT), varint(1234), |
Rafi Kamal | 4f02f05 | 2019-08-22 16:14:22 -0700 | [diff] [blame] | 914 | tag(31, WireFormatLite::WIRETYPE_VARINT), varint(1234))))), |
| 915 | delim(cat( |
| 916 | tag(2, WireFormatLite::WIRETYPE_LENGTH_DELIMITED), |
| 917 | delim(cat(tag(1, WireFormatLite::WIRETYPE_VARINT), varint(4321), |
Paul Yang | 2849a79 | 2019-07-24 12:26:40 -0700 | [diff] [blame] | 918 | tag(3, WireFormatLite::WIRETYPE_VARINT), varint(4321), |
Rafi Kamal | 4f02f05 | 2019-08-22 16:14:22 -0700 | [diff] [blame] | 919 | tag(31, WireFormatLite::WIRETYPE_VARINT), varint(4321))))), |
Paul Yang | 2849a79 | 2019-07-24 12:26:40 -0700 | [diff] [blame] | 920 | }; |
| 921 | |
| 922 | const std::string expected = |
| 923 | R"({ |
| 924 | corecursive: { |
| 925 | optional_int32: 4321, |
| 926 | optional_int64: 1234, |
| 927 | optional_uint32: 4321, |
| 928 | repeated_int32: [1234, 4321], |
| 929 | } |
| 930 | })"; |
| 931 | |
| 932 | for (int is_proto3 = 0; is_proto3 < 2; is_proto3++) { |
| 933 | string proto; |
| 934 | const FieldDescriptor* field = |
| 935 | GetFieldForType(FieldDescriptor::TYPE_MESSAGE, false, is_proto3); |
| 936 | for (size_t i = 0; i < values.size(); i++) { |
| 937 | proto += |
| 938 | cat(tag(field->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED), |
| 939 | values[i]); |
| 940 | } |
| 941 | |
Rafi Kamal | 4f02f05 | 2019-08-22 16:14:22 -0700 | [diff] [blame] | 942 | RunValidProtobufTest("RepeatedScalarMessageMerge", REQUIRED, proto, |
| 943 | field->name() + ": " + expected, is_proto3); |
Paul Yang | 2849a79 | 2019-07-24 12:26:40 -0700 | [diff] [blame] | 944 | } |
| 945 | } |
| 946 | |
Paul Yang | ce942bc | 2019-09-03 10:47:32 -0700 | [diff] [blame] | 947 | void BinaryAndJsonConformanceSuite::TestValidDataForMapType( |
Rafi Kamal | 6c92f9d | 2019-10-11 12:05:46 -0700 | [diff] [blame] | 948 | FieldDescriptor::Type key_type, FieldDescriptor::Type value_type) { |
Paul Yang | ce942bc | 2019-09-03 10:47:32 -0700 | [diff] [blame] | 949 | const string key_type_name = |
| 950 | UpperCase(string(".") + FieldDescriptor::TypeName(key_type)); |
| 951 | const string value_type_name = |
| 952 | UpperCase(string(".") + FieldDescriptor::TypeName(value_type)); |
Rafi Kamal | 6c92f9d | 2019-10-11 12:05:46 -0700 | [diff] [blame] | 953 | WireFormatLite::WireType key_wire_type = WireFormatLite::WireTypeForFieldType( |
| 954 | static_cast<WireFormatLite::FieldType>(key_type)); |
Paul Yang | ce942bc | 2019-09-03 10:47:32 -0700 | [diff] [blame] | 955 | WireFormatLite::WireType value_wire_type = |
| 956 | WireFormatLite::WireTypeForFieldType( |
| 957 | static_cast<WireFormatLite::FieldType>(value_type)); |
| 958 | |
Rafi Kamal | 6c92f9d | 2019-10-11 12:05:46 -0700 | [diff] [blame] | 959 | string key1_data = cat(tag(1, key_wire_type), GetDefaultValue(key_type)); |
Paul Yang | ce942bc | 2019-09-03 10:47:32 -0700 | [diff] [blame] | 960 | string value1_data = |
| 961 | cat(tag(2, value_wire_type), GetDefaultValue(value_type)); |
Rafi Kamal | 6c92f9d | 2019-10-11 12:05:46 -0700 | [diff] [blame] | 962 | string key2_data = cat(tag(1, key_wire_type), GetNonDefaultValue(key_type)); |
Paul Yang | ce942bc | 2019-09-03 10:47:32 -0700 | [diff] [blame] | 963 | string value2_data = |
| 964 | cat(tag(2, value_wire_type), GetNonDefaultValue(value_type)); |
| 965 | |
| 966 | for (int is_proto3 = 0; is_proto3 < 2; is_proto3++) { |
| 967 | const FieldDescriptor* field = |
| 968 | GetFieldForMapType(key_type, value_type, is_proto3); |
| 969 | |
| 970 | { |
| 971 | // Tests map with default key and value. |
Rafi Kamal | 6c92f9d | 2019-10-11 12:05:46 -0700 | [diff] [blame] | 972 | string proto = |
| 973 | cat(tag(field->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED), |
| 974 | delim(cat(key1_data, value1_data))); |
Paul Yang | ce942bc | 2019-09-03 10:47:32 -0700 | [diff] [blame] | 975 | std::unique_ptr<Message> test_message = NewTestMessage(is_proto3); |
| 976 | test_message->MergeFromString(proto); |
| 977 | string text = test_message->DebugString(); |
Rafi Kamal | 58d4420 | 2019-11-11 17:06:56 -0800 | [diff] [blame] | 978 | RunValidProtobufTest(StrCat("ValidDataMap", key_type_name, |
| 979 | value_type_name, ".Default"), |
| 980 | REQUIRED, proto, text, is_proto3); |
Paul Yang | ce942bc | 2019-09-03 10:47:32 -0700 | [diff] [blame] | 981 | } |
| 982 | |
| 983 | { |
| 984 | // Tests map with missing default key and value. |
Rafi Kamal | 6c92f9d | 2019-10-11 12:05:46 -0700 | [diff] [blame] | 985 | string proto = |
| 986 | cat(tag(field->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED), |
| 987 | delim("")); |
Paul Yang | ce942bc | 2019-09-03 10:47:32 -0700 | [diff] [blame] | 988 | std::unique_ptr<Message> test_message = NewTestMessage(is_proto3); |
| 989 | test_message->MergeFromString(proto); |
| 990 | string text = test_message->DebugString(); |
Rafi Kamal | 6c92f9d | 2019-10-11 12:05:46 -0700 | [diff] [blame] | 991 | RunValidProtobufTest(StrCat("ValidDataMap", key_type_name, |
Rafi Kamal | 58d4420 | 2019-11-11 17:06:56 -0800 | [diff] [blame] | 992 | value_type_name, ".MissingDefault"), |
Rafi Kamal | 6c92f9d | 2019-10-11 12:05:46 -0700 | [diff] [blame] | 993 | REQUIRED, proto, text, is_proto3); |
Paul Yang | ce942bc | 2019-09-03 10:47:32 -0700 | [diff] [blame] | 994 | } |
| 995 | |
| 996 | { |
| 997 | // Tests map with non-default key and value. |
Rafi Kamal | 6c92f9d | 2019-10-11 12:05:46 -0700 | [diff] [blame] | 998 | string proto = |
| 999 | cat(tag(field->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED), |
| 1000 | delim(cat(key2_data, value2_data))); |
Paul Yang | ce942bc | 2019-09-03 10:47:32 -0700 | [diff] [blame] | 1001 | std::unique_ptr<Message> test_message = NewTestMessage(is_proto3); |
| 1002 | test_message->MergeFromString(proto); |
| 1003 | string text = test_message->DebugString(); |
Rafi Kamal | 58d4420 | 2019-11-11 17:06:56 -0800 | [diff] [blame] | 1004 | RunValidProtobufTest(StrCat("ValidDataMap", key_type_name, |
| 1005 | value_type_name, ".NonDefault"), |
| 1006 | REQUIRED, proto, text, is_proto3); |
Paul Yang | ce942bc | 2019-09-03 10:47:32 -0700 | [diff] [blame] | 1007 | } |
| 1008 | |
| 1009 | { |
| 1010 | // Tests map with unordered key and value. |
Rafi Kamal | 6c92f9d | 2019-10-11 12:05:46 -0700 | [diff] [blame] | 1011 | string proto = |
| 1012 | cat(tag(field->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED), |
| 1013 | delim(cat(value2_data, key2_data))); |
Paul Yang | ce942bc | 2019-09-03 10:47:32 -0700 | [diff] [blame] | 1014 | std::unique_ptr<Message> test_message = NewTestMessage(is_proto3); |
| 1015 | test_message->MergeFromString(proto); |
| 1016 | string text = test_message->DebugString(); |
Rafi Kamal | 58d4420 | 2019-11-11 17:06:56 -0800 | [diff] [blame] | 1017 | RunValidProtobufTest(StrCat("ValidDataMap", key_type_name, |
| 1018 | value_type_name, ".Unordered"), |
| 1019 | REQUIRED, proto, text, is_proto3); |
Paul Yang | ce942bc | 2019-09-03 10:47:32 -0700 | [diff] [blame] | 1020 | } |
| 1021 | |
| 1022 | { |
| 1023 | // Tests map with duplicate key. |
Rafi Kamal | 6c92f9d | 2019-10-11 12:05:46 -0700 | [diff] [blame] | 1024 | string proto1 = |
| 1025 | cat(tag(field->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED), |
| 1026 | delim(cat(key2_data, value1_data))); |
| 1027 | string proto2 = |
| 1028 | cat(tag(field->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED), |
| 1029 | delim(cat(key2_data, value2_data))); |
Paul Yang | ce942bc | 2019-09-03 10:47:32 -0700 | [diff] [blame] | 1030 | string proto = cat(proto1, proto2); |
| 1031 | std::unique_ptr<Message> test_message = NewTestMessage(is_proto3); |
| 1032 | test_message->MergeFromString(proto2); |
| 1033 | string text = test_message->DebugString(); |
Rafi Kamal | 6c92f9d | 2019-10-11 12:05:46 -0700 | [diff] [blame] | 1034 | RunValidProtobufTest(StrCat("ValidDataMap", key_type_name, |
Rafi Kamal | 58d4420 | 2019-11-11 17:06:56 -0800 | [diff] [blame] | 1035 | value_type_name, ".DuplicateKey"), |
Rafi Kamal | 6c92f9d | 2019-10-11 12:05:46 -0700 | [diff] [blame] | 1036 | REQUIRED, proto, text, is_proto3); |
Paul Yang | ce942bc | 2019-09-03 10:47:32 -0700 | [diff] [blame] | 1037 | } |
| 1038 | |
| 1039 | { |
| 1040 | // Tests map with duplicate key in map entry. |
Rafi Kamal | 6c92f9d | 2019-10-11 12:05:46 -0700 | [diff] [blame] | 1041 | string proto = |
| 1042 | cat(tag(field->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED), |
| 1043 | delim(cat(key1_data, key2_data, value2_data))); |
Paul Yang | ce942bc | 2019-09-03 10:47:32 -0700 | [diff] [blame] | 1044 | std::unique_ptr<Message> test_message = NewTestMessage(is_proto3); |
| 1045 | test_message->MergeFromString(proto); |
| 1046 | string text = test_message->DebugString(); |
Rafi Kamal | 58d4420 | 2019-11-11 17:06:56 -0800 | [diff] [blame] | 1047 | RunValidProtobufTest( |
| 1048 | StrCat("ValidDataMap", key_type_name, value_type_name, |
| 1049 | ".DuplicateKeyInMapEntry"), |
| 1050 | REQUIRED, proto, text, is_proto3); |
Paul Yang | ce942bc | 2019-09-03 10:47:32 -0700 | [diff] [blame] | 1051 | } |
| 1052 | |
| 1053 | { |
| 1054 | // Tests map with duplicate value in map entry. |
Rafi Kamal | 6c92f9d | 2019-10-11 12:05:46 -0700 | [diff] [blame] | 1055 | string proto = |
| 1056 | cat(tag(field->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED), |
| 1057 | delim(cat(key2_data, value1_data, value2_data))); |
Paul Yang | ce942bc | 2019-09-03 10:47:32 -0700 | [diff] [blame] | 1058 | std::unique_ptr<Message> test_message = NewTestMessage(is_proto3); |
| 1059 | test_message->MergeFromString(proto); |
| 1060 | string text = test_message->DebugString(); |
Rafi Kamal | 58d4420 | 2019-11-11 17:06:56 -0800 | [diff] [blame] | 1061 | RunValidProtobufTest( |
| 1062 | StrCat("ValidDataMap", key_type_name, value_type_name, |
| 1063 | ".DuplicateValueInMapEntry"), |
| 1064 | REQUIRED, proto, text, is_proto3); |
Paul Yang | ce942bc | 2019-09-03 10:47:32 -0700 | [diff] [blame] | 1065 | } |
| 1066 | } |
| 1067 | } |
| 1068 | |
| 1069 | void BinaryAndJsonConformanceSuite::TestOverwriteMessageValueMap() { |
| 1070 | string key_data = |
| 1071 | cat(tag(1, WireFormatLite::WIRETYPE_LENGTH_DELIMITED), delim("")); |
| 1072 | string field1_data = cat(tag(1, WireFormatLite::WIRETYPE_VARINT), varint(1)); |
| 1073 | string field2_data = cat(tag(2, WireFormatLite::WIRETYPE_VARINT), varint(1)); |
Rafi Kamal | 6c92f9d | 2019-10-11 12:05:46 -0700 | [diff] [blame] | 1074 | string field31_data = |
| 1075 | cat(tag(31, WireFormatLite::WIRETYPE_VARINT), varint(1)); |
Paul Yang | ce942bc | 2019-09-03 10:47:32 -0700 | [diff] [blame] | 1076 | string submsg1_data = delim(cat(field1_data, field31_data)); |
| 1077 | string submsg2_data = delim(cat(field2_data, field31_data)); |
| 1078 | string value1_data = |
| 1079 | cat(tag(2, WireFormatLite::WIRETYPE_LENGTH_DELIMITED), |
| 1080 | delim(cat(tag(2, WireFormatLite::WIRETYPE_LENGTH_DELIMITED), |
| 1081 | submsg1_data))); |
| 1082 | string value2_data = |
| 1083 | cat(tag(2, WireFormatLite::WIRETYPE_LENGTH_DELIMITED), |
| 1084 | delim(cat(tag(2, WireFormatLite::WIRETYPE_LENGTH_DELIMITED), |
| 1085 | submsg2_data))); |
| 1086 | |
| 1087 | for (int is_proto3 = 0; is_proto3 < 2; is_proto3++) { |
Rafi Kamal | 6c92f9d | 2019-10-11 12:05:46 -0700 | [diff] [blame] | 1088 | const FieldDescriptor* field = GetFieldForMapType( |
| 1089 | FieldDescriptor::TYPE_STRING, FieldDescriptor::TYPE_MESSAGE, is_proto3); |
Paul Yang | ce942bc | 2019-09-03 10:47:32 -0700 | [diff] [blame] | 1090 | |
Rafi Kamal | 6c92f9d | 2019-10-11 12:05:46 -0700 | [diff] [blame] | 1091 | string proto1 = |
| 1092 | cat(tag(field->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED), |
| 1093 | delim(cat(key_data, value1_data))); |
| 1094 | string proto2 = |
| 1095 | cat(tag(field->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED), |
| 1096 | delim(cat(key_data, value2_data))); |
Paul Yang | ce942bc | 2019-09-03 10:47:32 -0700 | [diff] [blame] | 1097 | string proto = cat(proto1, proto2); |
| 1098 | std::unique_ptr<Message> test_message = NewTestMessage(is_proto3); |
| 1099 | test_message->MergeFromString(proto2); |
| 1100 | string text = test_message->DebugString(); |
Rafi Kamal | 6c92f9d | 2019-10-11 12:05:46 -0700 | [diff] [blame] | 1101 | RunValidProtobufTest("ValidDataMap.STRING.MESSAGE.MergeValue", REQUIRED, |
| 1102 | proto, text, is_proto3); |
Paul Yang | ce942bc | 2019-09-03 10:47:32 -0700 | [diff] [blame] | 1103 | } |
| 1104 | } |
| 1105 | |
Paul Yang | 7114d73 | 2019-09-09 13:31:53 -0700 | [diff] [blame] | 1106 | void BinaryAndJsonConformanceSuite::TestValidDataForOneofType( |
| 1107 | FieldDescriptor::Type type) { |
| 1108 | const string type_name = |
| 1109 | UpperCase(string(".") + FieldDescriptor::TypeName(type)); |
Rafi Kamal | 6c92f9d | 2019-10-11 12:05:46 -0700 | [diff] [blame] | 1110 | WireFormatLite::WireType wire_type = WireFormatLite::WireTypeForFieldType( |
| 1111 | static_cast<WireFormatLite::FieldType>(type)); |
Paul Yang | 7114d73 | 2019-09-09 13:31:53 -0700 | [diff] [blame] | 1112 | |
| 1113 | for (int is_proto3 = 0; is_proto3 < 2; is_proto3++) { |
| 1114 | const FieldDescriptor* field = GetFieldForOneofType(type, is_proto3); |
| 1115 | const string default_value = |
| 1116 | cat(tag(field->number(), wire_type), GetDefaultValue(type)); |
| 1117 | const string non_default_value = |
| 1118 | cat(tag(field->number(), wire_type), GetNonDefaultValue(type)); |
| 1119 | |
| 1120 | { |
| 1121 | // Tests oneof with default value. |
| 1122 | const string proto = default_value; |
| 1123 | std::unique_ptr<Message> test_message = NewTestMessage(is_proto3); |
| 1124 | test_message->MergeFromString(proto); |
| 1125 | string text = test_message->DebugString(); |
| 1126 | |
Rafi Kamal | 58d4420 | 2019-11-11 17:06:56 -0800 | [diff] [blame] | 1127 | RunValidProtobufTest( |
| 1128 | StrCat("ValidDataOneof", type_name, ".DefaultValue"), REQUIRED, |
| 1129 | proto, text, is_proto3); |
Paul Yang | 7114d73 | 2019-09-09 13:31:53 -0700 | [diff] [blame] | 1130 | RunValidBinaryProtobufTest( |
| 1131 | StrCat("ValidDataOneofBinary", type_name, ".DefaultValue"), |
| 1132 | RECOMMENDED, proto, proto, is_proto3); |
| 1133 | } |
| 1134 | |
| 1135 | { |
| 1136 | // Tests oneof with non-default value. |
| 1137 | const string proto = non_default_value; |
| 1138 | std::unique_ptr<Message> test_message = NewTestMessage(is_proto3); |
| 1139 | test_message->MergeFromString(proto); |
| 1140 | string text = test_message->DebugString(); |
| 1141 | |
| 1142 | RunValidProtobufTest( |
Rafi Kamal | 58d4420 | 2019-11-11 17:06:56 -0800 | [diff] [blame] | 1143 | StrCat("ValidDataOneof", type_name, ".NonDefaultValue"), |
| 1144 | REQUIRED, proto, text, is_proto3); |
Paul Yang | 7114d73 | 2019-09-09 13:31:53 -0700 | [diff] [blame] | 1145 | RunValidBinaryProtobufTest( |
| 1146 | StrCat("ValidDataOneofBinary", type_name, ".NonDefaultValue"), |
| 1147 | RECOMMENDED, proto, proto, is_proto3); |
| 1148 | } |
| 1149 | |
| 1150 | { |
| 1151 | // Tests oneof with multiple values of the same field. |
| 1152 | const string proto = StrCat(default_value, non_default_value); |
| 1153 | const string expected_proto = non_default_value; |
| 1154 | std::unique_ptr<Message> test_message = NewTestMessage(is_proto3); |
| 1155 | test_message->MergeFromString(expected_proto); |
| 1156 | string text = test_message->DebugString(); |
| 1157 | |
Rafi Kamal | 58d4420 | 2019-11-11 17:06:56 -0800 | [diff] [blame] | 1158 | RunValidProtobufTest(StrCat("ValidDataOneof", type_name, |
Rafi Kamal | 6c92f9d | 2019-10-11 12:05:46 -0700 | [diff] [blame] | 1159 | ".MultipleValuesForSameField"), |
Rafi Kamal | 58d4420 | 2019-11-11 17:06:56 -0800 | [diff] [blame] | 1160 | REQUIRED, proto, text, is_proto3); |
| 1161 | RunValidBinaryProtobufTest(StrCat("ValidDataOneofBinary", type_name, |
| 1162 | ".MultipleValuesForSameField"), |
Rafi Kamal | 6c92f9d | 2019-10-11 12:05:46 -0700 | [diff] [blame] | 1163 | RECOMMENDED, proto, expected_proto, is_proto3); |
Paul Yang | 7114d73 | 2019-09-09 13:31:53 -0700 | [diff] [blame] | 1164 | } |
| 1165 | |
| 1166 | { |
| 1167 | // Tests oneof with multiple values of the different fields. |
| 1168 | const FieldDescriptor* other_field = |
| 1169 | GetFieldForOneofType(type, is_proto3, true); |
| 1170 | FieldDescriptor::Type other_type = other_field->type(); |
| 1171 | WireFormatLite::WireType other_wire_type = |
| 1172 | WireFormatLite::WireTypeForFieldType( |
| 1173 | static_cast<WireFormatLite::FieldType>(other_type)); |
| 1174 | const string other_value = |
| 1175 | cat(tag(other_field->number(), other_wire_type), |
| 1176 | GetDefaultValue(other_type)); |
| 1177 | |
| 1178 | const string proto = StrCat(other_value, non_default_value); |
| 1179 | const string expected_proto = non_default_value; |
| 1180 | std::unique_ptr<Message> test_message = NewTestMessage(is_proto3); |
| 1181 | test_message->MergeFromString(expected_proto); |
| 1182 | string text = test_message->DebugString(); |
| 1183 | |
Rafi Kamal | 6c92f9d | 2019-10-11 12:05:46 -0700 | [diff] [blame] | 1184 | RunValidProtobufTest(StrCat("ValidDataOneof", type_name, |
Rafi Kamal | 6c92f9d | 2019-10-11 12:05:46 -0700 | [diff] [blame] | 1185 | ".MultipleValuesForDifferentField"), |
Rafi Kamal | 58d4420 | 2019-11-11 17:06:56 -0800 | [diff] [blame] | 1186 | REQUIRED, proto, text, is_proto3); |
| 1187 | RunValidBinaryProtobufTest( |
| 1188 | StrCat("ValidDataOneofBinary", type_name, |
| 1189 | ".MultipleValuesForDifferentField"), |
| 1190 | RECOMMENDED, proto, expected_proto, is_proto3); |
Paul Yang | 7114d73 | 2019-09-09 13:31:53 -0700 | [diff] [blame] | 1191 | } |
| 1192 | } |
| 1193 | } |
| 1194 | |
| 1195 | void BinaryAndJsonConformanceSuite::TestMergeOneofMessage() { |
| 1196 | string field1_data = cat(tag(1, WireFormatLite::WIRETYPE_VARINT), varint(1)); |
| 1197 | string field2a_data = cat(tag(2, WireFormatLite::WIRETYPE_VARINT), varint(1)); |
| 1198 | string field2b_data = cat(tag(2, WireFormatLite::WIRETYPE_VARINT), varint(1)); |
Rafi Kamal | 6c92f9d | 2019-10-11 12:05:46 -0700 | [diff] [blame] | 1199 | string field89_data = |
| 1200 | cat(tag(89, WireFormatLite::WIRETYPE_VARINT), varint(1)); |
Paul Yang | 7114d73 | 2019-09-09 13:31:53 -0700 | [diff] [blame] | 1201 | string submsg1_data = |
| 1202 | cat(tag(2, WireFormatLite::WIRETYPE_LENGTH_DELIMITED), |
| 1203 | delim(cat(field1_data, field2a_data, field89_data))); |
Rafi Kamal | 6c92f9d | 2019-10-11 12:05:46 -0700 | [diff] [blame] | 1204 | string submsg2_data = cat(tag(2, WireFormatLite::WIRETYPE_LENGTH_DELIMITED), |
| 1205 | delim(cat(field2b_data, field89_data))); |
| 1206 | string merged_data = |
Paul Yang | 7114d73 | 2019-09-09 13:31:53 -0700 | [diff] [blame] | 1207 | cat(tag(2, WireFormatLite::WIRETYPE_LENGTH_DELIMITED), |
Rafi Kamal | 6c92f9d | 2019-10-11 12:05:46 -0700 | [diff] [blame] | 1208 | delim(cat(field1_data, field2b_data, field89_data, field89_data))); |
Paul Yang | 7114d73 | 2019-09-09 13:31:53 -0700 | [diff] [blame] | 1209 | |
| 1210 | for (int is_proto3 = 0; is_proto3 < 2; is_proto3++) { |
| 1211 | const FieldDescriptor* field = |
| 1212 | GetFieldForOneofType(FieldDescriptor::TYPE_MESSAGE, is_proto3); |
| 1213 | |
Rafi Kamal | 6c92f9d | 2019-10-11 12:05:46 -0700 | [diff] [blame] | 1214 | string proto1 = |
| 1215 | cat(tag(field->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED), |
| 1216 | delim(submsg1_data)); |
| 1217 | string proto2 = |
| 1218 | cat(tag(field->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED), |
| 1219 | delim(submsg2_data)); |
Paul Yang | 7114d73 | 2019-09-09 13:31:53 -0700 | [diff] [blame] | 1220 | string proto = cat(proto1, proto2); |
| 1221 | string expected_proto = |
Rafi Kamal | 6c92f9d | 2019-10-11 12:05:46 -0700 | [diff] [blame] | 1222 | cat(tag(field->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED), |
| 1223 | delim(merged_data)); |
Paul Yang | 7114d73 | 2019-09-09 13:31:53 -0700 | [diff] [blame] | 1224 | |
| 1225 | std::unique_ptr<Message> test_message = NewTestMessage(is_proto3); |
| 1226 | test_message->MergeFromString(expected_proto); |
| 1227 | string text = test_message->DebugString(); |
Rafi Kamal | 6c92f9d | 2019-10-11 12:05:46 -0700 | [diff] [blame] | 1228 | RunValidProtobufTest("ValidDataOneof.MESSAGE.Merge", REQUIRED, proto, text, |
| 1229 | is_proto3); |
| 1230 | RunValidBinaryProtobufTest("ValidDataOneofBinary.MESSAGE.Merge", |
| 1231 | RECOMMENDED, proto, expected_proto, is_proto3); |
Paul Yang | 7114d73 | 2019-09-09 13:31:53 -0700 | [diff] [blame] | 1232 | } |
| 1233 | } |
| 1234 | |
Paul Yang | cecba29 | 2018-12-14 16:05:03 -0800 | [diff] [blame] | 1235 | void BinaryAndJsonConformanceSuite::TestIllegalTags() { |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 1236 | // field num 0 is illegal |
| 1237 | string nullfield[] = { |
| 1238 | "\1DEADBEEF", |
| 1239 | "\2\1\1", |
| 1240 | "\3\4", |
| 1241 | "\5DEAD" |
| 1242 | }; |
| 1243 | for (int i = 0; i < 4; i++) { |
| 1244 | string name = "IllegalZeroFieldNum_Case_0"; |
| 1245 | name.back() += i; |
| 1246 | ExpectParseFailureForProto(nullfield[i], name, REQUIRED); |
| 1247 | } |
| 1248 | } |
| 1249 | template <class MessageType> |
Paul Yang | cecba29 | 2018-12-14 16:05:03 -0800 | [diff] [blame] | 1250 | void BinaryAndJsonConformanceSuite::TestOneofMessage ( |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 1251 | MessageType &message, bool is_proto3) { |
| 1252 | message.set_oneof_uint32(0); |
| 1253 | RunValidProtobufTestWithMessage( |
| 1254 | "OneofZeroUint32", RECOMMENDED, &message, "oneof_uint32: 0", is_proto3); |
| 1255 | message.mutable_oneof_nested_message()->set_a(0); |
| 1256 | RunValidProtobufTestWithMessage( |
| 1257 | "OneofZeroMessage", RECOMMENDED, &message, |
| 1258 | is_proto3 ? "oneof_nested_message: {}" : "oneof_nested_message: {a: 0}", |
| 1259 | is_proto3); |
| 1260 | message.mutable_oneof_nested_message()->set_a(1); |
| 1261 | RunValidProtobufTestWithMessage( |
| 1262 | "OneofZeroMessageSetTwice", RECOMMENDED, &message, |
| 1263 | "oneof_nested_message: {a: 1}", |
| 1264 | is_proto3); |
| 1265 | message.set_oneof_string(""); |
| 1266 | RunValidProtobufTestWithMessage( |
| 1267 | "OneofZeroString", RECOMMENDED, &message, "oneof_string: \"\"", is_proto3); |
| 1268 | message.set_oneof_bytes(""); |
| 1269 | RunValidProtobufTestWithMessage( |
| 1270 | "OneofZeroBytes", RECOMMENDED, &message, "oneof_bytes: \"\"", is_proto3); |
| 1271 | message.set_oneof_bool(false); |
| 1272 | RunValidProtobufTestWithMessage( |
| 1273 | "OneofZeroBool", RECOMMENDED, &message, "oneof_bool: false", is_proto3); |
| 1274 | message.set_oneof_uint64(0); |
| 1275 | RunValidProtobufTestWithMessage( |
| 1276 | "OneofZeroUint64", RECOMMENDED, &message, "oneof_uint64: 0", is_proto3); |
| 1277 | message.set_oneof_float(0.0f); |
| 1278 | RunValidProtobufTestWithMessage( |
| 1279 | "OneofZeroFloat", RECOMMENDED, &message, "oneof_float: 0", is_proto3); |
| 1280 | message.set_oneof_double(0.0); |
| 1281 | RunValidProtobufTestWithMessage( |
| 1282 | "OneofZeroDouble", RECOMMENDED, &message, "oneof_double: 0", is_proto3); |
| 1283 | message.set_oneof_enum(MessageType::FOO); |
| 1284 | RunValidProtobufTestWithMessage( |
| 1285 | "OneofZeroEnum", RECOMMENDED, &message, "oneof_enum: FOO", is_proto3); |
| 1286 | } |
| 1287 | |
| 1288 | template <class MessageType> |
Paul Yang | cecba29 | 2018-12-14 16:05:03 -0800 | [diff] [blame] | 1289 | void BinaryAndJsonConformanceSuite::TestUnknownMessage( |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 1290 | MessageType& message, bool is_proto3) { |
| 1291 | message.ParseFromString("\xA8\x1F\x01"); |
| 1292 | RunValidBinaryProtobufTest("UnknownVarint", REQUIRED, |
| 1293 | message.SerializeAsString(), is_proto3); |
| 1294 | } |
| 1295 | |
Paul Yang | cecba29 | 2018-12-14 16:05:03 -0800 | [diff] [blame] | 1296 | void BinaryAndJsonConformanceSuite::RunSuiteImpl() { |
Yilun Chong | d8c2501 | 2019-02-22 18:13:33 +0800 | [diff] [blame] | 1297 | // Hack to get the list of test failures based on whether |
Rafi Kamal | 58d4420 | 2019-11-11 17:06:56 -0800 | [diff] [blame] | 1298 | // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER is enabled or not. |
Yilun Chong | d8c2501 | 2019-02-22 18:13:33 +0800 | [diff] [blame] | 1299 | conformance::FailureSet failure_set; |
| 1300 | ConformanceRequest req; |
| 1301 | ConformanceResponse res; |
| 1302 | req.set_message_type(failure_set.GetTypeName()); |
| 1303 | req.set_protobuf_payload(""); |
| 1304 | req.set_requested_output_format(conformance::WireFormat::PROTOBUF); |
| 1305 | RunTest("FindFailures", req, &res); |
| 1306 | GOOGLE_CHECK(failure_set.MergeFromString(res.protobuf_payload())); |
| 1307 | for (const string& failure : failure_set.failure()) { |
| 1308 | AddExpectedFailedTest(failure); |
| 1309 | } |
| 1310 | |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 1311 | type_resolver_.reset(NewTypeResolverForDescriptorPool( |
| 1312 | kTypeUrlPrefix, DescriptorPool::generated_pool())); |
| 1313 | type_url_ = GetTypeUrl(TestAllTypesProto3::descriptor()); |
| 1314 | |
| 1315 | for (int i = 1; i <= FieldDescriptor::MAX_TYPE; i++) { |
| 1316 | if (i == FieldDescriptor::TYPE_GROUP) continue; |
| 1317 | TestPrematureEOFForType(static_cast<FieldDescriptor::Type>(i)); |
| 1318 | } |
| 1319 | |
| 1320 | TestIllegalTags(); |
| 1321 | |
| 1322 | int64 kInt64Min = -9223372036854775808ULL; |
| 1323 | int64 kInt64Max = 9223372036854775807ULL; |
| 1324 | uint64 kUint64Max = 18446744073709551615ULL; |
| 1325 | int32 kInt32Max = 2147483647; |
| 1326 | int32 kInt32Min = -2147483648; |
| 1327 | uint32 kUint32Max = 4294967295UL; |
| 1328 | |
Rafi Kamal | 6c92f9d | 2019-10-11 12:05:46 -0700 | [diff] [blame] | 1329 | TestValidDataForType( |
| 1330 | FieldDescriptor::TYPE_DOUBLE, |
| 1331 | { |
| 1332 | {dbl(0), dbl(0)}, |
| 1333 | {dbl(0.1), dbl(0.1)}, |
| 1334 | {dbl(1.7976931348623157e+308), dbl(1.7976931348623157e+308)}, |
| 1335 | {dbl(2.22507385850720138309e-308), dbl(2.22507385850720138309e-308)}, |
| 1336 | }); |
| 1337 | TestValidDataForType( |
| 1338 | FieldDescriptor::TYPE_FLOAT, |
| 1339 | { |
| 1340 | {flt(0), flt(0)}, |
| 1341 | {flt(0.1), flt(0.1)}, |
| 1342 | {flt(1.00000075e-36), flt(1.00000075e-36)}, |
| 1343 | {flt(3.402823e+38), flt(3.402823e+38)}, // 3.40282347e+38 |
| 1344 | {flt(1.17549435e-38f), flt(1.17549435e-38)}, |
| 1345 | }); |
| 1346 | TestValidDataForType(FieldDescriptor::TYPE_INT64, |
| 1347 | { |
| 1348 | {varint(0), varint(0)}, |
| 1349 | {varint(12345), varint(12345)}, |
| 1350 | {varint(kInt64Max), varint(kInt64Max)}, |
| 1351 | {varint(kInt64Min), varint(kInt64Min)}, |
| 1352 | }); |
| 1353 | TestValidDataForType(FieldDescriptor::TYPE_UINT64, |
| 1354 | { |
| 1355 | {varint(0), varint(0)}, |
| 1356 | {varint(12345), varint(12345)}, |
| 1357 | {varint(kUint64Max), varint(kUint64Max)}, |
| 1358 | }); |
| 1359 | TestValidDataForType(FieldDescriptor::TYPE_INT32, |
| 1360 | { |
| 1361 | {varint(0), varint(0)}, |
| 1362 | {varint(12345), varint(12345)}, |
| 1363 | {longvarint(12345, 2), varint(12345)}, |
| 1364 | {longvarint(12345, 7), varint(12345)}, |
| 1365 | {varint(kInt32Max), varint(kInt32Max)}, |
| 1366 | {varint(kInt32Min), varint(kInt32Min)}, |
| 1367 | {varint(1LL << 33), varint(0)}, |
| 1368 | {varint((1LL << 33) - 1), varint(-1)}, |
Rafi Kamal | 58d4420 | 2019-11-11 17:06:56 -0800 | [diff] [blame] | 1369 | {varint(kInt64Max), varint(-1)}, |
| 1370 | {varint(kInt64Min + 1), varint(1)}, |
Rafi Kamal | 6c92f9d | 2019-10-11 12:05:46 -0700 | [diff] [blame] | 1371 | }); |
| 1372 | TestValidDataForType( |
| 1373 | FieldDescriptor::TYPE_UINT32, |
| 1374 | { |
| 1375 | {varint(0), varint(0)}, |
| 1376 | {varint(12345), varint(12345)}, |
| 1377 | {longvarint(12345, 2), varint(12345)}, |
| 1378 | {longvarint(12345, 7), varint(12345)}, |
| 1379 | {varint(kUint32Max), varint(kUint32Max)}, // UINT32_MAX |
| 1380 | {varint(1LL << 33), varint(0)}, |
Rafi Kamal | 58d4420 | 2019-11-11 17:06:56 -0800 | [diff] [blame] | 1381 | {varint((1LL << 33) + 1), varint(1)}, |
Rafi Kamal | 6c92f9d | 2019-10-11 12:05:46 -0700 | [diff] [blame] | 1382 | {varint((1LL << 33) - 1), varint((1LL << 32) - 1)}, |
Rafi Kamal | 58d4420 | 2019-11-11 17:06:56 -0800 | [diff] [blame] | 1383 | {varint(kInt64Max), varint((1LL << 32) - 1)}, |
| 1384 | {varint(kInt64Min + 1), varint(1)}, |
Rafi Kamal | 6c92f9d | 2019-10-11 12:05:46 -0700 | [diff] [blame] | 1385 | }); |
| 1386 | TestValidDataForType(FieldDescriptor::TYPE_FIXED64, |
| 1387 | { |
| 1388 | {u64(0), u64(0)}, |
| 1389 | {u64(12345), u64(12345)}, |
| 1390 | {u64(kUint64Max), u64(kUint64Max)}, |
| 1391 | }); |
| 1392 | TestValidDataForType(FieldDescriptor::TYPE_FIXED32, |
| 1393 | { |
| 1394 | {u32(0), u32(0)}, |
| 1395 | {u32(12345), u32(12345)}, |
| 1396 | {u32(kUint32Max), u32(kUint32Max)}, // UINT32_MAX |
| 1397 | }); |
| 1398 | TestValidDataForType(FieldDescriptor::TYPE_SFIXED64, |
| 1399 | { |
| 1400 | {u64(0), u64(0)}, |
| 1401 | {u64(12345), u64(12345)}, |
| 1402 | {u64(kInt64Max), u64(kInt64Max)}, |
| 1403 | {u64(kInt64Min), u64(kInt64Min)}, |
| 1404 | }); |
| 1405 | TestValidDataForType(FieldDescriptor::TYPE_SFIXED32, |
| 1406 | { |
| 1407 | {u32(0), u32(0)}, |
| 1408 | {u32(12345), u32(12345)}, |
| 1409 | {u32(kInt32Max), u32(kInt32Max)}, |
| 1410 | {u32(kInt32Min), u32(kInt32Min)}, |
| 1411 | }); |
| 1412 | // Bools should be serialized as 0 for false and 1 for true. Parsers should |
| 1413 | // also interpret any nonzero value as true. |
| 1414 | TestValidDataForType(FieldDescriptor::TYPE_BOOL, |
| 1415 | { |
| 1416 | {varint(0), varint(0)}, |
| 1417 | {varint(1), varint(1)}, |
Rafi Kamal | 58d4420 | 2019-11-11 17:06:56 -0800 | [diff] [blame] | 1418 | {varint(-1), varint(1)}, |
Rafi Kamal | 6c92f9d | 2019-10-11 12:05:46 -0700 | [diff] [blame] | 1419 | {varint(12345678), varint(1)}, |
Rafi Kamal | 58d4420 | 2019-11-11 17:06:56 -0800 | [diff] [blame] | 1420 | {varint(1LL << 33), varint(1)}, |
| 1421 | {varint(kInt64Max), varint(1)}, |
| 1422 | {varint(kInt64Min), varint(1)}, |
Rafi Kamal | 6c92f9d | 2019-10-11 12:05:46 -0700 | [diff] [blame] | 1423 | }); |
| 1424 | TestValidDataForType(FieldDescriptor::TYPE_SINT32, |
| 1425 | { |
| 1426 | {zz32(0), zz32(0)}, |
| 1427 | {zz32(12345), zz32(12345)}, |
| 1428 | {zz32(kInt32Max), zz32(kInt32Max)}, |
| 1429 | {zz32(kInt32Min), zz32(kInt32Min)}, |
Rafi Kamal | 58d4420 | 2019-11-11 17:06:56 -0800 | [diff] [blame] | 1430 | {zz64(kInt32Max + 2LL), zz32(1)}, |
Rafi Kamal | 6c92f9d | 2019-10-11 12:05:46 -0700 | [diff] [blame] | 1431 | }); |
| 1432 | TestValidDataForType(FieldDescriptor::TYPE_SINT64, |
| 1433 | { |
| 1434 | {zz64(0), zz64(0)}, |
| 1435 | {zz64(12345), zz64(12345)}, |
| 1436 | {zz64(kInt64Max), zz64(kInt64Max)}, |
| 1437 | {zz64(kInt64Min), zz64(kInt64Min)}, |
| 1438 | }); |
| 1439 | TestValidDataForType( |
| 1440 | FieldDescriptor::TYPE_STRING, |
| 1441 | { |
| 1442 | {delim(""), delim("")}, |
| 1443 | {delim("Hello world!"), delim("Hello world!")}, |
| 1444 | {delim("\'\"\?\\\a\b\f\n\r\t\v"), |
| 1445 | delim("\'\"\?\\\a\b\f\n\r\t\v")}, // escape |
| 1446 | {delim("谷歌"), delim("谷歌")}, // Google in Chinese |
| 1447 | {delim("\u8C37\u6B4C"), delim("谷歌")}, // unicode escape |
| 1448 | {delim("\u8c37\u6b4c"), delim("谷歌")}, // lowercase unicode |
| 1449 | {delim("\xF0\x9F\x98\x81"), delim("\xF0\x9F\x98\x81")}, // emoji: 😁 |
| 1450 | }); |
| 1451 | TestValidDataForType(FieldDescriptor::TYPE_BYTES, |
| 1452 | { |
| 1453 | {delim(""), delim("")}, |
Rafi Kamal | 58d4420 | 2019-11-11 17:06:56 -0800 | [diff] [blame] | 1454 | {delim("Hello world!"), delim("Hello world!")}, |
Rafi Kamal | 6c92f9d | 2019-10-11 12:05:46 -0700 | [diff] [blame] | 1455 | {delim("\x01\x02"), delim("\x01\x02")}, |
| 1456 | {delim("\xfb"), delim("\xfb")}, |
| 1457 | }); |
Rafi Kamal | 58d4420 | 2019-11-11 17:06:56 -0800 | [diff] [blame] | 1458 | TestValidDataForType(FieldDescriptor::TYPE_ENUM, |
| 1459 | { |
| 1460 | {varint(0), varint(0)}, |
| 1461 | {varint(1), varint(1)}, |
| 1462 | {varint(2), varint(2)}, |
| 1463 | {varint(-1), varint(-1)}, |
| 1464 | {varint(kInt64Max), varint(-1)}, |
| 1465 | {varint(kInt64Min + 1), varint(1)}, |
| 1466 | }); |
Paul Yang | 2849a79 | 2019-07-24 12:26:40 -0700 | [diff] [blame] | 1467 | TestValidDataForRepeatedScalarMessage(); |
Rafi Kamal | 6c92f9d | 2019-10-11 12:05:46 -0700 | [diff] [blame] | 1468 | TestValidDataForType( |
| 1469 | FieldDescriptor::TYPE_MESSAGE, |
| 1470 | { |
| 1471 | {delim(""), delim("")}, |
| 1472 | {delim(cat(tag(1, WireFormatLite::WIRETYPE_VARINT), varint(1234))), |
| 1473 | delim(cat(tag(1, WireFormatLite::WIRETYPE_VARINT), varint(1234)))}, |
| 1474 | }); |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 1475 | |
Rafi Kamal | 6c92f9d | 2019-10-11 12:05:46 -0700 | [diff] [blame] | 1476 | TestValidDataForMapType(FieldDescriptor::TYPE_INT32, |
| 1477 | FieldDescriptor::TYPE_INT32); |
| 1478 | TestValidDataForMapType(FieldDescriptor::TYPE_INT64, |
| 1479 | FieldDescriptor::TYPE_INT64); |
| 1480 | TestValidDataForMapType(FieldDescriptor::TYPE_UINT32, |
| 1481 | FieldDescriptor::TYPE_UINT32); |
| 1482 | TestValidDataForMapType(FieldDescriptor::TYPE_UINT64, |
| 1483 | FieldDescriptor::TYPE_UINT64); |
| 1484 | TestValidDataForMapType(FieldDescriptor::TYPE_SINT32, |
| 1485 | FieldDescriptor::TYPE_SINT32); |
| 1486 | TestValidDataForMapType(FieldDescriptor::TYPE_SINT64, |
| 1487 | FieldDescriptor::TYPE_SINT64); |
| 1488 | TestValidDataForMapType(FieldDescriptor::TYPE_FIXED32, |
| 1489 | FieldDescriptor::TYPE_FIXED32); |
| 1490 | TestValidDataForMapType(FieldDescriptor::TYPE_FIXED64, |
| 1491 | FieldDescriptor::TYPE_FIXED64); |
| 1492 | TestValidDataForMapType(FieldDescriptor::TYPE_SFIXED32, |
| 1493 | FieldDescriptor::TYPE_SFIXED32); |
| 1494 | TestValidDataForMapType(FieldDescriptor::TYPE_SFIXED64, |
| 1495 | FieldDescriptor::TYPE_SFIXED64); |
| 1496 | TestValidDataForMapType(FieldDescriptor::TYPE_INT32, |
| 1497 | FieldDescriptor::TYPE_FLOAT); |
| 1498 | TestValidDataForMapType(FieldDescriptor::TYPE_INT32, |
| 1499 | FieldDescriptor::TYPE_DOUBLE); |
| 1500 | TestValidDataForMapType(FieldDescriptor::TYPE_BOOL, |
| 1501 | FieldDescriptor::TYPE_BOOL); |
| 1502 | TestValidDataForMapType(FieldDescriptor::TYPE_STRING, |
| 1503 | FieldDescriptor::TYPE_STRING); |
| 1504 | TestValidDataForMapType(FieldDescriptor::TYPE_STRING, |
| 1505 | FieldDescriptor::TYPE_BYTES); |
| 1506 | TestValidDataForMapType(FieldDescriptor::TYPE_STRING, |
| 1507 | FieldDescriptor::TYPE_ENUM); |
| 1508 | TestValidDataForMapType(FieldDescriptor::TYPE_STRING, |
| 1509 | FieldDescriptor::TYPE_MESSAGE); |
Paul Yang | ce942bc | 2019-09-03 10:47:32 -0700 | [diff] [blame] | 1510 | // Additional test to check overwriting message value map. |
| 1511 | TestOverwriteMessageValueMap(); |
| 1512 | |
Paul Yang | 7114d73 | 2019-09-09 13:31:53 -0700 | [diff] [blame] | 1513 | TestValidDataForOneofType(FieldDescriptor::TYPE_UINT32); |
| 1514 | TestValidDataForOneofType(FieldDescriptor::TYPE_BOOL); |
| 1515 | TestValidDataForOneofType(FieldDescriptor::TYPE_UINT64); |
| 1516 | TestValidDataForOneofType(FieldDescriptor::TYPE_FLOAT); |
| 1517 | TestValidDataForOneofType(FieldDescriptor::TYPE_DOUBLE); |
| 1518 | TestValidDataForOneofType(FieldDescriptor::TYPE_STRING); |
| 1519 | TestValidDataForOneofType(FieldDescriptor::TYPE_BYTES); |
| 1520 | TestValidDataForOneofType(FieldDescriptor::TYPE_ENUM); |
| 1521 | TestValidDataForOneofType(FieldDescriptor::TYPE_MESSAGE); |
| 1522 | // Additional test to check merging oneof message. |
| 1523 | TestMergeOneofMessage(); |
| 1524 | |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 1525 | // TODO(haberman): |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 1526 | // TestValidDataForType(FieldDescriptor::TYPE_GROUP |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 1527 | |
Rafi Kamal | 58d4420 | 2019-11-11 17:06:56 -0800 | [diff] [blame] | 1528 | // Unknown fields. |
| 1529 | { |
| 1530 | TestAllTypesProto3 messageProto3; |
| 1531 | TestAllTypesProto2 messageProto2; |
| 1532 | // TODO(yilunchong): update this behavior when unknown field's behavior |
| 1533 | // changed in open source. Also delete |
| 1534 | // Required.Proto3.ProtobufInput.UnknownVarint.ProtobufOutput |
| 1535 | // from failure list of python_cpp python java |
| 1536 | TestUnknownMessage(messageProto3, true); |
| 1537 | TestUnknownMessage(messageProto2, false); |
| 1538 | } |
| 1539 | |
| 1540 | RunJsonTests(); |
| 1541 | } |
| 1542 | |
| 1543 | void BinaryAndJsonConformanceSuite::RunJsonTests() { |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 1544 | RunValidJsonTest("HelloWorld", REQUIRED, |
| 1545 | "{\"optionalString\":\"Hello, World!\"}", |
| 1546 | "optional_string: 'Hello, World!'"); |
| 1547 | |
| 1548 | // NOTE: The spec for JSON support is still being sorted out, these may not |
| 1549 | // all be correct. |
Rafi Kamal | 58d4420 | 2019-11-11 17:06:56 -0800 | [diff] [blame] | 1550 | |
| 1551 | RunJsonTestsForFieldNameConvention(); |
| 1552 | RunJsonTestsForNonRepeatedTypes(); |
| 1553 | RunJsonTestsForRepeatedTypes(); |
| 1554 | RunJsonTestsForNullTypes(); |
| 1555 | RunJsonTestsForWrapperTypes(); |
| 1556 | RunJsonTestsForFieldMask(); |
| 1557 | RunJsonTestsForStruct(); |
| 1558 | RunJsonTestsForValue(); |
| 1559 | RunJsonTestsForAny(); |
| 1560 | |
| 1561 | RunValidJsonIgnoreUnknownTest("IgnoreUnknownJsonNumber", REQUIRED, |
| 1562 | R"({ |
| 1563 | "unknown": 1 |
| 1564 | })", |
| 1565 | ""); |
| 1566 | RunValidJsonIgnoreUnknownTest("IgnoreUnknownJsonString", REQUIRED, |
| 1567 | R"({ |
| 1568 | "unknown": "a" |
| 1569 | })", |
| 1570 | ""); |
| 1571 | RunValidJsonIgnoreUnknownTest("IgnoreUnknownJsonTrue", REQUIRED, |
| 1572 | R"({ |
| 1573 | "unknown": true |
| 1574 | })", |
| 1575 | ""); |
| 1576 | RunValidJsonIgnoreUnknownTest("IgnoreUnknownJsonFalse", REQUIRED, |
| 1577 | R"({ |
| 1578 | "unknown": false |
| 1579 | })", |
| 1580 | ""); |
| 1581 | RunValidJsonIgnoreUnknownTest("IgnoreUnknownJsonNull", REQUIRED, |
| 1582 | R"({ |
| 1583 | "unknown": null |
| 1584 | })", |
| 1585 | ""); |
| 1586 | RunValidJsonIgnoreUnknownTest("IgnoreUnknownJsonObject", REQUIRED, |
| 1587 | R"({ |
| 1588 | "unknown": {"a": 1} |
| 1589 | })", |
| 1590 | ""); |
| 1591 | |
| 1592 | ExpectParseFailureForJson("RejectTopLevelNull", REQUIRED, "null"); |
| 1593 | } |
| 1594 | |
| 1595 | void BinaryAndJsonConformanceSuite::RunJsonTestsForFieldNameConvention() { |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 1596 | RunValidJsonTest( |
| 1597 | "FieldNameInSnakeCase", REQUIRED, |
| 1598 | R"({ |
| 1599 | "fieldname1": 1, |
| 1600 | "fieldName2": 2, |
| 1601 | "FieldName3": 3, |
| 1602 | "fieldName4": 4 |
| 1603 | })", |
| 1604 | R"( |
| 1605 | fieldname1: 1 |
| 1606 | field_name2: 2 |
| 1607 | _field_name3: 3 |
| 1608 | field__name4_: 4 |
| 1609 | )"); |
| 1610 | RunValidJsonTest( |
| 1611 | "FieldNameWithNumbers", REQUIRED, |
| 1612 | R"({ |
| 1613 | "field0name5": 5, |
| 1614 | "field0Name6": 6 |
| 1615 | })", |
| 1616 | R"( |
| 1617 | field0name5: 5 |
| 1618 | field_0_name6: 6 |
| 1619 | )"); |
| 1620 | RunValidJsonTest( |
| 1621 | "FieldNameWithMixedCases", REQUIRED, |
| 1622 | R"({ |
| 1623 | "fieldName7": 7, |
| 1624 | "FieldName8": 8, |
| 1625 | "fieldName9": 9, |
| 1626 | "FieldName10": 10, |
| 1627 | "FIELDNAME11": 11, |
| 1628 | "FIELDName12": 12 |
| 1629 | })", |
| 1630 | R"( |
| 1631 | fieldName7: 7 |
| 1632 | FieldName8: 8 |
| 1633 | field_Name9: 9 |
| 1634 | Field_Name10: 10 |
| 1635 | FIELD_NAME11: 11 |
| 1636 | FIELD_name12: 12 |
| 1637 | )"); |
| 1638 | RunValidJsonTest( |
| 1639 | "FieldNameWithDoubleUnderscores", RECOMMENDED, |
| 1640 | R"({ |
| 1641 | "FieldName13": 13, |
| 1642 | "FieldName14": 14, |
| 1643 | "fieldName15": 15, |
| 1644 | "fieldName16": 16, |
| 1645 | "fieldName17": 17, |
| 1646 | "FieldName18": 18 |
| 1647 | })", |
| 1648 | R"( |
| 1649 | __field_name13: 13 |
| 1650 | __Field_name14: 14 |
| 1651 | field__name15: 15 |
| 1652 | field__Name16: 16 |
| 1653 | field_name17__: 17 |
| 1654 | Field_name18__: 18 |
| 1655 | )"); |
| 1656 | // Using the original proto field name in JSON is also allowed. |
| 1657 | RunValidJsonTest( |
| 1658 | "OriginalProtoFieldName", REQUIRED, |
| 1659 | R"({ |
| 1660 | "fieldname1": 1, |
| 1661 | "field_name2": 2, |
| 1662 | "_field_name3": 3, |
| 1663 | "field__name4_": 4, |
| 1664 | "field0name5": 5, |
| 1665 | "field_0_name6": 6, |
| 1666 | "fieldName7": 7, |
| 1667 | "FieldName8": 8, |
| 1668 | "field_Name9": 9, |
| 1669 | "Field_Name10": 10, |
| 1670 | "FIELD_NAME11": 11, |
| 1671 | "FIELD_name12": 12, |
| 1672 | "__field_name13": 13, |
| 1673 | "__Field_name14": 14, |
| 1674 | "field__name15": 15, |
| 1675 | "field__Name16": 16, |
| 1676 | "field_name17__": 17, |
| 1677 | "Field_name18__": 18 |
| 1678 | })", |
| 1679 | R"( |
| 1680 | fieldname1: 1 |
| 1681 | field_name2: 2 |
| 1682 | _field_name3: 3 |
| 1683 | field__name4_: 4 |
| 1684 | field0name5: 5 |
| 1685 | field_0_name6: 6 |
| 1686 | fieldName7: 7 |
| 1687 | FieldName8: 8 |
| 1688 | field_Name9: 9 |
| 1689 | Field_Name10: 10 |
| 1690 | FIELD_NAME11: 11 |
| 1691 | FIELD_name12: 12 |
| 1692 | __field_name13: 13 |
| 1693 | __Field_name14: 14 |
| 1694 | field__name15: 15 |
| 1695 | field__Name16: 16 |
| 1696 | field_name17__: 17 |
| 1697 | Field_name18__: 18 |
| 1698 | )"); |
| 1699 | // Field names can be escaped. |
| 1700 | RunValidJsonTest( |
| 1701 | "FieldNameEscaped", REQUIRED, |
| 1702 | R"({"fieldn\u0061me1": 1})", |
| 1703 | "fieldname1: 1"); |
| 1704 | // String ends with escape character. |
| 1705 | ExpectParseFailureForJson( |
| 1706 | "StringEndsWithEscapeChar", RECOMMENDED, |
| 1707 | "{\"optionalString\": \"abc\\"); |
| 1708 | // Field names must be quoted (or it's not valid JSON). |
| 1709 | ExpectParseFailureForJson( |
| 1710 | "FieldNameNotQuoted", RECOMMENDED, |
| 1711 | "{fieldname1: 1}"); |
| 1712 | // Trailing comma is not allowed (not valid JSON). |
| 1713 | ExpectParseFailureForJson( |
| 1714 | "TrailingCommaInAnObject", RECOMMENDED, |
| 1715 | R"({"fieldname1":1,})"); |
| 1716 | ExpectParseFailureForJson( |
| 1717 | "TrailingCommaInAnObjectWithSpace", RECOMMENDED, |
| 1718 | R"({"fieldname1":1 ,})"); |
| 1719 | ExpectParseFailureForJson( |
| 1720 | "TrailingCommaInAnObjectWithSpaceCommaSpace", RECOMMENDED, |
| 1721 | R"({"fieldname1":1 , })"); |
| 1722 | ExpectParseFailureForJson( |
| 1723 | "TrailingCommaInAnObjectWithNewlines", RECOMMENDED, |
| 1724 | R"({ |
| 1725 | "fieldname1":1, |
| 1726 | })"); |
| 1727 | // JSON doesn't support comments. |
| 1728 | ExpectParseFailureForJson( |
| 1729 | "JsonWithComments", RECOMMENDED, |
| 1730 | R"({ |
| 1731 | // This is a comment. |
| 1732 | "fieldname1": 1 |
| 1733 | })"); |
| 1734 | // JSON spec says whitespace doesn't matter, so try a few spacings to be sure. |
| 1735 | RunValidJsonTest( |
| 1736 | "OneLineNoSpaces", RECOMMENDED, |
| 1737 | "{\"optionalInt32\":1,\"optionalInt64\":2}", |
| 1738 | R"( |
| 1739 | optional_int32: 1 |
| 1740 | optional_int64: 2 |
| 1741 | )"); |
| 1742 | RunValidJsonTest( |
| 1743 | "OneLineWithSpaces", RECOMMENDED, |
| 1744 | "{ \"optionalInt32\" : 1 , \"optionalInt64\" : 2 }", |
| 1745 | R"( |
| 1746 | optional_int32: 1 |
| 1747 | optional_int64: 2 |
| 1748 | )"); |
| 1749 | RunValidJsonTest( |
| 1750 | "MultilineNoSpaces", RECOMMENDED, |
| 1751 | "{\n\"optionalInt32\"\n:\n1\n,\n\"optionalInt64\"\n:\n2\n}", |
| 1752 | R"( |
| 1753 | optional_int32: 1 |
| 1754 | optional_int64: 2 |
| 1755 | )"); |
| 1756 | RunValidJsonTest( |
| 1757 | "MultilineWithSpaces", RECOMMENDED, |
| 1758 | "{\n \"optionalInt32\" : 1\n ,\n \"optionalInt64\" : 2\n}\n", |
| 1759 | R"( |
| 1760 | optional_int32: 1 |
| 1761 | optional_int64: 2 |
| 1762 | )"); |
| 1763 | // Missing comma between key/value pairs. |
| 1764 | ExpectParseFailureForJson( |
| 1765 | "MissingCommaOneLine", RECOMMENDED, |
| 1766 | "{ \"optionalInt32\": 1 \"optionalInt64\": 2 }"); |
| 1767 | ExpectParseFailureForJson( |
| 1768 | "MissingCommaMultiline", RECOMMENDED, |
| 1769 | "{\n \"optionalInt32\": 1\n \"optionalInt64\": 2\n}"); |
| 1770 | // Duplicated field names are not allowed. |
| 1771 | ExpectParseFailureForJson( |
| 1772 | "FieldNameDuplicate", RECOMMENDED, |
| 1773 | R"({ |
| 1774 | "optionalNestedMessage": {a: 1}, |
| 1775 | "optionalNestedMessage": {} |
| 1776 | })"); |
| 1777 | ExpectParseFailureForJson( |
| 1778 | "FieldNameDuplicateDifferentCasing1", RECOMMENDED, |
| 1779 | R"({ |
| 1780 | "optional_nested_message": {a: 1}, |
| 1781 | "optionalNestedMessage": {} |
| 1782 | })"); |
| 1783 | ExpectParseFailureForJson( |
| 1784 | "FieldNameDuplicateDifferentCasing2", RECOMMENDED, |
| 1785 | R"({ |
| 1786 | "optionalNestedMessage": {a: 1}, |
| 1787 | "optional_nested_message": {} |
| 1788 | })"); |
| 1789 | // Serializers should use lowerCamelCase by default. |
| 1790 | RunValidJsonTestWithValidator( |
| 1791 | "FieldNameInLowerCamelCase", REQUIRED, |
| 1792 | R"({ |
| 1793 | "fieldname1": 1, |
| 1794 | "fieldName2": 2, |
| 1795 | "FieldName3": 3, |
| 1796 | "fieldName4": 4 |
| 1797 | })", |
| 1798 | [](const Json::Value& value) { |
| 1799 | return value.isMember("fieldname1") && |
| 1800 | value.isMember("fieldName2") && |
| 1801 | value.isMember("FieldName3") && |
| 1802 | value.isMember("fieldName4"); |
Joshua Haberman | 2d80a70 | 2020-05-07 16:21:50 -0700 | [diff] [blame] | 1803 | }, |
| 1804 | true); |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 1805 | RunValidJsonTestWithValidator( |
| 1806 | "FieldNameWithNumbers", REQUIRED, |
| 1807 | R"({ |
| 1808 | "field0name5": 5, |
| 1809 | "field0Name6": 6 |
| 1810 | })", |
| 1811 | [](const Json::Value& value) { |
| 1812 | return value.isMember("field0name5") && |
| 1813 | value.isMember("field0Name6"); |
Joshua Haberman | 2d80a70 | 2020-05-07 16:21:50 -0700 | [diff] [blame] | 1814 | }, |
| 1815 | true); |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 1816 | RunValidJsonTestWithValidator( |
| 1817 | "FieldNameWithMixedCases", REQUIRED, |
| 1818 | R"({ |
| 1819 | "fieldName7": 7, |
| 1820 | "FieldName8": 8, |
| 1821 | "fieldName9": 9, |
| 1822 | "FieldName10": 10, |
| 1823 | "FIELDNAME11": 11, |
| 1824 | "FIELDName12": 12 |
| 1825 | })", |
| 1826 | [](const Json::Value& value) { |
| 1827 | return value.isMember("fieldName7") && |
| 1828 | value.isMember("FieldName8") && |
| 1829 | value.isMember("fieldName9") && |
| 1830 | value.isMember("FieldName10") && |
| 1831 | value.isMember("FIELDNAME11") && |
| 1832 | value.isMember("FIELDName12"); |
Joshua Haberman | 2d80a70 | 2020-05-07 16:21:50 -0700 | [diff] [blame] | 1833 | }, |
| 1834 | true); |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 1835 | RunValidJsonTestWithValidator( |
| 1836 | "FieldNameWithDoubleUnderscores", RECOMMENDED, |
| 1837 | R"({ |
| 1838 | "FieldName13": 13, |
| 1839 | "FieldName14": 14, |
| 1840 | "fieldName15": 15, |
| 1841 | "fieldName16": 16, |
| 1842 | "fieldName17": 17, |
| 1843 | "FieldName18": 18 |
| 1844 | })", |
| 1845 | [](const Json::Value& value) { |
| 1846 | return value.isMember("FieldName13") && |
| 1847 | value.isMember("FieldName14") && |
| 1848 | value.isMember("fieldName15") && |
| 1849 | value.isMember("fieldName16") && |
| 1850 | value.isMember("fieldName17") && |
| 1851 | value.isMember("FieldName18"); |
Joshua Haberman | 2d80a70 | 2020-05-07 16:21:50 -0700 | [diff] [blame] | 1852 | }, |
| 1853 | true); |
| 1854 | RunValidJsonTestWithValidator( |
| 1855 | "StoresDefaultPrimitive", REQUIRED, |
| 1856 | R"({ |
| 1857 | "FieldName13": 0 |
| 1858 | })", |
| 1859 | [](const Json::Value& value) { return value.isMember("FieldName13"); }, |
| 1860 | false); |
| 1861 | RunValidJsonTestWithValidator( |
| 1862 | "SkipsDefaultPrimitive", REQUIRED, |
| 1863 | R"({ |
| 1864 | "FieldName13": 0 |
| 1865 | })", |
| 1866 | [](const Json::Value& value) { return !value.isMember("FieldName13"); }, |
| 1867 | true); |
Joshua Haberman | 6b5fb80 | 2020-05-11 00:12:20 -0700 | [diff] [blame] | 1868 | RunValidJsonTestWithValidator( |
| 1869 | "FieldNameExtension", RECOMMENDED, |
| 1870 | R"({ |
| 1871 | "[protobuf_test_messages.proto2.extension_int32]": 1 |
| 1872 | })", |
| 1873 | [](const Json::Value& value) { |
| 1874 | return value.isMember( |
| 1875 | "[protobuf_test_messages.proto2.extension_int32]"); |
| 1876 | }, |
| 1877 | false); |
Rafi Kamal | 58d4420 | 2019-11-11 17:06:56 -0800 | [diff] [blame] | 1878 | } |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 1879 | |
Rafi Kamal | 58d4420 | 2019-11-11 17:06:56 -0800 | [diff] [blame] | 1880 | void BinaryAndJsonConformanceSuite::RunJsonTestsForNonRepeatedTypes() { |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 1881 | // Integer fields. |
| 1882 | RunValidJsonTest( |
| 1883 | "Int32FieldMaxValue", REQUIRED, |
| 1884 | R"({"optionalInt32": 2147483647})", |
| 1885 | "optional_int32: 2147483647"); |
| 1886 | RunValidJsonTest( |
| 1887 | "Int32FieldMinValue", REQUIRED, |
| 1888 | R"({"optionalInt32": -2147483648})", |
| 1889 | "optional_int32: -2147483648"); |
| 1890 | RunValidJsonTest( |
| 1891 | "Uint32FieldMaxValue", REQUIRED, |
| 1892 | R"({"optionalUint32": 4294967295})", |
| 1893 | "optional_uint32: 4294967295"); |
| 1894 | RunValidJsonTest( |
| 1895 | "Int64FieldMaxValue", REQUIRED, |
| 1896 | R"({"optionalInt64": "9223372036854775807"})", |
| 1897 | "optional_int64: 9223372036854775807"); |
| 1898 | RunValidJsonTest( |
| 1899 | "Int64FieldMinValue", REQUIRED, |
| 1900 | R"({"optionalInt64": "-9223372036854775808"})", |
| 1901 | "optional_int64: -9223372036854775808"); |
| 1902 | RunValidJsonTest( |
| 1903 | "Uint64FieldMaxValue", REQUIRED, |
| 1904 | R"({"optionalUint64": "18446744073709551615"})", |
| 1905 | "optional_uint64: 18446744073709551615"); |
| 1906 | // While not the largest Int64, this is the largest |
| 1907 | // Int64 which can be exactly represented within an |
| 1908 | // IEEE-754 64-bit float, which is the expected level |
| 1909 | // of interoperability guarantee. Larger values may |
| 1910 | // work in some implementations, but should not be |
| 1911 | // relied upon. |
| 1912 | RunValidJsonTest( |
| 1913 | "Int64FieldMaxValueNotQuoted", REQUIRED, |
| 1914 | R"({"optionalInt64": 9223372036854774784})", |
| 1915 | "optional_int64: 9223372036854774784"); |
| 1916 | RunValidJsonTest( |
| 1917 | "Int64FieldMinValueNotQuoted", REQUIRED, |
| 1918 | R"({"optionalInt64": -9223372036854775808})", |
| 1919 | "optional_int64: -9223372036854775808"); |
| 1920 | // Largest interoperable Uint64; see comment above |
| 1921 | // for Int64FieldMaxValueNotQuoted. |
| 1922 | RunValidJsonTest( |
| 1923 | "Uint64FieldMaxValueNotQuoted", REQUIRED, |
| 1924 | R"({"optionalUint64": 18446744073709549568})", |
| 1925 | "optional_uint64: 18446744073709549568"); |
| 1926 | // Values can be represented as JSON strings. |
| 1927 | RunValidJsonTest( |
| 1928 | "Int32FieldStringValue", REQUIRED, |
| 1929 | R"({"optionalInt32": "2147483647"})", |
| 1930 | "optional_int32: 2147483647"); |
| 1931 | RunValidJsonTest( |
| 1932 | "Int32FieldStringValueEscaped", REQUIRED, |
| 1933 | R"({"optionalInt32": "2\u003147483647"})", |
| 1934 | "optional_int32: 2147483647"); |
| 1935 | |
| 1936 | // Parsers reject out-of-bound integer values. |
| 1937 | ExpectParseFailureForJson( |
| 1938 | "Int32FieldTooLarge", REQUIRED, |
| 1939 | R"({"optionalInt32": 2147483648})"); |
| 1940 | ExpectParseFailureForJson( |
| 1941 | "Int32FieldTooSmall", REQUIRED, |
| 1942 | R"({"optionalInt32": -2147483649})"); |
| 1943 | ExpectParseFailureForJson( |
| 1944 | "Uint32FieldTooLarge", REQUIRED, |
| 1945 | R"({"optionalUint32": 4294967296})"); |
| 1946 | ExpectParseFailureForJson( |
| 1947 | "Int64FieldTooLarge", REQUIRED, |
| 1948 | R"({"optionalInt64": "9223372036854775808"})"); |
| 1949 | ExpectParseFailureForJson( |
| 1950 | "Int64FieldTooSmall", REQUIRED, |
| 1951 | R"({"optionalInt64": "-9223372036854775809"})"); |
| 1952 | ExpectParseFailureForJson( |
| 1953 | "Uint64FieldTooLarge", REQUIRED, |
| 1954 | R"({"optionalUint64": "18446744073709551616"})"); |
| 1955 | // Parser reject non-integer numeric values as well. |
| 1956 | ExpectParseFailureForJson( |
| 1957 | "Int32FieldNotInteger", REQUIRED, |
| 1958 | R"({"optionalInt32": 0.5})"); |
| 1959 | ExpectParseFailureForJson( |
| 1960 | "Uint32FieldNotInteger", REQUIRED, |
| 1961 | R"({"optionalUint32": 0.5})"); |
| 1962 | ExpectParseFailureForJson( |
| 1963 | "Int64FieldNotInteger", REQUIRED, |
| 1964 | R"({"optionalInt64": "0.5"})"); |
| 1965 | ExpectParseFailureForJson( |
| 1966 | "Uint64FieldNotInteger", REQUIRED, |
| 1967 | R"({"optionalUint64": "0.5"})"); |
| 1968 | |
| 1969 | // Integers but represented as float values are accepted. |
| 1970 | RunValidJsonTest( |
| 1971 | "Int32FieldFloatTrailingZero", REQUIRED, |
| 1972 | R"({"optionalInt32": 100000.000})", |
| 1973 | "optional_int32: 100000"); |
| 1974 | RunValidJsonTest( |
| 1975 | "Int32FieldExponentialFormat", REQUIRED, |
| 1976 | R"({"optionalInt32": 1e5})", |
| 1977 | "optional_int32: 100000"); |
| 1978 | RunValidJsonTest( |
| 1979 | "Int32FieldMaxFloatValue", REQUIRED, |
| 1980 | R"({"optionalInt32": 2.147483647e9})", |
| 1981 | "optional_int32: 2147483647"); |
| 1982 | RunValidJsonTest( |
| 1983 | "Int32FieldMinFloatValue", REQUIRED, |
| 1984 | R"({"optionalInt32": -2.147483648e9})", |
| 1985 | "optional_int32: -2147483648"); |
| 1986 | RunValidJsonTest( |
| 1987 | "Uint32FieldMaxFloatValue", REQUIRED, |
| 1988 | R"({"optionalUint32": 4.294967295e9})", |
| 1989 | "optional_uint32: 4294967295"); |
| 1990 | |
| 1991 | // Parser reject non-numeric values. |
| 1992 | ExpectParseFailureForJson( |
| 1993 | "Int32FieldNotNumber", REQUIRED, |
| 1994 | R"({"optionalInt32": "3x3"})"); |
| 1995 | ExpectParseFailureForJson( |
| 1996 | "Uint32FieldNotNumber", REQUIRED, |
| 1997 | R"({"optionalUint32": "3x3"})"); |
| 1998 | ExpectParseFailureForJson( |
| 1999 | "Int64FieldNotNumber", REQUIRED, |
| 2000 | R"({"optionalInt64": "3x3"})"); |
| 2001 | ExpectParseFailureForJson( |
| 2002 | "Uint64FieldNotNumber", REQUIRED, |
| 2003 | R"({"optionalUint64": "3x3"})"); |
Brian Wignall | a104dff | 2020-01-08 13:18:20 -0500 | [diff] [blame] | 2004 | // JSON does not allow "+" on numeric values. |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 2005 | ExpectParseFailureForJson( |
| 2006 | "Int32FieldPlusSign", REQUIRED, |
| 2007 | R"({"optionalInt32": +1})"); |
| 2008 | // JSON doesn't allow leading 0s. |
| 2009 | ExpectParseFailureForJson( |
| 2010 | "Int32FieldLeadingZero", REQUIRED, |
| 2011 | R"({"optionalInt32": 01})"); |
| 2012 | ExpectParseFailureForJson( |
| 2013 | "Int32FieldNegativeWithLeadingZero", REQUIRED, |
| 2014 | R"({"optionalInt32": -01})"); |
| 2015 | // String values must follow the same syntax rule. Specifically leading |
| 2016 | // or trailing spaces are not allowed. |
| 2017 | ExpectParseFailureForJson( |
| 2018 | "Int32FieldLeadingSpace", REQUIRED, |
| 2019 | R"({"optionalInt32": " 1"})"); |
| 2020 | ExpectParseFailureForJson( |
| 2021 | "Int32FieldTrailingSpace", REQUIRED, |
| 2022 | R"({"optionalInt32": "1 "})"); |
| 2023 | |
| 2024 | // 64-bit values are serialized as strings. |
| 2025 | RunValidJsonTestWithValidator( |
Joshua Haberman | 2d80a70 | 2020-05-07 16:21:50 -0700 | [diff] [blame] | 2026 | "Int64FieldBeString", RECOMMENDED, R"({"optionalInt64": 1})", |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 2027 | [](const Json::Value& value) { |
| 2028 | return value["optionalInt64"].type() == Json::stringValue && |
| 2029 | value["optionalInt64"].asString() == "1"; |
Joshua Haberman | 2d80a70 | 2020-05-07 16:21:50 -0700 | [diff] [blame] | 2030 | }, |
| 2031 | true); |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 2032 | RunValidJsonTestWithValidator( |
Joshua Haberman | 2d80a70 | 2020-05-07 16:21:50 -0700 | [diff] [blame] | 2033 | "Uint64FieldBeString", RECOMMENDED, R"({"optionalUint64": 1})", |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 2034 | [](const Json::Value& value) { |
| 2035 | return value["optionalUint64"].type() == Json::stringValue && |
| 2036 | value["optionalUint64"].asString() == "1"; |
Joshua Haberman | 2d80a70 | 2020-05-07 16:21:50 -0700 | [diff] [blame] | 2037 | }, |
| 2038 | true); |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 2039 | |
| 2040 | // Bool fields. |
| 2041 | RunValidJsonTest( |
| 2042 | "BoolFieldTrue", REQUIRED, |
| 2043 | R"({"optionalBool":true})", |
| 2044 | "optional_bool: true"); |
| 2045 | RunValidJsonTest( |
| 2046 | "BoolFieldFalse", REQUIRED, |
| 2047 | R"({"optionalBool":false})", |
| 2048 | "optional_bool: false"); |
| 2049 | |
| 2050 | // Other forms are not allowed. |
| 2051 | ExpectParseFailureForJson( |
| 2052 | "BoolFieldIntegerZero", RECOMMENDED, |
| 2053 | R"({"optionalBool":0})"); |
| 2054 | ExpectParseFailureForJson( |
| 2055 | "BoolFieldIntegerOne", RECOMMENDED, |
| 2056 | R"({"optionalBool":1})"); |
| 2057 | ExpectParseFailureForJson( |
| 2058 | "BoolFieldCamelCaseTrue", RECOMMENDED, |
| 2059 | R"({"optionalBool":True})"); |
| 2060 | ExpectParseFailureForJson( |
| 2061 | "BoolFieldCamelCaseFalse", RECOMMENDED, |
| 2062 | R"({"optionalBool":False})"); |
| 2063 | ExpectParseFailureForJson( |
| 2064 | "BoolFieldAllCapitalTrue", RECOMMENDED, |
| 2065 | R"({"optionalBool":TRUE})"); |
| 2066 | ExpectParseFailureForJson( |
| 2067 | "BoolFieldAllCapitalFalse", RECOMMENDED, |
| 2068 | R"({"optionalBool":FALSE})"); |
| 2069 | ExpectParseFailureForJson( |
| 2070 | "BoolFieldDoubleQuotedTrue", RECOMMENDED, |
| 2071 | R"({"optionalBool":"true"})"); |
| 2072 | ExpectParseFailureForJson( |
| 2073 | "BoolFieldDoubleQuotedFalse", RECOMMENDED, |
| 2074 | R"({"optionalBool":"false"})"); |
| 2075 | |
| 2076 | // Float fields. |
| 2077 | RunValidJsonTest( |
| 2078 | "FloatFieldMinPositiveValue", REQUIRED, |
| 2079 | R"({"optionalFloat": 1.175494e-38})", |
| 2080 | "optional_float: 1.175494e-38"); |
| 2081 | RunValidJsonTest( |
| 2082 | "FloatFieldMaxNegativeValue", REQUIRED, |
| 2083 | R"({"optionalFloat": -1.175494e-38})", |
| 2084 | "optional_float: -1.175494e-38"); |
| 2085 | RunValidJsonTest( |
| 2086 | "FloatFieldMaxPositiveValue", REQUIRED, |
| 2087 | R"({"optionalFloat": 3.402823e+38})", |
| 2088 | "optional_float: 3.402823e+38"); |
| 2089 | RunValidJsonTest( |
| 2090 | "FloatFieldMinNegativeValue", REQUIRED, |
| 2091 | R"({"optionalFloat": 3.402823e+38})", |
| 2092 | "optional_float: 3.402823e+38"); |
| 2093 | // Values can be quoted. |
| 2094 | RunValidJsonTest( |
| 2095 | "FloatFieldQuotedValue", REQUIRED, |
| 2096 | R"({"optionalFloat": "1"})", |
| 2097 | "optional_float: 1"); |
| 2098 | // Special values. |
| 2099 | RunValidJsonTest( |
| 2100 | "FloatFieldNan", REQUIRED, |
| 2101 | R"({"optionalFloat": "NaN"})", |
| 2102 | "optional_float: nan"); |
| 2103 | RunValidJsonTest( |
| 2104 | "FloatFieldInfinity", REQUIRED, |
| 2105 | R"({"optionalFloat": "Infinity"})", |
| 2106 | "optional_float: inf"); |
| 2107 | RunValidJsonTest( |
| 2108 | "FloatFieldNegativeInfinity", REQUIRED, |
| 2109 | R"({"optionalFloat": "-Infinity"})", |
| 2110 | "optional_float: -inf"); |
Brian Wignall | a104dff | 2020-01-08 13:18:20 -0500 | [diff] [blame] | 2111 | // Non-canonical Nan will be correctly normalized. |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 2112 | { |
| 2113 | TestAllTypesProto3 message; |
| 2114 | // IEEE floating-point standard 32-bit quiet NaN: |
| 2115 | // 0111 1111 1xxx xxxx xxxx xxxx xxxx xxxx |
| 2116 | message.set_optional_float( |
| 2117 | WireFormatLite::DecodeFloat(0x7FA12345)); |
| 2118 | RunValidJsonTestWithProtobufInput( |
| 2119 | "FloatFieldNormalizeQuietNan", REQUIRED, message, |
| 2120 | "optional_float: nan"); |
| 2121 | // IEEE floating-point standard 64-bit signaling NaN: |
| 2122 | // 1111 1111 1xxx xxxx xxxx xxxx xxxx xxxx |
| 2123 | message.set_optional_float( |
| 2124 | WireFormatLite::DecodeFloat(0xFFB54321)); |
| 2125 | RunValidJsonTestWithProtobufInput( |
| 2126 | "FloatFieldNormalizeSignalingNan", REQUIRED, message, |
| 2127 | "optional_float: nan"); |
| 2128 | } |
| 2129 | |
| 2130 | // Special values must be quoted. |
| 2131 | ExpectParseFailureForJson( |
| 2132 | "FloatFieldNanNotQuoted", RECOMMENDED, |
| 2133 | R"({"optionalFloat": NaN})"); |
| 2134 | ExpectParseFailureForJson( |
| 2135 | "FloatFieldInfinityNotQuoted", RECOMMENDED, |
| 2136 | R"({"optionalFloat": Infinity})"); |
| 2137 | ExpectParseFailureForJson( |
| 2138 | "FloatFieldNegativeInfinityNotQuoted", RECOMMENDED, |
| 2139 | R"({"optionalFloat": -Infinity})"); |
| 2140 | // Parsers should reject out-of-bound values. |
| 2141 | ExpectParseFailureForJson( |
| 2142 | "FloatFieldTooSmall", REQUIRED, |
| 2143 | R"({"optionalFloat": -3.502823e+38})"); |
| 2144 | ExpectParseFailureForJson( |
| 2145 | "FloatFieldTooLarge", REQUIRED, |
| 2146 | R"({"optionalFloat": 3.502823e+38})"); |
| 2147 | |
| 2148 | // Double fields. |
| 2149 | RunValidJsonTest( |
| 2150 | "DoubleFieldMinPositiveValue", REQUIRED, |
| 2151 | R"({"optionalDouble": 2.22507e-308})", |
| 2152 | "optional_double: 2.22507e-308"); |
| 2153 | RunValidJsonTest( |
| 2154 | "DoubleFieldMaxNegativeValue", REQUIRED, |
| 2155 | R"({"optionalDouble": -2.22507e-308})", |
| 2156 | "optional_double: -2.22507e-308"); |
| 2157 | RunValidJsonTest( |
| 2158 | "DoubleFieldMaxPositiveValue", REQUIRED, |
| 2159 | R"({"optionalDouble": 1.79769e+308})", |
| 2160 | "optional_double: 1.79769e+308"); |
| 2161 | RunValidJsonTest( |
| 2162 | "DoubleFieldMinNegativeValue", REQUIRED, |
| 2163 | R"({"optionalDouble": -1.79769e+308})", |
| 2164 | "optional_double: -1.79769e+308"); |
| 2165 | // Values can be quoted. |
| 2166 | RunValidJsonTest( |
| 2167 | "DoubleFieldQuotedValue", REQUIRED, |
| 2168 | R"({"optionalDouble": "1"})", |
| 2169 | "optional_double: 1"); |
Brian Wignall | a104dff | 2020-01-08 13:18:20 -0500 | [diff] [blame] | 2170 | // Special values. |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 2171 | RunValidJsonTest( |
| 2172 | "DoubleFieldNan", REQUIRED, |
| 2173 | R"({"optionalDouble": "NaN"})", |
| 2174 | "optional_double: nan"); |
| 2175 | RunValidJsonTest( |
| 2176 | "DoubleFieldInfinity", REQUIRED, |
| 2177 | R"({"optionalDouble": "Infinity"})", |
| 2178 | "optional_double: inf"); |
| 2179 | RunValidJsonTest( |
| 2180 | "DoubleFieldNegativeInfinity", REQUIRED, |
| 2181 | R"({"optionalDouble": "-Infinity"})", |
| 2182 | "optional_double: -inf"); |
Brian Wignall | a104dff | 2020-01-08 13:18:20 -0500 | [diff] [blame] | 2183 | // Non-canonical Nan will be correctly normalized. |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 2184 | { |
| 2185 | TestAllTypesProto3 message; |
| 2186 | message.set_optional_double( |
Joshua Haberman | b99994d | 2020-03-31 16:25:37 -0700 | [diff] [blame] | 2187 | WireFormatLite::DecodeDouble(int64{0x7FFA123456789ABC})); |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 2188 | RunValidJsonTestWithProtobufInput( |
| 2189 | "DoubleFieldNormalizeQuietNan", REQUIRED, message, |
| 2190 | "optional_double: nan"); |
| 2191 | message.set_optional_double( |
Joshua Haberman | b99994d | 2020-03-31 16:25:37 -0700 | [diff] [blame] | 2192 | WireFormatLite::DecodeDouble(uint64{0xFFFBCBA987654321})); |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 2193 | RunValidJsonTestWithProtobufInput( |
| 2194 | "DoubleFieldNormalizeSignalingNan", REQUIRED, message, |
| 2195 | "optional_double: nan"); |
| 2196 | } |
| 2197 | |
| 2198 | // Special values must be quoted. |
| 2199 | ExpectParseFailureForJson( |
| 2200 | "DoubleFieldNanNotQuoted", RECOMMENDED, |
| 2201 | R"({"optionalDouble": NaN})"); |
| 2202 | ExpectParseFailureForJson( |
| 2203 | "DoubleFieldInfinityNotQuoted", RECOMMENDED, |
| 2204 | R"({"optionalDouble": Infinity})"); |
| 2205 | ExpectParseFailureForJson( |
| 2206 | "DoubleFieldNegativeInfinityNotQuoted", RECOMMENDED, |
| 2207 | R"({"optionalDouble": -Infinity})"); |
| 2208 | |
| 2209 | // Parsers should reject out-of-bound values. |
| 2210 | ExpectParseFailureForJson( |
| 2211 | "DoubleFieldTooSmall", REQUIRED, |
| 2212 | R"({"optionalDouble": -1.89769e+308})"); |
| 2213 | ExpectParseFailureForJson( |
| 2214 | "DoubleFieldTooLarge", REQUIRED, |
| 2215 | R"({"optionalDouble": +1.89769e+308})"); |
| 2216 | |
| 2217 | // Enum fields. |
| 2218 | RunValidJsonTest( |
| 2219 | "EnumField", REQUIRED, |
| 2220 | R"({"optionalNestedEnum": "FOO"})", |
| 2221 | "optional_nested_enum: FOO"); |
Hao Nguyen | 3d46d8d | 2018-12-14 16:41:44 -0800 | [diff] [blame] | 2222 | // Enum fields with alias |
| 2223 | RunValidJsonTest( |
| 2224 | "EnumFieldWithAlias", REQUIRED, |
| 2225 | R"({"optionalAliasedEnum": "ALIAS_BAZ"})", |
| 2226 | "optional_aliased_enum: ALIAS_BAZ"); |
| 2227 | RunValidJsonTest( |
| 2228 | "EnumFieldWithAliasUseAlias", REQUIRED, |
| 2229 | R"({"optionalAliasedEnum": "QUX"})", |
| 2230 | "optional_aliased_enum: ALIAS_BAZ"); |
| 2231 | RunValidJsonTest( |
| 2232 | "EnumFieldWithAliasLowerCase", REQUIRED, |
| 2233 | R"({"optionalAliasedEnum": "qux"})", |
| 2234 | "optional_aliased_enum: ALIAS_BAZ"); |
| 2235 | RunValidJsonTest( |
| 2236 | "EnumFieldWithAliasDifferentCase", REQUIRED, |
| 2237 | R"({"optionalAliasedEnum": "bAz"})", |
| 2238 | "optional_aliased_enum: ALIAS_BAZ"); |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 2239 | // Enum values must be represented as strings. |
| 2240 | ExpectParseFailureForJson( |
| 2241 | "EnumFieldNotQuoted", REQUIRED, |
| 2242 | R"({"optionalNestedEnum": FOO})"); |
| 2243 | // Numeric values are allowed. |
| 2244 | RunValidJsonTest( |
| 2245 | "EnumFieldNumericValueZero", REQUIRED, |
| 2246 | R"({"optionalNestedEnum": 0})", |
| 2247 | "optional_nested_enum: FOO"); |
| 2248 | RunValidJsonTest( |
| 2249 | "EnumFieldNumericValueNonZero", REQUIRED, |
| 2250 | R"({"optionalNestedEnum": 1})", |
| 2251 | "optional_nested_enum: BAR"); |
| 2252 | // Unknown enum values are represented as numeric values. |
| 2253 | RunValidJsonTestWithValidator( |
Joshua Haberman | 2d80a70 | 2020-05-07 16:21:50 -0700 | [diff] [blame] | 2254 | "EnumFieldUnknownValue", REQUIRED, R"({"optionalNestedEnum": 123})", |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 2255 | [](const Json::Value& value) { |
| 2256 | return value["optionalNestedEnum"].type() == Json::intValue && |
| 2257 | value["optionalNestedEnum"].asInt() == 123; |
Joshua Haberman | 2d80a70 | 2020-05-07 16:21:50 -0700 | [diff] [blame] | 2258 | }, |
| 2259 | true); |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 2260 | |
| 2261 | // String fields. |
| 2262 | RunValidJsonTest( |
| 2263 | "StringField", REQUIRED, |
| 2264 | R"({"optionalString": "Hello world!"})", |
| 2265 | "optional_string: \"Hello world!\""); |
| 2266 | RunValidJsonTest( |
| 2267 | "StringFieldUnicode", REQUIRED, |
| 2268 | // Google in Chinese. |
| 2269 | R"({"optionalString": "谷歌"})", |
| 2270 | R"(optional_string: "谷歌")"); |
| 2271 | RunValidJsonTest( |
| 2272 | "StringFieldEscape", REQUIRED, |
| 2273 | R"({"optionalString": "\"\\\/\b\f\n\r\t"})", |
| 2274 | R"(optional_string: "\"\\/\b\f\n\r\t")"); |
| 2275 | RunValidJsonTest( |
| 2276 | "StringFieldUnicodeEscape", REQUIRED, |
| 2277 | R"({"optionalString": "\u8C37\u6B4C"})", |
| 2278 | R"(optional_string: "谷歌")"); |
| 2279 | RunValidJsonTest( |
| 2280 | "StringFieldUnicodeEscapeWithLowercaseHexLetters", REQUIRED, |
| 2281 | R"({"optionalString": "\u8c37\u6b4c"})", |
| 2282 | R"(optional_string: "谷歌")"); |
| 2283 | RunValidJsonTest( |
| 2284 | "StringFieldSurrogatePair", REQUIRED, |
| 2285 | // The character is an emoji: grinning face with smiling eyes. 😁 |
| 2286 | R"({"optionalString": "\uD83D\uDE01"})", |
| 2287 | R"(optional_string: "\xF0\x9F\x98\x81")"); |
| 2288 | |
| 2289 | // Unicode escapes must start with "\u" (lowercase u). |
| 2290 | ExpectParseFailureForJson( |
| 2291 | "StringFieldUppercaseEscapeLetter", RECOMMENDED, |
| 2292 | R"({"optionalString": "\U8C37\U6b4C"})"); |
| 2293 | ExpectParseFailureForJson( |
| 2294 | "StringFieldInvalidEscape", RECOMMENDED, |
| 2295 | R"({"optionalString": "\uXXXX\u6B4C"})"); |
| 2296 | ExpectParseFailureForJson( |
| 2297 | "StringFieldUnterminatedEscape", RECOMMENDED, |
| 2298 | R"({"optionalString": "\u8C3"})"); |
| 2299 | ExpectParseFailureForJson( |
| 2300 | "StringFieldUnpairedHighSurrogate", RECOMMENDED, |
| 2301 | R"({"optionalString": "\uD800"})"); |
| 2302 | ExpectParseFailureForJson( |
| 2303 | "StringFieldUnpairedLowSurrogate", RECOMMENDED, |
| 2304 | R"({"optionalString": "\uDC00"})"); |
| 2305 | ExpectParseFailureForJson( |
| 2306 | "StringFieldSurrogateInWrongOrder", RECOMMENDED, |
| 2307 | R"({"optionalString": "\uDE01\uD83D"})"); |
| 2308 | ExpectParseFailureForJson( |
| 2309 | "StringFieldNotAString", REQUIRED, |
| 2310 | R"({"optionalString": 12345})"); |
| 2311 | |
| 2312 | // Bytes fields. |
| 2313 | RunValidJsonTest( |
| 2314 | "BytesField", REQUIRED, |
| 2315 | R"({"optionalBytes": "AQI="})", |
| 2316 | R"(optional_bytes: "\x01\x02")"); |
| 2317 | RunValidJsonTest( |
| 2318 | "BytesFieldBase64Url", RECOMMENDED, |
| 2319 | R"({"optionalBytes": "-_"})", |
| 2320 | R"(optional_bytes: "\xfb")"); |
| 2321 | |
| 2322 | // Message fields. |
| 2323 | RunValidJsonTest( |
| 2324 | "MessageField", REQUIRED, |
| 2325 | R"({"optionalNestedMessage": {"a": 1234}})", |
| 2326 | "optional_nested_message: {a: 1234}"); |
| 2327 | |
| 2328 | // Oneof fields. |
| 2329 | ExpectParseFailureForJson( |
| 2330 | "OneofFieldDuplicate", REQUIRED, |
| 2331 | R"({"oneofUint32": 1, "oneofString": "test"})"); |
Joshua Haberman | ba38367 | 2021-04-16 09:55:03 -0700 | [diff] [blame] | 2332 | RunValidJsonTest("OneofFieldNullFirst", REQUIRED, |
| 2333 | R"({"oneofUint32": null, "oneofString": "test"})", |
| 2334 | "oneof_string: \"test\""); |
| 2335 | RunValidJsonTest("OneofFieldNullSecond", REQUIRED, |
| 2336 | R"({"oneofString": "test", "oneofUint32": null})", |
| 2337 | "oneof_string: \"test\""); |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 2338 | // Ensure zero values for oneof make it out/backs. |
| 2339 | TestAllTypesProto3 messageProto3; |
| 2340 | TestAllTypesProto2 messageProto2; |
| 2341 | TestOneofMessage(messageProto3, true); |
| 2342 | TestOneofMessage(messageProto2, false); |
| 2343 | RunValidJsonTest( |
| 2344 | "OneofZeroUint32", RECOMMENDED, |
| 2345 | R"({"oneofUint32": 0})", "oneof_uint32: 0"); |
| 2346 | RunValidJsonTest( |
| 2347 | "OneofZeroMessage", RECOMMENDED, |
| 2348 | R"({"oneofNestedMessage": {}})", "oneof_nested_message: {}"); |
| 2349 | RunValidJsonTest( |
| 2350 | "OneofZeroString", RECOMMENDED, |
| 2351 | R"({"oneofString": ""})", "oneof_string: \"\""); |
| 2352 | RunValidJsonTest( |
| 2353 | "OneofZeroBytes", RECOMMENDED, |
| 2354 | R"({"oneofBytes": ""})", "oneof_bytes: \"\""); |
| 2355 | RunValidJsonTest( |
| 2356 | "OneofZeroBool", RECOMMENDED, |
| 2357 | R"({"oneofBool": false})", "oneof_bool: false"); |
| 2358 | RunValidJsonTest( |
| 2359 | "OneofZeroUint64", RECOMMENDED, |
| 2360 | R"({"oneofUint64": 0})", "oneof_uint64: 0"); |
| 2361 | RunValidJsonTest( |
| 2362 | "OneofZeroFloat", RECOMMENDED, |
| 2363 | R"({"oneofFloat": 0.0})", "oneof_float: 0"); |
| 2364 | RunValidJsonTest( |
| 2365 | "OneofZeroDouble", RECOMMENDED, |
| 2366 | R"({"oneofDouble": 0.0})", "oneof_double: 0"); |
| 2367 | RunValidJsonTest( |
| 2368 | "OneofZeroEnum", RECOMMENDED, |
| 2369 | R"({"oneofEnum":"FOO"})", "oneof_enum: FOO"); |
| 2370 | |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 2371 | // Map fields. |
| 2372 | RunValidJsonTest( |
| 2373 | "Int32MapField", REQUIRED, |
| 2374 | R"({"mapInt32Int32": {"1": 2, "3": 4}})", |
| 2375 | "map_int32_int32: {key: 1 value: 2}" |
| 2376 | "map_int32_int32: {key: 3 value: 4}"); |
| 2377 | ExpectParseFailureForJson( |
| 2378 | "Int32MapFieldKeyNotQuoted", RECOMMENDED, |
| 2379 | R"({"mapInt32Int32": {1: 2, 3: 4}})"); |
| 2380 | RunValidJsonTest( |
| 2381 | "Uint32MapField", REQUIRED, |
| 2382 | R"({"mapUint32Uint32": {"1": 2, "3": 4}})", |
| 2383 | "map_uint32_uint32: {key: 1 value: 2}" |
| 2384 | "map_uint32_uint32: {key: 3 value: 4}"); |
| 2385 | ExpectParseFailureForJson( |
| 2386 | "Uint32MapFieldKeyNotQuoted", RECOMMENDED, |
| 2387 | R"({"mapUint32Uint32": {1: 2, 3: 4}})"); |
| 2388 | RunValidJsonTest( |
| 2389 | "Int64MapField", REQUIRED, |
| 2390 | R"({"mapInt64Int64": {"1": 2, "3": 4}})", |
| 2391 | "map_int64_int64: {key: 1 value: 2}" |
| 2392 | "map_int64_int64: {key: 3 value: 4}"); |
| 2393 | ExpectParseFailureForJson( |
| 2394 | "Int64MapFieldKeyNotQuoted", RECOMMENDED, |
| 2395 | R"({"mapInt64Int64": {1: 2, 3: 4}})"); |
| 2396 | RunValidJsonTest( |
| 2397 | "Uint64MapField", REQUIRED, |
| 2398 | R"({"mapUint64Uint64": {"1": 2, "3": 4}})", |
| 2399 | "map_uint64_uint64: {key: 1 value: 2}" |
| 2400 | "map_uint64_uint64: {key: 3 value: 4}"); |
| 2401 | ExpectParseFailureForJson( |
| 2402 | "Uint64MapFieldKeyNotQuoted", RECOMMENDED, |
| 2403 | R"({"mapUint64Uint64": {1: 2, 3: 4}})"); |
| 2404 | RunValidJsonTest( |
| 2405 | "BoolMapField", REQUIRED, |
| 2406 | R"({"mapBoolBool": {"true": true, "false": false}})", |
| 2407 | "map_bool_bool: {key: true value: true}" |
| 2408 | "map_bool_bool: {key: false value: false}"); |
| 2409 | ExpectParseFailureForJson( |
| 2410 | "BoolMapFieldKeyNotQuoted", RECOMMENDED, |
| 2411 | R"({"mapBoolBool": {true: true, false: false}})"); |
| 2412 | RunValidJsonTest( |
| 2413 | "MessageMapField", REQUIRED, |
| 2414 | R"({ |
| 2415 | "mapStringNestedMessage": { |
| 2416 | "hello": {"a": 1234}, |
| 2417 | "world": {"a": 5678} |
| 2418 | } |
| 2419 | })", |
| 2420 | R"( |
| 2421 | map_string_nested_message: { |
| 2422 | key: "hello" |
| 2423 | value: {a: 1234} |
| 2424 | } |
| 2425 | map_string_nested_message: { |
| 2426 | key: "world" |
| 2427 | value: {a: 5678} |
| 2428 | } |
| 2429 | )"); |
| 2430 | // Since Map keys are represented as JSON strings, escaping should be allowed. |
| 2431 | RunValidJsonTest( |
| 2432 | "Int32MapEscapedKey", REQUIRED, |
| 2433 | R"({"mapInt32Int32": {"\u0031": 2}})", |
| 2434 | "map_int32_int32: {key: 1 value: 2}"); |
| 2435 | RunValidJsonTest( |
| 2436 | "Int64MapEscapedKey", REQUIRED, |
| 2437 | R"({"mapInt64Int64": {"\u0031": 2}})", |
| 2438 | "map_int64_int64: {key: 1 value: 2}"); |
| 2439 | RunValidJsonTest( |
| 2440 | "BoolMapEscapedKey", REQUIRED, |
| 2441 | R"({"mapBoolBool": {"tr\u0075e": true}})", |
| 2442 | "map_bool_bool: {key: true value: true}"); |
| 2443 | |
Rafi Kamal | 58d4420 | 2019-11-11 17:06:56 -0800 | [diff] [blame] | 2444 | // http://www.rfc-editor.org/rfc/rfc7159.txt says strings have to use double |
| 2445 | // quotes. |
| 2446 | ExpectParseFailureForJson("StringFieldSingleQuoteKey", RECOMMENDED, |
| 2447 | R"({'optionalString': "Hello world!"})"); |
| 2448 | ExpectParseFailureForJson("StringFieldSingleQuoteValue", RECOMMENDED, |
| 2449 | R"({"optionalString": 'Hello world!'})"); |
| 2450 | ExpectParseFailureForJson("StringFieldSingleQuoteBoth", RECOMMENDED, |
| 2451 | R"({'optionalString': 'Hello world!'})"); |
| 2452 | } |
| 2453 | |
| 2454 | void BinaryAndJsonConformanceSuite::RunJsonTestsForRepeatedTypes() { |
| 2455 | // Repeated fields. |
| 2456 | RunValidJsonTest("PrimitiveRepeatedField", REQUIRED, |
| 2457 | R"({"repeatedInt32": [1, 2, 3, 4]})", |
| 2458 | "repeated_int32: [1, 2, 3, 4]"); |
| 2459 | RunValidJsonTest("EnumRepeatedField", REQUIRED, |
| 2460 | R"({"repeatedNestedEnum": ["FOO", "BAR", "BAZ"]})", |
| 2461 | "repeated_nested_enum: [FOO, BAR, BAZ]"); |
| 2462 | RunValidJsonTest("StringRepeatedField", REQUIRED, |
| 2463 | R"({"repeatedString": ["Hello", "world"]})", |
| 2464 | R"(repeated_string: ["Hello", "world"])"); |
| 2465 | RunValidJsonTest("BytesRepeatedField", REQUIRED, |
| 2466 | R"({"repeatedBytes": ["AAEC", "AQI="]})", |
| 2467 | R"(repeated_bytes: ["\x00\x01\x02", "\x01\x02"])"); |
| 2468 | RunValidJsonTest("MessageRepeatedField", REQUIRED, |
| 2469 | R"({"repeatedNestedMessage": [{"a": 1234}, {"a": 5678}]})", |
| 2470 | "repeated_nested_message: {a: 1234}" |
| 2471 | "repeated_nested_message: {a: 5678}"); |
| 2472 | |
| 2473 | // Repeated field elements are of incorrect type. |
| 2474 | ExpectParseFailureForJson( |
| 2475 | "RepeatedFieldWrongElementTypeExpectingIntegersGotBool", REQUIRED, |
| 2476 | R"({"repeatedInt32": [1, false, 3, 4]})"); |
| 2477 | ExpectParseFailureForJson( |
| 2478 | "RepeatedFieldWrongElementTypeExpectingIntegersGotString", REQUIRED, |
| 2479 | R"({"repeatedInt32": [1, 2, "name", 4]})"); |
| 2480 | ExpectParseFailureForJson( |
| 2481 | "RepeatedFieldWrongElementTypeExpectingIntegersGotMessage", REQUIRED, |
| 2482 | R"({"repeatedInt32": [1, 2, 3, {"a": 4}]})"); |
| 2483 | ExpectParseFailureForJson( |
| 2484 | "RepeatedFieldWrongElementTypeExpectingStringsGotInt", REQUIRED, |
| 2485 | R"({"repeatedString": ["1", 2, "3", "4"]})"); |
| 2486 | ExpectParseFailureForJson( |
| 2487 | "RepeatedFieldWrongElementTypeExpectingStringsGotBool", REQUIRED, |
| 2488 | R"({"repeatedString": ["1", "2", false, "4"]})"); |
| 2489 | ExpectParseFailureForJson( |
| 2490 | "RepeatedFieldWrongElementTypeExpectingStringsGotMessage", REQUIRED, |
| 2491 | R"({"repeatedString": ["1", 2, "3", {"a": 4}]})"); |
| 2492 | ExpectParseFailureForJson( |
| 2493 | "RepeatedFieldWrongElementTypeExpectingMessagesGotInt", REQUIRED, |
| 2494 | R"({"repeatedNestedMessage": [{"a": 1}, 2]})"); |
| 2495 | ExpectParseFailureForJson( |
| 2496 | "RepeatedFieldWrongElementTypeExpectingMessagesGotBool", REQUIRED, |
| 2497 | R"({"repeatedNestedMessage": [{"a": 1}, false]})"); |
| 2498 | ExpectParseFailureForJson( |
| 2499 | "RepeatedFieldWrongElementTypeExpectingMessagesGotString", REQUIRED, |
| 2500 | R"({"repeatedNestedMessage": [{"a": 1}, "2"]})"); |
| 2501 | // Trailing comma in the repeated field is not allowed. |
| 2502 | ExpectParseFailureForJson("RepeatedFieldTrailingComma", RECOMMENDED, |
| 2503 | R"({"repeatedInt32": [1, 2, 3, 4,]})"); |
| 2504 | ExpectParseFailureForJson("RepeatedFieldTrailingCommaWithSpace", RECOMMENDED, |
| 2505 | "{\"repeatedInt32\": [1, 2, 3, 4 ,]}"); |
| 2506 | ExpectParseFailureForJson("RepeatedFieldTrailingCommaWithSpaceCommaSpace", |
| 2507 | RECOMMENDED, |
| 2508 | "{\"repeatedInt32\": [1, 2, 3, 4 , ]}"); |
| 2509 | ExpectParseFailureForJson( |
| 2510 | "RepeatedFieldTrailingCommaWithNewlines", RECOMMENDED, |
| 2511 | "{\"repeatedInt32\": [\n 1,\n 2,\n 3,\n 4,\n]}"); |
| 2512 | } |
| 2513 | |
| 2514 | void BinaryAndJsonConformanceSuite::RunJsonTestsForNullTypes() { |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 2515 | // "null" is accepted for all fields types. |
| 2516 | RunValidJsonTest( |
| 2517 | "AllFieldAcceptNull", REQUIRED, |
| 2518 | R"({ |
| 2519 | "optionalInt32": null, |
| 2520 | "optionalInt64": null, |
| 2521 | "optionalUint32": null, |
| 2522 | "optionalUint64": null, |
| 2523 | "optionalSint32": null, |
| 2524 | "optionalSint64": null, |
| 2525 | "optionalFixed32": null, |
| 2526 | "optionalFixed64": null, |
| 2527 | "optionalSfixed32": null, |
| 2528 | "optionalSfixed64": null, |
| 2529 | "optionalFloat": null, |
| 2530 | "optionalDouble": null, |
| 2531 | "optionalBool": null, |
| 2532 | "optionalString": null, |
| 2533 | "optionalBytes": null, |
| 2534 | "optionalNestedEnum": null, |
| 2535 | "optionalNestedMessage": null, |
| 2536 | "repeatedInt32": null, |
| 2537 | "repeatedInt64": null, |
| 2538 | "repeatedUint32": null, |
| 2539 | "repeatedUint64": null, |
| 2540 | "repeatedSint32": null, |
| 2541 | "repeatedSint64": null, |
| 2542 | "repeatedFixed32": null, |
| 2543 | "repeatedFixed64": null, |
| 2544 | "repeatedSfixed32": null, |
| 2545 | "repeatedSfixed64": null, |
| 2546 | "repeatedFloat": null, |
| 2547 | "repeatedDouble": null, |
| 2548 | "repeatedBool": null, |
| 2549 | "repeatedString": null, |
| 2550 | "repeatedBytes": null, |
| 2551 | "repeatedNestedEnum": null, |
| 2552 | "repeatedNestedMessage": null, |
| 2553 | "mapInt32Int32": null, |
| 2554 | "mapBoolBool": null, |
| 2555 | "mapStringNestedMessage": null |
| 2556 | })", |
| 2557 | ""); |
| 2558 | |
| 2559 | // Repeated field elements cannot be null. |
| 2560 | ExpectParseFailureForJson( |
| 2561 | "RepeatedFieldPrimitiveElementIsNull", RECOMMENDED, |
| 2562 | R"({"repeatedInt32": [1, null, 2]})"); |
| 2563 | ExpectParseFailureForJson( |
| 2564 | "RepeatedFieldMessageElementIsNull", RECOMMENDED, |
| 2565 | R"({"repeatedNestedMessage": [{"a":1}, null, {"a":2}]})"); |
| 2566 | // Map field keys cannot be null. |
| 2567 | ExpectParseFailureForJson( |
| 2568 | "MapFieldKeyIsNull", RECOMMENDED, |
| 2569 | R"({"mapInt32Int32": {null: 1}})"); |
| 2570 | // Map field values cannot be null. |
| 2571 | ExpectParseFailureForJson( |
| 2572 | "MapFieldValueIsNull", RECOMMENDED, |
| 2573 | R"({"mapInt32Int32": {"0": null}})"); |
Rafi Kamal | 58d4420 | 2019-11-11 17:06:56 -0800 | [diff] [blame] | 2574 | } |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 2575 | |
Rafi Kamal | 58d4420 | 2019-11-11 17:06:56 -0800 | [diff] [blame] | 2576 | void BinaryAndJsonConformanceSuite::RunJsonTestsForWrapperTypes() { |
| 2577 | RunValidJsonTest("OptionalBoolWrapper", REQUIRED, |
| 2578 | R"({"optionalBoolWrapper": false})", |
| 2579 | "optional_bool_wrapper: {value: false}"); |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 2580 | RunValidJsonTest( |
| 2581 | "OptionalInt32Wrapper", REQUIRED, |
| 2582 | R"({"optionalInt32Wrapper": 0})", |
| 2583 | "optional_int32_wrapper: {value: 0}"); |
| 2584 | RunValidJsonTest( |
| 2585 | "OptionalUint32Wrapper", REQUIRED, |
| 2586 | R"({"optionalUint32Wrapper": 0})", |
| 2587 | "optional_uint32_wrapper: {value: 0}"); |
| 2588 | RunValidJsonTest( |
| 2589 | "OptionalInt64Wrapper", REQUIRED, |
| 2590 | R"({"optionalInt64Wrapper": 0})", |
| 2591 | "optional_int64_wrapper: {value: 0}"); |
| 2592 | RunValidJsonTest( |
| 2593 | "OptionalUint64Wrapper", REQUIRED, |
| 2594 | R"({"optionalUint64Wrapper": 0})", |
| 2595 | "optional_uint64_wrapper: {value: 0}"); |
| 2596 | RunValidJsonTest( |
| 2597 | "OptionalFloatWrapper", REQUIRED, |
| 2598 | R"({"optionalFloatWrapper": 0})", |
| 2599 | "optional_float_wrapper: {value: 0}"); |
| 2600 | RunValidJsonTest( |
| 2601 | "OptionalDoubleWrapper", REQUIRED, |
| 2602 | R"({"optionalDoubleWrapper": 0})", |
| 2603 | "optional_double_wrapper: {value: 0}"); |
| 2604 | RunValidJsonTest( |
| 2605 | "OptionalStringWrapper", REQUIRED, |
| 2606 | R"({"optionalStringWrapper": ""})", |
| 2607 | R"(optional_string_wrapper: {value: ""})"); |
| 2608 | RunValidJsonTest( |
| 2609 | "OptionalBytesWrapper", REQUIRED, |
| 2610 | R"({"optionalBytesWrapper": ""})", |
| 2611 | R"(optional_bytes_wrapper: {value: ""})"); |
| 2612 | RunValidJsonTest( |
| 2613 | "OptionalWrapperTypesWithNonDefaultValue", REQUIRED, |
| 2614 | R"({ |
| 2615 | "optionalBoolWrapper": true, |
| 2616 | "optionalInt32Wrapper": 1, |
| 2617 | "optionalUint32Wrapper": 1, |
| 2618 | "optionalInt64Wrapper": "1", |
| 2619 | "optionalUint64Wrapper": "1", |
| 2620 | "optionalFloatWrapper": 1, |
| 2621 | "optionalDoubleWrapper": 1, |
| 2622 | "optionalStringWrapper": "1", |
| 2623 | "optionalBytesWrapper": "AQI=" |
| 2624 | })", |
| 2625 | R"( |
| 2626 | optional_bool_wrapper: {value: true} |
| 2627 | optional_int32_wrapper: {value: 1} |
| 2628 | optional_uint32_wrapper: {value: 1} |
| 2629 | optional_int64_wrapper: {value: 1} |
| 2630 | optional_uint64_wrapper: {value: 1} |
| 2631 | optional_float_wrapper: {value: 1} |
| 2632 | optional_double_wrapper: {value: 1} |
| 2633 | optional_string_wrapper: {value: "1"} |
| 2634 | optional_bytes_wrapper: {value: "\x01\x02"} |
| 2635 | )"); |
| 2636 | RunValidJsonTest( |
| 2637 | "RepeatedBoolWrapper", REQUIRED, |
| 2638 | R"({"repeatedBoolWrapper": [true, false]})", |
| 2639 | "repeated_bool_wrapper: {value: true}" |
| 2640 | "repeated_bool_wrapper: {value: false}"); |
| 2641 | RunValidJsonTest( |
| 2642 | "RepeatedInt32Wrapper", REQUIRED, |
| 2643 | R"({"repeatedInt32Wrapper": [0, 1]})", |
| 2644 | "repeated_int32_wrapper: {value: 0}" |
| 2645 | "repeated_int32_wrapper: {value: 1}"); |
| 2646 | RunValidJsonTest( |
| 2647 | "RepeatedUint32Wrapper", REQUIRED, |
| 2648 | R"({"repeatedUint32Wrapper": [0, 1]})", |
| 2649 | "repeated_uint32_wrapper: {value: 0}" |
| 2650 | "repeated_uint32_wrapper: {value: 1}"); |
| 2651 | RunValidJsonTest( |
| 2652 | "RepeatedInt64Wrapper", REQUIRED, |
| 2653 | R"({"repeatedInt64Wrapper": [0, 1]})", |
| 2654 | "repeated_int64_wrapper: {value: 0}" |
| 2655 | "repeated_int64_wrapper: {value: 1}"); |
| 2656 | RunValidJsonTest( |
| 2657 | "RepeatedUint64Wrapper", REQUIRED, |
| 2658 | R"({"repeatedUint64Wrapper": [0, 1]})", |
| 2659 | "repeated_uint64_wrapper: {value: 0}" |
| 2660 | "repeated_uint64_wrapper: {value: 1}"); |
| 2661 | RunValidJsonTest( |
| 2662 | "RepeatedFloatWrapper", REQUIRED, |
| 2663 | R"({"repeatedFloatWrapper": [0, 1]})", |
| 2664 | "repeated_float_wrapper: {value: 0}" |
| 2665 | "repeated_float_wrapper: {value: 1}"); |
| 2666 | RunValidJsonTest( |
| 2667 | "RepeatedDoubleWrapper", REQUIRED, |
| 2668 | R"({"repeatedDoubleWrapper": [0, 1]})", |
| 2669 | "repeated_double_wrapper: {value: 0}" |
| 2670 | "repeated_double_wrapper: {value: 1}"); |
| 2671 | RunValidJsonTest( |
| 2672 | "RepeatedStringWrapper", REQUIRED, |
| 2673 | R"({"repeatedStringWrapper": ["", "AQI="]})", |
| 2674 | R"( |
| 2675 | repeated_string_wrapper: {value: ""} |
| 2676 | repeated_string_wrapper: {value: "AQI="} |
| 2677 | )"); |
| 2678 | RunValidJsonTest( |
| 2679 | "RepeatedBytesWrapper", REQUIRED, |
| 2680 | R"({"repeatedBytesWrapper": ["", "AQI="]})", |
| 2681 | R"( |
| 2682 | repeated_bytes_wrapper: {value: ""} |
| 2683 | repeated_bytes_wrapper: {value: "\x01\x02"} |
| 2684 | )"); |
| 2685 | RunValidJsonTest( |
| 2686 | "WrapperTypesWithNullValue", REQUIRED, |
| 2687 | R"({ |
| 2688 | "optionalBoolWrapper": null, |
| 2689 | "optionalInt32Wrapper": null, |
| 2690 | "optionalUint32Wrapper": null, |
| 2691 | "optionalInt64Wrapper": null, |
| 2692 | "optionalUint64Wrapper": null, |
| 2693 | "optionalFloatWrapper": null, |
| 2694 | "optionalDoubleWrapper": null, |
| 2695 | "optionalStringWrapper": null, |
| 2696 | "optionalBytesWrapper": null, |
| 2697 | "repeatedBoolWrapper": null, |
| 2698 | "repeatedInt32Wrapper": null, |
| 2699 | "repeatedUint32Wrapper": null, |
| 2700 | "repeatedInt64Wrapper": null, |
| 2701 | "repeatedUint64Wrapper": null, |
| 2702 | "repeatedFloatWrapper": null, |
| 2703 | "repeatedDoubleWrapper": null, |
| 2704 | "repeatedStringWrapper": null, |
| 2705 | "repeatedBytesWrapper": null |
| 2706 | })", |
| 2707 | ""); |
| 2708 | |
| 2709 | // Duration |
| 2710 | RunValidJsonTest( |
| 2711 | "DurationMinValue", REQUIRED, |
| 2712 | R"({"optionalDuration": "-315576000000.999999999s"})", |
| 2713 | "optional_duration: {seconds: -315576000000 nanos: -999999999}"); |
| 2714 | RunValidJsonTest( |
| 2715 | "DurationMaxValue", REQUIRED, |
| 2716 | R"({"optionalDuration": "315576000000.999999999s"})", |
| 2717 | "optional_duration: {seconds: 315576000000 nanos: 999999999}"); |
| 2718 | RunValidJsonTest( |
| 2719 | "DurationRepeatedValue", REQUIRED, |
| 2720 | R"({"repeatedDuration": ["1.5s", "-1.5s"]})", |
| 2721 | "repeated_duration: {seconds: 1 nanos: 500000000}" |
| 2722 | "repeated_duration: {seconds: -1 nanos: -500000000}"); |
| 2723 | RunValidJsonTest( |
| 2724 | "DurationNull", REQUIRED, |
| 2725 | R"({"optionalDuration": null})", |
| 2726 | ""); |
| 2727 | |
| 2728 | ExpectParseFailureForJson( |
| 2729 | "DurationMissingS", REQUIRED, |
| 2730 | R"({"optionalDuration": "1"})"); |
| 2731 | ExpectParseFailureForJson( |
| 2732 | "DurationJsonInputTooSmall", REQUIRED, |
| 2733 | R"({"optionalDuration": "-315576000001.000000000s"})"); |
| 2734 | ExpectParseFailureForJson( |
| 2735 | "DurationJsonInputTooLarge", REQUIRED, |
| 2736 | R"({"optionalDuration": "315576000001.000000000s"})"); |
| 2737 | ExpectSerializeFailureForJson( |
| 2738 | "DurationProtoInputTooSmall", REQUIRED, |
| 2739 | "optional_duration: {seconds: -315576000001 nanos: 0}"); |
| 2740 | ExpectSerializeFailureForJson( |
| 2741 | "DurationProtoInputTooLarge", REQUIRED, |
| 2742 | "optional_duration: {seconds: 315576000001 nanos: 0}"); |
| 2743 | |
| 2744 | RunValidJsonTestWithValidator( |
| 2745 | "DurationHasZeroFractionalDigit", RECOMMENDED, |
| 2746 | R"({"optionalDuration": "1.000000000s"})", |
| 2747 | [](const Json::Value& value) { |
| 2748 | return value["optionalDuration"].asString() == "1s"; |
Joshua Haberman | 2d80a70 | 2020-05-07 16:21:50 -0700 | [diff] [blame] | 2749 | }, |
| 2750 | true); |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 2751 | RunValidJsonTestWithValidator( |
| 2752 | "DurationHas3FractionalDigits", RECOMMENDED, |
| 2753 | R"({"optionalDuration": "1.010000000s"})", |
| 2754 | [](const Json::Value& value) { |
| 2755 | return value["optionalDuration"].asString() == "1.010s"; |
Joshua Haberman | 2d80a70 | 2020-05-07 16:21:50 -0700 | [diff] [blame] | 2756 | }, |
| 2757 | true); |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 2758 | RunValidJsonTestWithValidator( |
| 2759 | "DurationHas6FractionalDigits", RECOMMENDED, |
| 2760 | R"({"optionalDuration": "1.000010000s"})", |
| 2761 | [](const Json::Value& value) { |
| 2762 | return value["optionalDuration"].asString() == "1.000010s"; |
Joshua Haberman | 2d80a70 | 2020-05-07 16:21:50 -0700 | [diff] [blame] | 2763 | }, |
| 2764 | true); |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 2765 | RunValidJsonTestWithValidator( |
| 2766 | "DurationHas9FractionalDigits", RECOMMENDED, |
| 2767 | R"({"optionalDuration": "1.000000010s"})", |
| 2768 | [](const Json::Value& value) { |
| 2769 | return value["optionalDuration"].asString() == "1.000000010s"; |
Joshua Haberman | 2d80a70 | 2020-05-07 16:21:50 -0700 | [diff] [blame] | 2770 | }, |
| 2771 | true); |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 2772 | |
| 2773 | // Timestamp |
| 2774 | RunValidJsonTest( |
| 2775 | "TimestampMinValue", REQUIRED, |
| 2776 | R"({"optionalTimestamp": "0001-01-01T00:00:00Z"})", |
| 2777 | "optional_timestamp: {seconds: -62135596800}"); |
| 2778 | RunValidJsonTest( |
| 2779 | "TimestampMaxValue", REQUIRED, |
| 2780 | R"({"optionalTimestamp": "9999-12-31T23:59:59.999999999Z"})", |
| 2781 | "optional_timestamp: {seconds: 253402300799 nanos: 999999999}"); |
| 2782 | RunValidJsonTest( |
| 2783 | "TimestampRepeatedValue", REQUIRED, |
| 2784 | R"({ |
| 2785 | "repeatedTimestamp": [ |
| 2786 | "0001-01-01T00:00:00Z", |
| 2787 | "9999-12-31T23:59:59.999999999Z" |
| 2788 | ] |
| 2789 | })", |
| 2790 | "repeated_timestamp: {seconds: -62135596800}" |
| 2791 | "repeated_timestamp: {seconds: 253402300799 nanos: 999999999}"); |
Rafi Kamal | 58d4420 | 2019-11-11 17:06:56 -0800 | [diff] [blame] | 2792 | RunValidJsonTest("TimestampLeap", REQUIRED, |
| 2793 | R"({"optionalTimestamp": "1993-02-10T00:00:00.000Z"})", |
| 2794 | "optional_timestamp: {seconds: 729302400}"); |
Hao Nguyen | 51026d9 | 2019-06-26 11:01:34 -0700 | [diff] [blame] | 2795 | RunValidJsonTest("TimestampWithPositiveOffset", REQUIRED, |
| 2796 | R"({"optionalTimestamp": "1970-01-01T08:00:01+08:00"})", |
| 2797 | "optional_timestamp: {seconds: 1}"); |
| 2798 | RunValidJsonTest("TimestampWithNegativeOffset", REQUIRED, |
| 2799 | R"({"optionalTimestamp": "1969-12-31T16:00:01-08:00"})", |
| 2800 | "optional_timestamp: {seconds: 1}"); |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 2801 | RunValidJsonTest( |
| 2802 | "TimestampNull", REQUIRED, |
| 2803 | R"({"optionalTimestamp": null})", |
| 2804 | ""); |
| 2805 | |
| 2806 | ExpectParseFailureForJson( |
| 2807 | "TimestampJsonInputTooSmall", REQUIRED, |
| 2808 | R"({"optionalTimestamp": "0000-01-01T00:00:00Z"})"); |
| 2809 | ExpectParseFailureForJson( |
| 2810 | "TimestampJsonInputTooLarge", REQUIRED, |
| 2811 | R"({"optionalTimestamp": "10000-01-01T00:00:00Z"})"); |
| 2812 | ExpectParseFailureForJson( |
| 2813 | "TimestampJsonInputMissingZ", REQUIRED, |
| 2814 | R"({"optionalTimestamp": "0001-01-01T00:00:00"})"); |
| 2815 | ExpectParseFailureForJson( |
| 2816 | "TimestampJsonInputMissingT", REQUIRED, |
| 2817 | R"({"optionalTimestamp": "0001-01-01 00:00:00Z"})"); |
| 2818 | ExpectParseFailureForJson( |
| 2819 | "TimestampJsonInputLowercaseZ", REQUIRED, |
| 2820 | R"({"optionalTimestamp": "0001-01-01T00:00:00z"})"); |
| 2821 | ExpectParseFailureForJson( |
| 2822 | "TimestampJsonInputLowercaseT", REQUIRED, |
| 2823 | R"({"optionalTimestamp": "0001-01-01t00:00:00Z"})"); |
| 2824 | ExpectSerializeFailureForJson( |
| 2825 | "TimestampProtoInputTooSmall", REQUIRED, |
| 2826 | "optional_timestamp: {seconds: -62135596801}"); |
| 2827 | ExpectSerializeFailureForJson( |
| 2828 | "TimestampProtoInputTooLarge", REQUIRED, |
| 2829 | "optional_timestamp: {seconds: 253402300800}"); |
| 2830 | RunValidJsonTestWithValidator( |
| 2831 | "TimestampZeroNormalized", RECOMMENDED, |
| 2832 | R"({"optionalTimestamp": "1969-12-31T16:00:00-08:00"})", |
| 2833 | [](const Json::Value& value) { |
Rafi Kamal | 58d4420 | 2019-11-11 17:06:56 -0800 | [diff] [blame] | 2834 | return value["optionalTimestamp"].asString() == "1970-01-01T00:00:00Z"; |
Joshua Haberman | 2d80a70 | 2020-05-07 16:21:50 -0700 | [diff] [blame] | 2835 | }, |
| 2836 | true); |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 2837 | RunValidJsonTestWithValidator( |
| 2838 | "TimestampHasZeroFractionalDigit", RECOMMENDED, |
| 2839 | R"({"optionalTimestamp": "1970-01-01T00:00:00.000000000Z"})", |
| 2840 | [](const Json::Value& value) { |
Rafi Kamal | 58d4420 | 2019-11-11 17:06:56 -0800 | [diff] [blame] | 2841 | return value["optionalTimestamp"].asString() == "1970-01-01T00:00:00Z"; |
Joshua Haberman | 2d80a70 | 2020-05-07 16:21:50 -0700 | [diff] [blame] | 2842 | }, |
| 2843 | true); |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 2844 | RunValidJsonTestWithValidator( |
| 2845 | "TimestampHas3FractionalDigits", RECOMMENDED, |
| 2846 | R"({"optionalTimestamp": "1970-01-01T00:00:00.010000000Z"})", |
| 2847 | [](const Json::Value& value) { |
| 2848 | return value["optionalTimestamp"].asString() == |
Rafi Kamal | 58d4420 | 2019-11-11 17:06:56 -0800 | [diff] [blame] | 2849 | "1970-01-01T00:00:00.010Z"; |
Joshua Haberman | 2d80a70 | 2020-05-07 16:21:50 -0700 | [diff] [blame] | 2850 | }, |
| 2851 | true); |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 2852 | RunValidJsonTestWithValidator( |
| 2853 | "TimestampHas6FractionalDigits", RECOMMENDED, |
| 2854 | R"({"optionalTimestamp": "1970-01-01T00:00:00.000010000Z"})", |
| 2855 | [](const Json::Value& value) { |
| 2856 | return value["optionalTimestamp"].asString() == |
Rafi Kamal | 58d4420 | 2019-11-11 17:06:56 -0800 | [diff] [blame] | 2857 | "1970-01-01T00:00:00.000010Z"; |
Joshua Haberman | 2d80a70 | 2020-05-07 16:21:50 -0700 | [diff] [blame] | 2858 | }, |
| 2859 | true); |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 2860 | RunValidJsonTestWithValidator( |
| 2861 | "TimestampHas9FractionalDigits", RECOMMENDED, |
| 2862 | R"({"optionalTimestamp": "1970-01-01T00:00:00.000000010Z"})", |
| 2863 | [](const Json::Value& value) { |
| 2864 | return value["optionalTimestamp"].asString() == |
Rafi Kamal | 58d4420 | 2019-11-11 17:06:56 -0800 | [diff] [blame] | 2865 | "1970-01-01T00:00:00.000000010Z"; |
Joshua Haberman | 2d80a70 | 2020-05-07 16:21:50 -0700 | [diff] [blame] | 2866 | }, |
| 2867 | true); |
Rafi Kamal | 58d4420 | 2019-11-11 17:06:56 -0800 | [diff] [blame] | 2868 | } |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 2869 | |
Rafi Kamal | 58d4420 | 2019-11-11 17:06:56 -0800 | [diff] [blame] | 2870 | void BinaryAndJsonConformanceSuite::RunJsonTestsForFieldMask() { |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 2871 | RunValidJsonTest( |
| 2872 | "FieldMask", REQUIRED, |
| 2873 | R"({"optionalFieldMask": "foo,barBaz"})", |
| 2874 | R"(optional_field_mask: {paths: "foo" paths: "bar_baz"})"); |
Paul Yang | 7f42d6d | 2019-01-22 15:35:12 -0800 | [diff] [blame] | 2875 | RunValidJsonTest( |
| 2876 | "EmptyFieldMask", REQUIRED, |
| 2877 | R"({"optionalFieldMask": ""})", |
| 2878 | R"(optional_field_mask: {})"); |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 2879 | ExpectParseFailureForJson( |
| 2880 | "FieldMaskInvalidCharacter", RECOMMENDED, |
| 2881 | R"({"optionalFieldMask": "foo,bar_bar"})"); |
| 2882 | ExpectSerializeFailureForJson( |
| 2883 | "FieldMaskPathsDontRoundTrip", RECOMMENDED, |
| 2884 | R"(optional_field_mask: {paths: "fooBar"})"); |
| 2885 | ExpectSerializeFailureForJson( |
| 2886 | "FieldMaskNumbersDontRoundTrip", RECOMMENDED, |
| 2887 | R"(optional_field_mask: {paths: "foo_3_bar"})"); |
| 2888 | ExpectSerializeFailureForJson( |
| 2889 | "FieldMaskTooManyUnderscore", RECOMMENDED, |
| 2890 | R"(optional_field_mask: {paths: "foo__bar"})"); |
Rafi Kamal | 58d4420 | 2019-11-11 17:06:56 -0800 | [diff] [blame] | 2891 | } |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 2892 | |
Rafi Kamal | 58d4420 | 2019-11-11 17:06:56 -0800 | [diff] [blame] | 2893 | void BinaryAndJsonConformanceSuite::RunJsonTestsForStruct() { |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 2894 | RunValidJsonTest( |
| 2895 | "Struct", REQUIRED, |
| 2896 | R"({ |
| 2897 | "optionalStruct": { |
| 2898 | "nullValue": null, |
| 2899 | "intValue": 1234, |
| 2900 | "boolValue": true, |
| 2901 | "doubleValue": 1234.5678, |
| 2902 | "stringValue": "Hello world!", |
| 2903 | "listValue": [1234, "5678"], |
| 2904 | "objectValue": { |
| 2905 | "value": 0 |
| 2906 | } |
| 2907 | } |
| 2908 | })", |
| 2909 | R"( |
| 2910 | optional_struct: { |
| 2911 | fields: { |
| 2912 | key: "nullValue" |
| 2913 | value: {null_value: NULL_VALUE} |
| 2914 | } |
| 2915 | fields: { |
| 2916 | key: "intValue" |
| 2917 | value: {number_value: 1234} |
| 2918 | } |
| 2919 | fields: { |
| 2920 | key: "boolValue" |
| 2921 | value: {bool_value: true} |
| 2922 | } |
| 2923 | fields: { |
| 2924 | key: "doubleValue" |
| 2925 | value: {number_value: 1234.5678} |
| 2926 | } |
| 2927 | fields: { |
| 2928 | key: "stringValue" |
| 2929 | value: {string_value: "Hello world!"} |
| 2930 | } |
| 2931 | fields: { |
| 2932 | key: "listValue" |
| 2933 | value: { |
| 2934 | list_value: { |
| 2935 | values: { |
| 2936 | number_value: 1234 |
| 2937 | } |
| 2938 | values: { |
| 2939 | string_value: "5678" |
| 2940 | } |
| 2941 | } |
| 2942 | } |
| 2943 | } |
| 2944 | fields: { |
| 2945 | key: "objectValue" |
| 2946 | value: { |
| 2947 | struct_value: { |
| 2948 | fields: { |
| 2949 | key: "value" |
| 2950 | value: { |
| 2951 | number_value: 0 |
| 2952 | } |
| 2953 | } |
| 2954 | } |
| 2955 | } |
| 2956 | } |
| 2957 | } |
| 2958 | )"); |
Paul Yang | a186808 | 2019-03-10 17:33:46 -0700 | [diff] [blame] | 2959 | RunValidJsonTest( |
| 2960 | "StructWithEmptyListValue", REQUIRED, |
| 2961 | R"({ |
| 2962 | "optionalStruct": { |
| 2963 | "listValue": [] |
| 2964 | } |
| 2965 | })", |
| 2966 | R"( |
| 2967 | optional_struct: { |
| 2968 | fields: { |
| 2969 | key: "listValue" |
| 2970 | value: { |
| 2971 | list_value: { |
| 2972 | } |
| 2973 | } |
| 2974 | } |
| 2975 | } |
| 2976 | )"); |
Rafi Kamal | 58d4420 | 2019-11-11 17:06:56 -0800 | [diff] [blame] | 2977 | } |
| 2978 | |
| 2979 | void BinaryAndJsonConformanceSuite::RunJsonTestsForValue() { |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 2980 | RunValidJsonTest( |
| 2981 | "ValueAcceptInteger", REQUIRED, |
| 2982 | R"({"optionalValue": 1})", |
| 2983 | "optional_value: { number_value: 1}"); |
| 2984 | RunValidJsonTest( |
| 2985 | "ValueAcceptFloat", REQUIRED, |
| 2986 | R"({"optionalValue": 1.5})", |
| 2987 | "optional_value: { number_value: 1.5}"); |
| 2988 | RunValidJsonTest( |
| 2989 | "ValueAcceptBool", REQUIRED, |
| 2990 | R"({"optionalValue": false})", |
| 2991 | "optional_value: { bool_value: false}"); |
| 2992 | RunValidJsonTest( |
| 2993 | "ValueAcceptNull", REQUIRED, |
| 2994 | R"({"optionalValue": null})", |
| 2995 | "optional_value: { null_value: NULL_VALUE}"); |
| 2996 | RunValidJsonTest( |
| 2997 | "ValueAcceptString", REQUIRED, |
| 2998 | R"({"optionalValue": "hello"})", |
| 2999 | R"(optional_value: { string_value: "hello"})"); |
| 3000 | RunValidJsonTest( |
| 3001 | "ValueAcceptList", REQUIRED, |
| 3002 | R"({"optionalValue": [0, "hello"]})", |
| 3003 | R"( |
| 3004 | optional_value: { |
| 3005 | list_value: { |
| 3006 | values: { |
| 3007 | number_value: 0 |
| 3008 | } |
| 3009 | values: { |
| 3010 | string_value: "hello" |
| 3011 | } |
| 3012 | } |
| 3013 | } |
| 3014 | )"); |
| 3015 | RunValidJsonTest( |
| 3016 | "ValueAcceptObject", REQUIRED, |
| 3017 | R"({"optionalValue": {"value": 1}})", |
| 3018 | R"( |
| 3019 | optional_value: { |
| 3020 | struct_value: { |
| 3021 | fields: { |
| 3022 | key: "value" |
| 3023 | value: { |
| 3024 | number_value: 1 |
| 3025 | } |
| 3026 | } |
| 3027 | } |
| 3028 | } |
| 3029 | )"); |
Paul Yang | 4b145b1 | 2019-03-12 10:56:58 -0700 | [diff] [blame] | 3030 | RunValidJsonTest( |
| 3031 | "RepeatedValue", REQUIRED, |
| 3032 | R"({ |
| 3033 | "repeatedValue": [["a"]] |
| 3034 | })", |
| 3035 | R"( |
| 3036 | repeated_value: [ |
| 3037 | { |
| 3038 | list_value: { |
| 3039 | values: [ |
| 3040 | { string_value: "a"} |
| 3041 | ] |
| 3042 | } |
| 3043 | } |
| 3044 | ] |
| 3045 | )"); |
| 3046 | RunValidJsonTest( |
| 3047 | "RepeatedListValue", REQUIRED, |
| 3048 | R"({ |
| 3049 | "repeatedListValue": [["a"]] |
| 3050 | })", |
| 3051 | R"( |
| 3052 | repeated_list_value: [ |
| 3053 | { |
| 3054 | values: [ |
| 3055 | { string_value: "a"} |
| 3056 | ] |
| 3057 | } |
| 3058 | ] |
| 3059 | )"); |
Joshua Haberman | dfab275 | 2020-06-18 15:47:49 -0700 | [diff] [blame] | 3060 | RunValidJsonTestWithValidator( |
| 3061 | "NullValueInOtherOneofOldFormat", RECOMMENDED, |
| 3062 | R"({"oneofNullValue": "NULL_VALUE"})", |
| 3063 | [](const Json::Value& value) { |
| 3064 | return (value.isMember("oneofNullValue") && |
| 3065 | value["oneofNullValue"].isNull()); |
| 3066 | }, |
| 3067 | true); |
| 3068 | RunValidJsonTestWithValidator( |
| 3069 | "NullValueInOtherOneofNewFormat", RECOMMENDED, |
| 3070 | R"({"oneofNullValue": null})", |
| 3071 | [](const Json::Value& value) { |
| 3072 | return (value.isMember("oneofNullValue") && |
| 3073 | value["oneofNullValue"].isNull()); |
| 3074 | }, |
| 3075 | true); |
| 3076 | RunValidJsonTestWithValidator( |
| 3077 | "NullValueInNormalMessage", RECOMMENDED, |
| 3078 | R"({"optionalNullValue": null})", |
| 3079 | [](const Json::Value& value) { |
| 3080 | return value.empty(); |
| 3081 | }, |
| 3082 | true); |
Rafi Kamal | 58d4420 | 2019-11-11 17:06:56 -0800 | [diff] [blame] | 3083 | } |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 3084 | |
Rafi Kamal | 58d4420 | 2019-11-11 17:06:56 -0800 | [diff] [blame] | 3085 | void BinaryAndJsonConformanceSuite::RunJsonTestsForAny() { |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 3086 | RunValidJsonTest( |
| 3087 | "Any", REQUIRED, |
| 3088 | R"({ |
| 3089 | "optionalAny": { |
| 3090 | "@type": "type.googleapis.com/protobuf_test_messages.proto3.TestAllTypesProto3", |
| 3091 | "optionalInt32": 12345 |
| 3092 | } |
| 3093 | })", |
| 3094 | R"( |
| 3095 | optional_any: { |
| 3096 | [type.googleapis.com/protobuf_test_messages.proto3.TestAllTypesProto3] { |
| 3097 | optional_int32: 12345 |
| 3098 | } |
| 3099 | } |
| 3100 | )"); |
| 3101 | RunValidJsonTest( |
| 3102 | "AnyNested", REQUIRED, |
| 3103 | R"({ |
| 3104 | "optionalAny": { |
| 3105 | "@type": "type.googleapis.com/google.protobuf.Any", |
| 3106 | "value": { |
| 3107 | "@type": "type.googleapis.com/protobuf_test_messages.proto3.TestAllTypesProto3", |
| 3108 | "optionalInt32": 12345 |
| 3109 | } |
| 3110 | } |
| 3111 | })", |
| 3112 | R"( |
| 3113 | optional_any: { |
| 3114 | [type.googleapis.com/google.protobuf.Any] { |
| 3115 | [type.googleapis.com/protobuf_test_messages.proto3.TestAllTypesProto3] { |
| 3116 | optional_int32: 12345 |
| 3117 | } |
| 3118 | } |
| 3119 | } |
| 3120 | )"); |
| 3121 | // The special "@type" tag is not required to appear first. |
| 3122 | RunValidJsonTest( |
| 3123 | "AnyUnorderedTypeTag", REQUIRED, |
| 3124 | R"({ |
| 3125 | "optionalAny": { |
| 3126 | "optionalInt32": 12345, |
| 3127 | "@type": "type.googleapis.com/protobuf_test_messages.proto3.TestAllTypesProto3" |
| 3128 | } |
| 3129 | })", |
| 3130 | R"( |
| 3131 | optional_any: { |
| 3132 | [type.googleapis.com/protobuf_test_messages.proto3.TestAllTypesProto3] { |
| 3133 | optional_int32: 12345 |
| 3134 | } |
| 3135 | } |
| 3136 | )"); |
| 3137 | // Well-known types in Any. |
| 3138 | RunValidJsonTest( |
| 3139 | "AnyWithInt32ValueWrapper", REQUIRED, |
| 3140 | R"({ |
| 3141 | "optionalAny": { |
| 3142 | "@type": "type.googleapis.com/google.protobuf.Int32Value", |
| 3143 | "value": 12345 |
| 3144 | } |
| 3145 | })", |
| 3146 | R"( |
| 3147 | optional_any: { |
| 3148 | [type.googleapis.com/google.protobuf.Int32Value] { |
| 3149 | value: 12345 |
| 3150 | } |
| 3151 | } |
| 3152 | )"); |
| 3153 | RunValidJsonTest( |
| 3154 | "AnyWithDuration", REQUIRED, |
| 3155 | R"({ |
| 3156 | "optionalAny": { |
| 3157 | "@type": "type.googleapis.com/google.protobuf.Duration", |
| 3158 | "value": "1.5s" |
| 3159 | } |
| 3160 | })", |
| 3161 | R"( |
| 3162 | optional_any: { |
| 3163 | [type.googleapis.com/google.protobuf.Duration] { |
| 3164 | seconds: 1 |
| 3165 | nanos: 500000000 |
| 3166 | } |
| 3167 | } |
| 3168 | )"); |
| 3169 | RunValidJsonTest( |
| 3170 | "AnyWithTimestamp", REQUIRED, |
| 3171 | R"({ |
| 3172 | "optionalAny": { |
| 3173 | "@type": "type.googleapis.com/google.protobuf.Timestamp", |
| 3174 | "value": "1970-01-01T00:00:00Z" |
| 3175 | } |
| 3176 | })", |
| 3177 | R"( |
| 3178 | optional_any: { |
| 3179 | [type.googleapis.com/google.protobuf.Timestamp] { |
| 3180 | seconds: 0 |
| 3181 | nanos: 0 |
| 3182 | } |
| 3183 | } |
| 3184 | )"); |
| 3185 | RunValidJsonTest( |
| 3186 | "AnyWithFieldMask", REQUIRED, |
| 3187 | R"({ |
| 3188 | "optionalAny": { |
| 3189 | "@type": "type.googleapis.com/google.protobuf.FieldMask", |
| 3190 | "value": "foo,barBaz" |
| 3191 | } |
| 3192 | })", |
| 3193 | R"( |
| 3194 | optional_any: { |
| 3195 | [type.googleapis.com/google.protobuf.FieldMask] { |
| 3196 | paths: ["foo", "bar_baz"] |
| 3197 | } |
| 3198 | } |
| 3199 | )"); |
| 3200 | RunValidJsonTest( |
| 3201 | "AnyWithStruct", REQUIRED, |
| 3202 | R"({ |
| 3203 | "optionalAny": { |
| 3204 | "@type": "type.googleapis.com/google.protobuf.Struct", |
| 3205 | "value": { |
| 3206 | "foo": 1 |
| 3207 | } |
| 3208 | } |
| 3209 | })", |
| 3210 | R"( |
| 3211 | optional_any: { |
| 3212 | [type.googleapis.com/google.protobuf.Struct] { |
| 3213 | fields: { |
| 3214 | key: "foo" |
| 3215 | value: { |
| 3216 | number_value: 1 |
| 3217 | } |
| 3218 | } |
| 3219 | } |
| 3220 | } |
| 3221 | )"); |
| 3222 | RunValidJsonTest( |
| 3223 | "AnyWithValueForJsonObject", REQUIRED, |
| 3224 | R"({ |
| 3225 | "optionalAny": { |
| 3226 | "@type": "type.googleapis.com/google.protobuf.Value", |
| 3227 | "value": { |
| 3228 | "foo": 1 |
| 3229 | } |
| 3230 | } |
| 3231 | })", |
| 3232 | R"( |
| 3233 | optional_any: { |
| 3234 | [type.googleapis.com/google.protobuf.Value] { |
| 3235 | struct_value: { |
| 3236 | fields: { |
| 3237 | key: "foo" |
| 3238 | value: { |
| 3239 | number_value: 1 |
| 3240 | } |
| 3241 | } |
| 3242 | } |
| 3243 | } |
| 3244 | } |
| 3245 | )"); |
| 3246 | RunValidJsonTest( |
| 3247 | "AnyWithValueForInteger", REQUIRED, |
| 3248 | R"({ |
| 3249 | "optionalAny": { |
| 3250 | "@type": "type.googleapis.com/google.protobuf.Value", |
| 3251 | "value": 1 |
| 3252 | } |
| 3253 | })", |
| 3254 | R"( |
| 3255 | optional_any: { |
| 3256 | [type.googleapis.com/google.protobuf.Value] { |
| 3257 | number_value: 1 |
| 3258 | } |
| 3259 | } |
| 3260 | )"); |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 3261 | } |
| 3262 | |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 3263 | } // namespace protobuf |
| 3264 | } // namespace google |