Skip to content

Commit

Permalink
lib-fs: Improved unit tests.
Browse files Browse the repository at this point in the history
  • Loading branch information
sirainen committed Jun 2, 2016
1 parent f412ee7 commit 1d29d49
Show file tree
Hide file tree
Showing 5 changed files with 191 additions and 11 deletions.
1 change: 1 addition & 0 deletions src/lib-fs/Makefile.am
Expand Up @@ -14,6 +14,7 @@ libfs_la_SOURCES = \
fs-randomfail.c \
fs-posix.c \
fs-test.c \
fs-test-async.c \
fs-sis.c \
fs-sis-common.c \
fs-sis-queue.c \
Expand Down
97 changes: 97 additions & 0 deletions src/lib-fs/fs-test-async.c
@@ -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);
}
85 changes: 76 additions & 9 deletions src/lib-fs/fs-test.c
Expand Up @@ -40,17 +40,19 @@ static enum fs_properties fs_test_get_properties(struct fs *_fs)

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;
}

Expand Down Expand Up @@ -102,6 +104,16 @@ static int
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;
Expand Down Expand Up @@ -132,6 +144,8 @@ fs_test_read_stream(struct fs_file *_file, size_t max_buffer_size ATTR_UNUSED)

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);
Expand All @@ -155,6 +169,14 @@ static int fs_test_write_stream_finish(struct fs_file *_file, bool success)
{
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;
Expand Down Expand Up @@ -186,13 +208,29 @@ static int fs_test_exists(struct fs_file *_file)
{
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;
}

static int fs_test_stat(struct fs_file *_file, struct stat *st_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;
}
if (!file->exists) {
errno = ENOENT;
return -1;
Expand All @@ -204,9 +242,22 @@ static int fs_test_stat(struct fs_file *_file, struct stat *st_r)

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;
Expand All @@ -220,6 +271,12 @@ static int fs_test_copy(struct fs_file *_src, struct fs_file *_dest)
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;
Expand All @@ -231,6 +288,11 @@ static int fs_test_delete(struct fs_file *_file)
{
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;
Expand Down Expand Up @@ -302,21 +364,26 @@ static int fs_test_iter_deinit(struct fs_iter *_iter)
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;
}

struct test_fs_file *test_fs_file_get(struct fs *fs, const char *path)
{
struct fs_file *file;

fs = &test_fs_get(fs)->fs;

file = fs->files;
for (; n > 0; n--) {
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;
}

Expand Down
9 changes: 8 additions & 1 deletion src/lib-fs/fs-test.h
Expand Up @@ -18,12 +18,15 @@ struct test_fs_file {

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 {
Expand All @@ -33,6 +36,10 @@ struct test_fs_iter {
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
10 changes: 9 additions & 1 deletion src/lib-fs/test-fs-metawrap.c
Expand Up @@ -26,7 +26,7 @@ static void test_fs_metawrap_stat(void)
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) {
Expand All @@ -46,10 +46,18 @@ static void test_fs_metawrap_stat(void)
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);
Expand Down

0 comments on commit 1d29d49

Please sign in to comment.