Fix warnings.
[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 static uint8_t page_buffer[PAGE_SIZE];
57
58 static bool disk_open(struct BattFsSuper *d)
59 {
60         fp = fopen(test_filename, "r+b");
61         ASSERT(fp);
62         fseek(fp, 0, SEEK_END);
63         d->page_size = PAGE_SIZE;
64         d->page_count = ftell(fp) / d->page_size;
65         d->page_array = malloc(d->page_count * sizeof(pgcnt_t));
66         //TRACEMSG("page_size:%d, page_count:%d\n", d->page_size, d->page_count);
67         return (fp && d->page_array);
68 }
69
70 static size_t disk_page_read(struct BattFsSuper *d, pgcnt_t page, pgaddr_t addr, void *buf, size_t size)
71 {
72         //TRACEMSG("page:%d, addr:%d, size:%d", page, addr, size);
73         fseek(fp, page * d->page_size + addr, SEEK_SET);
74         return fread(buf, 1, size, fp);
75 }
76
77 static size_t disk_buffer_write(struct BattFsSuper *d, pgaddr_t addr, const void *buf, size_t size)
78 {
79         //TRACEMSG("addr:%d, size:%d", addr, size);
80         ASSERT(addr + size <= d->page_size);
81         memcpy(&page_buffer[addr], buf, size);
82
83         return size;
84 }
85
86 static size_t disk_buffer_read(struct BattFsSuper *d, pgaddr_t addr, void *buf, size_t size)
87 {
88         //TRACEMSG("addr:%d, size:%d", addr, size);
89         ASSERT(addr + size <= d->page_size);
90         memcpy(buf, &page_buffer[addr], size);
91
92         return size;
93 }
94
95 static bool disk_page_load(struct BattFsSuper *d, pgcnt_t page)
96 {
97         //TRACEMSG("page:%d", page);
98         fseek(fp, page * d->page_size, SEEK_SET);
99         return fread(page_buffer, 1, d->page_size, fp) == d->page_size;
100 }
101
102 static bool disk_page_save(struct BattFsSuper *d, pgcnt_t page)
103 {
104         //TRACEMSG("page:%d", page);
105         fseek(fp, page * d->page_size, SEEK_SET);
106         return fwrite(page_buffer, 1, d->page_size, fp) == d->page_size;
107 }
108
109 static bool disk_page_erase(struct BattFsSuper *d, pgcnt_t page)
110 {
111         //TRACEMSG("page:%d", page);
112         fseek(fp, page * d->page_size, SEEK_SET);
113
114         for (int i = 0; i < d->page_size; i++)
115                 if (fputc(0xff, fp) == EOF)
116                         return false;
117         return true;
118 }
119
120 static bool disk_close(struct BattFsSuper *d)
121 {
122         //TRACE;
123         free(d->page_array);
124         return (fclose(fp) != EOF);
125 }
126
127 static void testCheck(BattFsSuper *disk, pgcnt_t *reference)
128 {
129         ASSERT(battfs_init(disk));
130         ASSERT(battfs_fsck(disk));
131
132         for (int i = 0; i < disk->page_count; i++)
133         {
134                 if (disk->page_array[i] != reference[i])
135                 {
136                         kprintf("Error at addr %d: page_array read", i);
137                         for (pgcnt_t i = 0; i < disk->page_count; i++)
138                         {
139                                 if (!(i % 16))
140                                         kputchar('\n');
141                                 kprintf("%04d ", disk->page_array[i]);
142                         }
143                         kputchar('\n');
144                         kprintf("Expected:");
145                         for (pgcnt_t i = 0; i < disk->page_count; i++)
146                         {
147                                 if (!(i % 16))
148                                         kputchar('\n');
149                                 kprintf("%04d ", reference[i]);
150                         }
151                         kputchar('\n');
152                         battfs_close(disk);
153                         exit(2);
154                 }
155         }
156         ASSERT(battfs_fsck(disk));
157         battfs_close(disk);
158 }
159
160 static void diskNew(BattFsSuper *disk)
161 {
162         pgcnt_t ref[PAGE_COUNT];
163         TRACEMSG("1: disk new\n");
164
165         FILE *fpt = fopen(test_filename, "w+");
166
167         for (int i = 0; i < FILE_SIZE; i++)
168                 fputc(0xff, fpt);
169         fclose(fpt);
170         for (int i = 0; i < PAGE_COUNT; i++)
171                 ref[i] = i;
172
173         testCheck(disk, ref);
174         TRACEMSG("1: passed\n");
175 }
176
177 static void disk1File(BattFsSuper *disk)
178 {
179         pgcnt_t ref[PAGE_COUNT];
180         TRACEMSG("2: disk full with 1 contiguos file\n");
181
182
183         fp = fopen(test_filename, "w+");
184
185         for (int i = 0; i < PAGE_COUNT; i++)
186         {
187                 battfs_writeTestBlock(disk, i, 0, 0, disk->data_size, i);
188                 ref[i] = i;
189         }
190         fclose(fp);
191
192         testCheck(disk, ref);
193         TRACEMSG("2: passed\n");
194 }
195
196
197 static void diskHalfFile(BattFsSuper *disk)
198 {
199         pgcnt_t ref[PAGE_COUNT];
200         TRACEMSG("3: disk half full with 1 contiguos file, rest unformatted\n");
201
202
203         fp = fopen(test_filename, "w+");
204
205         for (int i = 0; i < PAGE_COUNT / 2; i++)
206         {
207                 battfs_writeTestBlock(disk, i, 0, 0, disk->data_size, i);
208                 ref[i] = i;
209         }
210         fseek(fp, FILE_SIZE / 2, SEEK_SET);
211         for (int i = FILE_SIZE / 2; i < FILE_SIZE; i++)
212                 fputc(0xff, fp);
213         fclose(fp);
214
215         for (int i = PAGE_COUNT / 2; i < PAGE_COUNT; i++)
216         {
217                 ref[i] = i;
218         }
219
220
221         testCheck(disk, ref);
222         TRACEMSG("3: passed\n");
223 }
224
225
226 static void oldSeq1(BattFsSuper *disk)
227 {
228         pgcnt_t ref[4];
229         TRACEMSG("6: 1 file with 1 old seq num, 1 free block\n");
230
231
232         fp = fopen(test_filename, "w+");
233         // page, inode, seq, fill, pgoff
234         battfs_writeTestBlock(disk, 0, 0, 0, disk->data_size, 0);
235         battfs_writeTestBlock(disk, 1, 0, 0, disk->data_size, 1);
236         battfs_writeTestBlock(disk, 2, 0, 1, disk->data_size, 1);
237         disk->erase(disk, 3);
238
239
240         fclose(fp);
241         ref[0] = 0;
242         ref[1] = 2;
243         ref[2] = 1;
244         ref[3] = 3;
245
246         testCheck(disk, ref);
247         TRACEMSG("6: passed\n");
248 }
249
250 static void oldSeq2(BattFsSuper *disk)
251 {
252         pgcnt_t ref[4];
253         TRACEMSG("7: 1 file with 1 old seq num, 1 free block\n");
254
255
256         fp = fopen(test_filename, "w+");
257         // page, inode, seq, fill, pgoff
258         battfs_writeTestBlock(disk, 0, 0, 0, disk->data_size, 0);
259         battfs_writeTestBlock(disk, 1, 0, 1, disk->data_size, 1);
260         battfs_writeTestBlock(disk, 2, 0, 0, disk->data_size, 1);
261         disk->erase(disk, 3);
262
263         fclose(fp);
264         ref[0] = 0;
265         ref[1] = 1;
266         ref[2] = 2;
267         ref[3] = 3;
268
269         testCheck(disk, ref);
270         TRACEMSG("7: passed\n");
271 }
272
273 static void oldSeq3(BattFsSuper *disk)
274 {
275         pgcnt_t ref[4];
276         TRACEMSG("8: 1 file with 1 old seq num, 1 free block\n");
277
278
279         fp = fopen(test_filename, "w+");
280
281         // page, inode, seq, fill, pgoff
282         disk->erase(disk, 0);
283         battfs_writeTestBlock(disk, 1, 0, 0, disk->data_size, 0);
284         battfs_writeTestBlock(disk, 2, 0, 1, disk->data_size, 1);
285         battfs_writeTestBlock(disk, 3, 0, 0, disk->data_size, 1);
286
287
288         fclose(fp);
289         ref[0] = 1;
290         ref[1] = 2;
291         ref[2] = 0;
292         ref[3] = 3;
293
294         testCheck(disk, ref);
295         TRACEMSG("8: passed\n");
296 }
297
298 static void oldSeq2File(BattFsSuper *disk)
299 {
300         pgcnt_t ref[8];
301         TRACEMSG("9: 2 file with old seq num, 2 free block\n");
302
303
304         fp = fopen(test_filename, "w+");
305
306         // page, inode, seq, fill, pgoff
307         disk->erase(disk, 0);
308         battfs_writeTestBlock(disk, 1, 0, 0, disk->data_size, 0);
309         battfs_writeTestBlock(disk, 2, 0, 3, disk->data_size, 1);
310         battfs_writeTestBlock(disk, 3, 0, 0, disk->data_size, 1);
311         disk->erase(disk, 4);
312         battfs_writeTestBlock(disk, 5, 4, 0, disk->data_size, 0);
313         battfs_writeTestBlock(disk, 6, 4, 1, disk->data_size, 1);
314         battfs_writeTestBlock(disk, 7, 4, 0, disk->data_size, 1);
315
316
317         fclose(fp);
318         ref[0] = 1;
319         ref[1] = 2;
320         ref[2] = 5;
321         ref[3] = 6;
322         ref[4] = 0;
323         ref[5] = 3;
324         ref[6] = 4;
325         ref[7] = 7;
326
327         testCheck(disk, ref);
328         TRACEMSG("9: passed\n");
329 }
330
331 static void openFile(BattFsSuper *disk)
332 {
333         BattFs fd1;
334         BattFs fd2;
335         TRACEMSG("10: open file test, inode 0 and inode 4\n");
336
337         fp = fopen(test_filename, "w+");
338
339         int PAGE_FILL = PAGE_SIZE - BATTFS_HEADER_LEN;
340         inode_t INODE = 0;
341         inode_t INODE2 = 4;
342         inode_t INEXISTENT_INODE = 123;
343         unsigned int MODE = 0;
344
345         // page, inode, seq, fill, pgoff
346         disk->erase(disk, 0);
347         battfs_writeTestBlock(disk, 1, INODE, 0, PAGE_FILL, 0);
348         battfs_writeTestBlock(disk, 2, INODE, 3, PAGE_FILL, 1);
349         battfs_writeTestBlock(disk, 3, INODE, 0, PAGE_FILL, 1);
350         disk->erase(disk, 4);
351         battfs_writeTestBlock(disk, 5, INODE2, 0, PAGE_FILL, 0);
352         battfs_writeTestBlock(disk, 6, INODE2, 1, PAGE_FILL, 1);
353         battfs_writeTestBlock(disk, 7, INODE2, 0, PAGE_FILL, 1);
354
355         fclose(fp);
356
357         ASSERT(battfs_init(disk));
358         ASSERT(battfs_fsck(disk));
359         ASSERT(!battfs_fileExists(disk, INEXISTENT_INODE));
360
361         ASSERT(battfs_fileExists(disk, INODE));
362         ASSERT(battfs_fileopen(disk, &fd1, INODE, MODE));
363         ASSERT(fd1.fd.size == PAGE_FILL * 2);
364         ASSERT(fd1.fd.seek_pos == 0);
365         ASSERT(fd1.mode == MODE);
366         ASSERT(fd1.inode == INODE);
367         ASSERT(fd1.start == &disk->page_array[0]);
368         ASSERT(fd1.disk == disk);
369         ASSERT(LIST_HEAD(&disk->file_opened_list) == &fd1.link);
370
371         ASSERT(kfile_reopen(&fd1.fd) == &fd1.fd);
372         ASSERT(fd1.fd.size == PAGE_FILL * 2);
373         ASSERT(fd1.fd.seek_pos == 0);
374         ASSERT(fd1.mode == MODE);
375         ASSERT(fd1.inode == INODE);
376         ASSERT(fd1.start == &disk->page_array[0]);
377         ASSERT(fd1.disk == disk);
378         ASSERT(LIST_HEAD(&disk->file_opened_list) == &fd1.link);
379
380         ASSERT(battfs_fileExists(disk, INODE2));
381         ASSERT(battfs_fileopen(disk, &fd2, INODE2, MODE));
382         ASSERT(fd2.fd.size == PAGE_FILL * 2);
383         ASSERT(fd2.fd.seek_pos == 0);
384         ASSERT(fd2.mode == MODE);
385         ASSERT(fd2.inode == INODE2);
386         ASSERT(fd2.start == &disk->page_array[2]);
387         ASSERT(fd2.disk == disk);
388         ASSERT(LIST_HEAD(&disk->file_opened_list)->succ == &fd2.link);
389
390         ASSERT(kfile_close(&fd1.fd) == 0);
391         ASSERT(kfile_close(&fd2.fd) == 0);
392         ASSERT(LIST_EMPTY(&disk->file_opened_list));
393         ASSERT(battfs_fsck(disk));
394         ASSERT(battfs_close(disk));
395
396         TRACEMSG("10: passed\n");
397 }
398
399 static void readFile(BattFsSuper *disk)
400 {
401         BattFs fd1;
402         uint8_t buf[16];
403
404         TRACEMSG("11: read file test\n");
405
406         fp = fopen(test_filename, "w+");
407
408         unsigned int PAGE_FILL = PAGE_SIZE - BATTFS_HEADER_LEN;
409         inode_t INODE = 0;
410         inode_t INODE2 = 4;
411         unsigned int MODE = 0;
412
413         disk->erase(disk, 0);
414         battfs_writeTestBlock(disk, 1, INODE, 0, PAGE_FILL, 0);
415         battfs_writeTestBlock(disk, 2, INODE, 3, PAGE_FILL, 1);
416         battfs_writeTestBlock(disk, 3, INODE, 0, PAGE_FILL, 1);
417         disk->erase(disk, 4);
418         battfs_writeTestBlock(disk, 5, INODE2, 0, PAGE_FILL, 0);
419         battfs_writeTestBlock(disk, 6, INODE2, 1, PAGE_FILL, 1);
420         battfs_writeTestBlock(disk, 7, INODE2, 0, PAGE_FILL, 1);
421
422         fclose(fp);
423
424         ASSERT(battfs_init(disk));
425         ASSERT(battfs_fsck(disk));
426         ASSERT(battfs_fileopen(disk, &fd1, INODE, MODE));
427         ASSERT(kfile_read(&fd1.fd, buf, sizeof(buf)) == sizeof(buf));
428         ASSERT(fd1.fd.seek_pos == sizeof(buf));
429         for (size_t i = 0; i < sizeof(buf); i++)
430                 ASSERT(buf[i] == 0xff);
431
432         ASSERT(kfile_close(&fd1.fd) == 0);
433         ASSERT(battfs_fsck(disk));
434         ASSERT(battfs_close(disk));
435
436         TRACEMSG("11: passed\n");
437 }
438
439 static void readAcross(BattFsSuper *disk)
440 {
441         BattFs fd1;
442
443         TRACEMSG("12: read file test across page boundary and seek test\n");
444
445         fp = fopen(test_filename, "w+");
446
447         const unsigned int PAGE_FILL = PAGE_SIZE - BATTFS_HEADER_LEN;
448         inode_t INODE = 0;
449         unsigned int MODE = 0;
450         uint8_t buf[PAGE_FILL + BATTFS_HEADER_LEN / 2];
451
452         disk->erase(disk, 0);
453         battfs_writeTestBlock(disk, 1, INODE, 0, PAGE_FILL, 0);
454         battfs_writeTestBlock(disk, 2, INODE, 3, PAGE_FILL, 1);
455         battfs_writeTestBlock(disk, 3, INODE, 0, PAGE_FILL, 1);
456         disk->erase(disk, 4);
457         battfs_writeTestBlock(disk, 5, INODE, 0, PAGE_FILL, 2);
458         battfs_writeTestBlock(disk, 6, INODE, 1, PAGE_FILL, 3);
459         battfs_writeTestBlock(disk, 7, INODE, 0, PAGE_FILL, 3);
460
461         fclose(fp);
462
463         ASSERT(battfs_init(disk));
464         ASSERT(battfs_fsck(disk));
465         ASSERT(battfs_fileopen(disk, &fd1, INODE, MODE));
466
467         ASSERT(kfile_read(&fd1.fd, buf, sizeof(buf)) == sizeof(buf));
468         ASSERT(fd1.fd.seek_pos == (kfile_off_t)sizeof(buf));
469         for (size_t i = 0; i < sizeof(buf); i++)
470                 ASSERT(buf[i] == 0xff);
471
472         ASSERT(kfile_read(&fd1.fd, buf, sizeof(buf)) == sizeof(buf));
473         ASSERT(fd1.fd.seek_pos == (kfile_off_t)sizeof(buf) * 2);
474         for (size_t i = 0; i < sizeof(buf); i++)
475                 ASSERT(buf[i] == 0xff);
476
477         ASSERT(kfile_read(&fd1.fd, buf, sizeof(buf)) == sizeof(buf));
478         ASSERT(fd1.fd.seek_pos == (kfile_off_t)sizeof(buf) * 3);
479         for (size_t i = 0; i < sizeof(buf); i++)
480                 ASSERT(buf[i] == 0xff);
481
482         ASSERT(kfile_read(&fd1.fd, buf, sizeof(buf)) == PAGE_FILL * 4 - sizeof(buf) * 3);
483         ASSERT(fd1.fd.seek_pos == (kfile_off_t)fd1.fd.size);
484         for (size_t i = 0; i < PAGE_FILL * 4 - sizeof(buf) * 3; i++)
485                 ASSERT(buf[i] == 0xff);
486
487         ASSERT(kfile_seek(&fd1.fd, 0, KSM_SEEK_SET) == 0);
488         ASSERT(fd1.fd.seek_pos == 0);
489
490         ASSERT(kfile_seek(&fd1.fd, 0, KSM_SEEK_END) == (kfile_off_t)fd1.fd.size);
491         ASSERT(fd1.fd.seek_pos = (kfile_off_t)fd1.fd.size);
492
493         ASSERT(kfile_close(&fd1.fd) == 0);
494         ASSERT(battfs_fsck(disk));
495         ASSERT(battfs_close(disk));
496
497         TRACEMSG("12: passed\n");
498 }
499
500
501 static void writeFile(BattFsSuper *disk)
502 {
503         BattFs fd1;
504         uint8_t buf[PAGE_SIZE - BATTFS_HEADER_LEN];
505
506         TRACEMSG("13: write file test\n");
507
508         fp = fopen(test_filename, "w+");
509
510         unsigned int PAGE_FILL = PAGE_SIZE - BATTFS_HEADER_LEN;
511         inode_t INODE = 0;
512         inode_t INODE2 = 4;
513         unsigned int MODE = 0;
514
515         disk->erase(disk, 0);
516         battfs_writeTestBlock(disk, 1, INODE, 0, PAGE_FILL, 0);
517         battfs_writeTestBlock(disk, 2, INODE, 3, PAGE_FILL, 1);
518         battfs_writeTestBlock(disk, 3, INODE, 0, PAGE_FILL, 1);
519         disk->erase(disk, 4);
520         battfs_writeTestBlock(disk, 5, INODE2, 0, PAGE_FILL, 0);
521         battfs_writeTestBlock(disk, 6, INODE2, 1, PAGE_FILL, 1);
522         battfs_writeTestBlock(disk, 7, INODE2, 0, PAGE_FILL, 1);
523
524         fclose(fp);
525
526         for (size_t i = 0; i < sizeof(buf); i++)
527                 buf[i] = i;
528
529         ASSERT(battfs_init(disk));
530         ASSERT(battfs_fsck(disk));
531         ASSERT(battfs_fileopen(disk, &fd1, INODE, MODE));
532         ASSERT(kfile_write(&fd1.fd, buf, sizeof(buf)) == sizeof(buf));
533         ASSERT(fd1.fd.seek_pos == sizeof(buf));
534         ASSERT(kfile_seek(&fd1.fd, 0, KSM_SEEK_SET) == 0);
535         ASSERT(fd1.fd.seek_pos == 0);
536
537         memset(buf, 0, sizeof(buf));
538         ASSERT(kfile_read(&fd1.fd, buf, sizeof(buf)) == sizeof(buf));
539         for (size_t i = 0; i < sizeof(buf); i++)
540                 ASSERT(buf[i] == i);
541
542         ASSERT(kfile_close(&fd1.fd) == 0);
543         ASSERT(battfs_fsck(disk));
544         ASSERT(battfs_close(disk));
545
546         TRACEMSG("13: passed\n");
547 }
548
549 static void writeAcross(BattFsSuper *disk)
550 {
551         BattFs fd1;
552
553         TRACEMSG("14: write file test across page boundary and seek test\n");
554
555         fp = fopen(test_filename, "w+");
556
557         const unsigned int PAGE_FILL = PAGE_SIZE - BATTFS_HEADER_LEN;
558         inode_t INODE = 0;
559         unsigned int MODE = 0;
560         uint8_t buf[PAGE_FILL + BATTFS_HEADER_LEN / 2];
561
562         disk->erase(disk, 0);
563         battfs_writeTestBlock(disk, 1, INODE, 0, PAGE_FILL, 0);
564         battfs_writeTestBlock(disk, 2, INODE, 3, PAGE_FILL, 1);
565         battfs_writeTestBlock(disk, 3, INODE, 0, PAGE_FILL, 1);
566         disk->erase(disk, 4);
567         battfs_writeTestBlock(disk, 5, INODE, 0, PAGE_FILL, 2);
568         battfs_writeTestBlock(disk, 6, INODE, 1, PAGE_FILL, 3);
569         battfs_writeTestBlock(disk, 7, INODE, 0, PAGE_FILL, 3);
570
571         fclose(fp);
572
573         ASSERT(battfs_init(disk));
574         ASSERT(battfs_fsck(disk));
575         ASSERT(battfs_fileopen(disk, &fd1, INODE, MODE));
576
577         uint8_t val = 0;
578         for (size_t i = 0; i < sizeof(buf); i++)
579                 buf[i] = val++;
580         ASSERT(kfile_write(&fd1.fd, buf, sizeof(buf)) == sizeof(buf));
581         ASSERT(fd1.fd.seek_pos == (kfile_off_t)sizeof(buf));
582
583         for (size_t i = 0; i < sizeof(buf); i++)
584                 buf[i] = val++;
585         ASSERT(kfile_write(&fd1.fd, buf, sizeof(buf)) == sizeof(buf));
586         ASSERT(fd1.fd.seek_pos == (kfile_off_t)sizeof(buf) * 2);
587
588         for (size_t i = 0; i < sizeof(buf); i++)
589                 buf[i] = val++;
590         ASSERT(kfile_write(&fd1.fd, buf, sizeof(buf)) == sizeof(buf));
591         ASSERT(fd1.fd.seek_pos == (kfile_off_t)sizeof(buf) * 3);
592
593         ASSERT(kfile_seek(&fd1.fd, 0, KSM_SEEK_SET) == 0);
594         ASSERT(fd1.fd.seek_pos == 0);
595         val = 0;
596
597         memset(buf, 0, sizeof(buf));
598         ASSERT(kfile_read(&fd1.fd, buf, sizeof(buf)) == sizeof(buf));
599         for (size_t i = 0; i < sizeof(buf); i++)
600                 ASSERT(buf[i] == val++);
601
602         memset(buf, 0, sizeof(buf));
603         ASSERT(kfile_read(&fd1.fd, buf, sizeof(buf)) == sizeof(buf));
604         for (size_t i = 0; i < sizeof(buf); i++)
605                 ASSERT(buf[i] == val++);
606
607         memset(buf, 0, sizeof(buf));
608         ASSERT(kfile_read(&fd1.fd, buf, sizeof(buf)) == sizeof(buf));
609         for (size_t i = 0; i < sizeof(buf); i++)
610                 ASSERT(buf[i] == val++);
611
612         ASSERT(fd1.fd.seek_pos == (kfile_off_t)sizeof(buf) * 3);
613
614         ASSERT(kfile_close(&fd1.fd) == 0);
615         ASSERT(battfs_fsck(disk));
616         ASSERT(battfs_close(disk));
617
618         TRACEMSG("14: passed\n");
619 }
620
621 static void createFile(BattFsSuper *disk)
622 {
623         TRACEMSG("15: file creation on new disk\n");
624
625         FILE *fpt = fopen(test_filename, "w+");
626
627         for (int i = 0; i < FILE_SIZE; i++)
628                 fputc(0xff, fpt);
629         fclose(fpt);
630
631         BattFs fd1;
632         inode_t INODE = 0;
633         unsigned int MODE = BATTFS_CREATE;
634
635         ASSERT(battfs_init(disk));
636         ASSERT(battfs_fsck(disk));
637         ASSERT(battfs_fileopen(disk, &fd1, INODE, MODE));
638         for (int i = 0; i < FILE_SIZE / 2; i++)
639                 ASSERT(kfile_putc(i, &fd1.fd) != EOF);
640
641         ASSERT(fd1.fd.seek_pos == FILE_SIZE / 2);
642         ASSERT(fd1.fd.size == FILE_SIZE / 2);
643         ASSERT(kfile_close(&fd1.fd) == 0);
644         ASSERT(battfs_fsck(disk));
645         ASSERT(battfs_close(disk));
646
647         ASSERT(battfs_init(disk));
648         ASSERT(battfs_fsck(disk));
649         ASSERT(battfs_fileopen(disk, &fd1, INODE, 0));
650         ASSERT(fd1.fd.size == FILE_SIZE / 2);
651         ASSERT(fd1.fd.seek_pos == 0);
652
653         uint8_t buf[FILE_SIZE / 2];
654         memset(buf, 0, sizeof(buf));
655         ASSERT(kfile_read(&fd1.fd, buf, FILE_SIZE / 2) == FILE_SIZE / 2);
656
657         for (int i = 0; i < FILE_SIZE / 2; i++)
658                 ASSERT(buf[i] == (i & 0xff));
659
660         ASSERT(fd1.fd.seek_pos == FILE_SIZE / 2);
661         ASSERT(kfile_close(&fd1.fd) == 0);
662         ASSERT(battfs_fsck(disk));
663         ASSERT(battfs_close(disk));
664
665
666         TRACEMSG("15: passed\n");
667 }
668
669 static void multipleWrite(BattFsSuper *disk)
670 {
671         TRACEMSG("16: multiple write on file\n");
672
673         FILE *fpt = fopen(test_filename, "w+");
674
675         for (int i = 0; i < FILE_SIZE; i++)
676                 fputc(0xff, fpt);
677         fclose(fpt);
678
679         BattFs fd1;
680         inode_t INODE = 0;
681         unsigned int MODE = BATTFS_CREATE;
682         uint8_t buf[1000];
683
684         ASSERT(battfs_init(disk));
685         ASSERT(battfs_fsck(disk));
686         ASSERT(battfs_fileopen(disk, &fd1, INODE, MODE));
687
688         int j;
689         for (j = 1; j < 1013; j++)
690         {
691                 for (unsigned i = 0; i < sizeof(buf); i++)
692                         buf[i] = j+i;
693
694                 ASSERT(kfile_write(&fd1.fd, buf, sizeof(buf)) == sizeof(buf));
695                 ASSERT(fd1.fd.seek_pos == sizeof(buf));
696                 ASSERT(fd1.fd.size == sizeof(buf));
697                 ASSERT(kfile_seek(&fd1.fd, 0, KSM_SEEK_SET) == 0);
698                 memset(buf, 0, sizeof(buf));
699                 ASSERT(kfile_read(&fd1.fd, buf, sizeof(buf)) == sizeof(buf));
700                 ASSERT(fd1.fd.seek_pos == sizeof(buf));
701                 for (unsigned i = 0; i < sizeof(buf); i++)
702                         ASSERT(buf[i] == ((j+i) & 0xff));
703                 ASSERT(kfile_seek(&fd1.fd, 0, KSM_SEEK_SET) == 0);
704                 ASSERT(disk->free_bytes == disk->disk_size - sizeof(buf));
705         }
706         ASSERT(kfile_close(&fd1.fd) == 0);
707         ASSERT(battfs_fsck(disk));
708         ASSERT(battfs_close(disk));
709
710         ASSERT(battfs_init(disk));
711         ASSERT(battfs_fsck(disk));
712         ASSERT(disk->free_bytes == disk->disk_size - sizeof(buf));
713         ASSERT(battfs_fileopen(disk, &fd1, INODE, 0));
714         ASSERT(fd1.fd.size == sizeof(buf));
715         memset(buf, 0, sizeof(buf));
716         ASSERT(kfile_read(&fd1.fd, buf, sizeof(buf)) == sizeof(buf));
717         for (unsigned i = 0; i < sizeof(buf); i++)
718                         ASSERT(buf[i] == ((j-1+i) & 0xff));
719         ASSERT(kfile_close(&fd1.fd) == 0);
720         ASSERT(battfs_fsck(disk));
721         ASSERT(battfs_close(disk));
722
723
724         TRACEMSG("16: passed\n");
725 }
726
727 static void increaseFile(BattFsSuper *disk)
728 {
729         TRACEMSG("17: increasing dimension of a file with multiple open files.\n");
730
731         FILE *fpt = fopen(test_filename, "w+");
732
733         for (int i = 0; i < FILE_SIZE / 10; i++)
734                 fputc(0xff, fpt);
735         fclose(fpt);
736
737         BattFs fd1,fd2;
738         inode_t INODE1 = 1, INODE2 = 2;
739         unsigned int MODE = BATTFS_CREATE;
740         uint8_t buf[1000];
741
742         ASSERT(battfs_init(disk));
743         ASSERT(battfs_fsck(disk));
744         ASSERT(battfs_fileopen(disk, &fd1, INODE1, MODE));
745         ASSERT(battfs_fileopen(disk, &fd2, INODE2, MODE));
746         for (unsigned i = 0; i < sizeof(buf); i++)
747                 ASSERT(kfile_putc(i, &fd2.fd) != EOF);
748         ASSERT(kfile_seek(&fd2.fd, 0, KSM_SEEK_SET) == 0);
749         memset(buf, 0, sizeof(buf));
750         ASSERT(kfile_read(&fd2.fd, buf, sizeof(buf)) == sizeof(buf));
751
752         for (unsigned i = 0; i < sizeof(buf); i++)
753                 ASSERT(buf[i] == (i & 0xff));
754         ASSERT(kfile_seek(&fd2.fd, 0, KSM_SEEK_SET) == 0);
755
756         for (unsigned i = 0; i < sizeof(buf); i++)
757                 ASSERT(kfile_putc(i, &fd1.fd) != EOF);
758
759         memset(buf, 0, sizeof(buf));
760         ASSERT(kfile_read(&fd2.fd, buf, sizeof(buf)) == sizeof(buf));
761
762         for (unsigned i = 0; i < sizeof(buf); i++)
763                 ASSERT(buf[i] == (i & 0xff));
764
765         ASSERT(kfile_close(&fd1.fd) == 0);
766         ASSERT(kfile_close(&fd2.fd) == 0);
767         ASSERT(battfs_fsck(disk));
768         ASSERT(battfs_close(disk));
769
770         TRACEMSG("17: passed\n");
771 }
772
773 static void readEOF(BattFsSuper *disk)
774 {
775         BattFs fd1;
776         uint8_t buf[16];
777
778         TRACEMSG("18: reading over EOF test\n");
779
780         fp = fopen(test_filename, "w+");
781
782         unsigned int PAGE_FILL = PAGE_SIZE - BATTFS_HEADER_LEN;
783         inode_t INODE = 0;
784         inode_t INODE2 = 4;
785         unsigned int MODE = 0;
786
787         disk->erase(disk, 0);
788         battfs_writeTestBlock(disk, 1, INODE, 0, PAGE_FILL, 0);
789         battfs_writeTestBlock(disk, 2, INODE, 3, PAGE_FILL, 1);
790         battfs_writeTestBlock(disk, 3, INODE, 0, PAGE_FILL, 1);
791         disk->erase(disk, 4);
792         battfs_writeTestBlock(disk, 5, INODE2, 0, PAGE_FILL, 0);
793         battfs_writeTestBlock(disk, 6, INODE2, 1, PAGE_FILL, 1);
794         battfs_writeTestBlock(disk, 7, INODE2, 0, PAGE_FILL, 1);
795
796         fclose(fp);
797
798         ASSERT(battfs_init(disk));
799         ASSERT(battfs_fsck(disk));
800         ASSERT(battfs_fileopen(disk, &fd1, INODE, MODE));
801         ASSERT(kfile_seek(&fd1.fd, fd1.fd.size + 10, SEEK_SET) == fd1.fd.size + 10);
802         ASSERT(fd1.fd.seek_pos == fd1.fd.size + 10);
803         ASSERT(kfile_read(&fd1.fd, buf, sizeof(buf)) == 0);
804
805         ASSERT(kfile_close(&fd1.fd) == 0);
806         ASSERT(battfs_fsck(disk));
807         ASSERT(battfs_close(disk));
808
809         TRACEMSG("18: passed\n");
810 }
811
812 static void writeEOF(BattFsSuper *disk)
813 {
814         TRACEMSG("19: writing over EOF test\n");
815
816         FILE *fpt = fopen(test_filename, "w+");
817
818         for (int i = 0; i < FILE_SIZE / 5; i++)
819                 fputc(0xff, fpt);
820         fclose(fpt);
821
822         BattFs fd1;
823         inode_t INODE = 0;
824         unsigned int MODE = BATTFS_CREATE;
825         uint8_t buf[FILE_SIZE / 13];
826
827         for (int i = 0; i < 2; i++)
828                 buf[i] = i;
829
830         ASSERT(battfs_init(disk));
831         ASSERT(battfs_fsck(disk));
832         disk_size_t prev_free = disk->free_bytes;
833         ASSERT(battfs_fileopen(disk, &fd1, INODE, MODE));
834         ASSERT(fd1.fd.size == 0);
835
836         ASSERT(kfile_seek(&fd1.fd, 2, KSM_SEEK_END) == 2);
837         ASSERT(kfile_write(&fd1.fd, buf, 2));
838         ASSERT(fd1.fd.seek_pos == 4);
839         ASSERT(fd1.fd.size == 4);
840         ASSERT(disk->free_bytes == prev_free - 4);
841         ASSERT(kfile_seek(&fd1.fd, 0, KSM_SEEK_SET) == 0);
842         memset(buf, 0, 2);
843         ASSERT(kfile_read(&fd1.fd, buf, 2) == 2);
844         for (int i = 0; i < 2; i++)
845                 ASSERT(buf[i] == 0);
846
847         memset(buf, 0, 2);
848         ASSERT(kfile_read(&fd1.fd, buf, 2) == 2);
849         for (int i = 0; i < 2; i++)
850                 ASSERT(buf[i] == (i & 0xff));
851
852         ASSERT(kfile_seek(&fd1.fd, sizeof(buf), KSM_SEEK_END) == sizeof(buf) + 4);
853         for (unsigned i = 0; i < sizeof(buf); i++)
854                 buf[i] = i;
855         ASSERT(kfile_write(&fd1.fd, buf, sizeof(buf)));
856         ASSERT(fd1.fd.seek_pos == sizeof(buf) * 2 + 4);
857         ASSERT(fd1.fd.size == sizeof(buf) * 2 + 4);
858         ASSERT(disk->free_bytes == prev_free - sizeof(buf) * 2 - 4);
859
860         ASSERT(kfile_seek(&fd1.fd, 0, KSM_SEEK_SET) == 0);
861
862         memset(buf, 0, 2);
863         ASSERT(kfile_read(&fd1.fd, buf, 2) == 2);
864         ASSERT(fd1.fd.seek_pos == 2);
865         for (int i = 0; i < 2; i++)
866                 ASSERT(buf[i] == 0);
867
868         memset(buf, 0, 2);
869         ASSERT(kfile_read(&fd1.fd, buf, 2) == 2);
870         ASSERT(fd1.fd.seek_pos == 4);
871         for (int i = 0; i < 2; i++)
872                 ASSERT(buf[i] == (i & 0xff));
873
874         memset(buf, 0, 4);
875         ASSERT(kfile_read(&fd1.fd, buf, sizeof(buf)) == sizeof(buf));
876         ASSERT(fd1.fd.seek_pos == sizeof(buf) + 4);
877         for (unsigned i = 0; i < sizeof(buf); i++)
878                 ASSERT(buf[i] == 0);
879
880         memset(buf, 0, sizeof(buf));
881         ASSERT(kfile_read(&fd1.fd, buf, sizeof(buf)) == sizeof(buf));
882         for (unsigned i = 0; i < sizeof(buf); i++)
883                 ASSERT(buf[i] == (i & 0xff));
884
885         ASSERT(kfile_close(&fd1.fd) == 0);
886         ASSERT(battfs_fsck(disk));
887         ASSERT(battfs_close(disk));
888
889         TRACEMSG("19: passed\n");
890
891 }
892
893 static void endOfSpace(BattFsSuper *disk)
894 {
895         TRACEMSG("20: what happens when disk space is over?\n");
896         BattFs fd1;
897         uint8_t buf[(PAGE_SIZE - BATTFS_HEADER_LEN) * 5];
898
899         fp = fopen(test_filename, "w+");
900
901         unsigned int PAGE_FILL = PAGE_SIZE - BATTFS_HEADER_LEN;
902         inode_t INODE = 0;
903         unsigned int MODE = BATTFS_CREATE;
904
905         disk->erase(disk, 0);
906         disk->erase(disk, 1);
907         disk->erase(disk, 2);
908         disk->erase(disk, 3);
909         fclose(fp);
910
911         ASSERT(battfs_init(disk));
912         ASSERT(battfs_fsck(disk));
913         ASSERT(battfs_fileopen(disk, &fd1, INODE, MODE));
914         ASSERT(kfile_write(&fd1.fd, buf, sizeof(buf)) == PAGE_FILL * 4);
915         ASSERT(fd1.fd.size == (kfile_off_t)(PAGE_FILL * 4));
916         ASSERT(fd1.fd.seek_pos == (kfile_off_t)(PAGE_FILL * 4));
917         ASSERT(disk->free_bytes == 0);
918
919         ASSERT(kfile_close(&fd1.fd) == 0);
920         ASSERT(battfs_fsck(disk));
921         ASSERT(battfs_close(disk));
922
923         TRACEMSG("20: passed\n");
924 }
925
926
927 static void multipleFilesRW(BattFsSuper *disk)
928 {
929         TRACEMSG("21: multiple files read/write test\n");
930
931         FILE *fpt = fopen(test_filename, "w+");
932
933         for (int i = 0; i < FILE_SIZE; i++)
934                 fputc(0xff, fpt);
935         fclose(fpt);
936
937         #define N_FILES 10
938         BattFs fd[N_FILES];
939         unsigned int MODE = BATTFS_CREATE;
940         uint32_t buf[FILE_SIZE / (4 * N_FILES * sizeof(uint32_t))];
941
942         ASSERT(battfs_init(disk));
943         ASSERT(battfs_fsck(disk));
944         for (inode_t i = 0; i < N_FILES; i++)
945                 ASSERT(battfs_fileopen(disk, &fd[i], i, MODE));
946
947         for (int i = N_FILES - 1; i >= 0; i--)
948         {
949                 for (uint32_t j = 0; j < countof(buf); j++)
950                         buf[j] = j+i;
951
952                 ASSERT(kfile_write(&fd[i].fd, buf, sizeof(buf)) == sizeof(buf));
953                 ASSERT(fd[i].fd.size == sizeof(buf));
954                 ASSERT(fd[i].fd.seek_pos == sizeof(buf));
955                 ASSERT(kfile_seek(&fd[i].fd, 0, SEEK_SET) == 0);
956         }
957
958         for (inode_t i = 0; i < N_FILES; i++)
959         {
960                 memset(buf, 0, sizeof(buf));
961                 ASSERT(kfile_read(&fd[i].fd, buf, sizeof(buf)) == sizeof(buf));
962
963                 for (uint32_t j = 0; j < countof(buf); j++)
964                         ASSERT(buf[j] == j+i);
965
966                 ASSERT(fd[i].fd.size == sizeof(buf));
967                 ASSERT(fd[i].fd.seek_pos == sizeof(buf));
968                 ASSERT(kfile_seek(&fd[i].fd, 0, SEEK_SET) == 0);
969         }
970
971         for (inode_t i = 0; i < N_FILES; i++)
972                 ASSERT(kfile_close(&fd[i].fd) == 0);
973
974         ASSERT(battfs_fsck(disk));
975         ASSERT(battfs_close(disk));
976
977         ASSERT(battfs_init(disk));
978         ASSERT(battfs_fsck(disk));
979
980         for (inode_t i = 0; i < N_FILES; i++)
981                 ASSERT(battfs_fileopen(disk, &fd[i], i, 0));
982
983         for (inode_t i = 0; i < N_FILES; i++)
984         {
985                 memset(buf, 0, sizeof(buf));
986                 ASSERT(kfile_read(&fd[i].fd, buf, sizeof(buf)) == sizeof(buf));
987
988                 for (uint32_t j = 0; j < countof(buf); j++)
989                         ASSERT(buf[j] == j+i);
990
991                 ASSERT(fd[i].fd.size == sizeof(buf));
992                 ASSERT(fd[i].fd.seek_pos == sizeof(buf));
993                 ASSERT(kfile_seek(&fd[i].fd, 0, SEEK_SET) == 0);
994         }
995
996         for (inode_t i = 0; i < N_FILES; i++)
997                 ASSERT(kfile_close(&fd[i].fd) == 0);
998
999         ASSERT(battfs_close(disk));
1000         TRACEMSG("21: passed\n");
1001 }
1002
1003
1004 int battfs_testRun(void)
1005 {
1006         BattFsSuper disk;
1007
1008         disk.page_size = PAGE_SIZE;
1009         disk.open = disk_open;
1010         disk.read = disk_page_read;
1011         disk.load = disk_page_load;
1012         disk.bufferWrite = disk_buffer_write;
1013         disk.bufferRead = disk_buffer_read;
1014         disk.save = disk_page_save;
1015         disk.erase = disk_page_erase;
1016         disk.close = disk_close;
1017
1018         diskNew(&disk);
1019         disk1File(&disk);
1020         diskHalfFile(&disk);
1021         oldSeq1(&disk);
1022         oldSeq2(&disk);
1023         oldSeq3(&disk);
1024         oldSeq2File(&disk);
1025         openFile(&disk);
1026         readFile(&disk);
1027         readAcross(&disk);
1028         writeFile(&disk);
1029         writeAcross(&disk);
1030         createFile(&disk);
1031         multipleWrite(&disk);
1032         increaseFile(&disk);
1033         readEOF(&disk);
1034         writeEOF(&disk);
1035         endOfSpace(&disk);
1036         multipleFilesRW(&disk);
1037
1038         kprintf("All tests passed!\n");
1039
1040         return 0;
1041 }
1042
1043 int battfs_testSetup(void)
1044 {
1045         return 0;
1046 }
1047
1048 int battfs_testTearDown(void)
1049 {
1050         return 0;
1051 }
1052
1053 TEST_MAIN(battfs)
1054
1055 #include <fs/battfs.c>
1056 #include <kern/kfile.c>
1057 #include <drv/kdebug.c>
1058 #include <mware/formatwr.c>
1059 #include <mware/hex.c>
1060
1061 #endif // _TEST