You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

btree_test.cc 5.6 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. /**
  2. * Copyright 2019 Huawei Technologies Co., Ltd
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #include <sstream>
  17. #include "dataset/util/btree.h"
  18. #include "dataset/util/auto_index.h"
  19. #include "dataset/util/system_pool.h"
  20. #include "dataset/util/task_manager.h"
  21. #include "common/common.h"
  22. #include "gtest/gtest.h"
  23. #include "dataset/util/de_error.h"
  24. #include "utils/log_adapter.h"
  25. using namespace mindspore::dataset;
  26. using mindspore::MsLogLevel::INFO;
  27. using mindspore::ExceptionType::NoExceptionType;
  28. using mindspore::LogStream;
  29. // For testing purposes, we will make the branching factor very low.
  30. struct mytraits {
  31. using slot_type = uint16_t;
  32. static const slot_type kLeafSlots = 6;
  33. static const slot_type kInnerSlots = 3;
  34. static const bool kAppendMode = false;
  35. };
  36. class MindDataTestBPlusTree : public UT::Common {
  37. public:
  38. MindDataTestBPlusTree() = default;
  39. };
  40. // Test serial insert.
  41. TEST_F(MindDataTestBPlusTree, Test1) {
  42. Allocator<std::string> alloc(std::make_shared<SystemPool>());
  43. BPlusTree<uint64_t, std::string, std::less<uint64_t>, mytraits> btree(alloc);
  44. Status rc;
  45. for (int i = 0; i < 100; i++) {
  46. uint64_t key = 2 * i;
  47. std::ostringstream oss;
  48. oss << "Hello World. I am " << key;
  49. rc = btree.DoInsert(key, oss.str());
  50. EXPECT_TRUE(rc.IsOk());
  51. }
  52. for (int i = 0; i < 100; i++) {
  53. uint64_t key = 2 * i + 1;
  54. std::ostringstream oss;
  55. oss << "Hello World. I am " << key;
  56. rc = btree.DoInsert(key, oss.str());
  57. EXPECT_TRUE(rc.IsOk());
  58. }
  59. EXPECT_EQ(btree.size(), 200);
  60. // Test iterator
  61. {
  62. int cnt = 0;
  63. auto it = btree.begin();
  64. uint64_t prev = it.key();
  65. ++it;
  66. ++cnt;
  67. while (it != btree.end()) {
  68. uint64_t cur = it.key();
  69. std::string val = "Hello World. I am " + std::to_string(cur);
  70. EXPECT_TRUE(prev < cur);
  71. EXPECT_EQ(it.value(), val);
  72. prev = cur;
  73. ++it;
  74. ++cnt;
  75. }
  76. EXPECT_EQ(cnt, 200);
  77. // Now go backward
  78. for (int i = 0; i < 10; i++) {
  79. --it;
  80. EXPECT_EQ(199 - i, it.key());
  81. }
  82. }
  83. // Test nearch
  84. {
  85. MS_LOG(INFO) << "Locate key " << 100 << " Expect found.";
  86. auto it = btree.Search(100);
  87. EXPECT_FALSE(it == btree.cend());
  88. EXPECT_EQ(it.key(), 100);
  89. EXPECT_EQ(it.value(), "Hello World. I am 100");
  90. MS_LOG(INFO) << "Locate key " << 300 << " Expect not found.";
  91. it = btree.Search(300);
  92. EXPECT_TRUE(it == btree.cend());
  93. }
  94. // Test duplicate key
  95. {
  96. rc = btree.DoInsert(100, "Expect error");
  97. EXPECT_EQ(rc, Status(StatusCode::kDuplicateKey));
  98. }
  99. }
  100. // Test concurrent insert.
  101. TEST_F(MindDataTestBPlusTree, Test2) {
  102. Allocator<std::string> alloc(std::make_shared<SystemPool>());
  103. BPlusTree<uint64_t, std::string, std::less<uint64_t>, mytraits> btree(alloc);
  104. TaskGroup vg;
  105. auto f = [&](int k) -> Status {
  106. TaskManager::FindMe()->Post();
  107. for (int i = 0; i < 100; i++) {
  108. uint64_t key = k * 100 + i;
  109. std::ostringstream oss;
  110. oss << "Hello World. I am " << key;
  111. Status rc = btree.DoInsert(key, oss.str());
  112. EXPECT_TRUE(rc.IsOk());
  113. }
  114. return Status::OK();
  115. };
  116. // Spawn two threads. One insert the odd numbers and the other insert the even numbers just like Test1
  117. for (int k = 0; k < 100; k++) {
  118. vg.CreateAsyncTask("Concurrent Insert", std::bind(f, k));
  119. }
  120. vg.join_all();
  121. EXPECT_EQ(btree.size(), 10000);
  122. // Test iterator
  123. {
  124. int cnt = 0;
  125. auto it = btree.begin();
  126. uint64_t prev = it.key();
  127. ++it;
  128. ++cnt;
  129. while (it != btree.end()) {
  130. uint64_t cur = it.key();
  131. std::string val = "Hello World. I am " + std::to_string(cur);
  132. EXPECT_TRUE(prev < cur);
  133. EXPECT_EQ(it.value(), val);
  134. prev = cur;
  135. ++it;
  136. ++cnt;
  137. }
  138. EXPECT_EQ(cnt, 10000);
  139. }
  140. // Test search
  141. {
  142. MS_LOG(INFO) << "Locating key from 0 to 9999. Expect found.";
  143. for (int i = 0; i < 10000; i++) {
  144. auto it = btree.Search(i);
  145. bool eoS = (it == btree.cend());
  146. EXPECT_FALSE(eoS);
  147. if (!eoS) {
  148. EXPECT_EQ(it.key(), i);
  149. std::string val = "Hello World. I am " + std::to_string(i);
  150. EXPECT_EQ(it.value(), val);
  151. }
  152. }
  153. MS_LOG(INFO) << "Locate key " << 10000 << ". Expect not found";
  154. auto it = btree.Search(10000);
  155. EXPECT_TRUE(it == btree.cend());
  156. }
  157. // Test to retrieve key at certain position.
  158. {
  159. for (int i = 0; i < 10000; i++) {
  160. int k = btree.KeyAtPos(i);
  161. EXPECT_EQ(k, i);
  162. }
  163. }
  164. }
  165. TEST_F(MindDataTestBPlusTree, Test3) {
  166. Allocator<std::string> alloc(std::make_shared<SystemPool>());
  167. AutoIndexObj<std::string> ai(alloc);
  168. Status rc;
  169. rc = ai.insert("Hello World");
  170. EXPECT_TRUE(rc.IsOk());
  171. ai.insert({"a", "b", "c"});
  172. EXPECT_TRUE(rc.IsOk());
  173. uint64_t min = ai.min_key();
  174. uint64_t max = ai.max_key();
  175. EXPECT_EQ(min, 1);
  176. EXPECT_EQ(max, 4);
  177. auto it = ai.Search(3);
  178. EXPECT_EQ(it.value(), "b");
  179. MS_LOG(INFO) << "Dump all the values using [] operator.";
  180. for (uint64_t i = min; i <= max; i++) {
  181. MS_LOG(DEBUG) << ai[i] << std::endl;
  182. }
  183. }