成员:陈予曈,朱陈媛
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

247 lines
8.7 KiB

  1. #include "gtest/gtest.h"
  2. #include "db/NewDB.h" // NewDB 的头文件
  3. #include "leveldb/env.h"
  4. #include "leveldb/db.h"
  5. #include <iostream>
  6. #include <random>
  7. #include <ctime>
  8. using namespace leveldb;
  9. Status OpenDB(std::string dbName, NewDB** db) {
  10. Options options = Options();
  11. options.create_if_missing = true;
  12. return NewDB::Open(options, dbName, db);
  13. }
  14. // 全局的随机数引擎
  15. std::default_random_engine rng;
  16. // 设置随机种子
  17. void SetGlobalSeed(unsigned seed) {
  18. rng.seed(seed);
  19. }
  20. // 生成随机字符串
  21. std::string GenerateRandomString(size_t length) {
  22. static const char alphanum[] =
  23. "0123456789"
  24. "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
  25. "abcdefghijklmnopqrstuvwxyz";
  26. std::uniform_int_distribution<int> dist(0, sizeof(alphanum) - 2);
  27. std::string str(length, 0);
  28. for (size_t i = 0; i < length; ++i) {
  29. str[i] = alphanum[dist(rng)];
  30. }
  31. return str;
  32. }
  33. std::string testdbname = "testdb2";
  34. TEST(TestNewDB, BulkCreateIndexAndQueryTest) {
  35. // 创建 NewDB 实例
  36. NewDB* db;
  37. ASSERT_TRUE(OpenDB(testdbname, &db).ok());
  38. // 批量插入数据
  39. std::vector<std::pair<std::string, FieldArray>> bulk_data;
  40. const int num_records = 100;
  41. for (int i = 0; i < num_records; ++i) {
  42. std::string key = "k_" + GenerateRandomString(5);
  43. FieldArray fields = {
  44. {"name", GenerateRandomString(5)},
  45. {"address", GenerateRandomString(15)},
  46. {"phone", GenerateRandomString(11)}
  47. };
  48. bulk_data.emplace_back(key, fields);
  49. ASSERT_TRUE(db->Put_fields(WriteOptions(), key, fields).ok());
  50. }
  51. // 创建索引字段
  52. db->CreateIndexOnField("address");
  53. // 验证插入的数据和索引
  54. for (const auto& [key, fields] : bulk_data) {
  55. // 获取并验证字段数据
  56. FieldArray retrieved_fields;
  57. ASSERT_TRUE(db->Get_fields(ReadOptions(), Slice(key), &retrieved_fields).ok());
  58. EXPECT_EQ(retrieved_fields.size(), fields.size());
  59. // 验证插入的每个字段
  60. for (size_t i = 0; i < fields.size(); ++i) {
  61. EXPECT_EQ(fields[i].first, retrieved_fields[i].first); // 字段名
  62. EXPECT_EQ(fields[i].second, retrieved_fields[i].second); // 字段值
  63. }
  64. // 验证索引是否能正确找到对应的键
  65. Field field_to_query{"address", fields[1].second}; // 使用 address 字段进行查询
  66. std::vector<std::string> matching_keys = db->QueryByIndex(field_to_query);
  67. EXPECT_FALSE(matching_keys.empty()); // 应该能找到对应的键
  68. EXPECT_NE(std::find(matching_keys.begin(), matching_keys.end(), key), matching_keys.end());
  69. }
  70. delete db;
  71. }
  72. // 测试创建二级索引后批量插入、以及删除索引后的查询
  73. TEST(TestNewDB, BulkPutFieldsAndDeleteIndexTest) {
  74. // 创建 NewDB 实例
  75. NewDB* db;
  76. ASSERT_TRUE(OpenDB(testdbname, &db).ok());
  77. db->CreateIndexOnField("address");
  78. // 批量插入数据
  79. std::vector<std::pair<std::string, FieldArray>> bulk_data;
  80. const int num_records = 100;
  81. for (int i = 0; i < num_records; ++i) {
  82. std::string key = "k_" + GenerateRandomString(5);
  83. FieldArray fields = {
  84. {"name", GenerateRandomString(5)},
  85. {"address", GenerateRandomString(15)},
  86. {"phone", GenerateRandomString(11)}
  87. };
  88. bulk_data.emplace_back(key, fields);
  89. ASSERT_TRUE(db->Put_fields(WriteOptions(), key, fields).ok());
  90. }
  91. // 验证插入的数据和索引
  92. for (const auto& [key, fields] : bulk_data) {
  93. // 获取并验证字段数据
  94. FieldArray retrieved_fields;
  95. ASSERT_TRUE(db->Get_fields(ReadOptions(), Slice(key), &retrieved_fields).ok());
  96. EXPECT_EQ(retrieved_fields.size(), fields.size());
  97. // 验证插入的每个字段
  98. for (size_t i = 0; i < fields.size(); ++i) {
  99. EXPECT_EQ(fields[i].first, retrieved_fields[i].first); // 字段名
  100. EXPECT_EQ(fields[i].second, retrieved_fields[i].second); // 字段值
  101. }
  102. // 验证索引是否能正确找到对应的键
  103. Field field_to_query{"address", fields[1].second}; // 使用 address 字段进行查询
  104. std::vector<std::string> matching_keys = db->QueryByIndex(field_to_query);
  105. EXPECT_FALSE(matching_keys.empty()); // 应该能找到对应的键
  106. EXPECT_NE(std::find(matching_keys.begin(), matching_keys.end(), key), matching_keys.end());
  107. }
  108. // 删除部分数据
  109. const int num_updates = 20;
  110. for (int i = 0; i < num_updates; ++i) {
  111. auto& [key, fields] = bulk_data[i];
  112. ASSERT_TRUE(db->Delete(WriteOptions(), key));
  113. }
  114. for (int i = 0; i < num_updates; ++i) {
  115. Field query_field{"address", bulk_data[i].second[1].second};
  116. std::vector<std::string> matching_keys = db->QueryByIndex(query_field);
  117. EXPECT_TRUE(matching_keys.empty());
  118. }
  119. // 删除索引
  120. ASSERT_TRUE(db->DeleteIndex("address"));
  121. // 验证删除索引后无法再通过索引查询到数据
  122. for (const auto& [key, fields] : bulk_data) {
  123. Field field_to_query{"address", fields[1].second}; // 使用 address 字段进行查询
  124. std::vector<std::string> matching_keys = db->QueryByIndex(field_to_query);
  125. EXPECT_TRUE(matching_keys.empty()); // 索引已被删除,应该找不到任何匹配的键
  126. }
  127. delete db;
  128. }
  129. TEST(TestNewDB, UpdateFieldsAndQueryIndexTest) {
  130. // 创建 NewDB 实例
  131. NewDB* db;
  132. ASSERT_TRUE(OpenDB(testdbname, &db).ok());
  133. // 创建索引字段
  134. ASSERT_TRUE(db->CreateIndexOnField("address"));
  135. // 批量插入数据
  136. const int num_records = 100;
  137. std::vector<std::pair<std::string, FieldArray>> initial_bulk_data;
  138. for (int i = 0; i < num_records; ++i) {
  139. std::string key = "k_" + GenerateRandomString(5);
  140. FieldArray fields = {
  141. {"name", GenerateRandomString(5)},
  142. {"address", GenerateRandomString(15)},
  143. {"phone", GenerateRandomString(11)}
  144. };
  145. initial_bulk_data.emplace_back(key, fields);
  146. ASSERT_TRUE(db->Put_fields(WriteOptions(), key, fields).ok());
  147. }
  148. // 验证初始数据的索引查询
  149. for (const auto& [key, fields] : initial_bulk_data) {
  150. Field query_field{"address", fields[1].second}; // 使用 address 字段进行查询
  151. std::vector<std::string> matching_keys = db->QueryByIndex(query_field);
  152. ASSERT_FALSE(matching_keys.empty()); // 应该能找到对应的键
  153. EXPECT_NE(std::find(matching_keys.begin(), matching_keys.end(), key), matching_keys.end());
  154. }
  155. // 更新部分数据
  156. const int num_updates = 20;
  157. std::vector<std::pair<std::string, FieldArray>> updated_bulk_data;
  158. for (int i = 0; i < num_updates; ++i) {
  159. auto& [key, fields] = initial_bulk_data[i];
  160. FieldArray updated_fields = {
  161. {"name", fields[0].second},
  162. {"address", GenerateRandomString(15)}, // 更新 address
  163. {"phone", fields[2].second}
  164. };
  165. updated_bulk_data.emplace_back(key, updated_fields);
  166. ASSERT_TRUE(db->Put_fields(WriteOptions(), key, updated_fields).ok());
  167. }
  168. // 验证更新后的数据和索引
  169. for (const auto& [key, updated_fields] : updated_bulk_data) {
  170. // 获取并验证字段数据
  171. FieldArray retrieved_fields;
  172. ASSERT_TRUE(db->Get_fields(ReadOptions(), Slice(key), &retrieved_fields).ok());
  173. EXPECT_EQ(retrieved_fields.size(), updated_fields.size());
  174. // 验证插入的每个字段
  175. for (size_t i = 0; i < updated_fields.size(); ++i) {
  176. EXPECT_EQ(updated_fields[i].first, retrieved_fields[i].first); // 字段名
  177. EXPECT_EQ(updated_fields[i].second, retrieved_fields[i].second); // 字段值
  178. }
  179. // 验证新的 address 字段值存在于索引中
  180. Field query_field_new{"address", updated_fields[1].second};
  181. std::vector<std::string> matching_keys_new = db->QueryByIndex(query_field_new);
  182. ASSERT_FALSE(matching_keys_new.empty()); // 新地址应该能找到对应的键
  183. EXPECT_NE(std::find(matching_keys_new.begin(), matching_keys_new.end(), key), matching_keys_new.end());
  184. }
  185. for (int i = 0; i < num_updates; ++i) {
  186. // 验证旧的 address 字段值不再存在于索引中
  187. Field query_field_old{"address", initial_bulk_data[i].second[1].second};
  188. std::vector<std::string> matching_keys_old = db->QueryByIndex(query_field_old);
  189. EXPECT_TRUE(matching_keys_old.empty()); // 旧地址不应该再找到对应的键
  190. }
  191. delete db;
  192. }
  193. int main(int argc, char** argv) {
  194. // 设置全局随机种子
  195. SetGlobalSeed(static_cast<unsigned>(time(nullptr)));
  196. testing::InitGoogleTest(&argc, argv);
  197. return RUN_ALL_TESTS();
  198. }