blob: 8b70281b3e300af452a8e31614585929ddf01a1b [file] [edit]
// Protocol Buffers - Google's data interchange format
// Copyright 2026 Google LLC. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file or at
// https://developers.google.com/open-source/licenses/bsd
// JSON conformance tests for float and double fields: the value ranges,
// quoted values, the special values NaN / Infinity / -Infinity (which must be
// quoted), the normalization of non-canonical NaN bit patterns when
// serializing to JSON, and rejected out-of-range, empty, non-numeric and
// boolean values. This replaces the "Float fields" and "Double fields" blocks
// of the legacy BinaryAndJsonConformanceSuiteImpl<M>::
// RunJsonTestsForNonRepeatedTypes(); the test names and the requests sent to
// the testee are identical to the legacy ones, except that the NaN
// normalization tests are BINARY_TEST requests (see below).
//
// Like the legacy RunValidJsonTest(), each valid input is sent twice: once to
// be serialized as binary ("<name>.ProtobufOutput") and once as JSON
// ("<name>.JsonOutput"). ExpectParseFailureForJson() asked for JSON output
// under a name without an output suffix. The NaN normalization tests
// (RunValidJsonTestWithProtobufInput()) send a *binary* payload and ask for
// JSON output ("<S>.<E>.ProtobufInput.<name>.JsonOutput"); the legacy suite
// filed them under the JSON_TEST category, here ParseBinary() categorizes them
// as BINARY_TEST, which no testee tells apart from JSON_TEST on a binary
// payload (b/563657722).
#include <cstdint>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "absl/strings/string_view.h"
#include "conformance/binary_test_util.h"
#include "conformance/binary_wireformat.h"
#include "conformance/matchers.h"
#include "conformance/message_type_fixtures.h"
#include "conformance/testee.h"
namespace google {
namespace protobuf {
namespace conformance {
namespace {
using ::testing::ValuesIn;
// The field numbers of optional_float and optional_double, the same in every
// test message type.
constexpr uint32_t kOptionalFloatFieldNumber = 11;
constexpr uint32_t kOptionalDoubleFieldNumber = 12;
// ---------------------------------------------------------------------------
// Float fields.
// ---------------------------------------------------------------------------
using JsonFloatTest = MessageTypeConformanceTest;
TEST_P(JsonFloatTest, FloatFieldMinPositiveValue) {
constexpr absl::string_view kInput =
R"json({"optionalFloat": 1.175494e-38})json";
constexpr absl::string_view kExpected = R"pb(optional_float: 1.175494e-38)pb";
EXPECT_THAT(Testee("FloatFieldMinPositiveValue")
.ParseJson(message(), kInput)
.SerializeBinary(),
Yields(WhenParsed(EqualsTextProto(kExpected))));
EXPECT_THAT(Testee("FloatFieldMinPositiveValue")
.ParseJson(message(), kInput)
.SerializeJson(),
Yields(WhenParsed(EqualsTextProto(kExpected))));
}
TEST_P(JsonFloatTest, FloatFieldMaxNegativeValue) {
constexpr absl::string_view kInput =
R"json({"optionalFloat": -1.175494e-38})json";
constexpr absl::string_view kExpected =
R"pb(optional_float: -1.175494e-38)pb";
EXPECT_THAT(Testee("FloatFieldMaxNegativeValue")
.ParseJson(message(), kInput)
.SerializeBinary(),
Yields(WhenParsed(EqualsTextProto(kExpected))));
EXPECT_THAT(Testee("FloatFieldMaxNegativeValue")
.ParseJson(message(), kInput)
.SerializeJson(),
Yields(WhenParsed(EqualsTextProto(kExpected))));
}
TEST_P(JsonFloatTest, FloatFieldMaxPositiveValue) {
constexpr absl::string_view kInput =
R"json({"optionalFloat": 3.402823e+38})json";
constexpr absl::string_view kExpected = R"pb(optional_float: 3.402823e+38)pb";
EXPECT_THAT(Testee("FloatFieldMaxPositiveValue")
.ParseJson(message(), kInput)
.SerializeBinary(),
Yields(WhenParsed(EqualsTextProto(kExpected))));
EXPECT_THAT(Testee("FloatFieldMaxPositiveValue")
.ParseJson(message(), kInput)
.SerializeJson(),
Yields(WhenParsed(EqualsTextProto(kExpected))));
}
// Sends the same (positive) value as FloatFieldMaxPositiveValue, like the
// legacy suite did.
TEST_P(JsonFloatTest, FloatFieldMinNegativeValue) {
constexpr absl::string_view kInput =
R"json({"optionalFloat": 3.402823e+38})json";
constexpr absl::string_view kExpected = R"pb(optional_float: 3.402823e+38)pb";
EXPECT_THAT(Testee("FloatFieldMinNegativeValue")
.ParseJson(message(), kInput)
.SerializeBinary(),
Yields(WhenParsed(EqualsTextProto(kExpected))));
EXPECT_THAT(Testee("FloatFieldMinNegativeValue")
.ParseJson(message(), kInput)
.SerializeJson(),
Yields(WhenParsed(EqualsTextProto(kExpected))));
}
// Values can be quoted.
TEST_P(JsonFloatTest, FloatFieldQuotedValue) {
constexpr absl::string_view kInput = R"json({"optionalFloat": "1"})json";
constexpr absl::string_view kExpected = R"pb(optional_float: 1)pb";
EXPECT_THAT(Testee("FloatFieldQuotedValue")
.ParseJson(message(), kInput)
.SerializeBinary(),
Yields(WhenParsed(EqualsTextProto(kExpected))));
EXPECT_THAT(Testee("FloatFieldQuotedValue")
.ParseJson(message(), kInput)
.SerializeJson(),
Yields(WhenParsed(EqualsTextProto(kExpected))));
}
TEST_P(JsonFloatTest, FloatFieldQuotedExponentialValue) {
constexpr absl::string_view kInput =
R"json({"optionalFloat": "1.175494e-38"})json";
constexpr absl::string_view kExpected = R"pb(optional_float: 1.175494e-38)pb";
EXPECT_THAT(Testee("FloatFieldQuotedExponentialValue")
.ParseJson(message(), kInput)
.SerializeBinary(),
Yields(WhenParsed(EqualsTextProto(kExpected))));
EXPECT_THAT(Testee("FloatFieldQuotedExponentialValue")
.ParseJson(message(), kInput)
.SerializeJson(),
Yields(WhenParsed(EqualsTextProto(kExpected))));
}
// Special values.
TEST_P(JsonFloatTest, FloatFieldNan) {
constexpr absl::string_view kInput = R"json({"optionalFloat": "NaN"})json";
constexpr absl::string_view kExpected = R"pb(optional_float: nan)pb";
EXPECT_THAT(
Testee("FloatFieldNan").ParseJson(message(), kInput).SerializeBinary(),
Yields(WhenParsed(EqualsTextProto(kExpected))));
EXPECT_THAT(
Testee("FloatFieldNan").ParseJson(message(), kInput).SerializeJson(),
Yields(WhenParsed(EqualsTextProto(kExpected))));
}
TEST_P(JsonFloatTest, FloatFieldInfinity) {
constexpr absl::string_view kInput =
R"json({"optionalFloat": "Infinity"})json";
constexpr absl::string_view kExpected = R"pb(optional_float: inf)pb";
EXPECT_THAT(Testee("FloatFieldInfinity")
.ParseJson(message(), kInput)
.SerializeBinary(),
Yields(WhenParsed(EqualsTextProto(kExpected))));
EXPECT_THAT(
Testee("FloatFieldInfinity").ParseJson(message(), kInput).SerializeJson(),
Yields(WhenParsed(EqualsTextProto(kExpected))));
}
TEST_P(JsonFloatTest, FloatFieldNegativeInfinity) {
constexpr absl::string_view kInput =
R"json({"optionalFloat": "-Infinity"})json";
constexpr absl::string_view kExpected = R"pb(optional_float: -inf)pb";
EXPECT_THAT(Testee("FloatFieldNegativeInfinity")
.ParseJson(message(), kInput)
.SerializeBinary(),
Yields(WhenParsed(EqualsTextProto(kExpected))));
EXPECT_THAT(Testee("FloatFieldNegativeInfinity")
.ParseJson(message(), kInput)
.SerializeJson(),
Yields(WhenParsed(EqualsTextProto(kExpected))));
}
// Non-canonical NaNs are normalized: the binary payload carries a NaN with
// a non-canonical payload (0x7FA12345; the legacy names notwithstanding,
// bit 22 is clear in both patterns, so both are signaling NaNs), ...
TEST_P(JsonFloatTest, FloatFieldNormalizeQuietNan) {
EXPECT_THAT(
Testee("FloatFieldNormalizeQuietNan")
.ParseBinary(message(),
Fixed32Field(kOptionalFloatFieldNumber, 0x7FA12345))
.SerializeJson(),
Yields(WhenParsed(EqualsTextProto(R"pb(optional_float: nan)pb"))));
}
// ... or a NaN with the sign bit set and another payload (0xFFB54321).
TEST_P(JsonFloatTest, FloatFieldNormalizeSignalingNan) {
EXPECT_THAT(
Testee("FloatFieldNormalizeSignalingNan")
.ParseBinary(message(),
Fixed32Field(kOptionalFloatFieldNumber, 0xFFB54321))
.SerializeJson(),
Yields(WhenParsed(EqualsTextProto(R"pb(optional_float: nan)pb"))));
}
// Special values must be quoted.
TEST_P(JsonFloatTest, FloatFieldNanNotQuoted) {
EXPECT_THAT(Testee(kP1, "FloatFieldNanNotQuoted")
.ParseJson(message(), R"json({"optionalFloat": NaN})json")
.ParseOnly(),
Yields(IsParseError()));
}
TEST_P(JsonFloatTest, FloatFieldInfinityNotQuoted) {
EXPECT_THAT(
Testee(kP1, "FloatFieldInfinityNotQuoted")
.ParseJson(message(), R"json({"optionalFloat": Infinity})json")
.ParseOnly(),
Yields(IsParseError()));
}
TEST_P(JsonFloatTest, FloatFieldNegativeInfinityNotQuoted) {
EXPECT_THAT(
Testee(kP1, "FloatFieldNegativeInfinityNotQuoted")
.ParseJson(message(), R"json({"optionalFloat": -Infinity})json")
.ParseOnly(),
Yields(IsParseError()));
}
// Parsers should reject out-of-bound values.
TEST_P(JsonFloatTest, FloatFieldTooSmall) {
EXPECT_THAT(
Testee("FloatFieldTooSmall")
.ParseJson(message(), R"json({"optionalFloat": -3.502823e+38})json")
.ParseOnly(),
Yields(IsParseError()));
}
TEST_P(JsonFloatTest, FloatFieldTooLarge) {
EXPECT_THAT(
Testee("FloatFieldTooLarge")
.ParseJson(message(), R"json({"optionalFloat": 3.502823e+38})json")
.ParseOnly(),
Yields(IsParseError()));
}
// Parsers should reject empty string values.
TEST_P(JsonFloatTest, FloatFieldEmptyString) {
EXPECT_THAT(Testee("FloatFieldEmptyString")
.ParseJson(message(), R"json({"optionalFloat": ""})json")
.ParseOnly(),
Yields(IsParseError()));
}
// Parsers reject non-numeric string values.
TEST_P(JsonFloatTest, FloatFieldStringValuePartiallyNumeric) {
EXPECT_THAT(Testee("FloatFieldStringValuePartiallyNumeric")
.ParseJson(message(), R"json({"optionalFloat": "12abc"})json")
.ParseOnly(),
Yields(IsParseError()));
}
TEST_P(JsonFloatTest, FloatFieldStringValueNonNumeric) {
EXPECT_THAT(Testee("FloatFieldStringValueNonNumeric")
.ParseJson(message(), R"json({"optionalFloat": "abc"})json")
.ParseOnly(),
Yields(IsParseError()));
}
TEST_P(JsonFloatTest, FloatFieldStringValuePartiallyNumericSpace) {
EXPECT_THAT(Testee("FloatFieldStringValuePartiallyNumericSpace")
.ParseJson(message(), R"json({"optionalFloat": "12 34"})json")
.ParseOnly(),
Yields(IsParseError()));
}
TEST_P(JsonFloatTest, FloatFieldStringValuePartiallyNumericComma) {
EXPECT_THAT(Testee("FloatFieldStringValuePartiallyNumericComma")
.ParseJson(message(), R"json({"optionalFloat": "12,34"})json")
.ParseOnly(),
Yields(IsParseError()));
}
TEST_P(JsonFloatTest, FloatFieldStringValuePartiallyNumericUnicode) {
// Not a raw string literal: the payload holds the UTF-8 bytes of U+8C37
// U+6B4C between the digits.
EXPECT_THAT(Testee("FloatFieldStringValuePartiallyNumericUnicode")
.ParseJson(message(),
"{\"optionalFloat\": \"12\xE8\xB0\xB7\xE6\xAD\x8C"
"34\"}")
.ParseOnly(),
Yields(IsParseError()));
}
// Only ASCII digits are accepted in quoted numbers. Not raw string
// literals: the payloads hold the UTF-8 bytes of the Arabic-Indic digits
// U+0661 U+0662 U+0663 and of the fullwidth digits U+FF11 U+FF12 U+FF13.
TEST_P(JsonFloatTest, FloatFieldStringValueArabicIndicDigits) {
constexpr absl::string_view kInput =
"{\"optionalFloat\": \"\xD9\xA1\xD9\xA2\xD9\xA3\"}";
EXPECT_THAT(Testee("FloatFieldStringValueArabicIndicDigits")
.ParseJson(message(), kInput)
.ParseOnly(),
Yields(IsParseError()));
}
TEST_P(JsonFloatTest, FloatFieldStringValueFullwidthDigits) {
constexpr absl::string_view kInput =
"{\"optionalFloat\": \"\xEF\xBC\x91\xEF\xBC\x92\xEF\xBC\x93\"}";
EXPECT_THAT(Testee("FloatFieldStringValueFullwidthDigits")
.ParseJson(message(), kInput)
.ParseOnly(),
Yields(IsParseError()));
}
// Parsers reject boolean values for float fields.
TEST_P(JsonFloatTest, FloatFieldTrueValue) {
EXPECT_THAT(Testee("FloatFieldTrueValue")
.ParseJson(message(), R"json({"optionalFloat": true})json")
.ParseOnly(),
Yields(IsParseError()));
}
TEST_P(JsonFloatTest, FloatFieldFalseValue) {
EXPECT_THAT(Testee("FloatFieldFalseValue")
.ParseJson(message(), R"json({"optionalFloat": false})json")
.ParseOnly(),
Yields(IsParseError()));
}
INSTANTIATE_TEST_SUITE_P(All, JsonFloatTest, ValuesIn(AllTestMessageTypes()),
MessageTypeParamName);
// ---------------------------------------------------------------------------
// Double fields.
// ---------------------------------------------------------------------------
using JsonDoubleTest = MessageTypeConformanceTest;
TEST_P(JsonDoubleTest, DoubleFieldMinPositiveValue) {
constexpr absl::string_view kInput =
R"json({"optionalDouble": 2.22507e-308})json";
constexpr absl::string_view kExpected =
R"pb(optional_double: 2.22507e-308)pb";
EXPECT_THAT(Testee("DoubleFieldMinPositiveValue")
.ParseJson(message(), kInput)
.SerializeBinary(),
Yields(WhenParsed(EqualsTextProto(kExpected))));
EXPECT_THAT(Testee("DoubleFieldMinPositiveValue")
.ParseJson(message(), kInput)
.SerializeJson(),
Yields(WhenParsed(EqualsTextProto(kExpected))));
}
TEST_P(JsonDoubleTest, DoubleFieldMaxNegativeValue) {
constexpr absl::string_view kInput =
R"json({"optionalDouble": -2.22507e-308})json";
constexpr absl::string_view kExpected =
R"pb(optional_double: -2.22507e-308)pb";
EXPECT_THAT(Testee("DoubleFieldMaxNegativeValue")
.ParseJson(message(), kInput)
.SerializeBinary(),
Yields(WhenParsed(EqualsTextProto(kExpected))));
EXPECT_THAT(Testee("DoubleFieldMaxNegativeValue")
.ParseJson(message(), kInput)
.SerializeJson(),
Yields(WhenParsed(EqualsTextProto(kExpected))));
}
TEST_P(JsonDoubleTest, DoubleFieldMaxPositiveValue) {
constexpr absl::string_view kInput =
R"json({"optionalDouble": 1.79769e+308})json";
constexpr absl::string_view kExpected =
R"pb(optional_double: 1.79769e+308)pb";
EXPECT_THAT(Testee("DoubleFieldMaxPositiveValue")
.ParseJson(message(), kInput)
.SerializeBinary(),
Yields(WhenParsed(EqualsTextProto(kExpected))));
EXPECT_THAT(Testee("DoubleFieldMaxPositiveValue")
.ParseJson(message(), kInput)
.SerializeJson(),
Yields(WhenParsed(EqualsTextProto(kExpected))));
}
TEST_P(JsonDoubleTest, DoubleFieldMinNegativeValue) {
constexpr absl::string_view kInput =
R"json({"optionalDouble": -1.79769e+308})json";
constexpr absl::string_view kExpected =
R"pb(optional_double: -1.79769e+308)pb";
EXPECT_THAT(Testee("DoubleFieldMinNegativeValue")
.ParseJson(message(), kInput)
.SerializeBinary(),
Yields(WhenParsed(EqualsTextProto(kExpected))));
EXPECT_THAT(Testee("DoubleFieldMinNegativeValue")
.ParseJson(message(), kInput)
.SerializeJson(),
Yields(WhenParsed(EqualsTextProto(kExpected))));
}
// Values can be quoted.
TEST_P(JsonDoubleTest, DoubleFieldQuotedValue) {
constexpr absl::string_view kInput = R"json({"optionalDouble": "1"})json";
constexpr absl::string_view kExpected = R"pb(optional_double: 1)pb";
EXPECT_THAT(Testee("DoubleFieldQuotedValue")
.ParseJson(message(), kInput)
.SerializeBinary(),
Yields(WhenParsed(EqualsTextProto(kExpected))));
EXPECT_THAT(Testee("DoubleFieldQuotedValue")
.ParseJson(message(), kInput)
.SerializeJson(),
Yields(WhenParsed(EqualsTextProto(kExpected))));
}
TEST_P(JsonDoubleTest, DoubleFieldQuotedExponentialValue) {
constexpr absl::string_view kInput =
R"json({"optionalDouble": "2.22507e-308"})json";
constexpr absl::string_view kExpected =
R"pb(optional_double: 2.22507e-308)pb";
EXPECT_THAT(Testee("DoubleFieldQuotedExponentialValue")
.ParseJson(message(), kInput)
.SerializeBinary(),
Yields(WhenParsed(EqualsTextProto(kExpected))));
EXPECT_THAT(Testee("DoubleFieldQuotedExponentialValue")
.ParseJson(message(), kInput)
.SerializeJson(),
Yields(WhenParsed(EqualsTextProto(kExpected))));
}
// Special values.
TEST_P(JsonDoubleTest, DoubleFieldNan) {
constexpr absl::string_view kInput = R"json({"optionalDouble": "NaN"})json";
constexpr absl::string_view kExpected = R"pb(optional_double: nan)pb";
EXPECT_THAT(
Testee("DoubleFieldNan").ParseJson(message(), kInput).SerializeBinary(),
Yields(WhenParsed(EqualsTextProto(kExpected))));
EXPECT_THAT(
Testee("DoubleFieldNan").ParseJson(message(), kInput).SerializeJson(),
Yields(WhenParsed(EqualsTextProto(kExpected))));
}
TEST_P(JsonDoubleTest, DoubleFieldInfinity) {
constexpr absl::string_view kInput =
R"json({"optionalDouble": "Infinity"})json";
constexpr absl::string_view kExpected = R"pb(optional_double: inf)pb";
EXPECT_THAT(Testee("DoubleFieldInfinity")
.ParseJson(message(), kInput)
.SerializeBinary(),
Yields(WhenParsed(EqualsTextProto(kExpected))));
EXPECT_THAT(Testee("DoubleFieldInfinity")
.ParseJson(message(), kInput)
.SerializeJson(),
Yields(WhenParsed(EqualsTextProto(kExpected))));
}
TEST_P(JsonDoubleTest, DoubleFieldNegativeInfinity) {
constexpr absl::string_view kInput =
R"json({"optionalDouble": "-Infinity"})json";
constexpr absl::string_view kExpected = R"pb(optional_double: -inf)pb";
EXPECT_THAT(Testee("DoubleFieldNegativeInfinity")
.ParseJson(message(), kInput)
.SerializeBinary(),
Yields(WhenParsed(EqualsTextProto(kExpected))));
EXPECT_THAT(Testee("DoubleFieldNegativeInfinity")
.ParseJson(message(), kInput)
.SerializeJson(),
Yields(WhenParsed(EqualsTextProto(kExpected))));
}
// Non-canonical NaNs are normalized, as for floats above.
TEST_P(JsonDoubleTest, DoubleFieldNormalizeQuietNan) {
EXPECT_THAT(
Testee("DoubleFieldNormalizeQuietNan")
.ParseBinary(message(), Fixed64Field(kOptionalDoubleFieldNumber,
0x7FFA123456789ABC))
.SerializeJson(),
Yields(WhenParsed(EqualsTextProto(R"pb(optional_double: nan)pb"))));
}
TEST_P(JsonDoubleTest, DoubleFieldNormalizeSignalingNan) {
EXPECT_THAT(
Testee("DoubleFieldNormalizeSignalingNan")
.ParseBinary(message(), Fixed64Field(kOptionalDoubleFieldNumber,
0xFFFBCBA987654321))
.SerializeJson(),
Yields(WhenParsed(EqualsTextProto(R"pb(optional_double: nan)pb"))));
}
// Special values must be quoted.
TEST_P(JsonDoubleTest, DoubleFieldNanNotQuoted) {
EXPECT_THAT(Testee(kP1, "DoubleFieldNanNotQuoted")
.ParseJson(message(), R"json({"optionalDouble": NaN})json")
.ParseOnly(),
Yields(IsParseError()));
}
TEST_P(JsonDoubleTest, DoubleFieldInfinityNotQuoted) {
EXPECT_THAT(
Testee(kP1, "DoubleFieldInfinityNotQuoted")
.ParseJson(message(), R"json({"optionalDouble": Infinity})json")
.ParseOnly(),
Yields(IsParseError()));
}
TEST_P(JsonDoubleTest, DoubleFieldNegativeInfinityNotQuoted) {
EXPECT_THAT(
Testee(kP1, "DoubleFieldNegativeInfinityNotQuoted")
.ParseJson(message(), R"json({"optionalDouble": -Infinity})json")
.ParseOnly(),
Yields(IsParseError()));
}
// Parsers should reject out-of-bound values.
TEST_P(JsonDoubleTest, DoubleFieldTooSmall) {
EXPECT_THAT(
Testee("DoubleFieldTooSmall")
.ParseJson(message(), R"json({"optionalDouble": -1.89769e+308})json")
.ParseOnly(),
Yields(IsParseError()));
}
TEST_P(JsonDoubleTest, DoubleFieldTooLarge) {
EXPECT_THAT(
Testee("DoubleFieldTooLarge")
.ParseJson(message(), R"json({"optionalDouble": 1.89769e+308})json")
.ParseOnly(),
Yields(IsParseError()));
}
// Parsers should reject empty string values.
TEST_P(JsonDoubleTest, DoubleFieldEmptyString) {
EXPECT_THAT(Testee("DoubleFieldEmptyString")
.ParseJson(message(), R"json({"optionalDouble": ""})json")
.ParseOnly(),
Yields(IsParseError()));
}
// Parsers reject non-numeric string values.
TEST_P(JsonDoubleTest, DoubleFieldStringValuePartiallyNumeric) {
EXPECT_THAT(
Testee("DoubleFieldStringValuePartiallyNumeric")
.ParseJson(message(), R"json({"optionalDouble": "12abc"})json")
.ParseOnly(),
Yields(IsParseError()));
}
TEST_P(JsonDoubleTest, DoubleFieldStringValueNonNumeric) {
EXPECT_THAT(Testee("DoubleFieldStringValueNonNumeric")
.ParseJson(message(), R"json({"optionalDouble": "abc"})json")
.ParseOnly(),
Yields(IsParseError()));
}
// Only ASCII digits are accepted in quoted numbers. Not raw string
// literals: the payloads hold the UTF-8 bytes of the Arabic-Indic digits
// U+0661 U+0662 U+0663 and of the fullwidth digits U+FF11 U+FF12 U+FF13.
TEST_P(JsonDoubleTest, DoubleFieldStringValueArabicIndicDigits) {
constexpr absl::string_view kInput =
"{\"optionalDouble\": \"\xD9\xA1\xD9\xA2\xD9\xA3\"}";
EXPECT_THAT(Testee("DoubleFieldStringValueArabicIndicDigits")
.ParseJson(message(), kInput)
.ParseOnly(),
Yields(IsParseError()));
}
TEST_P(JsonDoubleTest, DoubleFieldStringValueFullwidthDigits) {
constexpr absl::string_view kInput =
"{\"optionalDouble\": \"\xEF\xBC\x91\xEF\xBC\x92\xEF\xBC\x93\"}";
EXPECT_THAT(Testee("DoubleFieldStringValueFullwidthDigits")
.ParseJson(message(), kInput)
.ParseOnly(),
Yields(IsParseError()));
}
// Parsers reject boolean values for double fields.
TEST_P(JsonDoubleTest, DoubleFieldTrueValue) {
EXPECT_THAT(Testee("DoubleFieldTrueValue")
.ParseJson(message(), R"json({"optionalDouble": true})json")
.ParseOnly(),
Yields(IsParseError()));
}
TEST_P(JsonDoubleTest, DoubleFieldFalseValue) {
EXPECT_THAT(Testee("DoubleFieldFalseValue")
.ParseJson(message(), R"json({"optionalDouble": false})json")
.ParseOnly(),
Yields(IsParseError()));
}
INSTANTIATE_TEST_SUITE_P(All, JsonDoubleTest, ValuesIn(AllTestMessageTypes()),
MessageTypeParamName);
} // namespace
} // namespace conformance
} // namespace protobuf
} // namespace google