|
|
- #include "gtest/gtest.h"
- #include "db/NewDB.h" // NewDB 的头文件
- #include "leveldb/env.h"
- #include "leveldb/db.h"
- #include <iostream>
- #include <random>
- #include <ctime>
-
- using namespace leveldb;
-
- Status OpenDB(std::string dbName, NewDB** db) {
- Options options = Options();
- options.create_if_missing = true;
- return NewDB::Open(options, dbName, db);
- }
-
- // 全局的随机数引擎
- std::default_random_engine rng;
-
- // 设置随机种子
- void SetGlobalSeed(unsigned seed) {
- rng.seed(seed);
- }
-
- // 生成随机字符串
- std::string GenerateRandomString(size_t length) {
- static const char alphanum[] =
- "0123456789"
- "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
- "abcdefghijklmnopqrstuvwxyz";
-
- std::uniform_int_distribution<int> dist(0, sizeof(alphanum) - 2);
-
- std::string str(length, 0);
- for (size_t i = 0; i < length; ++i) {
- str[i] = alphanum[dist(rng)];
- }
- return str;
- }
-
- std::string testdbname = "testdb2";
-
- TEST(TestNewDB, BulkCreateIndexAndQueryTest) {
- // 创建 NewDB 实例
- NewDB* db;
- ASSERT_TRUE(OpenDB(testdbname, &db).ok());
-
- // 批量插入数据
- std::vector<std::pair<std::string, FieldArray>> bulk_data;
- const int num_records = 100;
-
- for (int i = 0; i < num_records; ++i) {
- std::string key = "k_" + GenerateRandomString(5);
- FieldArray fields = {
- {"name", GenerateRandomString(5)},
- {"address", GenerateRandomString(15)},
- {"phone", GenerateRandomString(11)}
- };
- bulk_data.emplace_back(key, fields);
-
- ASSERT_TRUE(db->Put_fields(WriteOptions(), key, fields).ok());
- }
-
- // 创建索引字段
- db->CreateIndexOnField("address");
-
- // 验证插入的数据和索引
- for (const auto& [key, fields] : bulk_data) {
- // 获取并验证字段数据
- FieldArray retrieved_fields;
- ASSERT_TRUE(db->Get_fields(ReadOptions(), Slice(key), &retrieved_fields).ok());
- EXPECT_EQ(retrieved_fields.size(), fields.size());
-
- // 验证插入的每个字段
- for (size_t i = 0; i < fields.size(); ++i) {
- EXPECT_EQ(fields[i].first, retrieved_fields[i].first); // 字段名
- EXPECT_EQ(fields[i].second, retrieved_fields[i].second); // 字段值
- }
-
- // 验证索引是否能正确找到对应的键
- Field field_to_query{"address", fields[1].second}; // 使用 address 字段进行查询
- std::vector<std::string> matching_keys = db->QueryByIndex(field_to_query);
- EXPECT_FALSE(matching_keys.empty()); // 应该能找到对应的键
- EXPECT_NE(std::find(matching_keys.begin(), matching_keys.end(), key), matching_keys.end());
- }
-
- delete db;
- }
-
-
-
- // 测试创建二级索引后批量插入、以及删除索引后的查询
- TEST(TestNewDB, BulkPutFieldsAndDeleteIndexTest) {
- // 创建 NewDB 实例
- NewDB* db;
- ASSERT_TRUE(OpenDB(testdbname, &db).ok());
-
- db->CreateIndexOnField("address");
-
- // 批量插入数据
- std::vector<std::pair<std::string, FieldArray>> bulk_data;
- const int num_records = 100;
-
- for (int i = 0; i < num_records; ++i) {
- std::string key = "k_" + GenerateRandomString(5);
- FieldArray fields = {
- {"name", GenerateRandomString(5)},
- {"address", GenerateRandomString(15)},
- {"phone", GenerateRandomString(11)}
- };
- bulk_data.emplace_back(key, fields);
-
- ASSERT_TRUE(db->Put_fields(WriteOptions(), key, fields).ok());
- }
-
- // 验证插入的数据和索引
- for (const auto& [key, fields] : bulk_data) {
- // 获取并验证字段数据
- FieldArray retrieved_fields;
- ASSERT_TRUE(db->Get_fields(ReadOptions(), Slice(key), &retrieved_fields).ok());
- EXPECT_EQ(retrieved_fields.size(), fields.size());
-
- // 验证插入的每个字段
- for (size_t i = 0; i < fields.size(); ++i) {
- EXPECT_EQ(fields[i].first, retrieved_fields[i].first); // 字段名
- EXPECT_EQ(fields[i].second, retrieved_fields[i].second); // 字段值
- }
-
- // 验证索引是否能正确找到对应的键
- Field field_to_query{"address", fields[1].second}; // 使用 address 字段进行查询
- std::vector<std::string> matching_keys = db->QueryByIndex(field_to_query);
- EXPECT_FALSE(matching_keys.empty()); // 应该能找到对应的键
- EXPECT_NE(std::find(matching_keys.begin(), matching_keys.end(), key), matching_keys.end());
- }
-
- // 删除部分数据
- const int num_updates = 20;
-
- for (int i = 0; i < num_updates; ++i) {
- auto& [key, fields] = bulk_data[i];
- ASSERT_TRUE(db->Delete(WriteOptions(), key));
- }
-
- for (int i = 0; i < num_updates; ++i) {
- Field query_field{"address", bulk_data[i].second[1].second};
- std::vector<std::string> matching_keys = db->QueryByIndex(query_field);
- EXPECT_TRUE(matching_keys.empty());
- }
-
- // 删除索引
- ASSERT_TRUE(db->DeleteIndex("address"));
-
- // 验证删除索引后无法再通过索引查询到数据
- for (const auto& [key, fields] : bulk_data) {
- Field field_to_query{"address", fields[1].second}; // 使用 address 字段进行查询
- std::vector<std::string> matching_keys = db->QueryByIndex(field_to_query);
- EXPECT_TRUE(matching_keys.empty()); // 索引已被删除,应该找不到任何匹配的键
- }
-
- delete db;
- }
-
-
- TEST(TestNewDB, UpdateFieldsAndQueryIndexTest) {
- // 创建 NewDB 实例
- NewDB* db;
- ASSERT_TRUE(OpenDB(testdbname, &db).ok());
-
- // 创建索引字段
- ASSERT_TRUE(db->CreateIndexOnField("address"));
-
- // 批量插入数据
- const int num_records = 100;
- std::vector<std::pair<std::string, FieldArray>> initial_bulk_data;
-
- for (int i = 0; i < num_records; ++i) {
- std::string key = "k_" + GenerateRandomString(5);
- FieldArray fields = {
- {"name", GenerateRandomString(5)},
- {"address", GenerateRandomString(15)},
- {"phone", GenerateRandomString(11)}
- };
- initial_bulk_data.emplace_back(key, fields);
-
- ASSERT_TRUE(db->Put_fields(WriteOptions(), key, fields).ok());
- }
-
- // 验证初始数据的索引查询
- for (const auto& [key, fields] : initial_bulk_data) {
- Field query_field{"address", fields[1].second}; // 使用 address 字段进行查询
- std::vector<std::string> matching_keys = db->QueryByIndex(query_field);
- ASSERT_FALSE(matching_keys.empty()); // 应该能找到对应的键
- EXPECT_NE(std::find(matching_keys.begin(), matching_keys.end(), key), matching_keys.end());
- }
-
- // 更新部分数据
- const int num_updates = 20;
- std::vector<std::pair<std::string, FieldArray>> updated_bulk_data;
-
- for (int i = 0; i < num_updates; ++i) {
- auto& [key, fields] = initial_bulk_data[i];
- FieldArray updated_fields = {
- {"name", fields[0].second},
- {"address", GenerateRandomString(15)}, // 更新 address
- {"phone", fields[2].second}
- };
- updated_bulk_data.emplace_back(key, updated_fields);
-
- ASSERT_TRUE(db->Put_fields(WriteOptions(), key, updated_fields).ok());
- }
-
- // 验证更新后的数据和索引
- for (const auto& [key, updated_fields] : updated_bulk_data) {
- // 获取并验证字段数据
- FieldArray retrieved_fields;
- ASSERT_TRUE(db->Get_fields(ReadOptions(), Slice(key), &retrieved_fields).ok());
- EXPECT_EQ(retrieved_fields.size(), updated_fields.size());
-
- // 验证插入的每个字段
- for (size_t i = 0; i < updated_fields.size(); ++i) {
- EXPECT_EQ(updated_fields[i].first, retrieved_fields[i].first); // 字段名
- EXPECT_EQ(updated_fields[i].second, retrieved_fields[i].second); // 字段值
- }
-
- // 验证新的 address 字段值存在于索引中
- Field query_field_new{"address", updated_fields[1].second};
- std::vector<std::string> matching_keys_new = db->QueryByIndex(query_field_new);
- ASSERT_FALSE(matching_keys_new.empty()); // 新地址应该能找到对应的键
- EXPECT_NE(std::find(matching_keys_new.begin(), matching_keys_new.end(), key), matching_keys_new.end());
- }
- for (int i = 0; i < num_updates; ++i) {
- // 验证旧的 address 字段值不再存在于索引中
- Field query_field_old{"address", initial_bulk_data[i].second[1].second};
- std::vector<std::string> matching_keys_old = db->QueryByIndex(query_field_old);
- EXPECT_TRUE(matching_keys_old.empty()); // 旧地址不应该再找到对应的键
- }
-
- delete db;
- }
-
-
- int main(int argc, char** argv) {
- // 设置全局随机种子
- SetGlobalSeed(static_cast<unsigned>(time(nullptr)));
- testing::InitGoogleTest(&argc, argv);
- return RUN_ALL_TESTS();
- }
|