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