1 /*
2 * Copyright (c) 2019 Peter Bigot Consulting, LLC
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 /* Basic littlefs operations:
8 * * create
9 * * write
10 * * stat
11 * * read
12 * * seek
13 * * tell
14 * * truncate
15 * * unlink
16 * * sync
17 */
18
19 #include <string.h>
20 #include <zephyr/ztest.h>
21 #include "testfs_tests.h"
22 #include "testfs_lfs.h"
23 #include <lfs.h>
24
25 #include <zephyr/fs/littlefs.h>
26
mount(struct fs_mount_t * mp)27 static int mount(struct fs_mount_t *mp)
28 {
29 TC_PRINT("mounting %s\n", mp->mnt_point);
30
31 zassert_equal(fs_mount(mp), 0,
32 "mount failed");
33
34 return TC_PASS;
35 }
36
clear_partition(struct fs_mount_t * mp)37 static int clear_partition(struct fs_mount_t *mp)
38 {
39 TC_PRINT("clearing partition %s\n", mp->mnt_point);
40
41 zassert_equal(testfs_lfs_wipe_partition(mp),
42 TC_PASS,
43 "failed to wipe partition");
44
45 return TC_PASS;
46 }
47
clean_statvfs(const struct fs_mount_t * mp)48 static int clean_statvfs(const struct fs_mount_t *mp)
49 {
50 struct fs_statvfs stat;
51
52 TC_PRINT("checking clean statvfs of %s\n", mp->mnt_point);
53
54 zassert_equal(fs_statvfs(mp->mnt_point, &stat), 0,
55 "statvfs failed");
56
57 TC_PRINT("%s: bsize %lu ; frsize %lu ; blocks %lu ; bfree %lu\n",
58 mp->mnt_point,
59 stat.f_bsize, stat.f_frsize, stat.f_blocks, stat.f_bfree);
60 zassert_equal(stat.f_bsize, 16,
61 "bsize fail");
62 zassert_equal(stat.f_frsize, 4096,
63 "frsize fail");
64 zassert_equal(stat.f_blocks, 16,
65 "blocks fail");
66 zassert_equal(stat.f_bfree, stat.f_blocks - 2U,
67 "bfree fail");
68
69 return TC_PASS;
70 }
71
check_medium(void)72 static int check_medium(void)
73 {
74 struct fs_mount_t *mp = &testfs_medium_mnt;
75 struct fs_statvfs stat;
76
77 zassert_equal(clear_partition(mp), TC_PASS,
78 "clear partition failed");
79
80 zassert_equal(fs_mount(mp), 0,
81 "medium mount failed");
82
83 zassert_equal(fs_statvfs(mp->mnt_point, &stat), 0,
84 "statvfs failed");
85
86 TC_PRINT("%s: bsize %lu ; frsize %lu ; blocks %lu ; bfree %lu\n",
87 mp->mnt_point,
88 stat.f_bsize, stat.f_frsize, stat.f_blocks, stat.f_bfree);
89 zassert_equal(stat.f_bsize, MEDIUM_IO_SIZE,
90 "bsize fail");
91 zassert_equal(stat.f_frsize, 4096,
92 "frsize fail");
93 zassert_equal(stat.f_blocks, 240,
94 "blocks fail");
95 zassert_equal(stat.f_bfree, stat.f_blocks - 2U,
96 "bfree fail");
97
98 zassert_equal(fs_unmount(mp), 0,
99 "medium unmount failed");
100
101 return TC_PASS;
102 }
103
check_large(void)104 static int check_large(void)
105 {
106 struct fs_mount_t *mp = &testfs_large_mnt;
107 struct fs_statvfs stat;
108
109 zassert_equal(clear_partition(mp), TC_PASS,
110 "clear partition failed");
111
112 zassert_equal(fs_mount(mp), 0,
113 "large mount failed");
114
115 zassert_equal(fs_statvfs(mp->mnt_point, &stat), 0,
116 "statvfs failed");
117
118 TC_PRINT("%s: bsize %lu ; frsize %lu ; blocks %lu ; bfree %lu\n",
119 mp->mnt_point,
120 stat.f_bsize, stat.f_frsize, stat.f_blocks, stat.f_bfree);
121 zassert_equal(stat.f_bsize, LARGE_IO_SIZE,
122 "bsize fail");
123 zassert_equal(stat.f_frsize, 32768,
124 "frsize fail");
125 zassert_equal(stat.f_blocks, 96,
126 "blocks fail");
127 zassert_equal(stat.f_bfree, stat.f_blocks - 2U,
128 "bfree fail");
129
130 zassert_equal(fs_unmount(mp), 0,
131 "large unmount failed");
132
133 return TC_PASS;
134 }
135
num_files(struct fs_mount_t * mp)136 static int num_files(struct fs_mount_t *mp)
137 {
138 struct testfs_path path;
139 char name[2] = { 0 };
140 const char *pstr;
141 struct fs_file_t files[CONFIG_FS_LITTLEFS_NUM_FILES];
142 size_t fi = 0;
143 int rc;
144
145 memset(files, 0, sizeof(files));
146
147 TC_PRINT("CONFIG_FS_LITTLEFS_NUM_FILES=%u\n", CONFIG_FS_LITTLEFS_NUM_FILES);
148 while (fi < ARRAY_SIZE(files)) {
149 struct fs_file_t *const file = &files[fi];
150
151 name[0] = 'A' + fi;
152 pstr = testfs_path_init(&path, mp,
153 name,
154 TESTFS_PATH_END);
155
156 TC_PRINT("opening %s\n", pstr);
157 rc = fs_open(file, pstr, FS_O_CREATE | FS_O_RDWR);
158 zassert_equal(rc, 0, "open %s failed: %d", pstr, rc);
159
160 rc = testfs_write_incrementing(file, 0, TESTFS_BUFFER_SIZE);
161 zassert_equal(rc, TESTFS_BUFFER_SIZE, "write %s failed: %d", pstr, rc);
162
163 ++fi;
164 }
165
166 while (fi-- != 0) {
167 struct fs_file_t *const file = &files[fi];
168
169 name[0] = 'A' + fi;
170 pstr = testfs_path_init(&path, mp,
171 name,
172 TESTFS_PATH_END);
173
174 TC_PRINT("Close and unlink %s\n", pstr);
175
176 rc = fs_close(file);
177 zassert_equal(rc, 0, "close %s failed: %d", pstr, rc);
178
179 rc = fs_unlink(pstr);
180 zassert_equal(rc, 0, "unlink %s failed: %d", pstr, rc);
181 }
182
183 return TC_PASS;
184 }
185
num_dirs(struct fs_mount_t * mp)186 static int num_dirs(struct fs_mount_t *mp)
187 {
188 struct testfs_path path;
189 char name[3] = "Dx";
190 const char *pstr;
191 struct fs_dir_t dirs[CONFIG_FS_LITTLEFS_NUM_DIRS];
192 size_t di = 0;
193 int rc;
194
195 memset(dirs, 0, sizeof(dirs));
196
197 TC_PRINT("CONFIG_FS_LITTLEFS_NUM_DIRS=%u\n", CONFIG_FS_LITTLEFS_NUM_DIRS);
198 while (di < ARRAY_SIZE(dirs)) {
199 struct fs_dir_t *const dir = &dirs[di];
200
201 name[1] = 'A' + di;
202 pstr = testfs_path_init(&path, mp,
203 name,
204 TESTFS_PATH_END);
205
206 TC_PRINT("making and opening directory %s\n", pstr);
207 rc = fs_mkdir(pstr);
208 zassert_equal(rc, 0, "mkdir %s failed: %d", pstr, rc);
209
210 rc = fs_opendir(dir, pstr);
211 zassert_equal(rc, 0, "opendir %s failed: %d", name, rc);
212
213 ++di;
214 }
215
216 while (di-- != 0) {
217 struct fs_dir_t *const dir = &dirs[di];
218
219 name[1] = 'A' + di;
220 pstr = testfs_path_init(&path, mp,
221 name,
222 TESTFS_PATH_END);
223
224 TC_PRINT("Close and rmdir %s\n", pstr);
225
226 rc = fs_closedir(dir);
227 zassert_equal(rc, 0, "closedir %s failed: %d", name, rc);
228
229 rc = fs_unlink(pstr);
230 zassert_equal(rc, 0, "unlink %s failed: %d", name, rc);
231 }
232
233 return TC_PASS;
234 }
235
236 void test_fs_basic(void);
237
238 /* Mount structure needed by test_fs_basic tests. */
239 struct fs_mount_t *fs_basic_test_mp = &testfs_small_mnt;
240
ZTEST(littlefs,test_lfs_basic)241 ZTEST(littlefs, test_lfs_basic)
242 {
243 struct fs_mount_t *mp = &testfs_small_mnt;
244
245 zassert_equal(clear_partition(mp), TC_PASS,
246 "clear partition failed");
247
248 /* Common basic tests.
249 * (File system is mounted and unmounted during that test.)
250 */
251 test_fs_basic();
252
253 /* LittleFS specific tests */
254
255 zassert_equal(mount(mp), TC_PASS,
256 "clean mount failed");
257
258 zassert_equal(clean_statvfs(mp), TC_PASS,
259 "clean statvfs failed");
260
261 zassert_equal(num_files(mp), TC_PASS,
262 "num_files failed");
263
264 zassert_equal(num_dirs(mp), TC_PASS,
265 "num_dirs failed");
266
267 TC_PRINT("unmounting %s\n", mp->mnt_point);
268 zassert_equal(fs_unmount(mp), 0,
269 "unmount small failed");
270
271 if (IS_ENABLED(CONFIG_APP_TEST_CUSTOM)) {
272 zassert_equal(check_medium(), TC_PASS,
273 "check medium failed");
274
275 zassert_equal(check_large(), TC_PASS,
276 "check large failed");
277 }
278 }
279