1#include "fs/tests/test_internal.h"
2
3TEST_GROUP_DECLARE(tmpfs, .intensity_desc = {
4 .curve = SCALE_PIECEWISE_LOG,
5 .unit = "ops",
6 });
7
8#define TMPFS_SETUP_NODE(root, node, name, e) \
9 struct vfs_node *root = tmpfs_mkroot("tmp"); \
10 TEST_ASSERT_NONNULL(root); \
11 TEST_ASSERT(!ERR_IS_FATAL(root->ops->create(root, name, VFS_MODE_FILE))); \
12 struct vfs_dirent ent; \
13 struct vfs_node *node; \
14 TEST_ASSERT(!ERR_IS_FATAL(root->ops->finddir(root, name, &ent))); \
15 node = ent.node; \
16 TEST_ASSERT_NONNULL(node);
17
18TEST_DECLARE_INTEGRATION(tmpfs, file_lifecycle, TEST_INTENSITY(1, 16, 256)) {
19 size_t ops = ctx->intensity_val ? ctx->intensity_val : 16;
20 const char *lstr = large_test_string;
21 uint64_t len = strlen(str: lstr);
22
23 char *out_buf = kmalloc(len + 1, ALLOC_FLAGS_ZERO);
24 TEST_ASSERT_NONNULL(out_buf);
25
26 for (size_t iter = 0; iter < ops; iter++) {
27 char fname[32];
28 snprintf(buffer: fname, buffer_len: sizeof(fname), format: "place_%zu", iter);
29
30 struct vfs_node *root = tmpfs_mkroot(mount_point: "tmp");
31 TEST_ASSERT_NONNULL(root);
32 TEST_ASSERT(
33 !ERR_IS_FATAL(root->ops->create(root, fname, VFS_MODE_FILE)));
34 struct vfs_dirent ent;
35 struct vfs_node *node;
36 TEST_ASSERT(!ERR_IS_FATAL(root->ops->finddir(root, fname, &ent)));
37 node = ent.node;
38 TEST_ASSERT_NONNULL(node);
39 TEST_ASSERT_EQ(node->size, 0);
40
41 TEST_ASSERT(!ERR_IS_FATAL(node->ops->write(node, lstr, len, 0)));
42 TEST_ASSERT_EQ(node->size, len);
43
44 memset(out_buf, 0, len + 1);
45 TEST_ASSERT(!ERR_IS_FATAL(node->ops->read(node, out_buf, len, 0)));
46 TEST_ASSERT_MEM_EQ(out_buf, lstr, len);
47
48 TEST_ASSERT(!ERR_IS_FATAL(node->ops->truncate(node, len / 2)));
49 TEST_ASSERT_EQ(node->size, len / 2);
50
51 memset(out_buf, 0, len + 1);
52 TEST_ASSERT(!ERR_IS_FATAL(node->ops->read(node, out_buf, len, 0)));
53 TEST_ASSERT(!ERR_IS_FATAL(node->ops->unlink(root, fname)));
54
55 enum errno e = root->ops->finddir(root, fname, &ent);
56 TEST_ASSERT_EQ(e, ERR_NO_ENT);
57
58 TEST_ASSERT_EQ(strlen(out_buf), len / 2);
59 }
60
61 kfree(out_buf);
62 return TEST_SUCCESS;
63}
64
65TEST_DECLARE_INTEGRATION(tmpfs, dir_ops, TEST_INTENSITY(1, 8, 128)) {
66 size_t ops = ctx->intensity_val ? ctx->intensity_val : 8;
67 const char *lstr = large_test_string;
68 uint64_t len = strlen(str: lstr);
69
70 char *out_buf = kmalloc(len + 1, ALLOC_FLAGS_ZERO);
71 TEST_ASSERT_NONNULL(out_buf);
72
73 for (size_t iter = 0; iter < ops; iter++) {
74 char dname[32];
75 snprintf(buffer: dname, buffer_len: sizeof(dname), format: "place_%zu", iter);
76
77 struct vfs_node *root = tmpfs_mkroot(mount_point: "tmp");
78 TEST_ASSERT_NONNULL(root);
79
80 TEST_ASSERT(!ERR_IS_FATAL(root->ops->mkdir(root, dname, VFS_MODE_DIR)));
81
82 struct vfs_dirent ent;
83 struct vfs_node *dir;
84
85 TEST_ASSERT(!ERR_IS_FATAL(root->ops->finddir(root, dname, &ent)));
86
87 dir = ent.node;
88 TEST_ASSERT_NONNULL(dir);
89
90 enum errno e = dir->ops->write(dir, lstr, len, 0);
91 TEST_ASSERT_EQ(e, ERR_IS_DIR);
92
93 e = dir->ops->read(dir, out_buf, len, 0);
94 TEST_ASSERT_EQ(e, ERR_IS_DIR);
95
96 TEST_ASSERT(!ERR_IS_FATAL(dir->ops->rmdir(root, dname)));
97
98 e = root->ops->finddir(root, dname, &ent);
99 TEST_ASSERT_EQ(e, ERR_NO_ENT);
100 }
101
102 kfree(out_buf);
103 return TEST_SUCCESS;
104}
105
106TEST_DECLARE_INTEGRATION(tmpfs, attributes_and_symlinks) {
107 TMPFS_SETUP_NODE(root, node, "place", e);
108
109 TEST_ASSERT(!ERR_IS_FATAL(node->ops->chmod(node, VFS_MODE_EXEC)));
110
111 TEST_ASSERT_EQ(node->mode, VFS_MODE_EXEC);
112
113 TEST_ASSERT(!ERR_IS_FATAL(node->ops->chown(node, 42, 37)));
114
115 TEST_ASSERT_EQ(node->uid, 42);
116 TEST_ASSERT_EQ(node->gid, 37);
117
118 TEST_ASSERT(
119 !ERR_IS_FATAL(root->ops->mkdir(root, "bingbong", VFS_MODE_DIR)));
120 TEST_ASSERT(!ERR_IS_FATAL(root->ops->finddir(root, "bingbong", &ent)));
121
122 node = ent.node;
123 TEST_ASSERT_NONNULL(node);
124
125 TEST_ASSERT(!ERR_IS_FATAL(node->ops->symlink(node, "/tmp", "bang")));
126
127 struct vfs_node *bang;
128 TEST_ASSERT(!ERR_IS_FATAL(node->ops->finddir(node, "bang", &ent)));
129
130 bang = ent.node;
131 TEST_ASSERT_NONNULL(bang);
132
133 char *buf = kmalloc(10, ALLOC_FLAGS_ZERO);
134 TEST_ASSERT_NONNULL(buf);
135
136 TEST_ASSERT(!ERR_IS_FATAL(bang->ops->readlink(bang, buf, 10)));
137
138 TEST_ASSERT_STR_EQ(buf, "/tmp");
139
140 kfree(buf);
141 return TEST_SUCCESS;
142}
143