diff --git a/Tests/Kernel/TestExt2FS.cpp b/Tests/Kernel/TestExt2FS.cpp index 06b6ee0638c..6004d0f15f1 100644 --- a/Tests/Kernel/TestExt2FS.cpp +++ b/Tests/Kernel/TestExt2FS.cpp @@ -6,6 +6,9 @@ #include #include +#include +#include +#include #include TEST_CASE(test_uid_and_gid_high_bits_are_set) @@ -16,6 +19,7 @@ TEST_CASE(test_uid_and_gid_high_bits_are_set) EXPECT_EQ(uid, 0u); auto fd = open(TEST_FILE_PATH, O_CREAT); + VERIFY(fd != -1); auto cleanup_guard = ScopeGuard([&] { close(fd); unlink(TEST_FILE_PATH); @@ -29,3 +33,76 @@ TEST_CASE(test_uid_and_gid_high_bits_are_set) EXPECT_EQ(st.st_uid, 65536u); EXPECT_EQ(st.st_gid, 65536u); } + +TEST_CASE(test_ext2_writes_and_reads_to_block_ranges) +{ + static constexpr auto TEST_FILE_PATH = "/home/anon/.ext2_test"; + + auto fd = open(TEST_FILE_PATH, O_RDWR | O_CREAT); + VERIFY(fd != -1); + auto cleanup_guard = ScopeGuard([&] { + close(fd); + unlink(TEST_FILE_PATH); + }); + + struct statvfs stvfs; + int rc = fstatvfs(fd, &stvfs); + VERIFY(rc != -1); + + size_t block_size = (size_t)stvfs.f_bsize; + size_t ptrs_per_indirect_block = block_size / sizeof(u32); + + size_t direct_block_count = 12; + size_t singly_indirect_block_count = ptrs_per_indirect_block; + size_t doubly_indirect_block_count = pow(ptrs_per_indirect_block, 2); + size_t triply_indirect_block_count = pow(ptrs_per_indirect_block, 3); + + size_t direct_blocks_capacity = direct_block_count; + size_t singly_indirect_blocks_capacity = direct_blocks_capacity + singly_indirect_block_count; + size_t doubly_indirect_blocks_capacity = singly_indirect_blocks_capacity + doubly_indirect_block_count; + size_t triply_indirect_blocks_capacity = doubly_indirect_blocks_capacity + triply_indirect_block_count; + + char* block_buf = (char*)malloc(block_size); + block_buf[0] = '!'; + block_buf[block_size - 1] = '!'; + char* read_buf = (char*)malloc(block_size); + auto malloc_cleanup_guard = ScopeGuard([&] { + free(block_buf); + free(read_buf); + }); + + auto write_then_read_block = [&](size_t block) { + size_t offset = block * block_size; + + // write the block, and verify that write() was successful + off_t seek_rc = lseek(fd, offset, SEEK_SET); + VERIFY(seek_rc != -1); + int nwrite = write(fd, block_buf, block_size); + EXPECT((size_t)nwrite == block_size); + + // read the block we just wrote, and verify that read() was successful + seek_rc = lseek(fd, offset, SEEK_SET); + VERIFY(seek_rc != -1); + int nread = read(fd, read_buf, block_size); + EXPECT((size_t)nread == block_size); + + // verify that the block we read back is identical to the block we wrote + EXPECT(memcmp(read_buf, block_buf, block_size) == 0); + }; + + // run test on the first & last direct blocks + write_then_read_block(0); + write_then_read_block(direct_blocks_capacity - 1); + + // run test on the first & last singly indirect blocks + write_then_read_block(direct_blocks_capacity); + write_then_read_block(singly_indirect_blocks_capacity - 1); + + // run test on the first & last doubly indirect blocks + write_then_read_block(singly_indirect_blocks_capacity); + write_then_read_block(doubly_indirect_blocks_capacity - 1); + + // run test on the first & last triply indirect blocks + write_then_read_block(doubly_indirect_blocks_capacity); + write_then_read_block(triply_indirect_blocks_capacity - 1); +}