2 * Asterisk -- An open source telephony toolkit.
4 * Copyright (C) 2012 - 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/astobj2.h"
39 #include "asterisk/sorcery.h"
40 #include "asterisk/logger.h"
41 #include "asterisk/json.h"
43 /*! \brief Dummy sorcery object */
44 struct test_sorcery_object {
45 SORCERY_OBJECT(details);
50 /*! \brief Internal function to allocate a test object */
51 static void *test_sorcery_object_alloc(const char *id)
53 return ast_sorcery_generic_alloc(sizeof(struct test_sorcery_object), NULL);
56 /*! \brief Internal function for object set transformation */
57 static struct ast_variable *test_sorcery_transform(struct ast_variable *set)
59 struct ast_variable *field, *transformed = NULL;
61 for (field = set; field; field = field->next) {
62 struct ast_variable *transformed_field;
64 if (!strcmp(field->name, "joe")) {
65 transformed_field = ast_variable_new(field->name, "5000", "");
67 transformed_field = ast_variable_new(field->name, field->value, "");
70 if (!transformed_field) {
71 ast_variables_destroy(transformed);
75 transformed_field->next = transformed;
76 transformed = transformed_field;
82 /*! \brief Internal function which copies pre-defined data into an object, natively */
83 static int test_sorcery_copy(const void *src, void *dst)
85 struct test_sorcery_object *obj = dst;
91 /*! \brief Internal function which creates a pre-defined diff natively */
92 static int test_sorcery_diff(const void *original, const void *modified, struct ast_variable **changes)
94 *changes = ast_variable_new("yes", "itworks", "");
98 /*! \brief Internal function which sets some values */
99 static int test_sorcery_regex_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
101 struct test_sorcery_object *test = obj;
108 /*! \brief Internal function which creates some ast_variable structures */
109 static int test_sorcery_regex_fields(const void *obj, struct ast_variable **fields)
111 *fields = ast_variable_new("toast-bob", "10", "");
116 /*! \brief Test structure for caching */
117 struct sorcery_test_caching {
118 /*! \brief Whether the object has been created in the cache or not */
119 unsigned int created:1;
121 /*! \brief Whether the object has been updated in the cache or not */
122 unsigned int updated:1;
124 /*! \brief Whether the object has been deleted from the cache or not */
125 unsigned int deleted:1;
127 /*! \brief Object to return when asked */
128 struct test_sorcery_object object;
131 /*! \brief Test structure for observer */
132 struct sorcery_test_observer {
133 /*! \brief Lock for notification */
136 /*! \brief Condition for notification */
139 /*! \brief Pointer to the created object */
142 /*! \brief Pointer to the update object */
145 /*! \brief Pointer to the deleted object */
148 /*! \brief Whether the type has been loaded */
149 unsigned int loaded:1;
152 /*! \brief Global scope apply handler integer to make sure it executed */
153 static int apply_handler_called;
155 /*! \brief Simple apply handler which sets global scope integer to 1 if called */
156 static int test_apply_handler(const struct ast_sorcery *sorcery, void *obj)
158 apply_handler_called = 1;
162 /*! \brief Global scope caching structure for testing */
163 static struct sorcery_test_caching cache = { 0, };
165 /*! \brief Global scope observer structure for testing */
166 static struct sorcery_test_observer observer;
168 static int sorcery_test_create(const struct ast_sorcery *sorcery, void *data, void *object)
176 static void *sorcery_test_retrieve_id(const struct ast_sorcery *sorcery, void *data, const char *type, const char *id)
178 return (cache.created && !cache.deleted) ? ast_sorcery_alloc(sorcery, type, id) : NULL;
181 static int sorcery_test_update(const struct ast_sorcery *sorcery, void *data, void *object)
187 static int sorcery_test_delete(const struct ast_sorcery *sorcery, void *data, void *object)
193 /*! \brief Dummy sorcery wizard, not actually used so we only populate the name and nothing else */
194 static struct ast_sorcery_wizard test_wizard = {
196 .create = sorcery_test_create,
197 .retrieve_id = sorcery_test_retrieve_id,
198 .update = sorcery_test_update,
199 .delete = sorcery_test_delete,
202 static void sorcery_observer_created(const void *object)
204 SCOPED_MUTEX(lock, &observer.lock);
205 observer.created = object;
206 ast_cond_signal(&observer.cond);
209 static void sorcery_observer_updated(const void *object)
211 SCOPED_MUTEX(lock, &observer.lock);
212 observer.updated = object;
213 ast_cond_signal(&observer.cond);
216 static void sorcery_observer_deleted(const void *object)
218 SCOPED_MUTEX(lock, &observer.lock);
219 observer.deleted = object;
220 ast_cond_signal(&observer.cond);
223 static void sorcery_observer_loaded(const char *object_type)
225 SCOPED_MUTEX(lock, &observer.lock);
227 ast_cond_signal(&observer.cond);
230 /*! \brief Test sorcery observer implementation */
231 static const struct ast_sorcery_observer test_observer = {
232 .created = sorcery_observer_created,
233 .updated = sorcery_observer_updated,
234 .deleted = sorcery_observer_deleted,
235 .loaded = sorcery_observer_loaded,
238 static struct ast_sorcery *alloc_and_initialize_sorcery(void)
240 struct ast_sorcery *sorcery;
242 if (!(sorcery = ast_sorcery_open())) {
246 if (ast_sorcery_apply_default(sorcery, "test", "memory", NULL) ||
247 ast_sorcery_internal_object_register(sorcery, "test", test_sorcery_object_alloc, NULL, NULL)) {
248 ast_sorcery_unref(sorcery);
252 ast_sorcery_object_field_register_nodoc(sorcery, "test", "bob", "5", OPT_UINT_T, 0, FLDSET(struct test_sorcery_object, bob));
253 ast_sorcery_object_field_register_nodoc(sorcery, "test", "joe", "10", OPT_UINT_T, 0, FLDSET(struct test_sorcery_object, joe));
258 AST_TEST_DEFINE(wizard_registration)
262 info->name = "wizard_registration";
263 info->category = "/main/sorcery/";
264 info->summary = "sorcery wizard registration and unregistration unit test";
266 "Test registration and unregistration of a sorcery wizard";
267 return AST_TEST_NOT_RUN;
272 if (ast_sorcery_wizard_register(&test_wizard)) {
273 ast_test_status_update(test, "Failed to register a perfectly valid sorcery wizard\n");
274 return AST_TEST_FAIL;
277 if (!ast_sorcery_wizard_register(&test_wizard)) {
278 ast_test_status_update(test, "Successfully registered a sorcery wizard twice, which is bad\n");
279 return AST_TEST_FAIL;
282 if (ast_sorcery_wizard_unregister(&test_wizard)) {
283 ast_test_status_update(test, "Failed to unregister a perfectly valid sorcery wizard\n");
284 return AST_TEST_FAIL;
287 if (!ast_sorcery_wizard_unregister(&test_wizard)) {
288 ast_test_status_update(test, "Successfully unregistered a sorcery wizard twice, which is bad\n");
289 return AST_TEST_FAIL;
292 return AST_TEST_PASS;
295 AST_TEST_DEFINE(sorcery_open)
297 RAII_VAR(struct ast_sorcery *, sorcery, NULL, ast_sorcery_unref);
298 RAII_VAR(struct ast_sorcery *, sorcery2, NULL, ast_sorcery_unref);
304 info->category = "/main/sorcery/";
305 info->summary = "sorcery open/close unit test";
307 "Test opening of sorcery and registry operations";
308 return AST_TEST_NOT_RUN;
313 if ((sorcery = ast_sorcery_retrieve_by_module_name(AST_MODULE))) {
314 ast_test_status_update(test, "There should NOT have been an existing sorcery instance\n");
315 return AST_TEST_FAIL;
318 if (!(sorcery = ast_sorcery_open())) {
319 ast_test_status_update(test, "Failed to open new sorcery structure\n");
320 return AST_TEST_FAIL;
323 if (!(sorcery2 = ast_sorcery_retrieve_by_module_name(AST_MODULE))) {
324 ast_test_status_update(test, "Failed to find sorcery structure in registry\n");
325 return AST_TEST_FAIL;
328 if (sorcery2 != sorcery) {
329 ast_test_status_update(test, "Should have gotten same sorcery on retrieve\n");
330 return AST_TEST_FAIL;
332 ast_sorcery_unref(sorcery2);
334 if ((refcount = ao2_ref(sorcery, 0)) != 2) {
335 ast_test_status_update(test, "Should have been 2 references to sorcery instead of %d\n", refcount);
336 return AST_TEST_FAIL;
339 if (!(sorcery2 = ast_sorcery_open())) {
340 ast_test_status_update(test, "Failed to open second sorcery structure\n");
341 return AST_TEST_FAIL;
344 if (sorcery2 != sorcery) {
345 ast_test_status_update(test, "Should have gotten same sorcery on 2nd open\n");
346 return AST_TEST_FAIL;
349 if ((refcount = ao2_ref(sorcery, 0)) != 3) {
350 ast_test_status_update(test, "Should have been 3 references to sorcery instead of %d\n", refcount);
351 return AST_TEST_FAIL;
354 ast_sorcery_unref(sorcery);
355 ast_sorcery_unref(sorcery2);
359 if ((sorcery = ast_sorcery_retrieve_by_module_name(AST_MODULE))) {
360 ast_sorcery_unref(sorcery);
362 ast_test_status_update(test, "Should NOT have found sorcery structure in registry\n");
363 return AST_TEST_FAIL;
366 return AST_TEST_PASS;
369 AST_TEST_DEFINE(apply_default)
371 RAII_VAR(struct ast_sorcery *, sorcery, NULL, ast_sorcery_unref);
375 info->name = "apply_default";
376 info->category = "/main/sorcery/";
377 info->summary = "sorcery default wizard unit test";
379 "Test setting default type wizard in sorcery";
380 return AST_TEST_NOT_RUN;
385 if (!(sorcery = ast_sorcery_open())) {
386 ast_test_status_update(test, "Failed to open sorcery structure\n");
387 return AST_TEST_FAIL;
390 if (!ast_sorcery_apply_default(sorcery, "test", "dummy", NULL)) {
391 ast_test_status_update(test, "Successfully set a default wizard that doesn't exist\n");
392 return AST_TEST_FAIL;
395 if (ast_sorcery_apply_default(sorcery, "test", "memory", NULL)) {
396 ast_test_status_update(test, "Failed to set a known wizard as a default\n");
397 return AST_TEST_FAIL;
400 if (!ast_sorcery_apply_default(sorcery, "test", "memory", NULL)) {
401 ast_test_status_update(test, "Successfully set a default wizard on a type twice\n");
402 return AST_TEST_FAIL;
405 return AST_TEST_PASS;
408 AST_TEST_DEFINE(apply_config)
410 struct ast_flags flags = { CONFIG_FLAG_NOCACHE };
411 struct ast_config *config;
412 RAII_VAR(struct ast_sorcery *, sorcery, NULL, ast_sorcery_unref);
416 info->name = "apply_config";
417 info->category = "/main/sorcery/";
418 info->summary = "sorcery object mapping configuration unit test";
420 "Test configured object mapping in sorcery";
421 return AST_TEST_NOT_RUN;
426 if (!(config = ast_config_load2("sorcery.conf", "test_sorcery", flags))) {
427 ast_test_status_update(test, "Sorcery configuration file not present - skipping apply_config test\n");
428 return AST_TEST_NOT_RUN;
431 if (!ast_category_get(config, "test_sorcery")) {
432 ast_test_status_update(test, "Sorcery configuration file does not have test_sorcery section\n");
433 ast_config_destroy(config);
434 return AST_TEST_NOT_RUN;
437 ast_config_destroy(config);
439 if (!(sorcery = ast_sorcery_open())) {
440 ast_test_status_update(test, "Failed to open sorcery structure\n");
441 return AST_TEST_FAIL;
444 if (ast_sorcery_apply_config(sorcery, "test_sorcery")) {
445 ast_test_status_update(test, "Failed to apply configured object mappings\n");
446 return AST_TEST_FAIL;
449 return AST_TEST_PASS;
452 AST_TEST_DEFINE(object_register)
454 RAII_VAR(struct ast_sorcery *, sorcery, NULL, ast_sorcery_unref);
458 info->name = "object_register";
459 info->category = "/main/sorcery/";
460 info->summary = "sorcery object type registration unit test";
462 "Test object type registration in sorcery";
463 return AST_TEST_NOT_RUN;
468 if (!(sorcery = ast_sorcery_open())) {
469 ast_test_status_update(test, "Failed to open structure\n");
470 return AST_TEST_FAIL;
473 if (ast_sorcery_apply_default(sorcery, "test", "memory", NULL)) {
474 ast_test_status_update(test, "Failed to set a known wizard as a default\n");
475 return AST_TEST_FAIL;
478 if (ast_sorcery_internal_object_register(sorcery, "test", test_sorcery_object_alloc, NULL, NULL)) {
479 ast_test_status_update(test, "Failed to register object type\n");
480 return AST_TEST_FAIL;
483 if (!ast_sorcery_internal_object_register(sorcery, "test", test_sorcery_object_alloc, NULL, NULL)) {
484 ast_test_status_update(test, "Registered object type a second time, despite it being registered already\n");
485 return AST_TEST_FAIL;
488 return AST_TEST_PASS;
491 AST_TEST_DEFINE(object_register_without_mapping)
493 RAII_VAR(struct ast_sorcery *, sorcery, NULL, ast_sorcery_unref);
497 info->name = "object_register_without_mapping";
498 info->category = "/main/sorcery/";
499 info->summary = "sorcery object type registration (without mapping) unit test";
501 "Test object type registration when no mapping exists in sorcery";
502 return AST_TEST_NOT_RUN;
507 if (!(sorcery = ast_sorcery_open())) {
508 ast_test_status_update(test, "Failed to open sorcery structure\n");
509 return AST_TEST_FAIL;
512 if (!ast_sorcery_internal_object_register(sorcery, "test", test_sorcery_object_alloc, NULL, NULL)) {
513 ast_test_status_update(test, "Registered object type when no object mapping exists\n");
514 return AST_TEST_FAIL;
517 return AST_TEST_PASS;
520 AST_TEST_DEFINE(object_field_register)
522 RAII_VAR(struct ast_sorcery *, sorcery, NULL, ast_sorcery_unref);
526 info->name = "object_field_register";
527 info->category = "/main/sorcery/";
528 info->summary = "sorcery object field registration unit test";
530 "Test object field registration in sorcery with a provided id";
531 return AST_TEST_NOT_RUN;
536 if (!(sorcery = ast_sorcery_open())) {
537 ast_test_status_update(test, "Failed to open sorcery structure\n");
538 return AST_TEST_FAIL;
541 if (!ast_sorcery_object_field_register_nodoc(sorcery, "test", "bob", "5", OPT_UINT_T, 0, FLDSET(struct test_sorcery_object, bob))) {
542 ast_test_status_update(test, "Registered an object field successfully when no mappings or object types exist\n");
543 return AST_TEST_FAIL;
546 if (ast_sorcery_apply_default(sorcery, "test", "memory", NULL)) {
547 ast_test_status_update(test, "Failed to set a known wizard as a default\n");
548 return AST_TEST_FAIL;
551 if (!ast_sorcery_object_field_register_nodoc(sorcery, "test", "bob", "5", OPT_UINT_T, 0, FLDSET(struct test_sorcery_object, bob))) {
552 ast_test_status_update(test, "Registered an object field successfully when object type does not exist\n");
553 return AST_TEST_FAIL;
556 if (ast_sorcery_internal_object_register(sorcery, "test", test_sorcery_object_alloc, NULL, NULL)) {
557 ast_test_status_update(test, "Failed to register object type\n");
558 return AST_TEST_FAIL;
561 if (ast_sorcery_object_field_register_nodoc(sorcery, "test", "bob", "5", OPT_UINT_T, 0, FLDSET(struct test_sorcery_object, bob))) {
562 ast_test_status_update(test, "Could not successfully register object field when mapping and object type exists\n");
563 return AST_TEST_FAIL;
566 return AST_TEST_PASS;
569 AST_TEST_DEFINE(object_fields_register)
571 RAII_VAR(struct ast_sorcery *, sorcery, NULL, ast_sorcery_unref);
575 info->name = "object_fields_register";
576 info->category = "/main/sorcery/";
577 info->summary = "sorcery object regex fields registration unit test";
579 "Test object regex fields registration in sorcery with a provided id";
580 return AST_TEST_NOT_RUN;
585 if (!(sorcery = ast_sorcery_open())) {
586 ast_test_status_update(test, "Failed to open sorcery structure\n");
587 return AST_TEST_FAIL;
590 if (!ast_sorcery_object_fields_register(sorcery, "test", "^toast-", test_sorcery_regex_handler, test_sorcery_regex_fields)) {
591 ast_test_status_update(test, "Registered a regex object field successfully when no mappings or object types exist\n");
592 return AST_TEST_FAIL;
595 if (ast_sorcery_apply_default(sorcery, "test", "memory", NULL)) {
596 ast_test_status_update(test, "Failed to set a known wizard as a default\n");
597 return AST_TEST_FAIL;
600 if (!ast_sorcery_object_fields_register(sorcery, "test", "^toast-", test_sorcery_regex_handler, test_sorcery_regex_fields)) {
601 ast_test_status_update(test, "Registered a regex object field successfully when object type does not exist\n");
602 return AST_TEST_FAIL;
605 if (ast_sorcery_internal_object_register(sorcery, "test", test_sorcery_object_alloc, NULL, NULL)) {
606 ast_test_status_update(test, "Failed to register object type\n");
607 return AST_TEST_FAIL;
610 if (ast_sorcery_object_fields_register(sorcery, "test", "^toast-", test_sorcery_regex_handler, test_sorcery_regex_fields)) {
611 ast_test_status_update(test, "Registered a regex object field successfully when no mappings or object types exist\n");
612 return AST_TEST_FAIL;
615 return AST_TEST_PASS;
618 AST_TEST_DEFINE(object_alloc_with_id)
620 int res = AST_TEST_PASS;
621 RAII_VAR(struct ast_sorcery *, sorcery, NULL, ast_sorcery_unref);
622 RAII_VAR(struct test_sorcery_object *, obj, NULL, ao2_cleanup);
626 info->name = "object_alloc_with_id";
627 info->category = "/main/sorcery/";
628 info->summary = "sorcery object allocation (with id) unit test";
630 "Test object allocation in sorcery with a provided id";
631 return AST_TEST_NOT_RUN;
636 if (!(sorcery = alloc_and_initialize_sorcery())) {
637 ast_test_status_update(test, "Failed to open sorcery structure\n");
638 return AST_TEST_FAIL;
641 if (!(obj = ast_sorcery_alloc(sorcery, "test", "blah"))) {
642 ast_test_status_update(test, "Failed to allocate a known object type\n");
644 } else if (ast_strlen_zero(ast_sorcery_object_get_id(obj))) {
645 ast_test_status_update(test, "Allocated object has empty id when it should not\n");
647 } else if (strcmp(ast_sorcery_object_get_id(obj), "blah")) {
648 ast_test_status_update(test, "Allocated object does not have correct id\n");
650 } else if (ast_strlen_zero(ast_sorcery_object_get_type(obj))) {
651 ast_test_status_update(test, "Allocated object has empty type when it should not\n");
653 } else if (strcmp(ast_sorcery_object_get_type(obj), "test")) {
654 ast_test_status_update(test, "Allocated object does not have correct type\n");
656 } else if ((obj->bob != 5) || (obj->joe != 10)) {
657 ast_test_status_update(test, "Allocated object does not have defaults set as it should\n");
664 AST_TEST_DEFINE(object_alloc_without_id)
666 int res = AST_TEST_PASS;
667 RAII_VAR(struct ast_sorcery *, sorcery, NULL, ast_sorcery_unref);
668 RAII_VAR(struct test_sorcery_object *, obj, NULL, ao2_cleanup);
672 info->name = "object_alloc_without_id";
673 info->category = "/main/sorcery/";
674 info->summary = "sorcery object allocation (without id) unit test";
676 "Test object allocation in sorcery with no provided id";
677 return AST_TEST_NOT_RUN;
682 if (!(sorcery = alloc_and_initialize_sorcery())) {
683 ast_test_status_update(test, "Failed to open sorcery structure\n");
684 return AST_TEST_FAIL;
687 if (!(obj = ast_sorcery_alloc(sorcery, "test", NULL))) {
688 ast_test_status_update(test, "Failed to allocate a known object type\n");
690 } else if (ast_strlen_zero(ast_sorcery_object_get_id(obj))) {
691 ast_test_status_update(test, "Allocated object has empty id when it should not\n");
699 AST_TEST_DEFINE(object_copy)
701 int res = AST_TEST_PASS;
702 RAII_VAR(struct ast_sorcery *, sorcery, NULL, ast_sorcery_unref);
703 RAII_VAR(struct test_sorcery_object *, obj, NULL, ao2_cleanup);
704 RAII_VAR(struct test_sorcery_object *, copy, NULL, ao2_cleanup);
708 info->name = "object_copy";
709 info->category = "/main/sorcery/";
710 info->summary = "sorcery object copy unit test";
712 "Test object copy in sorcery";
713 return AST_TEST_NOT_RUN;
718 if (!(sorcery = alloc_and_initialize_sorcery())) {
719 ast_test_status_update(test, "Failed to open sorcery structure\n");
720 return AST_TEST_FAIL;
723 if (!(obj = ast_sorcery_alloc(sorcery, "test", "blah"))) {
724 ast_test_status_update(test, "Failed to allocate a known object type\n");
725 return AST_TEST_FAIL;
731 if (!(copy = ast_sorcery_copy(sorcery, obj))) {
732 ast_test_status_update(test, "Failed to create a copy of a known valid object\n");
734 } else if (copy == obj) {
735 ast_test_status_update(test, "Created copy is actually the original object\n");
737 } else if (copy->bob != obj->bob) {
738 ast_test_status_update(test, "Value of 'bob' on newly created copy is not the same as original\n");
740 } else if (copy->joe != obj->joe) {
741 ast_test_status_update(test, "Value of 'joe' on newly created copy is not the same as original\n");
748 AST_TEST_DEFINE(object_copy_native)
750 int res = AST_TEST_PASS;
751 RAII_VAR(struct ast_sorcery *, sorcery, NULL, ast_sorcery_unref);
752 RAII_VAR(struct test_sorcery_object *, obj, NULL, ao2_cleanup);
753 RAII_VAR(struct test_sorcery_object *, copy, NULL, ao2_cleanup);
757 info->name = "object_copy_native";
758 info->category = "/main/sorcery/";
759 info->summary = "sorcery object native copy unit test";
761 "Test object native copy in sorcery";
762 return AST_TEST_NOT_RUN;
767 if (!(sorcery = alloc_and_initialize_sorcery())) {
768 ast_test_status_update(test, "Failed to open sorcery structure\n");
769 return AST_TEST_FAIL;
772 ast_sorcery_object_set_copy_handler(sorcery, "test", test_sorcery_copy);
774 if (!(obj = ast_sorcery_alloc(sorcery, "test", "blah"))) {
775 ast_test_status_update(test, "Failed to allocate a known object type\n");
776 return AST_TEST_FAIL;
782 if (!(copy = ast_sorcery_copy(sorcery, obj))) {
783 ast_test_status_update(test, "Failed to create a copy of a known valid object\n");
785 } else if (copy == obj) {
786 ast_test_status_update(test, "Created copy is actually the original object\n");
788 } else if (copy->bob != 10) {
789 ast_test_status_update(test, "Value of 'bob' on newly created copy is not the predefined native copy value\n");
791 } else if (copy->joe != 20) {
792 ast_test_status_update(test, "Value of 'joe' on newly created copy is not the predefined native copy value\n");
799 AST_TEST_DEFINE(object_diff)
801 RAII_VAR(struct ast_sorcery *, sorcery, NULL, ast_sorcery_unref);
802 RAII_VAR(struct test_sorcery_object *, obj1, NULL, ao2_cleanup);
803 RAII_VAR(struct test_sorcery_object *, obj2, NULL, ao2_cleanup);
804 RAII_VAR(struct ast_variable *, changes, NULL, ast_variables_destroy);
805 struct ast_variable *field;
806 int res = AST_TEST_PASS;
810 info->name = "object_diff";
811 info->category = "/main/sorcery/";
812 info->summary = "sorcery object diff unit test";
814 "Test object diffing in sorcery";
815 return AST_TEST_NOT_RUN;
820 if (!(sorcery = alloc_and_initialize_sorcery())) {
821 ast_test_status_update(test, "Failed to open sorcery structure\n");
822 return AST_TEST_FAIL;
825 if (!(obj1 = ast_sorcery_alloc(sorcery, "test", "blah"))) {
826 ast_test_status_update(test, "Failed to allocate a known object type\n");
827 return AST_TEST_FAIL;
833 if (!(obj2 = ast_sorcery_alloc(sorcery, "test", "blah2"))) {
834 ast_test_status_update(test, "Failed to allocate a second known object type\n");
835 return AST_TEST_FAIL;
841 if (ast_sorcery_diff(sorcery, obj1, obj2, &changes)) {
842 ast_test_status_update(test, "Failed to diff obj1 and obj2\n");
843 } else if (!changes) {
844 ast_test_status_update(test, "Failed to produce a diff of two objects, despite there being differences\n");
845 return AST_TEST_FAIL;
848 for (field = changes; field; field = field->next) {
849 if (!strcmp(field->name, "joe")) {
850 if (strcmp(field->value, "42")) {
851 ast_test_status_update(test, "Object diff produced unexpected value '%s' for joe\n", field->value);
855 ast_test_status_update(test, "Object diff produced unexpected field '%s'\n", field->name);
863 AST_TEST_DEFINE(object_diff_native)
865 RAII_VAR(struct ast_sorcery *, sorcery, NULL, ast_sorcery_unref);
866 RAII_VAR(struct test_sorcery_object *, obj1, NULL, ao2_cleanup);
867 RAII_VAR(struct test_sorcery_object *, obj2, NULL, ao2_cleanup);
868 RAII_VAR(struct ast_variable *, changes, NULL, ast_variables_destroy);
869 struct ast_variable *field;
870 int res = AST_TEST_PASS;
874 info->name = "object_diff_native";
875 info->category = "/main/sorcery/";
876 info->summary = "sorcery object native diff unit test";
878 "Test native object diffing in sorcery";
879 return AST_TEST_NOT_RUN;
884 if (!(sorcery = alloc_and_initialize_sorcery())) {
885 ast_test_status_update(test, "Failed to open sorcery structure\n");
886 return AST_TEST_FAIL;
889 ast_sorcery_object_set_diff_handler(sorcery, "test", test_sorcery_diff);
891 if (!(obj1 = ast_sorcery_alloc(sorcery, "test", "blah"))) {
892 ast_test_status_update(test, "Failed to allocate a known object type\n");
893 return AST_TEST_FAIL;
899 if (!(obj2 = ast_sorcery_alloc(sorcery, "test", "blah2"))) {
900 ast_test_status_update(test, "Failed to allocate a second known object type\n");
901 return AST_TEST_FAIL;
907 if (ast_sorcery_diff(sorcery, obj1, obj2, &changes)) {
908 ast_test_status_update(test, "Failed to diff obj1 and obj2\n");
909 } else if (!changes) {
910 ast_test_status_update(test, "Failed to produce a diff of two objects, despite there being differences\n");
911 return AST_TEST_FAIL;
914 for (field = changes; field; field = field->next) {
915 if (!strcmp(field->name, "yes")) {
916 if (strcmp(field->value, "itworks")) {
917 ast_test_status_update(test, "Object diff produced unexpected value '%s' for joe\n", field->value);
921 ast_test_status_update(test, "Object diff produced unexpected field '%s'\n", field->name);
929 AST_TEST_DEFINE(objectset_create)
931 int res = AST_TEST_PASS;
932 RAII_VAR(struct ast_sorcery *, sorcery, NULL, ast_sorcery_unref);
933 RAII_VAR(struct test_sorcery_object *, obj, NULL, ao2_cleanup);
934 RAII_VAR(struct ast_variable *, objset, NULL, ast_variables_destroy);
935 struct ast_variable *field;
939 info->name = "objectset_create";
940 info->category = "/main/sorcery/";
941 info->summary = "sorcery object set creation unit test";
943 "Test object set creation in sorcery";
944 return AST_TEST_NOT_RUN;
949 if (!(sorcery = alloc_and_initialize_sorcery())) {
950 ast_test_status_update(test, "Failed to open sorcery structure\n");
951 return AST_TEST_FAIL;
954 if (!(obj = ast_sorcery_alloc(sorcery, "test", "blah"))) {
955 ast_test_status_update(test, "Failed to allocate a known object type\n");
956 return AST_TEST_FAIL;
959 if (!(objset = ast_sorcery_objectset_create(sorcery, obj))) {
960 ast_test_status_update(test, "Failed to create an object set for a known sane object\n");
961 return AST_TEST_FAIL;
964 for (field = objset; field; field = field->next) {
965 if (!strcmp(field->name, "bob")) {
966 if (strcmp(field->value, "5")) {
967 ast_test_status_update(test, "Object set failed to create proper value for 'bob'\n");
970 } else if (!strcmp(field->name, "joe")) {
971 if (strcmp(field->value, "10")) {
972 ast_test_status_update(test, "Object set failed to create proper value for 'joe'\n");
976 ast_test_status_update(test, "Object set created field '%s' which is unknown\n", field->name);
984 AST_TEST_DEFINE(objectset_json_create)
986 int res = AST_TEST_PASS;
987 RAII_VAR(struct ast_sorcery *, sorcery, NULL, ast_sorcery_unref);
988 RAII_VAR(struct test_sorcery_object *, obj, NULL, ao2_cleanup);
989 RAII_VAR(struct ast_json *, objset, NULL, ast_json_unref);
990 struct ast_json_iter *field;
994 info->name = "objectset_json_create";
995 info->category = "/main/sorcery/";
996 info->summary = "sorcery json object set creation unit test";
998 "Test object set creation (for JSON format) in sorcery";
999 return AST_TEST_NOT_RUN;
1004 if (!(sorcery = alloc_and_initialize_sorcery())) {
1005 ast_test_status_update(test, "Failed to open sorcery structure\n");
1006 return AST_TEST_FAIL;
1009 if (!(obj = ast_sorcery_alloc(sorcery, "test", "blah"))) {
1010 ast_test_status_update(test, "Failed to allocate a known object type\n");
1011 return AST_TEST_FAIL;
1014 if (!(objset = ast_sorcery_objectset_json_create(sorcery, obj))) {
1015 ast_test_status_update(test, "Failed to create an object set for a known sane object\n");
1016 return AST_TEST_FAIL;
1019 for (field = ast_json_object_iter(objset); field; field = ast_json_object_iter_next(objset, field)) {
1020 struct ast_json *value = ast_json_object_iter_value(field);
1022 if (!strcmp(ast_json_object_iter_key(field), "bob")) {
1023 if (strcmp(ast_json_string_get(value), "5")) {
1024 ast_test_status_update(test, "Object set failed to create proper value for 'bob'\n");
1025 res = AST_TEST_FAIL;
1027 } else if (!strcmp(ast_json_object_iter_key(field), "joe")) {
1028 if (strcmp(ast_json_string_get(value), "10")) {
1029 ast_test_status_update(test, "Object set failed to create proper value for 'joe'\n");
1030 res = AST_TEST_FAIL;
1033 ast_test_status_update(test, "Object set created field '%s' which is unknown\n", ast_json_object_iter_key(field));
1034 res = AST_TEST_FAIL;
1041 AST_TEST_DEFINE(objectset_create_regex)
1043 int res = AST_TEST_PASS;
1044 RAII_VAR(struct ast_sorcery *, sorcery, NULL, ast_sorcery_unref);
1045 RAII_VAR(struct test_sorcery_object *, obj, NULL, ao2_cleanup);
1046 RAII_VAR(struct ast_variable *, objset, NULL, ast_variables_destroy);
1047 struct ast_variable *field;
1051 info->name = "objectset_create_regex";
1052 info->category = "/main/sorcery/";
1053 info->summary = "sorcery object set creation with regex fields unit test";
1055 "Test object set creation with regex fields in sorcery";
1056 return AST_TEST_NOT_RUN;
1061 if (!(sorcery = ast_sorcery_open())) {
1062 ast_test_status_update(test, "Failed to open sorcery structure\n");
1063 return AST_TEST_FAIL;
1066 if (ast_sorcery_apply_default(sorcery, "test", "memory", NULL) ||
1067 ast_sorcery_internal_object_register(sorcery, "test", test_sorcery_object_alloc, NULL, test_apply_handler)) {
1068 ast_test_status_update(test, "Failed to register 'test' object type\n");
1069 return AST_TEST_FAIL;
1072 ast_sorcery_object_fields_register(sorcery, "test", "^toast-", test_sorcery_regex_handler, test_sorcery_regex_fields);
1074 if (!(obj = ast_sorcery_alloc(sorcery, "test", "blah"))) {
1075 ast_test_status_update(test, "Failed to allocate a known object type\n");
1076 return AST_TEST_FAIL;
1079 if (!(objset = ast_sorcery_objectset_create(sorcery, obj))) {
1080 ast_test_status_update(test, "Failed to create an object set for a known sane object\n");
1081 return AST_TEST_FAIL;
1084 for (field = objset; field; field = field->next) {
1085 if (!strcmp(field->name, "toast-bob")) {
1086 if (strcmp(field->value, "10")) {
1087 ast_test_status_update(test, "Object set failed to create proper value for 'bob'\n");
1088 res = AST_TEST_FAIL;
1091 ast_test_status_update(test, "Object set created field '%s' which is unknown\n", field->name);
1092 res = AST_TEST_FAIL;
1099 AST_TEST_DEFINE(objectset_apply)
1101 int res = AST_TEST_PASS;
1102 RAII_VAR(struct ast_sorcery *, sorcery, NULL, ast_sorcery_unref);
1103 RAII_VAR(struct test_sorcery_object *, obj, NULL, ao2_cleanup);
1104 RAII_VAR(struct ast_variable *, objset, NULL, ast_variables_destroy);
1108 info->name = "objectset_apply";
1109 info->category = "/main/sorcery/";
1110 info->summary = "sorcery object apply unit test";
1112 "Test object set applying in sorcery";
1113 return AST_TEST_NOT_RUN;
1118 if (!(sorcery = alloc_and_initialize_sorcery())) {
1119 ast_test_status_update(test, "Failed to open sorcery structure\n");
1120 return AST_TEST_FAIL;
1123 if (!(obj = ast_sorcery_alloc(sorcery, "test", "blah"))) {
1124 ast_test_status_update(test, "Failed to allocate a known object type\n");
1125 return AST_TEST_FAIL;
1128 if (!(objset = ast_variable_new("joe", "25", ""))) {
1129 ast_test_status_update(test, "Failed to create an object set, test could not occur\n");
1130 res = AST_TEST_FAIL;
1131 } else if (ast_sorcery_objectset_apply(sorcery, obj, objset)) {
1132 ast_test_status_update(test, "Failed to apply valid object set to object\n");
1133 res = AST_TEST_FAIL;
1134 } else if (obj->joe != 25) {
1135 ast_test_status_update(test, "Object set was not actually applied to object despite it returning success\n");
1136 res = AST_TEST_FAIL;
1142 AST_TEST_DEFINE(objectset_apply_handler)
1144 int res = AST_TEST_PASS;
1145 RAII_VAR(struct ast_sorcery *, sorcery, NULL, ast_sorcery_unref);
1146 RAII_VAR(struct test_sorcery_object *, obj, NULL, ao2_cleanup);
1147 RAII_VAR(struct ast_variable *, objset, NULL, ast_variables_destroy);
1151 info->name = "objectset_apply_handler";
1152 info->category = "/main/sorcery/";
1153 info->summary = "sorcery object apply handler unit test";
1155 "Test object set apply handler call in sorcery";
1156 return AST_TEST_NOT_RUN;
1161 if (!(sorcery = ast_sorcery_open())) {
1162 ast_test_status_update(test, "Failed to open sorcery structure\n");
1163 return AST_TEST_FAIL;
1166 if (ast_sorcery_apply_default(sorcery, "test", "memory", NULL) ||
1167 ast_sorcery_internal_object_register(sorcery, "test", test_sorcery_object_alloc, NULL, test_apply_handler)) {
1168 ast_test_status_update(test, "Failed to register 'test' object type\n");
1169 return AST_TEST_FAIL;
1172 ast_sorcery_object_field_register_nodoc(sorcery, "test", "bob", "5", OPT_UINT_T, 0, FLDSET(struct test_sorcery_object, bob));
1173 ast_sorcery_object_field_register_nodoc(sorcery, "test", "joe", "10", OPT_UINT_T, 0, FLDSET(struct test_sorcery_object, joe));
1175 if (!(obj = ast_sorcery_alloc(sorcery, "test", "blah"))) {
1176 ast_test_status_update(test, "Failed to allocate a known object type\n");
1177 return AST_TEST_FAIL;
1180 apply_handler_called = 0;
1182 if (!(objset = ast_variable_new("joe", "25", ""))) {
1183 ast_test_status_update(test, "Failed to create an object set, test could not occur\n");
1184 res = AST_TEST_FAIL;
1185 } else if (ast_sorcery_objectset_apply(sorcery, obj, objset)) {
1186 ast_test_status_update(test, "Failed to apply valid object set to object\n");
1187 res = AST_TEST_FAIL;
1188 } else if (!apply_handler_called) {
1189 ast_test_status_update(test, "Apply handler was not called when it should have been\n");
1190 res = AST_TEST_FAIL;
1196 AST_TEST_DEFINE(objectset_apply_invalid)
1198 RAII_VAR(struct ast_sorcery *, sorcery, NULL, ast_sorcery_unref);
1199 RAII_VAR(struct test_sorcery_object *, obj, NULL, ao2_cleanup);
1200 RAII_VAR(struct ast_variable *, objset, NULL, ast_variables_destroy);
1204 info->name = "objectset_apply_invalid";
1205 info->category = "/main/sorcery/";
1206 info->summary = "sorcery object invalid apply unit test";
1208 "Test object set applying of an invalid set in sorcery";
1209 return AST_TEST_NOT_RUN;
1214 if (!(sorcery = alloc_and_initialize_sorcery())) {
1215 ast_test_status_update(test, "Failed to open sorcery structure\n");
1216 return AST_TEST_FAIL;
1219 if (!(obj = ast_sorcery_alloc(sorcery, "test", "blah"))) {
1220 ast_test_status_update(test, "Failed to allocate a known object type\n");
1221 return AST_TEST_FAIL;
1224 if (!(objset = ast_variable_new("fred", "99", ""))) {
1225 ast_test_status_update(test, "Failed to create an object set, test could not occur\n");
1226 return AST_TEST_FAIL;
1227 } else if (!ast_sorcery_objectset_apply(sorcery, obj, objset)) {
1228 ast_test_status_update(test, "Successfully applied an invalid object set\n");
1229 return AST_TEST_FAIL;
1230 } else if ((obj->bob != 5) || (obj->joe != 10)) {
1231 ast_test_status_update(test, "Object set modified object fields when it should not have\n");
1232 return AST_TEST_FAIL;
1235 return AST_TEST_PASS;
1238 AST_TEST_DEFINE(objectset_transform)
1240 RAII_VAR(struct ast_sorcery *, sorcery, NULL, ast_sorcery_unref);
1241 RAII_VAR(struct test_sorcery_object *, obj, NULL, ao2_cleanup);
1242 RAII_VAR(struct ast_variable *, objset, NULL, ast_variables_destroy);
1246 info->name = "objectset_transform";
1247 info->category = "/main/sorcery/";
1248 info->summary = "sorcery object set transformation unit test";
1250 "Test object set transformation in sorcery";
1251 return AST_TEST_NOT_RUN;
1256 if (!(sorcery = ast_sorcery_open())) {
1257 ast_test_status_update(test, "Failed to open sorcery structure\n");
1258 return AST_TEST_FAIL;
1261 if (ast_sorcery_apply_default(sorcery, "test", "memory", NULL)) {
1262 ast_test_status_update(test, "Failed to set a known wizard as a default\n");
1263 return AST_TEST_FAIL;
1266 if (ast_sorcery_internal_object_register(sorcery, "test", test_sorcery_object_alloc, test_sorcery_transform, NULL)) {
1267 ast_test_status_update(test, "Failed to register object type\n");
1268 return AST_TEST_FAIL;
1271 ast_sorcery_object_field_register_nodoc(sorcery, "test", "bob", "5", OPT_UINT_T, 0, FLDSET(struct test_sorcery_object, bob));
1272 ast_sorcery_object_field_register_nodoc(sorcery, "test", "joe", "10", OPT_UINT_T, 0, FLDSET(struct test_sorcery_object, joe));
1274 if (!(obj = ast_sorcery_alloc(sorcery, "test", "blah"))) {
1275 ast_test_status_update(test, "Failed to allocate a known object type\n");
1276 return AST_TEST_FAIL;
1279 if (!(objset = ast_sorcery_objectset_create(sorcery, obj))) {
1280 ast_test_status_update(test, "Failed to create an object set for a known sane object\n");
1281 return AST_TEST_FAIL;
1284 if (ast_sorcery_objectset_apply(sorcery, obj, objset)) {
1285 ast_test_status_update(test, "Failed to apply properly created object set against object\n");
1286 return AST_TEST_FAIL;
1289 if (obj->bob != 5) {
1290 ast_test_status_update(test, "Application of object set produced incorrect value on 'bob'\n");
1291 return AST_TEST_FAIL;
1292 } else if (obj->joe == 10) {
1293 ast_test_status_update(test, "Transformation callback did not change value of 'joe' from provided value\n");
1294 return AST_TEST_FAIL;
1295 } else if (obj->joe != 5000) {
1296 ast_test_status_update(test, "Value of 'joe' differs from default AND from transformation value\n");
1297 return AST_TEST_FAIL;
1300 return AST_TEST_PASS;
1303 AST_TEST_DEFINE(objectset_apply_fields)
1305 int res = AST_TEST_PASS;
1306 RAII_VAR(struct ast_sorcery *, sorcery, NULL, ast_sorcery_unref);
1307 RAII_VAR(struct test_sorcery_object *, obj, NULL, ao2_cleanup);
1308 RAII_VAR(struct ast_variable *, objset, NULL, ast_variables_destroy);
1312 info->name = "objectset_apply_fields";
1313 info->category = "/main/sorcery/";
1314 info->summary = "sorcery object apply regex fields unit test";
1316 "Test object set apply with regex fields in sorcery";
1317 return AST_TEST_NOT_RUN;
1322 if (!(sorcery = ast_sorcery_open())) {
1323 ast_test_status_update(test, "Failed to open sorcery structure\n");
1324 return AST_TEST_FAIL;
1327 if (ast_sorcery_apply_default(sorcery, "test", "memory", NULL) ||
1328 ast_sorcery_internal_object_register(sorcery, "test", test_sorcery_object_alloc, NULL, test_apply_handler)) {
1329 ast_test_status_update(test, "Failed to register 'test' object type\n");
1330 return AST_TEST_FAIL;
1333 ast_sorcery_object_fields_register(sorcery, "test", "^toast-", test_sorcery_regex_handler, test_sorcery_regex_fields);
1335 if (!(obj = ast_sorcery_alloc(sorcery, "test", "blah"))) {
1336 ast_test_status_update(test, "Failed to allocate a known object type\n");
1337 return AST_TEST_FAIL;
1340 if (!(objset = ast_variable_new("toast-bob", "20", ""))) {
1341 ast_test_status_update(test, "Failed to create an object set, test could not occur\n");
1342 res = AST_TEST_FAIL;
1343 } else if (ast_sorcery_objectset_apply(sorcery, obj, objset)) {
1344 ast_test_status_update(test, "Failed to apply valid object set to object\n");
1345 res = AST_TEST_FAIL;
1346 } else if (obj->bob != 256) {
1347 ast_test_status_update(test, "Regex field handler was not called when it should have been\n");
1348 res = AST_TEST_FAIL;
1354 AST_TEST_DEFINE(extended_fields)
1356 int res = AST_TEST_PASS;
1357 RAII_VAR(struct ast_sorcery *, sorcery, NULL, ast_sorcery_unref);
1358 RAII_VAR(struct test_sorcery_object *, obj, NULL, ao2_cleanup);
1359 RAII_VAR(struct ast_variable *, objset, NULL, ast_variables_destroy);
1364 info->name = "extended_fields";
1365 info->category = "/main/sorcery/";
1366 info->summary = "sorcery object extended fields unit test";
1368 "Test extended fields support in sorcery";
1369 return AST_TEST_NOT_RUN;
1374 if (!(sorcery = alloc_and_initialize_sorcery())) {
1375 ast_test_status_update(test, "Failed to open sorcery structure\n");
1376 return AST_TEST_FAIL;
1379 if (!(obj = ast_sorcery_alloc(sorcery, "test", "blah"))) {
1380 ast_test_status_update(test, "Failed to allocate a known object type\n");
1381 return AST_TEST_FAIL;
1384 if (!(objset = ast_variable_new("@testing", "toast", ""))) {
1385 ast_test_status_update(test, "Failed to create an object set, test could not occur\n");
1386 res = AST_TEST_FAIL;
1387 } else if (ast_sorcery_objectset_apply(sorcery, obj, objset)) {
1388 ast_test_status_update(test, "Failed to apply valid object set to object\n");
1389 res = AST_TEST_FAIL;
1390 } else if (!(value = ast_sorcery_object_get_extended(obj, "testing"))) {
1391 ast_test_status_update(test, "Extended field, which was set using object set, could not be found\n");
1392 res = AST_TEST_FAIL;
1393 } else if (strcmp(value, "toast")) {
1394 ast_test_status_update(test, "Extended field does not contain expected value\n");
1395 res = AST_TEST_FAIL;
1396 } else if (ast_sorcery_object_set_extended(obj, "@tacos", "supreme")) {
1397 ast_test_status_update(test, "Extended field could not be set\n");
1398 res = AST_TEST_FAIL;
1399 } else if (!(value = ast_sorcery_object_get_extended(obj, "tacos"))) {
1400 ast_test_status_update(test, "Extended field, which was set using the API, could not be found\n");
1401 res = AST_TEST_FAIL;
1402 } else if (strcmp(value, "supreme")) {
1403 ast_test_status_update(test, "Extended field does not contain expected value\n");
1404 res = AST_TEST_FAIL;
1405 } else if (ast_sorcery_object_set_extended(obj, "@tacos", "canadian")) {
1406 ast_test_status_update(test, "Extended field could not be set a second time\n");
1407 res = AST_TEST_FAIL;
1408 } else if (!(value = ast_sorcery_object_get_extended(obj, "tacos"))) {
1409 ast_test_status_update(test, "Extended field, which was set using the API, could not be found\n");
1410 res = AST_TEST_FAIL;
1411 } else if (strcmp(value, "canadian")) {
1412 ast_test_status_update(test, "Extended field does not contain expected value\n");
1413 res = AST_TEST_FAIL;
1419 AST_TEST_DEFINE(changeset_create)
1421 int res = AST_TEST_PASS;
1422 RAII_VAR(struct ast_variable *, original, NULL, ast_variables_destroy);
1423 RAII_VAR(struct ast_variable *, modified, NULL, ast_variables_destroy);
1424 RAII_VAR(struct ast_variable *, changes, NULL, ast_variables_destroy);
1425 struct ast_variable *tmp;
1429 info->name = "changeset_create";
1430 info->category = "/main/sorcery/";
1431 info->summary = "sorcery changeset creation unit test";
1433 "Test changeset creation in sorcery";
1434 return AST_TEST_NOT_RUN;
1439 if (!(tmp = ast_variable_new("bananas", "purple", ""))) {
1440 ast_test_status_update(test, "Failed to create first field for original objectset\n");
1441 return AST_TEST_FAIL;
1443 tmp->next = original;
1446 if (!(tmp = ast_variable_new("apples", "orange", ""))) {
1447 ast_test_status_update(test, "Failed to create second field for original objectset\n");
1448 return AST_TEST_FAIL;
1450 tmp->next = original;
1453 if (!(tmp = ast_variable_new("bananas", "green", ""))) {
1454 ast_test_status_update(test, "Failed to create first field for modified objectset\n");
1455 return AST_TEST_FAIL;
1457 tmp->next = modified;
1460 if (!(tmp = ast_variable_new("apples", "orange", ""))) {
1461 ast_test_status_update(test, "Failed to create second field for modified objectset\n");
1462 return AST_TEST_FAIL;
1464 tmp->next = modified;
1467 if (ast_sorcery_changeset_create(original, modified, &changes)) {
1468 ast_test_status_update(test, "Failed to create a changeset due to an error\n");
1469 return AST_TEST_FAIL;
1470 } else if (!changes) {
1471 ast_test_status_update(test, "Failed to produce a changeset when there should be one\n");
1472 return AST_TEST_FAIL;
1475 for (tmp = changes; tmp; tmp = tmp->next) {
1476 if (!strcmp(tmp->name, "bananas")) {
1477 if (strcmp(tmp->value, "green")) {
1478 ast_test_status_update(test, "Changeset produced had unexpected value '%s' for bananas\n", tmp->value);
1479 res = AST_TEST_FAIL;
1482 ast_test_status_update(test, "Changeset produced had unexpected field '%s'\n", tmp->name);
1483 res = AST_TEST_FAIL;
1490 AST_TEST_DEFINE(changeset_create_unchanged)
1492 RAII_VAR(struct ast_variable *, original, NULL, ast_variables_destroy);
1493 RAII_VAR(struct ast_variable *, changes, NULL, ast_variables_destroy);
1494 RAII_VAR(struct ast_variable *, same, NULL, ast_variables_destroy);
1495 struct ast_variable *tmp;
1499 info->name = "changeset_create_unchanged";
1500 info->category = "/main/sorcery/";
1501 info->summary = "sorcery changeset creation unit test when no changes exist";
1503 "Test changeset creation in sorcery when no changes actually exist";
1504 return AST_TEST_NOT_RUN;
1509 if (!(tmp = ast_variable_new("bananas", "purple", ""))) {
1510 ast_test_status_update(test, "Failed to create first field for original objectset\n");
1511 return AST_TEST_FAIL;
1513 tmp->next = original;
1516 if (!(tmp = ast_variable_new("apples", "orange", ""))) {
1517 ast_test_status_update(test, "Failed to create second field for original objectset\n");
1518 return AST_TEST_FAIL;
1520 tmp->next = original;
1523 if (ast_sorcery_changeset_create(original, original, &changes)) {
1524 ast_test_status_update(test, "Failed to create a changeset due to an error\n");
1525 return AST_TEST_FAIL;
1526 } else if (changes) {
1527 ast_test_status_update(test, "Created a changeset when no changes actually exist\n");
1528 return AST_TEST_FAIL;
1531 if (!(tmp = ast_variable_new("bananas", "purple", ""))) {
1532 ast_test_status_update(test, "Failed to create first field for same objectset\n");
1533 return AST_TEST_FAIL;
1538 if (!(tmp = ast_variable_new("apples", "orange", ""))) {
1539 ast_test_status_update(test, "Failed to create second field for same objectset\n");
1540 return AST_TEST_FAIL;
1545 if (ast_sorcery_changeset_create(original, same, &changes)) {
1546 ast_test_status_update(test, "Failed to create a changeset due to an error\n");
1547 return AST_TEST_FAIL;
1548 } else if (changes) {
1549 ast_test_status_update(test, "Created a changeset between two different objectsets when no changes actually exist\n");
1550 return AST_TEST_FAIL;
1553 return AST_TEST_PASS;
1556 AST_TEST_DEFINE(object_create)
1558 RAII_VAR(struct ast_sorcery *, sorcery, NULL, ast_sorcery_unref);
1559 RAII_VAR(struct test_sorcery_object *, obj, NULL, ao2_cleanup);
1563 info->name = "object_create";
1564 info->category = "/main/sorcery/";
1565 info->summary = "sorcery object creation unit test";
1567 "Test object creation in sorcery";
1568 return AST_TEST_NOT_RUN;
1573 if (!(sorcery = alloc_and_initialize_sorcery())) {
1574 ast_test_status_update(test, "Failed to open sorcery structure\n");
1575 return AST_TEST_FAIL;
1578 if (!(obj = ast_sorcery_alloc(sorcery, "test", "blah"))) {
1579 ast_test_status_update(test, "Failed to allocate a known object type\n");
1580 return AST_TEST_FAIL;
1583 if (ast_sorcery_create(sorcery, obj)) {
1584 ast_test_status_update(test, "Failed to create object using in-memory wizard\n");
1585 return AST_TEST_FAIL;
1588 return AST_TEST_PASS;
1591 AST_TEST_DEFINE(object_retrieve_id)
1593 RAII_VAR(struct ast_sorcery *, sorcery, NULL, ast_sorcery_unref);
1594 RAII_VAR(struct test_sorcery_object *, obj, NULL, ao2_cleanup);
1598 info->name = "object_retrieve_id";
1599 info->category = "/main/sorcery/";
1600 info->summary = "sorcery object retrieval using id unit test";
1602 "Test object retrieval using id in sorcery";
1603 return AST_TEST_NOT_RUN;
1608 if (!(sorcery = alloc_and_initialize_sorcery())) {
1609 ast_test_status_update(test, "Failed to open sorcery structure\n");
1610 return AST_TEST_FAIL;
1613 if (!(obj = ast_sorcery_alloc(sorcery, "test", "blah"))) {
1614 ast_test_status_update(test, "Failed to allocate a known object type\n");
1615 return AST_TEST_FAIL;
1618 if (ast_sorcery_create(sorcery, obj)) {
1619 ast_test_status_update(test, "Failed to create object using in-memory wizard\n");
1620 return AST_TEST_FAIL;
1625 if (!(obj = ast_sorcery_alloc(sorcery, "test", "blah2"))) {
1626 ast_test_status_update(test, "Failed to allocate second instance of a known object type\n");
1627 return AST_TEST_FAIL;
1630 if (ast_sorcery_create(sorcery, obj)) {
1631 ast_test_status_update(test, "Failed to create second object using in-memory wizard\n");
1632 return AST_TEST_FAIL;
1637 if (!(obj = ast_sorcery_retrieve_by_id(sorcery, "test", "blah"))) {
1638 ast_test_status_update(test, "Failed to retrieve properly created object using id of 'blah'\n");
1639 return AST_TEST_FAIL;
1640 } else if (strcmp(ast_sorcery_object_get_id(obj), "blah")) {
1641 ast_test_status_update(test, "Retrieved object does not have correct id\n");
1642 return AST_TEST_FAIL;
1645 return AST_TEST_PASS;
1648 AST_TEST_DEFINE(object_retrieve_field)
1650 RAII_VAR(struct ast_sorcery *, sorcery, NULL, ast_sorcery_unref);
1651 RAII_VAR(struct test_sorcery_object *, obj, NULL, ao2_cleanup);
1652 RAII_VAR(struct ast_variable *, fields, ast_variable_new("joe", "42", ""), ast_variables_destroy);
1656 info->name = "object_retrieve_field";
1657 info->category = "/main/sorcery/";
1658 info->summary = "sorcery object retrieval using a specific field unit test";
1660 "Test object retrieval using a specific field in sorcery";
1661 return AST_TEST_NOT_RUN;
1667 ast_test_status_update(test, "Failed to create fields for object retrieval attempt\n");
1668 return AST_TEST_FAIL;
1671 if (!(sorcery = alloc_and_initialize_sorcery())) {
1672 ast_test_status_update(test, "Failed to open sorcery structure\n");
1673 return AST_TEST_FAIL;
1676 if (!(obj = ast_sorcery_alloc(sorcery, "test", "blah"))) {
1677 ast_test_status_update(test, "Failed to allocate a known object type\n");
1678 return AST_TEST_FAIL;
1683 if (ast_sorcery_create(sorcery, obj)) {
1684 ast_test_status_update(test, "Failed to create object using in-memory wizard\n");
1685 return AST_TEST_FAIL;
1690 if (!(obj = ast_sorcery_retrieve_by_fields(sorcery, "test", AST_RETRIEVE_FLAG_DEFAULT, fields))) {
1691 ast_test_status_update(test, "Failed to retrieve properly created object using 'joe' field\n");
1692 return AST_TEST_FAIL;
1696 ast_variables_destroy(fields);
1698 if (!(fields = ast_variable_new("joe", "49", ""))) {
1699 ast_test_status_update(test, "Failed to create fields for object retrieval attempt\n");
1700 return AST_TEST_FAIL;
1703 if ((obj = ast_sorcery_retrieve_by_fields(sorcery, "test", AST_RETRIEVE_FLAG_DEFAULT, fields))) {
1704 ast_test_status_update(test, "Retrieved an object using a field with an in-correct value... that should not happen\n");
1705 return AST_TEST_FAIL;
1708 return AST_TEST_PASS;
1711 AST_TEST_DEFINE(object_retrieve_multiple_all)
1713 RAII_VAR(struct ast_sorcery *, sorcery, NULL, ast_sorcery_unref);
1714 RAII_VAR(struct test_sorcery_object *, obj, NULL, ao2_cleanup);
1715 RAII_VAR(struct ao2_container *, objects, NULL, ao2_cleanup);
1719 info->name = "object_retrieve_multiple_all";
1720 info->category = "/main/sorcery/";
1721 info->summary = "sorcery multiple object retrieval unit test";
1723 "Test multiple object retrieval in sorcery";
1724 return AST_TEST_NOT_RUN;
1729 if (!(sorcery = alloc_and_initialize_sorcery())) {
1730 ast_test_status_update(test, "Failed to open sorcery structure\n");
1731 return AST_TEST_FAIL;
1734 if (!(obj = ast_sorcery_alloc(sorcery, "test", "blah"))) {
1735 ast_test_status_update(test, "Failed to allocate a known object type\n");
1736 return AST_TEST_FAIL;
1739 if (ast_sorcery_create(sorcery, obj)) {
1740 ast_test_status_update(test, "Failed to create object using in-memory wizard\n");
1741 return AST_TEST_FAIL;
1746 if (!(obj = ast_sorcery_alloc(sorcery, "test", "blah2"))) {
1747 ast_test_status_update(test, "Failed to allocate second instance of a known object type\n");
1748 return AST_TEST_FAIL;
1751 if (ast_sorcery_create(sorcery, obj)) {
1752 ast_test_status_update(test, "Failed to create second object using in-memory wizard\n");
1753 return AST_TEST_FAIL;
1756 if (!(objects = ast_sorcery_retrieve_by_fields(sorcery, "test", AST_RETRIEVE_FLAG_MULTIPLE | AST_RETRIEVE_FLAG_ALL, NULL))) {
1757 ast_test_status_update(test, "Failed to retrieve a container of all objects\n");
1758 return AST_TEST_FAIL;
1759 } else if (ao2_container_count(objects) != 2) {
1760 ast_test_status_update(test, "Received a container with no objects in it when there should be some\n");
1761 return AST_TEST_FAIL;
1764 return AST_TEST_PASS;
1767 AST_TEST_DEFINE(object_retrieve_multiple_field)
1769 RAII_VAR(struct ast_sorcery *, sorcery, NULL, ast_sorcery_unref);
1770 RAII_VAR(struct test_sorcery_object *, obj, NULL, ao2_cleanup);
1771 RAII_VAR(struct ao2_container *, objects, NULL, ao2_cleanup);
1772 RAII_VAR(struct ast_variable *, fields, ast_variable_new("joe", "6", ""), ast_variables_destroy);
1776 info->name = "object_retrieve_multiple_field";
1777 info->category = "/main/sorcery/";
1778 info->summary = "sorcery multiple object retrieval unit test";
1780 "Test multiple object retrieval in sorcery using fields";
1781 return AST_TEST_NOT_RUN;
1787 ast_test_status_update(test, "Failed to create fields for multiple retrieve\n");
1788 return AST_TEST_FAIL;
1791 if (!(sorcery = alloc_and_initialize_sorcery())) {
1792 ast_test_status_update(test, "Failed to open sorcery structure\n");
1793 return AST_TEST_FAIL;
1796 if (!(obj = ast_sorcery_alloc(sorcery, "test", "blah"))) {
1797 ast_test_status_update(test, "Failed to allocate a known object type\n");
1798 return AST_TEST_FAIL;
1803 if (ast_sorcery_create(sorcery, obj)) {
1804 ast_test_status_update(test, "Failed to create object using in-memory wizard\n");
1805 return AST_TEST_FAIL;
1808 if (!(objects = ast_sorcery_retrieve_by_fields(sorcery, "test", AST_RETRIEVE_FLAG_MULTIPLE, fields))) {
1809 ast_test_status_update(test, "Failed to retrieve a container of all objects\n");
1810 return AST_TEST_FAIL;
1811 } else if (ao2_container_count(objects) != 1) {
1812 ast_test_status_update(test, "Received a container with no objects in it when there should be some\n");
1813 return AST_TEST_FAIL;
1816 ao2_cleanup(objects);
1817 ast_variables_destroy(fields);
1819 if (!(fields = ast_variable_new("joe", "7", ""))) {
1820 ast_test_status_update(test, "Failed to create fields for multiple retrieval\n");
1821 return AST_TEST_FAIL;
1822 } else if (!(objects = ast_sorcery_retrieve_by_fields(sorcery, "test", AST_RETRIEVE_FLAG_MULTIPLE, fields))) {
1823 ast_test_status_update(test, "Failed to retrieve an empty container when retrieving multiple\n");
1824 return AST_TEST_FAIL;
1825 } else if (ao2_container_count(objects)) {
1826 ast_test_status_update(test, "Received a container with objects when there should be none in it\n");
1827 return AST_TEST_FAIL;
1830 return AST_TEST_PASS;
1833 AST_TEST_DEFINE(object_retrieve_regex)
1835 RAII_VAR(struct ast_sorcery *, sorcery, NULL, ast_sorcery_unref);
1836 RAII_VAR(struct test_sorcery_object *, obj, NULL, ao2_cleanup);
1837 RAII_VAR(struct ao2_container *, objects, NULL, ao2_cleanup);
1841 info->name = "object_retrieve_regex";
1842 info->category = "/main/sorcery/";
1843 info->summary = "sorcery multiple object retrieval using regex unit test";
1845 "Test multiple object retrieval in sorcery using regular expression for matching";
1846 return AST_TEST_NOT_RUN;
1851 if (!(sorcery = alloc_and_initialize_sorcery())) {
1852 ast_test_status_update(test, "Failed to open sorcery structure\n");
1853 return AST_TEST_FAIL;
1856 if (!(obj = ast_sorcery_alloc(sorcery, "test", "blah-98joe"))) {
1857 ast_test_status_update(test, "Failed to allocate a known object type\n");
1858 return AST_TEST_FAIL;
1861 if (ast_sorcery_create(sorcery, obj)) {
1862 ast_test_status_update(test, "Failed to create object using in-memory wizard\n");
1863 return AST_TEST_FAIL;
1868 if (!(obj = ast_sorcery_alloc(sorcery, "test", "blah-93joe"))) {
1869 ast_test_status_update(test, "Failed to allocate second instance of a known object type\n");
1870 return AST_TEST_FAIL;
1873 if (ast_sorcery_create(sorcery, obj)) {
1874 ast_test_status_update(test, "Failed to create second object using in-memory wizard\n");
1875 return AST_TEST_FAIL;
1880 if (!(obj = ast_sorcery_alloc(sorcery, "test", "neener-93joe"))) {
1881 ast_test_status_update(test, "Failed to allocate third instance of a known object type\n");
1882 return AST_TEST_FAIL;
1885 if (ast_sorcery_create(sorcery, obj)) {
1886 ast_test_status_update(test, "Failed to create third object using in-memory wizard\n");
1887 return AST_TEST_FAIL;
1890 if (!(objects = ast_sorcery_retrieve_by_regex(sorcery, "test", "^blah-"))) {
1891 ast_test_status_update(test, "Failed to retrieve a container of objects\n");
1892 return AST_TEST_FAIL;
1893 } else if (ao2_container_count(objects) != 2) {
1894 ast_test_status_update(test, "Received a container with incorrect number of objects in it\n");
1895 return AST_TEST_FAIL;
1898 return AST_TEST_PASS;
1901 AST_TEST_DEFINE(object_update)
1903 RAII_VAR(struct ast_sorcery *, sorcery, NULL, ast_sorcery_unref);
1904 RAII_VAR(struct test_sorcery_object *, obj, NULL, ao2_cleanup);
1905 RAII_VAR(struct test_sorcery_object *, obj2, NULL, ao2_cleanup);
1909 info->name = "object_update";
1910 info->category = "/main/sorcery/";
1911 info->summary = "sorcery object update unit test";
1913 "Test object updating in sorcery";
1914 return AST_TEST_NOT_RUN;
1919 if (!(sorcery = alloc_and_initialize_sorcery())) {
1920 ast_test_status_update(test, "Failed to open sorcery structure\n");
1921 return AST_TEST_FAIL;
1924 if (!(obj = ast_sorcery_alloc(sorcery, "test", "blah"))) {
1925 ast_test_status_update(test, "Failed to allocate a known object type\n");
1926 return AST_TEST_FAIL;
1929 if (ast_sorcery_create(sorcery, obj)) {
1930 ast_test_status_update(test, "Failed to create object using in-memory wizard\n");
1931 return AST_TEST_FAIL;
1934 if (!(obj2 = ast_sorcery_copy(sorcery, obj))) {
1935 ast_test_status_update(test, "Failed to allocate a known object type for updating\n");
1936 return AST_TEST_FAIL;
1941 if (ast_sorcery_update(sorcery, obj2)) {
1942 ast_test_status_update(test, "Failed to update sorcery with new object\n");
1943 return AST_TEST_FAIL;
1946 if (!(obj = ast_sorcery_retrieve_by_id(sorcery, "test", "blah"))) {
1947 ast_test_status_update(test, "Failed to retrieve properly updated object\n");
1948 return AST_TEST_FAIL;
1949 } else if (obj != obj2) {
1950 ast_test_status_update(test, "Object retrieved is not the updated object\n");
1951 return AST_TEST_FAIL;
1954 return AST_TEST_PASS;
1957 AST_TEST_DEFINE(object_update_uncreated)
1959 RAII_VAR(struct ast_sorcery *, sorcery, NULL, ast_sorcery_unref);
1960 RAII_VAR(struct test_sorcery_object *, obj, NULL, ao2_cleanup);
1964 info->name = "object_update_uncreated";
1965 info->category = "/main/sorcery/";
1966 info->summary = "sorcery object update unit test";
1968 "Test updating of an uncreated object in sorcery";
1969 return AST_TEST_NOT_RUN;
1974 if (!(sorcery = alloc_and_initialize_sorcery())) {
1975 ast_test_status_update(test, "Failed to open sorcery structure\n");
1976 return AST_TEST_FAIL;
1979 if (!(obj = ast_sorcery_alloc(sorcery, "test", "blah"))) {
1980 ast_test_status_update(test, "Failed to allocate a known object type\n");
1981 return AST_TEST_FAIL;
1984 if (!ast_sorcery_update(sorcery, obj)) {
1985 ast_test_status_update(test, "Successfully updated an object which has not been created yet\n");
1986 return AST_TEST_FAIL;
1989 return AST_TEST_PASS;
1992 AST_TEST_DEFINE(object_delete)
1994 RAII_VAR(struct ast_sorcery *, sorcery, NULL, ast_sorcery_unref);
1995 RAII_VAR(struct test_sorcery_object *, obj, NULL, ao2_cleanup);
1999 info->name = "object_delete";
2000 info->category = "/main/sorcery/";
2001 info->summary = "sorcery object deletion unit test";
2003 "Test object deletion in sorcery";
2004 return AST_TEST_NOT_RUN;
2009 if (!(sorcery = alloc_and_initialize_sorcery())) {
2010 ast_test_status_update(test, "Failed to open sorcery structure\n");
2011 return AST_TEST_FAIL;
2014 if (!(obj = ast_sorcery_alloc(sorcery, "test", "blah"))) {
2015 ast_test_status_update(test, "Failed to allocate a known object type\n");
2016 return AST_TEST_FAIL;
2019 if (ast_sorcery_create(sorcery, obj)) {
2020 ast_test_status_update(test, "Failed to create object using in-memory wizard\n");
2021 return AST_TEST_FAIL;
2024 if (ast_sorcery_delete(sorcery, obj)) {
2025 ast_test_status_update(test, "Failed to delete object using in-memory wizard\n");
2026 return AST_TEST_FAIL;
2031 if ((obj = ast_sorcery_retrieve_by_id(sorcery, "test", "blah"))) {
2032 ast_test_status_update(test, "Retrieved deleted object that should not be there\n");
2033 return AST_TEST_FAIL;
2036 return AST_TEST_PASS;
2039 AST_TEST_DEFINE(object_delete_uncreated)
2041 RAII_VAR(struct ast_sorcery *, sorcery, NULL, ast_sorcery_unref);
2042 RAII_VAR(struct test_sorcery_object *, obj, NULL, ao2_cleanup);
2046 info->name = "object_delete_uncreated";
2047 info->category = "/main/sorcery/";
2048 info->summary = "sorcery object deletion unit test";
2050 "Test object deletion of an uncreated object in sorcery";
2051 return AST_TEST_NOT_RUN;
2056 if (!(sorcery = alloc_and_initialize_sorcery())) {
2057 ast_test_status_update(test, "Failed to open sorcery structure\n");
2058 return AST_TEST_FAIL;
2061 if (!(obj = ast_sorcery_alloc(sorcery, "test", "blah"))) {
2062 ast_test_status_update(test, "Failed to allocate a known object type\n");
2063 return AST_TEST_FAIL;
2066 if (!ast_sorcery_delete(sorcery, obj)) {
2067 ast_test_status_update(test, "Successfully deleted an object which was never created\n");
2068 return AST_TEST_FAIL;
2071 return AST_TEST_PASS;
2074 AST_TEST_DEFINE(caching_wizard_behavior)
2076 struct ast_flags flags = { CONFIG_FLAG_NOCACHE };
2077 struct ast_config *config;
2078 RAII_VAR(struct ast_sorcery *, sorcery, NULL, ast_sorcery_unref);
2079 RAII_VAR(struct test_sorcery_object *, obj, NULL, ao2_cleanup);
2080 RAII_VAR(struct test_sorcery_object *, obj2, NULL, ao2_cleanup);
2081 int res = AST_TEST_FAIL;
2085 info->name = "caching_wizard_behavior";
2086 info->category = "/main/sorcery/";
2087 info->summary = "sorcery caching wizard behavior unit test";
2089 "Test internal behavior of caching wizards";
2090 return AST_TEST_NOT_RUN;
2095 if (!(config = ast_config_load2("sorcery.conf", "test_sorcery_cache", flags))) {
2096 ast_test_status_update(test, "Sorcery configuration file not present - skipping caching_wizard_behavior test\n");
2097 return AST_TEST_NOT_RUN;
2100 if (!ast_category_get(config, "test_sorcery_cache")) {
2101 ast_test_status_update(test, "Sorcery configuration file does not contain 'test_sorcery_cache' section\n");
2102 ast_config_destroy(config);
2103 return AST_TEST_NOT_RUN;
2106 ast_config_destroy(config);
2108 if (ast_sorcery_wizard_register(&test_wizard)) {
2109 ast_test_status_update(test, "Failed to register a perfectly valid sorcery wizard\n");
2110 return AST_TEST_FAIL;
2113 if (!(sorcery = ast_sorcery_open())) {
2114 ast_test_status_update(test, "Failed to open sorcery structure\n");
2118 if (ast_sorcery_apply_config(sorcery, "test_sorcery_cache")) {
2119 ast_test_status_update(test, "Failed to apply configured object mappings\n");
2123 if (ast_sorcery_internal_object_register(sorcery, "test", test_sorcery_object_alloc, NULL, NULL)) {
2124 ast_test_status_update(test, "Failed to register object type\n");
2128 if (!(obj = ast_sorcery_alloc(sorcery, "test", "blah"))) {
2129 ast_test_status_update(test, "Failed to allocate a known object type\n");
2133 if (ast_sorcery_create(sorcery, obj)) {
2134 ast_test_status_update(test, "Failed to create object using in-memory wizard\n");
2140 if (!(obj = ast_sorcery_retrieve_by_id(sorcery, "test", "blah"))) {
2141 ast_test_status_update(test, "Failed to retrieve just created object\n");
2143 } else if (!cache.created) {
2144 ast_test_status_update(test, "Caching wizard was not told to cache just created object\n");
2146 } else if (!(obj2 = ast_sorcery_retrieve_by_id(sorcery, "test", "blah"))) {
2147 ast_test_status_update(test, "Failed to retrieve just cached object\n");
2149 } else if (obj == obj2) {
2150 ast_test_status_update(test, "Returned object is *NOT* a cached object\n");
2152 } else if (ast_sorcery_update(sorcery, obj)) {
2153 ast_test_status_update(test, "Failed to update a known stored object\n");
2155 } else if (!cache.updated) {
2156 ast_test_status_update(test, "Caching wizard was not told to update object\n");
2158 } else if (ast_sorcery_delete(sorcery, obj)) {
2159 ast_test_status_update(test, "Failed to delete a known stored object\n");
2161 } else if (!cache.deleted) {
2162 ast_test_status_update(test, "Caching wizard was not told to delete object\n");
2168 if ((obj2 = ast_sorcery_retrieve_by_id(sorcery, "test", "blah"))) {
2169 ast_test_status_update(test, "Retrieved an object that should have been deleted\n");
2173 res = AST_TEST_PASS;
2176 ast_sorcery_unref(sorcery);
2179 if (ast_sorcery_wizard_unregister(&test_wizard)) {
2180 ast_test_status_update(test, "Failed to unregister test sorcery wizard\n");
2181 return AST_TEST_FAIL;
2187 AST_TEST_DEFINE(object_type_observer)
2189 RAII_VAR(struct ast_sorcery *, sorcery, NULL, ast_sorcery_unref);
2190 RAII_VAR(struct test_sorcery_object *, obj, NULL, ao2_cleanup);
2191 int res = AST_TEST_FAIL;
2195 info->name = "object_type_observer";
2196 info->category = "/main/sorcery/";
2197 info->summary = "sorcery object type observer unit test";
2199 "Test that object type observers get called when they should";
2200 return AST_TEST_NOT_RUN;
2205 if (!(sorcery = alloc_and_initialize_sorcery())) {
2206 ast_test_status_update(test, "Failed to open sorcery structure\n");
2207 return AST_TEST_FAIL;
2210 if (!ast_sorcery_observer_add(sorcery, "test", NULL)) {
2211 ast_test_status_update(test, "Successfully added a NULL observer when it should not be possible\n");
2212 return AST_TEST_FAIL;
2215 if (ast_sorcery_observer_add(sorcery, "test", &test_observer)) {
2216 ast_test_status_update(test, "Failed to add a proper observer\n");
2217 return AST_TEST_FAIL;
2220 if (!(obj = ast_sorcery_alloc(sorcery, "test", "blah"))) {
2221 ast_test_status_update(test, "Failed to allocate a known object type\n");
2225 ast_mutex_init(&observer.lock);
2226 ast_cond_init(&observer.cond, NULL);
2227 observer.created = NULL;
2228 observer.updated = NULL;
2229 observer.deleted = NULL;
2231 if (ast_sorcery_create(sorcery, obj)) {
2232 ast_test_status_update(test, "Failed to create object using in-memory wizard\n");
2236 ast_mutex_lock(&observer.lock);
2237 while (!observer.created) {
2238 struct timeval start = ast_tvnow();
2239 struct timespec end = {
2240 .tv_sec = start.tv_sec + 10,
2241 .tv_nsec = start.tv_usec * 1000,
2243 if (ast_cond_timedwait(&observer.cond, &observer.lock, &end) == ETIMEDOUT) {
2247 ast_mutex_unlock(&observer.lock);
2249 if (!observer.created) {
2250 ast_test_status_update(test, "Failed to receive observer notification for object creation within suitable timeframe\n");
2254 if (ast_sorcery_update(sorcery, obj)) {
2255 ast_test_status_update(test, "Failed to update object using in-memory wizard\n");
2259 ast_mutex_lock(&observer.lock);
2260 while (!observer.updated) {
2261 struct timeval start = ast_tvnow();
2262 struct timespec end = {
2263 .tv_sec = start.tv_sec + 10,
2264 .tv_nsec = start.tv_usec * 1000,
2266 if (ast_cond_timedwait(&observer.cond, &observer.lock, &end) == ETIMEDOUT) {
2270 ast_mutex_unlock(&observer.lock);
2272 if (!observer.updated) {
2273 ast_test_status_update(test, "Failed to receive observer notification for object updating within suitable timeframe\n");
2277 if (ast_sorcery_delete(sorcery, obj)) {
2278 ast_test_status_update(test, "Failed to delete object using in-memory wizard\n");
2282 ast_mutex_lock(&observer.lock);
2283 while (!observer.deleted) {
2284 struct timeval start = ast_tvnow();
2285 struct timespec end = {
2286 .tv_sec = start.tv_sec + 10,
2287 .tv_nsec = start.tv_usec * 1000,
2289 if (ast_cond_timedwait(&observer.cond, &observer.lock, &end) == ETIMEDOUT) {
2293 ast_mutex_unlock(&observer.lock);
2295 if (!observer.deleted) {
2296 ast_test_status_update(test, "Failed to receive observer notification for object deletion within suitable timeframe\n");
2300 ast_sorcery_reload(sorcery);
2302 ast_mutex_lock(&observer.lock);
2303 while (!observer.loaded) {
2304 struct timeval start = ast_tvnow();
2305 struct timespec end = {
2306 .tv_sec = start.tv_sec + 10,
2307 .tv_nsec = start.tv_usec * 1000,
2309 if (ast_cond_timedwait(&observer.cond, &observer.lock, &end) == ETIMEDOUT) {
2313 ast_mutex_unlock(&observer.lock);
2315 if (!observer.loaded) {
2316 ast_test_status_update(test, "Failed to receive observer notification for object type load within suitable timeframe\n");
2320 res = AST_TEST_PASS;
2323 observer.created = NULL;
2324 observer.updated = NULL;
2325 observer.deleted = NULL;
2326 ast_mutex_destroy(&observer.lock);
2327 ast_cond_destroy(&observer.cond);
2332 AST_TEST_DEFINE(configuration_file_wizard)
2334 struct ast_flags flags = { CONFIG_FLAG_NOCACHE };
2335 struct ast_config *config;
2336 RAII_VAR(struct ast_sorcery *, sorcery, NULL, ast_sorcery_unref);
2337 RAII_VAR(struct test_sorcery_object *, obj, NULL, ao2_cleanup);
2341 info->name = "configuration_file_wizard";
2342 info->category = "/main/sorcery/";
2343 info->summary = "sorcery configuration file wizard unit test";
2345 "Test the configuration file wizard in sorcery";
2346 return AST_TEST_NOT_RUN;
2351 if (!(config = ast_config_load2("test_sorcery.conf", "test_sorcery", flags))) {
2352 ast_test_status_update(test, "Test sorcery configuration file wizard file not present - skipping configuration_file_wizard test\n");
2353 return AST_TEST_NOT_RUN;
2356 ast_config_destroy(config);
2358 if (!(sorcery = ast_sorcery_open())) {
2359 ast_test_status_update(test, "Failed to open sorcery structure\n");
2360 return AST_TEST_FAIL;
2363 if (ast_sorcery_apply_default(sorcery, "test", "config", "test_sorcery.conf")) {
2364 ast_test_status_update(test, "Could not set a default wizard of the 'config' type, so skipping since it may not be loaded\n");
2365 return AST_TEST_NOT_RUN;
2368 if (ast_sorcery_internal_object_register(sorcery, "test", test_sorcery_object_alloc, NULL, NULL)) {
2369 ast_test_status_update(test, "Failed to register object type\n");
2370 return AST_TEST_FAIL;
2373 ast_sorcery_object_field_register_nodoc(sorcery, "test", "bob", "5", OPT_UINT_T, 0, FLDSET(struct test_sorcery_object, bob));
2374 ast_sorcery_object_field_register_nodoc(sorcery, "test", "joe", "10", OPT_UINT_T, 0, FLDSET(struct test_sorcery_object, joe));
2376 ast_sorcery_load(sorcery);
2378 if ((obj = ast_sorcery_retrieve_by_id(sorcery, "test", "hey2"))) {
2379 ast_test_status_update(test, "Retrieved object which has an unknown field\n");
2380 return AST_TEST_FAIL;
2381 } else if (!(obj = ast_sorcery_retrieve_by_id(sorcery, "test", "hey"))) {
2382 ast_test_status_update(test, "Failed to retrieve a known object that has been configured in the configuration file\n");
2383 return AST_TEST_FAIL;
2384 } else if (obj->bob != 98) {
2385 ast_test_status_update(test, "Value of 'bob' on object is not what is configured in configuration file\n");
2386 return AST_TEST_FAIL;
2387 } else if (obj->joe != 41) {
2388 ast_test_status_update(test, "Value of 'joe' on object is not what is configured in configuration file\n");
2389 return AST_TEST_FAIL;
2392 return AST_TEST_PASS;
2395 AST_TEST_DEFINE(configuration_file_wizard_with_file_integrity)
2397 struct ast_flags flags = { CONFIG_FLAG_NOCACHE };
2398 struct ast_config *config;
2399 RAII_VAR(struct ast_sorcery *, sorcery, NULL, ast_sorcery_unref);
2400 RAII_VAR(struct test_sorcery_object *, obj, NULL, ao2_cleanup);
2404 info->name = "configuration_file_wizard_with_file_integrity";
2405 info->category = "/main/sorcery/";
2406 info->summary = "sorcery configuration file wizard file integrity unit test";
2408 "Test the configuration file wizard with file integrity turned on in sorcery";
2409 return AST_TEST_NOT_RUN;
2414 if (!(config = ast_config_load2("test_sorcery.conf", "test_sorcery", flags))) {
2415 ast_test_status_update(test, "Test sorcery configuration file wizard file not present - skipping configuration_file_wizard_with_file_integrity test\n");
2416 return AST_TEST_NOT_RUN;
2419 ast_config_destroy(config);
2421 if (!(sorcery = ast_sorcery_open())) {
2422 ast_test_status_update(test, "Failed to open sorcery structure\n");
2423 return AST_TEST_FAIL;
2426 if (ast_sorcery_apply_default(sorcery, "test", "config", "test_sorcery.conf,integrity=file")) {
2427 ast_test_status_update(test, "Could not set a default wizard of the 'config' type, so skipping since it may not be loaded\n");
2428 return AST_TEST_NOT_RUN;
2431 if (ast_sorcery_internal_object_register(sorcery, "test", test_sorcery_object_alloc, NULL, NULL)) {
2432 ast_test_status_update(test, "Failed to register object type\n");
2433 return AST_TEST_FAIL;
2436 ast_sorcery_object_field_register_nodoc(sorcery, "test", "bob", "5", OPT_UINT_T, 0, FLDSET(struct test_sorcery_object, bob));
2437 ast_sorcery_object_field_register_nodoc(sorcery, "test", "joe", "10", OPT_UINT_T, 0, FLDSET(struct test_sorcery_object, joe));
2439 ast_sorcery_load(sorcery);
2441 if ((obj = ast_sorcery_retrieve_by_id(sorcery, "test", "hey"))) {
2442 ast_test_status_update(test, "Retrieved object which has an unknown field\n");
2443 return AST_TEST_FAIL;
2446 return AST_TEST_PASS;
2449 AST_TEST_DEFINE(configuration_file_wizard_with_criteria)
2451 struct ast_flags flags = { CONFIG_FLAG_NOCACHE };
2452 struct ast_config *config;
2453 RAII_VAR(struct ast_sorcery *, sorcery, NULL, ast_sorcery_unref);
2454 RAII_VAR(struct test_sorcery_object *, obj, NULL, ao2_cleanup);
2458 info->name = "configuration_file_wizard_with_criteria";
2459 info->category = "/main/sorcery/";
2460 info->summary = "sorcery configuration file wizard with criteria unit test";
2462 "Test the configuration file wizard with criteria matching in sorcery";
2463 return AST_TEST_NOT_RUN;
2468 if (!(config = ast_config_load2("test_sorcery.conf", "test_sorcery", flags))) {
2469 ast_test_status_update(test, "Test sorcery configuration file wizard file not present - skipping configuration_file_wizard_with_criteria test\n");
2470 return AST_TEST_NOT_RUN;
2473 ast_config_destroy(config);
2475 if (!(sorcery = ast_sorcery_open())) {
2476 ast_test_status_update(test, "Failed to open sorcery structure\n");
2477 return AST_TEST_FAIL;
2480 if (ast_sorcery_apply_default(sorcery, "test", "config", "test_sorcery.conf,criteria=type=zombies")) {
2481 ast_test_status_update(test, "Could not set a default wizard of the 'config' type, so skipping since it may not be loaded\n");
2482 return AST_TEST_NOT_RUN;
2485 if (ast_sorcery_internal_object_register(sorcery, "test", test_sorcery_object_alloc, NULL, NULL)) {
2486 ast_test_status_update(test, "Failed to register object type\n");
2487 return AST_TEST_FAIL;
2490 ast_sorcery_object_field_register_nodoc(sorcery, "test", "bob", "5", OPT_UINT_T, 0, FLDSET(struct test_sorcery_object, bob));
2491 ast_sorcery_object_field_register_nodoc(sorcery, "test", "joe", "10", OPT_UINT_T, 0, FLDSET(struct test_sorcery_object, joe));
2492 ast_sorcery_object_field_register_nodoc(sorcery, "test", "type", NULL, OPT_NOOP_T, 0, NULL);
2494 ast_sorcery_load(sorcery);
2496 if ((obj = ast_sorcery_retrieve_by_id(sorcery, "test", "hey"))) {
2497 ast_test_status_update(test, "Retrieved object which did not match criteria\n");
2498 return AST_TEST_FAIL;
2499 } else if (!(obj = ast_sorcery_retrieve_by_id(sorcery, "test", "hey2"))) {
2500 ast_test_status_update(test, "Failed to retrieve a known object which matches criteria\n");
2501 return AST_TEST_FAIL;
2504 return AST_TEST_PASS;
2507 AST_TEST_DEFINE(configuration_file_wizard_retrieve_field)
2509 struct ast_flags flags = { CONFIG_FLAG_NOCACHE };
2510 struct ast_config *config;
2511 RAII_VAR(struct ast_sorcery *, sorcery, NULL, ast_sorcery_unref);
2512 RAII_VAR(struct test_sorcery_object *, obj, NULL, ao2_cleanup);
2513 RAII_VAR(struct ast_variable *, fields, ast_variable_new("joe", "41", ""), ast_variables_destroy);
2517 info->name = "configuration_file_wizard_retrieve_field";
2518 info->category = "/main/sorcery/";
2519 info->summary = "sorcery configuration file wizard field retrieval unit test";
2521 "Test the configuration file wizard retrieval using field in sorcery";
2522 return AST_TEST_NOT_RUN;
2527 if (!(config = ast_config_load2("test_sorcery.conf", "test_sorcery", flags))) {
2528 ast_test_status_update(test, "Test sorcery configuration file wizard file not present - skipping configuration_file_wizard_retrieve_field test\n");
2529 return AST_TEST_NOT_RUN;
2532 ast_config_destroy(config);
2534 if (!(sorcery = ast_sorcery_open())) {
2535 ast_test_status_update(test, "Failed to open sorcery structure\n");
2536 return AST_TEST_FAIL;
2539 if (ast_sorcery_apply_default(sorcery, "test", "config", "test_sorcery.conf")) {
2540 ast_test_status_update(test, "Could not set a default wizard of the 'config' type, so skipping since it may not be loaded\n");
2541 return AST_TEST_NOT_RUN;
2544 if (ast_sorcery_internal_object_register(sorcery, "test", test_sorcery_object_alloc, NULL, NULL)) {
2545 ast_test_status_update(test, "Failed to register object type\n");
2546 return AST_TEST_FAIL;
2549 ast_sorcery_object_field_register_nodoc(sorcery, "test", "bob", "5", OPT_UINT_T, 0, FLDSET(struct test_sorcery_object, bob));
2550 ast_sorcery_object_field_register_nodoc(sorcery, "test", "joe", "10", OPT_UINT_T, 0, FLDSET(struct test_sorcery_object, joe));
2552 ast_sorcery_load(sorcery);
2554 if (!(obj = ast_sorcery_retrieve_by_fields(sorcery, "test", AST_RETRIEVE_FLAG_DEFAULT, fields))) {
2555 ast_test_status_update(test, "Failed to retrieve a known object that has been configured with the correct field\n");
2556 return AST_TEST_FAIL;
2557 } else if (strcmp(ast_sorcery_object_get_id(obj), "hey")) {
2558 ast_test_status_update(test, "Retrieved object has incorrect object id of '%s'\n", ast_sorcery_object_get_id(obj));
2559 return AST_TEST_FAIL;
2562 return AST_TEST_PASS;
2565 AST_TEST_DEFINE(configuration_file_wizard_retrieve_multiple)
2567 struct ast_flags flags = { CONFIG_FLAG_NOCACHE };
2568 struct ast_config *config;
2569 RAII_VAR(struct ast_sorcery *, sorcery, NULL, ast_sorcery_unref);
2570 RAII_VAR(struct ao2_container *, objects, NULL, ao2_cleanup);
2571 RAII_VAR(struct ast_variable *, fields, ast_variable_new("joe", "99", ""), ast_variables_destroy);
2575 info->name = "configuration_file_wizard_retrieve_multiple";
2576 info->category = "/main/sorcery/";
2577 info->summary = "sorcery configuration file wizard multiple retrieval unit test";
2579 "Test the configuration file wizard multiple retrieval in sorcery";
2580 return AST_TEST_NOT_RUN;
2585 if (!(config = ast_config_load2("test_sorcery.conf", "test_sorcery", flags))) {
2586 ast_test_status_update(test, "Test sorcery configuration file wizard file not present - skipping configuration_file_wizard_retrieve_multiple test\n");
2587 return AST_TEST_NOT_RUN;
2590 ast_config_destroy(config);
2593 ast_test_status_update(test, "Failed to create fields for multiple retrieve\n");
2594 return AST_TEST_FAIL;
2597 if (!(sorcery = ast_sorcery_open())) {
2598 ast_test_status_update(test, "Failed to open sorcery structure\n");
2599 return AST_TEST_FAIL;
2602 if (ast_sorcery_apply_default(sorcery, "test", "config", "test_sorcery.conf")) {
2603 ast_test_status_update(test, "Could not set a default wizard of the 'config' type, so skipping since it may not be loaded\n");
2604 return AST_TEST_NOT_RUN;
2607 if (ast_sorcery_internal_object_register(sorcery, "test", test_sorcery_object_alloc, NULL, NULL)) {
2608 ast_test_status_update(test, "Failed to register object type\n");
2609 return AST_TEST_FAIL;
2612 ast_sorcery_object_field_register_nodoc(sorcery, "test", "bob", "5", OPT_UINT_T, 0, FLDSET(struct test_sorcery_object, bob));
2613 ast_sorcery_object_field_register_nodoc(sorcery, "test", "joe", "10", OPT_UINT_T, 0, FLDSET(struct test_sorcery_object, joe));
2615 ast_sorcery_load(sorcery);
2617 if (!(objects = ast_sorcery_retrieve_by_fields(sorcery, "test", AST_RETRIEVE_FLAG_MULTIPLE, fields))) {
2618 ast_test_status_update(test, "Failed to retrieve an empty container when retrieving multiple\n");
2619 return AST_TEST_FAIL;
2620 } else if (ao2_container_count(objects)) {
2621 ast_test_status_update(test, "Received a container with objects when there should be none in it\n");
2622 return AST_TEST_FAIL;
2625 ao2_cleanup(objects);
2626 ast_variables_destroy(fields);
2628 if (!(fields = ast_variable_new("joe", "41", ""))) {
2629 ast_test_status_update(test, "Failed to create fields for multiple retrieve\n");
2630 return AST_TEST_FAIL;
2631 } else if (!(objects = ast_sorcery_retrieve_by_fields(sorcery, "test", AST_RETRIEVE_FLAG_MULTIPLE, fields))) {
2632 ast_test_status_update(test, "Failed to retrieve a container when retrieving multiple\n");
2633 return AST_TEST_FAIL;
2634 } else if (ao2_container_count(objects) != 1) {
2635 ast_test_status_update(test, "Received a container with no objects in it when there should be\n");
2636 return AST_TEST_FAIL;
2639 return AST_TEST_PASS;
2642 AST_TEST_DEFINE(configuration_file_wizard_retrieve_multiple_all)
2644 struct ast_flags flags = { CONFIG_FLAG_NOCACHE };
2645 struct ast_config *config;
2646 RAII_VAR(struct ast_sorcery *, sorcery, NULL, ast_sorcery_unref);
2647 RAII_VAR(struct ao2_container *, objects, NULL, ao2_cleanup);
2651 info->name = "configuration_file_wizard_retrieve_multiple_all";
2652 info->category = "/main/sorcery/";
2653 info->summary = "sorcery configuration file wizard multiple retrieve all unit test";
2655 "Test the configuration file wizard multiple retrieve all in sorcery";
2656 return AST_TEST_NOT_RUN;
2661 if (!(config = ast_config_load2("test_sorcery.conf", "test_sorcery", flags))) {
2662 ast_test_status_update(test, "Test sorcery configuration file wizard file not present - skipping configuration_file_wizard_retrieve_multiple_all test\n");
2663 return AST_TEST_NOT_RUN;
2666 ast_config_destroy(config);
2668 if (!(sorcery = ast_sorcery_open())) {
2669 ast_test_status_update(test, "Failed to open sorcery structure\n");
2670 return AST_TEST_FAIL;
2673 if (ast_sorcery_apply_default(sorcery, "test", "config", "test_sorcery.conf")) {
2674 ast_test_status_update(test, "Could not set a default wizard of the 'config' type, so skipping since it may not be loaded\n");
2675 return AST_TEST_NOT_RUN;
2678 if (ast_sorcery_internal_object_register(sorcery, "test", test_sorcery_object_alloc, NULL, NULL)) {
2679 ast_test_status_update(test, "Failed to register object type\n");
2680 return AST_TEST_FAIL;
2683 ast_sorcery_object_field_register_nodoc(sorcery, "test", "bob", "5", OPT_UINT_T, 0, FLDSET(struct test_sorcery_object, bob));
2684 ast_sorcery_object_field_register_nodoc(sorcery, "test", "joe", "10", OPT_UINT_T, 0, FLDSET(struct test_sorcery_object, joe));
2686 ast_sorcery_load(sorcery);
2688 if (!(objects = ast_sorcery_retrieve_by_fields(sorcery, "test", AST_RETRIEVE_FLAG_MULTIPLE | AST_RETRIEVE_FLAG_ALL, NULL))) {
2689 ast_test_status_update(test, "Failed to retrieve a container with all objects when there should be one\n");
2690 return AST_TEST_FAIL;
2691 } else if (ao2_container_count(objects) != 2) {
2692 ast_test_status_update(test, "Returned container does not have the correct number of objects in it\n");
2693 return AST_TEST_FAIL;
2696 return AST_TEST_PASS;
2699 static int unload_module(void)
2701 AST_TEST_UNREGISTER(wizard_registration);
2702 AST_TEST_UNREGISTER(sorcery_open);
2703 AST_TEST_UNREGISTER(apply_default);
2704 AST_TEST_UNREGISTER(apply_config);
2705 AST_TEST_UNREGISTER(object_register);
2706 AST_TEST_UNREGISTER(object_register_without_mapping);
2707 AST_TEST_UNREGISTER(object_field_register);
2708 AST_TEST_UNREGISTER(object_fields_register);
2709 AST_TEST_UNREGISTER(object_alloc_with_id);
2710 AST_TEST_UNREGISTER(object_alloc_without_id);
2711 AST_TEST_UNREGISTER(object_copy);
2712 AST_TEST_UNREGISTER(object_copy_native);
2713 AST_TEST_UNREGISTER(object_diff);
2714 AST_TEST_UNREGISTER(object_diff_native);
2715 AST_TEST_UNREGISTER(objectset_create);
2716 AST_TEST_UNREGISTER(objectset_json_create);
2717 AST_TEST_UNREGISTER(objectset_create_regex);
2718 AST_TEST_UNREGISTER(objectset_apply);
2719 AST_TEST_UNREGISTER(objectset_apply_handler);
2720 AST_TEST_UNREGISTER(objectset_apply_invalid);
2721 AST_TEST_UNREGISTER(objectset_transform);
2722 AST_TEST_UNREGISTER(objectset_apply_fields);
2723 AST_TEST_UNREGISTER(extended_fields);
2724 AST_TEST_UNREGISTER(changeset_create);
2725 AST_TEST_UNREGISTER(changeset_create_unchanged);
2726 AST_TEST_UNREGISTER(object_create);
2727 AST_TEST_UNREGISTER(object_retrieve_id);
2728 AST_TEST_UNREGISTER(object_retrieve_field);
2729 AST_TEST_UNREGISTER(object_retrieve_multiple_all);
2730 AST_TEST_UNREGISTER(object_retrieve_multiple_field);
2731 AST_TEST_UNREGISTER(object_retrieve_regex);
2732 AST_TEST_UNREGISTER(object_update);
2733 AST_TEST_UNREGISTER(object_update_uncreated);
2734 AST_TEST_UNREGISTER(object_delete);
2735 AST_TEST_UNREGISTER(object_delete_uncreated);
2736 AST_TEST_UNREGISTER(caching_wizard_behavior);
2737 AST_TEST_UNREGISTER(object_type_observer);
2738 AST_TEST_UNREGISTER(configuration_file_wizard);
2739 AST_TEST_UNREGISTER(configuration_file_wizard_with_file_integrity);
2740 AST_TEST_UNREGISTER(configuration_file_wizard_with_criteria);
2741 AST_TEST_UNREGISTER(configuration_file_wizard_retrieve_field);
2742 AST_TEST_UNREGISTER(configuration_file_wizard_retrieve_multiple);
2743 AST_TEST_UNREGISTER(configuration_file_wizard_retrieve_multiple_all);
2747 static int load_module(void)
2749 AST_TEST_REGISTER(wizard_registration);
2750 AST_TEST_REGISTER(sorcery_open);
2751 AST_TEST_REGISTER(apply_default);
2752 AST_TEST_REGISTER(apply_config);
2753 AST_TEST_REGISTER(object_register);
2754 AST_TEST_REGISTER(object_register_without_mapping);
2755 AST_TEST_REGISTER(object_field_register);
2756 AST_TEST_REGISTER(object_fields_register);
2757 AST_TEST_REGISTER(object_alloc_with_id);
2758 AST_TEST_REGISTER(object_alloc_without_id);
2759 AST_TEST_REGISTER(object_copy);
2760 AST_TEST_REGISTER(object_copy_native);
2761 AST_TEST_REGISTER(object_diff);
2762 AST_TEST_REGISTER(object_diff_native);
2763 AST_TEST_REGISTER(objectset_create);
2764 AST_TEST_REGISTER(objectset_json_create);
2765 AST_TEST_REGISTER(objectset_create_regex);
2766 AST_TEST_REGISTER(objectset_apply);
2767 AST_TEST_REGISTER(objectset_apply_handler);
2768 AST_TEST_REGISTER(objectset_apply_invalid);
2769 AST_TEST_REGISTER(objectset_transform);
2770 AST_TEST_REGISTER(objectset_apply_fields);
2771 AST_TEST_REGISTER(extended_fields);
2772 AST_TEST_REGISTER(changeset_create);
2773 AST_TEST_REGISTER(changeset_create_unchanged);
2774 AST_TEST_REGISTER(object_create);
2775 AST_TEST_REGISTER(object_retrieve_id);
2776 AST_TEST_REGISTER(object_retrieve_field);
2777 AST_TEST_REGISTER(object_retrieve_multiple_all);
2778 AST_TEST_REGISTER(object_retrieve_multiple_field);
2779 AST_TEST_REGISTER(object_retrieve_regex);
2780 AST_TEST_REGISTER(object_update);
2781 AST_TEST_REGISTER(object_update_uncreated);
2782 AST_TEST_REGISTER(object_delete);
2783 AST_TEST_REGISTER(object_delete_uncreated);
2784 AST_TEST_REGISTER(caching_wizard_behavior);
2785 AST_TEST_REGISTER(object_type_observer);
2786 AST_TEST_REGISTER(configuration_file_wizard);
2787 AST_TEST_REGISTER(configuration_file_wizard_with_file_integrity);
2788 AST_TEST_REGISTER(configuration_file_wizard_with_criteria);
2789 AST_TEST_REGISTER(configuration_file_wizard_retrieve_field);
2790 AST_TEST_REGISTER(configuration_file_wizard_retrieve_multiple);
2791 AST_TEST_REGISTER(configuration_file_wizard_retrieve_multiple_all);
2792 return AST_MODULE_LOAD_SUCCESS;
2795 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Sorcery test module");