2 * Asterisk -- An open source telephony toolkit.
4 * Copyright (C) 2013, Digium, Inc.
6 * Joshua Colp <jcolp@digium.com>
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.
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.
21 * \brief Sorcery Unit Tests
23 * \author Joshua Colp <jcolp@digium.com>
28 <depend>TEST_FRAMEWORK</depend>
29 <support_level>core</support_level>
34 ASTERISK_FILE_VERSION(__FILE__, "")
36 #include "asterisk/test.h"
37 #include "asterisk/module.h"
38 #include "asterisk/sorcery.h"
39 #include "asterisk/astdb.h"
40 #include "asterisk/logger.h"
42 /*! \brief Dummy sorcery object */
43 struct test_sorcery_object {
44 SORCERY_OBJECT(details);
49 /*! \brief Internal function to allocate a test object */
50 static void *test_sorcery_object_alloc(const char *id)
52 return ast_sorcery_generic_alloc(sizeof(struct test_sorcery_object), NULL);
55 static struct ast_sorcery *alloc_and_initialize_sorcery(void)
57 struct ast_sorcery *sorcery;
59 if (!(sorcery = ast_sorcery_open())) {
63 if ((ast_sorcery_apply_default(sorcery, "test", "astdb", "test") != AST_SORCERY_APPLY_SUCCESS) ||
64 ast_sorcery_internal_object_register(sorcery, "test", test_sorcery_object_alloc, NULL, NULL)) {
65 ast_sorcery_unref(sorcery);
69 ast_sorcery_object_field_register_nodoc(sorcery, "test", "bob", "5", OPT_UINT_T, 0, FLDSET(struct test_sorcery_object, bob));
70 ast_sorcery_object_field_register_nodoc(sorcery, "test", "joe", "10", OPT_UINT_T, 0, FLDSET(struct test_sorcery_object, joe));
75 static void deinitialize_sorcery(struct ast_sorcery *sorcery)
77 ast_db_deltree("test/test", NULL);
78 ast_sorcery_unref(sorcery);
81 AST_TEST_DEFINE(object_create)
83 RAII_VAR(struct ast_sorcery *, sorcery, NULL, deinitialize_sorcery);
84 RAII_VAR(struct test_sorcery_object *, obj, NULL, ao2_cleanup);
89 info->name = "object_create";
90 info->category = "/res/sorcery_astdb/";
91 info->summary = "sorcery astdb object creation unit test";
93 "Test object creation in sorcery using astdb wizard";
94 return AST_TEST_NOT_RUN;
99 if (!(sorcery = alloc_and_initialize_sorcery())) {
100 ast_test_status_update(test, "Failed to open sorcery structure\n");
101 return AST_TEST_FAIL;
104 if (!(obj = ast_sorcery_alloc(sorcery, "test", "blah"))) {
105 ast_test_status_update(test, "Failed to allocate a known object type\n");
106 return AST_TEST_FAIL;
109 if (ast_sorcery_create(sorcery, obj)) {
110 ast_test_status_update(test, "Failed to create object using astdb wizard\n");
111 return AST_TEST_FAIL;
112 } else if (ast_db_get("test/test", "blah", value, sizeof(value))) {
113 ast_test_status_update(test, "Object was apparently created but does not actually exist in astdb\n");
114 return AST_TEST_FAIL;
117 return AST_TEST_PASS;
120 AST_TEST_DEFINE(object_retrieve_id)
122 RAII_VAR(struct ast_sorcery *, sorcery, NULL, deinitialize_sorcery);
123 RAII_VAR(struct test_sorcery_object *, obj, NULL, ao2_cleanup);
127 info->name = "object_retrieve_id";
128 info->category = "/res/sorcery_astdb/";
129 info->summary = "sorcery object retrieval using id unit test";
131 "Test object retrieval using id in sorcery with astdb wizard";
132 return AST_TEST_NOT_RUN;
137 if (!(sorcery = alloc_and_initialize_sorcery())) {
138 ast_test_status_update(test, "Failed to open sorcery structure\n");
139 return AST_TEST_FAIL;
142 if (!(obj = ast_sorcery_alloc(sorcery, "test", "blah"))) {
143 ast_test_status_update(test, "Failed to allocate a known object type\n");
144 return AST_TEST_FAIL;
147 if (ast_sorcery_create(sorcery, obj)) {
148 ast_test_status_update(test, "Failed to create object using astdb wizard\n");
149 return AST_TEST_FAIL;
154 if (!(obj = ast_sorcery_alloc(sorcery, "test", "blah2"))) {
155 ast_test_status_update(test, "Failed to allocate second instance of a known object type\n");
156 return AST_TEST_FAIL;
159 if (ast_sorcery_create(sorcery, obj)) {
160 ast_test_status_update(test, "Failed to create second object using astdb wizard\n");
161 return AST_TEST_FAIL;
166 if (!(obj = ast_sorcery_retrieve_by_id(sorcery, "test", "blah"))) {
167 ast_test_status_update(test, "Failed to retrieve properly created object using id of 'blah'\n");
168 return AST_TEST_FAIL;
169 } else if (strcmp(ast_sorcery_object_get_id(obj), "blah")) {
170 ast_test_status_update(test, "Retrieved object does not have correct id\n");
171 return AST_TEST_FAIL;
174 return AST_TEST_PASS;
177 AST_TEST_DEFINE(object_retrieve_field)
179 RAII_VAR(struct ast_sorcery *, sorcery, NULL, deinitialize_sorcery);
180 RAII_VAR(struct test_sorcery_object *, obj, NULL, ao2_cleanup);
181 RAII_VAR(struct ast_variable *, fields, ast_variable_new("joe", "42", ""), ast_variables_destroy);
185 info->name = "object_retrieve_field";
186 info->category = "/res/sorcery_astdb/";
187 info->summary = "sorcery object retrieval using a specific field unit test";
189 "Test object retrieval using a specific field in sorcery with astdb wizard";
190 return AST_TEST_NOT_RUN;
196 ast_test_status_update(test, "Failed to create fields for object retrieval attempt\n");
197 return AST_TEST_FAIL;
200 if (!(sorcery = alloc_and_initialize_sorcery())) {
201 ast_test_status_update(test, "Failed to open sorcery structure\n");
202 return AST_TEST_FAIL;
205 if (!(obj = ast_sorcery_alloc(sorcery, "test", "blah"))) {
206 ast_test_status_update(test, "Failed to allocate a known object type\n");
207 return AST_TEST_FAIL;
212 if (ast_sorcery_create(sorcery, obj)) {
213 ast_test_status_update(test, "Failed to create object using astdb wizard\n");
214 return AST_TEST_FAIL;
219 if (!(obj = ast_sorcery_retrieve_by_fields(sorcery, "test", AST_RETRIEVE_FLAG_DEFAULT, fields))) {
220 ast_test_status_update(test, "Failed to retrieve properly created object using 'joe' field\n");
221 return AST_TEST_FAIL;
225 ast_variables_destroy(fields);
227 if (!(fields = ast_variable_new("joe", "49", ""))) {
228 ast_test_status_update(test, "Failed to create fields for object retrieval attempt\n");
229 return AST_TEST_FAIL;
232 if ((obj = ast_sorcery_retrieve_by_fields(sorcery, "test", AST_RETRIEVE_FLAG_DEFAULT, fields))) {
233 ast_test_status_update(test, "Retrieved an object using a field with an in-correct value... that should not happen\n");
234 return AST_TEST_FAIL;
237 return AST_TEST_PASS;
240 AST_TEST_DEFINE(object_retrieve_multiple_all)
242 RAII_VAR(struct ast_sorcery *, sorcery, NULL, deinitialize_sorcery);
243 RAII_VAR(struct test_sorcery_object *, obj, NULL, ao2_cleanup);
244 RAII_VAR(struct ao2_container *, objects, NULL, ao2_cleanup);
248 info->name = "object_retrieve_multiple_all";
249 info->category = "/res/sorcery_astdb/";
250 info->summary = "sorcery multiple object retrieval unit test";
252 "Test multiple object retrieval in sorcery using astdb wizard";
253 return AST_TEST_NOT_RUN;
258 if (!(sorcery = alloc_and_initialize_sorcery())) {
259 ast_test_status_update(test, "Failed to open sorcery structure\n");
260 return AST_TEST_FAIL;
263 if (!(obj = ast_sorcery_alloc(sorcery, "test", "blah"))) {
264 ast_test_status_update(test, "Failed to allocate a known object type\n");
265 return AST_TEST_FAIL;
268 if (ast_sorcery_create(sorcery, obj)) {
269 ast_test_status_update(test, "Failed to create object using astdb wizard\n");
270 return AST_TEST_FAIL;
275 if (!(obj = ast_sorcery_alloc(sorcery, "test", "blah2"))) {
276 ast_test_status_update(test, "Failed to allocate second instance of a known object type\n");
277 return AST_TEST_FAIL;
280 if (ast_sorcery_create(sorcery, obj)) {
281 ast_test_status_update(test, "Failed to create second object using astdb wizard\n");
282 return AST_TEST_FAIL;
285 if (!(objects = ast_sorcery_retrieve_by_fields(sorcery, "test", AST_RETRIEVE_FLAG_MULTIPLE | AST_RETRIEVE_FLAG_ALL, NULL))) {
286 ast_test_status_update(test, "Failed to retrieve a container of all objects\n");
287 return AST_TEST_FAIL;
288 } else if (ao2_container_count(objects) != 2) {
289 ast_test_status_update(test, "Received a container with no objects in it when there should be some\n");
290 return AST_TEST_FAIL;
293 return AST_TEST_PASS;
296 AST_TEST_DEFINE(object_retrieve_multiple_field)
298 RAII_VAR(struct ast_sorcery *, sorcery, NULL, deinitialize_sorcery);
299 RAII_VAR(struct test_sorcery_object *, obj, NULL, ao2_cleanup);
300 RAII_VAR(struct ao2_container *, objects, NULL, ao2_cleanup);
301 RAII_VAR(struct ast_variable *, fields, ast_variable_new("joe", "6", ""), ast_variables_destroy);
305 info->name = "object_retrieve_multiple_field";
306 info->category = "/res/sorcery_astdb/";
307 info->summary = "sorcery multiple object retrieval unit test";
309 "Test multiple object retrieval in sorcery using fields using astdb wizard";
310 return AST_TEST_NOT_RUN;
316 ast_test_status_update(test, "Failed to create fields for multiple retrieve\n");
317 return AST_TEST_FAIL;
320 if (!(sorcery = alloc_and_initialize_sorcery())) {
321 ast_test_status_update(test, "Failed to open sorcery structure\n");
322 return AST_TEST_FAIL;
325 if (!(obj = ast_sorcery_alloc(sorcery, "test", "blah"))) {
326 ast_test_status_update(test, "Failed to allocate a known object type\n");
327 return AST_TEST_FAIL;
332 if (ast_sorcery_create(sorcery, obj)) {
333 ast_test_status_update(test, "Failed to create object using astdb wizard\n");
334 return AST_TEST_FAIL;
337 if (!(objects = ast_sorcery_retrieve_by_fields(sorcery, "test", AST_RETRIEVE_FLAG_MULTIPLE, fields))) {
338 ast_test_status_update(test, "Failed to retrieve a container of all objects\n");
339 return AST_TEST_FAIL;
340 } else if (ao2_container_count(objects) != 1) {
341 ast_test_status_update(test, "Received a container with no objects in it when there should be some\n");
342 return AST_TEST_FAIL;
345 ao2_cleanup(objects);
346 ast_variables_destroy(fields);
348 if (!(fields = ast_variable_new("joe", "7", ""))) {
349 ast_test_status_update(test, "Failed to create fields for multiple retrieval\n");
350 return AST_TEST_FAIL;
351 } else if (!(objects = ast_sorcery_retrieve_by_fields(sorcery, "test", AST_RETRIEVE_FLAG_MULTIPLE, fields))) {
352 ast_test_status_update(test, "Failed to retrieve an empty container when retrieving multiple\n");
353 return AST_TEST_FAIL;
354 } else if (ao2_container_count(objects)) {
355 ast_test_status_update(test, "Received a container with objects when there should be none in it\n");
356 return AST_TEST_FAIL;
359 return AST_TEST_PASS;
362 AST_TEST_DEFINE(object_retrieve_regex)
364 RAII_VAR(struct ast_sorcery *, sorcery, NULL, deinitialize_sorcery);
365 RAII_VAR(struct test_sorcery_object *, obj, NULL, ao2_cleanup);
366 RAII_VAR(struct ao2_container *, objects, NULL, ao2_cleanup);
370 info->name = "object_retrieve_regex";
371 info->category = "/res/sorcery_astdb/";
372 info->summary = "sorcery multiple object retrieval using regex unit test";
374 "Test multiple object retrieval in sorcery using regular expression for matching using astdb wizard";
375 return AST_TEST_NOT_RUN;
380 if (!(sorcery = alloc_and_initialize_sorcery())) {
381 ast_test_status_update(test, "Failed to open sorcery structure\n");
382 return AST_TEST_FAIL;
385 if (!(obj = ast_sorcery_alloc(sorcery, "test", "blah-98joe"))) {
386 ast_test_status_update(test, "Failed to allocate a known object type\n");
387 return AST_TEST_FAIL;
390 if (ast_sorcery_create(sorcery, obj)) {
391 ast_test_status_update(test, "Failed to create object using astdb wizard\n");
392 return AST_TEST_FAIL;
397 if (!(obj = ast_sorcery_alloc(sorcery, "test", "blah-93joe"))) {
398 ast_test_status_update(test, "Failed to allocate second instance of a known object type\n");
399 return AST_TEST_FAIL;
402 if (ast_sorcery_create(sorcery, obj)) {
403 ast_test_status_update(test, "Failed to create second object using astdb wizard\n");
404 return AST_TEST_FAIL;
409 if (!(obj = ast_sorcery_alloc(sorcery, "test", "neener-93joe"))) {
410 ast_test_status_update(test, "Failed to allocate third instance of a known object type\n");
411 return AST_TEST_FAIL;
414 if (ast_sorcery_create(sorcery, obj)) {
415 ast_test_status_update(test, "Failed to create third object using astdb wizard\n");
416 return AST_TEST_FAIL;
419 if (!(objects = ast_sorcery_retrieve_by_regex(sorcery, "test", "^blah-"))) {
420 ast_test_status_update(test, "Failed to retrieve a container of objects\n");
421 return AST_TEST_FAIL;
422 } else if (ao2_container_count(objects) != 2) {
423 ast_test_status_update(test, "Received a container with incorrect number of objects in it\n");
424 return AST_TEST_FAIL;
427 return AST_TEST_PASS;
430 AST_TEST_DEFINE(object_update)
432 RAII_VAR(struct ast_sorcery *, sorcery, NULL, deinitialize_sorcery);
433 RAII_VAR(struct test_sorcery_object *, obj, NULL, ao2_cleanup);
434 RAII_VAR(struct test_sorcery_object *, obj2, NULL, ao2_cleanup);
438 info->name = "object_update";
439 info->category = "/res/sorcery_astdb/";
440 info->summary = "sorcery object update unit test";
442 "Test object updating in sorcery using astdb wizard";
443 return AST_TEST_NOT_RUN;
448 if (!(sorcery = alloc_and_initialize_sorcery())) {
449 ast_test_status_update(test, "Failed to open sorcery structure\n");
450 return AST_TEST_FAIL;
453 if (!(obj = ast_sorcery_alloc(sorcery, "test", "blah"))) {
454 ast_test_status_update(test, "Failed to allocate a known object type\n");
455 return AST_TEST_FAIL;
458 if (ast_sorcery_create(sorcery, obj)) {
459 ast_test_status_update(test, "Failed to create object using astdb wizard\n");
460 return AST_TEST_FAIL;
463 if (!(obj2 = ast_sorcery_copy(sorcery, obj))) {
464 ast_test_status_update(test, "Failed to allocate a known object type for updating\n");
465 return AST_TEST_FAIL;
473 if (ast_sorcery_update(sorcery, obj2)) {
474 ast_test_status_update(test, "Failed to update sorcery with new object\n");
475 return AST_TEST_FAIL;
478 if (!(obj = ast_sorcery_retrieve_by_id(sorcery, "test", "blah"))) {
479 ast_test_status_update(test, "Failed to retrieve properly updated object\n");
480 return AST_TEST_FAIL;
481 } else if ((obj->bob != obj2->bob) || (obj->joe != obj2->joe)) {
482 ast_test_status_update(test, "Object retrieved is not the updated object\n");
483 return AST_TEST_FAIL;
486 return AST_TEST_PASS;
489 AST_TEST_DEFINE(object_update_uncreated)
491 RAII_VAR(struct ast_sorcery *, sorcery, NULL, deinitialize_sorcery);
492 RAII_VAR(struct test_sorcery_object *, obj, NULL, ao2_cleanup);
496 info->name = "object_update_uncreated";
497 info->category = "/res/sorcery_astdb/";
498 info->summary = "sorcery object update unit test";
500 "Test updating of an uncreated object in sorcery using astdb wizard";
501 return AST_TEST_NOT_RUN;
506 if (!(sorcery = alloc_and_initialize_sorcery())) {
507 ast_test_status_update(test, "Failed to open sorcery structure\n");
508 return AST_TEST_FAIL;
511 if (!(obj = ast_sorcery_alloc(sorcery, "test", "blah"))) {
512 ast_test_status_update(test, "Failed to allocate a known object type\n");
513 return AST_TEST_FAIL;
516 if (!ast_sorcery_update(sorcery, obj)) {
517 ast_test_status_update(test, "Successfully updated an object which has not been created yet\n");
518 return AST_TEST_FAIL;
521 return AST_TEST_PASS;
524 AST_TEST_DEFINE(object_delete)
526 RAII_VAR(struct ast_sorcery *, sorcery, NULL, deinitialize_sorcery);
527 RAII_VAR(struct test_sorcery_object *, obj, NULL, ao2_cleanup);
531 info->name = "object_delete";
532 info->category = "/res/sorcery_astdb/";
533 info->summary = "sorcery object deletion unit test";
535 "Test object deletion in sorcery using astdb wizard";
536 return AST_TEST_NOT_RUN;
541 if (!(sorcery = alloc_and_initialize_sorcery())) {
542 ast_test_status_update(test, "Failed to open sorcery structure\n");
543 return AST_TEST_FAIL;
546 if (!(obj = ast_sorcery_alloc(sorcery, "test", "blah"))) {
547 ast_test_status_update(test, "Failed to allocate a known object type\n");
548 return AST_TEST_FAIL;
551 if (ast_sorcery_create(sorcery, obj)) {
552 ast_test_status_update(test, "Failed to create object using astdb wizard\n");
553 return AST_TEST_FAIL;
556 if (ast_sorcery_delete(sorcery, obj)) {
557 ast_test_status_update(test, "Failed to delete object using astdb wizard\n");
558 return AST_TEST_FAIL;
563 if ((obj = ast_sorcery_retrieve_by_id(sorcery, "test", "blah"))) {
564 ast_test_status_update(test, "Retrieved deleted object that should not be there\n");
565 return AST_TEST_FAIL;
568 return AST_TEST_PASS;
571 AST_TEST_DEFINE(object_delete_uncreated)
573 RAII_VAR(struct ast_sorcery *, sorcery, NULL, deinitialize_sorcery);
574 RAII_VAR(struct test_sorcery_object *, obj, NULL, ao2_cleanup);
578 info->name = "object_delete_uncreated";
579 info->category = "/res/sorcery_astdb/";
580 info->summary = "sorcery object deletion unit test";
582 "Test object deletion of an uncreated object in sorcery using astdb wizard";
583 return AST_TEST_NOT_RUN;
588 if (!(sorcery = alloc_and_initialize_sorcery())) {
589 ast_test_status_update(test, "Failed to open sorcery structure\n");
590 return AST_TEST_FAIL;
593 if (!(obj = ast_sorcery_alloc(sorcery, "test", "blah"))) {
594 ast_test_status_update(test, "Failed to allocate a known object type\n");
595 return AST_TEST_FAIL;
598 if (!ast_sorcery_delete(sorcery, obj)) {
599 ast_test_status_update(test, "Successfully deleted an object which was never created\n");
600 return AST_TEST_FAIL;
603 return AST_TEST_PASS;
606 static int unload_module(void)
608 AST_TEST_UNREGISTER(object_create);
609 AST_TEST_UNREGISTER(object_retrieve_id);
610 AST_TEST_UNREGISTER(object_retrieve_field);
611 AST_TEST_UNREGISTER(object_retrieve_multiple_all);
612 AST_TEST_UNREGISTER(object_retrieve_multiple_field);
613 AST_TEST_UNREGISTER(object_retrieve_regex);
614 AST_TEST_UNREGISTER(object_update);
615 AST_TEST_UNREGISTER(object_update_uncreated);
616 AST_TEST_UNREGISTER(object_delete);
617 AST_TEST_UNREGISTER(object_delete_uncreated);
622 static int load_module(void)
624 AST_TEST_REGISTER(object_create);
625 AST_TEST_REGISTER(object_retrieve_id);
626 AST_TEST_REGISTER(object_retrieve_field);
627 AST_TEST_REGISTER(object_retrieve_multiple_all);
628 AST_TEST_REGISTER(object_retrieve_multiple_field);
629 AST_TEST_REGISTER(object_retrieve_regex);
630 AST_TEST_REGISTER(object_update);
631 AST_TEST_REGISTER(object_update_uncreated);
632 AST_TEST_REGISTER(object_delete);
633 AST_TEST_REGISTER(object_delete_uncreated);
635 return AST_MODULE_LOAD_SUCCESS;
638 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Sorcery astdb Wizard test module");