|
|
|
@ -64,6 +64,11 @@ |
|
|
|
|
// Must be included last.
|
|
|
|
|
#include <google/protobuf/port_def.inc> |
|
|
|
|
|
|
|
|
|
bool IsJson2() { |
|
|
|
|
// Pay no attention to the person behind the curtain.
|
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
namespace google { |
|
|
|
|
namespace protobuf { |
|
|
|
|
namespace util { |
|
|
|
@ -76,6 +81,7 @@ using ::proto3::TestOneof; |
|
|
|
|
using ::proto3::TestWrapper; |
|
|
|
|
using ::proto_util_converter::testing::MapIn; |
|
|
|
|
using ::testing::ElementsAre; |
|
|
|
|
using ::testing::Not; |
|
|
|
|
using ::testing::SizeIs; |
|
|
|
|
|
|
|
|
|
// TODO(b/234474291): Use the gtest versions once that's available in OSS.
|
|
|
|
@ -274,20 +280,37 @@ TEST_P(JsonTest, TestDefaultValues) { |
|
|
|
|
|
|
|
|
|
// The ESF parser actually gets this wrong, and serializes floats whose
|
|
|
|
|
// default value is non-finite as 0. We make sure to reproduce this bug.
|
|
|
|
|
EXPECT_THAT( |
|
|
|
|
ToJson(protobuf_unittest::TestExtremeDefaultValues(), options), |
|
|
|
|
IsOkAndHolds( |
|
|
|
|
R"({"escapedBytes":"XDAwMFwwMDFcMDA3XDAxMFwwMTRcblxyXHRcMDEzXFxcJ1wiXDM3Ng==")" |
|
|
|
|
R"(,"largeUint32":4294967295,"largeUint64":"18446744073709551615",)" |
|
|
|
|
R"("smallInt32":-2147483647,"smallInt64":"-9223372036854775807")" |
|
|
|
|
R"(,"reallySmallInt32":-2147483648,"reallySmallInt64":"-9223372036854775808",)" |
|
|
|
|
R"("utf8String":"ሴ","zeroFloat":0,"oneFloat":1,"smallFloat":1.5,)" |
|
|
|
|
R"("negativeOneFloat":-1,"negativeFloat":-1.5,"largeFloat":2e+08,)" |
|
|
|
|
R"("smallNegativeFloat":-8e-28,"infDouble":0,"negInfDouble":0)" |
|
|
|
|
R"(,"nanDouble":0,"infFloat":0,"negInfFloat":0,"nanFloat":0)" |
|
|
|
|
R"(,"cppTrigraph":"? ? ?? ?? ??? ??/ ??-","stringWithZero":"hel\u0000lo")" |
|
|
|
|
R"(,"bytesWithZero":"d29yXDAwMGxk","stringPieceWithZero":"ab\u0000c")" |
|
|
|
|
R"(,"cordWithZero":"12\u00003","replacementString":"${unknown}"})")); |
|
|
|
|
if (IsJson2()) { |
|
|
|
|
EXPECT_THAT( |
|
|
|
|
ToJson(protobuf_unittest::TestExtremeDefaultValues(), options), |
|
|
|
|
IsOkAndHolds( |
|
|
|
|
R"({"escapedBytes":"XDAwMFwwMDFcMDA3XDAxMFwwMTRcblxyXHRcMDEzXFxcJ1wiXDM3Ng==")" |
|
|
|
|
R"(,"largeUint32":4294967295,"largeUint64":"18446744073709551615",)" |
|
|
|
|
R"("smallInt32":-2147483647,"smallInt64":"-9223372036854775807",)" |
|
|
|
|
R"("utf8String":"ሴ","zeroFloat":0,"oneFloat":1,"smallFloat":1.5,)" |
|
|
|
|
R"("negativeOneFloat":-1,"negativeFloat":-1.5,"largeFloat":2e+08,)" |
|
|
|
|
R"("smallNegativeFloat":-8e-28,"infDouble":0,"negInfDouble":0,)" |
|
|
|
|
R"("nanDouble":0,"infFloat":0,"negInfFloat":0,"nanFloat":0,)" |
|
|
|
|
R"("cppTrigraph":"? ? ?? ?? ??? ??/ ??-","reallySmallInt32":-2147483648)" |
|
|
|
|
R"(,"reallySmallInt64":"-9223372036854775808","stringWithZero":"hel\u0000lo")" |
|
|
|
|
R"(,"bytesWithZero":"d29yXDAwMGxk","stringPieceWithZero":"ab\u0000c")" |
|
|
|
|
R"(,"cordWithZero":"12\u00003","replacementString":"${unknown}"})")); |
|
|
|
|
} else { |
|
|
|
|
EXPECT_THAT( |
|
|
|
|
ToJson(protobuf_unittest::TestExtremeDefaultValues(), options), |
|
|
|
|
IsOkAndHolds( |
|
|
|
|
R"({"escapedBytes":"XDAwMFwwMDFcMDA3XDAxMFwwMTRcblxyXHRcMDEzXFxcJ1wiXDM3Ng==")" |
|
|
|
|
R"(,"largeUint32":4294967295,"largeUint64":"18446744073709551615",)" |
|
|
|
|
R"("smallInt32":-2147483647,"smallInt64":"-9223372036854775807")" |
|
|
|
|
R"(,"reallySmallInt32":-2147483648,"reallySmallInt64":"-9223372036854775808",)" |
|
|
|
|
R"("utf8String":"ሴ","zeroFloat":0,"oneFloat":1,"smallFloat":1.5,)" |
|
|
|
|
R"("negativeOneFloat":-1,"negativeFloat":-1.5,"largeFloat":2e+08,)" |
|
|
|
|
R"("smallNegativeFloat":-8e-28,"infDouble":0,"negInfDouble":0)" |
|
|
|
|
R"(,"nanDouble":0,"infFloat":0,"negInfFloat":0,"nanFloat":0)" |
|
|
|
|
R"(,"cppTrigraph":"? ? ?? ?? ??? ??/ ??-","stringWithZero":"hel\u0000lo")" |
|
|
|
|
R"(,"bytesWithZero":"d29yXDAwMGxk","stringPieceWithZero":"ab\u0000c")" |
|
|
|
|
R"(,"cordWithZero":"12\u00003","replacementString":"${unknown}"})")); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
TEST_P(JsonTest, TestPreserveProtoFieldNames) { |
|
|
|
@ -762,6 +785,20 @@ TEST_P(JsonTest, TestParsingBrokenAny) { |
|
|
|
|
} |
|
|
|
|
)json"), |
|
|
|
|
StatusIs(util::StatusCode::kInvalidArgument)); |
|
|
|
|
|
|
|
|
|
TestAny m2; |
|
|
|
|
m2.mutable_value(); |
|
|
|
|
EXPECT_THAT(ToJson(m2), IsOkAndHolds(R"({"value":{}})")); |
|
|
|
|
m2.mutable_value()->set_value("garbage"); |
|
|
|
|
// The ESF parser does not return InvalidArgument for this error.
|
|
|
|
|
EXPECT_THAT(ToJson(m2), Not(StatusIs(util::StatusCode::kOk))); |
|
|
|
|
|
|
|
|
|
m2.Clear(); |
|
|
|
|
m2.mutable_value()->set_type_url("type.googleapis.com/proto3.TestMessage"); |
|
|
|
|
EXPECT_THAT( |
|
|
|
|
ToJson(m2), |
|
|
|
|
IsOkAndHolds( |
|
|
|
|
R"({"value":{"@type":"type.googleapis.com/proto3.TestMessage"}})")); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
TEST_P(JsonTest, TestFlatList) { |
|
|
|
@ -952,6 +989,37 @@ TEST_P(JsonTest, TestParsingEnumIgnoreCase) { |
|
|
|
|
EXPECT_EQ(m.enum_value(), proto3::BAR); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// This functionality is not correctly implemented by the ESF parser, so
|
|
|
|
|
// the test is only turned on when testing json2.
|
|
|
|
|
TEST_P(JsonTest, Extensions) { |
|
|
|
|
if (GetParam() == Codec::kResolver || !IsJson2()) { |
|
|
|
|
GTEST_SKIP(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
auto m = ToProto<protobuf_unittest::TestMixedFieldsAndExtensions>(R"json({ |
|
|
|
|
"[protobuf_unittest.TestMixedFieldsAndExtensions.c]": 42, |
|
|
|
|
"a": 5, |
|
|
|
|
"b": [1, 2, 3], |
|
|
|
|
"[protobuf_unittest.TestMixedFieldsAndExtensions.d]": [1, 1, 2, 3, 5, 8, 13] |
|
|
|
|
})json"); |
|
|
|
|
ASSERT_OK(m); |
|
|
|
|
EXPECT_EQ(m->a(), 5); |
|
|
|
|
EXPECT_THAT(m->b(), ElementsAre(1, 2, 3)); |
|
|
|
|
EXPECT_EQ(m->GetExtension(protobuf_unittest::TestMixedFieldsAndExtensions::c), |
|
|
|
|
42); |
|
|
|
|
EXPECT_THAT( |
|
|
|
|
m->GetRepeatedExtension(protobuf_unittest::TestMixedFieldsAndExtensions::d), |
|
|
|
|
ElementsAre(1, 1, 2, 3, 5, 8, 13)); |
|
|
|
|
|
|
|
|
|
EXPECT_THAT( |
|
|
|
|
ToJson(*m), |
|
|
|
|
IsOkAndHolds( |
|
|
|
|
R"({"a":5,)" |
|
|
|
|
R"("[protobuf_unittest.TestMixedFieldsAndExtensions.c]":42,)" |
|
|
|
|
R"("b":[1,2,3],)" |
|
|
|
|
R"("[protobuf_unittest.TestMixedFieldsAndExtensions.d]":[1,1,2,3,5,8,13]})")); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Parsing does NOT work like MergeFrom: existing repeated field values are
|
|
|
|
|
// clobbered, not appended to.
|
|
|
|
|
TEST_P(JsonTest, TestOverwriteRepeated) { |
|
|
|
@ -1158,6 +1226,34 @@ TEST_P(JsonTest, HtmlEscape) { |
|
|
|
|
m.set_string_value("</script>"); |
|
|
|
|
EXPECT_THAT(ToJson(m), |
|
|
|
|
IsOkAndHolds(R"({"stringValue":"\u003c/script\u003e"})")); |
|
|
|
|
|
|
|
|
|
proto3::TestEvilJson m2; |
|
|
|
|
JsonPrintOptions opts; |
|
|
|
|
opts.always_print_primitive_fields = true; |
|
|
|
|
EXPECT_THAT( |
|
|
|
|
ToJson(m2, opts), |
|
|
|
|
IsOkAndHolds( |
|
|
|
|
R"({"regular_name":0,"\u003c/script\u003e":0,)" |
|
|
|
|
R"("unbalanced\"quotes":0,)" |
|
|
|
|
R"("\"\u003cscript\u003ealert('hello!);\u003c/script\u003e":0})")); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
TEST_P(JsonTest, FieldOrder) { |
|
|
|
|
// $ protoscope -s <<< "3: 3 22: 2 1: 1 22: 2"
|
|
|
|
|
std::string out; |
|
|
|
|
util::Status s = BinaryToJsonString( |
|
|
|
|
resolver_.get(), "type.googleapis.com/proto3.TestMessage", |
|
|
|
|
"\x18\x03\xb0\x01\x02\x08\x01\xb0\x01\x02", &out); |
|
|
|
|
ASSERT_OK(s); |
|
|
|
|
if (IsJson2()) { |
|
|
|
|
EXPECT_EQ( |
|
|
|
|
out, |
|
|
|
|
R"({"boolValue":true,"int64Value":"3","repeatedInt32Value":[2,2]})"); |
|
|
|
|
} else { |
|
|
|
|
EXPECT_EQ( |
|
|
|
|
out, |
|
|
|
|
R"({"int64Value":"3","repeatedInt32Value":[2],"boolValue":true,"repeatedInt32Value":[2]})"); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} // namespace
|
|
|
|
|