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