Sync from Piper @review/462489109

PROTOBUF_SYNC_PIPER
pull/10325/head
Sandy Zhang 2 years ago
parent aebdd0885f
commit 897b2cebb4
  1. 1
      src/Makefile.am
  2. 1
      src/file_lists.cmake
  3. 2
      src/google/protobuf/arena_unittest.cc
  4. 1
      src/google/protobuf/compiler/cpp/field.cc
  5. 1
      src/google/protobuf/compiler/cpp/field.h
  6. 8
      src/google/protobuf/compiler/cpp/file.cc
  7. 4
      src/google/protobuf/compiler/cpp/helpers.cc
  8. 80
      src/google/protobuf/compiler/cpp/message.cc
  9. 36
      src/google/protobuf/compiler/java/message_serialization.h
  10. 124
      src/google/protobuf/compiler/java/message_serialization_unittest.cc
  11. 56
      src/google/protobuf/compiler/java/message_serialization_unittest.proto
  12. 2
      src/google/protobuf/generated_message_tctable_impl.h
  13. 16
      src/google/protobuf/io/printer.h
  14. 2
      src/google/protobuf/message.cc
  15. 3
      src/google/protobuf/message.h
  16. 62
      src/google/protobuf/util/json_util_test.cc

@ -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 \

@ -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

@ -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) {

@ -330,6 +330,7 @@ void FieldGenerator::GenerateCopyConstructorCode(io::Printer* printer) const {
}
}
void SetCommonOneofFieldVariables(
const FieldDescriptor* descriptor,
std::map<std::string, std::string>* variables) {

@ -208,6 +208,7 @@ class FieldGenerator {
virtual bool IsInlined() const { return false; }
virtual ArenaDtorNeeds NeedsArenaDestructor() const {
return ArenaDtorNeeds::kNone;
}

@ -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));
}

@ -176,6 +176,7 @@ static const char* const kKeywordList[] = {
#endif // !PROTOBUF_FUTURE_BREAKING_CHANGES
};
static std::unordered_set<std::string>* MakeKeywordsMap() {
auto* result = new std::unordered_set<std::string>();
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;

@ -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<const Impl_::Split*>(&$1$);\n"
" return $split$ == reinterpret_cast<Impl_::Split*>(&$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<Impl_::Split*>"
"(reinterpret_cast<const Impl_::Split*>(&$1$))}",
DefaultInstanceName(descriptor_, options_, /*split=*/true));
format("decltype($split$){reinterpret_cast<Impl_::Split*>(&$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<Impl_::Split*>(&$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<Impl_::Split*>"
"(reinterpret_cast<const Impl_::Split*>(&$1$))}",
DefaultInstanceName(descriptor_, options_, /*split=*/true));
format("decltype($split$){reinterpret_cast<Impl_::Split*>(&$1$)}",
DefaultInstanceName(descriptor_, options_, /*split=*/true));
}
for (auto oneof : OneOfRange(descriptor_)) {
put_sep();

@ -32,7 +32,6 @@
#define GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_SERIALIZATION_H__
#include <algorithm>
#include <cstddef>
#include <vector>
#include <google/protobuf/io/printer.h>
@ -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());
}
}

@ -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 <cstddef>
#include <string>
#include <utility>
#include <vector>
#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/testing/file.h>
#include <google/protobuf/testing/file.h>
#include <gmock/gmock.h>
#include <google/protobuf/testing/googletest.h>
#include <gtest/gtest.h>
#include <google/protobuf/compiler/command_line_interface.h>
#include <google/protobuf/compiler/java/generator.h>
#include <google/protobuf/test_util2.h>
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<std::string> 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

@ -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;
}

@ -38,6 +38,8 @@
#include <google/protobuf/port.h>
#include <google/protobuf/extension_set.h>
#include <google/protobuf/generated_message_tctable_decl.h>
#include <google/protobuf/generated_message_tctable_impl.h>
#include <google/protobuf/message_lite.h>
#include <google/protobuf/metadata_lite.h>
#include <google/protobuf/parse_context.h>
#include <google/protobuf/wire_format_lite.h>

@ -251,8 +251,7 @@ class PROTOBUF_EXPORT Printer {
template <typename... Args>
void Print(const char* text, const Args&... args) {
std::map<std::string, std::string> 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<int>& path);
void FillMap(std::map<std::string, std::string>* vars) {}
// Base case
void PrintInternal(std::map<std::string, std::string>* vars,
const char* text) {
Print(*vars, text);
}
template <typename... Args>
void FillMap(std::map<std::string, std::string>* vars, const std::string& key,
const std::string& value, const Args&... args) {
void PrintInternal(std::map<std::string, std::string>* 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_.

@ -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);

@ -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.

@ -307,15 +307,6 @@ TEST_P(JsonTest, Camels) {
EXPECT_THAT(ToJson(m), IsOkAndHolds(R"({"StringField":"sTRINGfIELD"})"));
}
TEST_P(JsonTest, EvilString) {
auto m = ToProto<TestMessage>(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<google::protobuf::Value>(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<proto3::TestListValue>(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<proto3::TestListValue>(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) {

Loading…
Cancel
Save