Protocol Buffers - Google's data interchange format (grpc依赖)
https://developers.google.com/protocol-buffers/
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
318 lines
11 KiB
318 lines
11 KiB
// Protocol Buffers - Google's data interchange format |
|
// Copyright 2024 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 |
|
|
|
#include <gmock/gmock.h> |
|
#include <gtest/gtest.h> |
|
#include "google/protobuf/compiler/hpb/tests/child_model.upb.proto.h" |
|
#include "google/protobuf/compiler/hpb/tests/test_extension.upb.proto.h" |
|
#include "google/protobuf/compiler/hpb/tests/test_model.upb.proto.h" |
|
#include "google/protobuf/hpb/requires.h" |
|
|
|
namespace { |
|
|
|
using ::hpb::internal::Requires; |
|
using ::hpb_unittest::protos::ChildModel1; |
|
using ::hpb_unittest::protos::TestModel; |
|
using ::testing::ElementsAre; |
|
|
|
const char kTestStr1[] = "abcdefg"; |
|
const char kTestStr2[] = "just another test string"; |
|
|
|
TEST(CppGeneratedCode, RepeatedMessages) { |
|
::hpb::Arena arena; |
|
auto test_model = ::hpb::CreateMessage<TestModel>(arena); |
|
EXPECT_EQ(0, test_model.child_models_size()); |
|
// Should be able to clear repeated field when empty. |
|
test_model.mutable_child_models()->clear(); |
|
EXPECT_EQ(0, test_model.child_models_size()); |
|
// Add 2 children. |
|
auto new_child = test_model.add_child_models(); |
|
EXPECT_EQ(true, new_child.ok()); |
|
new_child.value()->set_child_str1(kTestStr1); |
|
new_child = test_model.add_child_models(); |
|
EXPECT_EQ(true, new_child.ok()); |
|
new_child.value()->set_child_str1(kTestStr2); |
|
EXPECT_EQ(2, test_model.child_models_size()); |
|
// Mutable access. |
|
auto mutable_first = test_model.mutable_child_models(0); |
|
EXPECT_EQ(mutable_first->child_str1(), kTestStr1); |
|
mutable_first->set_child_str1("change1"); |
|
auto mutable_second = test_model.mutable_child_models(1); |
|
EXPECT_EQ(mutable_second->child_str1(), kTestStr2); |
|
mutable_second->set_child_str1("change2"); |
|
// Check mutations using views. |
|
auto view_first = test_model.child_models(0); |
|
EXPECT_EQ(view_first->child_str1(), "change1"); |
|
auto view_second = test_model.child_models(1); |
|
EXPECT_EQ(view_second->child_str1(), "change2"); |
|
} |
|
|
|
TEST(CppGeneratedCode, RepeatedScalar) { |
|
::hpb::Arena arena; |
|
auto test_model = ::hpb::CreateMessage<TestModel>(arena); |
|
EXPECT_EQ(0, test_model.value_array_size()); |
|
// Should be able to clear repeated field when empty. |
|
test_model.mutable_value_array()->clear(); |
|
EXPECT_EQ(0, test_model.value_array_size()); |
|
// Add 2 children. |
|
EXPECT_EQ(true, test_model.add_value_array(5)); |
|
EXPECT_EQ(true, test_model.add_value_array(6)); |
|
EXPECT_EQ(2, test_model.value_array_size()); |
|
EXPECT_EQ(5, test_model.value_array(0)); |
|
EXPECT_EQ(6, test_model.value_array(1)); |
|
EXPECT_EQ(true, test_model.resize_value_array(3)); |
|
EXPECT_EQ(3, test_model.value_array_size()); |
|
test_model.set_value_array(2, 7); |
|
EXPECT_EQ(5, test_model.value_array(0)); |
|
EXPECT_EQ(6, test_model.value_array(1)); |
|
EXPECT_EQ(7, test_model.value_array(2)); |
|
} |
|
|
|
TEST(CppGeneratedCode, RepeatedFieldClear) { |
|
::hpb::Arena arena; |
|
auto test_model = ::hpb::CreateMessage<TestModel>(arena); |
|
test_model.mutable_value_array()->push_back(5); |
|
test_model.mutable_value_array()->push_back(16); |
|
test_model.mutable_value_array()->push_back(27); |
|
ASSERT_EQ(test_model.mutable_value_array()->size(), 3); |
|
test_model.mutable_value_array()->clear(); |
|
EXPECT_EQ(test_model.mutable_value_array()->size(), 0); |
|
} |
|
|
|
TEST(CppGeneratedCode, RepeatedFieldProxyForScalars) { |
|
::hpb::Arena arena; |
|
auto test_model = ::hpb::CreateMessage<TestModel>(arena); |
|
EXPECT_EQ(0, test_model.value_array().size()); |
|
EXPECT_EQ(0, test_model.mutable_value_array()->size()); |
|
|
|
test_model.mutable_value_array()->push_back(5); |
|
test_model.mutable_value_array()->push_back(16); |
|
test_model.mutable_value_array()->push_back(27); |
|
|
|
ASSERT_EQ(test_model.mutable_value_array()->size(), 3); |
|
EXPECT_EQ((*test_model.mutable_value_array())[0], 5); |
|
EXPECT_EQ((*test_model.mutable_value_array())[1], 16); |
|
EXPECT_EQ((*test_model.mutable_value_array())[2], 27); |
|
|
|
const auto value_array = test_model.value_array(); |
|
ASSERT_EQ(value_array.size(), 3); |
|
EXPECT_EQ(value_array[0], 5); |
|
EXPECT_EQ(value_array[1], 16); |
|
EXPECT_EQ(value_array[2], 27); |
|
|
|
EXPECT_THAT(value_array, ElementsAre(5, 16, 27)); |
|
|
|
EXPECT_THAT(std::vector(value_array.begin(), value_array.end()), |
|
ElementsAre(5, 16, 27)); |
|
EXPECT_THAT(std::vector(value_array.cbegin(), value_array.cend()), |
|
ElementsAre(5, 16, 27)); |
|
EXPECT_THAT(std::vector(value_array.rbegin(), value_array.rend()), |
|
ElementsAre(27, 16, 5)); |
|
EXPECT_THAT(std::vector(value_array.crbegin(), value_array.crend()), |
|
ElementsAre(27, 16, 5)); |
|
} |
|
|
|
TEST(CppGeneratedCode, RepeatedScalarIterator) { |
|
::hpb::Arena arena; |
|
auto test_model = ::hpb::CreateMessage<TestModel>(arena); |
|
test_model.mutable_value_array()->push_back(5); |
|
test_model.mutable_value_array()->push_back(16); |
|
test_model.mutable_value_array()->push_back(27); |
|
int sum = 0; |
|
// Access by value. |
|
const ::hpb::RepeatedField<int32_t>::CProxy rep1 = test_model.value_array(); |
|
for (auto i : rep1) { |
|
sum += i; |
|
} |
|
EXPECT_EQ(sum, 5 + 16 + 27); |
|
// Access by const reference. |
|
sum = 0; |
|
for (const auto& i : *test_model.mutable_value_array()) { |
|
sum += i; |
|
} |
|
EXPECT_EQ(sum, 5 + 16 + 27); |
|
// Access by forwarding reference. |
|
sum = 0; |
|
for (auto&& i : *test_model.mutable_value_array()) { |
|
sum += i; |
|
} |
|
EXPECT_EQ(sum, 5 + 16 + 27); |
|
// Test iterator operators. |
|
auto begin = test_model.value_array().begin(); |
|
auto end = test_model.value_array().end(); |
|
sum = 0; |
|
for (auto it = begin; it != end; ++it) { |
|
sum += *it; |
|
} |
|
EXPECT_EQ(sum, 5 + 16 + 27); |
|
auto it = begin; |
|
++it; |
|
EXPECT_TRUE(begin < it); |
|
EXPECT_TRUE(begin <= it); |
|
it = end; |
|
EXPECT_TRUE(it == end); |
|
EXPECT_TRUE(it > begin); |
|
EXPECT_TRUE(it >= begin); |
|
EXPECT_TRUE(it != begin); |
|
// difference type |
|
it = end; |
|
--it; |
|
--it; |
|
EXPECT_EQ(end - it, 2); |
|
it = begin; |
|
EXPECT_EQ(it[0], 5); |
|
EXPECT_EQ(it[1], 16); |
|
EXPECT_EQ(it[2], 27); |
|
// ValueProxy. |
|
sum = 0; |
|
for (::hpb::RepeatedField<int32_t>::ValueCProxy c : |
|
test_model.value_array()) { |
|
sum += c; |
|
} |
|
EXPECT_EQ(sum, 5 + 16 + 27); |
|
sum = 0; |
|
for (::hpb::RepeatedField<int32_t>::ValueProxy c : |
|
*test_model.mutable_value_array()) { |
|
sum += c; |
|
} |
|
EXPECT_EQ(sum, 5 + 16 + 27); |
|
} |
|
|
|
TEST(CppGeneratedCode, RepeatedFieldProxyForStrings) { |
|
::hpb::Arena arena; |
|
auto test_model = ::hpb::CreateMessage<TestModel>(arena); |
|
EXPECT_EQ(0, test_model.repeated_string().size()); |
|
EXPECT_EQ(0, test_model.mutable_repeated_string()->size()); |
|
|
|
test_model.mutable_repeated_string()->push_back("a"); |
|
test_model.mutable_repeated_string()->push_back("b"); |
|
test_model.mutable_repeated_string()->push_back("c"); |
|
|
|
ASSERT_EQ(test_model.repeated_string().size(), 3); |
|
EXPECT_EQ(test_model.repeated_string()[0], "a"); |
|
EXPECT_EQ(test_model.repeated_string()[1], "b"); |
|
EXPECT_EQ(test_model.repeated_string()[2], "c"); |
|
|
|
EXPECT_THAT(test_model.repeated_string(), ElementsAre("a", "b", "c")); |
|
EXPECT_THAT(*test_model.mutable_repeated_string(), |
|
ElementsAre("a", "b", "c")); |
|
|
|
ASSERT_EQ(test_model.mutable_repeated_string()->size(), 3); |
|
EXPECT_EQ((*test_model.mutable_repeated_string())[0], "a"); |
|
EXPECT_EQ((*test_model.mutable_repeated_string())[1], "b"); |
|
EXPECT_EQ((*test_model.mutable_repeated_string())[2], "c"); |
|
|
|
// The const accessor can't be used to modify the element |
|
EXPECT_FALSE((std::is_assignable<decltype(test_model.repeated_string()[1]), |
|
absl::string_view>::value)); |
|
// But the mutable one is fine. |
|
(*test_model.mutable_repeated_string())[1] = "other"; |
|
EXPECT_THAT(test_model.repeated_string(), ElementsAre("a", "other", "c")); |
|
|
|
test_model.mutable_repeated_string()->clear(); |
|
EXPECT_EQ(test_model.mutable_repeated_string()->size(), 0); |
|
} |
|
|
|
TEST(CppGeneratedCode, RepeatedFieldProxyForMessages) { |
|
::hpb::Arena arena; |
|
auto test_model = ::hpb::CreateMessage<TestModel>(arena); |
|
EXPECT_EQ(0, test_model.child_models().size()); |
|
ChildModel1 child1; |
|
child1.set_child_str1(kTestStr1); |
|
test_model.mutable_child_models()->push_back(child1); |
|
ChildModel1 child2; |
|
child2.set_child_str1(kTestStr2); |
|
test_model.mutable_child_models()->push_back(std::move(child2)); |
|
|
|
int i = 0; |
|
for (auto child : test_model.child_models()) { |
|
EXPECT_FALSE(Requires<decltype(child)>( |
|
[](auto&& x) -> decltype(x.set_child_str1("")) {})); |
|
if (i++ == 0) { |
|
EXPECT_EQ(child.child_str1(), kTestStr1); |
|
} else { |
|
EXPECT_EQ(child.child_str1(), kTestStr2); |
|
} |
|
} |
|
|
|
i = 0; |
|
for (const auto& child : *test_model.mutable_child_models()) { |
|
if (i++ == 0) { |
|
EXPECT_EQ(child.child_str1(), kTestStr1); |
|
} else { |
|
EXPECT_EQ(child.child_str1(), kTestStr2); |
|
} |
|
} |
|
|
|
using testing::_; |
|
EXPECT_THAT(test_model.child_models(), ElementsAre(_, _)); |
|
|
|
EXPECT_EQ(test_model.child_models().size(), 2); |
|
EXPECT_EQ(test_model.child_models()[0].child_str1(), kTestStr1); |
|
EXPECT_EQ(test_model.child_models()[1].child_str1(), kTestStr2); |
|
EXPECT_EQ((*test_model.mutable_child_models())[0].child_str1(), kTestStr1); |
|
EXPECT_EQ((*test_model.mutable_child_models())[1].child_str1(), kTestStr2); |
|
(*test_model.mutable_child_models())[0].set_child_str1("change1"); |
|
EXPECT_EQ((*test_model.mutable_child_models())[0].child_str1(), "change1"); |
|
test_model.mutable_child_models()->clear(); |
|
EXPECT_EQ(test_model.mutable_child_models()->size(), 0); |
|
} |
|
|
|
TEST(CppGeneratedCode, EmptyRepeatedFieldProxyForMessages) { |
|
::hpb::Arena arena; |
|
auto test_model = ::hpb::CreateMessage<TestModel>(arena); |
|
EXPECT_EQ(0, test_model.child_models().size()); |
|
ChildModel1 child1; |
|
child1.set_child_str1(kTestStr1); |
|
|
|
EXPECT_EQ(test_model.child_models().size(), 0); |
|
EXPECT_EQ(std::distance(test_model.child_models().begin(), |
|
test_model.child_models().end()), |
|
0); |
|
} |
|
|
|
TEST(CppGeneratedCode, RepeatedFieldProxyForMessagesIndexOperator) { |
|
::hpb::Arena arena; |
|
auto test_model = ::hpb::CreateMessage<TestModel>(arena); |
|
EXPECT_EQ(0, test_model.child_models().size()); |
|
ChildModel1 child1; |
|
child1.set_child_str1(kTestStr1); |
|
test_model.mutable_child_models()->push_back(child1); |
|
ChildModel1 child2; |
|
|
|
child2.set_child_str1(kTestStr2); |
|
test_model.mutable_child_models()->push_back(std::move(child2)); |
|
ASSERT_EQ(test_model.child_models().size(), 2); |
|
|
|
// test_model.child_models()[0].set_child_str1("change1"); |
|
(*test_model.mutable_child_models())[0].set_child_str1("change1"); |
|
EXPECT_EQ((*test_model.mutable_child_models())[0].child_str1(), "change1"); |
|
} |
|
|
|
TEST(CppGeneratedCode, RepeatedStrings) { |
|
::hpb::Arena arena; |
|
auto test_model = ::hpb::CreateMessage<TestModel>(arena); |
|
EXPECT_EQ(0, test_model.repeated_string_size()); |
|
// Should be able to clear repeated field when empty. |
|
test_model.mutable_repeated_string()->clear(); |
|
EXPECT_EQ(0, test_model.repeated_string_size()); |
|
// Add 2 children. |
|
EXPECT_EQ(true, test_model.add_repeated_string("Hello")); |
|
EXPECT_EQ(true, test_model.add_repeated_string("World")); |
|
EXPECT_EQ(2, test_model.repeated_string_size()); |
|
EXPECT_EQ("Hello", test_model.repeated_string(0)); |
|
EXPECT_EQ("World", test_model.repeated_string(1)); |
|
EXPECT_EQ(true, test_model.resize_repeated_string(3)); |
|
EXPECT_EQ(3, test_model.repeated_string_size()); |
|
test_model.set_repeated_string(2, "Test"); |
|
EXPECT_EQ("Hello", test_model.repeated_string(0)); |
|
EXPECT_EQ("World", test_model.repeated_string(1)); |
|
EXPECT_EQ("Test", test_model.repeated_string(2)); |
|
} |
|
|
|
|
|
} // namespace
|
|
|