Add file open test.
[bertos.git] / app / battfs / 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 Develer S.r.l. (http://www.develer.com/)
30  *
31  * -->
32  *
33  * \version $Id: demo.c 18242 2007-10-08 17:35:23Z marco $
34  *
35  * \author Francesco Sacchi <batt@develer.com>
36  *
37  * \brief BattFs Test.
38  */
39
40 #include <cfg/debug.h>
41 #include <fs/battfs.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 FILE *fp;
52 const char test_filename[]="battfs_disk.bin";
53
54
55 static bool disk_open(struct BattFsSuper *d)
56 {
57         fp = fopen(test_filename, "r+b");
58         ASSERT(fp);
59         fseek(fp, 0, SEEK_END);
60         d->page_size = PAGE_SIZE;
61         d->page_count = ftell(fp) / d->page_size;
62         d->page_array = malloc(d->page_count * sizeof(pgcnt_t));
63         //TRACEMSG("page_size:%d, page_count:%d\n", d->page_size, d->page_count);
64         return (fp && d->page_array);
65 }
66
67 static size_t disk_page_read(struct BattFsSuper *d, pgcnt_t page, pgaddr_t addr, void *buf, size_t size)
68 {
69         //TRACEMSG("page:%d, addr:%d, size:%d\n", page, addr, size);
70         fseek(fp, page * d->page_size + addr, SEEK_SET);
71         return fread(buf, 1, size, fp);
72 }
73
74 static size_t disk_page_write(struct BattFsSuper *d, pgcnt_t page, pgaddr_t addr, const void *buf, size_t size)
75 {
76         //TRACEMSG("page:%d, addr:%d, size:%d\n", page, addr, size);
77         fseek(fp, page * d->page_size + addr, SEEK_SET);
78         return fwrite(buf, 1, size, fp);
79 }
80
81 static bool disk_page_erase(struct BattFsSuper *d, pgcnt_t page)
82 {
83         //TRACEMSG("page:%d\n", page);
84         fseek(fp, page * d->page_size, SEEK_SET);
85
86         for (int i = 0; i < d->page_size; i++)
87                 if (fputc(0xff, fp) == EOF)
88                         return false;
89         return true;
90 }
91
92 static bool disk_close(struct BattFsSuper *d)
93 {
94         //TRACE;
95         free(d->page_array);
96         return (fclose(fp) != EOF);
97 }
98
99 static void testCheck(BattFsSuper *disk, pgcnt_t *reference)
100 {
101         ASSERT(battfs_init(disk));
102         
103         for (int i = 0; i < disk->page_count; i++)
104         {
105                 if (disk->page_array[i] != reference[i])
106                 {
107                         kprintf("Error at addr %d: page_array read", i);
108                         for (pgcnt_t i = 0; i < disk->page_count; i++)
109                         {
110                                 if (!(i % 16))
111                                         kputchar('\n');
112                                 kprintf("%04d ", disk->page_array[i]);
113                         }
114                         kputchar('\n');
115                         kprintf("Expected:");
116                         for (pgcnt_t i = 0; i < disk->page_count; i++)
117                         {
118                                 if (!(i % 16))
119                                         kputchar('\n');
120                                 kprintf("%04d ", reference[i]);
121                         }
122                         kputchar('\n');
123                         battfs_close(disk);
124                         exit(2);
125                 }
126         }
127         battfs_close(disk);
128 }
129
130 static void test1(BattFsSuper *disk)
131 {
132         pgcnt_t ref[PAGE_COUNT];
133         kprintf("Test1: disk new\n");
134
135         FILE *fpt = fopen(test_filename, "w+");
136
137         for (int i = 0; i < FILE_SIZE; i++)
138                 fputc(0xff, fpt);
139         fclose(fpt);
140         for (int i = 0; i < PAGE_COUNT; i++)
141                 ref[i] = PAGE_COUNT - i - 1;
142
143         testCheck(disk, ref);
144         kprintf("Test1: passed\n");
145 }
146
147 static void test2(BattFsSuper *disk)
148 {
149         pgcnt_t ref[PAGE_COUNT];
150         kprintf("Test2: disk full with 1 contiguos file\n");
151
152
153         fp = fopen(test_filename, "w+");
154
155         for (int i = 0; i < PAGE_COUNT; i++)
156         {
157                 battfs_writeTestBlock(disk, i, 0, 0, 0, i, MARK_PAGE_VALID);
158                 ref[i] = i;
159         }
160         fclose(fp);
161
162         testCheck(disk, ref);
163         kprintf("Test2: passed\n");
164 }
165
166
167 static void test3(BattFsSuper *disk)
168 {
169         pgcnt_t ref[PAGE_COUNT];
170         kprintf("Test3: disk half full with 1 contiguos file, rest unformatted\n");
171
172
173         fp = fopen(test_filename, "w+");
174
175         for (int i = 0; i < PAGE_COUNT / 2; i++)
176         {
177                 battfs_writeTestBlock(disk, i, 0, 0, 0, i, MARK_PAGE_VALID);
178                 ref[i] = i;
179         }
180         fseek(fp, FILE_SIZE / 2, SEEK_SET);
181         for (int i = FILE_SIZE / 2; i < FILE_SIZE; i++)
182                 fputc(0xff, fp);
183         fclose(fp);
184
185         for (int i = PAGE_COUNT / 2; i < PAGE_COUNT; i++)
186         {
187                 ref[i] = PAGE_COUNT + PAGE_COUNT / 2 - i - 1;
188         }
189
190
191         testCheck(disk, ref);
192         kprintf("Test3: passed\n");
193 }
194
195 static void test4(BattFsSuper *disk)
196 {
197         pgcnt_t ref[PAGE_COUNT];
198         kprintf("Test4: disk half full with 1 contiguos file, rest marked free\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, MARK_PAGE_VALID);
206                 ref[i] = i;
207         }
208         for (int i = PAGE_COUNT / 2; i < PAGE_COUNT; i++)
209         {
210                 battfs_writeTestBlock(disk, i, 0, 0, 0, i, i);
211                 ref[i] = i;
212         }
213         fclose(fp);
214
215
216         testCheck(disk, ref);
217         kprintf("Test4: passed\n");
218 }
219
220 static void test5(BattFsSuper *disk)
221 {
222         pgcnt_t ref[PAGE_COUNT];
223         kprintf("Test5: disk 1/3 full with 1 contiguos file, 1/3 marked free, rest unformatted\n");
224
225
226         fp = fopen(test_filename, "w+");
227
228         for (int i = 0; i < FILE_SIZE; i++)
229                 fputc(0xff, fp);
230
231         for (int i = 0; i < PAGE_COUNT / 3; i++)
232         {
233                 battfs_writeTestBlock(disk, i, 0, 0, 0, i, MARK_PAGE_VALID);
234                 ref[i] = i;
235         }
236         for (int i = PAGE_COUNT / 3; i < 2 * (PAGE_COUNT / 3); i++)
237         {
238                 battfs_writeTestBlock(disk, i, 0, 0, 0, i, i);
239                 ref[i + PAGE_COUNT / 3 + 1] = i;
240         }
241         fclose(fp);
242
243         for (int i = PAGE_COUNT / 3; i < 2 * (PAGE_COUNT / 3) + 1; i++)
244                 ref[i] = PAGE_COUNT + PAGE_COUNT / 3 - i - 1;
245
246         testCheck(disk, ref);
247         kprintf("Test5: passed\n");
248 }
249
250 static void test6(BattFsSuper *disk)
251 {
252         pgcnt_t ref[4];
253         kprintf("Test6: 1 file with 1 old seq num, 1 free block\n");
254
255
256         fp = fopen(test_filename, "w+");
257
258         battfs_writeTestBlock(disk, 0, 0, 0, 0, 0, MARK_PAGE_VALID);
259         battfs_writeTestBlock(disk, 1, 0, 0, 0, 1, MARK_PAGE_VALID);
260         battfs_writeTestBlock(disk, 2, 0, 1, 0, 1, MARK_PAGE_VALID);
261         battfs_writeTestBlock(disk, 3, 0, 0, 0, 0, 123);
262
263         fclose(fp);
264         ref[0] = 0;
265         ref[1] = 2;
266         ref[2] = 3;
267         ref[3] = 1;
268
269         testCheck(disk, ref);
270         kprintf("Test6: passed\n");
271 }
272
273 static void test7(BattFsSuper *disk)
274 {
275         pgcnt_t ref[4];
276         kprintf("Test7: 1 file with 1 old seq num, 1 free block\n");
277
278
279         fp = fopen(test_filename, "w+");
280
281         battfs_writeTestBlock(disk, 0, 0, 0, 0, 0, MARK_PAGE_VALID);
282         battfs_writeTestBlock(disk, 1, 0, 1, 0, 1, MARK_PAGE_VALID);
283         battfs_writeTestBlock(disk, 2, 0, 0, 0, 1, MARK_PAGE_VALID);
284         battfs_writeTestBlock(disk, 3, 0, 0, 0, 0, 123);
285
286         fclose(fp);
287         ref[0] = 0;
288         ref[1] = 1;
289         ref[2] = 3;
290         ref[3] = 2;
291
292         testCheck(disk, ref);
293         kprintf("Test7: passed\n");
294 }
295
296 static void test8(BattFsSuper *disk)
297 {
298         pgcnt_t ref[4];
299         kprintf("Test8: 1 file with 1 old seq num, 1 free block\n");
300
301
302         fp = fopen(test_filename, "w+");
303
304         battfs_writeTestBlock(disk, 0, 0, 0, 0, 0, 1235);
305         battfs_writeTestBlock(disk, 1, 0, 0, 0, 0, MARK_PAGE_VALID);
306         battfs_writeTestBlock(disk, 2, 0, 1, 0, 1, MARK_PAGE_VALID);
307         battfs_writeTestBlock(disk, 3, 0, 0, 0, 1, MARK_PAGE_VALID);
308
309
310         fclose(fp);
311         ref[0] = 1;
312         ref[1] = 2;
313         ref[2] = 0;
314         ref[3] = 3;
315
316         testCheck(disk, ref);
317         kprintf("Test8: passed\n");
318 }
319
320 static void test9(BattFsSuper *disk)
321 {
322         pgcnt_t ref[8];
323         kprintf("Test9: 2 file with old seq num, 2 free block\n");
324
325
326         fp = fopen(test_filename, "w+");
327
328         battfs_writeTestBlock(disk, 0, 0, 0, 0, 0, 1235);
329         battfs_writeTestBlock(disk, 1, 0, 0, 0, 0, MARK_PAGE_VALID);
330         battfs_writeTestBlock(disk, 2, 0, 3, 0, 1, MARK_PAGE_VALID);
331         battfs_writeTestBlock(disk, 3, 0, 0, 0, 1, MARK_PAGE_VALID);
332         battfs_writeTestBlock(disk, 4, 0, 0, 0, 0, 1236);
333         battfs_writeTestBlock(disk, 5, 4, 0, 0, 0, MARK_PAGE_VALID);
334         battfs_writeTestBlock(disk, 6, 4, 1, 0, 1, MARK_PAGE_VALID);
335         battfs_writeTestBlock(disk, 7, 4, 0, 0, 1, MARK_PAGE_VALID);
336
337
338         fclose(fp);
339         ref[0] = 1;
340         ref[1] = 3;
341         ref[2] = 5;
342         ref[3] = 6;
343         ref[4] = 0;
344         ref[5] = 4;
345         ref[6] = 2;
346         ref[7] = 7;
347
348         testCheck(disk, ref);
349         kprintf("Test9: passed\n");
350 }
351
352 static void test10(BattFsSuper *disk)
353 {
354         KFileBattFs fd1;
355         KFileBattFs fd2;
356         kprintf("Test10: open file test, inode 0 and inode 4\n");
357
358         fp = fopen(test_filename, "w+");
359
360         #define PAGE_FILL 116
361         #define INODE 0
362         #define INODE2 4
363         #define MODE 0
364
365         battfs_writeTestBlock(disk, 0, INODE, 0, PAGE_FILL, 0, 1235);
366         battfs_writeTestBlock(disk, 1, INODE, 0, PAGE_FILL, 0, MARK_PAGE_VALID);
367         battfs_writeTestBlock(disk, 2, INODE, 3, PAGE_FILL, 1, MARK_PAGE_VALID);
368         battfs_writeTestBlock(disk, 3, INODE, 0, PAGE_FILL, 1, MARK_PAGE_VALID);
369         battfs_writeTestBlock(disk, 4, INODE2, 0, PAGE_FILL, 0, 1236);
370         battfs_writeTestBlock(disk, 5, INODE2, 0, PAGE_FILL, 0, MARK_PAGE_VALID);
371         battfs_writeTestBlock(disk, 6, INODE2, 1, PAGE_FILL, 1, MARK_PAGE_VALID);
372         battfs_writeTestBlock(disk, 7, INODE2, 0, PAGE_FILL, 1, MARK_PAGE_VALID);
373
374         fclose(fp);
375
376         ASSERT(battfs_init(disk));
377
378         ASSERT(battfs_fileopen(disk, &fd1, INODE, MODE));
379         ASSERT(fd1.fd.size == PAGE_FILL * 2);
380         ASSERT(fd1.fd.seek_pos == 0);
381         ASSERT(fd1.mode == MODE);
382         ASSERT(fd1.inode == INODE);
383         ASSERT(fd1.start == &disk->page_array[0]);
384         ASSERT(fd1.disk == disk);
385         ASSERT(LIST_HEAD(&disk->file_opened_list) == &fd1.link);
386
387         ASSERT(battfs_fileopen(disk, &fd2, INODE2, MODE));
388         ASSERT(fd2.fd.size == PAGE_FILL * 2);
389         ASSERT(fd2.fd.seek_pos == 0);
390         ASSERT(fd2.mode == MODE);
391         ASSERT(fd2.inode == INODE2);
392         ASSERT(fd2.start == &disk->page_array[2]);
393         ASSERT(fd2.disk == disk);
394         ASSERT(LIST_HEAD(&disk->file_opened_list)->succ == &fd2.link);
395
396         ASSERT(kfile_close(&fd1.fd) == 0);
397         ASSERT(kfile_close(&fd2.fd) == 0);
398         ASSERT(LIST_EMPTY(&disk->file_opened_list));
399         ASSERT(battfs_close(disk));
400
401         kprintf("Test10: passed\n");
402 }
403
404
405
406
407
408 int main(void)
409 {
410         BattFsSuper disk;
411
412         disk.open = disk_open;
413         disk.read = disk_page_read;
414         disk.write = disk_page_write;
415         disk.erase = disk_page_erase;
416         disk.close = disk_close;
417         test1(&disk);
418         test2(&disk);
419         test3(&disk);
420         test4(&disk);
421         test5(&disk);
422         test6(&disk);
423         test7(&disk);
424         test8(&disk);
425         test9(&disk);
426         test10(&disk);
427         kprintf("All test passed!\n");
428
429         return 0;
430 }