Skip to content

Commit

Permalink
Merge pull request #10263 from acozzette/sync-stage
Browse files Browse the repository at this point in the history
Integrate from Piper for C++, Java, and Python
  • Loading branch information
acozzette authored Jul 19, 2022
2 parents 42d79a9 + 838db5a commit df6bb50
Show file tree
Hide file tree
Showing 11 changed files with 171 additions and 19 deletions.
6 changes: 6 additions & 0 deletions conformance/binary_json_conformance_suite.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2724,6 +2724,12 @@ void BinaryAndJsonConformanceSuite::RunJsonTestsForWrapperTypes() {
"DurationNull", REQUIRED,
R"({"optionalDuration": null})",
"");
RunValidJsonTest("DurationNegativeSeconds", REQUIRED,
R"({"optionalDuration": "-5s"})",
"optional_duration: {seconds: -5 nanos: 0}");
RunValidJsonTest("DurationNegativeNanos", REQUIRED,
R"({"optionalDuration": "-0.5s"})",
"optional_duration: {seconds: 0 nanos: -500000000}");

ExpectParseFailureForJson(
"DurationMissingS", REQUIRED,
Expand Down
2 changes: 2 additions & 0 deletions conformance/failure_list_php.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ Recommended.Proto3.JsonInput.FieldMaskInvalidCharacter
Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.MESSAGE.Merge.ProtobufOutput
Required.Proto2.JsonInput.StoresDefaultPrimitive.Validator
Required.Proto3.JsonInput.DoubleFieldTooSmall
Required.Proto3.JsonInput.DurationNegativeNanos.JsonOutput
Required.Proto3.JsonInput.DurationNegativeNanos.ProtobufOutput
Required.Proto3.JsonInput.FloatFieldTooLarge
Required.Proto3.JsonInput.FloatFieldTooSmall
Required.Proto3.JsonInput.Int32FieldNotInteger
Expand Down
3 changes: 3 additions & 0 deletions conformance/failure_list_php_c.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
Recommended.Proto2.JsonInput.FieldNameExtension.Validator
Required.Proto2.JsonInput.StoresDefaultPrimitive.Validator
Required.Proto3.JsonInput.DurationNegativeNanos.JsonOutput
Required.Proto3.JsonInput.DurationNegativeNanos.ProtobufOutput
Required.Proto3.JsonInput.DurationNegativeSeconds.JsonOutput
3 changes: 3 additions & 0 deletions conformance/failure_list_ruby.txt
Original file line number Diff line number Diff line change
Expand Up @@ -56,3 +56,6 @@ Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT32.PackedInput.UnpackedOu
Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT32.UnpackedInput.UnpackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT64.PackedInput.UnpackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT64.UnpackedInput.UnpackedOutput.ProtobufOutput
Required.Proto3.JsonInput.DurationNegativeNanos.JsonOutput
Required.Proto3.JsonInput.DurationNegativeNanos.ProtobufOutput
Required.Proto3.JsonInput.DurationNegativeSeconds.JsonOutput
21 changes: 21 additions & 0 deletions java/core/src/main/java/com/google/protobuf/Descriptors.java
Original file line number Diff line number Diff line change
Expand Up @@ -1788,6 +1788,27 @@ public List<EnumValueDescriptor> getValues() {
return Collections.unmodifiableList(Arrays.asList(values));
}

/** Determines if the given field number is reserved. */
public boolean isReservedNumber(final int number) {
for (final EnumDescriptorProto.EnumReservedRange range : proto.getReservedRangeList()) {
if (range.getStart() <= number && number <= range.getEnd()) {
return true;
}
}
return false;
}

/** Determines if the given field name is reserved. */
public boolean isReservedName(final String name) {
checkNotNull(name);
for (final String reservedName : proto.getReservedNameList()) {
if (reservedName.equals(name)) {
return true;
}
}
return false;
}

/**
* Find an enum value by name.
*
Expand Down
15 changes: 15 additions & 0 deletions java/core/src/test/java/com/google/protobuf/DescriptorsTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@
import protobuf_unittest.UnittestProto.TestJsonName;
import protobuf_unittest.UnittestProto.TestMultipleExtensionRanges;
import protobuf_unittest.UnittestProto.TestRequired;
import protobuf_unittest.UnittestProto.TestReservedEnumFields;
import protobuf_unittest.UnittestProto.TestReservedFields;
import protobuf_unittest.UnittestProto.TestService;
import java.util.Collections;
Expand Down Expand Up @@ -796,6 +797,20 @@ public void testReservedFields() {
assertThat(d.isReservedName("baz")).isTrue();
}

@Test
public void testReservedEnumFields() {
EnumDescriptor d = TestReservedEnumFields.getDescriptor();
assertThat(d.isReservedNumber(2)).isTrue();
assertThat(d.isReservedNumber(8)).isFalse();
assertThat(d.isReservedNumber(9)).isTrue();
assertThat(d.isReservedNumber(10)).isTrue();
assertThat(d.isReservedNumber(11)).isTrue();
assertThat(d.isReservedNumber(12)).isFalse();
assertThat(d.isReservedName("foo")).isFalse();
assertThat(d.isReservedName("bar")).isTrue();
assertThat(d.isReservedName("baz")).isTrue();
}

@Test
public void testToString() {
assertThat(
Expand Down
49 changes: 32 additions & 17 deletions src/google/protobuf/port_def.inc
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,13 @@
# define PROTOBUF_GNUC_MIN(x, y) 0
#endif

#if defined(__clang__) && defined(__clang_major__) && defined(__clang_minor__)
#define PROTOBUF_CLANG_MIN(x, y) \
(__clang_major__ > (x) || __clang_major__ == (x) && __clang_minor__ >= (y))
#else
#define PROTOBUF_CLANG_MIN(x, y) 0
#endif

// Portable check for MSVC minimum version:
// https://docs.microsoft.com/en-us/cpp/preprocessor/predefined-macros
#if defined(_MSC_VER)
Expand Down Expand Up @@ -666,30 +673,38 @@
// This experiment is purely for the purpose of gathering data. All code guarded
// by this flag is supposed to be removed after this experiment.
#define PROTOBUF_MESSAGE_OWNED_ARENA_EXPERIMENT

#ifdef PROTOBUF_CONSTINIT
#error PROTOBUF_CONSTINIT was previously defined
#endif
#if defined(__cpp_constinit) && !defined(_MSC_VER) && !defined(__CYGWIN__)
#define PROTOBUF_CONSTINIT constinit
#define PROTOBUF_CONSTEXPR constexpr

#if defined(_MSC_VER)
// MSVC 17 currently seems to raise an error about constant-initialized pointers.
# if PROTOBUF_MSC_VER_MIN(1930)
# define PROTOBUF_CONSTINIT
# define PROTOBUF_CONSTEXPR constexpr
# endif
#else
# if defined(__cpp_constinit) && !defined(__CYGWIN__)
# define PROTOBUF_CONSTINIT constinit
# define PROTOBUF_CONSTEXPR constexpr
// Some older Clang versions incorrectly raise an error about
// constant-initializing weak default instance pointers. Versions 12.0 and
// higher seem to work, except that XCode 12.5.1 shows the error even though it
// uses Clang 12.0.5.
// Clang-cl on Windows raises error also.
#elif !defined(_MSC_VER) && !defined(__CYGWIN__) && __has_cpp_attribute(clang::require_constant_initialization) && \
((defined(__APPLE__) && __clang_major__ >= 13) || \
(!defined(__APPLE__) && __clang_major__ >= 12))
#define PROTOBUF_CONSTINIT [[clang::require_constant_initialization]]
#define PROTOBUF_CONSTEXPR constexpr
#elif PROTOBUF_GNUC_MIN(12, 2)
#define PROTOBUF_CONSTINIT __constinit
#define PROTOBUF_CONSTEXPR constexpr
// MSVC 17 currently seems to raise an error about constant-initialized pointers.
#elif defined(_MSC_VER) && _MSC_VER >= 1930
#define PROTOBUF_CONSTINIT
#define PROTOBUF_CONSTEXPR constexpr
#else
# elif !defined(__CYGWIN__) && \
__has_cpp_attribute(clang::require_constant_initialization) && \
((defined(__APPLE__) && PROTOBUF_CLANG_MIN(13, 0)) || \
(!defined(__APPLE__) && PROTOBUF_CLANG_MIN(12, 0)))
# define PROTOBUF_CONSTINIT [[clang::require_constant_initialization]]
# define PROTOBUF_CONSTEXPR constexpr
# elif PROTOBUF_GNUC_MIN(12, 2)
# define PROTOBUF_CONSTINIT __constinit
# define PROTOBUF_CONSTEXPR constexpr
# endif
#endif

#ifndef PROTOBUF_CONSTINIT
#define PROTOBUF_CONSTINIT
#define PROTOBUF_CONSTEXPR
#endif
Expand Down
1 change: 1 addition & 0 deletions src/google/protobuf/port_undef.inc
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
#undef PROTOBUF_BUILTIN_BSWAP64
#undef PROTOBUF_BUILTIN_ATOMIC
#undef PROTOBUF_GNUC_MIN
#undef PROTOBUF_CLANG_MIN
#undef PROTOBUF_MSC_VER_MIN
#undef PROTOBUF_CPLUSPLUS_MIN
#undef PROTOBUF_NAMESPACE
Expand Down
6 changes: 6 additions & 0 deletions src/google/protobuf/unittest.proto
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,12 @@ message TestReservedFields {
reserved "bar", "baz";
}

enum TestReservedEnumFields {
UNKNOWN = 0;
reserved 2, 15, 9 to 11;
reserved "bar", "baz";
}

message TestAllExtensions {
extensions 1 to max;
}
Expand Down
6 changes: 6 additions & 0 deletions src/google/protobuf/util/json_util.cc
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,12 @@
#include <google/protobuf/util/zero_copy_sink.h>
#include <google/protobuf/stubs/status_macros.h>


// clang-format off
#include <google/protobuf/port_def.inc>
// clang-format on


namespace google {
namespace protobuf {
namespace util {
Expand All @@ -62,6 +64,7 @@ util::Status BinaryToJsonStream(TypeResolver* resolver,
io::ZeroCopyInputStream* binary_input,
io::ZeroCopyOutputStream* json_output,
const JsonPrintOptions& options) {

io::CodedInputStream in_stream(binary_input);
google::protobuf::Type type;
RETURN_IF_ERROR(resolver->ResolveMessageType(type_url, &type));
Expand Down Expand Up @@ -152,6 +155,7 @@ util::Status JsonToBinaryStream(TypeResolver* resolver,
io::ZeroCopyInputStream* json_input,
io::ZeroCopyOutputStream* binary_output,
const JsonParseOptions& options) {

google::protobuf::Type type;
RETURN_IF_ERROR(resolver->ResolveMessageType(type_url, &type));
ZeroCopyStreamByteSink sink(binary_output);
Expand Down Expand Up @@ -219,6 +223,7 @@ TypeResolver* GetGeneratedTypeResolver() {

util::Status MessageToJsonString(const Message& message, std::string* output,
const JsonOptions& options) {

const DescriptorPool* pool = message.GetDescriptor()->file()->pool();
TypeResolver* resolver =
pool == DescriptorPool::generated_pool()
Expand All @@ -235,6 +240,7 @@ util::Status MessageToJsonString(const Message& message, std::string* output,

util::Status JsonStringToMessage(StringPiece input, Message* message,
const JsonParseOptions& options) {

const DescriptorPool* pool = message->GetDescriptor()->file()->pool();
TypeResolver* resolver =
pool == DescriptorPool::generated_pool()
Expand Down
78 changes: 76 additions & 2 deletions src/google/protobuf/util/json_util_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -470,8 +470,10 @@ TEST_P(JsonTest, ParseMap) {

TEST_P(JsonTest, RepeatedMapKey) {
EXPECT_THAT(ToProto<TestMap>(R"json({
"twiceKey": 0,
"twiceKey": 1
"string_map": {
"twiceKey": 0,
"twiceKey": 1
}
})json"), StatusIs(util::StatusCode::kInvalidArgument));
}

Expand Down Expand Up @@ -700,6 +702,37 @@ TEST_P(JsonTest, TestParsingNestedAnys) {
R"("int32Value":5,"stringValue":"expected_value","messageValue":{"value":1}}}})"));
}

TEST_P(JsonTest, TestParsingBrokenAny) {
auto m = ToProto<TestAny>(R"json(
{
"value": {}
}
)json");
ASSERT_OK(m);
EXPECT_EQ(m->value().type_url(), "");
EXPECT_EQ(m->value().value(), "");

EXPECT_THAT(ToProto<TestAny>(R"json(
{
"value": {
"type_url": "garbage",
"value": "bW9yZSBnYXJiYWdl"
}
}
)json"),
StatusIs(util::StatusCode::kInvalidArgument));
}

TEST_P(JsonTest, TestFlatList) {
auto m = ToProto<TestMessage>(R"json(
{
"repeatedInt32Value": [[[5]], [6]]
}
)json");
ASSERT_OK(m);
EXPECT_THAT(m->repeated_int32_value(), ElementsAre(5, 6));
}

TEST_P(JsonTest, ParseWrappers) {
auto m = ToProto<TestWrapper>(R"json(
{
Expand Down Expand Up @@ -757,6 +790,14 @@ TEST_P(JsonTest, TestParsingUnknownAnyFields) {
EXPECT_EQ(t.string_value(), "expected_value");
}

TEST_P(JsonTest, TestHugeBareString) {
auto m = ToProto<TestMessage>(R"json({
"int64Value": 6009652459062546621
})json");
ASSERT_OK(m);
EXPECT_EQ(m->int64_value(), 6009652459062546621);
}

TEST_P(JsonTest, TestParsingUnknownEnumsProto2) {
StringPiece input = R"json({"ayuLmao": "UNKNOWN_VALUE"})json";

Expand Down Expand Up @@ -895,6 +936,39 @@ TEST_P(JsonTest, TestDuration) {

EXPECT_EQ(m2->value().seconds(), 4);
EXPECT_EQ(m2->value().nanos(), 5);

// Negative duration with zero seconds.
auto m3 = ToProto<proto3::TestDuration>(R"json(
{
"value": {"nanos": -5},
}
)json");
ASSERT_OK(m3);
EXPECT_EQ(m3->value().seconds(), 0);
EXPECT_EQ(m3->value().nanos(), -5);
EXPECT_THAT(ToJson(m3->value()), IsOkAndHolds("\"-0.000000005s\""));

// Negative duration with zero nanos.
auto m4 = ToProto<proto3::TestDuration>(R"json(
{
"value": {"seconds": -5},
}
)json");
ASSERT_OK(m4);
EXPECT_EQ(m4->value().seconds(), -5);
EXPECT_EQ(m4->value().nanos(), 0);
EXPECT_THAT(ToJson(m4->value()), IsOkAndHolds("\"-5s\""));

// Parse "0.5s" as a JSON string.
auto m5 = ToProto<proto3::TestDuration>(R"json(
{
"value": "0.5s",
}
)json");
ASSERT_OK(m5);
EXPECT_EQ(m5->value().seconds(), 0);
EXPECT_EQ(m5->value().nanos(), 500000000);
EXPECT_THAT(ToJson(m5->value()), IsOkAndHolds("\"0.500s\""));
}

// These tests are not exhaustive; tests in //third_party/protobuf/conformance
Expand Down

0 comments on commit df6bb50

Please sign in to comment.