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