Fix UPGRADE.txt Due To Merging From Branch 11
[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 ASTERISK_FILE_VERSION(__FILE__, "")
35
36 #include "asterisk/test.h"
37 #include "asterisk/module.h"
38 #include "asterisk/astdb.h"
39 #include "asterisk/logger.h"
40
41 enum {
42         FAMILY = 0,
43         KEY    = 1,
44         VALUE  = 2,
45 };
46
47 /* Longest value we can support is 256 for family/key/ so, with
48  * family = astdbtest and two slashes we are left with 244 bytes */
49 static const char long_val[] = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
50
51 AST_TEST_DEFINE(put_get_del)
52 {
53         int res = AST_TEST_PASS;
54         const char *inputs[][3] = {
55                 {"family", "key", "value"},
56                 {"astdbtest", "a", "b"},
57                 {"astdbtest", "a", "a"},
58                 {"astdbtest", "b", "a"},
59                 {"astdbtest", "b", "b"},
60                 {"astdbtest", "b", "!@#$%^&*()|+-<>?"},
61                 {"astdbtest", long_val, "b"},
62                 {"astdbtest", "b", long_val},
63                 {"astdbtest", "!@#$%^&*()|+-<>?", "b"},
64         };
65         size_t x;
66         char buf[sizeof(long_val)] = { 0, };
67
68         switch (cmd) {
69         case TEST_INIT:
70                 info->name = "put_get_del";
71                 info->category = "/main/astdb/";
72                 info->summary = "ast_db_(put|get|del) unit test";
73                 info->description =
74                         "Ensures that the ast_db put, get, and del functions work";
75                 return AST_TEST_NOT_RUN;
76         case TEST_EXECUTE:
77                 break;
78         }
79
80         for (x = 0; x < ARRAY_LEN(inputs); x++) {
81                 if (ast_db_put(inputs[x][FAMILY], inputs[x][KEY], inputs[x][VALUE])) {
82                         ast_test_status_update(test, "Failed to put %s : %s : %s\n", inputs[x][FAMILY], inputs[x][KEY], inputs[x][VALUE]);
83                         res = AST_TEST_FAIL;
84                 }
85                 if (ast_db_get(inputs[x][FAMILY], inputs[x][KEY], buf, sizeof(buf))) {
86                         ast_test_status_update(test, "Failed to get %s : %s : %s\n", inputs[x][FAMILY], inputs[x][KEY], inputs[x][VALUE]);
87                         res = AST_TEST_FAIL;
88                 } else if (strcmp(buf, inputs[x][VALUE])) {
89                         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);
90                         res = AST_TEST_FAIL;
91                 }
92                 if (ast_db_del(inputs[x][FAMILY], inputs[x][KEY])) {
93                         ast_test_status_update(test, "Failed to del %s : %s\n", inputs[x][FAMILY], inputs[x][KEY]);
94                         res = AST_TEST_FAIL;
95                 }
96         }
97
98         return res;
99 }
100
101 AST_TEST_DEFINE(gettree_deltree)
102 {
103         int res = AST_TEST_PASS;
104         const char *inputs[][3] = {
105 #define BASE "astdbtest"
106 #define SUB1 "one"
107 #define SUB2 "two"
108 #define FAM1 BASE "/" SUB1
109 #define FAM2 BASE "/" SUB2
110                 {FAM1, "one", "blah"},
111                 {FAM1, "two", "bling"},
112                 {FAM1, "three", "blast"},
113                 {FAM2, "one", "blah"},
114                 {FAM2, "two", "bling"},
115                 {FAM2, "three", "blast"},
116         };
117         size_t x;
118         struct ast_db_entry *dbes, *cur;
119         int num_deleted;
120
121         switch (cmd) {
122         case TEST_INIT:
123                 info->name = "gettree_deltree";
124                 info->category = "/main/astdb/";
125                 info->summary = "ast_db_(gettree|deltree) unit test";
126                 info->description =
127                         "Ensures that the ast_db gettree and deltree functions work";
128                 return AST_TEST_NOT_RUN;
129         case TEST_EXECUTE:
130                 break;
131         }
132
133         for (x = 0; x < ARRAY_LEN(inputs); x++) {
134                 if (ast_db_put(inputs[x][FAMILY], inputs[x][KEY], inputs[x][VALUE])) {
135                         ast_test_status_update(test, "Failed to put %s : %s : %s\n", inputs[x][FAMILY], inputs[x][KEY], inputs[x][VALUE]);
136                         res = AST_TEST_FAIL;
137                 }
138         }
139
140         if (!(dbes = ast_db_gettree(BASE, NULL))) {
141                 ast_test_status_update(test, "Failed to ast_db_gettree family %s\n", BASE);
142                 res = AST_TEST_FAIL;
143         }
144
145         for (cur = dbes, x = 0; cur; cur = cur->next, x++) {
146                 int found = 0;
147                 size_t z;
148                 for (z = 0; z < ARRAY_LEN(inputs); z++) {
149                         char buf[256];
150                         snprintf(buf, sizeof(buf), "/%s/%s", inputs[z][FAMILY], inputs[z][KEY]);
151                         if (!strcmp(buf, cur->key) && !strcmp(inputs[z][VALUE], cur->data)) {
152                                 found = 1;
153                         }
154                 }
155                 if (!found) {
156                         ast_test_status_update(test, "inputs array has no entry for %s == %s\n", cur->key, cur->data);
157                         res = AST_TEST_FAIL;
158                 }
159         }
160
161         if (x != ARRAY_LEN(inputs)) {
162                 ast_test_status_update(test, "ast_db_gettree returned %zu entries when we expected %zu\n", x, ARRAY_LEN(inputs));
163                 res = AST_TEST_FAIL;
164         }
165
166         ast_db_freetree(dbes);
167
168         if (!(dbes = ast_db_gettree(BASE, SUB1))) {
169                 ast_test_status_update(test, "Failed to ast_db_gettree for %s/%s\n", BASE, SUB1);
170                 res = AST_TEST_FAIL;
171         }
172
173         for (cur = dbes, x = 0; cur; cur = cur->next, x++) {
174                 int found = 0;
175                 size_t z;
176                 for (z = 0; z < ARRAY_LEN(inputs); z++) {
177                         char buf[256];
178                         snprintf(buf, sizeof(buf), "/%s/%s", inputs[z][FAMILY], inputs[z][KEY]);
179                         if (!strcmp(buf, cur->key) && !strcmp(inputs[z][VALUE], cur->data)) {
180                                 found = 1;
181                         }
182                 }
183                 if (!found) {
184                         ast_test_status_update(test, "inputs array has no entry for %s == %s\n", cur->key, cur->data);
185                         res = AST_TEST_FAIL;
186                 }
187         }
188
189         if (x != (ARRAY_LEN(inputs) / 2)) {
190                 ast_test_status_update(test, "ast_db_gettree returned %zu entries when we expected %zu\n", x, ARRAY_LEN(inputs) / 2);
191                 res = AST_TEST_FAIL;
192         }
193
194         ast_db_freetree(dbes);
195
196         if ((num_deleted = ast_db_deltree(BASE, SUB2)) != ARRAY_LEN(inputs) / 2) {
197                 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);
198                 res = AST_TEST_FAIL;
199         }
200
201         if ((num_deleted = ast_db_deltree(BASE, NULL)) != ARRAY_LEN(inputs) / 2) {
202                 ast_test_status_update(test, "Failed to deltree %s, expected %zu deletions and got %d\n", BASE, ARRAY_LEN(inputs) / 2, num_deleted);
203                 res = AST_TEST_FAIL;
204         }
205
206         return res;
207 }
208
209 AST_TEST_DEFINE(perftest)
210 {
211         int res = AST_TEST_PASS;
212         size_t x;
213         char buf[10];
214
215         switch (cmd) {
216         case TEST_INIT:
217                 info->name = "perftest";
218                 info->category = "/main/astdb/";
219                 info->summary = "astdb performance unit test";
220                 info->description =
221                         "Measure astdb performance";
222                 return AST_TEST_NOT_RUN;
223         case TEST_EXECUTE:
224                 break;
225         }
226
227         for (x = 0; x < 100000; x++) {
228                 sprintf(buf, "%zu", x);
229                 ast_db_put("astdbtest", buf, buf);
230         }
231         ast_db_deltree("astdbtest", NULL);
232
233         return res;
234 }
235
236 AST_TEST_DEFINE(put_get_long)
237 {
238         int res = AST_TEST_PASS;
239         struct ast_str *s;
240         int i, j;
241
242 #define STR_FILL_32 "abcdefghijklmnopqrstuvwxyz123456"
243
244         switch (cmd) {
245         case TEST_INIT:
246                 info->name = "put_get_long";
247                 info->category = "/main/astdb/";
248                 info->summary = "ast_db_(put|get_allocated) unit test";
249                 info->description =
250                         "Ensures that the ast_db_put and ast_db_get_allocated functions work";
251                 return AST_TEST_NOT_RUN;
252         case TEST_EXECUTE:
253                 break;
254         }
255
256         if (!(s = ast_str_create(4096))) {
257                 return AST_TEST_FAIL;
258         }
259
260         for (i = 1024; i <= 1024 * 1024 * 8; i *= 2) {
261                 char *out = NULL;
262
263                 ast_str_reset(s);
264
265                 for (j = 0; j < i; j += sizeof(STR_FILL_32) - 1) {
266                         ast_str_append(&s, 0, "%s", STR_FILL_32);
267                 }
268
269                 if (ast_db_put("astdbtest", "long", ast_str_buffer(s))) {
270                         ast_test_status_update(test, "Failed to put value of %zu bytes\n", ast_str_strlen(s));
271                         res = AST_TEST_FAIL;
272                 } else if (ast_db_get_allocated("astdbtest", "long", &out)) {
273                         ast_test_status_update(test, "Failed to get value of %zu bytes\n", ast_str_strlen(s));
274                         res = AST_TEST_FAIL;
275                 } else if (strcmp(ast_str_buffer(s), out)) {
276                         ast_test_status_update(test, "Failed to match value of %zu bytes\n", ast_str_strlen(s));
277                         res = AST_TEST_FAIL;
278                 } else if (ast_db_del("astdbtest", "long")) {
279                         ast_test_status_update(test, "Failed to delete astdbtest/long\n");
280                         res = AST_TEST_FAIL;
281                 }
282
283                 if (out) {
284                         ast_free(out);
285                 }
286         }
287
288         ast_free(s);
289
290         return res;
291 }
292
293 static int unload_module(void)
294 {
295         AST_TEST_UNREGISTER(put_get_del);
296         AST_TEST_UNREGISTER(gettree_deltree);
297         AST_TEST_UNREGISTER(perftest);
298         AST_TEST_UNREGISTER(put_get_long);
299         return 0;
300 }
301
302 static int load_module(void)
303 {
304         AST_TEST_REGISTER(put_get_del);
305         AST_TEST_REGISTER(gettree_deltree);
306         AST_TEST_REGISTER(perftest);
307         AST_TEST_REGISTER(put_get_long);
308         return AST_MODULE_LOAD_SUCCESS;
309 }
310
311 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "AstDB test module");