1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc. All rights reserved.
3 // https://developers.google.com/protocol-buffers/
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are
9 // * Redistributions of source code must retain the above copyright
10 // notice, this list of conditions and the following disclaimer.
11 // * Redistributions in binary form must reproduce the above
12 // copyright notice, this list of conditions and the following disclaimer
13 // in the documentation and/or other materials provided with the
15 // * Neither the name of Google Inc. nor the names of its
16 // contributors may be used to endorse or promote products derived from
17 // this software without specific prior written permission.
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 #include <unordered_map>
35 #include <google/protobuf/stubs/logging.h>
36 #include <google/protobuf/stubs/common.h>
37 #include <google/protobuf/arena_test_util.h>
38 #include <google/protobuf/map_test_util.h>
39 #include <google/protobuf/map_unittest.pb.h>
40 #include <google/protobuf/unittest.pb.h>
41 #include <google/protobuf/arena.h>
42 #include <google/protobuf/map.h>
43 #include <google/protobuf/map_field_inl.h>
44 #include <google/protobuf/message.h>
45 #include <google/protobuf/repeated_field.h>
46 #include <gtest/gtest.h>
53 using unittest::TestAllTypes;
55 class MapFieldBaseStub : public MapFieldBase {
57 typedef void InternalArenaConstructable_;
58 typedef void DestructorSkippable_;
60 explicit MapFieldBaseStub(Arena* arena) : MapFieldBase(arena) {}
61 void SyncRepeatedFieldWithMap() const {
62 MapFieldBase::SyncRepeatedFieldWithMap();
64 void SyncMapWithRepeatedField() const {
65 MapFieldBase::SyncMapWithRepeatedField();
67 // Get underlined repeated field without synchronizing map.
68 RepeatedPtrField<Message>* InternalRepeatedField() { return repeated_field_; }
70 return state_.load(std::memory_order_relaxed) != STATE_MODIFIED_MAP;
72 bool IsRepeatedClean() {
73 return state_.load(std::memory_order_relaxed) != STATE_MODIFIED_REPEATED;
76 state_.store(STATE_MODIFIED_MAP, std::memory_order_relaxed);
78 void SetRepeatedDirty() {
79 state_.store(STATE_MODIFIED_REPEATED, std::memory_order_relaxed);
81 bool ContainsMapKey(const MapKey& map_key) const override { return false; }
82 bool InsertOrLookupMapValue(const MapKey& map_key,
83 MapValueRef* val) override {
86 bool DeleteMapValue(const MapKey& map_key) override { return false; }
87 bool EqualIterator(const MapIterator& a,
88 const MapIterator& b) const override {
91 int size() const override { return 0; }
92 void Clear() override {}
93 void MapBegin(MapIterator* map_iter) const override {}
94 void MapEnd(MapIterator* map_iter) const override {}
95 void MergeFrom(const MapFieldBase& other) override {}
96 void Swap(MapFieldBase* other) override {}
97 void InitializeIterator(MapIterator* map_iter) const override {}
98 void DeleteIterator(MapIterator* map_iter) const override {}
99 void CopyIterator(MapIterator* this_iterator,
100 const MapIterator& other_iterator) const override {}
101 void IncreaseIterator(MapIterator* map_iter) const override {}
102 void SetDefaultMessageEntry(const Message* message) const {}
103 const Message* GetDefaultMessageEntry() const { return NULL; }
106 class MapFieldBasePrimitiveTest : public ::testing::Test {
108 typedef unittest::TestMap_MapInt32Int32Entry_DoNotUse EntryType;
109 typedef MapField<EntryType, int32, int32, WireFormatLite::TYPE_INT32,
110 WireFormatLite::TYPE_INT32, false>
113 MapFieldBasePrimitiveTest() {
115 map_descriptor_ = unittest::TestMap::descriptor()
116 ->FindFieldByName("map_int32_int32")
118 key_descriptor_ = map_descriptor_->FindFieldByName("key");
119 value_descriptor_ = map_descriptor_->FindFieldByName("value");
122 map_field_.reset(new MapFieldType);
123 map_field_base_ = map_field_.get();
124 map_ = map_field_->MutableMap();
125 initial_value_map_[0] = 100;
126 initial_value_map_[1] = 101;
127 map_->insert(initial_value_map_.begin(), initial_value_map_.end());
128 EXPECT_EQ(2, map_->size());
131 std::unique_ptr<MapFieldType> map_field_;
132 MapFieldBase* map_field_base_;
133 Map<int32, int32>* map_;
134 const Descriptor* map_descriptor_;
135 const FieldDescriptor* key_descriptor_;
136 const FieldDescriptor* value_descriptor_;
137 std::map<int32, int32> initial_value_map_; // copy of initial values inserted
140 TEST_F(MapFieldBasePrimitiveTest, SpaceUsedExcludingSelf) {
141 EXPECT_LT(0, map_field_base_->SpaceUsedExcludingSelf());
144 TEST_F(MapFieldBasePrimitiveTest, GetRepeatedField) {
145 const RepeatedPtrField<Message>& repeated =
146 reinterpret_cast<const RepeatedPtrField<Message>&>(
147 map_field_base_->GetRepeatedField());
148 EXPECT_EQ(2, repeated.size());
149 for (int i = 0; i < repeated.size(); i++) {
150 const Message& message = repeated.Get(i);
151 int key = message.GetReflection()->GetInt32(message, key_descriptor_);
152 int value = message.GetReflection()->GetInt32(message, value_descriptor_);
153 EXPECT_EQ(value, initial_value_map_[key]);
157 TEST_F(MapFieldBasePrimitiveTest, MutableRepeatedField) {
158 RepeatedPtrField<Message>* repeated =
159 reinterpret_cast<RepeatedPtrField<Message>*>(
160 map_field_base_->MutableRepeatedField());
161 EXPECT_EQ(2, repeated->size());
162 for (int i = 0; i < repeated->size(); i++) {
163 const Message& message = repeated->Get(i);
164 int key = message.GetReflection()->GetInt32(message, key_descriptor_);
165 int value = message.GetReflection()->GetInt32(message, value_descriptor_);
166 EXPECT_EQ(value, initial_value_map_[key]);
170 TEST_F(MapFieldBasePrimitiveTest, Arena) {
171 // Allocate a large initial block to avoid mallocs during hooked test.
172 std::vector<char> arena_block(128 * 1024);
173 ArenaOptions options;
174 options.initial_block = &arena_block[0];
175 options.initial_block_size = arena_block.size();
176 Arena arena(options);
179 // TODO(liujisi): Re-write the test to ensure the memory for the map and
180 // repeated fields are allocated from arenas.
181 // NoHeapChecker no_heap;
183 MapFieldType* map_field = Arena::CreateMessage<MapFieldType>(&arena);
185 // Set content in map
186 (*map_field->MutableMap())[100] = 101;
188 // Trigger conversion to repeated field.
189 map_field->GetRepeatedField();
193 // TODO(liujisi): Re-write the test to ensure the memory for the map and
194 // repeated fields are allocated from arenas.
195 // NoHeapChecker no_heap;
197 MapFieldBaseStub* map_field =
198 Arena::CreateMessage<MapFieldBaseStub>(&arena);
200 // Trigger conversion to repeated field.
201 EXPECT_TRUE(map_field->MutableRepeatedField() != NULL);
206 enum State { CLEAN, MAP_DIRTY, REPEATED_DIRTY };
207 } // anonymous namespace
209 class MapFieldStateTest : public testing::TestWithParam<State> {
212 typedef unittest::TestMap_MapInt32Int32Entry_DoNotUse EntryType;
213 typedef MapField<EntryType, int32, int32, WireFormatLite::TYPE_INT32,
214 WireFormatLite::TYPE_INT32, false>
216 MapFieldStateTest() : state_(GetParam()) {
218 map_field_.reset(new MapFieldType());
219 map_field_base_ = map_field_.get();
221 Expect(map_field_.get(), MAP_DIRTY, 0, 0, true);
224 AddOneStillClean(map_field_.get());
227 MakeMapDirty(map_field_.get());
230 MakeRepeatedDirty(map_field_.get());
237 void AddOneStillClean(MapFieldType* map_field) {
238 MapFieldBase* map_field_base = map_field;
239 Map<int32, int32>* map = map_field->MutableMap();
241 map_field_base->GetRepeatedField();
242 Expect(map_field, CLEAN, 1, 1, false);
245 void MakeMapDirty(MapFieldType* map_field) {
246 Map<int32, int32>* map = map_field->MutableMap();
248 Expect(map_field, MAP_DIRTY, 1, 0, true);
251 void MakeRepeatedDirty(MapFieldType* map_field) {
252 MakeMapDirty(map_field);
253 MapFieldBase* map_field_base = map_field;
254 map_field_base->MutableRepeatedField();
255 // We use MutableMap on impl_ because we don't want to disturb the syncing
256 Map<int32, int32>* map = map_field->impl_.MutableMap();
259 Expect(map_field, REPEATED_DIRTY, 0, 1, false);
262 void Expect(MapFieldType* map_field, State state, int map_size,
263 int repeated_size, bool is_repeated_null) {
264 MapFieldBase* map_field_base = map_field;
265 MapFieldBaseStub* stub =
266 reinterpret_cast<MapFieldBaseStub*>(map_field_base);
268 // We use MutableMap on impl_ because we don't want to disturb the syncing
269 Map<int32, int32>* map = map_field->impl_.MutableMap();
270 RepeatedPtrField<Message>* repeated_field = stub->InternalRepeatedField();
274 EXPECT_FALSE(stub->IsMapClean());
275 EXPECT_TRUE(stub->IsRepeatedClean());
278 EXPECT_TRUE(stub->IsMapClean());
279 EXPECT_FALSE(stub->IsRepeatedClean());
282 EXPECT_TRUE(stub->IsMapClean());
283 EXPECT_TRUE(stub->IsRepeatedClean());
289 EXPECT_EQ(map_size, map->size());
290 if (is_repeated_null) {
291 EXPECT_TRUE(repeated_field == NULL);
293 if (repeated_field == nullptr) {
294 EXPECT_EQ(repeated_size, 0);
296 EXPECT_EQ(repeated_size, repeated_field->size());
301 std::unique_ptr<MapFieldType> map_field_;
302 MapFieldBase* map_field_base_;
306 INSTANTIATE_TEST_SUITE_P(MapFieldStateTestInstance, MapFieldStateTest,
307 ::testing::Values(CLEAN, MAP_DIRTY, REPEATED_DIRTY));
309 TEST_P(MapFieldStateTest, GetMap) {
310 map_field_->GetMap();
311 if (state_ != MAP_DIRTY) {
312 Expect(map_field_.get(), CLEAN, 1, 1, false);
314 Expect(map_field_.get(), MAP_DIRTY, 1, 0, true);
318 TEST_P(MapFieldStateTest, MutableMap) {
319 map_field_->MutableMap();
320 if (state_ != MAP_DIRTY) {
321 Expect(map_field_.get(), MAP_DIRTY, 1, 1, false);
323 Expect(map_field_.get(), MAP_DIRTY, 1, 0, true);
327 TEST_P(MapFieldStateTest, MergeFromClean) {
329 AddOneStillClean(&other);
331 map_field_->MergeFrom(other);
333 if (state_ != MAP_DIRTY) {
334 Expect(map_field_.get(), MAP_DIRTY, 1, 1, false);
336 Expect(map_field_.get(), MAP_DIRTY, 1, 0, true);
339 Expect(&other, CLEAN, 1, 1, false);
342 TEST_P(MapFieldStateTest, MergeFromMapDirty) {
344 MakeMapDirty(&other);
346 map_field_->MergeFrom(other);
348 if (state_ != MAP_DIRTY) {
349 Expect(map_field_.get(), MAP_DIRTY, 1, 1, false);
351 Expect(map_field_.get(), MAP_DIRTY, 1, 0, true);
354 Expect(&other, MAP_DIRTY, 1, 0, true);
357 TEST_P(MapFieldStateTest, MergeFromRepeatedDirty) {
359 MakeRepeatedDirty(&other);
361 map_field_->MergeFrom(other);
363 if (state_ != MAP_DIRTY) {
364 Expect(map_field_.get(), MAP_DIRTY, 1, 1, false);
366 Expect(map_field_.get(), MAP_DIRTY, 1, 0, true);
369 Expect(&other, CLEAN, 1, 1, false);
372 TEST_P(MapFieldStateTest, SwapClean) {
374 AddOneStillClean(&other);
376 map_field_->Swap(&other);
378 Expect(map_field_.get(), CLEAN, 1, 1, false);
382 Expect(&other, CLEAN, 1, 1, false);
385 Expect(&other, MAP_DIRTY, 1, 0, true);
388 Expect(&other, REPEATED_DIRTY, 0, 1, false);
395 TEST_P(MapFieldStateTest, SwapMapDirty) {
397 MakeMapDirty(&other);
399 map_field_->Swap(&other);
401 Expect(map_field_.get(), MAP_DIRTY, 1, 0, true);
405 Expect(&other, CLEAN, 1, 1, false);
408 Expect(&other, MAP_DIRTY, 1, 0, true);
411 Expect(&other, REPEATED_DIRTY, 0, 1, false);
418 TEST_P(MapFieldStateTest, SwapRepeatedDirty) {
420 MakeRepeatedDirty(&other);
422 map_field_->Swap(&other);
424 Expect(map_field_.get(), REPEATED_DIRTY, 0, 1, false);
428 Expect(&other, CLEAN, 1, 1, false);
431 Expect(&other, MAP_DIRTY, 1, 0, true);
434 Expect(&other, REPEATED_DIRTY, 0, 1, false);
441 TEST_P(MapFieldStateTest, Clear) {
444 Expect(map_field_.get(), MAP_DIRTY, 0, 0, false);
447 TEST_P(MapFieldStateTest, SpaceUsedExcludingSelf) {
448 map_field_base_->SpaceUsedExcludingSelf();
452 Expect(map_field_.get(), CLEAN, 1, 1, false);
455 Expect(map_field_.get(), MAP_DIRTY, 1, 0, true);
458 Expect(map_field_.get(), REPEATED_DIRTY, 0, 1, false);
465 TEST_P(MapFieldStateTest, GetMapField) {
466 map_field_base_->GetRepeatedField();
468 if (state_ != REPEATED_DIRTY) {
469 Expect(map_field_.get(), CLEAN, 1, 1, false);
471 Expect(map_field_.get(), REPEATED_DIRTY, 0, 1, false);
475 TEST_P(MapFieldStateTest, MutableMapField) {
476 map_field_base_->MutableRepeatedField();
478 if (state_ != REPEATED_DIRTY) {
479 Expect(map_field_.get(), REPEATED_DIRTY, 1, 1, false);
481 Expect(map_field_.get(), REPEATED_DIRTY, 0, 1, false);
486 } // namespace internal
487 } // namespace protobuf
488 } // namespace google