diff options
Diffstat (limited to 'src/google/protobuf/repeated_field_unittest.cc')
-rw-r--r-- | src/google/protobuf/repeated_field_unittest.cc | 378 |
1 files changed, 342 insertions, 36 deletions
diff --git a/src/google/protobuf/repeated_field_unittest.cc b/src/google/protobuf/repeated_field_unittest.cc index 39b24b33..053a4d68 100644 --- a/src/google/protobuf/repeated_field_unittest.cc +++ b/src/google/protobuf/repeated_field_unittest.cc @@ -45,17 +45,19 @@ #include <google/protobuf/stubs/logging.h> #include <google/protobuf/stubs/common.h> #include <google/protobuf/unittest.pb.h> -#include <google/protobuf/stubs/strutil.h> +#include <gmock/gmock.h> #include <google/protobuf/testing/googletest.h> #include <gtest/gtest.h> +#include <google/protobuf/stubs/strutil.h> #include <google/protobuf/stubs/stl_util.h> namespace google { -using protobuf_unittest::TestAllTypes; - namespace protobuf { namespace { +using ::protobuf_unittest::TestAllTypes; +using ::testing::ElementsAre; + // Test operations on a small RepeatedField. TEST(RepeatedField, Small) { RepeatedField<int> field; @@ -95,7 +97,7 @@ TEST(RepeatedField, Small) { EXPECT_EQ(field.size(), 0); // Additional bytes are for 'struct Rep' header. int expected_usage = 4 * sizeof(int) + sizeof(Arena*); - EXPECT_EQ(field.SpaceUsedExcludingSelf(), expected_usage); + EXPECT_GE(field.SpaceUsedExcludingSelf(), expected_usage); } @@ -207,7 +209,7 @@ TEST(RepeatedField, ReserveMoreThanDouble) { RepeatedField<int> field; field.Reserve(20); - EXPECT_EQ(20, ReservedSpace(&field)); + EXPECT_LE(20, ReservedSpace(&field)); } TEST(RepeatedField, ReserveLessThanDouble) { @@ -215,9 +217,10 @@ TEST(RepeatedField, ReserveLessThanDouble) { // field to grow by double instead. RepeatedField<int> field; field.Reserve(20); - field.Reserve(30); + int capacity = field.Capacity(); + field.Reserve(capacity * 1.5); - EXPECT_EQ(40, ReservedSpace(&field)); + EXPECT_LE(2 * capacity, ReservedSpace(&field)); } TEST(RepeatedField, ReserveLessThanExisting) { @@ -229,7 +232,7 @@ TEST(RepeatedField, ReserveLessThanExisting) { field.Reserve(10); EXPECT_EQ(previous_ptr, field.data()); - EXPECT_EQ(20, ReservedSpace(&field)); + EXPECT_LE(20, ReservedSpace(&field)); } TEST(RepeatedField, Resize) { @@ -266,13 +269,6 @@ TEST(RepeatedField, MergeFrom) { EXPECT_EQ(5, destination.Get(4)); } -#ifdef PROTOBUF_HAS_DEATH_TEST -TEST(RepeatedField, MergeFromSelf) { - RepeatedField<int> me; - me.Add(3); - EXPECT_DEATH(me.MergeFrom(me), ""); -} -#endif // PROTOBUF_HAS_DEATH_TEST TEST(RepeatedField, CopyFrom) { RepeatedField<int> source, destination; @@ -343,7 +339,7 @@ TEST(RepeatedField, CopyConstruct) { } TEST(RepeatedField, IteratorConstruct) { - vector<int> values; + std::vector<int> values; values.push_back(1); values.push_back(2); @@ -387,6 +383,138 @@ TEST(RepeatedField, SelfAssign) { EXPECT_EQ(8, source.Get(1)); } +TEST(RepeatedField, MoveConstruct) { + { + RepeatedField<int> source; + source.Add(1); + source.Add(2); + const int* data = source.data(); + RepeatedField<int> destination = std::move(source); + EXPECT_EQ(data, destination.data()); + EXPECT_THAT(destination, ElementsAre(1, 2)); + // This property isn't guaranteed but it's useful to have a test that would + // catch changes in this area. + EXPECT_TRUE(source.empty()); + } + { + Arena arena; + RepeatedField<int>* source = + Arena::CreateMessage<RepeatedField<int>>(&arena); + source->Add(1); + source->Add(2); + RepeatedField<int> destination = std::move(*source); + EXPECT_EQ(nullptr, destination.GetArena()); + EXPECT_THAT(destination, ElementsAre(1, 2)); + // This property isn't guaranteed but it's useful to have a test that would + // catch changes in this area. + EXPECT_THAT(*source, ElementsAre(1, 2)); + } +} + +TEST(RepeatedField, MoveAssign) { + { + RepeatedField<int> source; + source.Add(1); + source.Add(2); + RepeatedField<int> destination; + destination.Add(3); + const int* source_data = source.data(); + const int* destination_data = destination.data(); + destination = std::move(source); + EXPECT_EQ(source_data, destination.data()); + EXPECT_THAT(destination, ElementsAre(1, 2)); + // This property isn't guaranteed but it's useful to have a test that would + // catch changes in this area. + EXPECT_EQ(destination_data, source.data()); + EXPECT_THAT(source, ElementsAre(3)); + } + { + Arena arena; + RepeatedField<int>* source = + Arena::CreateMessage<RepeatedField<int>>(&arena); + source->Add(1); + source->Add(2); + RepeatedField<int>* destination = + Arena::CreateMessage<RepeatedField<int>>(&arena); + destination->Add(3); + const int* source_data = source->data(); + const int* destination_data = destination->data(); + *destination = std::move(*source); + EXPECT_EQ(source_data, destination->data()); + EXPECT_THAT(*destination, ElementsAre(1, 2)); + // This property isn't guaranteed but it's useful to have a test that would + // catch changes in this area. + EXPECT_EQ(destination_data, source->data()); + EXPECT_THAT(*source, ElementsAre(3)); + } + { + Arena source_arena; + RepeatedField<int>* source = + Arena::CreateMessage<RepeatedField<int>>(&source_arena); + source->Add(1); + source->Add(2); + Arena destination_arena; + RepeatedField<int>* destination = + Arena::CreateMessage<RepeatedField<int>>(&destination_arena); + destination->Add(3); + *destination = std::move(*source); + EXPECT_THAT(*destination, ElementsAre(1, 2)); + // This property isn't guaranteed but it's useful to have a test that would + // catch changes in this area. + EXPECT_THAT(*source, ElementsAre(1, 2)); + } + { + Arena arena; + RepeatedField<int>* source = + Arena::CreateMessage<RepeatedField<int>>(&arena); + source->Add(1); + source->Add(2); + RepeatedField<int> destination; + destination.Add(3); + destination = std::move(*source); + EXPECT_THAT(destination, ElementsAre(1, 2)); + // This property isn't guaranteed but it's useful to have a test that would + // catch changes in this area. + EXPECT_THAT(*source, ElementsAre(1, 2)); + } + { + RepeatedField<int> source; + source.Add(1); + source.Add(2); + Arena arena; + RepeatedField<int>* destination = + Arena::CreateMessage<RepeatedField<int>>(&arena); + destination->Add(3); + *destination = std::move(source); + EXPECT_THAT(*destination, ElementsAre(1, 2)); + // This property isn't guaranteed but it's useful to have a test that would + // catch changes in this area. + EXPECT_THAT(source, ElementsAre(1, 2)); + } + { + RepeatedField<int> field; + // An alias to defeat -Wself-move. + RepeatedField<int>& alias = field; + field.Add(1); + field.Add(2); + const int* data = field.data(); + field = std::move(alias); + EXPECT_EQ(data, field.data()); + EXPECT_THAT(field, ElementsAre(1, 2)); + } + { + Arena arena; + RepeatedField<int>* field = + Arena::CreateMessage<RepeatedField<int>>(&arena); + field->Add(1); + field->Add(2); + const int* data = field->data(); + *field = std::move(*field); + EXPECT_EQ(data, field->data()); + EXPECT_THAT(*field, ElementsAre(1, 2)); + } +} + TEST(RepeatedField, MutableDataIsMutable) { RepeatedField<int> field; field.Add(1); @@ -397,6 +525,16 @@ TEST(RepeatedField, MutableDataIsMutable) { EXPECT_EQ(2, field.Get(0)); } +TEST(RepeatedField, SubscriptOperators) { + RepeatedField<int> field; + field.Add(1); + EXPECT_EQ(1, field.Get(0)); + EXPECT_EQ(1, field[0]); + EXPECT_EQ(field.Mutable(0), &field[0]); + const RepeatedField<int>& const_field = field; + EXPECT_EQ(field.data(), &const_field[0]); +} + TEST(RepeatedField, Truncate) { RepeatedField<int> field; @@ -470,11 +608,11 @@ TEST(RepeatedField, ClearThenReserveMore) { EXPECT_EQ(32, field.size()); field.Clear(); EXPECT_EQ(0, field.size()); - EXPECT_EQ(32, field.Capacity()); + EXPECT_LE(32, field.Capacity()); field.Reserve(1024); EXPECT_EQ(0, field.size()); - EXPECT_EQ(1024, field.Capacity()); + EXPECT_LE(1024, field.Capacity()); // Finish test -- |field| should destroy the cleared-but-not-yet-destroyed // strings. } @@ -629,15 +767,18 @@ TEST(RepeatedPtrField, ReserveMoreThanDouble) { RepeatedPtrField<string> field; field.Reserve(20); - EXPECT_EQ(20, ReservedSpace(&field)); + EXPECT_LE(20, ReservedSpace(&field)); } TEST(RepeatedPtrField, ReserveLessThanDouble) { RepeatedPtrField<string> field; field.Reserve(20); - field.Reserve(30); - EXPECT_EQ(40, ReservedSpace(&field)); + int capacity = field.Capacity(); + // Grow by 1.5x + field.Reserve(capacity + (capacity >> 2)); + + EXPECT_LE(2 * capacity, ReservedSpace(&field)); } TEST(RepeatedPtrField, ReserveLessThanExisting) { @@ -647,7 +788,7 @@ TEST(RepeatedPtrField, ReserveLessThanExisting) { field.Reserve(10); EXPECT_EQ(previous_ptr, field.data()); - EXPECT_EQ(20, ReservedSpace(&field)); + EXPECT_LE(20, ReservedSpace(&field)); } TEST(RepeatedPtrField, ReserveDoesntLoseAllocated) { @@ -767,13 +908,6 @@ TEST(RepeatedPtrField, MergeFrom) { EXPECT_EQ("5", destination.Get(4)); } -#ifdef PROTOBUF_HAS_DEATH_TEST -TEST(RepeatedPtrField, MergeFromSelf) { - RepeatedPtrField<string> me; - me.Add()->assign("1"); - EXPECT_DEATH(me.MergeFrom(me), ""); -} -#endif // PROTOBUF_HAS_DEATH_TEST TEST(RepeatedPtrField, CopyFrom) { RepeatedPtrField<string> source, destination; @@ -844,7 +978,7 @@ TEST(RepeatedPtrField, CopyConstruct) { } TEST(RepeatedPtrField, IteratorConstruct_String) { - vector<string> values; + std::vector<string> values; values.push_back("1"); values.push_back("2"); @@ -861,7 +995,7 @@ TEST(RepeatedPtrField, IteratorConstruct_String) { TEST(RepeatedPtrField, IteratorConstruct_Proto) { typedef TestAllTypes::NestedMessage Nested; - vector<Nested> values; + std::vector<Nested> values; values.push_back(Nested()); values.back().set_bb(1); values.push_back(Nested()); @@ -907,6 +1041,138 @@ TEST(RepeatedPtrField, SelfAssign) { EXPECT_EQ("8", source.Get(1)); } +TEST(RepeatedPtrField, MoveConstruct) { + { + RepeatedPtrField<string> source; + *source.Add() = "1"; + *source.Add() = "2"; + const string* const* data = source.data(); + RepeatedPtrField<string> destination = std::move(source); + EXPECT_EQ(data, destination.data()); + EXPECT_THAT(destination, ElementsAre("1", "2")); + // This property isn't guaranteed but it's useful to have a test that would + // catch changes in this area. + EXPECT_TRUE(source.empty()); + } + { + Arena arena; + RepeatedPtrField<string>* source = + Arena::CreateMessage<RepeatedPtrField<string>>(&arena); + *source->Add() = "1"; + *source->Add() = "2"; + RepeatedPtrField<string> destination = std::move(*source); + EXPECT_EQ(nullptr, destination.GetArena()); + EXPECT_THAT(destination, ElementsAre("1", "2")); + // This property isn't guaranteed but it's useful to have a test that would + // catch changes in this area. + EXPECT_THAT(*source, ElementsAre("1", "2")); + } +} + +TEST(RepeatedPtrField, MoveAssign) { + { + RepeatedPtrField<string> source; + *source.Add() = "1"; + *source.Add() = "2"; + RepeatedPtrField<string> destination; + *destination.Add() = "3"; + const string* const* source_data = source.data(); + const string* const* destination_data = destination.data(); + destination = std::move(source); + EXPECT_EQ(source_data, destination.data()); + EXPECT_THAT(destination, ElementsAre("1", "2")); + // This property isn't guaranteed but it's useful to have a test that would + // catch changes in this area. + EXPECT_EQ(destination_data, source.data()); + EXPECT_THAT(source, ElementsAre("3")); + } + { + Arena arena; + RepeatedPtrField<string>* source = + Arena::CreateMessage<RepeatedPtrField<string>>(&arena); + *source->Add() = "1"; + *source->Add() = "2"; + RepeatedPtrField<string>* destination = + Arena::CreateMessage<RepeatedPtrField<string>>(&arena); + *destination->Add() = "3"; + const string* const* source_data = source->data(); + const string* const* destination_data = destination->data(); + *destination = std::move(*source); + EXPECT_EQ(source_data, destination->data()); + EXPECT_THAT(*destination, ElementsAre("1", "2")); + // This property isn't guaranteed but it's useful to have a test that would + // catch changes in this area. + EXPECT_EQ(destination_data, source->data()); + EXPECT_THAT(*source, ElementsAre("3")); + } + { + Arena source_arena; + RepeatedPtrField<string>* source = + Arena::CreateMessage<RepeatedPtrField<string>>(&source_arena); + *source->Add() = "1"; + *source->Add() = "2"; + Arena destination_arena; + RepeatedPtrField<string>* destination = + Arena::CreateMessage<RepeatedPtrField<string>>(&destination_arena); + *destination->Add() = "3"; + *destination = std::move(*source); + EXPECT_THAT(*destination, ElementsAre("1", "2")); + // This property isn't guaranteed but it's useful to have a test that would + // catch changes in this area. + EXPECT_THAT(*source, ElementsAre("1", "2")); + } + { + Arena arena; + RepeatedPtrField<string>* source = + Arena::CreateMessage<RepeatedPtrField<string>>(&arena); + *source->Add() = "1"; + *source->Add() = "2"; + RepeatedPtrField<string> destination; + *destination.Add() = "3"; + destination = std::move(*source); + EXPECT_THAT(destination, ElementsAre("1", "2")); + // This property isn't guaranteed but it's useful to have a test that would + // catch changes in this area. + EXPECT_THAT(*source, ElementsAre("1", "2")); + } + { + RepeatedPtrField<string> source; + *source.Add() = "1"; + *source.Add() = "2"; + Arena arena; + RepeatedPtrField<string>* destination = + Arena::CreateMessage<RepeatedPtrField<string>>(&arena); + *destination->Add() = "3"; + *destination = std::move(source); + EXPECT_THAT(*destination, ElementsAre("1", "2")); + // This property isn't guaranteed but it's useful to have a test that would + // catch changes in this area. + EXPECT_THAT(source, ElementsAre("1", "2")); + } + { + RepeatedPtrField<string> field; + // An alias to defeat -Wself-move. + RepeatedPtrField<string>& alias = field; + *field.Add() = "1"; + *field.Add() = "2"; + const string* const* data = field.data(); + field = std::move(alias); + EXPECT_EQ(data, field.data()); + EXPECT_THAT(field, ElementsAre("1", "2")); + } + { + Arena arena; + RepeatedPtrField<string>* field = + Arena::CreateMessage<RepeatedPtrField<string>>(&arena); + *field->Add() = "1"; + *field->Add() = "2"; + const string* const* data = field->data(); + *field = std::move(*field); + EXPECT_EQ(data, field->data()); + EXPECT_THAT(*field, ElementsAre("1", "2")); + } +} + TEST(RepeatedPtrField, MutableDataIsMutable) { RepeatedPtrField<string> field; *field.Add() = "1"; @@ -918,6 +1184,16 @@ TEST(RepeatedPtrField, MutableDataIsMutable) { EXPECT_EQ("2", field.Get(0)); } +TEST(RepeatedPtrField, SubscriptOperators) { + RepeatedPtrField<string> field; + *field.Add() = "1"; + EXPECT_EQ("1", field.Get(0)); + EXPECT_EQ("1", field[0]); + EXPECT_EQ(field.Mutable(0), &field[0]); + const RepeatedPtrField<string>& const_field = field; + EXPECT_EQ(*field.data(), &const_field[0]); +} + TEST(RepeatedPtrField, ExtractSubrange) { // Exhaustively test every subrange in arrays of all sizes from 0 through 9 // with 0 through 3 cleared elements at the end. @@ -925,7 +1201,7 @@ TEST(RepeatedPtrField, ExtractSubrange) { for (int num = 0; num <= sz; ++num) { for (int start = 0; start < sz - num; ++start) { for (int extra = 0; extra < 4; ++extra) { - vector<string*> subject; + std::vector<string*> subject; // Create an array with "sz" elements and "extra" cleared elements. RepeatedPtrField<string> field; @@ -1487,7 +1763,7 @@ TEST_F(RepeatedFieldInsertionIteratorsTest, Nesteds) { TEST_F(RepeatedFieldInsertionIteratorsTest, AllocatedRepeatedPtrFieldWithStringIntData) { - vector<Nested*> data; + std::vector<Nested*> data; TestAllTypes goldenproto; for (int i = 0; i < 10; ++i) { Nested* new_data = new Nested; @@ -1506,7 +1782,7 @@ TEST_F(RepeatedFieldInsertionIteratorsTest, TEST_F(RepeatedFieldInsertionIteratorsTest, AllocatedRepeatedPtrFieldWithString) { - vector<string*> data; + std::vector<string*> data; TestAllTypes goldenproto; for (int i = 0; i < 10; ++i) { string* new_data = new string; @@ -1524,7 +1800,7 @@ TEST_F(RepeatedFieldInsertionIteratorsTest, TEST_F(RepeatedFieldInsertionIteratorsTest, UnsafeArenaAllocatedRepeatedPtrFieldWithStringIntData) { - vector<Nested*> data; + std::vector<Nested*> data; TestAllTypes goldenproto; for (int i = 0; i < 10; ++i) { Nested* new_data = new Nested; @@ -1543,7 +1819,7 @@ TEST_F(RepeatedFieldInsertionIteratorsTest, TEST_F(RepeatedFieldInsertionIteratorsTest, UnsafeArenaAllocatedRepeatedPtrFieldWithString) { - vector<string*> data; + std::vector<string*> data; TestAllTypes goldenproto; for (int i = 0; i < 10; ++i) { string* new_data = new string; @@ -1560,6 +1836,36 @@ TEST_F(RepeatedFieldInsertionIteratorsTest, EXPECT_EQ(testproto.DebugString(), goldenproto.DebugString()); } +TEST_F(RepeatedFieldInsertionIteratorsTest, MoveStrings) { + std::vector<string> src = {"a", "b", "c", "d"}; + std::vector<string> copy = src; // copy since move leaves in undefined state + TestAllTypes testproto; + std::move(copy.begin(), copy.end(), + RepeatedFieldBackInserter(testproto.mutable_repeated_string())); + + ASSERT_THAT(testproto.repeated_string(), testing::ElementsAreArray(src)); +} + +TEST_F(RepeatedFieldInsertionIteratorsTest, MoveProtos) { + auto make_nested = [](int32 x) { + Nested ret; + ret.set_bb(x); + return ret; + }; + std::vector<Nested> src = {make_nested(3), make_nested(5), make_nested(7)}; + std::vector<Nested> copy = src; // copy since move leaves in undefined state + TestAllTypes testproto; + std::move( + copy.begin(), copy.end(), + RepeatedFieldBackInserter(testproto.mutable_repeated_nested_message())); + + ASSERT_EQ(src.size(), testproto.repeated_nested_message_size()); + for (int i = 0; i < src.size(); ++i) { + EXPECT_EQ(src[i].DebugString(), + testproto.repeated_nested_message(i).DebugString()); + } +} + } // namespace } // namespace protobuf |