|
2 | 2 | * lock_manager_test.cpp |
3 | 3 | */ |
4 | 4 |
|
5 | | -#include "concurrency/lock_manager.h" |
6 | | - |
7 | 5 | #include <random> |
8 | 6 | #include <thread> // NOLINT |
9 | 7 |
|
10 | 8 | #include "common/config.h" |
| 9 | +#include "common_checker.h" // NOLINT |
| 10 | +#include "concurrency/lock_manager.h" |
11 | 11 | #include "concurrency/transaction_manager.h" |
| 12 | + |
12 | 13 | #include "gtest/gtest.h" |
13 | 14 |
|
14 | 15 | namespace bustub { |
@@ -241,4 +242,66 @@ void TwoPLTest1() { |
241 | 242 |
|
242 | 243 | TEST(LockManagerTest, DISABLED_TwoPLTest1) { TwoPLTest1(); } // NOLINT |
243 | 244 |
|
| 245 | +void AbortTest1() { |
| 246 | + fmt::print(stderr, "AbortTest1: multiple X should block\n"); |
| 247 | + |
| 248 | + LockManager lock_mgr{}; |
| 249 | + TransactionManager txn_mgr{&lock_mgr}; |
| 250 | + |
| 251 | + table_oid_t oid = 0; |
| 252 | + RID rid{0, 0}; |
| 253 | + |
| 254 | + auto txn1 = txn_mgr.Begin(); |
| 255 | + auto txn2 = txn_mgr.Begin(); |
| 256 | + auto txn3 = txn_mgr.Begin(); |
| 257 | + |
| 258 | + /** All takes IX lock on table */ |
| 259 | + EXPECT_EQ(true, lock_mgr.LockTable(txn1, LockManager::LockMode::INTENTION_EXCLUSIVE, oid)); |
| 260 | + CheckTableLockSizes(txn1, 0, 0, 0, 1, 0); |
| 261 | + EXPECT_EQ(true, lock_mgr.LockTable(txn2, LockManager::LockMode::INTENTION_EXCLUSIVE, oid)); |
| 262 | + CheckTableLockSizes(txn2, 0, 0, 0, 1, 0); |
| 263 | + EXPECT_EQ(true, lock_mgr.LockTable(txn3, LockManager::LockMode::INTENTION_EXCLUSIVE, oid)); |
| 264 | + CheckTableLockSizes(txn3, 0, 0, 0, 1, 0); |
| 265 | + |
| 266 | + /** txn1 takes X lock on row */ |
| 267 | + EXPECT_EQ(true, lock_mgr.LockRow(txn1, LockManager::LockMode::EXCLUSIVE, oid, rid)); |
| 268 | + CheckTxnRowLockSize(txn1, oid, 0, 1); |
| 269 | + |
| 270 | + /** txn2 attempts X lock on table but should be blocked */ |
| 271 | + auto txn2_task = std::thread{[&]() { lock_mgr.LockRow(txn2, LockManager::LockMode::EXCLUSIVE, oid, rid); }}; |
| 272 | + |
| 273 | + /** Sleep for a bit */ |
| 274 | + std::this_thread::sleep_for(std::chrono::milliseconds(50)); |
| 275 | + /** txn2 shouldn't have been granted the lock */ |
| 276 | + CheckTxnRowLockSize(txn2, oid, 0, 0); |
| 277 | + |
| 278 | + /** txn3 attempts X lock on row but should be blocked */ |
| 279 | + auto txn3_task = std::thread{[&]() { lock_mgr.LockRow(txn3, LockManager::LockMode::EXCLUSIVE, oid, rid); }}; |
| 280 | + /** Sleep for a bit */ |
| 281 | + std::this_thread::sleep_for(std::chrono::milliseconds(50)); |
| 282 | + /** txn3 shouldn't have been granted the lock */ |
| 283 | + CheckTxnRowLockSize(txn3, oid, 0, 0); |
| 284 | + |
| 285 | + /** Abort txn2 */ |
| 286 | + txn_mgr.Abort(txn2); |
| 287 | + |
| 288 | + /** txn1 releases lock */ |
| 289 | + EXPECT_EQ(true, lock_mgr.UnlockRow(txn1, oid, rid)); |
| 290 | + CheckTxnRowLockSize(txn1, oid, 0, 0); |
| 291 | + |
| 292 | + txn2_task.join(); |
| 293 | + txn3_task.join(); |
| 294 | + /** txn2 shouldn't have any row locks */ |
| 295 | + CheckTxnRowLockSize(txn2, oid, 0, 0); |
| 296 | + CheckTableLockSizes(txn2, 0, 0, 0, 0, 0); |
| 297 | + /** txn3 should have the row lock */ |
| 298 | + CheckTxnRowLockSize(txn3, oid, 0, 1); |
| 299 | + |
| 300 | + delete txn1; |
| 301 | + delete txn2; |
| 302 | + delete txn3; |
| 303 | +} |
| 304 | + |
| 305 | +TEST(LockManagerTest, DISABLED_RowAbortTest1) { AbortTest1(); } // NOLINT |
| 306 | + |
244 | 307 | } // namespace bustub |
0 commit comments