Start to fix some tests.
[bertos.git] / bertos / fs / battfs_test.c
1 /**
2  * \file
3  * <!--
4  * This file is part of BeRTOS.
5  *
6  * Bertos is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19  *
20  * As a special exception, you may use this file as part of a free software
21  * library without restriction.  Specifically, if other files instantiate
22  * templates or use macros or inline functions from this file, or you compile
23  * this file and link it with other files to produce an executable, this
24  * file does not by itself cause the resulting executable to be covered by
25  * the GNU General Public License.  This exception does not however
26  * invalidate any other reasons why the executable file might be covered by
27  * the GNU General Public License.
28  *
29  * Copyright 2007, 2008 Develer S.r.l. (http://www.develer.com/)
30  * -->
31  *
32  * \brief BattFS Test.
33  *
34  * \version $Id$
35  * \author Francesco Sacchi <batt@develer.com>
36  */
37
38 #include <fs/battfs.h>
39
40 #include <cfg/debug.h>
41 #include <cfg/test.h>
42
43 #include <stdio.h>
44 #include <stdlib.h>
45 #include <string.h>
46
47 #define FILE_SIZE 32768
48 #define PAGE_SIZE 128
49 #define PAGE_COUNT FILE_SIZE / PAGE_SIZE
50
51 #if UNIT_TEST
52
53 FILE *fp;
54 const char test_filename[]="battfs_disk.bin";
55
56
57 static bool disk_open(struct BattFsSuper *d)
58 {
59         fp = fopen(test_filename, "r+b");
60         ASSERT(fp);
61         fseek(fp, 0, SEEK_END);
62         d->page_size = PAGE_SIZE;
63         d->page_count = ftell(fp) / d->page_size;
64         d->page_array = malloc(d->page_count * sizeof(pgcnt_t));
65         //TRACEMSG("page_size:%d, page_count:%d\n", d->page_size, d->page_count);
66         return (fp && d->page_array);
67 }
68
69 static size_t disk_page_read(struct BattFsSuper *d, pgcnt_t page, pgaddr_t addr, void *buf, size_t size)
70 {
71         //TRACEMSG("page:%d, addr:%d, size:%d\n", page, addr, size);
72         fseek(fp, page * d->page_size + addr, SEEK_SET);
73         return fread(buf, 1, size, fp);
74 }
75
76 static size_t disk_page_write(struct BattFsSuper *d, pgcnt_t page, pgaddr_t addr, const void *buf, size_t size)
77 {
78         //TRACEMSG("page:%d, addr:%d, size:%d\n", page, addr, size);
79         fseek(fp, page * d->page_size + addr, SEEK_SET);
80         return fwrite(buf, 1, size, fp);
81 }
82
83 static bool disk_page_erase(struct BattFsSuper *d, pgcnt_t page)
84 {
85         //TRACEMSG("page:%d\n", page);
86         fseek(fp, page * d->page_size, SEEK_SET);
87
88         for (int i = 0; i < d->page_size; i++)
89                 if (fputc(0xff, fp) == EOF)
90                         return false;
91         return true;
92 }
93
94 static bool disk_close(struct BattFsSuper *d)
95 {
96         //TRACE;
97         free(d->page_array);
98         return (fclose(fp) != EOF);
99 }
100
101 static void testCheck(BattFsSuper *disk, pgcnt_t *reference)
102 {
103         ASSERT(battfs_init(disk));
104
105         for (int i = 0; i < disk->page_count; i++)
106         {
107                 if (disk->page_array[i] != reference[i])
108                 {
109                         kprintf("Error at addr %d: page_array read", i);
110                         for (pgcnt_t i = 0; i < disk->page_count; i++)
111                         {
112                                 if (!(i % 16))
113                                         kputchar('\n');
114                                 kprintf("%04d ", disk->page_array[i]);
115                         }
116                         kputchar('\n');
117                         kprintf("Expected:");
118                         for (pgcnt_t i = 0; i < disk->page_count; i++)
119                         {
120                                 if (!(i % 16))
121                                         kputchar('\n');
122                                 kprintf("%04d ", reference[i]);
123                         }
124                         kputchar('\n');
125                         battfs_close(disk);
126                         exit(2);
127                 }
128         }
129         battfs_close(disk);
130 }
131
132 static void test1(BattFsSuper *disk)
133 {
134         pgcnt_t ref[PAGE_COUNT];
135         kprintf("Test1: disk new\n");
136
137         FILE *fpt = fopen(test_filename, "w+");
138
139         for (int i = 0; i < FILE_SIZE; i++)
140                 fputc(0xff, fpt);
141         fclose(fpt);
142         for (int i = 0; i < PAGE_COUNT; i++)
143                 ref[i] = i;
144
145         testCheck(disk, ref);
146         kprintf("Test1: passed\n");
147 }
148
149 static void test2(BattFsSuper *disk)
150 {
151         pgcnt_t ref[PAGE_COUNT];
152         kprintf("Test2: disk full with 1 contiguos file\n");
153
154
155         fp = fopen(test_filename, "w+");
156
157         for (int i = 0; i < PAGE_COUNT; i++)
158         {
159                 battfs_writeTestBlock(disk, i, 0, 0, 0, i);
160                 ref[i] = i;
161         }
162         fclose(fp);
163
164         testCheck(disk, ref);
165         kprintf("Test2: passed\n");
166 }
167
168
169 static void test3(BattFsSuper *disk)
170 {
171         pgcnt_t ref[PAGE_COUNT];
172         kprintf("Test3: disk half full with 1 contiguos file, rest unformatted\n");
173
174
175         fp = fopen(test_filename, "w+");
176
177         for (int i = 0; i < PAGE_COUNT / 2; i++)
178         {
179                 battfs_writeTestBlock(disk, i, 0, 0, 0, i);
180                 ref[i] = i;
181         }
182         fseek(fp, FILE_SIZE / 2, SEEK_SET);
183         for (int i = FILE_SIZE / 2; i < FILE_SIZE; i++)
184                 fputc(0xff, fp);
185         fclose(fp);
186
187         for (int i = PAGE_COUNT / 2; i < PAGE_COUNT; i++)
188         {
189                 ref[i] = i;
190         }
191
192
193         testCheck(disk, ref);
194         kprintf("Test3: passed\n");
195 }
196
197 #if 0
198 static void test4(BattFsSuper *disk)
199 {
200         pgcnt_t ref[PAGE_COUNT];
201         kprintf("Test4: disk half full with 1 contiguos file, rest marked free\n");
202
203
204         fp = fopen(test_filename, "w+");
205
206         for (int i = 0; i < PAGE_COUNT / 2; i++)
207         {
208                 battfs_writeTestBlock(disk, i, 0, 0, 0, i);
209                 ref[i] = i;
210         }
211         for (int i = PAGE_COUNT / 2; i < PAGE_COUNT; i++)
212         {
213                 battfs_writeTestBlock(disk, i, 0, 0, 0, i);
214                 ref[i] = i;
215         }
216         fclose(fp);
217
218
219         testCheck(disk, ref);
220         kprintf("Test4: passed\n");
221 }
222
223 static void test5(BattFsSuper *disk)
224 {
225         pgcnt_t ref[PAGE_COUNT];
226         kprintf("Test5: disk 1/3 full with 1 contiguos file, 1/3 marked free, rest unformatted\n");
227
228
229         fp = fopen(test_filename, "w+");
230
231         for (int i = 0; i < FILE_SIZE; i++)
232                 fputc(0xff, fp);
233
234         for (int i = 0; i < PAGE_COUNT / 3; i++)
235         {
236                 battfs_writeTestBlock(disk, i, 0, 0, 0, i);
237                 ref[i] = i;
238         }
239         for (int i = PAGE_COUNT / 3; i < 2 * (PAGE_COUNT / 3); i++)
240         {
241                 battfs_writeTestBlock(disk, i, 0, 0, 0, i);
242                 ref[i + PAGE_COUNT / 3 + 1] = i;
243         }
244         fclose(fp);
245
246         for (int i = PAGE_COUNT / 3; i < 2 * (PAGE_COUNT / 3) + 1; i++)
247                 ref[i] = PAGE_COUNT + PAGE_COUNT / 3 - i - 1;
248
249         testCheck(disk, ref);
250         kprintf("Test5: passed\n");
251 }
252 #endif
253
254 static void test6(BattFsSuper *disk)
255 {
256         pgcnt_t ref[4];
257         kprintf("Test6: 1 file with 1 old seq num, 1 free block\n");
258
259
260         fp = fopen(test_filename, "w+");
261
262         battfs_writeTestBlock(disk, 0, 0, 0, 0, 0);
263         battfs_writeTestBlock(disk, 1, 0, 0, 0, 1);
264         battfs_writeTestBlock(disk, 2, 0, 1, 0, 1);
265         disk->erase(disk, 3);
266
267
268         fclose(fp);
269         ref[0] = 0;
270         ref[1] = 2;
271         ref[2] = 3;
272         ref[3] = 1;
273
274         testCheck(disk, ref);
275         kprintf("Test6: passed\n");
276 }
277
278 static void test7(BattFsSuper *disk)
279 {
280         pgcnt_t ref[4];
281         kprintf("Test7: 1 file with 1 old seq num, 1 free block\n");
282
283
284         fp = fopen(test_filename, "w+");
285
286         battfs_writeTestBlock(disk, 0, 0, 0, 0, 0);
287         battfs_writeTestBlock(disk, 1, 0, 1, 0, 1);
288         battfs_writeTestBlock(disk, 2, 0, 0, 0, 1);
289         battfs_writeTestBlock(disk, 3, 0, 0, 0, 0);
290
291         fclose(fp);
292         ref[0] = 0;
293         ref[1] = 1;
294         ref[2] = 3;
295         ref[3] = 2;
296
297         testCheck(disk, ref);
298         kprintf("Test7: passed\n");
299 }
300
301 static void test8(BattFsSuper *disk)
302 {
303         pgcnt_t ref[4];
304         kprintf("Test8: 1 file with 1 old seq num, 1 free block\n");
305
306
307         fp = fopen(test_filename, "w+");
308
309         battfs_writeTestBlock(disk, 0, 0, 0, 0, 0);
310         battfs_writeTestBlock(disk, 1, 0, 0, 0, 0);
311         battfs_writeTestBlock(disk, 2, 0, 1, 0, 1);
312         battfs_writeTestBlock(disk, 3, 0, 0, 0, 1);
313
314
315         fclose(fp);
316         ref[0] = 1;
317         ref[1] = 2;
318         ref[2] = 0;
319         ref[3] = 3;
320
321         testCheck(disk, ref);
322         kprintf("Test8: passed\n");
323 }
324
325 static void test9(BattFsSuper *disk)
326 {
327         pgcnt_t ref[8];
328         kprintf("Test9: 2 file with old seq num, 2 free block\n");
329
330
331         fp = fopen(test_filename, "w+");
332
333         battfs_writeTestBlock(disk, 0, 0, 0, 0, 0);
334         battfs_writeTestBlock(disk, 1, 0, 0, 0, 0);
335         battfs_writeTestBlock(disk, 2, 0, 3, 0, 1);
336         battfs_writeTestBlock(disk, 3, 0, 0, 0, 1);
337         battfs_writeTestBlock(disk, 4, 0, 0, 0, 0);
338         battfs_writeTestBlock(disk, 5, 4, 0, 0, 0);
339         battfs_writeTestBlock(disk, 6, 4, 1, 0, 1);
340         battfs_writeTestBlock(disk, 7, 4, 0, 0, 1);
341
342
343         fclose(fp);
344         ref[0] = 1;
345         ref[1] = 3;
346         ref[2] = 5;
347         ref[3] = 6;
348         ref[4] = 0;
349         ref[5] = 4;
350         ref[6] = 2;
351         ref[7] = 7;
352
353         testCheck(disk, ref);
354         kprintf("Test9: passed\n");
355 }
356
357 static void test10(BattFsSuper *disk)
358 {
359         BattFs fd1;
360         BattFs fd2;
361         kprintf("Test10: open file test, inode 0 and inode 4\n");
362
363         fp = fopen(test_filename, "w+");
364
365         int PAGE_FILL = 116;
366         unsigned int INODE = 0;
367         unsigned int INODE2 = 4;
368         unsigned int INEXISTENT_INODE = 123;
369         unsigned int MODE = 0;
370
371         battfs_writeTestBlock(disk, 0, 123, 0, PAGE_FILL, 0);
372         battfs_writeTestBlock(disk, 1, INODE, 0, PAGE_FILL, 0);
373         battfs_writeTestBlock(disk, 2, INODE, 3, PAGE_FILL, 1);
374         battfs_writeTestBlock(disk, 3, INODE, 0, PAGE_FILL, 1);
375         battfs_writeTestBlock(disk, 4, INODE2, 0, PAGE_FILL, 0);
376         battfs_writeTestBlock(disk, 5, INODE2, 0, PAGE_FILL, 0);
377         battfs_writeTestBlock(disk, 6, INODE2, 1, PAGE_FILL, 1);
378         battfs_writeTestBlock(disk, 7, INODE2, 0, PAGE_FILL, 1);
379
380         fclose(fp);
381
382         ASSERT(battfs_init(disk));
383         ASSERT(!battfs_fileExists(disk, INEXISTENT_INODE));
384
385         ASSERT(battfs_fileExists(disk, INODE));
386         ASSERT(battfs_fileopen(disk, &fd1, INODE, MODE));
387         ASSERT(fd1.fd.size == PAGE_FILL * 2);
388         ASSERT(fd1.fd.seek_pos == 0);
389         ASSERT(fd1.mode == MODE);
390         ASSERT(fd1.inode == INODE);
391         ASSERT(fd1.start == &disk->page_array[0]);
392         ASSERT(fd1.disk == disk);
393         ASSERT(LIST_HEAD(&disk->file_opened_list) == &fd1.link);
394
395         ASSERT(kfile_reopen(&fd1.fd) == &fd1.fd);
396         ASSERT(fd1.fd.size == PAGE_FILL * 2);
397         ASSERT(fd1.fd.seek_pos == 0);
398         ASSERT(fd1.mode == MODE);
399         ASSERT(fd1.inode == INODE);
400         ASSERT(fd1.start == &disk->page_array[0]);
401         ASSERT(fd1.disk == disk);
402         ASSERT(LIST_HEAD(&disk->file_opened_list) == &fd1.link);
403
404         ASSERT(battfs_fileExists(disk, INODE2));
405         ASSERT(battfs_fileopen(disk, &fd2, INODE2, MODE));
406         ASSERT(fd2.fd.size == PAGE_FILL * 2);
407         ASSERT(fd2.fd.seek_pos == 0);
408         ASSERT(fd2.mode == MODE);
409         ASSERT(fd2.inode == INODE2);
410         ASSERT(fd2.start == &disk->page_array[2]);
411         ASSERT(fd2.disk == disk);
412         ASSERT(LIST_HEAD(&disk->file_opened_list)->succ == &fd2.link);
413
414         ASSERT(kfile_close(&fd1.fd) == 0);
415         ASSERT(kfile_close(&fd2.fd) == 0);
416         ASSERT(LIST_EMPTY(&disk->file_opened_list));
417         ASSERT(battfs_close(disk));
418
419         kprintf("Test10: passed\n");
420 }
421
422 static void test11(BattFsSuper *disk)
423 {
424         BattFs fd1;
425         uint8_t buf[16];
426
427         kprintf("Test11: read file test\n");
428
429         fp = fopen(test_filename, "w+");
430
431         unsigned int PAGE_FILL = 116;
432         unsigned int INODE = 0;
433         unsigned int INODE2 = 4;
434         unsigned int MODE = 0;
435
436         battfs_writeTestBlock(disk, 0, 123, 0, PAGE_FILL, 0);
437         battfs_writeTestBlock(disk, 1, INODE, 0, PAGE_FILL, 0);
438         battfs_writeTestBlock(disk, 2, INODE, 3, PAGE_FILL, 1);
439         battfs_writeTestBlock(disk, 3, INODE, 0, PAGE_FILL, 1);
440         battfs_writeTestBlock(disk, 4, INODE2, 0, PAGE_FILL, 0);
441         battfs_writeTestBlock(disk, 5, INODE2, 0, PAGE_FILL, 0);
442         battfs_writeTestBlock(disk, 6, INODE2, 1, PAGE_FILL, 1);
443         battfs_writeTestBlock(disk, 7, INODE2, 0, PAGE_FILL, 1);
444
445         fclose(fp);
446
447         ASSERT(battfs_init(disk));
448         ASSERT(battfs_fileopen(disk, &fd1, INODE, MODE));
449         ASSERT(kfile_read(&fd1.fd, buf, sizeof(buf)) == sizeof(buf));
450         ASSERT(fd1.fd.seek_pos == sizeof(buf));
451         for (size_t i = 0; i < sizeof(buf); i++)
452                 ASSERT(buf[i] == 0);
453
454         ASSERT(kfile_close(&fd1.fd) == 0);
455         ASSERT(battfs_close(disk));
456
457         kprintf("Test11: passed\n");
458 }
459
460 static void test12(BattFsSuper *disk)
461 {
462         BattFs fd1;
463
464         kprintf("Test12: read file test across page boundary and seek test\n");
465
466         fp = fopen(test_filename, "w+");
467
468         const unsigned int PAGE_FILL = 116;
469         unsigned int INODE = 0;
470         unsigned int MODE = 0;
471         uint8_t buf[PAGE_FILL + 10];
472
473         battfs_writeTestBlock(disk, 0, 123, 0, PAGE_FILL, 0);
474         battfs_writeTestBlock(disk, 1, INODE, 0, PAGE_FILL, 0);
475         battfs_writeTestBlock(disk, 2, INODE, 3, PAGE_FILL, 1);
476         battfs_writeTestBlock(disk, 3, INODE, 0, PAGE_FILL, 1);
477         battfs_writeTestBlock(disk, 4, INODE, 0, PAGE_FILL, 0);
478         battfs_writeTestBlock(disk, 5, INODE, 0, PAGE_FILL, 2);
479         battfs_writeTestBlock(disk, 6, INODE, 1, PAGE_FILL, 3);
480         battfs_writeTestBlock(disk, 7, INODE, 0, PAGE_FILL, 3);
481
482         fclose(fp);
483
484         ASSERT(battfs_init(disk));
485         ASSERT(battfs_fileopen(disk, &fd1, INODE, MODE));
486
487         ASSERT(kfile_read(&fd1.fd, buf, sizeof(buf)) == sizeof(buf));
488         ASSERT(fd1.fd.seek_pos == (kfile_off_t)sizeof(buf));
489         for (size_t i = 0; i < sizeof(buf); i++)
490                 ASSERT(buf[i] == 0);
491
492         ASSERT(kfile_read(&fd1.fd, buf, sizeof(buf)) == sizeof(buf));
493         ASSERT(fd1.fd.seek_pos == (kfile_off_t)sizeof(buf) * 2);
494         for (size_t i = 0; i < sizeof(buf); i++)
495                 ASSERT(buf[i] == 0);
496
497         ASSERT(kfile_read(&fd1.fd, buf, sizeof(buf)) == sizeof(buf));
498         ASSERT(fd1.fd.seek_pos == (kfile_off_t)sizeof(buf) * 3);
499         for (size_t i = 0; i < sizeof(buf); i++)
500                 ASSERT(buf[i] == 0);
501
502         ASSERT(kfile_read(&fd1.fd, buf, sizeof(buf)) == 86);
503         ASSERT(fd1.fd.seek_pos == (kfile_off_t)fd1.fd.size);
504         for (size_t i = 0; i < 86; i++)
505                 ASSERT(buf[i] == 0);
506
507         ASSERT(kfile_seek(&fd1.fd, 0, KSM_SEEK_SET) == 0);
508         ASSERT(fd1.fd.seek_pos == 0);
509
510         ASSERT(kfile_seek(&fd1.fd, 0, KSM_SEEK_END) == (kfile_off_t)fd1.fd.size);
511         ASSERT(fd1.fd.seek_pos = (kfile_off_t)fd1.fd.size);
512
513         ASSERT(kfile_close(&fd1.fd) == 0);
514         ASSERT(battfs_close(disk));
515
516         kprintf("Test12: passed\n");
517 }
518
519
520 int battfs_testRun(void)
521 {
522         BattFsSuper disk;
523
524         disk.open = disk_open;
525         disk.read = disk_page_read;
526         disk.write = disk_page_write;
527         disk.erase = disk_page_erase;
528         disk.close = disk_close;
529         test1(&disk);
530         test2(&disk);
531         test3(&disk);
532         //test4(&disk);
533         //test5(&disk);
534         test6(&disk);
535         test7(&disk);
536         test8(&disk);
537         test9(&disk);
538         test10(&disk);
539         test11(&disk);
540         test12(&disk);
541         kprintf("All tests passed!\n");
542
543         return 0;
544 }
545
546 int battfs_testSetup(void)
547 {
548         return 0;
549 }
550
551 int battfs_testTearDown(void)
552 {
553         return 0;
554 }
555
556 TEST_MAIN(battfs)
557
558 #include <fs/battfs.c>
559 #include <kern/kfile.c>
560 #include <drv/kdebug.c>
561 #include <mware/formatwr.c>
562 #include <mware/hex.c>
563
564 #endif // _TEST