小组成员:陈予曈、朱陈媛
 
 

436 wiersze
18 KiB

#include "gtest/gtest.h"
#include "db/NewDB.h" // NewDB 的头文件
#include "leveldb/env.h"
#include "leveldb/db.h"
#include <iostream>
#include <random>
#include <ctime>
#include <chrono> // 用于计时
#include <vector> // 用于存储延迟
using namespace std;
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, PersistentIndexTest) {
// // 创建 NewDB 实例
// NewDB* db;
// ASSERT_TRUE(OpenDB(testdbname, &db).ok());
// // 批量插入数据
// std::vector<std::pair<std::string, FieldArray>> bulk_data;
// const int num_records = 1000; // 适当减少记录数,以便测试
// for (int i = 0; i < num_records; ++i) {
// std::string key = "k_" + GenerateRandomString(10);
// FieldArray fields = {
// {"name", GenerateRandomString(10)},
// {"address", GenerateRandomString(25)},
// {"phone", GenerateRandomString(11)}
// };
// bulk_data.emplace_back(key, fields);
// ASSERT_TRUE(db->Put_fields(WriteOptions(), key, fields).ok());
// }
// // 创建索引字段
// db->CreateIndexOnField("address");
// // 关闭数据库
// delete db;
// // 重新打开数据库
// ASSERT_TRUE(OpenDB(testdbname, &db).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());
// // 验证索引是否能正确找到对应的键
// 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, BulkCreateIndexAndQueryTest) {
// // 创建 NewDB 实例
// NewDB* db;
// ASSERT_TRUE(OpenDB(testdbname, &db).ok());
// // 批量插入数据
// std::vector<std::pair<std::string, FieldArray>> bulk_data;
// const int num_records = 10000;
// for (int i = 0; i < num_records; ++i) {
// std::string key = "k_" + GenerateRandomString(10);
// FieldArray fields = {
// {"name", GenerateRandomString(10)},
// {"address", GenerateRandomString(25)},
// {"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); // 字段值
// if (fields[i].second != retrieved_fields[i].second) {
// std::cerr << "Mismatch at index: " << i
// << ", Key: " << key
// << ", Field Name: " << fields[i].first
// << ", Expected: " << fields[i].second
// << ", Retrieved: " << retrieved_fields[i].second
// << std::endl;
// }
// }
// // 验证索引是否能正确找到对应的键
// 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, QueryByIndexPerformance) {
// 创建 NewDB 实例
NewDB* db;
ASSERT_TRUE(OpenDB(testdbname, &db).ok());
// 批量插入数据
std::vector<std::pair<std::string, FieldArray>> bulk_data;
const int num_records = 10000;
for (int i = 0; i < num_records; ++i) {
std::string key = "k_" + GenerateRandomString(10);
FieldArray fields = {
{"name", GenerateRandomString(10)},
{"address", GenerateRandomString(25)},
{"phone", GenerateRandomString(11)}
};
bulk_data.emplace_back(key, fields);
ASSERT_TRUE(db->Put_fields(WriteOptions(), key, fields).ok());
}
// 创建索引字段
db->CreateIndexOnField("address");
// 测试查询延迟
auto start_time = std::chrono::high_resolution_clock::now(); // 记录开始时间
// 验证插入的数据和索引
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); // 字段值
// if (fields[i].second != retrieved_fields[i].second) {
// std::cerr << "Mismatch at index: " << i
// << ", Key: " << key
// << ", Field Name: " << fields[i].first
// << ", Expected: " << fields[i].second
// << ", Retrieved: " << retrieved_fields[i].second
// << std::endl;
// }
// }
// 验证索引是否能正确找到对应的键
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());
}
auto end_time = std::chrono::high_resolution_clock::now(); // 记录结束时间
auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end_time - start_time).count();
cout << "Throughput: " << num_records * 1000 / duration << " OPS" << endl;
cout << "Total Latency " << duration << " ms" << endl;
delete db;
}
// TEST(TestNewDB, FindKeysByFieldPerformance) {
// // 创建 NewDB 实例
// NewDB* db;
// ASSERT_TRUE(OpenDB(testdbname, &db).ok());
// // 批量插入数据
// std::vector<std::pair<std::string, FieldArray>> bulk_data;
// const int num_records = 100000;
// for (int i = 0; i < num_records; ++i) {
// std::string key = "k_" + GenerateRandomString(10);
// FieldArray fields = {
// {"name", GenerateRandomString(10)},
// {"address", GenerateRandomString(25)},
// {"phone", GenerateRandomString(11)}
// };
// bulk_data.emplace_back(key, fields);
// ASSERT_TRUE(db->Put_fields(WriteOptions(), key, fields).ok());
// }
// // 创建索引字段
// db->CreateIndexOnField("address");
// // 测试查询延迟
// auto start_time = std::chrono::high_resolution_clock::now(); // 记录开始时间
// // 验证插入的数据和索引
// 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); // 字段值
// // if (fields[i].second != retrieved_fields[i].second) {
// // std::cerr << "Mismatch at index: " << i
// // << ", Key: " << key
// // << ", Field Name: " << fields[i].first
// // << ", Expected: " << fields[i].second
// // << ", Retrieved: " << retrieved_fields[i].second
// // << std::endl;
// // }
// // }
// // 验证索引是否能正确找到对应的键
// Field field_to_query{"address", fields[1].second}; // 使用 address 字段进行查询
// std::vector<std::string> matching_keys = db->FindKeysByField(field_to_query);
// EXPECT_FALSE(matching_keys.empty()); // 应该能找到对应的键
// EXPECT_NE(std::find(matching_keys.begin(), matching_keys.end(), key), matching_keys.end());
// }
// auto end_time = std::chrono::high_resolution_clock::now(); // 记录结束时间
// auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end_time - start_time).count();
// cout << "Throughput: " << num_records * 1000 / duration << " OPS" << endl;
// cout << "Total Latency " << duration << " ms" << endl;
// delete db;
// }
//测试创建二级索引后批量插入、以及删除索引后的查询
// TEST(TestNewDB, BulkPutFieldsAndDeleteIndexPerformance) {
// // 创建 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 = 150000;
// for (int i = 0; i < num_records; ++i) {
// std::string key = "k_" + GenerateRandomString(10);
// FieldArray fields = {
// {"name", GenerateRandomString(10)},
// {"address", GenerateRandomString(25)},
// {"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());
// }
// // 测试插入吞吐量
// auto start_time = std::chrono::high_resolution_clock::now(); // 记录开始时间
// // 删除部分数据
// const int num_updates = 100000;
// 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"));
// auto end_time = std::chrono::high_resolution_clock::now(); // 记录结束时间
// auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end_time - start_time).count();
// // 计算吞吐量并输出
// cout << "Throughput: " << num_updates * 1000 / duration << " OPS" << endl;
// cout << "Total Latency " << duration << " ms" << endl;
// // // 验证删除索引后无法再通过索引查询到数据
// // 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, UpdateFieldsAndQueryIndexPerformance) {
// // 创建 NewDB 实例
// NewDB* db;
// ASSERT_TRUE(OpenDB(testdbname, &db).ok());
// // 创建索引字段
// ASSERT_TRUE(db->CreateIndexOnField("address"));
// // 批量插入数据
// const int num_records = 200000;
// std::vector<std::pair<std::string, FieldArray>> initial_bulk_data;
// for (int i = 0; i < num_records; ++i) {
// std::string key = "k_" + GenerateRandomString(10);
// FieldArray fields = {
// {"name", GenerateRandomString(10)},
// {"address", GenerateRandomString(25)},
// {"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 = 100000;
// std::vector<std::pair<std::string, FieldArray>> updated_bulk_data;
// // 测试插入吞吐量
// auto start_time = std::chrono::high_resolution_clock::now(); // 记录开始时间
// 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());
// }
// auto end_time = std::chrono::high_resolution_clock::now(); // 记录结束时间
// auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end_time - start_time).count();
// // 计算吞吐量并输出
// cout << "Throughput: " << num_updates * 1000 / duration << " OPS" << endl;
// cout << "Total Latency " << duration << " ms" << endl;
// // 验证更新后的数据和索引
// 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();
}