@@ -233,4 +233,181 @@ TEST_F(StorageManagerTests, WriteAndReadDifferentPages) {
233233 EXPECT_EQ (std::memcmp (page5, read_buf, StorageManager::PAGE_SIZE), 0 );
234234}
235235
236+ // ============= New Tests =============
237+
238+ /* *
239+ * @brief Verifies PAGE_SIZE constant value
240+ */
241+ TEST_F (StorageManagerTests, PageSizeConstant) {
242+ EXPECT_EQ (StorageManager::PAGE_SIZE, 4096U );
243+ }
244+
245+ /* *
246+ * @brief Verifies read_page auto-opens file if not already open
247+ */
248+ TEST_F (StorageManagerTests, ReadNonOpenedFileAutoOpens) {
249+ const std::string filename = " non_opened_read.db" ;
250+ cleanup_file (" ./test_data" , filename);
251+
252+ // Capture open-file count before operation
253+ auto before = sm_->get_stats ().files_opened .load ();
254+ ASSERT_FALSE (sm_->file_exists (filename));
255+
256+ // StorageManager auto-opens files, so read should succeed
257+ char buf[StorageManager::PAGE_SIZE];
258+ EXPECT_TRUE (sm_->read_page (filename, 0 , buf));
259+
260+ // Verify file was created and open-file count increased
261+ EXPECT_TRUE (sm_->file_exists (filename));
262+ EXPECT_EQ (sm_->get_stats ().files_opened .load (), before + 1 );
263+ }
264+
265+ /* *
266+ * @brief Verifies write_page auto-opens file if not already open
267+ */
268+ TEST_F (StorageManagerTests, WriteNonOpenedFileAutoOpens) {
269+ const std::string filename = " non_opened_write.db" ;
270+ cleanup_file (" ./test_data" , filename);
271+
272+ // Capture open-file count before operation
273+ auto before = sm_->get_stats ().files_opened .load ();
274+ ASSERT_FALSE (sm_->file_exists (filename));
275+
276+ char buf[StorageManager::PAGE_SIZE];
277+ std::memset (buf, 0xAB , StorageManager::PAGE_SIZE);
278+ // StorageManager auto-opens files, so write should succeed
279+ EXPECT_TRUE (sm_->write_page (filename, 0 , buf));
280+
281+ // Verify file was created and open-file count increased
282+ EXPECT_TRUE (sm_->file_exists (filename));
283+ EXPECT_EQ (sm_->get_stats ().files_opened .load (), before + 1 );
284+ }
285+
286+ /* *
287+ * @brief Verifies data persists across file open/close cycle
288+ */
289+ TEST_F (StorageManagerTests, DataPersistenceAcrossOpenClose) {
290+ const std::string filename = " persist_test.db" ;
291+ cleanup_file (" ./test_data" , filename);
292+
293+ // Write data to page 0
294+ ASSERT_TRUE (sm_->open_file (filename));
295+ char write_buf[StorageManager::PAGE_SIZE];
296+ for (int i = 0 ; i < StorageManager::PAGE_SIZE; ++i) {
297+ write_buf[i] = static_cast <char >(i & 0xFF );
298+ }
299+ ASSERT_TRUE (sm_->write_page (filename, 0 , write_buf));
300+ ASSERT_TRUE (sm_->close_file (filename));
301+
302+ // Reopen and read - data should persist
303+ ASSERT_TRUE (sm_->open_file (filename));
304+ char read_buf[StorageManager::PAGE_SIZE];
305+ ASSERT_TRUE (sm_->read_page (filename, 0 , read_buf));
306+ EXPECT_EQ (std::memcmp (write_buf, read_buf, StorageManager::PAGE_SIZE), 0 );
307+ ASSERT_TRUE (sm_->close_file (filename));
308+ }
309+
310+ /* *
311+ * @brief Verifies stats track bytes_read and bytes_written accurately
312+ */
313+ TEST_F (StorageManagerTests, StatsBytesAccurate) {
314+ const std::string filename = " stats_bytes_test.db" ;
315+ cleanup_file (" ./test_data" , filename);
316+
317+ const auto & stats = sm_->get_stats ();
318+ auto initial_bytes_read = stats.bytes_read .load ();
319+ auto initial_bytes_written = stats.bytes_written .load ();
320+
321+ ASSERT_TRUE (sm_->open_file (filename));
322+
323+ char buf[StorageManager::PAGE_SIZE];
324+ std::memset (buf, 0xAB , StorageManager::PAGE_SIZE);
325+ ASSERT_TRUE (sm_->write_page (filename, 0 , buf));
326+ ASSERT_TRUE (sm_->read_page (filename, 0 , buf));
327+
328+ EXPECT_EQ (stats.bytes_written .load (), initial_bytes_written + StorageManager::PAGE_SIZE);
329+ EXPECT_EQ (stats.bytes_read .load (), initial_bytes_read + StorageManager::PAGE_SIZE);
330+ }
331+
332+ /* *
333+ * @brief Verifies data isolation between multiple files
334+ */
335+ TEST_F (StorageManagerTests, MultipleFilesDataIsolation) {
336+ const std::string file1 = " isolate1.db" ;
337+ const std::string file2 = " isolate2.db" ;
338+ cleanup_file (" ./test_data" , file1);
339+ cleanup_file (" ./test_data" , file2);
340+
341+ ASSERT_TRUE (sm_->open_file (file1));
342+ ASSERT_TRUE (sm_->open_file (file2));
343+
344+ char buf1[StorageManager::PAGE_SIZE];
345+ char buf2[StorageManager::PAGE_SIZE];
346+ char read_buf[StorageManager::PAGE_SIZE];
347+
348+ std::memset (buf1, 0x11 , StorageManager::PAGE_SIZE);
349+ std::memset (buf2, 0x22 , StorageManager::PAGE_SIZE);
350+
351+ ASSERT_TRUE (sm_->write_page (file1, 0 , buf1));
352+ ASSERT_TRUE (sm_->write_page (file2, 0 , buf2));
353+
354+ // Read from file1 - should have file1's data
355+ ASSERT_TRUE (sm_->read_page (file1, 0 , read_buf));
356+ EXPECT_EQ (std::memcmp (buf1, read_buf, StorageManager::PAGE_SIZE), 0 );
357+
358+ // Read from file2 - should have file2's data
359+ ASSERT_TRUE (sm_->read_page (file2, 0 , read_buf));
360+ EXPECT_EQ (std::memcmp (buf2, read_buf, StorageManager::PAGE_SIZE), 0 );
361+ }
362+
363+ /* *
364+ * @brief Verifies deallocate_page stub doesn't crash
365+ */
366+ TEST_F (StorageManagerTests, DeallocatePageStub) {
367+ const std::string filename = " dealloc_test.db" ;
368+ cleanup_file (" ./test_data" , filename);
369+
370+ // deallocate_page is a stub but shouldn't crash
371+ EXPECT_NO_THROW (StorageManager::deallocate_page (filename, 0 ));
372+ }
373+
374+ /* *
375+ * @brief Verifies complex byte patterns persist correctly
376+ */
377+ TEST_F (StorageManagerTests, ReadAfterWriteDifferentPatterns) {
378+ const std::string filename = " patterns_test.db" ;
379+ cleanup_file (" ./test_data" , filename);
380+
381+ ASSERT_TRUE (sm_->open_file (filename));
382+
383+ // Write alternating pattern
384+ char page[StorageManager::PAGE_SIZE];
385+ for (size_t i = 0 ; i < StorageManager::PAGE_SIZE; ++i) {
386+ page[i] = (i % 2 == 0 ) ? 0xAA : 0x55 ;
387+ }
388+ ASSERT_TRUE (sm_->write_page (filename, 0 , page));
389+
390+ char read_buf[StorageManager::PAGE_SIZE];
391+ ASSERT_TRUE (sm_->read_page (filename, 0 , read_buf));
392+ EXPECT_EQ (std::memcmp (page, read_buf, StorageManager::PAGE_SIZE), 0 );
393+ }
394+
395+ /* *
396+ * @brief Verifies files_opened stat increments correctly
397+ */
398+ TEST_F (StorageManagerTests, FilesOpenedStatAccurate) {
399+ const std::string file1 = " stat_file1.db" ;
400+ const std::string file2 = " stat_file2.db" ;
401+ cleanup_file (" ./test_data" , file1);
402+ cleanup_file (" ./test_data" , file2);
403+
404+ const auto & stats = sm_->get_stats ();
405+ auto initial_files_opened = stats.files_opened .load ();
406+
407+ ASSERT_TRUE (sm_->open_file (file1));
408+ ASSERT_TRUE (sm_->open_file (file2));
409+
410+ EXPECT_EQ (stats.files_opened .load (), initial_files_opened + 2 );
411+ }
412+
236413} // namespace
0 commit comments