Mercurial > dovecot > core-2.2
changeset 20240:5142d4fbf69b
lib-fs: Improved unit tests.
author | Timo Sirainen <timo.sirainen@dovecot.fi> |
---|---|
date | Wed, 01 Jun 2016 17:12:51 +0300 |
parents | 6b546cab619f |
children | 1309caf0ca75 |
files | src/lib-fs/Makefile.am src/lib-fs/fs-test-async.c src/lib-fs/fs-test.c src/lib-fs/fs-test.h src/lib-fs/test-fs-metawrap.c |
diffstat | 5 files changed, 191 insertions(+), 11 deletions(-) [+] |
line wrap: on
line diff
--- a/src/lib-fs/Makefile.am Wed Jun 01 17:12:10 2016 +0300 +++ b/src/lib-fs/Makefile.am Wed Jun 01 17:12:51 2016 +0300 @@ -14,6 +14,7 @@ fs-randomfail.c \ fs-posix.c \ fs-test.c \ + fs-test-async.c \ fs-sis.c \ fs-sis-common.c \ fs-sis-queue.c \
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/lib-fs/fs-test-async.c Wed Jun 01 17:12:51 2016 +0300 @@ -0,0 +1,97 @@ +/* Copyright (c) 2016 Dovecot authors, see the included COPYING file */ + +#include "lib.h" +#include "str.h" +#include "ostream.h" +#include "fs-test.h" +#include "test-common.h" + +static void test_fs_async_write(const char *test_name, struct fs *fs) +{ + struct fs_file *file; + struct test_fs_file *test_file; + struct ostream *output; + unsigned int i; + + test_begin(t_strdup_printf("%s: async write", test_name)); + for (i = 0; i < 3; i++) { + file = fs_file_init(fs, "foo", FS_OPEN_MODE_REPLACE | + FS_OPEN_FLAG_ASYNC); + output = fs_write_stream(file); + + o_stream_nsend_str(output, "12345"); + if (i < 2) { + test_assert(fs_write_stream_finish(file, &output) == 0); + test_assert(output == NULL); + test_assert(fs_write_stream_finish_async(file) == 0); + } + + test_file = test_fs_file_get(fs, "foo"); + test_file->wait_async = FALSE; + + switch (i) { + case 0: + test_assert(fs_write_stream_finish_async(file) > 0); + test_assert(test_file->contents->used > 0); + break; + case 1: + test_file->io_failure = TRUE; + test_assert(fs_write_stream_finish_async(file) < 0); + test_assert(test_file->contents->used == 0); + break; + case 2: + fs_write_stream_abort(file, &output); + test_assert(test_file->contents->used == 0); + break; + } + fs_file_deinit(&file); + } + test_end(); +} + +static void test_fs_async_copy(const char *test_name, struct fs *fs) +{ + struct fs_file *src, *dest; + struct test_fs_file *test_file; + + test_begin(t_strdup_printf("%s: async copy", test_name)); + + src = fs_file_init(fs, "foo", FS_OPEN_MODE_REPLACE); + test_assert(fs_write(src, "source", 6) == 0); + + dest = fs_file_init(fs, "bar", FS_OPEN_MODE_REPLACE | + FS_OPEN_FLAG_ASYNC); + + test_assert(fs_copy(src, dest) == -1 && errno == EAGAIN); + + test_file = test_fs_file_get(fs, "bar"); + test_file->wait_async = FALSE; + + test_assert(fs_copy_finish_async(dest) == 0); + test_assert(test_file->contents->used > 0); + fs_file_deinit(&dest); + + fs_file_deinit(&src); + test_end(); +} + +void test_fs_async(const char *test_name, enum fs_properties properties, + const char *driver, const char *args) +{ + struct fs_settings fs_set; + struct fs *fs; + struct test_fs *test_fs; + const char *error; + + memset(&fs_set, 0, sizeof(fs_set)); + if (fs_init(driver, args, &fs_set, &fs, &error) < 0) + i_fatal("fs_init() failed: %s", error); + + test_fs = test_fs_get(fs); + test_fs->properties = properties; + + test_fs_async_write(test_name, fs); + test_fs_async_copy(test_name, fs); + + fs_deinit(&fs); +}
--- a/src/lib-fs/fs-test.c Wed Jun 01 17:12:10 2016 +0300 +++ b/src/lib-fs/fs-test.c Wed Jun 01 17:12:51 2016 +0300 @@ -40,17 +40,19 @@ static struct fs_file * fs_test_file_init(struct fs *_fs, const char *path, - enum fs_open_mode mode, enum fs_open_flags flags ATTR_UNUSED) + enum fs_open_mode mode, enum fs_open_flags flags) { struct test_fs_file *file; file = i_new(struct test_fs_file, 1); file->file.fs = _fs; file->file.path = i_strdup(path); + file->file.flags = flags; file->mode = mode; file->contents = buffer_create_dynamic(default_pool, 1024); file->exists = TRUE; file->seekable = TRUE; + file->wait_async = (flags & FS_OPEN_FLAG_ASYNC) != 0; return &file->file; } @@ -102,6 +104,16 @@ fs_test_get_metadata(struct fs_file *_file, const ARRAY_TYPE(fs_metadata) **metadata_r) { + struct test_fs_file *file = (struct test_fs_file *)_file; + + if (file->wait_async) { + fs_set_error_async(_file->fs); + return -1; + } + if (file->io_failure) { + errno = EIO; + return -1; + } fs_metadata_init(_file); *metadata_r = &_file->metadata; return 0; @@ -132,6 +144,8 @@ if (!file->exists) return i_stream_create_error(ENOENT); + if (file->io_failure) + return i_stream_create_error(EIO); input = test_istream_create_data(file->contents->data, file->contents->used); i_stream_add_destroy_callback(input, fs_test_stream_destroyed, file); @@ -155,6 +169,14 @@ { struct test_fs_file *file = (struct test_fs_file *)_file; + if (_file->output != NULL) + o_stream_destroy(&_file->output); + if (file->wait_async) { + fs_set_error_async(_file->fs); + return 0; + } + if (file->io_failure) + success = FALSE; if (!success) buffer_set_used_size(file->contents, 0); return success ? 1 : -1; @@ -186,6 +208,14 @@ { struct test_fs_file *file = (struct test_fs_file *)_file; + if (file->wait_async) { + fs_set_error_async(_file->fs); + return -1; + } + if (file->io_failure) { + errno = EIO; + return -1; + } return file->exists ? 1 : 0; } @@ -193,6 +223,14 @@ { struct test_fs_file *file = (struct test_fs_file *)_file; + if (file->wait_async) { + fs_set_error_async(_file->fs); + return -1; + } + if (file->io_failure) { + errno = EIO; + return -1; + } if (!file->exists) { errno = ENOENT; return -1; @@ -204,9 +242,22 @@ static int fs_test_copy(struct fs_file *_src, struct fs_file *_dest) { - struct test_fs_file *src = (struct test_fs_file *)_src; + struct test_fs_file *src; struct test_fs_file *dest = (struct test_fs_file *)_dest; + if (_src != NULL) + dest->copy_src = test_fs_file_get(_src->fs, fs_file_path(_src)); + src = dest->copy_src; + if (dest->wait_async) { + fs_set_error_async(_dest->fs); + return -1; + } + dest->copy_src = NULL; + + if (dest->io_failure) { + errno = EIO; + return -1; + } if (!src->exists) { errno = ENOENT; return -1; @@ -220,6 +271,12 @@ static int fs_test_rename(struct fs_file *_src, struct fs_file *_dest) { struct test_fs_file *src = (struct test_fs_file *)_src; + struct test_fs_file *dest = (struct test_fs_file *)_dest; + + if (src->wait_async || dest->wait_async) { + fs_set_error_async(_dest->fs); + return -1; + } if (fs_test_copy(_src, _dest) < 0) return -1; @@ -231,6 +288,11 @@ { struct test_fs_file *file = (struct test_fs_file *)_file; + if (file->wait_async) { + fs_set_error_async(_file->fs); + return -1; + } + if (!file->exists) { errno = ENOENT; return -1; @@ -302,21 +364,26 @@ return ret; } -struct test_fs_file *test_fs_file_get(struct fs *fs, unsigned int n) +struct test_fs *test_fs_get(struct fs *fs) { - struct fs_file *file; - while (strcmp(fs->name, "test") != 0) { i_assert(fs->parent != NULL); fs = fs->parent; } + return (struct test_fs *)fs; +} - file = fs->files; - for (; n > 0; n--) { +struct test_fs_file *test_fs_file_get(struct fs *fs, const char *path) +{ + struct fs_file *file; + + fs = &test_fs_get(fs)->fs; + + for (file = fs->files;; file = file->next) { i_assert(file != NULL); - file = file->next; + if (strcmp(fs_file_path(file), path) == 0) + break; } - i_assert(file != NULL); return (struct test_fs_file *)file; }
--- a/src/lib-fs/fs-test.h Wed Jun 01 17:12:10 2016 +0300 +++ b/src/lib-fs/fs-test.h Wed Jun 01 17:12:51 2016 +0300 @@ -18,12 +18,15 @@ buffer_t *contents; struct istream *input; + struct test_fs_file *copy_src; bool prefetched; bool locked; bool exists; bool seekable; bool closed; + bool io_failure; + bool wait_async; }; struct test_fs_iter { @@ -33,6 +36,10 @@ bool failed; }; -struct test_fs_file *test_fs_file_get(struct fs *fs, unsigned int n); +struct test_fs *test_fs_get(struct fs *fs); +struct test_fs_file *test_fs_file_get(struct fs *fs, const char *path); + +void test_fs_async(const char *test_name, enum fs_properties properties, + const char *driver, const char *args); #endif
--- a/src/lib-fs/test-fs-metawrap.c Wed Jun 01 17:12:10 2016 +0300 +++ b/src/lib-fs/test-fs-metawrap.c Wed Jun 01 17:12:51 2016 +0300 @@ -26,7 +26,7 @@ for (i = 0; i < 2; i++) { file = fs_file_init(fs, "foo", FS_OPEN_MODE_READONLY); - test_file = test_fs_file_get(fs, 0); + test_file = test_fs_file_get(fs, "foo"); str_append(test_file->contents, "key:value\n\n12345678901234567890"); if (i == 0) { @@ -46,10 +46,18 @@ test_end(); } +static void test_fs_metawrap_async(void) +{ + test_fs_async("metawrap", FS_PROPERTY_METADATA, "metawrap", "test"); + test_fs_async("metawrap passthrough", 0, "metawrap", "test"); + test_fs_async("double-metawrap", FS_PROPERTY_METADATA, "metawrap", "metawrap:test"); +} + int main(void) { static void (*test_functions[])(void) = { test_fs_metawrap_stat, + test_fs_metawrap_async, NULL }; return test_run(test_functions);