| Index: third_party/protobuf/conformance/conformance_test.cc
|
| diff --git a/third_party/protobuf/conformance/conformance_test.cc b/third_party/protobuf/conformance/conformance_test.cc
|
| index fc0605bfc4a20bcd9fc81c3a4b1b20478fc52a14..dd266d15ba703e276cac94f660fd277f4c3eeb8b 100644
|
| --- a/third_party/protobuf/conformance/conformance_test.cc
|
| +++ b/third_party/protobuf/conformance/conformance_test.cc
|
| @@ -30,14 +30,17 @@
|
|
|
| #include <stdarg.h>
|
| #include <string>
|
| +#include <fstream>
|
|
|
| #include "conformance.pb.h"
|
| #include "conformance_test.h"
|
| +#include <google/protobuf/test_messages_proto3.pb.h>
|
| +
|
| #include <google/protobuf/stubs/common.h>
|
| #include <google/protobuf/stubs/stringprintf.h>
|
| #include <google/protobuf/text_format.h>
|
| -#include <google/protobuf/util/json_util.h>
|
| #include <google/protobuf/util/field_comparator.h>
|
| +#include <google/protobuf/util/json_util.h>
|
| #include <google/protobuf/util/message_differencer.h>
|
| #include <google/protobuf/util/type_resolver_util.h>
|
| #include <google/protobuf/wire_format_lite.h>
|
| @@ -46,7 +49,6 @@
|
|
|
| using conformance::ConformanceRequest;
|
| using conformance::ConformanceResponse;
|
| -using conformance::TestAllTypes;
|
| using conformance::WireFormat;
|
| using google::protobuf::Descriptor;
|
| using google::protobuf::FieldDescriptor;
|
| @@ -57,6 +59,7 @@ using google::protobuf::util::JsonToBinaryString;
|
| using google::protobuf::util::MessageDifferencer;
|
| using google::protobuf::util::NewTypeResolverForDescriptorPool;
|
| using google::protobuf::util::Status;
|
| +using protobuf_test_messages::proto3::TestAllTypes;
|
| using std::string;
|
|
|
| namespace {
|
| @@ -129,8 +132,8 @@ string fixed32(void *data) { return string(static_cast<char*>(data), 4); }
|
| string fixed64(void *data) { return string(static_cast<char*>(data), 8); }
|
|
|
| string delim(const string& buf) { return cat(varint(buf.size()), buf); }
|
| -string uint32(uint32_t u32) { return fixed32(&u32); }
|
| -string uint64(uint64_t u64) { return fixed64(&u64); }
|
| +string u32(uint32_t u32) { return fixed32(&u32); }
|
| +string u64(uint64_t u64) { return fixed64(&u64); }
|
| string flt(float f) { return fixed32(&f); }
|
| string dbl(double d) { return fixed64(&d); }
|
| string zz32(int32_t x) { return varint(WireFormatLite::ZigZagEncode32(x)); }
|
| @@ -146,16 +149,17 @@ string submsg(uint32_t fn, const string& buf) {
|
|
|
| #define UNKNOWN_FIELD 666
|
|
|
| -uint32_t GetFieldNumberForType(FieldDescriptor::Type type, bool repeated) {
|
| +const FieldDescriptor* GetFieldForType(FieldDescriptor::Type type,
|
| + bool repeated) {
|
| const Descriptor* d = TestAllTypes().GetDescriptor();
|
| for (int i = 0; i < d->field_count(); i++) {
|
| const FieldDescriptor* f = d->field(i);
|
| if (f->type() == type && f->is_repeated() == repeated) {
|
| - return f->number();
|
| + return f;
|
| }
|
| }
|
| GOOGLE_LOG(FATAL) << "Couldn't find field with type " << (int)type;
|
| - return 0;
|
| + return nullptr;
|
| }
|
|
|
| string UpperCase(string str) {
|
| @@ -182,6 +186,7 @@ void ConformanceTestSuite::ReportSuccess(const string& test_name) {
|
| }
|
|
|
| void ConformanceTestSuite::ReportFailure(const string& test_name,
|
| + ConformanceLevel level,
|
| const ConformanceRequest& request,
|
| const ConformanceResponse& response,
|
| const char* fmt, ...) {
|
| @@ -189,6 +194,8 @@ void ConformanceTestSuite::ReportFailure(const string& test_name,
|
| expected_failures_++;
|
| if (!verbose_)
|
| return;
|
| + } else if (level == RECOMMENDED && !enforce_recommended_) {
|
| + StringAppendF(&output_, "WARNING, test=%s: ", test_name.c_str());
|
| } else {
|
| StringAppendF(&output_, "ERROR, test=%s: ", test_name.c_str());
|
| unexpected_failing_tests_.insert(test_name);
|
| @@ -213,6 +220,15 @@ void ConformanceTestSuite::ReportSkip(const string& test_name,
|
| skipped_.insert(test_name);
|
| }
|
|
|
| +string ConformanceTestSuite::ConformanceLevelToString(ConformanceLevel level) {
|
| + switch (level) {
|
| + case REQUIRED: return "Required";
|
| + case RECOMMENDED: return "Recommended";
|
| + }
|
| + GOOGLE_LOG(FATAL) << "Unknown value: " << level;
|
| + return "";
|
| +}
|
| +
|
| void ConformanceTestSuite::RunTest(const string& test_name,
|
| const ConformanceRequest& request,
|
| ConformanceResponse* response) {
|
| @@ -240,8 +256,9 @@ void ConformanceTestSuite::RunTest(const string& test_name,
|
| }
|
|
|
| void ConformanceTestSuite::RunValidInputTest(
|
| - const string& test_name, const string& input, WireFormat input_format,
|
| - const string& equivalent_text_format, WireFormat requested_output) {
|
| + const string& test_name, ConformanceLevel level, const string& input,
|
| + WireFormat input_format, const string& equivalent_text_format,
|
| + WireFormat requested_output) {
|
| TestAllTypes reference_message;
|
| GOOGLE_CHECK(
|
| TextFormat::ParseFromString(equivalent_text_format, &reference_message))
|
| @@ -271,11 +288,16 @@ void ConformanceTestSuite::RunValidInputTest(
|
| TestAllTypes test_message;
|
|
|
| switch (response.result_case()) {
|
| + case ConformanceResponse::RESULT_NOT_SET:
|
| + ReportFailure(test_name, level, request, response,
|
| + "Response didn't have any field in the Response.");
|
| + return;
|
| +
|
| case ConformanceResponse::kParseError:
|
| case ConformanceResponse::kRuntimeError:
|
| case ConformanceResponse::kSerializeError:
|
| - ReportFailure(test_name, request, response,
|
| - "Failed to parse JSON input or produce JSON output.");
|
| + ReportFailure(test_name, level, request, response,
|
| + "Failed to parse input or produce output.");
|
| return;
|
|
|
| case ConformanceResponse::kSkipped:
|
| @@ -285,7 +307,7 @@ void ConformanceTestSuite::RunValidInputTest(
|
| case ConformanceResponse::kJsonPayload: {
|
| if (requested_output != conformance::JSON) {
|
| ReportFailure(
|
| - test_name, request, response,
|
| + test_name, level, request, response,
|
| "Test was asked for protobuf output but provided JSON instead.");
|
| return;
|
| }
|
| @@ -294,13 +316,13 @@ void ConformanceTestSuite::RunValidInputTest(
|
| JsonToBinaryString(type_resolver_.get(), type_url_,
|
| response.json_payload(), &binary_protobuf);
|
| if (!status.ok()) {
|
| - ReportFailure(test_name, request, response,
|
| + ReportFailure(test_name, level, request, response,
|
| "JSON output we received from test was unparseable.");
|
| return;
|
| }
|
|
|
| if (!test_message.ParseFromString(binary_protobuf)) {
|
| - ReportFailure(test_name, request, response,
|
| + ReportFailure(test_name, level, request, response,
|
| "INTERNAL ERROR: internal JSON->protobuf transcode "
|
| "yielded unparseable proto.");
|
| return;
|
| @@ -312,13 +334,13 @@ void ConformanceTestSuite::RunValidInputTest(
|
| case ConformanceResponse::kProtobufPayload: {
|
| if (requested_output != conformance::PROTOBUF) {
|
| ReportFailure(
|
| - test_name, request, response,
|
| + test_name, level, request, response,
|
| "Test was asked for JSON output but provided protobuf instead.");
|
| return;
|
| }
|
|
|
| if (!test_message.ParseFromString(response.protobuf_payload())) {
|
| - ReportFailure(test_name, request, response,
|
| + ReportFailure(test_name, level, request, response,
|
| "Protobuf output we received from test was unparseable.");
|
| return;
|
| }
|
| @@ -341,7 +363,7 @@ void ConformanceTestSuite::RunValidInputTest(
|
| if (differencer.Compare(reference_message, test_message)) {
|
| ReportSuccess(test_name);
|
| } else {
|
| - ReportFailure(test_name, request, response,
|
| + ReportFailure(test_name, level, request, response,
|
| "Output was not equivalent to reference message: %s.",
|
| differences.c_str());
|
| }
|
| @@ -349,11 +371,12 @@ void ConformanceTestSuite::RunValidInputTest(
|
|
|
| // Expect that this precise protobuf will cause a parse error.
|
| void ConformanceTestSuite::ExpectParseFailureForProto(
|
| - const string& proto, const string& test_name) {
|
| + const string& proto, const string& test_name, ConformanceLevel level) {
|
| ConformanceRequest request;
|
| ConformanceResponse response;
|
| request.set_protobuf_payload(proto);
|
| - string effective_test_name = "ProtobufInput." + test_name;
|
| + string effective_test_name = ConformanceLevelToString(level) +
|
| + ".ProtobufInput." + test_name;
|
|
|
| // We don't expect output, but if the program erroneously accepts the protobuf
|
| // we let it send its response as this. We must not leave it unspecified.
|
| @@ -365,7 +388,7 @@ void ConformanceTestSuite::ExpectParseFailureForProto(
|
| } else if (response.result_case() == ConformanceResponse::kSkipped) {
|
| ReportSkip(effective_test_name, request, response);
|
| } else {
|
| - ReportFailure(effective_test_name, request, response,
|
| + ReportFailure(effective_test_name, level, request, response,
|
| "Should have failed to parse, but didn't.");
|
| }
|
| }
|
| @@ -376,27 +399,49 @@ void ConformanceTestSuite::ExpectParseFailureForProto(
|
| //
|
| // TODO(haberman): implement the second of these.
|
| void ConformanceTestSuite::ExpectHardParseFailureForProto(
|
| - const string& proto, const string& test_name) {
|
| - return ExpectParseFailureForProto(proto, test_name);
|
| + const string& proto, const string& test_name, ConformanceLevel level) {
|
| + return ExpectParseFailureForProto(proto, test_name, level);
|
| }
|
|
|
| void ConformanceTestSuite::RunValidJsonTest(
|
| - const string& test_name, const string& input_json,
|
| + const string& test_name, ConformanceLevel level, const string& input_json,
|
| const string& equivalent_text_format) {
|
| - RunValidInputTest("JsonInput." + test_name + ".ProtobufOutput", input_json,
|
| - conformance::JSON, equivalent_text_format,
|
| - conformance::PROTOBUF);
|
| - RunValidInputTest("JsonInput." + test_name + ".JsonOutput", input_json,
|
| - conformance::JSON, equivalent_text_format,
|
| - conformance::JSON);
|
| + RunValidInputTest(
|
| + ConformanceLevelToString(level) + ".JsonInput." + test_name +
|
| + ".ProtobufOutput", level, input_json, conformance::JSON,
|
| + equivalent_text_format, conformance::PROTOBUF);
|
| + RunValidInputTest(
|
| + ConformanceLevelToString(level) + ".JsonInput." + test_name +
|
| + ".JsonOutput", level, input_json, conformance::JSON,
|
| + equivalent_text_format, conformance::JSON);
|
| }
|
|
|
| void ConformanceTestSuite::RunValidJsonTestWithProtobufInput(
|
| - const string& test_name, const TestAllTypes& input,
|
| + const string& test_name, ConformanceLevel level, const TestAllTypes& input,
|
| const string& equivalent_text_format) {
|
| - RunValidInputTest("ProtobufInput." + test_name + ".JsonOutput",
|
| - input.SerializeAsString(), conformance::PROTOBUF,
|
| - equivalent_text_format, conformance::JSON);
|
| + RunValidInputTest(
|
| + ConformanceLevelToString(level) + ".ProtobufInput." + test_name +
|
| + ".JsonOutput", level, input.SerializeAsString(), conformance::PROTOBUF,
|
| + equivalent_text_format, conformance::JSON);
|
| +}
|
| +
|
| +void ConformanceTestSuite::RunValidProtobufTest(
|
| + const string& test_name, ConformanceLevel level,
|
| + const string& input_protobuf, const string& equivalent_text_format) {
|
| + RunValidInputTest(
|
| + ConformanceLevelToString(level) + ".ProtobufInput." + test_name +
|
| + ".ProtobufOutput", level, input_protobuf, conformance::PROTOBUF,
|
| + equivalent_text_format, conformance::PROTOBUF);
|
| + RunValidInputTest(
|
| + ConformanceLevelToString(level) + ".ProtobufInput." + test_name +
|
| + ".JsonOutput", level, input_protobuf, conformance::PROTOBUF,
|
| + equivalent_text_format, conformance::JSON);
|
| +}
|
| +
|
| +void ConformanceTestSuite::RunValidProtobufTestWithMessage(
|
| + const string& test_name, ConformanceLevel level, const TestAllTypes& input,
|
| + const string& equivalent_text_format) {
|
| + RunValidProtobufTest(test_name, level, input.SerializeAsString(), equivalent_text_format);
|
| }
|
|
|
| // According to proto3 JSON specification, JSON serializers follow more strict
|
| @@ -405,14 +450,15 @@ void ConformanceTestSuite::RunValidJsonTestWithProtobufInput(
|
| // method allows strict checking on a proto3 JSON serializer by inspecting
|
| // the JSON output directly.
|
| void ConformanceTestSuite::RunValidJsonTestWithValidator(
|
| - const string& test_name, const string& input_json,
|
| + const string& test_name, ConformanceLevel level, const string& input_json,
|
| const Validator& validator) {
|
| ConformanceRequest request;
|
| ConformanceResponse response;
|
| request.set_json_payload(input_json);
|
| request.set_requested_output_format(conformance::JSON);
|
|
|
| - string effective_test_name = "JsonInput." + test_name + ".Validator";
|
| + string effective_test_name = ConformanceLevelToString(level) +
|
| + ".JsonInput." + test_name + ".Validator";
|
|
|
| RunTest(effective_test_name, request, &response);
|
|
|
| @@ -422,7 +468,7 @@ void ConformanceTestSuite::RunValidJsonTestWithValidator(
|
| }
|
|
|
| if (response.result_case() != ConformanceResponse::kJsonPayload) {
|
| - ReportFailure(effective_test_name, request, response,
|
| + ReportFailure(effective_test_name, level, request, response,
|
| "Expected JSON payload but got type %d.",
|
| response.result_case());
|
| return;
|
| @@ -430,13 +476,13 @@ void ConformanceTestSuite::RunValidJsonTestWithValidator(
|
| Json::Reader reader;
|
| Json::Value value;
|
| if (!reader.parse(response.json_payload(), value)) {
|
| - ReportFailure(effective_test_name, request, response,
|
| + ReportFailure(effective_test_name, level, request, response,
|
| "JSON payload cannot be parsed as valid JSON: %s",
|
| reader.getFormattedErrorMessages().c_str());
|
| return;
|
| }
|
| if (!validator(value)) {
|
| - ReportFailure(effective_test_name, request, response,
|
| + ReportFailure(effective_test_name, level, request, response,
|
| "JSON payload validation failed.");
|
| return;
|
| }
|
| @@ -444,11 +490,12 @@ void ConformanceTestSuite::RunValidJsonTestWithValidator(
|
| }
|
|
|
| void ConformanceTestSuite::ExpectParseFailureForJson(
|
| - const string& test_name, const string& input_json) {
|
| + const string& test_name, ConformanceLevel level, const string& input_json) {
|
| ConformanceRequest request;
|
| ConformanceResponse response;
|
| request.set_json_payload(input_json);
|
| - string effective_test_name = "JsonInput." + test_name;
|
| + string effective_test_name =
|
| + ConformanceLevelToString(level) + ".JsonInput." + test_name;
|
|
|
| // We don't expect output, but if the program erroneously accepts the protobuf
|
| // we let it send its response as this. We must not leave it unspecified.
|
| @@ -460,13 +507,13 @@ void ConformanceTestSuite::ExpectParseFailureForJson(
|
| } else if (response.result_case() == ConformanceResponse::kSkipped) {
|
| ReportSkip(effective_test_name, request, response);
|
| } else {
|
| - ReportFailure(effective_test_name, request, response,
|
| + ReportFailure(effective_test_name, level, request, response,
|
| "Should have failed to parse, but didn't.");
|
| }
|
| }
|
|
|
| void ConformanceTestSuite::ExpectSerializeFailureForJson(
|
| - const string& test_name, const string& text_format) {
|
| + const string& test_name, ConformanceLevel level, const string& text_format) {
|
| TestAllTypes payload_message;
|
| GOOGLE_CHECK(
|
| TextFormat::ParseFromString(text_format, &payload_message))
|
| @@ -475,7 +522,8 @@ void ConformanceTestSuite::ExpectSerializeFailureForJson(
|
| ConformanceRequest request;
|
| ConformanceResponse response;
|
| request.set_protobuf_payload(payload_message.SerializeAsString());
|
| - string effective_test_name = test_name + ".JsonOutput";
|
| + string effective_test_name =
|
| + ConformanceLevelToString(level) + "." + test_name + ".JsonOutput";
|
| request.set_requested_output_format(conformance::JSON);
|
|
|
| RunTest(effective_test_name, request, &response);
|
| @@ -484,7 +532,7 @@ void ConformanceTestSuite::ExpectSerializeFailureForJson(
|
| } else if (response.result_case() == ConformanceResponse::kSkipped) {
|
| ReportSkip(effective_test_name, request, response);
|
| } else {
|
| - ReportFailure(effective_test_name, request, response,
|
| + ReportFailure(effective_test_name, level, request, response,
|
| "Should have failed to serialize, but didn't.");
|
| }
|
| }
|
| @@ -500,8 +548,8 @@ void ConformanceTestSuite::TestPrematureEOFForType(FieldDescriptor::Type type) {
|
| string("abc") // 32BIT
|
| };
|
|
|
| - uint32_t fieldnum = GetFieldNumberForType(type, false);
|
| - uint32_t rep_fieldnum = GetFieldNumberForType(type, true);
|
| + const FieldDescriptor* field = GetFieldForType(type, false);
|
| + const FieldDescriptor* rep_field = GetFieldForType(type, true);
|
| WireFormatLite::WireType wire_type = WireFormatLite::WireTypeForFieldType(
|
| static_cast<WireFormatLite::FieldType>(type));
|
| const string& incomplete = incompletes[wire_type];
|
| @@ -509,42 +557,44 @@ void ConformanceTestSuite::TestPrematureEOFForType(FieldDescriptor::Type type) {
|
| UpperCase(string(".") + FieldDescriptor::TypeName(type));
|
|
|
| ExpectParseFailureForProto(
|
| - tag(fieldnum, wire_type),
|
| - "PrematureEofBeforeKnownNonRepeatedValue" + type_name);
|
| + tag(field->number(), wire_type),
|
| + "PrematureEofBeforeKnownNonRepeatedValue" + type_name, REQUIRED);
|
|
|
| ExpectParseFailureForProto(
|
| - tag(rep_fieldnum, wire_type),
|
| - "PrematureEofBeforeKnownRepeatedValue" + type_name);
|
| + tag(rep_field->number(), wire_type),
|
| + "PrematureEofBeforeKnownRepeatedValue" + type_name, REQUIRED);
|
|
|
| ExpectParseFailureForProto(
|
| tag(UNKNOWN_FIELD, wire_type),
|
| - "PrematureEofBeforeUnknownValue" + type_name);
|
| + "PrematureEofBeforeUnknownValue" + type_name, REQUIRED);
|
|
|
| ExpectParseFailureForProto(
|
| - cat( tag(fieldnum, wire_type), incomplete ),
|
| - "PrematureEofInsideKnownNonRepeatedValue" + type_name);
|
| + cat( tag(field->number(), wire_type), incomplete ),
|
| + "PrematureEofInsideKnownNonRepeatedValue" + type_name, REQUIRED);
|
|
|
| ExpectParseFailureForProto(
|
| - cat( tag(rep_fieldnum, wire_type), incomplete ),
|
| - "PrematureEofInsideKnownRepeatedValue" + type_name);
|
| + cat( tag(rep_field->number(), wire_type), incomplete ),
|
| + "PrematureEofInsideKnownRepeatedValue" + type_name, REQUIRED);
|
|
|
| ExpectParseFailureForProto(
|
| cat( tag(UNKNOWN_FIELD, wire_type), incomplete ),
|
| - "PrematureEofInsideUnknownValue" + type_name);
|
| + "PrematureEofInsideUnknownValue" + type_name, REQUIRED);
|
|
|
| if (wire_type == WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
|
| ExpectParseFailureForProto(
|
| - cat( tag(fieldnum, wire_type), varint(1) ),
|
| - "PrematureEofInDelimitedDataForKnownNonRepeatedValue" + type_name);
|
| + cat( tag(field->number(), wire_type), varint(1) ),
|
| + "PrematureEofInDelimitedDataForKnownNonRepeatedValue" + type_name,
|
| + REQUIRED);
|
|
|
| ExpectParseFailureForProto(
|
| - cat( tag(rep_fieldnum, wire_type), varint(1) ),
|
| - "PrematureEofInDelimitedDataForKnownRepeatedValue" + type_name);
|
| + cat( tag(rep_field->number(), wire_type), varint(1) ),
|
| + "PrematureEofInDelimitedDataForKnownRepeatedValue" + type_name,
|
| + REQUIRED);
|
|
|
| // EOF in the middle of delimited data for unknown value.
|
| ExpectParseFailureForProto(
|
| cat( tag(UNKNOWN_FIELD, wire_type), varint(1) ),
|
| - "PrematureEofInDelimitedDataForUnknownValue" + type_name);
|
| + "PrematureEofInDelimitedDataForUnknownValue" + type_name, REQUIRED);
|
|
|
| if (type == FieldDescriptor::TYPE_MESSAGE) {
|
| // Submessage ends in the middle of a value.
|
| @@ -552,47 +602,95 @@ void ConformanceTestSuite::TestPrematureEOFForType(FieldDescriptor::Type type) {
|
| cat( tag(WireFormatLite::TYPE_INT32, WireFormatLite::WIRETYPE_VARINT),
|
| incompletes[WireFormatLite::WIRETYPE_VARINT] );
|
| ExpectHardParseFailureForProto(
|
| - cat( tag(fieldnum, WireFormatLite::WIRETYPE_LENGTH_DELIMITED),
|
| + cat( tag(field->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED),
|
| varint(incomplete_submsg.size()),
|
| incomplete_submsg ),
|
| - "PrematureEofInSubmessageValue" + type_name);
|
| + "PrematureEofInSubmessageValue" + type_name, REQUIRED);
|
| }
|
| } else if (type != FieldDescriptor::TYPE_GROUP) {
|
| // Non-delimited, non-group: eligible for packing.
|
|
|
| // Packed region ends in the middle of a value.
|
| ExpectHardParseFailureForProto(
|
| - cat( tag(rep_fieldnum, WireFormatLite::WIRETYPE_LENGTH_DELIMITED),
|
| - varint(incomplete.size()),
|
| - incomplete ),
|
| - "PrematureEofInPackedFieldValue" + type_name);
|
| + cat(tag(rep_field->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED),
|
| + varint(incomplete.size()), incomplete),
|
| + "PrematureEofInPackedFieldValue" + type_name, REQUIRED);
|
|
|
| // EOF in the middle of packed region.
|
| ExpectParseFailureForProto(
|
| - cat( tag(rep_fieldnum, WireFormatLite::WIRETYPE_LENGTH_DELIMITED),
|
| - varint(1) ),
|
| - "PrematureEofInPackedField" + type_name);
|
| + cat(tag(rep_field->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED),
|
| + varint(1)),
|
| + "PrematureEofInPackedField" + type_name, REQUIRED);
|
| }
|
| }
|
|
|
| -void ConformanceTestSuite::SetFailureList(const vector<string>& failure_list) {
|
| +void ConformanceTestSuite::TestValidDataForType(
|
| + FieldDescriptor::Type type,
|
| + std::vector<std::pair<std::string, std::string>> values) {
|
| + const string type_name =
|
| + UpperCase(string(".") + FieldDescriptor::TypeName(type));
|
| + WireFormatLite::WireType wire_type = WireFormatLite::WireTypeForFieldType(
|
| + static_cast<WireFormatLite::FieldType>(type));
|
| + const FieldDescriptor* field = GetFieldForType(type, false);
|
| + const FieldDescriptor* rep_field = GetFieldForType(type, true);
|
| +
|
| + RunValidProtobufTest("ValidDataScalar" + type_name, REQUIRED,
|
| + cat(tag(field->number(), wire_type), values[0].first),
|
| + field->name() + ": " + values[0].second);
|
| +
|
| + string proto;
|
| + string text = field->name() + ": " + values.back().second;
|
| + for (size_t i = 0; i < values.size(); i++) {
|
| + proto += cat(tag(field->number(), wire_type), values[i].first);
|
| + }
|
| + RunValidProtobufTest("RepeatedScalarSelectsLast" + type_name, REQUIRED,
|
| + proto, text);
|
| +
|
| + proto.clear();
|
| + text.clear();
|
| +
|
| + for (size_t i = 0; i < values.size(); i++) {
|
| + proto += cat(tag(rep_field->number(), wire_type), values[i].first);
|
| + text += rep_field->name() + ": " + values[i].second + " ";
|
| + }
|
| + RunValidProtobufTest("ValidDataRepeated" + type_name, REQUIRED, proto, text);
|
| +}
|
| +
|
| +void ConformanceTestSuite::SetFailureList(const string& filename,
|
| + const vector<string>& failure_list) {
|
| + failure_list_filename_ = filename;
|
| expected_to_fail_.clear();
|
| std::copy(failure_list.begin(), failure_list.end(),
|
| std::inserter(expected_to_fail_, expected_to_fail_.end()));
|
| }
|
|
|
| bool ConformanceTestSuite::CheckSetEmpty(const set<string>& set_to_check,
|
| - const char* msg) {
|
| + const std::string& write_to_file,
|
| + const std::string& msg) {
|
| if (set_to_check.empty()) {
|
| return true;
|
| } else {
|
| StringAppendF(&output_, "\n");
|
| - StringAppendF(&output_, "%s:\n", msg);
|
| + StringAppendF(&output_, "%s\n\n", msg.c_str());
|
| for (set<string>::const_iterator iter = set_to_check.begin();
|
| iter != set_to_check.end(); ++iter) {
|
| StringAppendF(&output_, " %s\n", iter->c_str());
|
| }
|
| StringAppendF(&output_, "\n");
|
| +
|
| + if (!write_to_file.empty()) {
|
| + std::ofstream os(write_to_file);
|
| + if (os) {
|
| + for (set<string>::const_iterator iter = set_to_check.begin();
|
| + iter != set_to_check.end(); ++iter) {
|
| + os << *iter << "\n";
|
| + }
|
| + } else {
|
| + StringAppendF(&output_, "Failed to open file: %s\n",
|
| + write_to_file.c_str());
|
| + }
|
| + }
|
| +
|
| return false;
|
| }
|
| }
|
| @@ -617,24 +715,109 @@ bool ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner,
|
| TestPrematureEOFForType(static_cast<FieldDescriptor::Type>(i));
|
| }
|
|
|
| - RunValidJsonTest("HelloWorld", "{\"optionalString\":\"Hello, World!\"}",
|
| + int64 kInt64Min = -9223372036854775808ULL;
|
| + int64 kInt64Max = 9223372036854775807ULL;
|
| + uint64 kUint64Max = 18446744073709551615ULL;
|
| + int32 kInt32Max = 2147483647;
|
| + int32 kInt32Min = -2147483648;
|
| + uint32 kUint32Max = 4294967295UL;
|
| +
|
| + TestValidDataForType(FieldDescriptor::TYPE_DOUBLE, {
|
| + {dbl(0.1), "0.1"},
|
| + {dbl(1.7976931348623157e+308), "1.7976931348623157e+308"},
|
| + {dbl(2.22507385850720138309e-308), "2.22507385850720138309e-308"}
|
| + });
|
| + TestValidDataForType(FieldDescriptor::TYPE_FLOAT, {
|
| + {flt(0.1), "0.1"},
|
| + {flt(3.402823e+38), "3.402823e+38"}, // 3.40282347e+38
|
| + {flt(1.17549435e-38f), "1.17549435e-38"}
|
| + });
|
| + TestValidDataForType(FieldDescriptor::TYPE_INT64, {
|
| + {varint(12345), "12345"},
|
| + {varint(kInt64Max), std::to_string(kInt64Max)},
|
| + {varint(kInt64Min), std::to_string(kInt64Min)}
|
| + });
|
| + TestValidDataForType(FieldDescriptor::TYPE_UINT64, {
|
| + {varint(12345), "12345"},
|
| + {varint(kUint64Max), std::to_string(kUint64Max)},
|
| + {varint(0), "0"}
|
| + });
|
| + TestValidDataForType(FieldDescriptor::TYPE_INT32, {
|
| + {varint(12345), "12345"},
|
| + {varint(kInt32Max), std::to_string(kInt32Max)},
|
| + {varint(kInt32Min), std::to_string(kInt32Min)},
|
| + });
|
| + TestValidDataForType(FieldDescriptor::TYPE_UINT32, {
|
| + {varint(12345), "12345"},
|
| + {varint(kUint32Max), std::to_string(kUint32Max)}, // UINT32_MAX
|
| + {varint(0), "0"}
|
| + });
|
| + TestValidDataForType(FieldDescriptor::TYPE_FIXED64, {
|
| + {u64(12345), "12345"},
|
| + {u64(kUint64Max), std::to_string(kUint64Max)},
|
| + {u64(0), "0"}
|
| + });
|
| + TestValidDataForType(FieldDescriptor::TYPE_FIXED32, {
|
| + {u32(12345), "12345"},
|
| + {u32(kUint32Max), std::to_string(kUint32Max)}, // UINT32_MAX
|
| + {u32(0), "0"}
|
| + });
|
| + TestValidDataForType(FieldDescriptor::TYPE_SFIXED64, {
|
| + {u64(12345), "12345"},
|
| + {u64(kInt64Max), std::to_string(kInt64Max)},
|
| + {u64(kInt64Min), std::to_string(kInt64Min)}
|
| + });
|
| + TestValidDataForType(FieldDescriptor::TYPE_SFIXED32, {
|
| + {u32(12345), "12345"},
|
| + {u32(kInt32Max), std::to_string(kInt32Max)},
|
| + {u32(kInt32Min), std::to_string(kInt32Min)}
|
| + });
|
| + TestValidDataForType(FieldDescriptor::TYPE_BOOL, {
|
| + {varint(1), "true"},
|
| + {varint(0), "false"},
|
| + {varint(12345678), "true"}
|
| + });
|
| + TestValidDataForType(FieldDescriptor::TYPE_SINT32, {
|
| + {zz32(12345), "12345"},
|
| + {zz32(kInt32Max), std::to_string(kInt32Max)},
|
| + {zz32(kInt32Min), std::to_string(kInt32Min)}
|
| + });
|
| + TestValidDataForType(FieldDescriptor::TYPE_SINT64, {
|
| + {zz64(12345), "12345"},
|
| + {zz64(kInt64Max), std::to_string(kInt64Max)},
|
| + {zz64(kInt64Min), std::to_string(kInt64Min)}
|
| + });
|
| +
|
| + // TODO(haberman):
|
| + // TestValidDataForType(FieldDescriptor::TYPE_STRING
|
| + // TestValidDataForType(FieldDescriptor::TYPE_GROUP
|
| + // TestValidDataForType(FieldDescriptor::TYPE_MESSAGE
|
| + // TestValidDataForType(FieldDescriptor::TYPE_BYTES
|
| + // TestValidDataForType(FieldDescriptor::TYPE_ENUM
|
| +
|
| + RunValidJsonTest("HelloWorld", REQUIRED,
|
| + "{\"optionalString\":\"Hello, World!\"}",
|
| "optional_string: 'Hello, World!'");
|
|
|
| + // NOTE: The spec for JSON support is still being sorted out, these may not
|
| + // all be correct.
|
| // Test field name conventions.
|
| RunValidJsonTest(
|
| - "FieldNameInSnakeCase",
|
| + "FieldNameInSnakeCase", REQUIRED,
|
| R"({
|
| "fieldname1": 1,
|
| "fieldName2": 2,
|
| - "FieldName3": 3
|
| + "FieldName3": 3,
|
| + "fieldName4": 4
|
| })",
|
| R"(
|
| fieldname1: 1
|
| field_name2: 2
|
| _field_name3: 3
|
| + field__name4_: 4
|
| )");
|
| RunValidJsonTest(
|
| - "FieldNameWithNumbers",
|
| + "FieldNameWithNumbers", REQUIRED,
|
| R"({
|
| "field0name5": 5,
|
| "field0Name6": 6
|
| @@ -644,14 +827,14 @@ bool ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner,
|
| field_0_name6: 6
|
| )");
|
| RunValidJsonTest(
|
| - "FieldNameWithMixedCases",
|
| + "FieldNameWithMixedCases", REQUIRED,
|
| R"({
|
| "fieldName7": 7,
|
| - "fieldName8": 8,
|
| + "FieldName8": 8,
|
| "fieldName9": 9,
|
| - "fieldName10": 10,
|
| - "fIELDNAME11": 11,
|
| - "fIELDName12": 12
|
| + "FieldName10": 10,
|
| + "FIELDNAME11": 11,
|
| + "FIELDName12": 12
|
| })",
|
| R"(
|
| fieldName7: 7
|
| @@ -661,13 +844,32 @@ bool ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner,
|
| FIELD_NAME11: 11
|
| FIELD_name12: 12
|
| )");
|
| + RunValidJsonTest(
|
| + "FieldNameWithDoubleUnderscores", RECOMMENDED,
|
| + R"({
|
| + "FieldName13": 13,
|
| + "FieldName14": 14,
|
| + "fieldName15": 15,
|
| + "fieldName16": 16,
|
| + "fieldName17": 17,
|
| + "FieldName18": 18
|
| + })",
|
| + R"(
|
| + __field_name13: 13
|
| + __Field_name14: 14
|
| + field__name15: 15
|
| + field__Name16: 16
|
| + field_name17__: 17
|
| + Field_name18__: 18
|
| + )");
|
| // Using the original proto field name in JSON is also allowed.
|
| RunValidJsonTest(
|
| - "OriginalProtoFieldName",
|
| + "OriginalProtoFieldName", REQUIRED,
|
| R"({
|
| "fieldname1": 1,
|
| "field_name2": 2,
|
| "_field_name3": 3,
|
| + "field__name4_": 4,
|
| "field0name5": 5,
|
| "field_0_name6": 6,
|
| "fieldName7": 7,
|
| @@ -675,12 +877,19 @@ bool ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner,
|
| "field_Name9": 9,
|
| "Field_Name10": 10,
|
| "FIELD_NAME11": 11,
|
| - "FIELD_name12": 12
|
| + "FIELD_name12": 12,
|
| + "__field_name13": 13,
|
| + "__Field_name14": 14,
|
| + "field__name15": 15,
|
| + "field__Name16": 16,
|
| + "field_name17__": 17,
|
| + "Field_name18__": 18
|
| })",
|
| R"(
|
| fieldname1: 1
|
| field_name2: 2
|
| _field_name3: 3
|
| + field__name4_: 4
|
| field0name5: 5
|
| field_0_name6: 6
|
| fieldName7: 7
|
| @@ -689,61 +898,120 @@ bool ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner,
|
| Field_Name10: 10
|
| FIELD_NAME11: 11
|
| FIELD_name12: 12
|
| + __field_name13: 13
|
| + __Field_name14: 14
|
| + field__name15: 15
|
| + field__Name16: 16
|
| + field_name17__: 17
|
| + Field_name18__: 18
|
| )");
|
| // Field names can be escaped.
|
| RunValidJsonTest(
|
| - "FieldNameEscaped",
|
| + "FieldNameEscaped", REQUIRED,
|
| R"({"fieldn\u0061me1": 1})",
|
| "fieldname1: 1");
|
| + // String ends with escape character.
|
| + ExpectParseFailureForJson(
|
| + "StringEndsWithEscapeChar", RECOMMENDED,
|
| + "{\"optionalString\": \"abc\\");
|
| // Field names must be quoted (or it's not valid JSON).
|
| ExpectParseFailureForJson(
|
| - "FieldNameNotQuoted",
|
| + "FieldNameNotQuoted", RECOMMENDED,
|
| "{fieldname1: 1}");
|
| // Trailing comma is not allowed (not valid JSON).
|
| ExpectParseFailureForJson(
|
| - "TrailingCommaInAnObject",
|
| + "TrailingCommaInAnObject", RECOMMENDED,
|
| R"({"fieldname1":1,})");
|
| + ExpectParseFailureForJson(
|
| + "TrailingCommaInAnObjectWithSpace", RECOMMENDED,
|
| + R"({"fieldname1":1 ,})");
|
| + ExpectParseFailureForJson(
|
| + "TrailingCommaInAnObjectWithSpaceCommaSpace", RECOMMENDED,
|
| + R"({"fieldname1":1 , })");
|
| + ExpectParseFailureForJson(
|
| + "TrailingCommaInAnObjectWithNewlines", RECOMMENDED,
|
| + R"({
|
| + "fieldname1":1,
|
| + })");
|
| // JSON doesn't support comments.
|
| ExpectParseFailureForJson(
|
| - "JsonWithComments",
|
| + "JsonWithComments", RECOMMENDED,
|
| R"({
|
| // This is a comment.
|
| "fieldname1": 1
|
| })");
|
| + // JSON spec says whitespace doesn't matter, so try a few spacings to be sure.
|
| + RunValidJsonTest(
|
| + "OneLineNoSpaces", RECOMMENDED,
|
| + "{\"optionalInt32\":1,\"optionalInt64\":2}",
|
| + R"(
|
| + optional_int32: 1
|
| + optional_int64: 2
|
| + )");
|
| + RunValidJsonTest(
|
| + "OneLineWithSpaces", RECOMMENDED,
|
| + "{ \"optionalInt32\" : 1 , \"optionalInt64\" : 2 }",
|
| + R"(
|
| + optional_int32: 1
|
| + optional_int64: 2
|
| + )");
|
| + RunValidJsonTest(
|
| + "MultilineNoSpaces", RECOMMENDED,
|
| + "{\n\"optionalInt32\"\n:\n1\n,\n\"optionalInt64\"\n:\n2\n}",
|
| + R"(
|
| + optional_int32: 1
|
| + optional_int64: 2
|
| + )");
|
| + RunValidJsonTest(
|
| + "MultilineWithSpaces", RECOMMENDED,
|
| + "{\n \"optionalInt32\" : 1\n ,\n \"optionalInt64\" : 2\n}\n",
|
| + R"(
|
| + optional_int32: 1
|
| + optional_int64: 2
|
| + )");
|
| + // Missing comma between key/value pairs.
|
| + ExpectParseFailureForJson(
|
| + "MissingCommaOneLine", RECOMMENDED,
|
| + "{ \"optionalInt32\": 1 \"optionalInt64\": 2 }");
|
| + ExpectParseFailureForJson(
|
| + "MissingCommaMultiline", RECOMMENDED,
|
| + "{\n \"optionalInt32\": 1\n \"optionalInt64\": 2\n}");
|
| // Duplicated field names are not allowed.
|
| ExpectParseFailureForJson(
|
| - "FieldNameDuplicate",
|
| + "FieldNameDuplicate", RECOMMENDED,
|
| R"({
|
| "optionalNestedMessage": {a: 1},
|
| "optionalNestedMessage": {}
|
| })");
|
| ExpectParseFailureForJson(
|
| - "FieldNameDuplicateDifferentCasing1",
|
| + "FieldNameDuplicateDifferentCasing1", RECOMMENDED,
|
| R"({
|
| "optional_nested_message": {a: 1},
|
| "optionalNestedMessage": {}
|
| })");
|
| ExpectParseFailureForJson(
|
| - "FieldNameDuplicateDifferentCasing2",
|
| + "FieldNameDuplicateDifferentCasing2", RECOMMENDED,
|
| R"({
|
| "optionalNestedMessage": {a: 1},
|
| "optional_nested_message": {}
|
| })");
|
| // Serializers should use lowerCamelCase by default.
|
| RunValidJsonTestWithValidator(
|
| - "FieldNameInLowerCamelCase",
|
| + "FieldNameInLowerCamelCase", REQUIRED,
|
| R"({
|
| "fieldname1": 1,
|
| "fieldName2": 2,
|
| - "FieldName3": 3
|
| + "FieldName3": 3,
|
| + "fieldName4": 4
|
| })",
|
| [](const Json::Value& value) {
|
| return value.isMember("fieldname1") &&
|
| value.isMember("fieldName2") &&
|
| - value.isMember("FieldName3");
|
| + value.isMember("FieldName3") &&
|
| + value.isMember("fieldName4");
|
| });
|
| RunValidJsonTestWithValidator(
|
| - "FieldNameWithNumbers",
|
| + "FieldNameWithNumbers", REQUIRED,
|
| R"({
|
| "field0name5": 5,
|
| "field0Name6": 6
|
| @@ -753,169 +1021,195 @@ bool ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner,
|
| value.isMember("field0Name6");
|
| });
|
| RunValidJsonTestWithValidator(
|
| - "FieldNameWithMixedCases",
|
| + "FieldNameWithMixedCases", REQUIRED,
|
| R"({
|
| "fieldName7": 7,
|
| - "fieldName8": 8,
|
| + "FieldName8": 8,
|
| "fieldName9": 9,
|
| - "fieldName10": 10,
|
| - "fIELDNAME11": 11,
|
| - "fIELDName12": 12
|
| + "FieldName10": 10,
|
| + "FIELDNAME11": 11,
|
| + "FIELDName12": 12
|
| })",
|
| [](const Json::Value& value) {
|
| return value.isMember("fieldName7") &&
|
| - value.isMember("fieldName8") &&
|
| + value.isMember("FieldName8") &&
|
| value.isMember("fieldName9") &&
|
| - value.isMember("fieldName10") &&
|
| - value.isMember("fIELDNAME11") &&
|
| - value.isMember("fIELDName12");
|
| + value.isMember("FieldName10") &&
|
| + value.isMember("FIELDNAME11") &&
|
| + value.isMember("FIELDName12");
|
| + });
|
| + RunValidJsonTestWithValidator(
|
| + "FieldNameWithDoubleUnderscores", RECOMMENDED,
|
| + R"({
|
| + "FieldName13": 13,
|
| + "FieldName14": 14,
|
| + "fieldName15": 15,
|
| + "fieldName16": 16,
|
| + "fieldName17": 17,
|
| + "FieldName18": 18
|
| + })",
|
| + [](const Json::Value& value) {
|
| + return value.isMember("FieldName13") &&
|
| + value.isMember("FieldName14") &&
|
| + value.isMember("fieldName15") &&
|
| + value.isMember("fieldName16") &&
|
| + value.isMember("fieldName17") &&
|
| + value.isMember("FieldName18");
|
| });
|
|
|
| // Integer fields.
|
| RunValidJsonTest(
|
| - "Int32FieldMaxValue",
|
| + "Int32FieldMaxValue", REQUIRED,
|
| R"({"optionalInt32": 2147483647})",
|
| "optional_int32: 2147483647");
|
| RunValidJsonTest(
|
| - "Int32FieldMinValue",
|
| + "Int32FieldMinValue", REQUIRED,
|
| R"({"optionalInt32": -2147483648})",
|
| "optional_int32: -2147483648");
|
| RunValidJsonTest(
|
| - "Uint32FieldMaxValue",
|
| + "Uint32FieldMaxValue", REQUIRED,
|
| R"({"optionalUint32": 4294967295})",
|
| "optional_uint32: 4294967295");
|
| RunValidJsonTest(
|
| - "Int64FieldMaxValue",
|
| + "Int64FieldMaxValue", REQUIRED,
|
| R"({"optionalInt64": "9223372036854775807"})",
|
| "optional_int64: 9223372036854775807");
|
| RunValidJsonTest(
|
| - "Int64FieldMinValue",
|
| + "Int64FieldMinValue", REQUIRED,
|
| R"({"optionalInt64": "-9223372036854775808"})",
|
| "optional_int64: -9223372036854775808");
|
| RunValidJsonTest(
|
| - "Uint64FieldMaxValue",
|
| + "Uint64FieldMaxValue", REQUIRED,
|
| R"({"optionalUint64": "18446744073709551615"})",
|
| "optional_uint64: 18446744073709551615");
|
| - RunValidJsonTest(
|
| - "Int64FieldMaxValueNotQuoted",
|
| - R"({"optionalInt64": 9223372036854775807})",
|
| - "optional_int64: 9223372036854775807");
|
| - RunValidJsonTest(
|
| - "Int64FieldMinValueNotQuoted",
|
| + // While not the largest Int64, this is the largest
|
| + // Int64 which can be exactly represented within an
|
| + // IEEE-754 64-bit float, which is the expected level
|
| + // of interoperability guarantee. Larger values may
|
| + // work in some implementations, but should not be
|
| + // relied upon.
|
| + RunValidJsonTest(
|
| + "Int64FieldMaxValueNotQuoted", REQUIRED,
|
| + R"({"optionalInt64": 9223372036854774784})",
|
| + "optional_int64: 9223372036854774784");
|
| + RunValidJsonTest(
|
| + "Int64FieldMinValueNotQuoted", REQUIRED,
|
| R"({"optionalInt64": -9223372036854775808})",
|
| "optional_int64: -9223372036854775808");
|
| + // Largest interoperable Uint64; see comment above
|
| + // for Int64FieldMaxValueNotQuoted.
|
| RunValidJsonTest(
|
| - "Uint64FieldMaxValueNotQuoted",
|
| - R"({"optionalUint64": 18446744073709551615})",
|
| - "optional_uint64: 18446744073709551615");
|
| + "Uint64FieldMaxValueNotQuoted", REQUIRED,
|
| + R"({"optionalUint64": 18446744073709549568})",
|
| + "optional_uint64: 18446744073709549568");
|
| // Values can be represented as JSON strings.
|
| RunValidJsonTest(
|
| - "Int32FieldStringValue",
|
| + "Int32FieldStringValue", REQUIRED,
|
| R"({"optionalInt32": "2147483647"})",
|
| "optional_int32: 2147483647");
|
| RunValidJsonTest(
|
| - "Int32FieldStringValueEscaped",
|
| + "Int32FieldStringValueEscaped", REQUIRED,
|
| R"({"optionalInt32": "2\u003147483647"})",
|
| "optional_int32: 2147483647");
|
|
|
| // Parsers reject out-of-bound integer values.
|
| ExpectParseFailureForJson(
|
| - "Int32FieldTooLarge",
|
| + "Int32FieldTooLarge", REQUIRED,
|
| R"({"optionalInt32": 2147483648})");
|
| ExpectParseFailureForJson(
|
| - "Int32FieldTooSmall",
|
| + "Int32FieldTooSmall", REQUIRED,
|
| R"({"optionalInt32": -2147483649})");
|
| ExpectParseFailureForJson(
|
| - "Uint32FieldTooLarge",
|
| + "Uint32FieldTooLarge", REQUIRED,
|
| R"({"optionalUint32": 4294967296})");
|
| ExpectParseFailureForJson(
|
| - "Int64FieldTooLarge",
|
| + "Int64FieldTooLarge", REQUIRED,
|
| R"({"optionalInt64": "9223372036854775808"})");
|
| ExpectParseFailureForJson(
|
| - "Int64FieldTooSmall",
|
| + "Int64FieldTooSmall", REQUIRED,
|
| R"({"optionalInt64": "-9223372036854775809"})");
|
| ExpectParseFailureForJson(
|
| - "Uint64FieldTooLarge",
|
| + "Uint64FieldTooLarge", REQUIRED,
|
| R"({"optionalUint64": "18446744073709551616"})");
|
| // Parser reject non-integer numeric values as well.
|
| ExpectParseFailureForJson(
|
| - "Int32FieldNotInteger",
|
| + "Int32FieldNotInteger", REQUIRED,
|
| R"({"optionalInt32": 0.5})");
|
| ExpectParseFailureForJson(
|
| - "Uint32FieldNotInteger",
|
| + "Uint32FieldNotInteger", REQUIRED,
|
| R"({"optionalUint32": 0.5})");
|
| ExpectParseFailureForJson(
|
| - "Int64FieldNotInteger",
|
| + "Int64FieldNotInteger", REQUIRED,
|
| R"({"optionalInt64": "0.5"})");
|
| ExpectParseFailureForJson(
|
| - "Uint64FieldNotInteger",
|
| + "Uint64FieldNotInteger", REQUIRED,
|
| R"({"optionalUint64": "0.5"})");
|
|
|
| // Integers but represented as float values are accepted.
|
| RunValidJsonTest(
|
| - "Int32FieldFloatTrailingZero",
|
| + "Int32FieldFloatTrailingZero", REQUIRED,
|
| R"({"optionalInt32": 100000.000})",
|
| "optional_int32: 100000");
|
| RunValidJsonTest(
|
| - "Int32FieldExponentialFormat",
|
| + "Int32FieldExponentialFormat", REQUIRED,
|
| R"({"optionalInt32": 1e5})",
|
| "optional_int32: 100000");
|
| RunValidJsonTest(
|
| - "Int32FieldMaxFloatValue",
|
| + "Int32FieldMaxFloatValue", REQUIRED,
|
| R"({"optionalInt32": 2.147483647e9})",
|
| "optional_int32: 2147483647");
|
| RunValidJsonTest(
|
| - "Int32FieldMinFloatValue",
|
| + "Int32FieldMinFloatValue", REQUIRED,
|
| R"({"optionalInt32": -2.147483648e9})",
|
| "optional_int32: -2147483648");
|
| RunValidJsonTest(
|
| - "Uint32FieldMaxFloatValue",
|
| + "Uint32FieldMaxFloatValue", REQUIRED,
|
| R"({"optionalUint32": 4.294967295e9})",
|
| "optional_uint32: 4294967295");
|
|
|
| // Parser reject non-numeric values.
|
| ExpectParseFailureForJson(
|
| - "Int32FieldNotNumber",
|
| + "Int32FieldNotNumber", REQUIRED,
|
| R"({"optionalInt32": "3x3"})");
|
| ExpectParseFailureForJson(
|
| - "Uint32FieldNotNumber",
|
| + "Uint32FieldNotNumber", REQUIRED,
|
| R"({"optionalUint32": "3x3"})");
|
| ExpectParseFailureForJson(
|
| - "Int64FieldNotNumber",
|
| + "Int64FieldNotNumber", REQUIRED,
|
| R"({"optionalInt64": "3x3"})");
|
| ExpectParseFailureForJson(
|
| - "Uint64FieldNotNumber",
|
| + "Uint64FieldNotNumber", REQUIRED,
|
| R"({"optionalUint64": "3x3"})");
|
| // JSON does not allow "+" on numric values.
|
| ExpectParseFailureForJson(
|
| - "Int32FieldPlusSign",
|
| + "Int32FieldPlusSign", REQUIRED,
|
| R"({"optionalInt32": +1})");
|
| // JSON doesn't allow leading 0s.
|
| ExpectParseFailureForJson(
|
| - "Int32FieldLeadingZero",
|
| + "Int32FieldLeadingZero", REQUIRED,
|
| R"({"optionalInt32": 01})");
|
| ExpectParseFailureForJson(
|
| - "Int32FieldNegativeWithLeadingZero",
|
| + "Int32FieldNegativeWithLeadingZero", REQUIRED,
|
| R"({"optionalInt32": -01})");
|
| // String values must follow the same syntax rule. Specifically leading
|
| // or traling spaces are not allowed.
|
| ExpectParseFailureForJson(
|
| - "Int32FieldLeadingSpace",
|
| + "Int32FieldLeadingSpace", REQUIRED,
|
| R"({"optionalInt32": " 1"})");
|
| ExpectParseFailureForJson(
|
| - "Int32FieldTrailingSpace",
|
| + "Int32FieldTrailingSpace", REQUIRED,
|
| R"({"optionalInt32": "1 "})");
|
|
|
| // 64-bit values are serialized as strings.
|
| RunValidJsonTestWithValidator(
|
| - "Int64FieldBeString",
|
| + "Int64FieldBeString", RECOMMENDED,
|
| R"({"optionalInt64": 1})",
|
| [](const Json::Value& value) {
|
| return value["optionalInt64"].type() == Json::stringValue &&
|
| value["optionalInt64"].asString() == "1";
|
| });
|
| RunValidJsonTestWithValidator(
|
| - "Uint64FieldBeString",
|
| + "Uint64FieldBeString", RECOMMENDED,
|
| R"({"optionalUint64": 1})",
|
| [](const Json::Value& value) {
|
| return value["optionalUint64"].type() == Json::stringValue &&
|
| @@ -924,73 +1218,73 @@ bool ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner,
|
|
|
| // Bool fields.
|
| RunValidJsonTest(
|
| - "BoolFieldTrue",
|
| + "BoolFieldTrue", REQUIRED,
|
| R"({"optionalBool":true})",
|
| "optional_bool: true");
|
| RunValidJsonTest(
|
| - "BoolFieldFalse",
|
| + "BoolFieldFalse", REQUIRED,
|
| R"({"optionalBool":false})",
|
| "optional_bool: false");
|
|
|
| // Other forms are not allowed.
|
| ExpectParseFailureForJson(
|
| - "BoolFieldIntegerZero",
|
| + "BoolFieldIntegerZero", RECOMMENDED,
|
| R"({"optionalBool":0})");
|
| ExpectParseFailureForJson(
|
| - "BoolFieldIntegerOne",
|
| + "BoolFieldIntegerOne", RECOMMENDED,
|
| R"({"optionalBool":1})");
|
| ExpectParseFailureForJson(
|
| - "BoolFieldCamelCaseTrue",
|
| + "BoolFieldCamelCaseTrue", RECOMMENDED,
|
| R"({"optionalBool":True})");
|
| ExpectParseFailureForJson(
|
| - "BoolFieldCamelCaseFalse",
|
| + "BoolFieldCamelCaseFalse", RECOMMENDED,
|
| R"({"optionalBool":False})");
|
| ExpectParseFailureForJson(
|
| - "BoolFieldAllCapitalTrue",
|
| + "BoolFieldAllCapitalTrue", RECOMMENDED,
|
| R"({"optionalBool":TRUE})");
|
| ExpectParseFailureForJson(
|
| - "BoolFieldAllCapitalFalse",
|
| + "BoolFieldAllCapitalFalse", RECOMMENDED,
|
| R"({"optionalBool":FALSE})");
|
| ExpectParseFailureForJson(
|
| - "BoolFieldDoubleQuotedTrue",
|
| + "BoolFieldDoubleQuotedTrue", RECOMMENDED,
|
| R"({"optionalBool":"true"})");
|
| ExpectParseFailureForJson(
|
| - "BoolFieldDoubleQuotedFalse",
|
| + "BoolFieldDoubleQuotedFalse", RECOMMENDED,
|
| R"({"optionalBool":"false"})");
|
|
|
| // Float fields.
|
| RunValidJsonTest(
|
| - "FloatFieldMinPositiveValue",
|
| + "FloatFieldMinPositiveValue", REQUIRED,
|
| R"({"optionalFloat": 1.175494e-38})",
|
| "optional_float: 1.175494e-38");
|
| RunValidJsonTest(
|
| - "FloatFieldMaxNegativeValue",
|
| + "FloatFieldMaxNegativeValue", REQUIRED,
|
| R"({"optionalFloat": -1.175494e-38})",
|
| "optional_float: -1.175494e-38");
|
| RunValidJsonTest(
|
| - "FloatFieldMaxPositiveValue",
|
| + "FloatFieldMaxPositiveValue", REQUIRED,
|
| R"({"optionalFloat": 3.402823e+38})",
|
| "optional_float: 3.402823e+38");
|
| RunValidJsonTest(
|
| - "FloatFieldMinNegativeValue",
|
| + "FloatFieldMinNegativeValue", REQUIRED,
|
| R"({"optionalFloat": 3.402823e+38})",
|
| "optional_float: 3.402823e+38");
|
| // Values can be quoted.
|
| RunValidJsonTest(
|
| - "FloatFieldQuotedValue",
|
| + "FloatFieldQuotedValue", REQUIRED,
|
| R"({"optionalFloat": "1"})",
|
| "optional_float: 1");
|
| // Special values.
|
| RunValidJsonTest(
|
| - "FloatFieldNan",
|
| + "FloatFieldNan", REQUIRED,
|
| R"({"optionalFloat": "NaN"})",
|
| "optional_float: nan");
|
| RunValidJsonTest(
|
| - "FloatFieldInfinity",
|
| + "FloatFieldInfinity", REQUIRED,
|
| R"({"optionalFloat": "Infinity"})",
|
| "optional_float: inf");
|
| RunValidJsonTest(
|
| - "FloatFieldNegativeInfinity",
|
| + "FloatFieldNegativeInfinity", REQUIRED,
|
| R"({"optionalFloat": "-Infinity"})",
|
| "optional_float: -inf");
|
| // Non-cannonical Nan will be correctly normalized.
|
| @@ -1001,68 +1295,68 @@ bool ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner,
|
| message.set_optional_float(
|
| WireFormatLite::DecodeFloat(0x7FA12345));
|
| RunValidJsonTestWithProtobufInput(
|
| - "FloatFieldNormalizeQuietNan", message,
|
| + "FloatFieldNormalizeQuietNan", REQUIRED, message,
|
| "optional_float: nan");
|
| // IEEE floating-point standard 64-bit signaling NaN:
|
| // 1111 1111 1xxx xxxx xxxx xxxx xxxx xxxx
|
| message.set_optional_float(
|
| WireFormatLite::DecodeFloat(0xFFB54321));
|
| RunValidJsonTestWithProtobufInput(
|
| - "FloatFieldNormalizeSignalingNan", message,
|
| + "FloatFieldNormalizeSignalingNan", REQUIRED, message,
|
| "optional_float: nan");
|
| }
|
|
|
| // Special values must be quoted.
|
| ExpectParseFailureForJson(
|
| - "FloatFieldNanNotQuoted",
|
| + "FloatFieldNanNotQuoted", RECOMMENDED,
|
| R"({"optionalFloat": NaN})");
|
| ExpectParseFailureForJson(
|
| - "FloatFieldInfinityNotQuoted",
|
| + "FloatFieldInfinityNotQuoted", RECOMMENDED,
|
| R"({"optionalFloat": Infinity})");
|
| ExpectParseFailureForJson(
|
| - "FloatFieldNegativeInfinityNotQuoted",
|
| + "FloatFieldNegativeInfinityNotQuoted", RECOMMENDED,
|
| R"({"optionalFloat": -Infinity})");
|
| // Parsers should reject out-of-bound values.
|
| ExpectParseFailureForJson(
|
| - "FloatFieldTooSmall",
|
| + "FloatFieldTooSmall", REQUIRED,
|
| R"({"optionalFloat": -3.502823e+38})");
|
| ExpectParseFailureForJson(
|
| - "FloatFieldTooLarge",
|
| + "FloatFieldTooLarge", REQUIRED,
|
| R"({"optionalFloat": 3.502823e+38})");
|
|
|
| // Double fields.
|
| RunValidJsonTest(
|
| - "DoubleFieldMinPositiveValue",
|
| + "DoubleFieldMinPositiveValue", REQUIRED,
|
| R"({"optionalDouble": 2.22507e-308})",
|
| "optional_double: 2.22507e-308");
|
| RunValidJsonTest(
|
| - "DoubleFieldMaxNegativeValue",
|
| + "DoubleFieldMaxNegativeValue", REQUIRED,
|
| R"({"optionalDouble": -2.22507e-308})",
|
| "optional_double: -2.22507e-308");
|
| RunValidJsonTest(
|
| - "DoubleFieldMaxPositiveValue",
|
| + "DoubleFieldMaxPositiveValue", REQUIRED,
|
| R"({"optionalDouble": 1.79769e+308})",
|
| "optional_double: 1.79769e+308");
|
| RunValidJsonTest(
|
| - "DoubleFieldMinNegativeValue",
|
| + "DoubleFieldMinNegativeValue", REQUIRED,
|
| R"({"optionalDouble": -1.79769e+308})",
|
| "optional_double: -1.79769e+308");
|
| // Values can be quoted.
|
| RunValidJsonTest(
|
| - "DoubleFieldQuotedValue",
|
| + "DoubleFieldQuotedValue", REQUIRED,
|
| R"({"optionalDouble": "1"})",
|
| "optional_double: 1");
|
| // Speical values.
|
| RunValidJsonTest(
|
| - "DoubleFieldNan",
|
| + "DoubleFieldNan", REQUIRED,
|
| R"({"optionalDouble": "NaN"})",
|
| "optional_double: nan");
|
| RunValidJsonTest(
|
| - "DoubleFieldInfinity",
|
| + "DoubleFieldInfinity", REQUIRED,
|
| R"({"optionalDouble": "Infinity"})",
|
| "optional_double: inf");
|
| RunValidJsonTest(
|
| - "DoubleFieldNegativeInfinity",
|
| + "DoubleFieldNegativeInfinity", REQUIRED,
|
| R"({"optionalDouble": "-Infinity"})",
|
| "optional_double: -inf");
|
| // Non-cannonical Nan will be correctly normalized.
|
| @@ -1071,55 +1365,55 @@ bool ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner,
|
| message.set_optional_double(
|
| WireFormatLite::DecodeDouble(0x7FFA123456789ABCLL));
|
| RunValidJsonTestWithProtobufInput(
|
| - "DoubleFieldNormalizeQuietNan", message,
|
| + "DoubleFieldNormalizeQuietNan", REQUIRED, message,
|
| "optional_double: nan");
|
| message.set_optional_double(
|
| WireFormatLite::DecodeDouble(0xFFFBCBA987654321LL));
|
| RunValidJsonTestWithProtobufInput(
|
| - "DoubleFieldNormalizeSignalingNan", message,
|
| + "DoubleFieldNormalizeSignalingNan", REQUIRED, message,
|
| "optional_double: nan");
|
| }
|
|
|
| // Special values must be quoted.
|
| ExpectParseFailureForJson(
|
| - "DoubleFieldNanNotQuoted",
|
| + "DoubleFieldNanNotQuoted", RECOMMENDED,
|
| R"({"optionalDouble": NaN})");
|
| ExpectParseFailureForJson(
|
| - "DoubleFieldInfinityNotQuoted",
|
| + "DoubleFieldInfinityNotQuoted", RECOMMENDED,
|
| R"({"optionalDouble": Infinity})");
|
| ExpectParseFailureForJson(
|
| - "DoubleFieldNegativeInfinityNotQuoted",
|
| + "DoubleFieldNegativeInfinityNotQuoted", RECOMMENDED,
|
| R"({"optionalDouble": -Infinity})");
|
|
|
| // Parsers should reject out-of-bound values.
|
| ExpectParseFailureForJson(
|
| - "DoubleFieldTooSmall",
|
| + "DoubleFieldTooSmall", REQUIRED,
|
| R"({"optionalDouble": -1.89769e+308})");
|
| ExpectParseFailureForJson(
|
| - "DoubleFieldTooLarge",
|
| + "DoubleFieldTooLarge", REQUIRED,
|
| R"({"optionalDouble": +1.89769e+308})");
|
|
|
| // Enum fields.
|
| RunValidJsonTest(
|
| - "EnumField",
|
| + "EnumField", REQUIRED,
|
| R"({"optionalNestedEnum": "FOO"})",
|
| "optional_nested_enum: FOO");
|
| // Enum values must be represented as strings.
|
| ExpectParseFailureForJson(
|
| - "EnumFieldNotQuoted",
|
| + "EnumFieldNotQuoted", REQUIRED,
|
| R"({"optionalNestedEnum": FOO})");
|
| // Numeric values are allowed.
|
| RunValidJsonTest(
|
| - "EnumFieldNumericValueZero",
|
| + "EnumFieldNumericValueZero", REQUIRED,
|
| R"({"optionalNestedEnum": 0})",
|
| "optional_nested_enum: FOO");
|
| RunValidJsonTest(
|
| - "EnumFieldNumericValueNonZero",
|
| + "EnumFieldNumericValueNonZero", REQUIRED,
|
| R"({"optionalNestedEnum": 1})",
|
| "optional_nested_enum: BAR");
|
| // Unknown enum values are represented as numeric values.
|
| RunValidJsonTestWithValidator(
|
| - "EnumFieldUnknownValue",
|
| + "EnumFieldUnknownValue", REQUIRED,
|
| R"({"optionalNestedEnum": 123})",
|
| [](const Json::Value& value) {
|
| return value["optionalNestedEnum"].type() == Json::intValue &&
|
| @@ -1128,177 +1422,241 @@ bool ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner,
|
|
|
| // String fields.
|
| RunValidJsonTest(
|
| - "StringField",
|
| + "StringField", REQUIRED,
|
| R"({"optionalString": "Hello world!"})",
|
| "optional_string: \"Hello world!\"");
|
| RunValidJsonTest(
|
| - "StringFieldUnicode",
|
| + "StringFieldUnicode", REQUIRED,
|
| // Google in Chinese.
|
| R"({"optionalString": "谷歌"})",
|
| R"(optional_string: "谷歌")");
|
| RunValidJsonTest(
|
| - "StringFieldEscape",
|
| + "StringFieldEscape", REQUIRED,
|
| R"({"optionalString": "\"\\\/\b\f\n\r\t"})",
|
| R"(optional_string: "\"\\/\b\f\n\r\t")");
|
| RunValidJsonTest(
|
| - "StringFieldUnicodeEscape",
|
| + "StringFieldUnicodeEscape", REQUIRED,
|
| R"({"optionalString": "\u8C37\u6B4C"})",
|
| R"(optional_string: "谷歌")");
|
| RunValidJsonTest(
|
| - "StringFieldUnicodeEscapeWithLowercaseHexLetters",
|
| + "StringFieldUnicodeEscapeWithLowercaseHexLetters", REQUIRED,
|
| R"({"optionalString": "\u8c37\u6b4c"})",
|
| R"(optional_string: "谷歌")");
|
| RunValidJsonTest(
|
| - "StringFieldSurrogatePair",
|
| + "StringFieldSurrogatePair", REQUIRED,
|
| // The character is an emoji: grinning face with smiling eyes. 😁
|
| R"({"optionalString": "\uD83D\uDE01"})",
|
| R"(optional_string: "\xF0\x9F\x98\x81")");
|
|
|
| // Unicode escapes must start with "\u" (lowercase u).
|
| ExpectParseFailureForJson(
|
| - "StringFieldUppercaseEscapeLetter",
|
| + "StringFieldUppercaseEscapeLetter", RECOMMENDED,
|
| R"({"optionalString": "\U8C37\U6b4C"})");
|
| ExpectParseFailureForJson(
|
| - "StringFieldInvalidEscape",
|
| + "StringFieldInvalidEscape", RECOMMENDED,
|
| R"({"optionalString": "\uXXXX\u6B4C"})");
|
| ExpectParseFailureForJson(
|
| - "StringFieldUnterminatedEscape",
|
| + "StringFieldUnterminatedEscape", RECOMMENDED,
|
| R"({"optionalString": "\u8C3"})");
|
| ExpectParseFailureForJson(
|
| - "StringFieldUnpairedHighSurrogate",
|
| + "StringFieldUnpairedHighSurrogate", RECOMMENDED,
|
| R"({"optionalString": "\uD800"})");
|
| ExpectParseFailureForJson(
|
| - "StringFieldUnpairedLowSurrogate",
|
| + "StringFieldUnpairedLowSurrogate", RECOMMENDED,
|
| R"({"optionalString": "\uDC00"})");
|
| ExpectParseFailureForJson(
|
| - "StringFieldSurrogateInWrongOrder",
|
| + "StringFieldSurrogateInWrongOrder", RECOMMENDED,
|
| R"({"optionalString": "\uDE01\uD83D"})");
|
| ExpectParseFailureForJson(
|
| - "StringFieldNotAString",
|
| + "StringFieldNotAString", REQUIRED,
|
| R"({"optionalString": 12345})");
|
|
|
| // Bytes fields.
|
| RunValidJsonTest(
|
| - "BytesField",
|
| + "BytesField", REQUIRED,
|
| R"({"optionalBytes": "AQI="})",
|
| R"(optional_bytes: "\x01\x02")");
|
| ExpectParseFailureForJson(
|
| - "BytesFieldNoPadding",
|
| - R"({"optionalBytes": "AQI"})");
|
| - ExpectParseFailureForJson(
|
| - "BytesFieldInvalidBase64Characters",
|
| + "BytesFieldInvalidBase64Characters", REQUIRED,
|
| R"({"optionalBytes": "-_=="})");
|
|
|
| // Message fields.
|
| RunValidJsonTest(
|
| - "MessageField",
|
| + "MessageField", REQUIRED,
|
| R"({"optionalNestedMessage": {"a": 1234}})",
|
| "optional_nested_message: {a: 1234}");
|
|
|
| // Oneof fields.
|
| ExpectParseFailureForJson(
|
| - "OneofFieldDuplicate",
|
| + "OneofFieldDuplicate", REQUIRED,
|
| R"({"oneofUint32": 1, "oneofString": "test"})");
|
| + // Ensure zero values for oneof make it out/backs.
|
| + {
|
| + TestAllTypes message;
|
| + message.set_oneof_uint32(0);
|
| + RunValidProtobufTestWithMessage(
|
| + "OneofZeroUint32", RECOMMENDED, message, "oneof_uint32: 0");
|
| + message.mutable_oneof_nested_message()->set_a(0);
|
| + RunValidProtobufTestWithMessage(
|
| + "OneofZeroMessage", RECOMMENDED, message, "oneof_nested_message: {}");
|
| + message.set_oneof_string("");
|
| + RunValidProtobufTestWithMessage(
|
| + "OneofZeroString", RECOMMENDED, message, "oneof_string: \"\"");
|
| + message.set_oneof_bytes("");
|
| + RunValidProtobufTestWithMessage(
|
| + "OneofZeroBytes", RECOMMENDED, message, "oneof_bytes: \"\"");
|
| + message.set_oneof_bool(false);
|
| + RunValidProtobufTestWithMessage(
|
| + "OneofZeroBool", RECOMMENDED, message, "oneof_bool: false");
|
| + message.set_oneof_uint64(0);
|
| + RunValidProtobufTestWithMessage(
|
| + "OneofZeroUint64", RECOMMENDED, message, "oneof_uint64: 0");
|
| + message.set_oneof_float(0.0f);
|
| + RunValidProtobufTestWithMessage(
|
| + "OneofZeroFloat", RECOMMENDED, message, "oneof_float: 0");
|
| + message.set_oneof_double(0.0);
|
| + RunValidProtobufTestWithMessage(
|
| + "OneofZeroDouble", RECOMMENDED, message, "oneof_double: 0");
|
| + message.set_oneof_enum(TestAllTypes::FOO);
|
| + RunValidProtobufTestWithMessage(
|
| + "OneofZeroEnum", RECOMMENDED, message, "oneof_enum: FOO");
|
| + }
|
| + RunValidJsonTest(
|
| + "OneofZeroUint32", RECOMMENDED,
|
| + R"({"oneofUint32": 0})", "oneof_uint32: 0");
|
| + RunValidJsonTest(
|
| + "OneofZeroMessage", RECOMMENDED,
|
| + R"({"oneofNestedMessage": {}})", "oneof_nested_message: {}");
|
| + RunValidJsonTest(
|
| + "OneofZeroString", RECOMMENDED,
|
| + R"({"oneofString": ""})", "oneof_string: \"\"");
|
| + RunValidJsonTest(
|
| + "OneofZeroBytes", RECOMMENDED,
|
| + R"({"oneofBytes": ""})", "oneof_bytes: \"\"");
|
| + RunValidJsonTest(
|
| + "OneofZeroBool", RECOMMENDED,
|
| + R"({"oneofBool": false})", "oneof_bool: false");
|
| + RunValidJsonTest(
|
| + "OneofZeroUint64", RECOMMENDED,
|
| + R"({"oneofUint64": 0})", "oneof_uint64: 0");
|
| + RunValidJsonTest(
|
| + "OneofZeroFloat", RECOMMENDED,
|
| + R"({"oneofFloat": 0.0})", "oneof_float: 0");
|
| + RunValidJsonTest(
|
| + "OneofZeroDouble", RECOMMENDED,
|
| + R"({"oneofDouble": 0.0})", "oneof_double: 0");
|
| + RunValidJsonTest(
|
| + "OneofZeroEnum", RECOMMENDED,
|
| + R"({"oneofEnum":"FOO"})", "oneof_enum: FOO");
|
|
|
| // Repeated fields.
|
| RunValidJsonTest(
|
| - "PrimitiveRepeatedField",
|
| + "PrimitiveRepeatedField", REQUIRED,
|
| R"({"repeatedInt32": [1, 2, 3, 4]})",
|
| "repeated_int32: [1, 2, 3, 4]");
|
| RunValidJsonTest(
|
| - "EnumRepeatedField",
|
| + "EnumRepeatedField", REQUIRED,
|
| R"({"repeatedNestedEnum": ["FOO", "BAR", "BAZ"]})",
|
| "repeated_nested_enum: [FOO, BAR, BAZ]");
|
| RunValidJsonTest(
|
| - "StringRepeatedField",
|
| + "StringRepeatedField", REQUIRED,
|
| R"({"repeatedString": ["Hello", "world"]})",
|
| R"(repeated_string: ["Hello", "world"])");
|
| RunValidJsonTest(
|
| - "BytesRepeatedField",
|
| + "BytesRepeatedField", REQUIRED,
|
| R"({"repeatedBytes": ["AAEC", "AQI="]})",
|
| R"(repeated_bytes: ["\x00\x01\x02", "\x01\x02"])");
|
| RunValidJsonTest(
|
| - "MessageRepeatedField",
|
| + "MessageRepeatedField", REQUIRED,
|
| R"({"repeatedNestedMessage": [{"a": 1234}, {"a": 5678}]})",
|
| "repeated_nested_message: {a: 1234}"
|
| "repeated_nested_message: {a: 5678}");
|
|
|
| // Repeated field elements are of incorrect type.
|
| ExpectParseFailureForJson(
|
| - "RepeatedFieldWrongElementTypeExpectingIntegersGotBool",
|
| + "RepeatedFieldWrongElementTypeExpectingIntegersGotBool", REQUIRED,
|
| R"({"repeatedInt32": [1, false, 3, 4]})");
|
| ExpectParseFailureForJson(
|
| - "RepeatedFieldWrongElementTypeExpectingIntegersGotString",
|
| + "RepeatedFieldWrongElementTypeExpectingIntegersGotString", REQUIRED,
|
| R"({"repeatedInt32": [1, 2, "name", 4]})");
|
| ExpectParseFailureForJson(
|
| - "RepeatedFieldWrongElementTypeExpectingIntegersGotMessage",
|
| + "RepeatedFieldWrongElementTypeExpectingIntegersGotMessage", REQUIRED,
|
| R"({"repeatedInt32": [1, 2, 3, {"a": 4}]})");
|
| ExpectParseFailureForJson(
|
| - "RepeatedFieldWrongElementTypeExpectingStringsGotInt",
|
| + "RepeatedFieldWrongElementTypeExpectingStringsGotInt", REQUIRED,
|
| R"({"repeatedString": ["1", 2, "3", "4"]})");
|
| ExpectParseFailureForJson(
|
| - "RepeatedFieldWrongElementTypeExpectingStringsGotBool",
|
| + "RepeatedFieldWrongElementTypeExpectingStringsGotBool", REQUIRED,
|
| R"({"repeatedString": ["1", "2", false, "4"]})");
|
| ExpectParseFailureForJson(
|
| - "RepeatedFieldWrongElementTypeExpectingStringsGotMessage",
|
| + "RepeatedFieldWrongElementTypeExpectingStringsGotMessage", REQUIRED,
|
| R"({"repeatedString": ["1", 2, "3", {"a": 4}]})");
|
| ExpectParseFailureForJson(
|
| - "RepeatedFieldWrongElementTypeExpectingMessagesGotInt",
|
| + "RepeatedFieldWrongElementTypeExpectingMessagesGotInt", REQUIRED,
|
| R"({"repeatedNestedMessage": [{"a": 1}, 2]})");
|
| ExpectParseFailureForJson(
|
| - "RepeatedFieldWrongElementTypeExpectingMessagesGotBool",
|
| + "RepeatedFieldWrongElementTypeExpectingMessagesGotBool", REQUIRED,
|
| R"({"repeatedNestedMessage": [{"a": 1}, false]})");
|
| ExpectParseFailureForJson(
|
| - "RepeatedFieldWrongElementTypeExpectingMessagesGotString",
|
| + "RepeatedFieldWrongElementTypeExpectingMessagesGotString", REQUIRED,
|
| R"({"repeatedNestedMessage": [{"a": 1}, "2"]})");
|
| // Trailing comma in the repeated field is not allowed.
|
| ExpectParseFailureForJson(
|
| - "RepeatedFieldTrailingComma",
|
| + "RepeatedFieldTrailingComma", RECOMMENDED,
|
| R"({"repeatedInt32": [1, 2, 3, 4,]})");
|
| + ExpectParseFailureForJson(
|
| + "RepeatedFieldTrailingCommaWithSpace", RECOMMENDED,
|
| + "{\"repeatedInt32\": [1, 2, 3, 4 ,]}");
|
| + ExpectParseFailureForJson(
|
| + "RepeatedFieldTrailingCommaWithSpaceCommaSpace", RECOMMENDED,
|
| + "{\"repeatedInt32\": [1, 2, 3, 4 , ]}");
|
| + ExpectParseFailureForJson(
|
| + "RepeatedFieldTrailingCommaWithNewlines", RECOMMENDED,
|
| + "{\"repeatedInt32\": [\n 1,\n 2,\n 3,\n 4,\n]}");
|
|
|
| // Map fields.
|
| RunValidJsonTest(
|
| - "Int32MapField",
|
| + "Int32MapField", REQUIRED,
|
| R"({"mapInt32Int32": {"1": 2, "3": 4}})",
|
| "map_int32_int32: {key: 1 value: 2}"
|
| "map_int32_int32: {key: 3 value: 4}");
|
| ExpectParseFailureForJson(
|
| - "Int32MapFieldKeyNotQuoted",
|
| + "Int32MapFieldKeyNotQuoted", RECOMMENDED,
|
| R"({"mapInt32Int32": {1: 2, 3: 4}})");
|
| RunValidJsonTest(
|
| - "Uint32MapField",
|
| + "Uint32MapField", REQUIRED,
|
| R"({"mapUint32Uint32": {"1": 2, "3": 4}})",
|
| "map_uint32_uint32: {key: 1 value: 2}"
|
| "map_uint32_uint32: {key: 3 value: 4}");
|
| ExpectParseFailureForJson(
|
| - "Uint32MapFieldKeyNotQuoted",
|
| + "Uint32MapFieldKeyNotQuoted", RECOMMENDED,
|
| R"({"mapUint32Uint32": {1: 2, 3: 4}})");
|
| RunValidJsonTest(
|
| - "Int64MapField",
|
| + "Int64MapField", REQUIRED,
|
| R"({"mapInt64Int64": {"1": 2, "3": 4}})",
|
| "map_int64_int64: {key: 1 value: 2}"
|
| "map_int64_int64: {key: 3 value: 4}");
|
| ExpectParseFailureForJson(
|
| - "Int64MapFieldKeyNotQuoted",
|
| + "Int64MapFieldKeyNotQuoted", RECOMMENDED,
|
| R"({"mapInt64Int64": {1: 2, 3: 4}})");
|
| RunValidJsonTest(
|
| - "Uint64MapField",
|
| + "Uint64MapField", REQUIRED,
|
| R"({"mapUint64Uint64": {"1": 2, "3": 4}})",
|
| "map_uint64_uint64: {key: 1 value: 2}"
|
| "map_uint64_uint64: {key: 3 value: 4}");
|
| ExpectParseFailureForJson(
|
| - "Uint64MapFieldKeyNotQuoted",
|
| + "Uint64MapFieldKeyNotQuoted", RECOMMENDED,
|
| R"({"mapUint64Uint64": {1: 2, 3: 4}})");
|
| RunValidJsonTest(
|
| - "BoolMapField",
|
| + "BoolMapField", REQUIRED,
|
| R"({"mapBoolBool": {"true": true, "false": false}})",
|
| "map_bool_bool: {key: true value: true}"
|
| "map_bool_bool: {key: false value: false}");
|
| ExpectParseFailureForJson(
|
| - "BoolMapFieldKeyNotQuoted",
|
| + "BoolMapFieldKeyNotQuoted", RECOMMENDED,
|
| R"({"mapBoolBool": {true: true, false: false}})");
|
| RunValidJsonTest(
|
| - "MessageMapField",
|
| + "MessageMapField", REQUIRED,
|
| R"({
|
| "mapStringNestedMessage": {
|
| "hello": {"a": 1234},
|
| @@ -1317,21 +1675,21 @@ bool ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner,
|
| )");
|
| // Since Map keys are represented as JSON strings, escaping should be allowed.
|
| RunValidJsonTest(
|
| - "Int32MapEscapedKey",
|
| + "Int32MapEscapedKey", REQUIRED,
|
| R"({"mapInt32Int32": {"\u0031": 2}})",
|
| "map_int32_int32: {key: 1 value: 2}");
|
| RunValidJsonTest(
|
| - "Int64MapEscapedKey",
|
| + "Int64MapEscapedKey", REQUIRED,
|
| R"({"mapInt64Int64": {"\u0031": 2}})",
|
| "map_int64_int64: {key: 1 value: 2}");
|
| RunValidJsonTest(
|
| - "BoolMapEscapedKey",
|
| + "BoolMapEscapedKey", REQUIRED,
|
| R"({"mapBoolBool": {"tr\u0075e": true}})",
|
| "map_bool_bool: {key: true value: true}");
|
|
|
| // "null" is accepted for all fields types.
|
| RunValidJsonTest(
|
| - "AllFieldAcceptNull",
|
| + "AllFieldAcceptNull", REQUIRED,
|
| R"({
|
| "optionalInt32": null,
|
| "optionalInt64": null,
|
| @@ -1359,59 +1717,71 @@ bool ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner,
|
|
|
| // Repeated field elements cannot be null.
|
| ExpectParseFailureForJson(
|
| - "RepeatedFieldPrimitiveElementIsNull",
|
| + "RepeatedFieldPrimitiveElementIsNull", RECOMMENDED,
|
| R"({"repeatedInt32": [1, null, 2]})");
|
| ExpectParseFailureForJson(
|
| - "RepeatedFieldMessageElementIsNull",
|
| + "RepeatedFieldMessageElementIsNull", RECOMMENDED,
|
| R"({"repeatedNestedMessage": [{"a":1}, null, {"a":2}]})");
|
| // Map field keys cannot be null.
|
| ExpectParseFailureForJson(
|
| - "MapFieldKeyIsNull",
|
| + "MapFieldKeyIsNull", RECOMMENDED,
|
| R"({"mapInt32Int32": {null: 1}})");
|
| // Map field values cannot be null.
|
| ExpectParseFailureForJson(
|
| - "MapFieldValueIsNull",
|
| + "MapFieldValueIsNull", RECOMMENDED,
|
| R"({"mapInt32Int32": {"0": null}})");
|
|
|
| + // http://www.rfc-editor.org/rfc/rfc7159.txt says strings have to use double
|
| + // quotes.
|
| + ExpectParseFailureForJson(
|
| + "StringFieldSingleQuoteKey", RECOMMENDED,
|
| + R"({'optionalString': "Hello world!"})");
|
| + ExpectParseFailureForJson(
|
| + "StringFieldSingleQuoteValue", RECOMMENDED,
|
| + R"({"optionalString": 'Hello world!'})");
|
| + ExpectParseFailureForJson(
|
| + "StringFieldSingleQuoteBoth", RECOMMENDED,
|
| + R"({'optionalString': 'Hello world!'})");
|
| +
|
| // Wrapper types.
|
| RunValidJsonTest(
|
| - "OptionalBoolWrapper",
|
| + "OptionalBoolWrapper", REQUIRED,
|
| R"({"optionalBoolWrapper": false})",
|
| "optional_bool_wrapper: {value: false}");
|
| RunValidJsonTest(
|
| - "OptionalInt32Wrapper",
|
| + "OptionalInt32Wrapper", REQUIRED,
|
| R"({"optionalInt32Wrapper": 0})",
|
| "optional_int32_wrapper: {value: 0}");
|
| RunValidJsonTest(
|
| - "OptionalUint32Wrapper",
|
| + "OptionalUint32Wrapper", REQUIRED,
|
| R"({"optionalUint32Wrapper": 0})",
|
| "optional_uint32_wrapper: {value: 0}");
|
| RunValidJsonTest(
|
| - "OptionalInt64Wrapper",
|
| + "OptionalInt64Wrapper", REQUIRED,
|
| R"({"optionalInt64Wrapper": 0})",
|
| "optional_int64_wrapper: {value: 0}");
|
| RunValidJsonTest(
|
| - "OptionalUint64Wrapper",
|
| + "OptionalUint64Wrapper", REQUIRED,
|
| R"({"optionalUint64Wrapper": 0})",
|
| "optional_uint64_wrapper: {value: 0}");
|
| RunValidJsonTest(
|
| - "OptionalFloatWrapper",
|
| + "OptionalFloatWrapper", REQUIRED,
|
| R"({"optionalFloatWrapper": 0})",
|
| "optional_float_wrapper: {value: 0}");
|
| RunValidJsonTest(
|
| - "OptionalDoubleWrapper",
|
| + "OptionalDoubleWrapper", REQUIRED,
|
| R"({"optionalDoubleWrapper": 0})",
|
| "optional_double_wrapper: {value: 0}");
|
| RunValidJsonTest(
|
| - "OptionalStringWrapper",
|
| + "OptionalStringWrapper", REQUIRED,
|
| R"({"optionalStringWrapper": ""})",
|
| R"(optional_string_wrapper: {value: ""})");
|
| RunValidJsonTest(
|
| - "OptionalBytesWrapper",
|
| + "OptionalBytesWrapper", REQUIRED,
|
| R"({"optionalBytesWrapper": ""})",
|
| R"(optional_bytes_wrapper: {value: ""})");
|
| RunValidJsonTest(
|
| - "OptionalWrapperTypesWithNonDefaultValue",
|
| + "OptionalWrapperTypesWithNonDefaultValue", REQUIRED,
|
| R"({
|
| "optionalBoolWrapper": true,
|
| "optionalInt32Wrapper": 1,
|
| @@ -1435,56 +1805,56 @@ bool ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner,
|
| optional_bytes_wrapper: {value: "\x01\x02"}
|
| )");
|
| RunValidJsonTest(
|
| - "RepeatedBoolWrapper",
|
| + "RepeatedBoolWrapper", REQUIRED,
|
| R"({"repeatedBoolWrapper": [true, false]})",
|
| "repeated_bool_wrapper: {value: true}"
|
| "repeated_bool_wrapper: {value: false}");
|
| RunValidJsonTest(
|
| - "RepeatedInt32Wrapper",
|
| + "RepeatedInt32Wrapper", REQUIRED,
|
| R"({"repeatedInt32Wrapper": [0, 1]})",
|
| "repeated_int32_wrapper: {value: 0}"
|
| "repeated_int32_wrapper: {value: 1}");
|
| RunValidJsonTest(
|
| - "RepeatedUint32Wrapper",
|
| + "RepeatedUint32Wrapper", REQUIRED,
|
| R"({"repeatedUint32Wrapper": [0, 1]})",
|
| "repeated_uint32_wrapper: {value: 0}"
|
| "repeated_uint32_wrapper: {value: 1}");
|
| RunValidJsonTest(
|
| - "RepeatedInt64Wrapper",
|
| + "RepeatedInt64Wrapper", REQUIRED,
|
| R"({"repeatedInt64Wrapper": [0, 1]})",
|
| "repeated_int64_wrapper: {value: 0}"
|
| "repeated_int64_wrapper: {value: 1}");
|
| RunValidJsonTest(
|
| - "RepeatedUint64Wrapper",
|
| + "RepeatedUint64Wrapper", REQUIRED,
|
| R"({"repeatedUint64Wrapper": [0, 1]})",
|
| "repeated_uint64_wrapper: {value: 0}"
|
| "repeated_uint64_wrapper: {value: 1}");
|
| RunValidJsonTest(
|
| - "RepeatedFloatWrapper",
|
| + "RepeatedFloatWrapper", REQUIRED,
|
| R"({"repeatedFloatWrapper": [0, 1]})",
|
| "repeated_float_wrapper: {value: 0}"
|
| "repeated_float_wrapper: {value: 1}");
|
| RunValidJsonTest(
|
| - "RepeatedDoubleWrapper",
|
| + "RepeatedDoubleWrapper", REQUIRED,
|
| R"({"repeatedDoubleWrapper": [0, 1]})",
|
| "repeated_double_wrapper: {value: 0}"
|
| "repeated_double_wrapper: {value: 1}");
|
| RunValidJsonTest(
|
| - "RepeatedStringWrapper",
|
| + "RepeatedStringWrapper", REQUIRED,
|
| R"({"repeatedStringWrapper": ["", "AQI="]})",
|
| R"(
|
| repeated_string_wrapper: {value: ""}
|
| repeated_string_wrapper: {value: "AQI="}
|
| )");
|
| RunValidJsonTest(
|
| - "RepeatedBytesWrapper",
|
| + "RepeatedBytesWrapper", REQUIRED,
|
| R"({"repeatedBytesWrapper": ["", "AQI="]})",
|
| R"(
|
| repeated_bytes_wrapper: {value: ""}
|
| repeated_bytes_wrapper: {value: "\x01\x02"}
|
| )");
|
| RunValidJsonTest(
|
| - "WrapperTypesWithNullValue",
|
| + "WrapperTypesWithNullValue", REQUIRED,
|
| R"({
|
| "optionalBoolWrapper": null,
|
| "optionalInt32Wrapper": null,
|
| @@ -1509,55 +1879,55 @@ bool ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner,
|
|
|
| // Duration
|
| RunValidJsonTest(
|
| - "DurationMinValue",
|
| + "DurationMinValue", REQUIRED,
|
| R"({"optionalDuration": "-315576000000.999999999s"})",
|
| "optional_duration: {seconds: -315576000000 nanos: -999999999}");
|
| RunValidJsonTest(
|
| - "DurationMaxValue",
|
| + "DurationMaxValue", REQUIRED,
|
| R"({"optionalDuration": "315576000000.999999999s"})",
|
| "optional_duration: {seconds: 315576000000 nanos: 999999999}");
|
| RunValidJsonTest(
|
| - "DurationRepeatedValue",
|
| + "DurationRepeatedValue", REQUIRED,
|
| R"({"repeatedDuration": ["1.5s", "-1.5s"]})",
|
| "repeated_duration: {seconds: 1 nanos: 500000000}"
|
| "repeated_duration: {seconds: -1 nanos: -500000000}");
|
|
|
| ExpectParseFailureForJson(
|
| - "DurationMissingS",
|
| + "DurationMissingS", REQUIRED,
|
| R"({"optionalDuration": "1"})");
|
| ExpectParseFailureForJson(
|
| - "DurationJsonInputTooSmall",
|
| + "DurationJsonInputTooSmall", REQUIRED,
|
| R"({"optionalDuration": "-315576000001.000000000s"})");
|
| ExpectParseFailureForJson(
|
| - "DurationJsonInputTooLarge",
|
| + "DurationJsonInputTooLarge", REQUIRED,
|
| R"({"optionalDuration": "315576000001.000000000s"})");
|
| ExpectSerializeFailureForJson(
|
| - "DurationProtoInputTooSmall",
|
| + "DurationProtoInputTooSmall", REQUIRED,
|
| "optional_duration: {seconds: -315576000001 nanos: 0}");
|
| ExpectSerializeFailureForJson(
|
| - "DurationProtoInputTooLarge",
|
| + "DurationProtoInputTooLarge", REQUIRED,
|
| "optional_duration: {seconds: 315576000001 nanos: 0}");
|
|
|
| RunValidJsonTestWithValidator(
|
| - "DurationHasZeroFractionalDigit",
|
| + "DurationHasZeroFractionalDigit", RECOMMENDED,
|
| R"({"optionalDuration": "1.000000000s"})",
|
| [](const Json::Value& value) {
|
| return value["optionalDuration"].asString() == "1s";
|
| });
|
| RunValidJsonTestWithValidator(
|
| - "DurationHas3FractionalDigits",
|
| + "DurationHas3FractionalDigits", RECOMMENDED,
|
| R"({"optionalDuration": "1.010000000s"})",
|
| [](const Json::Value& value) {
|
| return value["optionalDuration"].asString() == "1.010s";
|
| });
|
| RunValidJsonTestWithValidator(
|
| - "DurationHas6FractionalDigits",
|
| + "DurationHas6FractionalDigits", RECOMMENDED,
|
| R"({"optionalDuration": "1.000010000s"})",
|
| [](const Json::Value& value) {
|
| return value["optionalDuration"].asString() == "1.000010s";
|
| });
|
| RunValidJsonTestWithValidator(
|
| - "DurationHas9FractionalDigits",
|
| + "DurationHas9FractionalDigits", RECOMMENDED,
|
| R"({"optionalDuration": "1.000000010s"})",
|
| [](const Json::Value& value) {
|
| return value["optionalDuration"].asString() == "1.000000010s";
|
| @@ -1565,15 +1935,15 @@ bool ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner,
|
|
|
| // Timestamp
|
| RunValidJsonTest(
|
| - "TimestampMinValue",
|
| + "TimestampMinValue", REQUIRED,
|
| R"({"optionalTimestamp": "0001-01-01T00:00:00Z"})",
|
| "optional_timestamp: {seconds: -62135596800}");
|
| RunValidJsonTest(
|
| - "TimestampMaxValue",
|
| + "TimestampMaxValue", REQUIRED,
|
| R"({"optionalTimestamp": "9999-12-31T23:59:59.999999999Z"})",
|
| "optional_timestamp: {seconds: 253402300799 nanos: 999999999}");
|
| RunValidJsonTest(
|
| - "TimestampRepeatedValue",
|
| + "TimestampRepeatedValue", REQUIRED,
|
| R"({
|
| "repeatedTimestamp": [
|
| "0001-01-01T00:00:00Z",
|
| @@ -1583,68 +1953,68 @@ bool ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner,
|
| "repeated_timestamp: {seconds: -62135596800}"
|
| "repeated_timestamp: {seconds: 253402300799 nanos: 999999999}");
|
| RunValidJsonTest(
|
| - "TimestampWithPositiveOffset",
|
| + "TimestampWithPositiveOffset", REQUIRED,
|
| R"({"optionalTimestamp": "1970-01-01T08:00:00+08:00"})",
|
| "optional_timestamp: {seconds: 0}");
|
| RunValidJsonTest(
|
| - "TimestampWithNegativeOffset",
|
| + "TimestampWithNegativeOffset", REQUIRED,
|
| R"({"optionalTimestamp": "1969-12-31T16:00:00-08:00"})",
|
| "optional_timestamp: {seconds: 0}");
|
|
|
| ExpectParseFailureForJson(
|
| - "TimestampJsonInputTooSmall",
|
| + "TimestampJsonInputTooSmall", REQUIRED,
|
| R"({"optionalTimestamp": "0000-01-01T00:00:00Z"})");
|
| ExpectParseFailureForJson(
|
| - "TimestampJsonInputTooLarge",
|
| + "TimestampJsonInputTooLarge", REQUIRED,
|
| R"({"optionalTimestamp": "10000-01-01T00:00:00Z"})");
|
| ExpectParseFailureForJson(
|
| - "TimestampJsonInputMissingZ",
|
| + "TimestampJsonInputMissingZ", REQUIRED,
|
| R"({"optionalTimestamp": "0001-01-01T00:00:00"})");
|
| ExpectParseFailureForJson(
|
| - "TimestampJsonInputMissingT",
|
| + "TimestampJsonInputMissingT", REQUIRED,
|
| R"({"optionalTimestamp": "0001-01-01 00:00:00Z"})");
|
| ExpectParseFailureForJson(
|
| - "TimestampJsonInputLowercaseZ",
|
| + "TimestampJsonInputLowercaseZ", REQUIRED,
|
| R"({"optionalTimestamp": "0001-01-01T00:00:00z"})");
|
| ExpectParseFailureForJson(
|
| - "TimestampJsonInputLowercaseT",
|
| + "TimestampJsonInputLowercaseT", REQUIRED,
|
| R"({"optionalTimestamp": "0001-01-01t00:00:00Z"})");
|
| ExpectSerializeFailureForJson(
|
| - "TimestampProtoInputTooSmall",
|
| + "TimestampProtoInputTooSmall", REQUIRED,
|
| "optional_timestamp: {seconds: -62135596801}");
|
| ExpectSerializeFailureForJson(
|
| - "TimestampProtoInputTooLarge",
|
| + "TimestampProtoInputTooLarge", REQUIRED,
|
| "optional_timestamp: {seconds: 253402300800}");
|
| RunValidJsonTestWithValidator(
|
| - "TimestampZeroNormalized",
|
| + "TimestampZeroNormalized", RECOMMENDED,
|
| R"({"optionalTimestamp": "1969-12-31T16:00:00-08:00"})",
|
| [](const Json::Value& value) {
|
| return value["optionalTimestamp"].asString() ==
|
| "1970-01-01T00:00:00Z";
|
| });
|
| RunValidJsonTestWithValidator(
|
| - "TimestampHasZeroFractionalDigit",
|
| + "TimestampHasZeroFractionalDigit", RECOMMENDED,
|
| R"({"optionalTimestamp": "1970-01-01T00:00:00.000000000Z"})",
|
| [](const Json::Value& value) {
|
| return value["optionalTimestamp"].asString() ==
|
| "1970-01-01T00:00:00Z";
|
| });
|
| RunValidJsonTestWithValidator(
|
| - "TimestampHas3FractionalDigits",
|
| + "TimestampHas3FractionalDigits", RECOMMENDED,
|
| R"({"optionalTimestamp": "1970-01-01T00:00:00.010000000Z"})",
|
| [](const Json::Value& value) {
|
| return value["optionalTimestamp"].asString() ==
|
| "1970-01-01T00:00:00.010Z";
|
| });
|
| RunValidJsonTestWithValidator(
|
| - "TimestampHas6FractionalDigits",
|
| + "TimestampHas6FractionalDigits", RECOMMENDED,
|
| R"({"optionalTimestamp": "1970-01-01T00:00:00.000010000Z"})",
|
| [](const Json::Value& value) {
|
| return value["optionalTimestamp"].asString() ==
|
| "1970-01-01T00:00:00.000010Z";
|
| });
|
| RunValidJsonTestWithValidator(
|
| - "TimestampHas9FractionalDigits",
|
| + "TimestampHas9FractionalDigits", RECOMMENDED,
|
| R"({"optionalTimestamp": "1970-01-01T00:00:00.000000010Z"})",
|
| [](const Json::Value& value) {
|
| return value["optionalTimestamp"].asString() ==
|
| @@ -1653,25 +2023,25 @@ bool ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner,
|
|
|
| // FieldMask
|
| RunValidJsonTest(
|
| - "FieldMask",
|
| + "FieldMask", REQUIRED,
|
| R"({"optionalFieldMask": "foo,barBaz"})",
|
| R"(optional_field_mask: {paths: "foo" paths: "bar_baz"})");
|
| ExpectParseFailureForJson(
|
| - "FieldMaskInvalidCharacter",
|
| + "FieldMaskInvalidCharacter", RECOMMENDED,
|
| R"({"optionalFieldMask": "foo,bar_bar"})");
|
| ExpectSerializeFailureForJson(
|
| - "FieldMaskPathsDontRoundTrip",
|
| + "FieldMaskPathsDontRoundTrip", RECOMMENDED,
|
| R"(optional_field_mask: {paths: "fooBar"})");
|
| ExpectSerializeFailureForJson(
|
| - "FieldMaskNumbersDontRoundTrip",
|
| + "FieldMaskNumbersDontRoundTrip", RECOMMENDED,
|
| R"(optional_field_mask: {paths: "foo_3_bar"})");
|
| ExpectSerializeFailureForJson(
|
| - "FieldMaskTooManyUnderscore",
|
| + "FieldMaskTooManyUnderscore", RECOMMENDED,
|
| R"(optional_field_mask: {paths: "foo__bar"})");
|
|
|
| // Struct
|
| RunValidJsonTest(
|
| - "Struct",
|
| + "Struct", REQUIRED,
|
| R"({
|
| "optionalStruct": {
|
| "nullValue": null,
|
| @@ -1737,27 +2107,27 @@ bool ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner,
|
| )");
|
| // Value
|
| RunValidJsonTest(
|
| - "ValueAcceptInteger",
|
| + "ValueAcceptInteger", REQUIRED,
|
| R"({"optionalValue": 1})",
|
| "optional_value: { number_value: 1}");
|
| RunValidJsonTest(
|
| - "ValueAcceptFloat",
|
| + "ValueAcceptFloat", REQUIRED,
|
| R"({"optionalValue": 1.5})",
|
| "optional_value: { number_value: 1.5}");
|
| RunValidJsonTest(
|
| - "ValueAcceptBool",
|
| + "ValueAcceptBool", REQUIRED,
|
| R"({"optionalValue": false})",
|
| "optional_value: { bool_value: false}");
|
| RunValidJsonTest(
|
| - "ValueAcceptNull",
|
| + "ValueAcceptNull", REQUIRED,
|
| R"({"optionalValue": null})",
|
| "optional_value: { null_value: NULL_VALUE}");
|
| RunValidJsonTest(
|
| - "ValueAcceptString",
|
| + "ValueAcceptString", REQUIRED,
|
| R"({"optionalValue": "hello"})",
|
| R"(optional_value: { string_value: "hello"})");
|
| RunValidJsonTest(
|
| - "ValueAcceptList",
|
| + "ValueAcceptList", REQUIRED,
|
| R"({"optionalValue": [0, "hello"]})",
|
| R"(
|
| optional_value: {
|
| @@ -1772,7 +2142,7 @@ bool ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner,
|
| }
|
| )");
|
| RunValidJsonTest(
|
| - "ValueAcceptObject",
|
| + "ValueAcceptObject", REQUIRED,
|
| R"({"optionalValue": {"value": 1}})",
|
| R"(
|
| optional_value: {
|
| @@ -1789,27 +2159,27 @@ bool ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner,
|
|
|
| // Any
|
| RunValidJsonTest(
|
| - "Any",
|
| + "Any", REQUIRED,
|
| R"({
|
| "optionalAny": {
|
| - "@type": "type.googleapis.com/conformance.TestAllTypes",
|
| + "@type": "type.googleapis.com/protobuf_test_messages.proto3.TestAllTypes",
|
| "optionalInt32": 12345
|
| }
|
| })",
|
| R"(
|
| optional_any: {
|
| - [type.googleapis.com/conformance.TestAllTypes] {
|
| + [type.googleapis.com/protobuf_test_messages.proto3.TestAllTypes] {
|
| optional_int32: 12345
|
| }
|
| }
|
| )");
|
| RunValidJsonTest(
|
| - "AnyNested",
|
| + "AnyNested", REQUIRED,
|
| R"({
|
| "optionalAny": {
|
| "@type": "type.googleapis.com/google.protobuf.Any",
|
| "value": {
|
| - "@type": "type.googleapis.com/conformance.TestAllTypes",
|
| + "@type": "type.googleapis.com/protobuf_test_messages.proto3.TestAllTypes",
|
| "optionalInt32": 12345
|
| }
|
| }
|
| @@ -1817,7 +2187,7 @@ bool ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner,
|
| R"(
|
| optional_any: {
|
| [type.googleapis.com/google.protobuf.Any] {
|
| - [type.googleapis.com/conformance.TestAllTypes] {
|
| + [type.googleapis.com/protobuf_test_messages.proto3.TestAllTypes] {
|
| optional_int32: 12345
|
| }
|
| }
|
| @@ -1825,23 +2195,23 @@ bool ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner,
|
| )");
|
| // The special "@type" tag is not required to appear first.
|
| RunValidJsonTest(
|
| - "AnyUnorderedTypeTag",
|
| + "AnyUnorderedTypeTag", REQUIRED,
|
| R"({
|
| "optionalAny": {
|
| "optionalInt32": 12345,
|
| - "@type": "type.googleapis.com/conformance.TestAllTypes"
|
| + "@type": "type.googleapis.com/protobuf_test_messages.proto3.TestAllTypes"
|
| }
|
| })",
|
| R"(
|
| optional_any: {
|
| - [type.googleapis.com/conformance.TestAllTypes] {
|
| + [type.googleapis.com/protobuf_test_messages.proto3.TestAllTypes] {
|
| optional_int32: 12345
|
| }
|
| }
|
| )");
|
| // Well-known types in Any.
|
| RunValidJsonTest(
|
| - "AnyWithInt32ValueWrapper",
|
| + "AnyWithInt32ValueWrapper", REQUIRED,
|
| R"({
|
| "optionalAny": {
|
| "@type": "type.googleapis.com/google.protobuf.Int32Value",
|
| @@ -1856,7 +2226,7 @@ bool ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner,
|
| }
|
| )");
|
| RunValidJsonTest(
|
| - "AnyWithDuration",
|
| + "AnyWithDuration", REQUIRED,
|
| R"({
|
| "optionalAny": {
|
| "@type": "type.googleapis.com/google.protobuf.Duration",
|
| @@ -1872,7 +2242,7 @@ bool ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner,
|
| }
|
| )");
|
| RunValidJsonTest(
|
| - "AnyWithTimestamp",
|
| + "AnyWithTimestamp", REQUIRED,
|
| R"({
|
| "optionalAny": {
|
| "@type": "type.googleapis.com/google.protobuf.Timestamp",
|
| @@ -1888,7 +2258,7 @@ bool ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner,
|
| }
|
| )");
|
| RunValidJsonTest(
|
| - "AnyWithFieldMask",
|
| + "AnyWithFieldMask", REQUIRED,
|
| R"({
|
| "optionalAny": {
|
| "@type": "type.googleapis.com/google.protobuf.FieldMask",
|
| @@ -1903,7 +2273,7 @@ bool ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner,
|
| }
|
| )");
|
| RunValidJsonTest(
|
| - "AnyWithStruct",
|
| + "AnyWithStruct", REQUIRED,
|
| R"({
|
| "optionalAny": {
|
| "@type": "type.googleapis.com/google.protobuf.Struct",
|
| @@ -1925,7 +2295,7 @@ bool ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner,
|
| }
|
| )");
|
| RunValidJsonTest(
|
| - "AnyWithValueForJsonObject",
|
| + "AnyWithValueForJsonObject", REQUIRED,
|
| R"({
|
| "optionalAny": {
|
| "@type": "type.googleapis.com/google.protobuf.Value",
|
| @@ -1949,7 +2319,7 @@ bool ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner,
|
| }
|
| )");
|
| RunValidJsonTest(
|
| - "AnyWithValueForInteger",
|
| + "AnyWithValueForInteger", REQUIRED,
|
| R"({
|
| "optionalAny": {
|
| "@type": "type.googleapis.com/google.protobuf.Value",
|
| @@ -1965,27 +2335,34 @@ bool ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner,
|
| )");
|
|
|
| bool ok = true;
|
| - if (!CheckSetEmpty(expected_to_fail_,
|
| + if (!CheckSetEmpty(expected_to_fail_, "nonexistent_tests.txt",
|
| "These tests were listed in the failure list, but they "
|
| - "don't exist. Remove them from the failure list")) {
|
| + "don't exist. Remove them from the failure list by "
|
| + "running:\n"
|
| + " ./update_failure_list.py " + failure_list_filename_ +
|
| + " --remove nonexistent_tests.txt")) {
|
| ok = false;
|
| }
|
| - if (!CheckSetEmpty(unexpected_failing_tests_,
|
| + if (!CheckSetEmpty(unexpected_failing_tests_, "failing_tests.txt",
|
| "These tests failed. If they can't be fixed right now, "
|
| "you can add them to the failure list so the overall "
|
| - "suite can succeed")) {
|
| + "suite can succeed. Add them to the failure list by "
|
| + "running:\n"
|
| + " ./update_failure_list.py " + failure_list_filename_ +
|
| + " --add failing_tests.txt")) {
|
| + ok = false;
|
| + }
|
| + if (!CheckSetEmpty(unexpected_succeeding_tests_, "succeeding_tests.txt",
|
| + "These tests succeeded, even though they were listed in "
|
| + "the failure list. Remove them from the failure list "
|
| + "by running:\n"
|
| + " ./update_failure_list.py " + failure_list_filename_ +
|
| + " --remove succeeding_tests.txt")) {
|
| ok = false;
|
| }
|
| -
|
| - // Sometimes the testee may be fixed before we update the failure list (e.g.,
|
| - // the testee is from a different component). We warn about this case but
|
| - // don't consider it an overall test failure.
|
| - CheckSetEmpty(unexpected_succeeding_tests_,
|
| - "These tests succeeded, even though they were listed in "
|
| - "the failure list. Remove them from the failure list");
|
|
|
| if (verbose_) {
|
| - CheckSetEmpty(skipped_,
|
| + CheckSetEmpty(skipped_, "",
|
| "These tests were skipped (probably because support for some "
|
| "features is not implemented)");
|
| }
|
|
|