Asterisk - The Open Source Telephony Project GIT-master-f36a736
test_db.c
Go to the documentation of this file.
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
39enum {
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 */
47static const char long_val[] = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
48
49AST_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
99AST_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
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
234AST_TEST_DEFINE(put_get_long)
235{
236 int res = AST_TEST_PASS;
237 struct ast_str *s;
238 struct ast_str *key;
239 int i, j;
240
241#define STR_FILL_32 "abcdefghijklmnopqrstuvwxyz123456"
242
243 switch (cmd) {
244 case TEST_INIT:
245 info->name = "put_get_long";
246 info->category = "/main/astdb/";
247 info->summary = "ast_db_(put|get_allocated) unit test";
248 info->description =
249 "Ensures that the ast_db_put and ast_db_get_allocated functions work with log key and long data";
250 return AST_TEST_NOT_RUN;
251 case TEST_EXECUTE:
252 break;
253 }
254
255 if (!(s = ast_str_create(4096))) {
256 return AST_TEST_FAIL;
257 }
258
259 if (!(key = ast_str_create(512))) {
260 return AST_TEST_FAIL;
261 }
262
263 for (j = 0; j < 512; j += sizeof(STR_FILL_32) - 1) {
264 ast_str_append(&key, 0, "%s", STR_FILL_32);
265 }
266
267 for (i = 1024; i <= 1024 * 1024 * 8; i *= 2) {
268 char *out = NULL;
269
270 ast_str_reset(s);
271 ast_str_reset(key);
272
273 for (j = 0; j < i; j += sizeof(STR_FILL_32) - 1) {
274 ast_str_append(&s, 0, "%s", STR_FILL_32);
275 }
276
277 if (ast_db_put("astdbtest", ast_str_buffer(key), ast_str_buffer(s))) {
278 ast_test_status_update(test, "Failed to put value of %zu bytes\n", ast_str_strlen(s));
279 res = AST_TEST_FAIL;
280 } else if (ast_db_get_allocated("astdbtest", ast_str_buffer(key), &out)) {
281 ast_test_status_update(test, "Failed to get value of %zu bytes\n", ast_str_strlen(s));
282 res = AST_TEST_FAIL;
283 } else if (strcmp(ast_str_buffer(s), out)) {
284 ast_test_status_update(test, "Failed to match value of %zu bytes\n", ast_str_strlen(s));
285 res = AST_TEST_FAIL;
286 } else if (ast_db_del("astdbtest", ast_str_buffer(key))) {
287 ast_test_status_update(test, "Failed to delete astdbtest/long\n");
288 res = AST_TEST_FAIL;
289 }
290
291 if (out) {
292 ast_free(out);
293 }
294 }
295
296 ast_free(s);
297 ast_free(key);
298
299 return res;
300}
301
302static int unload_module(void)
303{
304 AST_TEST_UNREGISTER(put_get_del);
305 AST_TEST_UNREGISTER(gettree_deltree);
306 AST_TEST_UNREGISTER(perftest);
307 AST_TEST_UNREGISTER(put_get_long);
308 return 0;
309}
310
311static int load_module(void)
312{
313 AST_TEST_REGISTER(put_get_del);
314 AST_TEST_REGISTER(gettree_deltree);
315 AST_TEST_REGISTER(perftest);
316 AST_TEST_REGISTER(put_get_long);
318}
319
Persistent data storage (akin to *doze registry)
int ast_db_put(const char *family, const char *key, const char *value)
Store value addressed by family/key.
Definition: main/db.c:341
int ast_db_get_allocated(const char *family, const char *key, char **out)
Get key value specified by family/key as a heap allocated string.
Definition: main/db.c:437
int ast_db_get(const char *family, const char *key, char *value, int valuelen)
Get key value specified by family/key.
Definition: main/db.c:427
int ast_db_del(const char *family, const char *key)
Delete entry in astdb.
Definition: main/db.c:478
struct ast_db_entry * ast_db_gettree(const char *family, const char *keytree)
Get a list of values within the astdb tree.
Definition: main/db.c:641
int ast_db_deltree(const char *family, const char *keytree)
Delete one or more entries in astdb.
Definition: main/db.c:565
void ast_db_freetree(struct ast_db_entry *entry)
Free structure created by ast_db_gettree()
Definition: main/db.c:701
Asterisk main include file. File version handling, generic pbx functions.
#define ast_free(a)
Definition: astmm.h:180
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
Support for logging to various files, console and syslog Configuration in file logger....
Asterisk module definitions.
#define AST_MODULE_INFO_STANDARD(keystr, desc)
Definition: module.h:581
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:46
@ AST_MODULE_LOAD_SUCCESS
Definition: module.h:70
def info(msg)
#define NULL
Definition: resample.c:96
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
Definition: strings.h:1139
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:761
void ast_str_reset(struct ast_str *buf)
Reset the content of a dynamic string. Useful before a series of ast_str_append.
Definition: strings.h:693
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
Definition: strings.h:659
size_t ast_str_strlen(const struct ast_str *buf)
Returns the current length of the string stored within buf.
Definition: strings.h:730
Definition: astdb.h:31
struct ast_db_entry * next
Definition: astdb.h:32
char * key
Definition: astdb.h:33
char data[0]
Definition: astdb.h:34
Support for dynamic strings.
Definition: strings.h:623
Test Framework API.
@ TEST_INIT
Definition: test.h:200
@ TEST_EXECUTE
Definition: test.h:201
#define AST_TEST_REGISTER(cb)
Definition: test.h:127
#define ast_test_status_update(a, b, c...)
Definition: test.h:129
#define AST_TEST_UNREGISTER(cb)
Definition: test.h:128
@ AST_TEST_PASS
Definition: test.h:195
@ AST_TEST_FAIL
Definition: test.h:196
@ AST_TEST_NOT_RUN
Definition: test.h:194
#define FAM1
AST_TEST_DEFINE(put_get_del)
Definition: test_db.c:49
#define SUB2
#define STR_FILL_32
#define BASE
static const char long_val[]
Definition: test_db.c:47
#define SUB1
static int load_module(void)
Definition: test_db.c:311
#define FAM2
@ KEY
Definition: test_db.c:41
@ FAMILY
Definition: test_db.c:40
@ VALUE
Definition: test_db.c:42
static int unload_module(void)
Definition: test_db.c:302
FILE * out
Definition: utils/frame.c:33
#define ARRAY_LEN(a)
Definition: utils.h:666