Merge "Revert "app_voicemail: Remove need to subscribe to stasis""
[asterisk/asterisk.git] / tests / test_db.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2011, Digium, Inc.
5  *
6  * Terry Wilson <twilson@digium.com>
7  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  */
18
19 /*!
20  * \file
21  * \brief AstDB Unit Tests
22  *
23  * \author Terry Wilson <twilson@digium.com>
24  *
25  */
26
27 /*** MODULEINFO
28         <depend>TEST_FRAMEWORK</depend>
29         <support_level>core</support_level>
30  ***/
31
32 #include "asterisk.h"
33
34 #include "asterisk/test.h"
35 #include "asterisk/module.h"
36 #include "asterisk/astdb.h"
37 #include "asterisk/logger.h"
38
39 enum {
40         FAMILY = 0,
41         KEY    = 1,
42         VALUE  = 2,
43 };
44
45 /* Longest value we can support is 256 for family/key/ so, with
46  * family = astdbtest and two slashes we are left with 244 bytes */
47 static const char long_val[] = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
48
49 AST_TEST_DEFINE(put_get_del)
50 {
51         int res = AST_TEST_PASS;
52         const char *inputs[][3] = {
53                 {"family", "key", "value"},
54                 {"astdbtest", "a", "b"},
55                 {"astdbtest", "a", "a"},
56                 {"astdbtest", "b", "a"},
57                 {"astdbtest", "b", "b"},
58                 {"astdbtest", "b", "!@#$%^&*()|+-<>?"},
59                 {"astdbtest", long_val, "b"},
60                 {"astdbtest", "b", long_val},
61                 {"astdbtest", "!@#$%^&*()|+-<>?", "b"},
62         };
63         size_t x;
64         char buf[sizeof(long_val)] = { 0, };
65
66         switch (cmd) {
67         case TEST_INIT:
68                 info->name = "put_get_del";
69                 info->category = "/main/astdb/";
70                 info->summary = "ast_db_(put|get|del) unit test";
71                 info->description =
72                         "Ensures that the ast_db put, get, and del functions work";
73                 return AST_TEST_NOT_RUN;
74         case TEST_EXECUTE:
75                 break;
76         }
77
78         for (x = 0; x < ARRAY_LEN(inputs); x++) {
79                 if (ast_db_put(inputs[x][FAMILY], inputs[x][KEY], inputs[x][VALUE])) {
80                         ast_test_status_update(test, "Failed to put %s : %s : %s\n", inputs[x][FAMILY], inputs[x][KEY], inputs[x][VALUE]);
81                         res = AST_TEST_FAIL;
82                 }
83                 if (ast_db_get(inputs[x][FAMILY], inputs[x][KEY], buf, sizeof(buf))) {
84                         ast_test_status_update(test, "Failed to get %s : %s : %s\n", inputs[x][FAMILY], inputs[x][KEY], inputs[x][VALUE]);
85                         res = AST_TEST_FAIL;
86                 } else if (strcmp(buf, inputs[x][VALUE])) {
87                         ast_test_status_update(test, "Failed to match key '%s/%s' value '%s' to '%s'\n", inputs[x][FAMILY], inputs[x][KEY], inputs[x][VALUE], buf);
88                         res = AST_TEST_FAIL;
89                 }
90                 if (ast_db_del(inputs[x][FAMILY], inputs[x][KEY])) {
91                         ast_test_status_update(test, "Failed to del %s : %s\n", inputs[x][FAMILY], inputs[x][KEY]);
92                         res = AST_TEST_FAIL;
93                 }
94         }
95
96         return res;
97 }
98
99 AST_TEST_DEFINE(gettree_deltree)
100 {
101         int res = AST_TEST_PASS;
102         const char *inputs[][3] = {
103 #define BASE "astdbtest"
104 #define SUB1 "one"
105 #define SUB2 "two"
106 #define FAM1 BASE "/" SUB1
107 #define FAM2 BASE "/" SUB2
108                 {FAM1, "one", "blah"},
109                 {FAM1, "two", "bling"},
110                 {FAM1, "three", "blast"},
111                 {FAM2, "one", "blah"},
112                 {FAM2, "two", "bling"},
113                 {FAM2, "three", "blast"},
114         };
115         size_t x;
116         struct ast_db_entry *dbes, *cur;
117         int num_deleted;
118
119         switch (cmd) {
120         case TEST_INIT:
121                 info->name = "gettree_deltree";
122                 info->category = "/main/astdb/";
123                 info->summary = "ast_db_(gettree|deltree) unit test";
124                 info->description =
125                         "Ensures that the ast_db gettree and deltree functions work";
126                 return AST_TEST_NOT_RUN;
127         case TEST_EXECUTE:
128                 break;
129         }
130
131         for (x = 0; x < ARRAY_LEN(inputs); x++) {
132                 if (ast_db_put(inputs[x][FAMILY], inputs[x][KEY], inputs[x][VALUE])) {
133                         ast_test_status_update(test, "Failed to put %s : %s : %s\n", inputs[x][FAMILY], inputs[x][KEY], inputs[x][VALUE]);
134                         res = AST_TEST_FAIL;
135                 }
136         }
137
138         if (!(dbes = ast_db_gettree(BASE, NULL))) {
139                 ast_test_status_update(test, "Failed to ast_db_gettree family %s\n", BASE);
140                 res = AST_TEST_FAIL;
141         }
142
143         for (cur = dbes, x = 0; cur; cur = cur->next, x++) {
144                 int found = 0;
145                 size_t z;
146                 for (z = 0; z < ARRAY_LEN(inputs); z++) {
147                         char buf[256];
148                         snprintf(buf, sizeof(buf), "/%s/%s", inputs[z][FAMILY], inputs[z][KEY]);
149                         if (!strcmp(buf, cur->key) && !strcmp(inputs[z][VALUE], cur->data)) {
150                                 found = 1;
151                         }
152                 }
153                 if (!found) {
154                         ast_test_status_update(test, "inputs array has no entry for %s == %s\n", cur->key, cur->data);
155                         res = AST_TEST_FAIL;
156                 }
157         }
158
159         if (x != ARRAY_LEN(inputs)) {
160                 ast_test_status_update(test, "ast_db_gettree returned %zu entries when we expected %zu\n", x, ARRAY_LEN(inputs));
161                 res = AST_TEST_FAIL;
162         }
163
164         ast_db_freetree(dbes);
165
166         if (!(dbes = ast_db_gettree(BASE, SUB1))) {
167                 ast_test_status_update(test, "Failed to ast_db_gettree for %s/%s\n", BASE, SUB1);
168                 res = AST_TEST_FAIL;
169         }
170
171         for (cur = dbes, x = 0; cur; cur = cur->next, x++) {
172                 int found = 0;
173                 size_t z;
174                 for (z = 0; z < ARRAY_LEN(inputs); z++) {
175                         char buf[256];
176                         snprintf(buf, sizeof(buf), "/%s/%s", inputs[z][FAMILY], inputs[z][KEY]);
177                         if (!strcmp(buf, cur->key) && !strcmp(inputs[z][VALUE], cur->data)) {
178                                 found = 1;
179                         }
180                 }
181                 if (!found) {
182                         ast_test_status_update(test, "inputs array has no entry for %s == %s\n", cur->key, cur->data);
183                         res = AST_TEST_FAIL;
184                 }
185         }
186
187         if (x != (ARRAY_LEN(inputs) / 2)) {
188                 ast_test_status_update(test, "ast_db_gettree returned %zu entries when we expected %zu\n", x, ARRAY_LEN(inputs) / 2);
189                 res = AST_TEST_FAIL;
190         }
191
192         ast_db_freetree(dbes);
193
194         if ((num_deleted = ast_db_deltree(BASE, SUB2)) != ARRAY_LEN(inputs) / 2) {
195                 ast_test_status_update(test, "Failed to deltree %s/%s, expected %zu deletions and got %d\n", BASE, SUB2, ARRAY_LEN(inputs) / 2, num_deleted);
196                 res = AST_TEST_FAIL;
197         }
198
199         if ((num_deleted = ast_db_deltree(BASE, NULL)) != ARRAY_LEN(inputs) / 2) {
200                 ast_test_status_update(test, "Failed to deltree %s, expected %zu deletions and got %d\n", BASE, ARRAY_LEN(inputs) / 2, num_deleted);
201                 res = AST_TEST_FAIL;
202         }
203
204         return res;
205 }
206
207 AST_TEST_DEFINE(perftest)
208 {
209         int res = AST_TEST_PASS;
210         size_t x;
211         char buf[10];
212
213         switch (cmd) {
214         case TEST_INIT:
215                 info->name = "perftest";
216                 info->category = "/main/astdb/";
217                 info->summary = "astdb performance unit test";
218                 info->description =
219                         "Measure astdb performance";
220                 return AST_TEST_NOT_RUN;
221         case TEST_EXECUTE:
222                 break;
223         }
224
225         for (x = 0; x < 100000; x++) {
226                 sprintf(buf, "%zu", x);
227                 ast_db_put("astdbtest", buf, buf);
228         }
229         ast_db_deltree("astdbtest", NULL);
230
231         return res;
232 }
233
234 AST_TEST_DEFINE(put_get_long)
235 {
236         int res = AST_TEST_PASS;
237         struct ast_str *s;
238         int i, j;
239
240 #define STR_FILL_32 "abcdefghijklmnopqrstuvwxyz123456"
241
242         switch (cmd) {
243         case TEST_INIT:
244                 info->name = "put_get_long";
245                 info->category = "/main/astdb/";
246                 info->summary = "ast_db_(put|get_allocated) unit test";
247                 info->description =
248                         "Ensures that the ast_db_put and ast_db_get_allocated functions work";
249                 return AST_TEST_NOT_RUN;
250         case TEST_EXECUTE:
251                 break;
252         }
253
254         if (!(s = ast_str_create(4096))) {
255                 return AST_TEST_FAIL;
256         }
257
258         for (i = 1024; i <= 1024 * 1024 * 8; i *= 2) {
259                 char *out = NULL;
260
261                 ast_str_reset(s);
262
263                 for (j = 0; j < i; j += sizeof(STR_FILL_32) - 1) {
264                         ast_str_append(&s, 0, "%s", STR_FILL_32);
265                 }
266
267                 if (ast_db_put("astdbtest", "long", ast_str_buffer(s))) {
268                         ast_test_status_update(test, "Failed to put value of %zu bytes\n", ast_str_strlen(s));
269                         res = AST_TEST_FAIL;
270                 } else if (ast_db_get_allocated("astdbtest", "long", &out)) {
271                         ast_test_status_update(test, "Failed to get value of %zu bytes\n", ast_str_strlen(s));
272                         res = AST_TEST_FAIL;
273                 } else if (strcmp(ast_str_buffer(s), out)) {
274                         ast_test_status_update(test, "Failed to match value of %zu bytes\n", ast_str_strlen(s));
275                         res = AST_TEST_FAIL;
276                 } else if (ast_db_del("astdbtest", "long")) {
277                         ast_test_status_update(test, "Failed to delete astdbtest/long\n");
278                         res = AST_TEST_FAIL;
279                 }
280
281                 if (out) {
282                         ast_free(out);
283                 }
284         }
285
286         ast_free(s);
287
288         return res;
289 }
290
291 static int unload_module(void)
292 {
293         AST_TEST_UNREGISTER(put_get_del);
294         AST_TEST_UNREGISTER(gettree_deltree);
295         AST_TEST_UNREGISTER(perftest);
296         AST_TEST_UNREGISTER(put_get_long);
297         return 0;
298 }
299
300 static int load_module(void)
301 {
302         AST_TEST_REGISTER(put_get_del);
303         AST_TEST_REGISTER(gettree_deltree);
304         AST_TEST_REGISTER(perftest);
305         AST_TEST_REGISTER(put_get_long);
306         return AST_MODULE_LOAD_SUCCESS;
307 }
308
309 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "AstDB test module");