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