Skip to content

Commit 9553f1c

Browse files
authored
feat: Add overloaded version for Insert() & Delete() in common_checker.h (#578)
* feat: Add overloaded version for Insert() & Delete() in common_checker.h * feat: Add ExecuteSqlTxn result check logic && improve printed messages * fix: Ensure format consistency
1 parent 3531cf1 commit 9553f1c

File tree

1 file changed

+95
-0
lines changed

1 file changed

+95
-0
lines changed

test/concurrency/common_checker.h

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,71 @@ auto Insert(Transaction *txn, BustubInstance &instance, int v1) -> void {
3030
ASSERT_EQ(ss.str(), "3,\n");
3131
}
3232

33+
/// @brief Use this to write your own test cases, if needed
34+
/// @param v1_vec Elements to be insert into `t1:v1`, the size of which can either be 1, or same as @v2_vec
35+
/// @param v2_vec Elements to be insert into `t1:v2`, must not be empty
36+
/// @param flag When set to `true`, the size of @v1_vec should be exactly one, the default value is `false`
37+
/// Usage: Insert(txn, instance, {1, 2, 3}, {4, 5, 6}, flag = false);
38+
/// This overloaded function will then bound each pair from @v1_vec & @v2_vec as a insert value
39+
/// If flag is set to `true`, v1_vec should contain exactly one element,
40+
/// The insert pair will be {v1_vec[0], v2_vec[0]}, {v1_vec[0], v2_vec[1]} ...
41+
auto Insert(Transaction *txn, BustubInstance &instance, const std::vector<int> &v1_vec, const std::vector<int> &v2_vec,
42+
bool flag = false) -> void {
43+
// Check if the input vectors have the same size.
44+
if (!flag) {
45+
if (v1_vec.size() != v2_vec.size()) {
46+
fmt::print(stderr, "Vectors @v1_vec and @v2_vec must have the same size\n");
47+
return;
48+
}
49+
if (v1_vec.empty()) {
50+
fmt::print(stderr, "Input vectors must not be empty\n");
51+
return;
52+
}
53+
} else {
54+
if (v1_vec.size() != 1) {
55+
fmt::print(stderr, "Size of @v1_vec should be exactly 1 if flag is set to `true`\n");
56+
return;
57+
}
58+
if (v2_vec.empty()) {
59+
fmt::print(stderr, "Input vectors must not be empty\n");
60+
return;
61+
}
62+
}
63+
64+
std::stringstream ss;
65+
auto writer = bustub::SimpleStreamWriter(ss, true, ",");
66+
67+
assert(v1_vec.size() == 1);
68+
std::string val_str{};
69+
if (!flag) {
70+
for (size_t i = 0; i < v1_vec.size(); ++i) {
71+
val_str += fmt::format("({}, {}), ", v1_vec[i], v2_vec[i]);
72+
}
73+
} else {
74+
for (const auto &v2 : v2_vec) {
75+
val_str += fmt::format("({}, {}), ", v1_vec[0], v2);
76+
}
77+
}
78+
79+
// Remove the last comma and space
80+
assert(!val_str.empty() && val_str.size() >= 2);
81+
val_str.pop_back();
82+
val_str.pop_back();
83+
84+
fmt::print(stderr, "insert data with @v1_vec = {} and @v2_vec = {} in txn {} {}\n", v1_vec, v2_vec,
85+
txn->GetTransactionId(), txn->GetIsolationLevel());
86+
87+
std::string sql = "INSERT INTO t1 VALUES " + val_str;
88+
89+
bool res = instance.ExecuteSqlTxn(sql, writer, txn);
90+
if (!res) {
91+
fmt::print(stderr, "Failed to insert data with @v1_vec = {} and @v2_vec = {} in txn {} {}\n", v1_vec, v2_vec);
92+
}
93+
94+
// The final number of inserted elements should be the size of @v2_vec
95+
ASSERT_EQ(ss.str(), fmt::format("{},\n", v2_vec.size()));
96+
}
97+
3398
auto Delete(Transaction *txn, BustubInstance &instance, int v1) -> void {
3499
std::stringstream ss;
35100
auto writer = bustub::SimpleStreamWriter(ss, true, ",");
@@ -39,6 +104,36 @@ auto Delete(Transaction *txn, BustubInstance &instance, int v1) -> void {
39104
ASSERT_EQ(ss.str(), "3,\n");
40105
}
41106

107+
/// @brief Use this to write your own test cases, if needed
108+
/// @param d_vec Elements to be deleted from t1, represents the value of `t1:v1`
109+
/// @param d_size The size you expect to be deleted from t1, will be used as sanity check, default value is 3
110+
/// This overloaded function performs a vectorized self-constructed deletion to better test the implementation
111+
/// You should calculate the number of elements that logically should be deleted, and pass it in as @d_size.
112+
auto Delete(Transaction *txn, BustubInstance &instance, const std::vector<int> &d_vec, int d_size = 3) -> void {
113+
if (d_vec.empty()) {
114+
fmt::print(stderr, "Input vec must not be empty\n");
115+
return;
116+
}
117+
118+
assert(!d_vec.empty());
119+
120+
std::stringstream ss;
121+
auto writer = bustub::SimpleStreamWriter(ss, true, ",");
122+
123+
for (const auto &v1 : d_vec) {
124+
fmt::print(stderr, "delete data with v1 = {} in txn {} {}\n", v1, txn->GetTransactionId(),
125+
txn->GetIsolationLevel());
126+
std::string sql = fmt::format("DELETE FROM t1 WHERE v1 = {}", v1);
127+
bool res = instance.ExecuteSqlTxn(sql, writer, txn);
128+
if (!res) {
129+
fmt::print(stderr, "Failed to delete data with v1 = {} in txn {} {}\n", v1, txn->GetTransactionId(),
130+
txn->GetIsolationLevel());
131+
}
132+
}
133+
134+
ASSERT_EQ(ss.str(), fmt::format("{},\n", d_size));
135+
}
136+
42137
auto ExpectResult(const std::string &actual_result, const std::string &expected_result) -> bool {
43138
auto actual_result_rows = bustub::StringUtil::Split(actual_result, '\n');
44139
auto expected_result_rows = bustub::StringUtil::Split(expected_result, '\n');

0 commit comments

Comments
 (0)