summaryrefslogtreecommitdiffstats
path: root/src/lib-settings/test-settings.c
blob: 4ad2a6b562395ca225a555fa13a7fd2b7dd2986f (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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
/* Copyright (c) 2021 Dovecot authors, see the included COPYING file */

#include "lib.h"
#include "array.h"
#include "net.h"
#include "settings.h"
#include "istream.h"
#include "ostream.h"
#include "test-common.h"

#define TEST_SETTING_FILE ".test_settings.conf"

static const char *config_contents =
"# this is a comment\n"
"str = value\n"
"str2 = some other value # and this should be ignored\n"
"str3 = $ENV:test\n"
"str4 = $ENV:test %{second}\n"
"str5 = Hello $ENV:test\n"
"str6 = foo$ENV:test bar\n"
"str7 = \"this is $ENV:test string literal\"\n"
"str8 = \\$ENV:test escaped\n"
"str9 = $ENV:FOO$ENV:FOO bar\n"
"str10 = \\$escape \\escape \\\"escape\\\"\n"
"str11 = 'this is $ENV:test string literal'\n"
"str12 = $ENV:test $ENV:test\n"
"b_true = yes\n"
"b_false = no\n"
"number = 1234\n";

struct test_settings {
	const char *str;
	const char *str2;
	const char *str3;
	const char *str4;
	const char *str5;
	const char *str6;
	const char *str7;
	const char *str8;
	const char *str9;
	const char *str10;
	const char *str11;
	const char *str12;

	bool b_true;
	bool b_false;
	unsigned int number;
};

#undef DEF_STR
#undef DEF_BOOL
#undef DEF_INT

#define DEF_STR(name) DEF_STRUCT_STR(name, test_settings)
#define DEF_BOOL(name) DEF_STRUCT_BOOL(name, test_settings)
#define DEF_INT(name) DEF_STRUCT_INT(name, test_settings)

static struct setting_def setting_defs[] = {
	DEF_STR(str),
	DEF_STR(str2),
	DEF_STR(str3),
	DEF_STR(str4),
	DEF_STR(str5),
	DEF_STR(str6),
	DEF_STR(str7),
	DEF_STR(str8),
	DEF_STR(str9),
	DEF_STR(str10),
	DEF_STR(str11),
	DEF_STR(str12),
	DEF_BOOL(b_true),
	DEF_BOOL(b_false),
	DEF_INT(number),
	{ 0, NULL, 0 }
};

static struct test_settings default_settings = {
	.str   = "",
	.str2  = "",
	.str3  = "",
	.str4  = "",
	.str5  = "",
	.str6  = "",
	.str7  = "",
	.str8  = "",
	.str9  = "",
	.str10 = "",
	.str11 = "",
	.str12 = "",

	.b_true = FALSE,
	.b_false = TRUE,
	.number = 0,
};

struct test_settings_context {
	pool_t pool;
	struct test_settings set;
};

static const char *parse_setting(const char *key, const char *value,
				 struct test_settings_context *ctx)
{
	return parse_setting_from_defs(ctx->pool, setting_defs,
				       &ctx->set, key, value);
}

static void test_settings_read_nosection(void)
{
	test_begin("settings_read_nosection");

	const char *error = NULL;
	/* write a simple config file */
	struct ostream *os = o_stream_create_file(TEST_SETTING_FILE, 0, 0600, 0);
	o_stream_nsend_str(os, config_contents);
	test_assert(o_stream_finish(os) == 1);
	o_stream_unref(&os);

	putenv("test=first");
	putenv("FOO$ENV:FOO=works");
	/* try parse it */
	pool_t pool = pool_alloconly_create("test settings", 1024);
	struct test_settings_context *ctx =
		p_new(pool, struct test_settings_context, 1);
	ctx->pool = pool;
	ctx->set = default_settings;

	test_assert(settings_read_nosection(TEST_SETTING_FILE, parse_setting,
					    ctx, &error));
	test_assert(error == NULL);
	if (error != NULL)
		i_error("%s", error);

	/* see what we got */
	test_assert_strcmp(ctx->set.str, "value");
	test_assert_strcmp(ctx->set.str2, "some other value");
	test_assert_strcmp(ctx->set.str3, "first");
	test_assert_strcmp(ctx->set.str4, "first %{second}");
	test_assert_strcmp(ctx->set.str5, "Hello first");
	test_assert_strcmp(ctx->set.str6, "foo$ENV:test bar");
	test_assert_strcmp(ctx->set.str7, "this is $ENV:test string literal");
	test_assert_strcmp(ctx->set.str8, "\\$ENV:test escaped");
	test_assert_strcmp(ctx->set.str9, "works bar");
	test_assert_strcmp(ctx->set.str10, "\\$escape \\escape \\\"escape\\\"");
	test_assert_strcmp(ctx->set.str11, "this is $ENV:test string literal");
	test_assert_strcmp(ctx->set.str12, "first first");

	test_assert(ctx->set.b_true == TRUE);
	test_assert(ctx->set.b_false == FALSE);
	test_assert(ctx->set.number == 1234);

	pool_unref(&pool);

	i_unlink_if_exists(TEST_SETTING_FILE);
	test_end();
}

int main(void)
{
	static void (*const test_functions[])(void) = {
		test_settings_read_nosection,
		NULL
	};
	return test_run(test_functions);
}