11
11
// ===----------------------------------------------------------------------===//
12
12
13
13
#include < cstdio>
14
- #include < deque>
15
14
#include < filesystem>
16
15
17
16
#include " buffer/buffer_pool_manager.h"
@@ -27,36 +26,37 @@ const size_t FRAMES = 10;
27
26
// Note that this test assumes you are using the an LRU-K replacement policy.
28
27
const size_t K_DIST = 5 ;
29
28
29
+ void CopyString (char *dest, const std::string &src) {
30
+ BUSTUB_ENSURE (src.length () + 1 <= BUSTUB_PAGE_SIZE, " CopyString src too long" );
31
+ snprintf (dest, BUSTUB_PAGE_SIZE, " %s" , src.c_str ());
32
+ }
33
+
30
34
TEST (BufferPoolManagerTest, DISABLED_VeryBasicTest) {
31
35
// A very basic test.
32
36
33
37
auto disk_manager = std::make_shared<DiskManager>(db_fname);
34
38
auto bpm = std::make_shared<BufferPoolManager>(FRAMES, disk_manager.get (), K_DIST);
35
39
36
- page_id_t pid = bpm->NewPage ();
37
-
38
- char str[] = " Hello, world!" ;
40
+ const page_id_t pid = bpm->NewPage ();
41
+ const std::string str = " Hello, world!" ;
39
42
40
43
// Check `WritePageGuard` basic functionality.
41
44
{
42
45
auto guard = bpm->WritePage (pid);
43
- char *data = guard.GetDataMut ();
44
- snprintf (data, sizeof (str), " %s" , str);
45
- EXPECT_STREQ (data, str);
46
+ CopyString (guard.GetDataMut (), str);
47
+ EXPECT_STREQ (guard.GetData (), str.c_str ());
46
48
}
47
49
48
50
// Check `ReadPageGuard` basic functionality.
49
51
{
50
- auto guard = bpm->ReadPage (pid);
51
- const char *data = guard.GetData ();
52
- EXPECT_STREQ (data, str);
52
+ const auto guard = bpm->ReadPage (pid);
53
+ EXPECT_STREQ (guard.GetData (), str.c_str ());
53
54
}
54
55
55
56
// Check `ReadPageGuard` basic functionality (again).
56
57
{
57
- auto guard = bpm->ReadPage (pid);
58
- const char *data = guard.GetData ();
59
- EXPECT_STREQ (data, str);
58
+ const auto guard = bpm->ReadPage (pid);
59
+ EXPECT_STREQ (guard.GetData (), str.c_str ());
60
60
}
61
61
62
62
ASSERT_TRUE (bpm->DeletePage (pid));
@@ -66,31 +66,34 @@ TEST(BufferPoolManagerTest, DISABLED_PagePinEasyTest) {
66
66
auto disk_manager = std::make_shared<DiskManager>(db_fname);
67
67
auto bpm = std::make_shared<BufferPoolManager>(2 , disk_manager.get (), 5 );
68
68
69
- page_id_t pageid0;
70
- page_id_t pageid1;
69
+ const page_id_t pageid0 = bpm->NewPage ();
70
+ const page_id_t pageid1 = bpm->NewPage ();
71
+
72
+ const std::string str0 = " page0" ;
73
+ const std::string str1 = " page1" ;
74
+ const std::string str0updated = " page0updated" ;
75
+ const std::string str1updated = " page1updated" ;
71
76
72
77
{
73
- pageid0 = bpm->NewPage ();
74
78
auto page0_write_opt = bpm->CheckedWritePage (pageid0);
75
79
ASSERT_TRUE (page0_write_opt.has_value ());
76
- WritePageGuard page0_write = std::move (page0_write_opt.value ());
77
- strcpy (page0_write.GetDataMut (), " page0 " ); // NOLINT
80
+ auto page0_write = std::move (page0_write_opt.value ());
81
+ CopyString (page0_write.GetDataMut (), str0);
78
82
79
- pageid1 = bpm->NewPage ();
80
83
auto page1_write_opt = bpm->CheckedWritePage (pageid1);
81
84
ASSERT_TRUE (page1_write_opt.has_value ());
82
- WritePageGuard page1_write = std::move (page1_write_opt.value ());
83
- strcpy (page1_write.GetDataMut (), " page1 " ); // NOLINT
85
+ auto page1_write = std::move (page1_write_opt.value ());
86
+ CopyString (page1_write.GetDataMut (), str1);
84
87
85
88
ASSERT_EQ (1 , bpm->GetPinCount (pageid0));
86
89
ASSERT_EQ (1 , bpm->GetPinCount (pageid1));
87
90
88
- page_id_t temp_page_id1 = bpm->NewPage ();
89
- auto temp_page1_opt = bpm->CheckedReadPage (temp_page_id1);
91
+ const auto temp_page_id1 = bpm->NewPage ();
92
+ const auto temp_page1_opt = bpm->CheckedReadPage (temp_page_id1);
90
93
ASSERT_FALSE (temp_page1_opt.has_value ());
91
94
92
- page_id_t temp_page_id2 = bpm->NewPage ();
93
- auto temp_page2_opt = bpm->CheckedWritePage (temp_page_id2);
95
+ const auto temp_page_id2 = bpm->NewPage ();
96
+ const auto temp_page2_opt = bpm->CheckedWritePage (temp_page_id2);
94
97
ASSERT_FALSE (temp_page2_opt.has_value ());
95
98
96
99
ASSERT_EQ (1 , bpm->GetPinCount (pageid0));
@@ -103,12 +106,12 @@ TEST(BufferPoolManagerTest, DISABLED_PagePinEasyTest) {
103
106
}
104
107
105
108
{
106
- page_id_t temp_page_id1 = bpm->NewPage ();
107
- auto temp_page1_opt = bpm->CheckedReadPage (temp_page_id1);
109
+ const auto temp_page_id1 = bpm->NewPage ();
110
+ const auto temp_page1_opt = bpm->CheckedReadPage (temp_page_id1);
108
111
ASSERT_TRUE (temp_page1_opt.has_value ());
109
112
110
- page_id_t temp_page_id2 = bpm->NewPage ();
111
- auto temp_page2_opt = bpm->CheckedWritePage (temp_page_id2);
113
+ const auto temp_page_id2 = bpm->NewPage ();
114
+ const auto temp_page2_opt = bpm->CheckedWritePage (temp_page_id2);
112
115
ASSERT_TRUE (temp_page2_opt.has_value ());
113
116
114
117
ASSERT_FALSE (bpm->GetPinCount (pageid0).has_value ());
@@ -118,15 +121,15 @@ TEST(BufferPoolManagerTest, DISABLED_PagePinEasyTest) {
118
121
{
119
122
auto page0_write_opt = bpm->CheckedWritePage (pageid0);
120
123
ASSERT_TRUE (page0_write_opt.has_value ());
121
- WritePageGuard page0_write = std::move (page0_write_opt.value ());
122
- ASSERT_EQ ( 0 , strcmp ( page0_write.GetData (), " page0 " ));
123
- strcpy (page0_write.GetDataMut (), " page0updated " ); // NOLINT
124
+ auto page0_write = std::move (page0_write_opt.value ());
125
+ EXPECT_STREQ ( page0_write.GetData (), str0. c_str ( ));
126
+ CopyString (page0_write.GetDataMut (), str0updated);
124
127
125
128
auto page1_write_opt = bpm->CheckedWritePage (pageid1);
126
129
ASSERT_TRUE (page1_write_opt.has_value ());
127
- WritePageGuard page1_write = std::move (page1_write_opt.value ());
128
- ASSERT_EQ ( 0 , strcmp ( page1_write.GetData (), " page1 " ));
129
- strcpy (page1_write.GetDataMut (), " page1updated " ); // NOLINT
130
+ auto page1_write = std::move (page1_write_opt.value ());
131
+ EXPECT_STREQ ( page1_write.GetData (), str1. c_str ( ));
132
+ CopyString (page1_write.GetDataMut (), str1updated);
130
133
131
134
ASSERT_EQ (1 , bpm->GetPinCount (pageid0));
132
135
ASSERT_EQ (1 , bpm->GetPinCount (pageid1));
@@ -138,13 +141,13 @@ TEST(BufferPoolManagerTest, DISABLED_PagePinEasyTest) {
138
141
{
139
142
auto page0_read_opt = bpm->CheckedReadPage (pageid0);
140
143
ASSERT_TRUE (page0_read_opt.has_value ());
141
- ReadPageGuard page0_read = std::move (page0_read_opt.value ());
142
- ASSERT_EQ ( 0 , strcmp ( page0_read.GetData (), " page0updated " ));
144
+ const auto page0_read = std::move (page0_read_opt.value ());
145
+ EXPECT_STREQ ( page0_read.GetData (), str0updated. c_str ( ));
143
146
144
147
auto page1_read_opt = bpm->CheckedReadPage (pageid1);
145
148
ASSERT_TRUE (page1_read_opt.has_value ());
146
- ReadPageGuard page1_read = std::move (page1_read_opt.value ());
147
- ASSERT_EQ ( 0 , strcmp ( page1_read.GetData (), " page1updated " ));
149
+ const auto page1_read = std::move (page1_read_opt.value ());
150
+ EXPECT_STREQ ( page1_read.GetData (), str1updated. c_str ( ));
148
151
149
152
ASSERT_EQ (1 , bpm->GetPinCount (pageid0));
150
153
ASSERT_EQ (1 , bpm->GetPinCount (pageid1));
@@ -162,12 +165,13 @@ TEST(BufferPoolManagerTest, DISABLED_PagePinMediumTest) {
162
165
auto bpm = std::make_shared<BufferPoolManager>(FRAMES, disk_manager.get (), K_DIST);
163
166
164
167
// Scenario: The buffer pool is empty. We should be able to create a new page.
165
- page_id_t pid0 = bpm->NewPage ();
168
+ const auto pid0 = bpm->NewPage ();
166
169
auto page0 = bpm->WritePage (pid0);
167
170
168
171
// Scenario: Once we have a page, we should be able to read and write content.
169
- snprintf (page0.GetDataMut (), BUSTUB_PAGE_SIZE, " Hello" );
170
- EXPECT_EQ (0 , strcmp (page0.GetDataMut (), " Hello" ));
172
+ const std::string hello = " Hello" ;
173
+ CopyString (page0.GetDataMut (), hello);
174
+ EXPECT_STREQ (page0.GetData (), hello.c_str ());
171
175
172
176
page0.Drop ();
173
177
@@ -176,58 +180,58 @@ TEST(BufferPoolManagerTest, DISABLED_PagePinMediumTest) {
176
180
177
181
// Scenario: We should be able to create new pages until we fill up the buffer pool.
178
182
for (size_t i = 0 ; i < FRAMES; i++) {
179
- auto pid = bpm->NewPage ();
183
+ const auto pid = bpm->NewPage ();
180
184
auto page = bpm->WritePage (pid);
181
185
pages.push_back (std::move (page));
182
186
}
183
187
184
188
// Scenario: All of the pin counts should be 1.
185
189
for (const auto &page : pages) {
186
- auto pid = page.GetPageId ();
190
+ const auto pid = page.GetPageId ();
187
191
EXPECT_EQ (1 , bpm->GetPinCount (pid));
188
192
}
189
193
190
194
// Scenario: Once the buffer pool is full, we should not be able to create any new pages.
191
195
for (size_t i = 0 ; i < FRAMES; i++) {
192
- auto pid = bpm->NewPage ();
193
- auto fail = bpm->CheckedWritePage (pid);
196
+ const auto pid = bpm->NewPage ();
197
+ const auto fail = bpm->CheckedWritePage (pid);
194
198
ASSERT_FALSE (fail.has_value ());
195
199
}
196
200
197
201
// Scenario: Drop the first 5 pages to unpin them.
198
202
for (size_t i = 0 ; i < FRAMES / 2 ; i++) {
199
- page_id_t pid = pages[0 ].GetPageId ();
203
+ const auto pid = pages[0 ].GetPageId ();
200
204
EXPECT_EQ (1 , bpm->GetPinCount (pid));
201
205
pages.erase (pages.begin ());
202
206
EXPECT_EQ (0 , bpm->GetPinCount (pid));
203
207
}
204
208
205
209
// Scenario: All of the pin counts of the pages we haven't dropped yet should still be 1.
206
210
for (const auto &page : pages) {
207
- auto pid = page.GetPageId ();
211
+ const auto pid = page.GetPageId ();
208
212
EXPECT_EQ (1 , bpm->GetPinCount (pid));
209
213
}
210
214
211
215
// Scenario: After unpinning pages {1, 2, 3, 4, 5}, we should be able to create 4 new pages and bring them into
212
216
// memory. Bringing those 4 pages into memory should evict the first 4 pages {1, 2, 3, 4} because of LRU.
213
217
for (size_t i = 0 ; i < ((FRAMES / 2 ) - 1 ); i++) {
214
- auto pid = bpm->NewPage ();
218
+ const auto pid = bpm->NewPage ();
215
219
auto page = bpm->WritePage (pid);
216
220
pages.push_back (std::move (page));
217
221
}
218
222
219
223
// Scenario: There should be one frame available, and we should be able to fetch the data we wrote a while ago.
220
224
{
221
- ReadPageGuard original_page = bpm->ReadPage (pid0);
222
- EXPECT_EQ ( 0 , strcmp ( original_page.GetData (), " Hello " ));
225
+ const auto original_page = bpm->ReadPage (pid0);
226
+ EXPECT_STREQ ( original_page.GetData (), hello. c_str ( ));
223
227
}
224
228
225
229
// Scenario: Once we unpin page 0 and then make a new page, all the buffer pages should now be pinned. Fetching page 0
226
230
// again should fail.
227
- auto last_pid = bpm->NewPage ();
228
- auto last_page = bpm->ReadPage (last_pid);
231
+ const auto last_pid = bpm->NewPage ();
232
+ const auto last_page = bpm->ReadPage (last_pid);
229
233
230
- auto fail = bpm->CheckedReadPage (pid0);
234
+ const auto fail = bpm->CheckedReadPage (pid0);
231
235
ASSERT_FALSE (fail.has_value ());
232
236
233
237
// Shutdown the disk manager and remove the temporary file we created.
@@ -241,15 +245,15 @@ TEST(BufferPoolManagerTest, DISABLED_PageAccessTest) {
241
245
auto disk_manager = std::make_shared<DiskManager>(db_fname);
242
246
auto bpm = std::make_shared<BufferPoolManager>(1 , disk_manager.get (), K_DIST);
243
247
244
- auto pid = bpm->NewPage ();
248
+ const auto pid = bpm->NewPage ();
245
249
char buf[BUSTUB_PAGE_SIZE];
246
250
247
251
auto thread = std::thread ([&]() {
248
252
// The writer can keep writing to the same page.
249
253
for (size_t i = 0 ; i < rounds; i++) {
250
254
std::this_thread::sleep_for (std::chrono::milliseconds (5 ));
251
255
auto guard = bpm->WritePage (pid);
252
- strcpy (guard.GetDataMut (), std::to_string (i). c_str ()); // NOLINT
256
+ CopyString (guard.GetDataMut (), std::to_string (i));
253
257
}
254
258
});
255
259
@@ -258,7 +262,7 @@ TEST(BufferPoolManagerTest, DISABLED_PageAccessTest) {
258
262
std::this_thread::sleep_for (std::chrono::milliseconds (10 ));
259
263
260
264
// While we are reading, nobody should be able to modify the data.
261
- auto guard = bpm->ReadPage (pid);
265
+ const auto guard = bpm->ReadPage (pid);
262
266
263
267
// Save the data we observe.
264
268
memcpy (buf, guard.GetData (), BUSTUB_PAGE_SIZE);
@@ -267,7 +271,7 @@ TEST(BufferPoolManagerTest, DISABLED_PageAccessTest) {
267
271
std::this_thread::sleep_for (std::chrono::milliseconds (10 ));
268
272
269
273
// Check that the data is unmodified.
270
- EXPECT_EQ ( 0 , strcmp ( guard.GetData (), buf) );
274
+ EXPECT_STREQ ( guard.GetData (), buf);
271
275
}
272
276
273
277
thread.join ();
@@ -279,33 +283,33 @@ TEST(BufferPoolManagerTest, DISABLED_ContentionTest) {
279
283
280
284
const size_t rounds = 100000 ;
281
285
282
- auto pid = bpm->NewPage ();
286
+ const auto pid = bpm->NewPage ();
283
287
284
288
auto thread1 = std::thread ([&]() {
285
289
for (size_t i = 0 ; i < rounds; i++) {
286
290
auto guard = bpm->WritePage (pid);
287
- strcpy (guard.GetDataMut (), std::to_string (i). c_str ()); // NOLINT
291
+ CopyString (guard.GetDataMut (), std::to_string (i));
288
292
}
289
293
});
290
294
291
295
auto thread2 = std::thread ([&]() {
292
296
for (size_t i = 0 ; i < rounds; i++) {
293
297
auto guard = bpm->WritePage (pid);
294
- strcpy (guard.GetDataMut (), std::to_string (i). c_str ()); // NOLINT
298
+ CopyString (guard.GetDataMut (), std::to_string (i));
295
299
}
296
300
});
297
301
298
302
auto thread3 = std::thread ([&]() {
299
303
for (size_t i = 0 ; i < rounds; i++) {
300
304
auto guard = bpm->WritePage (pid);
301
- strcpy (guard.GetDataMut (), std::to_string (i). c_str ()); // NOLINT
305
+ CopyString (guard.GetDataMut (), std::to_string (i));
302
306
}
303
307
});
304
308
305
309
auto thread4 = std::thread ([&]() {
306
310
for (size_t i = 0 ; i < rounds; i++) {
307
311
auto guard = bpm->WritePage (pid);
308
- strcpy (guard.GetDataMut (), std::to_string (i). c_str ()); // NOLINT
312
+ CopyString (guard.GetDataMut (), std::to_string (i));
309
313
}
310
314
});
311
315
@@ -319,8 +323,8 @@ TEST(BufferPoolManagerTest, DISABLED_DeadlockTest) {
319
323
auto disk_manager = std::make_shared<DiskManager>(db_fname);
320
324
auto bpm = std::make_shared<BufferPoolManager>(FRAMES, disk_manager.get (), K_DIST);
321
325
322
- auto pid0 = bpm->NewPage ();
323
- auto pid1 = bpm->NewPage ();
326
+ const auto pid0 = bpm->NewPage ();
327
+ const auto pid1 = bpm->NewPage ();
324
328
325
329
auto guard0 = bpm->WritePage (pid0);
326
330
@@ -332,7 +336,7 @@ TEST(BufferPoolManagerTest, DISABLED_DeadlockTest) {
332
336
start.store (true );
333
337
334
338
// Attempt to write to page 0.
335
- auto guard0 = bpm->WritePage (pid0);
339
+ const auto guard0 = bpm->WritePage (pid0);
336
340
});
337
341
338
342
// Wait for the other thread to begin before we start the test.
@@ -347,7 +351,7 @@ TEST(BufferPoolManagerTest, DISABLED_DeadlockTest) {
347
351
// Think about what might happen if you hold a certain "all-encompassing" latch for too long...
348
352
349
353
// While holding page 0, take the latch on page 1.
350
- auto guard1 = bpm->WritePage (pid1);
354
+ const auto guard1 = bpm->WritePage (pid1);
351
355
352
356
// Let the child thread have the page 0 since we're done with it.
353
357
guard0.Drop ();
@@ -357,8 +361,8 @@ TEST(BufferPoolManagerTest, DISABLED_DeadlockTest) {
357
361
358
362
TEST (BufferPoolManagerTest, DISABLED_EvictableTest) {
359
363
// Test if the evictable status of a frame is always correct.
360
- size_t rounds = 1000 ;
361
- size_t num_readers = 8 ;
364
+ const size_t rounds = 1000 ;
365
+ const size_t num_readers = 8 ;
362
366
363
367
auto disk_manager = std::make_shared<DiskManager>(db_fname);
364
368
// Only allocate 1 frame of memory to the buffer pool manager.
@@ -372,9 +376,9 @@ TEST(BufferPoolManagerTest, DISABLED_EvictableTest) {
372
376
bool signal = false ;
373
377
374
378
// This page will be loaded into the only available frame.
375
- page_id_t winner_pid = bpm->NewPage ();
379
+ const auto winner_pid = bpm->NewPage ();
376
380
// We will attempt to load this page into the occupied frame, and it should fail every time.
377
- page_id_t loser_pid = bpm->NewPage ();
381
+ const auto loser_pid = bpm->NewPage ();
378
382
379
383
std::vector<std::thread> readers;
380
384
for (size_t j = 0 ; j < num_readers; j++) {
@@ -387,7 +391,7 @@ TEST(BufferPoolManagerTest, DISABLED_EvictableTest) {
387
391
}
388
392
389
393
// Read the page in shared mode.
390
- auto read_guard = bpm->ReadPage (winner_pid);
394
+ const auto read_guard = bpm->ReadPage (winner_pid);
391
395
392
396
// Since the only frame is pinned, no thread should be able to bring in a new page.
393
397
ASSERT_FALSE (bpm->CheckedReadPage (loser_pid).has_value ());
0 commit comments