Imported Upstream version 3.8.0
[platform/upstream/protobuf.git] / src / google / protobuf / map_field_test.cc
1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc.  All rights reserved.
3 // https://developers.google.com/protocol-buffers/
4 //
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are
7 // met:
8 //
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
14 // distribution.
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.
18 //
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.
30
31 #include <map>
32 #include <memory>
33 #include <unordered_map>
34
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>
47
48 namespace google {
49 namespace protobuf {
50
51 namespace internal {
52
53 using unittest::TestAllTypes;
54
55 class MapFieldBaseStub : public MapFieldBase {
56  public:
57   typedef void InternalArenaConstructable_;
58   typedef void DestructorSkippable_;
59   MapFieldBaseStub() {}
60   explicit MapFieldBaseStub(Arena* arena) : MapFieldBase(arena) {}
61   void SyncRepeatedFieldWithMap() const {
62     MapFieldBase::SyncRepeatedFieldWithMap();
63   }
64   void SyncMapWithRepeatedField() const {
65     MapFieldBase::SyncMapWithRepeatedField();
66   }
67   // Get underlined repeated field without synchronizing map.
68   RepeatedPtrField<Message>* InternalRepeatedField() { return repeated_field_; }
69   bool IsMapClean() {
70     return state_.load(std::memory_order_relaxed) != STATE_MODIFIED_MAP;
71   }
72   bool IsRepeatedClean() {
73     return state_.load(std::memory_order_relaxed) != STATE_MODIFIED_REPEATED;
74   }
75   void SetMapDirty() {
76     state_.store(STATE_MODIFIED_MAP, std::memory_order_relaxed);
77   }
78   void SetRepeatedDirty() {
79     state_.store(STATE_MODIFIED_REPEATED, std::memory_order_relaxed);
80   }
81   bool ContainsMapKey(const MapKey& map_key) const override { return false; }
82   bool InsertOrLookupMapValue(const MapKey& map_key,
83                               MapValueRef* val) override {
84     return false;
85   }
86   bool DeleteMapValue(const MapKey& map_key) override { return false; }
87   bool EqualIterator(const MapIterator& a,
88                      const MapIterator& b) const override {
89     return false;
90   }
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; }
104 };
105
106 class MapFieldBasePrimitiveTest : public ::testing::Test {
107  protected:
108   typedef unittest::TestMap_MapInt32Int32Entry_DoNotUse EntryType;
109   typedef MapField<EntryType, int32, int32, WireFormatLite::TYPE_INT32,
110                    WireFormatLite::TYPE_INT32, false>
111       MapFieldType;
112
113   MapFieldBasePrimitiveTest() {
114     // Get descriptors
115     map_descriptor_ = unittest::TestMap::descriptor()
116                           ->FindFieldByName("map_int32_int32")
117                           ->message_type();
118     key_descriptor_ = map_descriptor_->FindFieldByName("key");
119     value_descriptor_ = map_descriptor_->FindFieldByName("value");
120
121     // Build map field
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());
129   }
130
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
138 };
139
140 TEST_F(MapFieldBasePrimitiveTest, SpaceUsedExcludingSelf) {
141   EXPECT_LT(0, map_field_base_->SpaceUsedExcludingSelf());
142 }
143
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]);
154   }
155 }
156
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]);
167   }
168 }
169
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);
177
178   {
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;
182
183     MapFieldType* map_field = Arena::CreateMessage<MapFieldType>(&arena);
184
185     // Set content in map
186     (*map_field->MutableMap())[100] = 101;
187
188     // Trigger conversion to repeated field.
189     map_field->GetRepeatedField();
190   }
191
192   {
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;
196
197     MapFieldBaseStub* map_field =
198         Arena::CreateMessage<MapFieldBaseStub>(&arena);
199
200     // Trigger conversion to repeated field.
201     EXPECT_TRUE(map_field->MutableRepeatedField() != NULL);
202   }
203 }
204
205 namespace {
206 enum State { CLEAN, MAP_DIRTY, REPEATED_DIRTY };
207 }  // anonymous namespace
208
209 class MapFieldStateTest : public testing::TestWithParam<State> {
210  public:
211  protected:
212   typedef unittest::TestMap_MapInt32Int32Entry_DoNotUse EntryType;
213   typedef MapField<EntryType, int32, int32, WireFormatLite::TYPE_INT32,
214                    WireFormatLite::TYPE_INT32, false>
215       MapFieldType;
216   MapFieldStateTest() : state_(GetParam()) {
217     // Build map field
218     map_field_.reset(new MapFieldType());
219     map_field_base_ = map_field_.get();
220
221     Expect(map_field_.get(), MAP_DIRTY, 0, 0, true);
222     switch (state_) {
223       case CLEAN:
224         AddOneStillClean(map_field_.get());
225         break;
226       case MAP_DIRTY:
227         MakeMapDirty(map_field_.get());
228         break;
229       case REPEATED_DIRTY:
230         MakeRepeatedDirty(map_field_.get());
231         break;
232       default:
233         break;
234     }
235   }
236
237   void AddOneStillClean(MapFieldType* map_field) {
238     MapFieldBase* map_field_base = map_field;
239     Map<int32, int32>* map = map_field->MutableMap();
240     (*map)[0] = 0;
241     map_field_base->GetRepeatedField();
242     Expect(map_field, CLEAN, 1, 1, false);
243   }
244
245   void MakeMapDirty(MapFieldType* map_field) {
246     Map<int32, int32>* map = map_field->MutableMap();
247     (*map)[0] = 0;
248     Expect(map_field, MAP_DIRTY, 1, 0, true);
249   }
250
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();
257     map->clear();
258
259     Expect(map_field, REPEATED_DIRTY, 0, 1, false);
260   }
261
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);
267
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();
271
272     switch (state) {
273       case MAP_DIRTY:
274         EXPECT_FALSE(stub->IsMapClean());
275         EXPECT_TRUE(stub->IsRepeatedClean());
276         break;
277       case REPEATED_DIRTY:
278         EXPECT_TRUE(stub->IsMapClean());
279         EXPECT_FALSE(stub->IsRepeatedClean());
280         break;
281       case CLEAN:
282         EXPECT_TRUE(stub->IsMapClean());
283         EXPECT_TRUE(stub->IsRepeatedClean());
284         break;
285       default:
286         FAIL();
287     }
288
289     EXPECT_EQ(map_size, map->size());
290     if (is_repeated_null) {
291       EXPECT_TRUE(repeated_field == NULL);
292     } else {
293       if (repeated_field == nullptr) {
294         EXPECT_EQ(repeated_size, 0);
295       } else {
296         EXPECT_EQ(repeated_size, repeated_field->size());
297       }
298     }
299   }
300
301   std::unique_ptr<MapFieldType> map_field_;
302   MapFieldBase* map_field_base_;
303   State state_;
304 };
305
306 INSTANTIATE_TEST_SUITE_P(MapFieldStateTestInstance, MapFieldStateTest,
307                          ::testing::Values(CLEAN, MAP_DIRTY, REPEATED_DIRTY));
308
309 TEST_P(MapFieldStateTest, GetMap) {
310   map_field_->GetMap();
311   if (state_ != MAP_DIRTY) {
312     Expect(map_field_.get(), CLEAN, 1, 1, false);
313   } else {
314     Expect(map_field_.get(), MAP_DIRTY, 1, 0, true);
315   }
316 }
317
318 TEST_P(MapFieldStateTest, MutableMap) {
319   map_field_->MutableMap();
320   if (state_ != MAP_DIRTY) {
321     Expect(map_field_.get(), MAP_DIRTY, 1, 1, false);
322   } else {
323     Expect(map_field_.get(), MAP_DIRTY, 1, 0, true);
324   }
325 }
326
327 TEST_P(MapFieldStateTest, MergeFromClean) {
328   MapFieldType other;
329   AddOneStillClean(&other);
330
331   map_field_->MergeFrom(other);
332
333   if (state_ != MAP_DIRTY) {
334     Expect(map_field_.get(), MAP_DIRTY, 1, 1, false);
335   } else {
336     Expect(map_field_.get(), MAP_DIRTY, 1, 0, true);
337   }
338
339   Expect(&other, CLEAN, 1, 1, false);
340 }
341
342 TEST_P(MapFieldStateTest, MergeFromMapDirty) {
343   MapFieldType other;
344   MakeMapDirty(&other);
345
346   map_field_->MergeFrom(other);
347
348   if (state_ != MAP_DIRTY) {
349     Expect(map_field_.get(), MAP_DIRTY, 1, 1, false);
350   } else {
351     Expect(map_field_.get(), MAP_DIRTY, 1, 0, true);
352   }
353
354   Expect(&other, MAP_DIRTY, 1, 0, true);
355 }
356
357 TEST_P(MapFieldStateTest, MergeFromRepeatedDirty) {
358   MapFieldType other;
359   MakeRepeatedDirty(&other);
360
361   map_field_->MergeFrom(other);
362
363   if (state_ != MAP_DIRTY) {
364     Expect(map_field_.get(), MAP_DIRTY, 1, 1, false);
365   } else {
366     Expect(map_field_.get(), MAP_DIRTY, 1, 0, true);
367   }
368
369   Expect(&other, CLEAN, 1, 1, false);
370 }
371
372 TEST_P(MapFieldStateTest, SwapClean) {
373   MapFieldType other;
374   AddOneStillClean(&other);
375
376   map_field_->Swap(&other);
377
378   Expect(map_field_.get(), CLEAN, 1, 1, false);
379
380   switch (state_) {
381     case CLEAN:
382       Expect(&other, CLEAN, 1, 1, false);
383       break;
384     case MAP_DIRTY:
385       Expect(&other, MAP_DIRTY, 1, 0, true);
386       break;
387     case REPEATED_DIRTY:
388       Expect(&other, REPEATED_DIRTY, 0, 1, false);
389       break;
390     default:
391       break;
392   }
393 }
394
395 TEST_P(MapFieldStateTest, SwapMapDirty) {
396   MapFieldType other;
397   MakeMapDirty(&other);
398
399   map_field_->Swap(&other);
400
401   Expect(map_field_.get(), MAP_DIRTY, 1, 0, true);
402
403   switch (state_) {
404     case CLEAN:
405       Expect(&other, CLEAN, 1, 1, false);
406       break;
407     case MAP_DIRTY:
408       Expect(&other, MAP_DIRTY, 1, 0, true);
409       break;
410     case REPEATED_DIRTY:
411       Expect(&other, REPEATED_DIRTY, 0, 1, false);
412       break;
413     default:
414       break;
415   }
416 }
417
418 TEST_P(MapFieldStateTest, SwapRepeatedDirty) {
419   MapFieldType other;
420   MakeRepeatedDirty(&other);
421
422   map_field_->Swap(&other);
423
424   Expect(map_field_.get(), REPEATED_DIRTY, 0, 1, false);
425
426   switch (state_) {
427     case CLEAN:
428       Expect(&other, CLEAN, 1, 1, false);
429       break;
430     case MAP_DIRTY:
431       Expect(&other, MAP_DIRTY, 1, 0, true);
432       break;
433     case REPEATED_DIRTY:
434       Expect(&other, REPEATED_DIRTY, 0, 1, false);
435       break;
436     default:
437       break;
438   }
439 }
440
441 TEST_P(MapFieldStateTest, Clear) {
442   map_field_->Clear();
443
444   Expect(map_field_.get(), MAP_DIRTY, 0, 0, false);
445 }
446
447 TEST_P(MapFieldStateTest, SpaceUsedExcludingSelf) {
448   map_field_base_->SpaceUsedExcludingSelf();
449
450   switch (state_) {
451     case CLEAN:
452       Expect(map_field_.get(), CLEAN, 1, 1, false);
453       break;
454     case MAP_DIRTY:
455       Expect(map_field_.get(), MAP_DIRTY, 1, 0, true);
456       break;
457     case REPEATED_DIRTY:
458       Expect(map_field_.get(), REPEATED_DIRTY, 0, 1, false);
459       break;
460     default:
461       break;
462   }
463 }
464
465 TEST_P(MapFieldStateTest, GetMapField) {
466   map_field_base_->GetRepeatedField();
467
468   if (state_ != REPEATED_DIRTY) {
469     Expect(map_field_.get(), CLEAN, 1, 1, false);
470   } else {
471     Expect(map_field_.get(), REPEATED_DIRTY, 0, 1, false);
472   }
473 }
474
475 TEST_P(MapFieldStateTest, MutableMapField) {
476   map_field_base_->MutableRepeatedField();
477
478   if (state_ != REPEATED_DIRTY) {
479     Expect(map_field_.get(), REPEATED_DIRTY, 1, 1, false);
480   } else {
481     Expect(map_field_.get(), REPEATED_DIRTY, 0, 1, false);
482   }
483 }
484
485
486 }  // namespace internal
487 }  // namespace protobuf
488 }  // namespace google