44 */
55
66#include < gtest/gtest.h>
7+
78#include < atomic>
89#include < chrono>
10+ #include < cstdio>
911#include < thread>
1012#include < vector>
11- #include < cstdio>
1213
1314#include " catalog/catalog.hpp"
1415#include " common/config.hpp"
1516#include " storage/buffer_pool_manager.hpp"
16- #include " storage/storage_manager.hpp"
1717#include " storage/heap_table.hpp"
18+ #include " storage/storage_manager.hpp"
1819#include " transaction/lock_manager.hpp"
1920#include " transaction/transaction.hpp"
2021#include " transaction/transaction_manager.hpp"
@@ -30,25 +31,26 @@ namespace {
3031 * @brief Fixture for transaction-related coverage tests to ensure proper resource management.
3132 */
3233class TransactionCoverageTests : public ::testing::Test {
33- protected:
34+ protected:
3435 void SetUp () override {
3536 catalog_ptr = Catalog::create ();
3637 disk_manager_ptr = std::make_unique<StorageManager>(" ./test_data" );
37- bpm_ptr = std::make_unique<BufferPoolManager>(config::Config::DEFAULT_BUFFER_POOL_SIZE, *disk_manager_ptr);
38+ bpm_ptr = std::make_unique<BufferPoolManager>(config::Config::DEFAULT_BUFFER_POOL_SIZE,
39+ *disk_manager_ptr);
3840 lm_ptr = std::make_unique<LockManager>();
3941 tm_ptr = std::make_unique<TransactionManager>(*lm_ptr, *catalog_ptr, *bpm_ptr, nullptr );
4042
4143 std::vector<ColumnInfo> cols = {{" id" , common::ValueType::TYPE_INT64, 0 },
4244 {" val" , common::ValueType::TYPE_TEXT, 1 }};
4345 catalog_ptr->create_table (" rollback_stress" , cols);
44-
46+
4547 executor::Schema schema;
4648 schema.add_column (" id" , common::ValueType::TYPE_INT64);
4749 schema.add_column (" val" , common::ValueType::TYPE_TEXT);
48-
50+
4951 table_ptr = std::make_unique<HeapTable>(" rollback_stress" , *bpm_ptr, schema);
5052 table_ptr->create ();
51-
53+
5254 txn = nullptr ;
5355 }
5456
@@ -62,7 +64,7 @@ class TransactionCoverageTests : public ::testing::Test {
6264 bpm_ptr.reset ();
6365 disk_manager_ptr.reset ();
6466 catalog_ptr.reset ();
65-
67+
6668 static_cast <void >(std::remove (" ./test_data/rollback_stress.heap" ));
6769 }
6870
@@ -73,7 +75,7 @@ class TransactionCoverageTests : public ::testing::Test {
7375 std::unique_ptr<LockManager> lm_ptr;
7476 std::unique_ptr<TransactionManager> tm_ptr;
7577 std::unique_ptr<HeapTable> table_ptr;
76-
78+
7779 // Live transaction pointer for cleanup
7880 Transaction* txn;
7981};
@@ -89,7 +91,7 @@ TEST(TransactionCoverageTestsStandalone, LockManagerConcurrency) {
8991 std::atomic<bool > stop{false };
9092
9193 Transaction writer_txn (100 );
92-
94+
9395 // Writers holds exclusive lock initially
9496 ASSERT_TRUE (lm.acquire_exclusive (&writer_txn, " RESOURCE" ));
9597
@@ -112,7 +114,7 @@ TEST(TransactionCoverageTestsStandalone, LockManagerConcurrency) {
112114
113115 // Release writer lock, readers should proceed
114116 lm.unlock (&writer_txn, " RESOURCE" );
115-
117+
116118 // Wait for all readers to get the lock
117119 for (int i = 0 ; i < 50 && shared_granted.load () < num_readers; ++i) {
118120 std::this_thread::sleep_for (std::chrono::milliseconds (50 ));
@@ -135,36 +137,43 @@ TEST_F(TransactionCoverageTests, DeepRollback) {
135137 HeapTable& table = *table_ptr;
136138
137139 txn = tm.begin ();
138-
140+
139141 // 1. Insert some data
140- auto rid1 = table.insert (executor::Tuple ({common::Value::make_int64 (1 ), common::Value::make_text (" A" )}), txn->get_id ());
142+ auto rid1 =
143+ table.insert (executor::Tuple ({common::Value::make_int64 (1 ), common::Value::make_text (" A" )}),
144+ txn->get_id ());
141145 txn->add_undo_log (UndoLog::Type::INSERT, " rollback_stress" , rid1);
142-
143- auto rid2 = table.insert (executor::Tuple ({common::Value::make_int64 (2 ), common::Value::make_text (" B" )}), txn->get_id ());
146+
147+ auto rid2 =
148+ table.insert (executor::Tuple ({common::Value::make_int64 (2 ), common::Value::make_text (" B" )}),
149+ txn->get_id ());
144150 txn->add_undo_log (UndoLog::Type::INSERT, " rollback_stress" , rid2);
145151
146152 // 2. Update data
147- table.remove (rid1, txn->get_id ()); // Mark old version deleted
148- auto rid1_new = table.insert (executor::Tuple ({common::Value::make_int64 (1 ), common::Value::make_text (" A_NEW" )}), txn->get_id ());
153+ table.remove (rid1, txn->get_id ()); // Mark old version deleted
154+ auto rid1_new = table.insert (
155+ executor::Tuple ({common::Value::make_int64 (1 ), common::Value::make_text (" A_NEW" )}),
156+ txn->get_id ());
149157 txn->add_undo_log (UndoLog::Type::UPDATE, " rollback_stress" , rid1_new, rid1);
150158
151159 // 3. Delete data
152160 table.remove (rid2, txn->get_id ());
153161 txn->add_undo_log (UndoLog::Type::DELETE, " rollback_stress" , rid2);
154162
155- EXPECT_EQ (table.tuple_count (), 1U ); // rid1_new is active, rid1 and rid2 are logically deleted
163+ EXPECT_EQ (table.tuple_count (), 1U ); // rid1_new is active, rid1 and rid2 are logically deleted
156164
157165 // 4. Abort
158166 tm.abort (txn);
159- txn = nullptr ; // Marked as aborted and handled by TearDown if still set
167+ txn = nullptr ; // Marked as aborted and handled by TearDown if still set
160168
161169 // 5. Verify restoration
162- EXPECT_EQ (table.tuple_count (), 0U ); // Inserted rows should be physically removed or logically invisible
163-
170+ EXPECT_EQ (table.tuple_count (),
171+ 0U ); // Inserted rows should be physically removed or logically invisible
172+
164173 // The table should be empty because we aborted the inserts
165174 auto iter = table.scan ();
166175 executor::Tuple t;
167176 EXPECT_FALSE (iter.next (t));
168177}
169178
170- } // namespace
179+ } // namespace
0 commit comments