summaryrefslogtreecommitdiffstats
path: root/src/lib-dict-extra/test-dict-fs.c
blob: a7b9905b4a06efbe2c37e5ee88066eae1dab79aa (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
#include <errno.h>
#include <sys/stat.h>
#include "lib.h"
#include "unlink-directory.h"
#include "test-common.h"
#include "dict-private.h"

static void test_dict_set_get(struct dict *dict, const char *key,
			     const char *value)
{
	const char *got_value, *error;
	struct dict_op_settings set = {
		.username = "testuser",
	};
	struct dict_transaction_context *t = dict_transaction_begin(dict, &set);
	dict_set(t, key, value);
	if (dict_transaction_commit(&t, &error) < 0)
		i_fatal("dict_transaction_commit(%s) failed: %s", key, error);
	if (dict_lookup(dict, &set, pool_datastack_create(), key, &got_value,
			&error) < 0)
		i_fatal("dict_lookup(%s) failed: %s", key, error);
	test_assert_strcmp(got_value, value);
}

static bool test_file_exists(const char *path)
{
	struct stat st;
	if (stat(path, &st) < 0) {
		if (ENOTFOUND(errno)) return FALSE;
		i_fatal("stat(%s) failed: %m", path);
	}
	return TRUE;
}

static void test_dict_fs_set_get(void)
{
	test_begin("dict-fs get/set");
	const char *error;
	struct dict *dict;
	struct dict_settings set = {
		.base_dir = ".",
	};
	if (dict_init("fs:posix:prefix=.test-dict/", &set, &dict, &error) < 0)
		i_fatal("dict_init() failed: %s", error);

	/* shared paths */
	struct {
		const char *key;
		const char *path;
	} test_cases[] = {
		{ "shared/./key", ".test-dict/.../key" },
		{ "shared/../key", ".test-dict/..../key" },
		{ "shared/.../key", ".test-dict/...../key" },
		{ "shared/..../key", ".test-dict/....../key" },
		{ "shared/...../key", ".test-dict/......./key" },
		{ "shared/key/.", ".test-dict/key/..." },
		{ "shared/key/..", ".test-dict/key/...." },
		{ "shared/key/...", ".test-dict/key/....." },
		{ "shared/key/....", ".test-dict/key/......" },
		{ "shared/key/.....", ".test-dict/key/......." },
		{ "shared/key/.key", ".test-dict/key/.key" },
		{ "shared/key/..key", ".test-dict/key/..key" },
		{ "shared/key/...key", ".test-dict/key/...key" },
		{ "shared/.key/key", ".test-dict/.key/key" },
		{ "shared/..key/key", ".test-dict/..key/key" },
		{ "shared/...key/key", ".test-dict/...key/key" },
	};
	for (size_t i = 0; i < N_ELEMENTS(test_cases); i++) {
		test_dict_set_get(dict, test_cases[i].key, "1");
		test_assert(test_file_exists(test_cases[i].path));
	}

	/* per user paths */
	test_dict_set_get(dict, "priv/value", "priv1");
	test_assert(test_file_exists(".test-dict/testuser/value"));
	test_dict_set_get(dict, "priv/path/with/value", "priv2");
	test_assert(test_file_exists(".test-dict/testuser/path/with/value"));

	/* check that dots work correctly */
	test_dict_set_get(dict, "shared/../test-dict-fs.c", "3");
	test_assert(test_file_exists(".test-dict/..../test-dict-fs.c"));
	test_dict_set_get(dict, "shared/./test", "4");
	test_assert(test_file_exists(".test-dict/.../test"));
	test_dict_set_get(dict, "shared/.test", "5");
	test_assert(test_file_exists(".test-dict/.test"));
	test_dict_set_get(dict, "shared/..test", "6");
	test_assert(test_file_exists(".test-dict/..test"));
	dict_deinit(&dict);

	if (unlink_directory(".test-dict", UNLINK_DIRECTORY_FLAG_RMDIR, &error) < 0)
		i_fatal("unlink_directory(.test_dict) failed: %s", error);
	test_end();
}

int main(void)
{
	static void (*const test_functions[])(void) = {
		test_dict_fs_set_get,
		NULL
	};
	int ret;
	dict_driver_register(&dict_driver_fs);
	ret = test_run(test_functions);
	dict_driver_unregister(&dict_driver_fs);
	return ret;
}