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