#include "gtest/gtest.h" #include "db/NewDB.h" // NewDB 的头文件 #include "leveldb/env.h" #include "leveldb/db.h" #include #include #include 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 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> 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 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> 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 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 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 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> 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 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> 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 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 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(time(nullptr))); testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); }