diff options
author | Christopher Haster <chaster@utexas.edu> | 2017-03-26 02:11:45 +0300 |
---|---|---|
committer | Christopher Haster <chaster@utexas.edu> | 2017-03-26 03:23:30 +0300 |
commit | a711675607496eb6271c22de9239f334639980e3 (patch) | |
tree | 31d841affb695dbf46b82f46dae8225b87c8c23e | |
parent | afa4ad82544048581913e0a273745acb3886dc84 (diff) |
Added dir tests, test fixes, config
-rw-r--r-- | Makefile | 8 | ||||
-rw-r--r-- | lfs.c | 168 | ||||
-rw-r--r-- | lfs.h | 29 | ||||
-rwxr-xr-x | tests/stats.py | 4 | ||||
-rw-r--r-- | tests/template.fmt | 10 | ||||
-rwxr-xr-x | tests/test_dirs.sh | 59 | ||||
-rwxr-xr-x | tests/test_format.sh | 30 |
7 files changed, 248 insertions, 60 deletions
@@ -9,7 +9,7 @@ OBJ := $(SRC:.c=.o) DEP := $(SRC:.c=.d) ASM := $(SRC:.c=.s) -TEST := $(wildcard tests/test_*) +TEST := $(patsubst tests/%.sh,%,$(wildcard tests/test_*)) ifdef DEBUG CFLAGS += -O0 -g3 @@ -30,8 +30,10 @@ asm: $(ASM) size: $(OBJ) $(SIZE) -t $^ -test: - for t in $(TEST) ; do ./$$t ; done +.SUFFIXES: +test: $(TEST) +test_%: tests/test_%.sh + ./$< -include $(DEP) @@ -39,9 +39,9 @@ static int lfs_bd_cmp(lfs_t *lfs, lfs_block_t block, lfs_off_t off, lfs_size_t size, const void *buffer) { const uint8_t *data = buffer; - while (off < size) { + for (lfs_off_t i = 0; i < size; i++) { uint8_t c; - int err = lfs_bd_read(lfs, block, off, 1, &c); + int err = lfs_bd_read(lfs, block, off+i, 1, &c); if (err) { return err; } @@ -51,7 +51,6 @@ static int lfs_bd_cmp(lfs_t *lfs, lfs_block_t block, } data += 1; - off += 1; } return true; @@ -329,29 +328,35 @@ static int lfs_dir_create(lfs_t *lfs, lfs_dir_t *dir, lfs_block_t parent[2]) { dir->d.rev += 1; // Calculate total size - dir->d.size = sizeof(dir->d); - if (parent) { - dir->d.size += sizeof(struct lfs_disk_entry); - } + dir->d.size = sizeof(dir->d) + 2*sizeof(struct lfs_disk_entry) + 3; + dir->off = sizeof(dir->d); // Other defaults - dir->off = dir->d.size; dir->d.tail[0] = 0; dir->d.tail[1] = 0; dir->d.free = lfs->free; // Write out to memory return lfs_pair_commit(lfs, dir->pair, - 1 + (parent ? 2 : 0), (struct lfs_commit_region[]){ + 5, (struct lfs_commit_region[]){ {0, sizeof(dir->d), &dir->d}, {sizeof(dir->d), sizeof(struct lfs_disk_entry), &(struct lfs_disk_entry){ .type = LFS_TYPE_DIR, - .len = 12+2, - .u.dir[0] = parent ? parent[0] : 0, - .u.dir[1] = parent ? parent[1] : 0, + .len = sizeof(struct lfs_disk_entry)+1, + .u.dir[0] = dir->pair[0], + .u.dir[1] = dir->pair[1], + }}, + {sizeof(dir->d)+sizeof(struct lfs_disk_entry), 1, "."}, + {sizeof(dir->d)+sizeof(struct lfs_disk_entry)+1, + sizeof(struct lfs_disk_entry), + &(struct lfs_disk_entry){ + .type = LFS_TYPE_DIR, + .len = sizeof(struct lfs_disk_entry)+2, + .u.dir[0] = parent ? parent[0] : dir->pair[0], + .u.dir[1] = parent ? parent[1] : dir->pair[1], }}, - {sizeof(dir->d)+sizeof(struct lfs_disk_entry), 2, ".."}, + {sizeof(dir->d)+2*sizeof(struct lfs_disk_entry)+1, 2, ".."}, }); } @@ -473,9 +478,19 @@ int lfs_mkdir(lfs_t *lfs, const char *path) { } int lfs_dir_open(lfs_t *lfs, lfs_dir_t *dir, const char *path) { - int err = lfs_dir_fetch(lfs, dir, lfs->cwd); + if (path[0] == '/') { + dir->pair[0] = lfs->root[0]; + dir->pair[1] = lfs->root[1]; + } else { + dir->pair[0] = lfs->cwd[0]; + dir->pair[1] = lfs->cwd[1]; + } + + int err = lfs_dir_fetch(lfs, dir, dir->pair); if (err) { return err; + } else if (strcmp(path, "/") == 0) { + return 0; } lfs_entry_t entry; @@ -494,6 +509,29 @@ int lfs_dir_close(lfs_t *lfs, lfs_dir_t *dir) { return 0; } +int lfs_dir_read(lfs_t *lfs, lfs_dir_t *dir, struct lfs_info *info) { + memset(info, 0, sizeof(*info)); + + lfs_entry_t entry; + int err = lfs_dir_next(lfs, dir, &entry); + if (err) { + return (err == LFS_ERROR_NO_ENTRY) ? 0 : err; + } + + info->type = entry.d.type & 0xff; + if (info->type == LFS_TYPE_REG) { + info->size = entry.d.u.file.size; + } + + err = lfs_bd_read(lfs, entry.dir[0], entry.off + sizeof(entry.d), + entry.d.len - sizeof(entry.d), info->name); + if (err) { + return err; + } + + return 1; +} + /// File operations /// @@ -548,6 +586,8 @@ int lfs_file_open(lfs_t *lfs, lfs_file_t *file, file->entry.d.len-sizeof(file->entry.d), path} }); + } else if (file->entry.d.type == LFS_TYPE_DIR) { + return LFS_ERROR_IS_DIR; } else { file->head = file->entry.d.u.file.head; file->size = file->entry.d.u.file.size; @@ -675,9 +715,9 @@ lfs_ssize_t lfs_file_read(lfs_t *lfs, lfs_file_t *file, /// Generic filesystem operations /// -int lfs_format(lfs_t *lfs, lfs_bd_t *bd, const struct lfs_bd_ops *bd_ops) { - lfs->bd = bd; - lfs->bd_ops = bd_ops; +static int lfs_configure(lfs_t *lfs, const struct lfs_config *config) { + lfs->bd = config->bd; + lfs->bd_ops = config->bd_ops; struct lfs_bd_info info; int err = lfs_bd_info(lfs, &info); @@ -685,11 +725,67 @@ int lfs_format(lfs_t *lfs, lfs_bd_t *bd, const struct lfs_bd_ops *bd_ops) { return err; } - lfs->read_size = info.read_size; - lfs->prog_size = info.prog_size; - lfs->block_size = info.erase_size; - lfs->block_count = info.total_size / info.erase_size; - lfs->words = info.erase_size / sizeof(uint32_t); + if (config->read_size) { + if (config->read_size < info.read_size || + config->read_size % info.read_size != 0) { + LFS_ERROR("Invalid read size %u, device has %u\n", + config->read_size, info.read_size); + return LFS_ERROR_INVALID; + } + + lfs->read_size = config->read_size; + } else { + lfs->read_size = info.read_size; + } + + if (config->prog_size) { + if (config->prog_size < info.prog_size || + config->prog_size % info.prog_size != 0) { + LFS_ERROR("Invalid prog size %u, device has %u\n", + config->prog_size, info.prog_size); + return LFS_ERROR_INVALID; + } + + lfs->prog_size = config->prog_size; + } else { + lfs->prog_size = info.prog_size; + } + + if (config->block_size) { + if (config->block_size < info.erase_size || + config->block_size % info.erase_size != 0) { + LFS_ERROR("Invalid block size %u, device has %u\n", + config->prog_size, info.prog_size); + return LFS_ERROR_INVALID; + } + + lfs->block_size = config->block_size; + } else { + lfs->block_size = lfs_min(512, info.erase_size); + } + + if (config->block_count) { + if (config->block_count > info.total_size/info.erase_size) { + LFS_ERROR("Invalid block size %u, device has %u\n", + config->block_size, + (uint32_t)(info.total_size/info.erase_size)); + return LFS_ERROR_INVALID; + } + + lfs->block_count = config->block_count; + } else { + lfs->block_count = info.total_size / info.erase_size; + } + + lfs->words = lfs->block_size / sizeof(uint32_t); + return 0; +} + +int lfs_format(lfs_t *lfs, const struct lfs_config *config) { + int err = lfs_configure(lfs, config); + if (err) { + return err; + } // Create free list lfs->free.begin = 2; @@ -701,6 +797,8 @@ int lfs_format(lfs_t *lfs, lfs_bd_t *bd, const struct lfs_bd_ops *bd_ops) { if (err) { return err; } + lfs->root[0] = root.pair[0]; + lfs->root[1] = root.pair[1]; lfs->cwd[0] = root.pair[0]; lfs->cwd[1] = root.pair[1]; @@ -736,22 +834,12 @@ int lfs_format(lfs_t *lfs, lfs_bd_t *bd, const struct lfs_bd_ops *bd_ops) { return 0; } -int lfs_mount(lfs_t *lfs, lfs_bd_t *bd, const struct lfs_bd_ops *bd_ops) { - lfs->bd = bd; - lfs->bd_ops = bd_ops; - - struct lfs_bd_info info; - int err = lfs_bd_info(lfs, &info); +int lfs_mount(lfs_t *lfs, const struct lfs_config *config) { + int err = lfs_configure(lfs, config); if (err) { return err; } - lfs->read_size = info.read_size; - lfs->prog_size = info.prog_size; - lfs->block_size = info.erase_size; - lfs->block_count = info.total_size / info.erase_size; - lfs->words = info.erase_size / sizeof(uint32_t); - lfs_superblock_t superblock = { .pair = {0, 1}, }; @@ -767,9 +855,21 @@ int lfs_mount(lfs_t *lfs, lfs_bd_t *bd, const struct lfs_bd_ops *bd_ops) { return LFS_ERROR_CORRUPT; } + lfs->root[0] = superblock.d.root[0]; + lfs->root[1] = superblock.d.root[1]; lfs->cwd[0] = superblock.d.root[0]; lfs->cwd[1] = superblock.d.root[1]; + // TODO this is wrong, needs to check all dirs + lfs_dir_t dir; + err = lfs_dir_fetch(lfs, &dir, lfs->cwd); + if (err) { + return err; + } + + lfs->free.begin = dir.d.free.begin; + lfs->free.end = dir.d.free.end; + return err; } @@ -18,8 +18,9 @@ enum lfs_error { LFS_ERROR_NO_ENTRY = -4, LFS_ERROR_EXISTS = -5, LFS_ERROR_NOT_DIR = -6, - LFS_ERROR_INVALID = -7, - LFS_ERROR_NO_SPACE = -8, + LFS_ERROR_IS_DIR = -7, + LFS_ERROR_INVALID = -8, + LFS_ERROR_NO_SPACE = -9, }; enum lfs_type { @@ -39,6 +40,22 @@ enum lfs_open_flags { }; +struct lfs_config { + lfs_bd_t *bd; + const struct lfs_bd_ops *bd_ops; + + lfs_size_t read_size; + lfs_size_t prog_size; + + lfs_size_t block_size; + lfs_size_t block_count; +}; + +struct lfs_info { + uint8_t type; + lfs_size_t size; + char name[LFS_NAME_MAX+1]; +}; typedef struct lfs_entry { lfs_block_t dir[2]; @@ -104,6 +121,7 @@ typedef struct lfs { lfs_bd_t *bd; const struct lfs_bd_ops *bd_ops; + lfs_block_t root[2]; lfs_block_t cwd[2]; struct lfs_disk_free free; @@ -115,11 +133,14 @@ typedef struct lfs { } lfs_t; // Functions -int lfs_format(lfs_t *lfs, lfs_bd_t *bd, const struct lfs_bd_ops *bd_ops); -int lfs_mount(lfs_t *lfs, lfs_bd_t *bd, const struct lfs_bd_ops *bd_ops); +int lfs_format(lfs_t *lfs, const struct lfs_config *config); +int lfs_mount(lfs_t *lfs, const struct lfs_config *config); int lfs_unmount(lfs_t *lfs); int lfs_mkdir(lfs_t *lfs, const char *path); +int lfs_dir_open(lfs_t *lfs, lfs_dir_t *dir, const char *path); +int lfs_dir_close(lfs_t *lfs, lfs_dir_t *dir); +int lfs_dir_read(lfs_t *lfs, lfs_dir_t *dir, struct lfs_info *info); int lfs_file_open(lfs_t *lfs, lfs_file_t *file, const char *path, int flags); diff --git a/tests/stats.py b/tests/stats.py index 9508e79..b0c66a3 100755 --- a/tests/stats.py +++ b/tests/stats.py @@ -18,13 +18,13 @@ def main(): os.path.getsize(os.path.join('blocks', f)) for f in os.listdir('blocks') if re.match('\d+', f)) - print 'runtime: %.3f' % (time.time() - os.stat('blocks').st_ctime) - with open('blocks/stats') as file: s = struct.unpack('<QQQ', file.read()) print 'read_count: %d' % s[0] print 'prog_count: %d' % s[1] print 'erase_count: %d' % s[2] + print 'runtime: %.3f' % (time.time() - os.stat('blocks').st_ctime) + if __name__ == "__main__": main(*sys.argv[1:]) diff --git a/tests/template.fmt b/tests/template.fmt index 9370c63..2f94015 100644 --- a/tests/template.fmt +++ b/tests/template.fmt @@ -23,8 +23,9 @@ lfs_t lfs; lfs_emubd_t bd; lfs_file_t file[4]; lfs_dir_t dir[4]; -struct lfs_bd_info info; -struct lfs_bd_stats stats; +struct lfs_bd_info bd_info; +struct lfs_bd_stats bd_stats; +struct lfs_info info; uint8_t buffer[1024]; uint8_t wbuffer[1024]; @@ -35,6 +36,11 @@ lfs_size_t rsize; uintmax_t res; +const struct lfs_config config = {{ + .bd = &bd, + .bd_ops = &lfs_emubd_ops, +}}; + int main() {{ lfs_emubd_create(&bd, "blocks"); diff --git a/tests/test_dirs.sh b/tests/test_dirs.sh new file mode 100755 index 0000000..00304b3 --- /dev/null +++ b/tests/test_dirs.sh @@ -0,0 +1,59 @@ +#!/bin/bash +set -eu + +echo "=== Directory tests ===" +rm -rf blocks + +echo "--- Root directory ---" +tests/test.py << TEST + lfs_format(&lfs, &config) => 0; + + lfs_dir_open(&lfs, &dir[0], "/") => 0; + lfs_dir_close(&lfs, &dir[0]) => 0; +TEST + +echo "--- Directory creation ---" +tests/test.py << TEST + lfs_mount(&lfs, &config) => 0; + lfs_mkdir(&lfs, "potato") => 0; + lfs_unmount(&lfs) => 0; +TEST + +echo "--- File creation ---" +tests/test.py << TEST + lfs_mount(&lfs, &config) => 0; + lfs_file_open(&lfs, &file[0], "burito", LFS_O_CREAT | LFS_O_WRONLY) => 0; + lfs_file_close(&lfs, &file[0]) => 0; + lfs_unmount(&lfs) => 0; +TEST + +echo "--- Directory iteration ---" +tests/test.py << TEST + lfs_mount(&lfs, &config) => 0; + lfs_dir_open(&lfs, &dir[0], "/") => 0; + lfs_dir_read(&lfs, &dir[0], &info) => 1; + strcmp(info.name, ".") => 0; + lfs_dir_read(&lfs, &dir[0], &info) => 1; + strcmp(info.name, "..") => 0; + lfs_dir_read(&lfs, &dir[0], &info) => 1; + strcmp(info.name, "potato") => 0; + lfs_dir_read(&lfs, &dir[0], &info) => 1; + strcmp(info.name, "burito") => 0; + lfs_dir_read(&lfs, &dir[0], &info) => 0; + lfs_dir_close(&lfs, &dir[0]) => 0; + lfs_unmount(&lfs) => 0; +TEST + +echo "--- Directory failures ---" +tests/test.py << TEST + lfs_mount(&lfs, &config) => 0; + lfs_mkdir(&lfs, "potato") => LFS_ERROR_EXISTS; + lfs_dir_open(&lfs, &dir[0], "tomato") => LFS_ERROR_NO_ENTRY; + lfs_dir_open(&lfs, &dir[0], "burito") => LFS_ERROR_NOT_DIR; + lfs_file_open(&lfs, &file[0], "tomato", LFS_O_RDONLY) => LFS_ERROR_NO_ENTRY; + lfs_file_open(&lfs, &file[0], "potato", LFS_O_RDONLY) => LFS_ERROR_IS_DIR; + lfs_unmount(&lfs) => 0; +TEST + +echo "--- Results ---" +tests/stats.py diff --git a/tests/test_format.sh b/tests/test_format.sh index cca00ee..1e12885 100755 --- a/tests/test_format.sh +++ b/tests/test_format.sh @@ -5,41 +5,41 @@ echo "=== Formatting tests ===" rm -rf blocks echo "--- Basic formatting ---" -./tests/test.py << TEST - lfs_format(&lfs, &bd, &lfs_emubd_ops) => 0; +tests/test.py << TEST + lfs_format(&lfs, &config) => 0; TEST echo "--- Invalid superblocks ---" ln -f -s /dev/null blocks/0 -./tests/test.py << TEST - lfs_format(&lfs, &bd, &lfs_emubd_ops) => LFS_ERROR_CORRUPT; +tests/test.py << TEST + lfs_format(&lfs, &config) => LFS_ERROR_CORRUPT; TEST rm blocks/0 echo "--- Basic mounting ---" -./tests/test.py << TEST - lfs_mount(&lfs, &bd, &lfs_emubd_ops) => 0; +tests/test.py << TEST + lfs_mount(&lfs, &config) => 0; lfs_unmount(&lfs) => 0; TEST echo "--- Invalid mount ---" -./tests/test.py << TEST - lfs_format(&lfs, &bd, &lfs_emubd_ops) => 0; +tests/test.py << TEST + lfs_format(&lfs, &config) => 0; TEST rm blocks/0 blocks/1 -./tests/test.py << TEST - lfs_mount(&lfs, &bd, &lfs_emubd_ops) => LFS_ERROR_CORRUPT; +tests/test.py << TEST + lfs_mount(&lfs, &config) => LFS_ERROR_CORRUPT; TEST echo "--- Valid corrupt mount ---" -./tests/test.py << TEST - lfs_format(&lfs, &bd, &lfs_emubd_ops) => 0; +tests/test.py << TEST + lfs_format(&lfs, &config) => 0; TEST rm blocks/0 -./tests/test.py << TEST - lfs_mount(&lfs, &bd, &lfs_emubd_ops) => 0; +tests/test.py << TEST + lfs_mount(&lfs, &config) => 0; lfs_unmount(&lfs) => 0; TEST echo "--- Results ---" -./tests/stats.py +tests/stats.py |