diff --git a/src/Makefile.am b/src/Makefile.am index 4f4fc808a6..9875b1c575 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -774,7 +774,6 @@ protobuf_test_SOURCES = \ google/protobuf/compiler/csharp/csharp_generator_unittest.cc \ google/protobuf/compiler/importer_unittest.cc \ google/protobuf/compiler/java/doc_comment_unittest.cc \ - google/protobuf/compiler/java/message_serialization_unittest.cc \ google/protobuf/compiler/java/plugin_unittest.cc \ google/protobuf/compiler/mock_code_generator.cc \ google/protobuf/compiler/mock_code_generator.h \ diff --git a/src/file_lists.cmake b/src/file_lists.cmake index 67092cc39e..32f10b2705 100644 --- a/src/file_lists.cmake +++ b/src/file_lists.cmake @@ -771,7 +771,6 @@ set(compiler_test_files ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/csharp/csharp_generator_unittest.cc ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/importer_unittest.cc ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/doc_comment_unittest.cc - ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/message_serialization_unittest.cc ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/plugin_unittest.cc ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/objectivec/objectivec_helpers_unittest.cc ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/parser_unittest.cc diff --git a/src/google/protobuf/arena_unittest.cc b/src/google/protobuf/arena_unittest.cc index 1466376ed7..0987c9929e 100644 --- a/src/google/protobuf/arena_unittest.cc +++ b/src/google/protobuf/arena_unittest.cc @@ -1419,7 +1419,7 @@ TEST(ArenaTest, BlockSizeDoubling) { ASSERT_GT(arena.SpaceAllocated(), first_block_size); auto second_block_size = (arena.SpaceAllocated() - first_block_size); - EXPECT_GE(second_block_size, 2*first_block_size); + EXPECT_EQ(second_block_size, 2*first_block_size); } TEST(ArenaTest, Alignment) { diff --git a/src/google/protobuf/compiler/cpp/field.cc b/src/google/protobuf/compiler/cpp/field.cc index 90d20848b3..cf4f14e8bf 100644 --- a/src/google/protobuf/compiler/cpp/field.cc +++ b/src/google/protobuf/compiler/cpp/field.cc @@ -330,6 +330,7 @@ void FieldGenerator::GenerateCopyConstructorCode(io::Printer* printer) const { } } + void SetCommonOneofFieldVariables( const FieldDescriptor* descriptor, std::map* variables) { diff --git a/src/google/protobuf/compiler/cpp/field.h b/src/google/protobuf/compiler/cpp/field.h index 3fcbda371c..3903e79862 100644 --- a/src/google/protobuf/compiler/cpp/field.h +++ b/src/google/protobuf/compiler/cpp/field.h @@ -208,6 +208,7 @@ class FieldGenerator { virtual bool IsInlined() const { return false; } + virtual ArenaDtorNeeds NeedsArenaDestructor() const { return ArenaDtorNeeds::kNone; } diff --git a/src/google/protobuf/compiler/cpp/file.cc b/src/google/protobuf/compiler/cpp/file.cc index 502d8c007e..838e0ab9b4 100644 --- a/src/google/protobuf/compiler/cpp/file.cc +++ b/src/google/protobuf/compiler/cpp/file.cc @@ -495,10 +495,12 @@ void FileGenerator::GenerateSourceDefaultInstance(int idx, generator->GenerateInitDefaultSplitInstance(printer); format( "} {}\n" + " ~$1$() {}\n" " union {\n" - " $1$ _instance;\n" + " $2$ _instance;\n" " };\n" "};\n", + DefaultInstanceType(generator->descriptor_, options_, /*split=*/true), StrCat(generator->classname_, "::Impl_::Split")); // NO_DESTROY is not necessary for correctness. The empty destructor is // enough. However, the empty destructor fails to be elided in some @@ -506,7 +508,7 @@ void FileGenerator::GenerateSourceDefaultInstance(int idx, // there just to improve performance and binary size in these builds. format( "PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT " - "PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const $1$ $2$;\n", + "PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 $1$ $2$;\n", DefaultInstanceType(generator->descriptor_, options_, /*split=*/true), DefaultInstanceName(generator->descriptor_, options_, /*split=*/true)); } @@ -997,7 +999,7 @@ class FileGenerator::ForwardDeclarations { const Descriptor* class_desc = p.second; format( "struct $1$;\n" - "$dllexport_decl $extern const $1$ $2$;\n", + "$dllexport_decl $extern $1$ $2$;\n", DefaultInstanceType(class_desc, options, /*split=*/true), DefaultInstanceName(class_desc, options, /*split=*/true)); } diff --git a/src/google/protobuf/compiler/cpp/helpers.cc b/src/google/protobuf/compiler/cpp/helpers.cc index d182c8607f..4939aa533f 100644 --- a/src/google/protobuf/compiler/cpp/helpers.cc +++ b/src/google/protobuf/compiler/cpp/helpers.cc @@ -176,6 +176,7 @@ static const char* const kKeywordList[] = { #endif // !PROTOBUF_FUTURE_BREAKING_CHANGES }; + static std::unordered_set* MakeKeywordsMap() { auto* result = new std::unordered_set(); for (const auto keyword : kKeywordList) { @@ -524,6 +525,7 @@ std::string FieldName(const FieldDescriptor* field) { return result; } + std::string FieldMemberName(const FieldDescriptor* field, bool split) { StringPiece prefix = IsMapEntryMessage(field->containing_type()) ? "" : "_impl_."; @@ -874,6 +876,8 @@ std::string SafeFunctionName(const Descriptor* descriptor, bool IsProfileDriven(const Options& options) { return options.access_info_map != nullptr; } + + bool IsStringInlined(const FieldDescriptor* descriptor, const Options& options) { (void)descriptor; diff --git a/src/google/protobuf/compiler/cpp/message.cc b/src/google/protobuf/compiler/cpp/message.cc index 51a3e652f1..3713b9cf2c 100644 --- a/src/google/protobuf/compiler/cpp/message.cc +++ b/src/google/protobuf/compiler/cpp/message.cc @@ -828,6 +828,7 @@ void MessageGenerator::GenerateFieldAccessorDeclarations(io::Printer* printer) { // Generate type-specific accessor declarations. field_generators_.get(field).GenerateAccessorDeclarations(printer); + format("\n"); } @@ -1237,41 +1238,41 @@ void MessageGenerator::GenerateFieldAccessorDefinitions(io::Printer* printer) { Formatter::SaveState saver(&format); format.AddMap(vars); - - // Generate has_$name$() or $name$_size(). - if (field->is_repeated()) { - if (IsFieldStripped(field, options_)) { - format( - "inline int $classname$::$name$_size() const { " - "__builtin_trap(); }\n"); + // Generate has_$name$() or $name$_size(). + if (field->is_repeated()) { + if (IsFieldStripped(field, options_)) { + format( + "inline int $classname$::$name$_size() const { " + "__builtin_trap(); }\n"); + } else { + format( + "inline int $classname$::_internal_$name$_size() const {\n" + " return $field$$1$.size();\n" + "}\n" + "inline int $classname$::$name$_size() const {\n" + "$annotate_size$" + " return _internal_$name$_size();\n" + "}\n", + IsImplicitWeakField(field, options_, scc_analyzer_) && + field->message_type() + ? ".weak" + : ""); + } + } else if (field->real_containing_oneof()) { + format.Set("field_name", UnderscoresToCamelCase(field->name(), true)); + format.Set("oneof_name", field->containing_oneof()->name()); + format.Set("oneof_index", + StrCat(field->containing_oneof()->index())); + GenerateOneofMemberHasBits(field, format); } else { - format( - "inline int $classname$::_internal_$name$_size() const {\n" - " return $field$$1$.size();\n" - "}\n" - "inline int $classname$::$name$_size() const {\n" - "$annotate_size$" - " return _internal_$name$_size();\n" - "}\n", - IsImplicitWeakField(field, options_, scc_analyzer_) && - field->message_type() - ? ".weak" - : ""); + // Singular field. + GenerateSingularFieldHasBits(field, format); } - } else if (field->real_containing_oneof()) { - format.Set("field_name", UnderscoresToCamelCase(field->name(), true)); - format.Set("oneof_name", field->containing_oneof()->name()); - format.Set("oneof_index", - StrCat(field->containing_oneof()->index())); - GenerateOneofMemberHasBits(field, format); - } else { - // Singular field. - GenerateSingularFieldHasBits(field, format); - } if (!IsCrossFileMaybeMap(field)) { GenerateFieldClear(field, true, format); } + // Generate type-specific accessors. if (!IsFieldStripped(field, options_)) { field_generators_.get(field).GenerateInlineAccessorDefinitions(printer); @@ -1759,7 +1760,7 @@ void MessageGenerator::GenerateClassDefinition(io::Printer* printer) { format( "private:\n" "inline bool IsSplitMessageDefault() const {\n" - " return $split$ == reinterpret_cast(&$1$);\n" + " return $split$ == reinterpret_cast(&$1$);\n" "}\n" "PROTOBUF_NOINLINE void PrepareSplitMessageForWrite();\n" "public:\n", @@ -2422,15 +2423,8 @@ void MessageGenerator::GenerateSharedConstructorCode(io::Printer* printer) { } if (ShouldSplit(descriptor_, options_)) { put_sep(); - // We can't assign the default split to this->split without the const_cast - // because the former is a const. The const_cast is safe because we don't - // intend to modify the default split through this pointer, and we also - // expect the default split to be in the rodata section which is protected - // from mutation. - format( - "decltype($split$){const_cast" - "(reinterpret_cast(&$1$))}", - DefaultInstanceName(descriptor_, options_, /*split=*/true)); + format("decltype($split$){reinterpret_cast(&$1$)}", + DefaultInstanceName(descriptor_, options_, /*split=*/true)); } for (auto oneof : OneOfRange(descriptor_)) { put_sep(); @@ -2689,7 +2683,7 @@ void MessageGenerator::GenerateConstexprConstructor(io::Printer* printer) { } if (ShouldSplit(descriptor_, options_)) { put_sep(); - format("/*decltype($split$)*/const_cast(&$1$._instance)", + format("/*decltype($split$)*/&$1$._instance", DefaultInstanceName(descriptor_, options_, /*split=*/true)); } @@ -2874,10 +2868,8 @@ void MessageGenerator::GenerateStructors(io::Printer* printer) { } if (ShouldSplit(descriptor_, options_)) { put_sep(); - format( - "decltype($split$){const_cast" - "(reinterpret_cast(&$1$))}", - DefaultInstanceName(descriptor_, options_, /*split=*/true)); + format("decltype($split$){reinterpret_cast(&$1$)}", + DefaultInstanceName(descriptor_, options_, /*split=*/true)); } for (auto oneof : OneOfRange(descriptor_)) { put_sep(); diff --git a/src/google/protobuf/compiler/java/message_serialization.h b/src/google/protobuf/compiler/java/message_serialization.h index 15dc515a85..6145392f81 100644 --- a/src/google/protobuf/compiler/java/message_serialization.h +++ b/src/google/protobuf/compiler/java/message_serialization.h @@ -32,7 +32,6 @@ #define GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_SERIALIZATION_H__ #include -#include #include #include @@ -67,31 +66,20 @@ void GenerateSerializeFieldsAndExtensions( std::sort(sorted_extensions.begin(), sorted_extensions.end(), ExtensionRangeOrdering()); - std::size_t range_idx = 0; - // Merge the fields and the extension ranges, both sorted by field number. - for (int i = 0; i < descriptor->field_count(); ++i) { - const FieldDescriptor* field = sorted_fields[i]; - - // Collapse all extension ranges up until the next field. This leads to - // shorter and more efficient codegen for messages containing a large - // number of extension ranges without fields in between them. - const Descriptor::ExtensionRange* range = nullptr; - while (range_idx < sorted_extensions.size() && - sorted_extensions[range_idx]->end <= field->number()) { - range = sorted_extensions[range_idx++]; - } - - if (range != nullptr) { - GenerateSerializeExtensionRange(printer, range); + for (int i = 0, j = 0; + i < descriptor->field_count() || j < sorted_extensions.size();) { + if (i == descriptor->field_count()) { + GenerateSerializeExtensionRange(printer, sorted_extensions[j++]); + } else if (j == sorted_extensions.size()) { + field_generators.get(sorted_fields[i++]) + .GenerateSerializationCode(printer); + } else if (sorted_fields[i]->number() < sorted_extensions[j]->start) { + field_generators.get(sorted_fields[i++]) + .GenerateSerializationCode(printer); + } else { + GenerateSerializeExtensionRange(printer, sorted_extensions[j++]); } - field_generators.get(field).GenerateSerializationCode(printer); - } - - // After serializing all fields, serialize any remaining extensions via a - // single writeUntil call. - if (range_idx < sorted_extensions.size()) { - GenerateSerializeExtensionRange(printer, sorted_extensions.back()); } } diff --git a/src/google/protobuf/compiler/java/message_serialization_unittest.cc b/src/google/protobuf/compiler/java/message_serialization_unittest.cc deleted file mode 100644 index b2e1fcaed8..0000000000 --- a/src/google/protobuf/compiler/java/message_serialization_unittest.cc +++ /dev/null @@ -1,124 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace google { -namespace protobuf { -namespace compiler { -namespace java { -namespace { - -using ::testing::ElementsAre; - -// Generates Java code for the specified Java proto, returning the compiler's -// exit status. -int CompileJavaProto(std::string proto_file_name) { - JavaGenerator java_generator; - - CommandLineInterface cli; - cli.RegisterGenerator("--java_out", &java_generator, /*help_text=*/""); - - std::string proto_path = StrCat( - "--proto_path=", - TestUtil::GetTestDataPath("third_party/protobuf/compiler/java")); - std::string java_out = StrCat("--java_out=", TestTempDir()); - - const char* argv[] = { - "protoc", - proto_path.c_str(), - java_out.c_str(), - proto_file_name.c_str(), - }; - - // Open-source codebase does not support ABSL_ARRAYSIZE. - return cli.Run(sizeof(argv) / sizeof(*argv), argv); -} - -TEST(MessageSerializationTest, CollapseAdjacentExtensionRanges) { - GOOGLE_CHECK_EQ(CompileJavaProto("message_serialization_unittest.proto"), 0); - - std::string java_source; - GOOGLE_CHECK_OK(File::GetContents( - // Open-source codebase does not support file::JoinPath, so we manually - // concatenate instead. - StrCat(TestTempDir(), - "/TestMessageWithManyExtensionRanges.java"), - &java_source, true)); - - // Open-source codebase does not support constexpr StringPiece. - static constexpr const char kWriteUntilCall[] = "extensionWriter.writeUntil("; - - std::vector range_ends; - - // Open-source codebase does not have Split overload taking a single - // char delimiter. - // - // NOLINTNEXTLINE(abseil-faster-strsplit-delimiter) - for (const auto& line : Split(java_source, "\n")) { - // Extract end position from writeUntil call. (Open-source codebase does not - // support RE2.) - std::size_t write_until_pos = line.find(kWriteUntilCall); - if (write_until_pos == std::string::npos) { - continue; - } - write_until_pos += (sizeof(kWriteUntilCall) - 1); - - std::size_t comma_pos = line.find(',', write_until_pos); - if (comma_pos == std::string::npos) { - continue; - } - - range_ends.push_back( - std::string(line.substr(write_until_pos, comma_pos - write_until_pos))); - } - - EXPECT_THAT(range_ends, ElementsAre("3", "13", "43")); -} - -} // namespace -} // namespace java -} // namespace compiler -} // namespace protobuf -} // namespace google diff --git a/src/google/protobuf/compiler/java/message_serialization_unittest.proto b/src/google/protobuf/compiler/java/message_serialization_unittest.proto deleted file mode 100644 index 9cfdf42b32..0000000000 --- a/src/google/protobuf/compiler/java/message_serialization_unittest.proto +++ /dev/null @@ -1,56 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -syntax = "proto2"; - -package protobuf_unittest; - -option java_multiple_files = true; -option java_package = ""; - -// Each batch of extension ranges not separated by a non-extension field should -// be serialized using a single ExtensionWriter#writeUntil call. -message TestMessageWithManyExtensionRanges { - // First extension range: ends at field number 3 (exclusive) - extensions 1 to 2; - - optional int32 foo = 3; - optional int32 bar = 5; - - // Second extension range: ends at field number 13 (exclusive) - extensions 6; - extensions 8; - extensions 10 to 12; - - optional int32 baz = 23; - - // Third extension range: ends at field number 43 (exclusive) - extensions 42; -} diff --git a/src/google/protobuf/generated_message_tctable_impl.h b/src/google/protobuf/generated_message_tctable_impl.h index 3fad18c7f7..11ac5baf35 100644 --- a/src/google/protobuf/generated_message_tctable_impl.h +++ b/src/google/protobuf/generated_message_tctable_impl.h @@ -38,6 +38,8 @@ #include #include #include +#include +#include #include #include #include diff --git a/src/google/protobuf/io/printer.h b/src/google/protobuf/io/printer.h index aa507cb014..e30bfa6908 100644 --- a/src/google/protobuf/io/printer.h +++ b/src/google/protobuf/io/printer.h @@ -251,8 +251,7 @@ class PROTOBUF_EXPORT Printer { template void Print(const char* text, const Args&... args) { std::map vars; - FillMap(&vars, args...); - Print(vars, text); + PrintInternal(&vars, text, args...); } // Indent text by two spaces. After calling Indent(), two spaces will be @@ -300,13 +299,18 @@ class PROTOBUF_EXPORT Printer { void Annotate(const char* begin_varname, const char* end_varname, const std::string& file_path, const std::vector& path); - void FillMap(std::map* vars) {} + // Base case + void PrintInternal(std::map* vars, + const char* text) { + Print(*vars, text); + } template - void FillMap(std::map* vars, const std::string& key, - const std::string& value, const Args&... args) { + void PrintInternal(std::map* vars, const char* text, + const char* key, const std::string& value, + const Args&... args) { (*vars)[key] = value; - FillMap(vars, args...); + PrintInternal(vars, text, args...); } // Copy size worth of bytes from data to buffer_. diff --git a/src/google/protobuf/message.cc b/src/google/protobuf/message.cc index 1279164619..724a6220f0 100644 --- a/src/google/protobuf/message.cc +++ b/src/google/protobuf/message.cc @@ -214,7 +214,7 @@ uint64_t Message::GetInvariantPerBuild(uint64_t salt) { } namespace internal { -void* CreateSplitMessageGeneric(Arena* arena, const void* default_split, +void* CreateSplitMessageGeneric(Arena* arena, void* default_split, size_t size) { void* split = (arena == nullptr) ? ::operator new(size) : arena->AllocateAligned(size); diff --git a/src/google/protobuf/message.h b/src/google/protobuf/message.h index b61fafb333..7042a13342 100644 --- a/src/google/protobuf/message.h +++ b/src/google/protobuf/message.h @@ -411,8 +411,7 @@ class PROTOBUF_EXPORT Message : public MessageLite { namespace internal { // Creates and returns an allocation for a split message. -void* CreateSplitMessageGeneric(Arena* arena, const void* default_split, - size_t size); +void* CreateSplitMessageGeneric(Arena* arena, void* default_split, size_t size); // Forward-declare interfaces used to implement RepeatedFieldRef. // These are protobuf internals that users shouldn't care about. diff --git a/src/google/protobuf/util/json_util_test.cc b/src/google/protobuf/util/json_util_test.cc index ca9fe731dd..ebe1b604d1 100644 --- a/src/google/protobuf/util/json_util_test.cc +++ b/src/google/protobuf/util/json_util_test.cc @@ -307,15 +307,6 @@ TEST_P(JsonTest, Camels) { EXPECT_THAT(ToJson(m), IsOkAndHolds(R"({"StringField":"sTRINGfIELD"})")); } -TEST_P(JsonTest, EvilString) { - auto m = ToProto(R"json( - {"string_value": ")json" - "\n\r\b\f\1\2\3" - "\"}"); - ASSERT_OK(m); - EXPECT_EQ(m->string_value(), "\n\r\b\f\1\2\3"); -} - TEST_P(JsonTest, TestAlwaysPrintEnumsAsInts) { TestMessage orig; orig.set_enum_value(proto3::BAR); @@ -408,7 +399,6 @@ TEST_P(JsonTest, ParseMessage) { "repeatedEnumValue": [1, "FOO"], "repeatedMessageValue": [ {"value": 40}, - {}, {"value": 96} ] } @@ -437,10 +427,9 @@ TEST_P(JsonTest, ParseMessage) { EXPECT_THAT(m->repeated_string_value(), ElementsAre("foo", "bar ", "")); EXPECT_THAT(m->repeated_enum_value(), ElementsAre(proto3::BAR, proto3::FOO)); - ASSERT_THAT(m->repeated_message_value(), SizeIs(3)); + ASSERT_THAT(m->repeated_message_value(), SizeIs(2)); EXPECT_EQ(m->repeated_message_value(0).value(), 40); - EXPECT_EQ(m->repeated_message_value(1).value(), 0); - EXPECT_EQ(m->repeated_message_value(2).value(), 96); + EXPECT_EQ(m->repeated_message_value(1).value(), 96); EXPECT_THAT( ToJson(*m), @@ -451,7 +440,7 @@ TEST_P(JsonTest, ParseMessage) { R"("messageValue":{"value":2048},"repeatedBoolValue":[true],"repeatedInt32Value":[0,-42])" R"(,"repeatedUint64Value":["1","2"],"repeatedDoubleValue":[1.5,-2],)" R"("repeatedStringValue":["foo","bar ",""],"repeatedEnumValue":["BAR","FOO"],)" - R"("repeatedMessageValue":[{"value":40},{},{"value":96}]})")); + R"("repeatedMessageValue":[{"value":40},{"value":96}]})")); } TEST_P(JsonTest, CurseOfAtob) { @@ -772,24 +761,6 @@ TEST_P(JsonTest, TestFlatList) { )json"); ASSERT_OK(m); EXPECT_THAT(m->repeated_int32_value(), ElementsAre(5, 6)); - - // The above flatteing behavior is supressed for google::protobuf::ListValue. - auto m2 = ToProto(R"json( - { - "repeatedInt32Value": [[[5]], [6]] - } - )json"); - ASSERT_OK(m2); - auto fields = m2->struct_value().fields(); - auto list = fields["repeatedInt32Value"].list_value(); - EXPECT_EQ(list.values(0) - .list_value() - .values(0) - .list_value() - .values(0) - .number_value(), - 5); - EXPECT_EQ(list.values(1).list_value().values(0).number_value(), 6); } TEST_P(JsonTest, ParseWrappers) { @@ -1124,33 +1095,6 @@ TEST_P(JsonTest, TestLegalNullsInArray) { ASSERT_THAT(m2->repeated_value(), SizeIs(1)); EXPECT_TRUE(m2->repeated_value(0).has_null_value()); - - m2->Clear(); - m2->mutable_repeated_value(); // Materialize an empty singular Value. - m2->add_repeated_value(); - m2->add_repeated_value()->set_string_value("solitude"); - m2->add_repeated_value(); - EXPECT_THAT(ToJson(*m2), IsOkAndHolds(R"({"repeatedValue":["solitude"]})")); -} - -TEST_P(JsonTest, ListList) { - auto m = ToProto(R"json({ - "repeated_value": [["ayy", "lmao"]] - })json"); - ASSERT_OK(m); - - EXPECT_EQ(m->repeated_value(0).values(0).string_value(), "ayy"); - EXPECT_EQ(m->repeated_value(0).values(1).string_value(), "lmao"); - - m = ToProto(R"json({ - "repeated_value": [{ - "values": ["ayy", "lmao"] - }] - })json"); - ASSERT_OK(m); - - EXPECT_EQ(m->repeated_value(0).values(0).string_value(), "ayy"); - EXPECT_EQ(m->repeated_value(0).values(1).string_value(), "lmao"); } TEST_P(JsonTest, HtmlEscape) {