X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2Ftest%2Fao_fat_test.c;h=63be71c6b378b6b0424bf7cc3ff708ce278a5dc4;hb=d37945f1404043e6bd287ce7ad7a57bc3289609b;hp=3f94703443a98af2bcc576e6fb136436ff76e998;hpb=c7b606e93a4e4fbd2c0e883352ed74619ee24cf7;p=fw%2Faltos diff --git a/src/test/ao_fat_test.c b/src/test/ao_fat_test.c index 3f947034..63be71c6 100644 --- a/src/test/ao_fat_test.c +++ b/src/test/ao_fat_test.c @@ -3,7 +3,8 @@ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of @@ -84,14 +85,33 @@ ao_sdcard_write_block(uint32_t block, uint8_t *data) return write(fs_fd, data, 512) == 512; } -char *fs = "fs.fat"; +struct fs_param { + int fat; + int blocks; +} fs_params[] = { + { .fat = 16, .blocks = 16384 }, + { .fat = 32, .blocks = 16384 }, + { .fat = 16, .blocks = 65536 }, + { .fat = 32, .blocks = 65536 }, + { .fat = 16, .blocks = 1048576 }, + { .fat = 32, .blocks = 1048576 }, + { .fat = 0, .blocks = 0 }, +}; + +char *fs = "fs.fat"; +struct fs_param *param; void ao_sdcard_init(void) { char cmd[1024]; - snprintf(cmd, sizeof(cmd), "rm -f %s && mkfs.vfat -C %s 16384", fs, fs); + if (fs_fd) { + close(fs_fd); + fs_fd = 0; + } + snprintf(cmd, sizeof(cmd), "rm -f %s && mkfs.vfat -F %d -C %s %d", + fs, param->fat, fs, param->blocks); if (system (cmd) != 0) { fprintf(stderr, "'%s' failed\n", cmd); exit(1); @@ -125,22 +145,28 @@ check_fat(void); #include "ao_fat.c" /* Get the next cluster entry in the chain */ -static uint16_t -ao_fat_entry_raw_read(uint16_t cluster, uint8_t fat) +static cluster_t +ao_fat_entry_raw_read(cluster_t cluster, uint8_t fat) { - uint32_t sector; - uint16_t offset; - uint8_t *buf; - uint16_t ret; - -// cluster -= 2; - sector = cluster >> (SECTOR_SHIFT - 1); - offset = (cluster << 1) & SECTOR_MASK; - buf = ao_fat_sector_get(fat_start + fat * sectors_per_fat + sector); + sector_t sector; + cluster_offset_t offset; + uint8_t *buf; + cluster_t ret; + + if (fat32) + cluster <<= 2; + else + cluster <<= 1; + sector = cluster >> SECTOR_SHIFT; + offset = cluster & SECTOR_MASK; + buf = _ao_fat_sector_get(fat_start + fat * sectors_per_fat + sector); if (!buf) return 0; - ret = get_u16(buf + offset); - ao_fat_sector_put(buf, 0); + if (fat32) + ret = get_u32(buf + offset); + else + ret = get_u16(buf + offset); + _ao_fat_sector_put(buf, 0); return ret; } @@ -153,16 +179,21 @@ dump_fat(void) for (e = 0; e < number_cluster; e++) { if ((e & 0xf) == 0x0) printf ("%04x: ", e); - printf (" %04x", ao_fat_entry_raw_read(e, 0)); + if (fat32) + printf (" %08x", ao_fat_entry_raw_read(e, 0)); + else + printf (" %04x", ao_fat_entry_raw_read(e, 0)); if ((e & 0xf) == 0xf) putchar ('\n'); } + if (e & 0xf) + putchar('\n'); } void fat_list(void) { - uint16_t entry = 0; + dirent_t entry = 0; struct ao_fat_dirent dirent; printf (" **** Root directory ****\n"); @@ -182,8 +213,8 @@ fat_list(void) void fatal(char *msg, ...) { - dump_fat(); - fat_list(); +// dump_fat(); +// fat_list(); va_list l; va_start(l, msg); @@ -196,36 +227,37 @@ fatal(char *msg, ...) void check_fat(void) { - int e; - int f; + cluster_t e; + int f; for (e = 0; e < number_cluster; e++) { - uint16_t v = ao_fat_entry_raw_read(e, 0); + cluster_t v = ao_fat_entry_raw_read(e, 0); for (f = 1; f < number_fat; f++) { - if (ao_fat_entry_raw_read(e, f) != v) - fatal ("fats differ at %d\n", e); + cluster_t o = ao_fat_entry_raw_read(e, f); + if (o != v) + fatal ("fats differ at %08x (0 %08x %d %08x)\n", e, v, f, o); } } } -uint16_t -check_file(uint16_t dent, uint16_t first_cluster, uint8_t *used) +cluster_t +check_file(dirent_t dent, cluster_t first_cluster, dirent_t *used) { - uint16_t clusters = 0; - uint16_t cluster; + cluster_t clusters = 0; + cluster_t cluster; if (!first_cluster) return 0; for (cluster = first_cluster; - (cluster & 0xfff8) != 0xfff8; + fat32 ? !AO_FAT_IS_LAST_CLUSTER(cluster) : !AO_FAT_IS_LAST_CLUSTER16(cluster); cluster = ao_fat_entry_raw_read(cluster, 0)) { - if (!ao_fat_cluster_valid(cluster)) - fatal("file %d: invalid cluster %04x\n", dent, cluster); + if (!_ao_fat_cluster_valid(cluster)) + fatal("file %d: invalid cluster %08x\n", dent, cluster); if (used[cluster]) - fatal("file %d: duplicate cluster %04x\n", dent, cluster); - used[cluster] = 1; + fatal("file %d: duplicate cluster %08x also in file %d\n", dent, cluster, used[cluster]-1); + used[cluster] = dent; clusters++; } return clusters; @@ -234,54 +266,70 @@ check_file(uint16_t dent, uint16_t first_cluster, uint8_t *used) void check_fs(void) { - uint16_t r; - uint16_t cluster, chain; - uint8_t *used; + dirent_t r; + cluster_t cluster, chain; + dirent_t *used; + uint8_t *dent; check_fat(); - used = calloc(1, number_cluster); + used = calloc(sizeof (dirent_t), number_cluster); - for (r = 0; r < root_entries; r++) { - uint8_t *dent = ao_fat_root_get(r); - uint16_t clusters; - uint32_t size; - uint16_t first_cluster; - uint8_t name[11]; + for (r = 0; (dent = _ao_fat_root_get(r)); r++) { + cluster_t clusters; + offset_t size; + cluster_t first_cluster; + char name[11]; if (!dent) fatal("cannot map dent %d\n", r); memcpy(name, dent+0, 11); first_cluster = get_u16(dent + 0x1a); + if (fat32) + first_cluster |= (cluster_t) get_u16(dent + 0x14) << 16; size = get_u32(dent + 0x1c); - ao_fat_root_put(dent, r, 0); + _ao_fat_root_put(dent, r, 0); if (name[0] == AO_FAT_DENT_END) { break; } - clusters = check_file(r, first_cluster, used); - if (size > clusters * bytes_per_cluster) - fatal("file %d: size %u beyond clusters %d (%u)\n", - r, size, clusters, clusters * bytes_per_cluster); - if (size <= (clusters - 1) * bytes_per_cluster) - fatal("file %d: size %u too small clusters %d (%u)\n", - r, size, clusters, clusters * bytes_per_cluster); + clusters = check_file(r + 1, first_cluster, used); + if (size == 0) { + if (clusters != 0) + fatal("file %d: zero sized, but %d clusters\n", clusters); + } else { + if (size > clusters * bytes_per_cluster) + fatal("file %d: size %u beyond clusters %d (%u)\n", + r, size, clusters, clusters * bytes_per_cluster); + if (size <= (clusters - 1) * bytes_per_cluster) + fatal("file %d: size %u too small clusters %d (%u)\n", + r, size, clusters, clusters * bytes_per_cluster); + } } - for (; r < root_entries; r++) { - uint8_t *dent = ao_fat_root_get(r); - if (!dent) - fatal("cannot map dent %d\n", r); - if (dent[0] != AO_FAT_DENT_END) - fatal("found non-zero dent past end %d\n", r); - ao_fat_root_put(dent, r, 0); + if (!fat32) { + for (; r < root_entries; r++) { + uint8_t *dent = _ao_fat_root_get(r); + if (!dent) + fatal("cannot map dent %d\n", r); + if (dent[0] != AO_FAT_DENT_END) + fatal("found non-zero dent past end %d\n", r); + _ao_fat_root_put(dent, r, 0); + } + } else { + check_file((dirent_t) -1, root_cluster, used); } for (cluster = 0; cluster < 2; cluster++) { chain = ao_fat_entry_raw_read(cluster, 0); - if ((chain & 0xfff8) != 0xfff8) - fatal("cluster %d: not marked busy\n", cluster); + if (fat32) { + if ((chain & 0xffffff8) != 0xffffff8) + fatal("cluster %d: not marked busy\n", cluster); + } else { + if ((chain & 0xfff8) != 0xfff8) + fatal("cluster %d: not marked busy\n", cluster); + } } for (; cluster < number_cluster; cluster++) { chain = ao_fat_entry_raw_read(cluster, 0); @@ -291,96 +339,228 @@ check_fs(void) fatal("cluster %d: marked busy, but not in any file\n", cluster); } else { if (used[cluster] != 0) - fatal("cluster %d: marked free, but foudn in file\n", cluster); + fatal("cluster %d: marked free, but found in file %d\n", cluster, used[cluster]-1); } } } -#define NUM_FILES 512 -#define LINES_FILE 1000 +#define NUM_FILES 100 +#define LINES_FILE 500000 uint32_t sizes[NUM_FILES]; unsigned char md5[NUM_FILES][MD5_DIGEST_LENGTH]; -int -main(int argc, char **argv) +void +micro_test_fs(void) +{ + int8_t fd; + char name[] = "FOO "; + char buf[512]; + int len; + + printf ("write once\n"); + if ((fd = ao_fat_creat(name)) >= 0) { + ao_fat_write(fd, "hello world\n", 12); + ao_fat_close(fd); + } + + printf ("read first\n"); + if ((fd = ao_fat_open(name, AO_FAT_OPEN_READ)) >= 0) { + len = ao_fat_read(fd, buf, sizeof(buf)); + write (1, buf, len); + ao_fat_close(fd); + } + + printf ("write again\n"); + if ((fd = ao_fat_creat(name)) >= 0) { + ao_fat_write(fd, "hi\n", 3); + ao_fat_close(fd); + } + + printf ("read again\n"); + if ((fd = ao_fat_open(name, AO_FAT_OPEN_READ)) >= 0) { + len = ao_fat_read(fd, buf, sizeof(buf)); + write (1, buf, len); + ao_fat_close(fd); + } + + printf ("write 3\n"); + if ((fd = ao_fat_creat(name)) >= 0) { + int l; + char c; + + for (l = 0; l < 10; l++) { + for (c = ' '; c < '~'; c++) + ao_fat_write(fd, &c, 1); + c = '\n'; + ao_fat_write(fd, &c, 1); + } + ao_fat_close(fd); + } + + printf ("read 3\n"); + if ((fd = ao_fat_open(name, AO_FAT_OPEN_READ)) >= 0) { + while ((len = ao_fat_read(fd, buf, sizeof(buf))) > 0) + write (1, buf, len); + ao_fat_close(fd); + } + + check_fs(); + printf ("all done\n"); +} + + +void +short_test_fs(void) +{ + int len; + int8_t fd; + char buf[345]; + + if ((fd = ao_fat_open("HELLO TXT",AO_FAT_OPEN_READ)) >= 0) { + printf ("File contents for HELLO.TXT\n"); + while ((len = ao_fat_read(fd, buf, sizeof(buf)))) + write(1, buf, len); + ao_fat_close(fd); + } + + if ((fd = ao_fat_creat("NEWFILE TXT")) >= 0) { + printf ("Create new file\n"); + for (len = 0; len < 2; len++) + ao_fat_write(fd, "hello, world!\n", 14); + ao_fat_seek(fd, 0, AO_FAT_SEEK_SET); + printf ("read new file\n"); + while ((len = ao_fat_read(fd, buf, sizeof (buf)))) + write (1, buf, len); + ao_fat_close(fd); + } + + check_fs(); +} + +void +long_test_fs(void) { char name[12]; int id; MD5_CTX ctx; unsigned char md5_check[MD5_DIGEST_LENGTH]; + char buf[337]; + int len; + int8_t fd; + uint64_t total_file_size = 0; - if (argv[1]) - fs = argv[1]; - - ao_fat_init(); - - check_bufio("top"); - ao_fat_setup(); + total_reads = total_writes = 0; - check_fs(); - check_bufio("after setup"); printf (" **** Creating %d files\n", NUM_FILES); + memset(sizes, '\0', sizeof (sizes)); for (id = 0; id < NUM_FILES; id++) { sprintf(name, "D%07dTXT", id); - if (ao_fat_creat(name) == AO_FAT_SUCCESS) { + if ((id % ((NUM_FILES+49)/50)) == 0) { + printf ("."); fflush(stdout); + } + if ((fd = ao_fat_creat(name)) >= 0) { int j; char line[64]; check_bufio("file created"); MD5_Init(&ctx); - for (j = 0; j < 1000; j++) { - int len; + for (j = 0; j < LINES_FILE; j++) { + int len, ret; sprintf (line, "Hello, world %d %d\r\n", id, j); len = strlen(line); - ao_fat_write((uint8_t *) line, len); - MD5_Update(&ctx, line, len); - sizes[id] += len; + ret = ao_fat_write(fd, line, len); + if (ret <= 0) + break; + total_file_size += ret; + MD5_Update(&ctx, line, ret); + sizes[id] += ret; + if (ret != len) + printf ("write failed %d\n", ret); } - ao_fat_close(); + ao_fat_close(fd); MD5_Final(&md5[id][0], &ctx); - if (id == 0) { - printf ("MD5 write %d:", id); - for (j = 0; j < MD5_DIGEST_LENGTH; j++) - printf(" %02x", md5[id][j]); - printf ("\n"); - } check_bufio("file written"); } } + printf ("\n **** Write IO: read %llu write %llu data sectors %llu\n", total_reads, total_writes, (total_file_size + 511) / 512); + check_bufio("all files created"); printf (" **** All done creating files\n"); check_fs(); + total_reads = total_writes = 0; + printf (" **** Comparing %d files\n", NUM_FILES); for (id = 0; id < NUM_FILES; id++) { - char buf[337]; + uint32_t size; sprintf(name, "D%07dTXT", id); - if (ao_fat_open(name, AO_FAT_OPEN_READ) == AO_FAT_SUCCESS) { - int len; - + size = 0; + if ((id % ((NUM_FILES+49)/50)) == 0) { + printf ("."); fflush(stdout); + } + if ((fd = ao_fat_open(name, AO_FAT_OPEN_READ)) >= 0) { MD5_Init(&ctx); - while ((len = ao_fat_read((uint8_t *) buf, sizeof(buf))) > 0) { + while ((len = ao_fat_read(fd, buf, sizeof(buf))) > 0) { MD5_Update(&ctx, buf, len); + size += len; } - ao_fat_close(); + ao_fat_close(fd); MD5_Final(md5_check, &ctx); - if (id == 0) { - int j; - printf ("MD5 read %d:", id); - for (j = 0; j < MD5_DIGEST_LENGTH; j++) - printf(" %02x", md5_check[j]); - printf ("\n"); - } + if (size != sizes[id]) + fatal("file %d: size differs %d written %d read\n", + id, sizes[id], size); if (memcmp(md5_check, &md5[id][0], sizeof (md5_check)) != 0) - fatal ("checksum failed file %d\n", id); + fatal ("file %d: checksum failed\n", id); check_bufio("file shown"); } } + printf ("\n **** Read IO: read %llu write %llu\n", total_reads, total_writes); +} + +char *params[] = { + "-F 16 -C %s 16384", + "-F 32 -C %s 16384", + "-F 16 -C %s 65536", + "-F 32 -C %s 65536", + "-F 16 -C %s 1048576", + "-F 32 -C %s 1048576", + NULL +}; + +void +do_test(void (*test)(void)) +{ + ao_fat_init(); + + check_bufio("top"); + _ao_fat_setup(); + + check_fs(); + check_bufio("after setup"); + (*test)(); + ao_fat_unmount(); +} + +int +main(int argc, char **argv) +{ + int p; + + if (argv[1]) + fs = argv[1]; + + for (p = 0; fs_params[p].fat; p++) { + param = &fs_params[p]; + + do_test(micro_test_fs); + do_test(short_test_fs); + do_test(long_test_fs); + } + unlink (fs); - printf ("\n **** Total IO: read %llu write %llu\n", total_reads, total_writes); return 0; }