1 /*
2 * Copyright (c) 2016 Intel Corporation.
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 /*
8 * @filesystem
9 * @brief test_filesystem
10 * Demonstrates the ZEPHYR File System APIs
11 */
12
13 #include "test_fat.h"
14 #include <string.h>
15
test_file_open(const char * path)16 static int test_file_open(const char *path)
17 {
18 int res;
19
20 TC_PRINT("Open tests:\n");
21
22 if (check_file_dir_exists(path)) {
23 TC_PRINT("Opening existing file %s\n", path);
24 } else {
25 TC_PRINT("Creating new file %s\n", path);
26 }
27
28 /* Verify fs_open() */
29 res = fs_open(&filep, path, FS_O_CREATE | FS_O_RDWR);
30 if (res) {
31 TC_PRINT("Failed opening file [%d]\n", res);
32 return res;
33 }
34
35 TC_PRINT("Opened file %s\n", path);
36
37 return res;
38 }
39
test_file_write(void)40 int test_file_write(void)
41 {
42 ssize_t brw;
43 int res;
44
45 TC_PRINT("Write tests:\n");
46
47 /* Verify fs_seek() */
48 res = fs_seek(&filep, 0, FS_SEEK_SET);
49 if (res) {
50 TC_PRINT("fs_seek failed [%d]\n", res);
51 fs_close(&filep);
52 return res;
53 }
54
55 TC_PRINT("Data written:\"%s\"\n\n", test_str);
56
57 /* Verify fs_write() */
58 brw = fs_write(&filep, (char *)test_str, strlen(test_str));
59 if (brw < 0) {
60 TC_PRINT("Failed writing to file [%zd]\n", brw);
61 fs_close(&filep);
62 return brw;
63 }
64
65 if (brw < strlen(test_str)) {
66 TC_PRINT("Unable to complete write. Volume full.\n");
67 TC_PRINT("Number of bytes written: [%zd]\n", brw);
68 fs_close(&filep);
69 return TC_FAIL;
70 }
71
72 TC_PRINT("Data successfully written!\n");
73
74 return res;
75 }
76
test_file_sync(void)77 static int test_file_sync(void)
78 {
79 int res;
80
81 TC_PRINT("Sync tests:\n");
82
83 /* Verify fs_sync() */
84 res = fs_sync(&filep);
85 if (res) {
86 TC_PRINT("Error syncing file [%d]\n", res);
87 return res;
88 }
89
90 return res;
91 }
92
test_file_read(void)93 static int test_file_read(void)
94 {
95 ssize_t brw;
96 int res;
97 char read_buff[80];
98 size_t sz = strlen(test_str);
99
100 TC_PRINT("Read tests:\n");
101
102 res = fs_seek(&filep, 0, FS_SEEK_SET);
103 if (res) {
104 TC_PRINT("fs_seek failed [%d]\n", res);
105 fs_close(&filep);
106 return res;
107 }
108
109 /* Verify fs_read() */
110 brw = fs_read(&filep, read_buff, sz);
111 if (brw < 0) {
112 TC_PRINT("Failed reading file [%zd]\n", brw);
113 fs_close(&filep);
114 return brw;
115 }
116
117 read_buff[brw] = 0;
118
119 TC_PRINT("Data read:\"%s\"\n\n", read_buff);
120
121 if (strcmp(test_str, read_buff)) {
122 TC_PRINT("Error - Data read does not match data written\n");
123 TC_PRINT("Data read:\"%s\"\n\n", read_buff);
124 return TC_FAIL;
125 }
126
127 TC_PRINT("Data read matches data written\n");
128
129 return res;
130 }
131
test_file_truncate(void)132 static int test_file_truncate(void)
133 {
134 int res;
135 off_t orig_pos;
136 char read_buff[80];
137 ssize_t brw;
138
139 TC_PRINT("Truncate tests:\n");
140
141 /* Verify fs_truncate() */
142 /* Test truncating to 0 size */
143 TC_PRINT("Testing shrink to 0 size\n");
144 res = fs_truncate(&filep, 0);
145 if (res) {
146 TC_PRINT("fs_truncate failed [%d]\n", res);
147 fs_close(&filep);
148 return res;
149 }
150
151 res = fs_seek(&filep, 0, FS_SEEK_END);
152 if (res) {
153 TC_PRINT("fs_seek failed after truncating file [%d]\n", res);
154 fs_close(&filep);
155 return res;
156 }
157
158 /* Verify fs_tell() */
159 if (fs_tell(&filep) > 0) {
160 TC_PRINT("Failed truncating to size 0\n");
161 fs_close(&filep);
162 return TC_FAIL;
163 }
164
165 TC_PRINT("Testing write after truncating\n");
166 res = test_file_write();
167 if (res) {
168 TC_PRINT("Write failed after truncating\n");
169 return res;
170 }
171
172 res = fs_seek(&filep, 0, FS_SEEK_END);
173 if (res) {
174 TC_PRINT("fs_seek failed after writing to file [%d]\n", res);
175 fs_close(&filep);
176 return res;
177 }
178
179 orig_pos = fs_tell(&filep);
180 TC_PRINT("Original size of file = %ld\n", (long) orig_pos);
181
182 /* Test shrinking file */
183 TC_PRINT("\nTesting shrinking\n");
184 res = fs_truncate(&filep, orig_pos - 5);
185 if (res) {
186 TC_PRINT("fs_truncate failed [%d]\n", res);
187 fs_close(&filep);
188 return res;
189 }
190
191 res = fs_seek(&filep, 0, FS_SEEK_END);
192 if (res) {
193 TC_PRINT("fs_seek failed after shrinking file [%d]\n", res);
194 fs_close(&filep);
195 return res;
196 }
197
198 TC_PRINT("File size after shrinking by 5 bytes = %ld\n",
199 (long) fs_tell(&filep));
200 if (fs_tell(&filep) != (orig_pos - 5)) {
201 TC_PRINT("File size after fs_truncate not as expected\n");
202 fs_close(&filep);
203 return TC_FAIL;
204 }
205
206 /* Test expanding file */
207 TC_PRINT("Testing expanding\n");
208 res = fs_seek(&filep, 0, FS_SEEK_END);
209 if (res) {
210 TC_PRINT("fs_seek failed before expanding file [%d]\n", res);
211 fs_close(&filep);
212 return res;
213 }
214
215 orig_pos = fs_tell(&filep);
216 res = fs_truncate(&filep, orig_pos + 10);
217 if (res) {
218 TC_PRINT("fs_truncate failed [%d]\n", res);
219 fs_close(&filep);
220 return res;
221 }
222
223 res = fs_seek(&filep, 0, FS_SEEK_END);
224 if (res) {
225 TC_PRINT("fs_seek failed after expanding file [%d]\n", res);
226 fs_close(&filep);
227 return res;
228 }
229
230 TC_PRINT("File size after expanding by 10 bytes = %ld\n",
231 (long) fs_tell(&filep));
232 if (fs_tell(&filep) != (orig_pos + 10)) {
233 TC_PRINT("File size after fs_truncate not as expected\n");
234 fs_close(&filep);
235 return TC_FAIL;
236 }
237
238 /* Check if expanded regions are zeroed */
239 TC_PRINT("Testing for zeroes in expanded region\n");
240 res = fs_seek(&filep, -5, FS_SEEK_END);
241 if (res) {
242 TC_PRINT("fs_seek failed before testing for zeroes [%d]\n",
243 res);
244 fs_close(&filep);
245 return res;
246 }
247
248 brw = fs_read(&filep, read_buff, 5);
249
250 if (brw < 5) {
251 TC_PRINT("Read failed after truncating\n");
252 fs_close(&filep);
253 return -1;
254 }
255
256 for (int i = 0; i < 5; i++) {
257 if (read_buff[i]) {
258 TC_PRINT("Expanded regions are not zeroed\n");
259 fs_close(&filep);
260 return TC_FAIL;
261 }
262 }
263
264 return TC_PASS;
265 }
266
test_file_close(void)267 int test_file_close(void)
268 {
269 int res;
270
271 TC_PRINT("Close tests:\n");
272
273 res = fs_close(&filep);
274 if (res) {
275 TC_PRINT("Error closing file [%d]\n", res);
276 return res;
277 }
278
279 return res;
280 }
281
test_file_delete(const char * path)282 static int test_file_delete(const char *path)
283 {
284 int res;
285
286 TC_PRINT("Delete tests:\n");
287
288 /* Verify fs_unlink() */
289 res = fs_unlink(path);
290 if (res) {
291 TC_PRINT("Error deleting file [%d]\n", res);
292 return res;
293 }
294
295 /* Check if file was deleted */
296 if (check_file_dir_exists(path)) {
297 TC_PRINT("Failed deleting %s\n", path);
298 return TC_FAIL;
299 }
300
301 TC_PRINT("File (%s) deleted successfully!\n", path);
302
303 return res;
304 }
305
ZTEST(fat_fs_dual_drive,test_fat_file)306 ZTEST(fat_fs_dual_drive, test_fat_file)
307 {
308 TC_PRINT("Testing file operations on %s\n", FATFS_MNTP);
309 zassert_true(test_file_open(TEST_FILE) == TC_PASS);
310 zassert_true(test_file_write() == TC_PASS);
311 zassert_true(test_file_sync() == TC_PASS);
312 zassert_true(test_file_read() == TC_PASS);
313 zassert_true(test_file_truncate() == TC_PASS);
314 zassert_true(test_file_close() == TC_PASS);
315 zassert_true(test_file_delete(TEST_FILE) == TC_PASS);
316
317 TC_PRINT("Testing file operations on %s\n", FATFS_MNTP1);
318 zassert_true(test_file_open(TEST_FILE1) == TC_PASS);
319 zassert_true(test_file_write() == TC_PASS);
320 zassert_true(test_file_sync() == TC_PASS);
321 zassert_true(test_file_read() == TC_PASS);
322 zassert_true(test_file_truncate() == TC_PASS);
323 zassert_true(test_file_close() == TC_PASS);
324 zassert_true(test_file_delete(TEST_FILE1) == TC_PASS);
325 }
326