PageRenderTime 39ms CodeModel.GetById 10ms RepoModel.GetById 0ms app.codeStats 0ms

/third_party/protobuf/src/google/protobuf/map_field_test.cc

https://github.com/chromium/chromium
C++ | 484 lines | 369 code | 70 blank | 45 comment | 38 complexity | 75baa8023cd9ad5c623ebe2cd049869b MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception, Apache-2.0, BSD-3-Clause
  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. #include <map>
  31. #include <memory>
  32. #include <unordered_map>
  33. #include <google/protobuf/stubs/logging.h>
  34. #include <google/protobuf/stubs/common.h>
  35. #include <google/protobuf/arena_test_util.h>
  36. #include <google/protobuf/map_test_util.h>
  37. #include <google/protobuf/map_unittest.pb.h>
  38. #include <google/protobuf/unittest.pb.h>
  39. #include <google/protobuf/arena.h>
  40. #include <google/protobuf/map.h>
  41. #include <google/protobuf/map_field_inl.h>
  42. #include <google/protobuf/message.h>
  43. #include <google/protobuf/repeated_field.h>
  44. #include <gtest/gtest.h>
  45. namespace google {
  46. namespace protobuf {
  47. namespace internal {
  48. using unittest::TestAllTypes;
  49. class MapFieldBaseStub : public MapFieldBase {
  50. public:
  51. typedef void InternalArenaConstructable_;
  52. typedef void DestructorSkippable_;
  53. MapFieldBaseStub() {}
  54. explicit MapFieldBaseStub(Arena* arena) : MapFieldBase(arena) {}
  55. // Get underlined repeated field without synchronizing map.
  56. RepeatedPtrField<Message>* InternalRepeatedField() { return repeated_field_; }
  57. bool IsMapClean() {
  58. return state_.load(std::memory_order_relaxed) != STATE_MODIFIED_MAP;
  59. }
  60. bool IsRepeatedClean() {
  61. return state_.load(std::memory_order_relaxed) != STATE_MODIFIED_REPEATED;
  62. }
  63. void SetMapDirty() {
  64. state_.store(STATE_MODIFIED_MAP, std::memory_order_relaxed);
  65. }
  66. void SetRepeatedDirty() {
  67. state_.store(STATE_MODIFIED_REPEATED, std::memory_order_relaxed);
  68. }
  69. bool ContainsMapKey(const MapKey& map_key) const override { return false; }
  70. bool InsertOrLookupMapValue(const MapKey& map_key,
  71. MapValueRef* val) override {
  72. return false;
  73. }
  74. bool LookupMapValue(const MapKey& map_key,
  75. MapValueConstRef* val) const override {
  76. return false;
  77. }
  78. bool DeleteMapValue(const MapKey& map_key) override { return false; }
  79. bool EqualIterator(const MapIterator& a,
  80. const MapIterator& b) const override {
  81. return false;
  82. }
  83. int size() const override { return 0; }
  84. void Clear() override {}
  85. void MapBegin(MapIterator* map_iter) const override {}
  86. void MapEnd(MapIterator* map_iter) const override {}
  87. void MergeFrom(const MapFieldBase& other) override {}
  88. void Swap(MapFieldBase* other) override {}
  89. void InitializeIterator(MapIterator* map_iter) const override {}
  90. void DeleteIterator(MapIterator* map_iter) const override {}
  91. void CopyIterator(MapIterator* this_iterator,
  92. const MapIterator& other_iterator) const override {}
  93. void IncreaseIterator(MapIterator* map_iter) const override {}
  94. };
  95. class MapFieldBasePrimitiveTest : public ::testing::Test {
  96. protected:
  97. typedef unittest::TestMap_MapInt32Int32Entry_DoNotUse EntryType;
  98. typedef MapField<EntryType, int32, int32, WireFormatLite::TYPE_INT32,
  99. WireFormatLite::TYPE_INT32>
  100. MapFieldType;
  101. MapFieldBasePrimitiveTest() {
  102. // Get descriptors
  103. map_descriptor_ = unittest::TestMap::descriptor()
  104. ->FindFieldByName("map_int32_int32")
  105. ->message_type();
  106. key_descriptor_ = map_descriptor_->map_key();
  107. value_descriptor_ = map_descriptor_->map_value();
  108. // Build map field
  109. map_field_.reset(new MapFieldType);
  110. map_field_base_ = map_field_.get();
  111. map_ = map_field_->MutableMap();
  112. initial_value_map_[0] = 100;
  113. initial_value_map_[1] = 101;
  114. map_->insert(initial_value_map_.begin(), initial_value_map_.end());
  115. EXPECT_EQ(2, map_->size());
  116. }
  117. std::unique_ptr<MapFieldType> map_field_;
  118. MapFieldBase* map_field_base_;
  119. Map<int32, int32>* map_;
  120. const Descriptor* map_descriptor_;
  121. const FieldDescriptor* key_descriptor_;
  122. const FieldDescriptor* value_descriptor_;
  123. std::map<int32, int32> initial_value_map_; // copy of initial values inserted
  124. };
  125. TEST_F(MapFieldBasePrimitiveTest, SpaceUsedExcludingSelf) {
  126. EXPECT_LT(0, map_field_base_->SpaceUsedExcludingSelf());
  127. }
  128. TEST_F(MapFieldBasePrimitiveTest, GetRepeatedField) {
  129. const RepeatedPtrField<Message>& repeated =
  130. reinterpret_cast<const RepeatedPtrField<Message>&>(
  131. map_field_base_->GetRepeatedField());
  132. EXPECT_EQ(2, repeated.size());
  133. for (int i = 0; i < repeated.size(); i++) {
  134. const Message& message = repeated.Get(i);
  135. int key = message.GetReflection()->GetInt32(message, key_descriptor_);
  136. int value = message.GetReflection()->GetInt32(message, value_descriptor_);
  137. EXPECT_EQ(value, initial_value_map_[key]);
  138. }
  139. }
  140. TEST_F(MapFieldBasePrimitiveTest, MutableRepeatedField) {
  141. RepeatedPtrField<Message>* repeated =
  142. reinterpret_cast<RepeatedPtrField<Message>*>(
  143. map_field_base_->MutableRepeatedField());
  144. EXPECT_EQ(2, repeated->size());
  145. for (int i = 0; i < repeated->size(); i++) {
  146. const Message& message = repeated->Get(i);
  147. int key = message.GetReflection()->GetInt32(message, key_descriptor_);
  148. int value = message.GetReflection()->GetInt32(message, value_descriptor_);
  149. EXPECT_EQ(value, initial_value_map_[key]);
  150. }
  151. }
  152. TEST_F(MapFieldBasePrimitiveTest, Arena) {
  153. // Allocate a large initial block to avoid mallocs during hooked test.
  154. std::vector<char> arena_block(128 * 1024);
  155. ArenaOptions options;
  156. options.initial_block = &arena_block[0];
  157. options.initial_block_size = arena_block.size();
  158. Arena arena(options);
  159. {
  160. // TODO(liujisi): Re-write the test to ensure the memory for the map and
  161. // repeated fields are allocated from arenas.
  162. // NoHeapChecker no_heap;
  163. MapFieldType* map_field = Arena::CreateMessage<MapFieldType>(&arena);
  164. // Set content in map
  165. (*map_field->MutableMap())[100] = 101;
  166. // Trigger conversion to repeated field.
  167. map_field->GetRepeatedField();
  168. }
  169. {
  170. // TODO(liujisi): Re-write the test to ensure the memory for the map and
  171. // repeated fields are allocated from arenas.
  172. // NoHeapChecker no_heap;
  173. MapFieldBaseStub* map_field =
  174. Arena::CreateMessage<MapFieldBaseStub>(&arena);
  175. // Trigger conversion to repeated field.
  176. EXPECT_TRUE(map_field->MutableRepeatedField() != NULL);
  177. }
  178. }
  179. namespace {
  180. enum State { CLEAN, MAP_DIRTY, REPEATED_DIRTY };
  181. } // anonymous namespace
  182. class MapFieldStateTest : public testing::TestWithParam<State> {
  183. public:
  184. protected:
  185. typedef unittest::TestMap_MapInt32Int32Entry_DoNotUse EntryType;
  186. typedef MapField<EntryType, int32, int32, WireFormatLite::TYPE_INT32,
  187. WireFormatLite::TYPE_INT32>
  188. MapFieldType;
  189. MapFieldStateTest() : state_(GetParam()) {
  190. // Build map field
  191. map_field_.reset(new MapFieldType());
  192. map_field_base_ = map_field_.get();
  193. Expect(map_field_.get(), MAP_DIRTY, 0, 0, true);
  194. switch (state_) {
  195. case CLEAN:
  196. AddOneStillClean(map_field_.get());
  197. break;
  198. case MAP_DIRTY:
  199. MakeMapDirty(map_field_.get());
  200. break;
  201. case REPEATED_DIRTY:
  202. MakeRepeatedDirty(map_field_.get());
  203. break;
  204. default:
  205. break;
  206. }
  207. }
  208. void AddOneStillClean(MapFieldType* map_field) {
  209. MapFieldBase* map_field_base = map_field;
  210. Map<int32, int32>* map = map_field->MutableMap();
  211. (*map)[0] = 0;
  212. map_field_base->GetRepeatedField();
  213. Expect(map_field, CLEAN, 1, 1, false);
  214. }
  215. void MakeMapDirty(MapFieldType* map_field) {
  216. Map<int32, int32>* map = map_field->MutableMap();
  217. (*map)[0] = 0;
  218. Expect(map_field, MAP_DIRTY, 1, 0, true);
  219. }
  220. void MakeRepeatedDirty(MapFieldType* map_field) {
  221. MakeMapDirty(map_field);
  222. MapFieldBase* map_field_base = map_field;
  223. map_field_base->MutableRepeatedField();
  224. // We use MutableMap on impl_ because we don't want to disturb the syncing
  225. Map<int32, int32>* map = map_field->impl_.MutableMap();
  226. map->clear();
  227. Expect(map_field, REPEATED_DIRTY, 0, 1, false);
  228. }
  229. void Expect(MapFieldType* map_field, State state, int map_size,
  230. int repeated_size, bool is_repeated_null) {
  231. MapFieldBase* map_field_base = map_field;
  232. MapFieldBaseStub* stub =
  233. reinterpret_cast<MapFieldBaseStub*>(map_field_base);
  234. // We use MutableMap on impl_ because we don't want to disturb the syncing
  235. Map<int32, int32>* map = map_field->impl_.MutableMap();
  236. RepeatedPtrField<Message>* repeated_field = stub->InternalRepeatedField();
  237. switch (state) {
  238. case MAP_DIRTY:
  239. EXPECT_FALSE(stub->IsMapClean());
  240. EXPECT_TRUE(stub->IsRepeatedClean());
  241. break;
  242. case REPEATED_DIRTY:
  243. EXPECT_TRUE(stub->IsMapClean());
  244. EXPECT_FALSE(stub->IsRepeatedClean());
  245. break;
  246. case CLEAN:
  247. EXPECT_TRUE(stub->IsMapClean());
  248. EXPECT_TRUE(stub->IsRepeatedClean());
  249. break;
  250. default:
  251. FAIL();
  252. }
  253. EXPECT_EQ(map_size, map->size());
  254. if (is_repeated_null) {
  255. EXPECT_TRUE(repeated_field == NULL);
  256. } else {
  257. if (repeated_field == nullptr) {
  258. EXPECT_EQ(repeated_size, 0);
  259. } else {
  260. EXPECT_EQ(repeated_size, repeated_field->size());
  261. }
  262. }
  263. }
  264. std::unique_ptr<MapFieldType> map_field_;
  265. MapFieldBase* map_field_base_;
  266. State state_;
  267. };
  268. INSTANTIATE_TEST_SUITE_P(MapFieldStateTestInstance, MapFieldStateTest,
  269. ::testing::Values(CLEAN, MAP_DIRTY, REPEATED_DIRTY));
  270. TEST_P(MapFieldStateTest, GetMap) {
  271. map_field_->GetMap();
  272. if (state_ != MAP_DIRTY) {
  273. Expect(map_field_.get(), CLEAN, 1, 1, false);
  274. } else {
  275. Expect(map_field_.get(), MAP_DIRTY, 1, 0, true);
  276. }
  277. }
  278. TEST_P(MapFieldStateTest, MutableMap) {
  279. map_field_->MutableMap();
  280. if (state_ != MAP_DIRTY) {
  281. Expect(map_field_.get(), MAP_DIRTY, 1, 1, false);
  282. } else {
  283. Expect(map_field_.get(), MAP_DIRTY, 1, 0, true);
  284. }
  285. }
  286. TEST_P(MapFieldStateTest, MergeFromClean) {
  287. MapFieldType other;
  288. AddOneStillClean(&other);
  289. map_field_->MergeFrom(other);
  290. if (state_ != MAP_DIRTY) {
  291. Expect(map_field_.get(), MAP_DIRTY, 1, 1, false);
  292. } else {
  293. Expect(map_field_.get(), MAP_DIRTY, 1, 0, true);
  294. }
  295. Expect(&other, CLEAN, 1, 1, false);
  296. }
  297. TEST_P(MapFieldStateTest, MergeFromMapDirty) {
  298. MapFieldType other;
  299. MakeMapDirty(&other);
  300. map_field_->MergeFrom(other);
  301. if (state_ != MAP_DIRTY) {
  302. Expect(map_field_.get(), MAP_DIRTY, 1, 1, false);
  303. } else {
  304. Expect(map_field_.get(), MAP_DIRTY, 1, 0, true);
  305. }
  306. Expect(&other, MAP_DIRTY, 1, 0, true);
  307. }
  308. TEST_P(MapFieldStateTest, MergeFromRepeatedDirty) {
  309. MapFieldType other;
  310. MakeRepeatedDirty(&other);
  311. map_field_->MergeFrom(other);
  312. if (state_ != MAP_DIRTY) {
  313. Expect(map_field_.get(), MAP_DIRTY, 1, 1, false);
  314. } else {
  315. Expect(map_field_.get(), MAP_DIRTY, 1, 0, true);
  316. }
  317. Expect(&other, CLEAN, 1, 1, false);
  318. }
  319. TEST_P(MapFieldStateTest, SwapClean) {
  320. MapFieldType other;
  321. AddOneStillClean(&other);
  322. map_field_->Swap(&other);
  323. Expect(map_field_.get(), CLEAN, 1, 1, false);
  324. switch (state_) {
  325. case CLEAN:
  326. Expect(&other, CLEAN, 1, 1, false);
  327. break;
  328. case MAP_DIRTY:
  329. Expect(&other, MAP_DIRTY, 1, 0, true);
  330. break;
  331. case REPEATED_DIRTY:
  332. Expect(&other, REPEATED_DIRTY, 0, 1, false);
  333. break;
  334. default:
  335. break;
  336. }
  337. }
  338. TEST_P(MapFieldStateTest, SwapMapDirty) {
  339. MapFieldType other;
  340. MakeMapDirty(&other);
  341. map_field_->Swap(&other);
  342. Expect(map_field_.get(), MAP_DIRTY, 1, 0, true);
  343. switch (state_) {
  344. case CLEAN:
  345. Expect(&other, CLEAN, 1, 1, false);
  346. break;
  347. case MAP_DIRTY:
  348. Expect(&other, MAP_DIRTY, 1, 0, true);
  349. break;
  350. case REPEATED_DIRTY:
  351. Expect(&other, REPEATED_DIRTY, 0, 1, false);
  352. break;
  353. default:
  354. break;
  355. }
  356. }
  357. TEST_P(MapFieldStateTest, SwapRepeatedDirty) {
  358. MapFieldType other;
  359. MakeRepeatedDirty(&other);
  360. map_field_->Swap(&other);
  361. Expect(map_field_.get(), REPEATED_DIRTY, 0, 1, false);
  362. switch (state_) {
  363. case CLEAN:
  364. Expect(&other, CLEAN, 1, 1, false);
  365. break;
  366. case MAP_DIRTY:
  367. Expect(&other, MAP_DIRTY, 1, 0, true);
  368. break;
  369. case REPEATED_DIRTY:
  370. Expect(&other, REPEATED_DIRTY, 0, 1, false);
  371. break;
  372. default:
  373. break;
  374. }
  375. }
  376. TEST_P(MapFieldStateTest, Clear) {
  377. map_field_->Clear();
  378. Expect(map_field_.get(), MAP_DIRTY, 0, 0, false);
  379. }
  380. TEST_P(MapFieldStateTest, SpaceUsedExcludingSelf) {
  381. map_field_base_->SpaceUsedExcludingSelf();
  382. switch (state_) {
  383. case CLEAN:
  384. Expect(map_field_.get(), CLEAN, 1, 1, false);
  385. break;
  386. case MAP_DIRTY:
  387. Expect(map_field_.get(), MAP_DIRTY, 1, 0, true);
  388. break;
  389. case REPEATED_DIRTY:
  390. Expect(map_field_.get(), REPEATED_DIRTY, 0, 1, false);
  391. break;
  392. default:
  393. break;
  394. }
  395. }
  396. TEST_P(MapFieldStateTest, GetMapField) {
  397. map_field_base_->GetRepeatedField();
  398. if (state_ != REPEATED_DIRTY) {
  399. Expect(map_field_.get(), CLEAN, 1, 1, false);
  400. } else {
  401. Expect(map_field_.get(), REPEATED_DIRTY, 0, 1, false);
  402. }
  403. }
  404. TEST_P(MapFieldStateTest, MutableMapField) {
  405. map_field_base_->MutableRepeatedField();
  406. if (state_ != REPEATED_DIRTY) {
  407. Expect(map_field_.get(), REPEATED_DIRTY, 1, 1, false);
  408. } else {
  409. Expect(map_field_.get(), REPEATED_DIRTY, 0, 1, false);
  410. }
  411. }
  412. } // namespace internal
  413. } // namespace protobuf
  414. } // namespace google