1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
|
#include "kernel/filesystem/open_file_description.hpp"
#include "kernel/filesystem/vfs.hpp"
#include "kernel/test_support/filesystem/inode.hpp"
#include "kernel/test_support/filesystem/storage_boot_module_vfs_fixture.hpp"
#include <kstd/memory>
#include <kstd/print>
#include <kstd/vector>
#include <catch2/catch_test_macros.hpp>
#include <cstddef>
#include <filesystem>
#include <string_view>
SCENARIO("Open file description construction", "[filesystem][open_file_description]")
{
GIVEN("an inode and an open file description for that inode")
{
auto inode = kstd::make_shared<kernel::tests::filesystem::inode>();
auto file_description = kernel::filesystem::open_file_description{inode};
THEN("the initial offset is zero")
{
REQUIRE(file_description.offset() == 0);
}
}
}
SCENARIO("Open file description read/write offset management", "[filesystem][open_file_description]")
{
GIVEN("an inode that tracks read/write calls and an open file description for that inode")
{
auto inode = kstd::make_shared<kernel::tests::filesystem::inode>();
auto file_description = kernel::filesystem::open_file_description{inode};
THEN("the offset is updated correctly after reads")
{
REQUIRE(file_description.read(nullptr, 100) == 100);
REQUIRE(file_description.offset() == 100);
REQUIRE(file_description.read(nullptr, 50) == 50);
REQUIRE(file_description.offset() == 150);
}
THEN("the offset is updated correctly after writes")
{
REQUIRE(file_description.write(nullptr, 200) == 200);
REQUIRE(file_description.offset() == 200);
REQUIRE(file_description.write(nullptr, 25) == 25);
REQUIRE(file_description.offset() == 225);
}
THEN("reads and writes both update the same offset")
{
REQUIRE(file_description.read(nullptr, 10) == 10);
REQUIRE(file_description.offset() == 10);
REQUIRE(file_description.write(nullptr, 20) == 20);
REQUIRE(file_description.offset() == 30);
REQUIRE(file_description.read(nullptr, 5) == 5);
REQUIRE(file_description.offset() == 35);
REQUIRE(file_description.write(nullptr, 15) == 15);
REQUIRE(file_description.offset() == 50);
}
}
}
SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture,
"Open file description read with real image", "[filesystem][open_file_description][img]")
{
auto const image_path = std::filesystem::path{KERNEL_TEST_ASSETS_DIR} / "ext2_1KB_fs.img";
GIVEN("an open file description for a file in a real image")
{
REQUIRE(std::filesystem::exists(image_path));
REQUIRE_NOTHROW(setup_modules_from_img_and_init_vfs({"test_img_module"}, {image_path}));
auto & vfs = kernel::filesystem::vfs::get();
auto ofd = vfs.open("/information/info_1.txt");
REQUIRE(ofd != nullptr);
THEN("the file can be read and the offset is updated")
{
kstd::vector<std::byte> buffer(32);
auto bytes_read = ofd->read(buffer.data(), buffer.size());
REQUIRE(bytes_read == 32);
REQUIRE(ofd->offset() == 32);
std::string_view buffer_as_str{reinterpret_cast<char *>(buffer.data()), static_cast<size_t>(bytes_read)};
auto const content_end = buffer_as_str.find('\0');
REQUIRE(buffer_as_str.substr(0, content_end) == "info_1\n");
for (auto i = content_end; i < buffer_as_str.size(); ++i)
{
REQUIRE(buffer_as_str[i] == '\0');
}
}
THEN("the file can be read multiple times")
{
kstd::vector<std::byte> buffer(4);
auto bytes_read_1 = ofd->read(buffer.data(), buffer.size() / 2);
REQUIRE(bytes_read_1 == buffer.size() / 2);
REQUIRE(ofd->offset() == buffer.size() / 2);
auto bytes_read_2 = ofd->read(buffer.data() + buffer.size() / 2, buffer.size() / 2);
REQUIRE(bytes_read_2 == buffer.size() / 2);
REQUIRE(ofd->offset() == buffer.size());
std::string_view buffer_as_str{reinterpret_cast<char *>(buffer.data()), bytes_read_1 + bytes_read_2};
REQUIRE(buffer_as_str == "info");
}
}
}
|