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 // Must be included last.
49 #include <google/protobuf/port_def.inc>
50
51 namespace google {
52 namespace protobuf {
53
54 namespace internal {
55
56 using unittest::TestAllTypes;
57
58 class MapFieldBaseStub : public MapFieldBase {
59 public:
60 typedef void InternalArenaConstructable_;
61 typedef void DestructorSkippable_;
MapFieldBaseStub()62 MapFieldBaseStub() {}
MapFieldBaseStub(Arena * arena)63 explicit MapFieldBaseStub(Arena* arena) : MapFieldBase(arena) {}
64 // Get underlined repeated field without synchronizing map.
InternalRepeatedField()65 RepeatedPtrField<Message>* InternalRepeatedField() { return repeated_field_; }
IsMapClean()66 bool IsMapClean() {
67 return state_.load(std::memory_order_relaxed) != STATE_MODIFIED_MAP;
68 }
IsRepeatedClean()69 bool IsRepeatedClean() {
70 return state_.load(std::memory_order_relaxed) != STATE_MODIFIED_REPEATED;
71 }
SetMapDirty()72 void SetMapDirty() {
73 state_.store(STATE_MODIFIED_MAP, std::memory_order_relaxed);
74 }
SetRepeatedDirty()75 void SetRepeatedDirty() {
76 state_.store(STATE_MODIFIED_REPEATED, std::memory_order_relaxed);
77 }
ContainsMapKey(const MapKey & map_key) const78 bool ContainsMapKey(const MapKey& map_key) const override { return false; }
InsertOrLookupMapValue(const MapKey & map_key,MapValueRef * val)79 bool InsertOrLookupMapValue(const MapKey& map_key,
80 MapValueRef* val) override {
81 return false;
82 }
LookupMapValue(const MapKey & map_key,MapValueConstRef * val) const83 bool LookupMapValue(const MapKey& map_key,
84 MapValueConstRef* val) const override {
85 return false;
86 }
DeleteMapValue(const MapKey & map_key)87 bool DeleteMapValue(const MapKey& map_key) override { return false; }
EqualIterator(const MapIterator & a,const MapIterator & b) const88 bool EqualIterator(const MapIterator& a,
89 const MapIterator& b) const override {
90 return false;
91 }
size() const92 int size() const override { return 0; }
Clear()93 void Clear() override {}
MapBegin(MapIterator * map_iter) const94 void MapBegin(MapIterator* map_iter) const override {}
MapEnd(MapIterator * map_iter) const95 void MapEnd(MapIterator* map_iter) const override {}
MergeFrom(const MapFieldBase & other)96 void MergeFrom(const MapFieldBase& other) override {}
Swap(MapFieldBase * other)97 void Swap(MapFieldBase* other) override {}
InitializeIterator(MapIterator * map_iter) const98 void InitializeIterator(MapIterator* map_iter) const override {}
DeleteIterator(MapIterator * map_iter) const99 void DeleteIterator(MapIterator* map_iter) const override {}
CopyIterator(MapIterator * this_iterator,const MapIterator & other_iterator) const100 void CopyIterator(MapIterator* this_iterator,
101 const MapIterator& other_iterator) const override {}
IncreaseIterator(MapIterator * map_iter) const102 void IncreaseIterator(MapIterator* map_iter) const override {}
103 };
104
105 class MapFieldBasePrimitiveTest : public ::testing::Test {
106 protected:
107 typedef unittest::TestMap_MapInt32Int32Entry_DoNotUse EntryType;
108 typedef MapField<EntryType, int32, int32, WireFormatLite::TYPE_INT32,
109 WireFormatLite::TYPE_INT32>
110 MapFieldType;
111
MapFieldBasePrimitiveTest()112 MapFieldBasePrimitiveTest() {
113 // Get descriptors
114 map_descriptor_ = unittest::TestMap::descriptor()
115 ->FindFieldByName("map_int32_int32")
116 ->message_type();
117 key_descriptor_ = map_descriptor_->map_key();
118 value_descriptor_ = map_descriptor_->map_value();
119
120 // Build map field
121 map_field_.reset(new MapFieldType);
122 map_field_base_ = map_field_.get();
123 map_ = map_field_->MutableMap();
124 initial_value_map_[0] = 100;
125 initial_value_map_[1] = 101;
126 map_->insert(initial_value_map_.begin(), initial_value_map_.end());
127 EXPECT_EQ(2, map_->size());
128 }
129
130 std::unique_ptr<MapFieldType> map_field_;
131 MapFieldBase* map_field_base_;
132 Map<int32, int32>* map_;
133 const Descriptor* map_descriptor_;
134 const FieldDescriptor* key_descriptor_;
135 const FieldDescriptor* value_descriptor_;
136 std::map<int32, int32> initial_value_map_; // copy of initial values inserted
137 };
138
TEST_F(MapFieldBasePrimitiveTest,SpaceUsedExcludingSelf)139 TEST_F(MapFieldBasePrimitiveTest, SpaceUsedExcludingSelf) {
140 EXPECT_LT(0, map_field_base_->SpaceUsedExcludingSelf());
141 }
142
TEST_F(MapFieldBasePrimitiveTest,GetRepeatedField)143 TEST_F(MapFieldBasePrimitiveTest, GetRepeatedField) {
144 const RepeatedPtrField<Message>& repeated =
145 reinterpret_cast<const RepeatedPtrField<Message>&>(
146 map_field_base_->GetRepeatedField());
147 EXPECT_EQ(2, repeated.size());
148 for (int i = 0; i < repeated.size(); i++) {
149 const Message& message = repeated.Get(i);
150 int key = message.GetReflection()->GetInt32(message, key_descriptor_);
151 int value = message.GetReflection()->GetInt32(message, value_descriptor_);
152 EXPECT_EQ(value, initial_value_map_[key]);
153 }
154 }
155
TEST_F(MapFieldBasePrimitiveTest,MutableRepeatedField)156 TEST_F(MapFieldBasePrimitiveTest, MutableRepeatedField) {
157 RepeatedPtrField<Message>* repeated =
158 reinterpret_cast<RepeatedPtrField<Message>*>(
159 map_field_base_->MutableRepeatedField());
160 EXPECT_EQ(2, repeated->size());
161 for (int i = 0; i < repeated->size(); i++) {
162 const Message& message = repeated->Get(i);
163 int key = message.GetReflection()->GetInt32(message, key_descriptor_);
164 int value = message.GetReflection()->GetInt32(message, value_descriptor_);
165 EXPECT_EQ(value, initial_value_map_[key]);
166 }
167 }
168
TEST_F(MapFieldBasePrimitiveTest,Arena)169 TEST_F(MapFieldBasePrimitiveTest, Arena) {
170 // Allocate a large initial block to avoid mallocs during hooked test.
171 std::vector<char> arena_block(128 * 1024);
172 ArenaOptions options;
173 options.initial_block = &arena_block[0];
174 options.initial_block_size = arena_block.size();
175 Arena arena(options);
176
177 {
178 // TODO(liujisi): Re-write the test to ensure the memory for the map and
179 // repeated fields are allocated from arenas.
180 // NoHeapChecker no_heap;
181
182 MapFieldType* map_field = Arena::CreateMessage<MapFieldType>(&arena);
183
184 // Set content in map
185 (*map_field->MutableMap())[100] = 101;
186
187 // Trigger conversion to repeated field.
188 map_field->GetRepeatedField();
189 }
190
191 {
192 // TODO(liujisi): Re-write the test to ensure the memory for the map and
193 // repeated fields are allocated from arenas.
194 // NoHeapChecker no_heap;
195
196 MapFieldBaseStub* map_field =
197 Arena::CreateMessage<MapFieldBaseStub>(&arena);
198
199 // Trigger conversion to repeated field.
200 EXPECT_TRUE(map_field->MutableRepeatedField() != NULL);
201 }
202 }
203
204 namespace {
205 enum State { CLEAN, MAP_DIRTY, REPEATED_DIRTY };
206 } // anonymous namespace
207
208 class MapFieldStateTest : public testing::TestWithParam<State> {
209 public:
210 protected:
211 typedef unittest::TestMap_MapInt32Int32Entry_DoNotUse EntryType;
212 typedef MapField<EntryType, int32, int32, WireFormatLite::TYPE_INT32,
213 WireFormatLite::TYPE_INT32>
214 MapFieldType;
MapFieldStateTest()215 MapFieldStateTest() : state_(GetParam()) {
216 // Build map field
217 map_field_.reset(new MapFieldType());
218 map_field_base_ = map_field_.get();
219
220 Expect(map_field_.get(), MAP_DIRTY, 0, 0, true);
221 switch (state_) {
222 case CLEAN:
223 AddOneStillClean(map_field_.get());
224 break;
225 case MAP_DIRTY:
226 MakeMapDirty(map_field_.get());
227 break;
228 case REPEATED_DIRTY:
229 MakeRepeatedDirty(map_field_.get());
230 break;
231 default:
232 break;
233 }
234 }
235
AddOneStillClean(MapFieldType * map_field)236 void AddOneStillClean(MapFieldType* map_field) {
237 MapFieldBase* map_field_base = map_field;
238 Map<int32, int32>* map = map_field->MutableMap();
239 (*map)[0] = 0;
240 map_field_base->GetRepeatedField();
241 Expect(map_field, CLEAN, 1, 1, false);
242 }
243
MakeMapDirty(MapFieldType * map_field)244 void MakeMapDirty(MapFieldType* map_field) {
245 Map<int32, int32>* map = map_field->MutableMap();
246 (*map)[0] = 0;
247 Expect(map_field, MAP_DIRTY, 1, 0, true);
248 }
249
MakeRepeatedDirty(MapFieldType * map_field)250 void MakeRepeatedDirty(MapFieldType* map_field) {
251 MakeMapDirty(map_field);
252 MapFieldBase* map_field_base = map_field;
253 map_field_base->MutableRepeatedField();
254 // We use MutableMap on impl_ because we don't want to disturb the syncing
255 Map<int32, int32>* map = map_field->impl_.MutableMap();
256 map->clear();
257
258 Expect(map_field, REPEATED_DIRTY, 0, 1, false);
259 }
260
Expect(MapFieldType * map_field,State state,int map_size,int repeated_size,bool is_repeated_null)261 void Expect(MapFieldType* map_field, State state, int map_size,
262 int repeated_size, bool is_repeated_null) {
263 MapFieldBase* map_field_base = map_field;
264 MapFieldBaseStub* stub =
265 reinterpret_cast<MapFieldBaseStub*>(map_field_base);
266
267 // We use MutableMap on impl_ because we don't want to disturb the syncing
268 Map<int32, int32>* map = map_field->impl_.MutableMap();
269 RepeatedPtrField<Message>* repeated_field = stub->InternalRepeatedField();
270
271 switch (state) {
272 case MAP_DIRTY:
273 EXPECT_FALSE(stub->IsMapClean());
274 EXPECT_TRUE(stub->IsRepeatedClean());
275 break;
276 case REPEATED_DIRTY:
277 EXPECT_TRUE(stub->IsMapClean());
278 EXPECT_FALSE(stub->IsRepeatedClean());
279 break;
280 case CLEAN:
281 EXPECT_TRUE(stub->IsMapClean());
282 EXPECT_TRUE(stub->IsRepeatedClean());
283 break;
284 default:
285 FAIL();
286 }
287
288 EXPECT_EQ(map_size, map->size());
289 if (is_repeated_null) {
290 EXPECT_TRUE(repeated_field == NULL);
291 } else {
292 if (repeated_field == nullptr) {
293 EXPECT_EQ(repeated_size, 0);
294 } else {
295 EXPECT_EQ(repeated_size, repeated_field->size());
296 }
297 }
298 }
299
300 std::unique_ptr<MapFieldType> map_field_;
301 MapFieldBase* map_field_base_;
302 State state_;
303 };
304
305 INSTANTIATE_TEST_SUITE_P(MapFieldStateTestInstance, MapFieldStateTest,
306 ::testing::Values(CLEAN, MAP_DIRTY, REPEATED_DIRTY));
307
TEST_P(MapFieldStateTest,GetMap)308 TEST_P(MapFieldStateTest, GetMap) {
309 map_field_->GetMap();
310 if (state_ != MAP_DIRTY) {
311 Expect(map_field_.get(), CLEAN, 1, 1, false);
312 } else {
313 Expect(map_field_.get(), MAP_DIRTY, 1, 0, true);
314 }
315 }
316
TEST_P(MapFieldStateTest,MutableMap)317 TEST_P(MapFieldStateTest, MutableMap) {
318 map_field_->MutableMap();
319 if (state_ != MAP_DIRTY) {
320 Expect(map_field_.get(), MAP_DIRTY, 1, 1, false);
321 } else {
322 Expect(map_field_.get(), MAP_DIRTY, 1, 0, true);
323 }
324 }
325
TEST_P(MapFieldStateTest,MergeFromClean)326 TEST_P(MapFieldStateTest, MergeFromClean) {
327 MapFieldType other;
328 AddOneStillClean(&other);
329
330 map_field_->MergeFrom(other);
331
332 if (state_ != MAP_DIRTY) {
333 Expect(map_field_.get(), MAP_DIRTY, 1, 1, false);
334 } else {
335 Expect(map_field_.get(), MAP_DIRTY, 1, 0, true);
336 }
337
338 Expect(&other, CLEAN, 1, 1, false);
339 }
340
TEST_P(MapFieldStateTest,MergeFromMapDirty)341 TEST_P(MapFieldStateTest, MergeFromMapDirty) {
342 MapFieldType other;
343 MakeMapDirty(&other);
344
345 map_field_->MergeFrom(other);
346
347 if (state_ != MAP_DIRTY) {
348 Expect(map_field_.get(), MAP_DIRTY, 1, 1, false);
349 } else {
350 Expect(map_field_.get(), MAP_DIRTY, 1, 0, true);
351 }
352
353 Expect(&other, MAP_DIRTY, 1, 0, true);
354 }
355
TEST_P(MapFieldStateTest,MergeFromRepeatedDirty)356 TEST_P(MapFieldStateTest, MergeFromRepeatedDirty) {
357 MapFieldType other;
358 MakeRepeatedDirty(&other);
359
360 map_field_->MergeFrom(other);
361
362 if (state_ != MAP_DIRTY) {
363 Expect(map_field_.get(), MAP_DIRTY, 1, 1, false);
364 } else {
365 Expect(map_field_.get(), MAP_DIRTY, 1, 0, true);
366 }
367
368 Expect(&other, CLEAN, 1, 1, false);
369 }
370
TEST_P(MapFieldStateTest,SwapClean)371 TEST_P(MapFieldStateTest, SwapClean) {
372 MapFieldType other;
373 AddOneStillClean(&other);
374
375 map_field_->Swap(&other);
376
377 Expect(map_field_.get(), CLEAN, 1, 1, false);
378
379 switch (state_) {
380 case CLEAN:
381 Expect(&other, CLEAN, 1, 1, false);
382 break;
383 case MAP_DIRTY:
384 Expect(&other, MAP_DIRTY, 1, 0, true);
385 break;
386 case REPEATED_DIRTY:
387 Expect(&other, REPEATED_DIRTY, 0, 1, false);
388 break;
389 default:
390 break;
391 }
392 }
393
TEST_P(MapFieldStateTest,SwapMapDirty)394 TEST_P(MapFieldStateTest, SwapMapDirty) {
395 MapFieldType other;
396 MakeMapDirty(&other);
397
398 map_field_->Swap(&other);
399
400 Expect(map_field_.get(), MAP_DIRTY, 1, 0, true);
401
402 switch (state_) {
403 case CLEAN:
404 Expect(&other, CLEAN, 1, 1, false);
405 break;
406 case MAP_DIRTY:
407 Expect(&other, MAP_DIRTY, 1, 0, true);
408 break;
409 case REPEATED_DIRTY:
410 Expect(&other, REPEATED_DIRTY, 0, 1, false);
411 break;
412 default:
413 break;
414 }
415 }
416
TEST_P(MapFieldStateTest,SwapRepeatedDirty)417 TEST_P(MapFieldStateTest, SwapRepeatedDirty) {
418 MapFieldType other;
419 MakeRepeatedDirty(&other);
420
421 map_field_->Swap(&other);
422
423 Expect(map_field_.get(), REPEATED_DIRTY, 0, 1, false);
424
425 switch (state_) {
426 case CLEAN:
427 Expect(&other, CLEAN, 1, 1, false);
428 break;
429 case MAP_DIRTY:
430 Expect(&other, MAP_DIRTY, 1, 0, true);
431 break;
432 case REPEATED_DIRTY:
433 Expect(&other, REPEATED_DIRTY, 0, 1, false);
434 break;
435 default:
436 break;
437 }
438 }
439
TEST_P(MapFieldStateTest,Clear)440 TEST_P(MapFieldStateTest, Clear) {
441 map_field_->Clear();
442
443 Expect(map_field_.get(), MAP_DIRTY, 0, 0, false);
444 }
445
TEST_P(MapFieldStateTest,SpaceUsedExcludingSelf)446 TEST_P(MapFieldStateTest, SpaceUsedExcludingSelf) {
447 map_field_base_->SpaceUsedExcludingSelf();
448
449 switch (state_) {
450 case CLEAN:
451 Expect(map_field_.get(), CLEAN, 1, 1, false);
452 break;
453 case MAP_DIRTY:
454 Expect(map_field_.get(), MAP_DIRTY, 1, 0, true);
455 break;
456 case REPEATED_DIRTY:
457 Expect(map_field_.get(), REPEATED_DIRTY, 0, 1, false);
458 break;
459 default:
460 break;
461 }
462 }
463
TEST_P(MapFieldStateTest,GetMapField)464 TEST_P(MapFieldStateTest, GetMapField) {
465 map_field_base_->GetRepeatedField();
466
467 if (state_ != REPEATED_DIRTY) {
468 Expect(map_field_.get(), CLEAN, 1, 1, false);
469 } else {
470 Expect(map_field_.get(), REPEATED_DIRTY, 0, 1, false);
471 }
472 }
473
TEST_P(MapFieldStateTest,MutableMapField)474 TEST_P(MapFieldStateTest, MutableMapField) {
475 map_field_base_->MutableRepeatedField();
476
477 if (state_ != REPEATED_DIRTY) {
478 Expect(map_field_.get(), REPEATED_DIRTY, 1, 1, false);
479 } else {
480 Expect(map_field_.get(), REPEATED_DIRTY, 0, 1, false);
481 }
482 }
483
484 class MyMapField
485 : public MapField<unittest::TestMap_MapInt32Int32Entry_DoNotUse, int32,
486 int32, internal::WireFormatLite::TYPE_INT32,
487 internal::WireFormatLite::TYPE_INT32> {
488 public:
MyMapField()489 constexpr MyMapField()
490 : MyMapField::MapField(internal::ConstantInitialized{}) {}
491 };
492
TEST(MapFieldTest,ConstInit)493 TEST(MapFieldTest, ConstInit) {
494 // This tests that `MapField` and all its base classes can be constant
495 // initialized.
496 PROTOBUF_CONSTINIT static MyMapField field; // NOLINT
497 EXPECT_EQ(field.size(), 0);
498 }
499
500
501 } // namespace internal
502 } // namespace protobuf
503 } // namespace google
504