43 static struct ast_variable *realtime_sorcery(
const char *database,
const char *table,
const struct ast_variable *fields)
45 char *object_id = NULL;
58 static struct ast_config *realtime_sorcery_multi(
const char *database,
const char *table,
const struct ast_variable *fields)
61 char *object_id = NULL;
87 static int realtime_sorcery_update(
const char *database,
const char *table,
const char *keyfield,
const char *entity,
const struct ast_variable *fields)
99 ast_variable_append(
object, ast_variable_new(keyfield, entity,
""));
105 static int realtime_sorcery_store(
const char *database,
const char *table,
const struct ast_variable *fields)
121 static int realtime_sorcery_destroy(
const char *database,
const char *table,
const char *keyfield,
const char *entity,
const struct ast_variable *fields)
134 .name =
"sorcery_realtime_test",
135 .realtime_func = realtime_sorcery,
136 .realtime_multi_func = realtime_sorcery_multi,
137 .update_func = realtime_sorcery_update,
138 .store_func = realtime_sorcery_store,
139 .destroy_func = realtime_sorcery_destroy,
144 SORCERY_OBJECT(details);
155 static struct ast_sorcery *alloc_and_initialize_sorcery(
char *table)
176 static void deinitialize_sorcery(
struct ast_sorcery *sorcery)
179 realtime_objects = NULL;
190 info->name =
"object_create";
191 info->category =
"/res/sorcery_realtime/";
192 info->summary =
"sorcery realtime object creation unit test";
194 "Test object creation in sorcery using realtime wizard";
195 return AST_TEST_NOT_RUN;
200 if (!(sorcery = alloc_and_initialize_sorcery(
"sorcery_realtime_test"))) {
201 ast_test_status_update(
test,
"Failed to open sorcery structure\n");
202 return AST_TEST_FAIL;
206 ast_test_status_update(
test,
"Failed to allocate a known object type\n");
207 return AST_TEST_FAIL;
211 ast_test_status_update(
test,
"Failed to create object using realtime wizard\n");
212 return AST_TEST_FAIL;
215 return AST_TEST_PASS;
225 info->name =
"object_retrieve_id";
226 info->category =
"/res/sorcery_realtime/";
227 info->summary =
"sorcery object retrieval using id unit test";
229 "Test object retrieval using id in sorcery with realtime wizard";
230 return AST_TEST_NOT_RUN;
235 if (!(sorcery = alloc_and_initialize_sorcery(
"sorcery_realtime_test"))) {
236 ast_test_status_update(
test,
"Failed to open sorcery structure\n");
237 return AST_TEST_FAIL;
241 ast_test_status_update(
test,
"Failed to allocate a known object type\n");
242 return AST_TEST_FAIL;
246 ast_test_status_update(
test,
"Failed to create object using astdb wizard\n");
247 return AST_TEST_FAIL;
253 ast_test_status_update(
test,
"Failed to allocate second instance of a known object type\n");
254 return AST_TEST_FAIL;
258 ast_test_status_update(
test,
"Failed to create second object using astdb wizard\n");
259 return AST_TEST_FAIL;
265 ast_test_status_update(
test,
"Failed to retrieve properly created object using id of 'blah'\n");
266 return AST_TEST_FAIL;
268 ast_test_status_update(
test,
"Retrieved object does not have correct id\n");
269 return AST_TEST_FAIL;
272 return AST_TEST_PASS;
283 info->name =
"object_retrieve_field";
284 info->category =
"/res/sorcery_realtime/";
285 info->summary =
"sorcery object retrieval using a specific field unit test";
287 "Test object retrieval using a specific field in sorcery with realtime wizard";
288 return AST_TEST_NOT_RUN;
294 ast_test_status_update(
test,
"Failed to create fields for object retrieval attempt\n");
295 return AST_TEST_FAIL;
298 if (!(sorcery = alloc_and_initialize_sorcery(
"sorcery_realtime_test"))) {
299 ast_test_status_update(
test,
"Failed to open sorcery structure\n");
300 return AST_TEST_FAIL;
304 ast_test_status_update(
test,
"Failed to allocate a known object type\n");
305 return AST_TEST_FAIL;
311 ast_test_status_update(
test,
"Failed to create object using realtime wizard\n");
312 return AST_TEST_FAIL;
318 ast_test_status_update(
test,
"Failed to retrieve properly created object using 'joe' field\n");
319 return AST_TEST_FAIL;
325 if (!(fields = ast_variable_new(
"joe",
"49",
""))) {
326 ast_test_status_update(
test,
"Failed to create fields for object retrieval attempt\n");
327 return AST_TEST_FAIL;
331 ast_test_status_update(
test,
"Retrieved an object using a field with an in-correct value... that should not happen\n");
332 return AST_TEST_FAIL;
335 return AST_TEST_PASS;
346 info->name =
"object_retrieve_multiple_all";
347 info->category =
"/res/sorcery_realtime/";
348 info->summary =
"sorcery multiple object retrieval unit test";
350 "Test multiple object retrieval in sorcery using realtime wizard";
351 return AST_TEST_NOT_RUN;
356 if (!(sorcery = alloc_and_initialize_sorcery(
"sorcery_realtime_test"))) {
357 ast_test_status_update(
test,
"Failed to open sorcery structure\n");
358 return AST_TEST_FAIL;
362 ast_test_status_update(
test,
"Failed to allocate a known object type\n");
363 return AST_TEST_FAIL;
367 ast_test_status_update(
test,
"Failed to create object using realtime wizard\n");
368 return AST_TEST_FAIL;
374 ast_test_status_update(
test,
"Failed to allocate second instance of a known object type\n");
375 return AST_TEST_FAIL;
379 ast_test_status_update(
test,
"Failed to create second object using realtime wizard\n");
380 return AST_TEST_FAIL;
384 ast_test_status_update(
test,
"Failed to retrieve a container of all objects\n");
385 return AST_TEST_FAIL;
387 ast_test_status_update(
test,
"Received a container with no objects in it when there should be some\n");
388 return AST_TEST_FAIL;
391 return AST_TEST_PASS;
402 info->name =
"object_retrieve_multiple_all_nofetch";
403 info->category =
"/res/sorcery_realtime/";
404 info->summary =
"sorcery multiple object retrieval unit test";
406 "Test multiple object retrieval in sorcery using realtime wizard";
407 return AST_TEST_NOT_RUN;
412 if (!(sorcery = alloc_and_initialize_sorcery(
"sorcery_realtime_test,allow_unqualified_fetch=no"))) {
413 ast_test_status_update(
test,
"Failed to open sorcery structure\n");
414 return AST_TEST_FAIL;
418 ast_test_status_update(
test,
"Failed to allocate a known object type\n");
419 return AST_TEST_FAIL;
423 ast_test_status_update(
test,
"Failed to create object using realtime wizard\n");
424 return AST_TEST_FAIL;
430 ast_test_status_update(
test,
"Failed to allocate second instance of a known object type\n");
431 return AST_TEST_FAIL;
435 ast_test_status_update(
test,
"Failed to create second object using realtime wizard\n");
436 return AST_TEST_FAIL;
440 ast_test_status_update(
test,
"Failed to retrieve a container of all objects\n");
441 return AST_TEST_FAIL;
443 ast_test_status_update(
test,
"Received a container with objects in it when there should be none\n");
444 return AST_TEST_FAIL;
447 return AST_TEST_PASS;
460 info->name =
"object_retrieve_multiple_field";
461 info->category =
"/res/sorcery_realtime/";
462 info->summary =
"sorcery multiple object retrieval unit test";
464 "Test multiple object retrieval in sorcery using fields using realtime wizard";
465 return AST_TEST_NOT_RUN;
471 ast_test_status_update(
test,
"Failed to create fields for multiple retrieve\n");
472 return AST_TEST_FAIL;
475 if (!(sorcery = alloc_and_initialize_sorcery(
"sorcery_realtime_test"))) {
476 ast_test_status_update(
test,
"Failed to open sorcery structure\n");
477 return AST_TEST_FAIL;
481 ast_test_status_update(
test,
"Failed to allocate a known object type\n");
482 return AST_TEST_FAIL;
488 ast_test_status_update(
test,
"Failed to create object using realtime wizard\n");
489 return AST_TEST_FAIL;
493 ast_test_status_update(
test,
"Failed to retrieve a container of all objects\n");
494 return AST_TEST_FAIL;
496 ast_test_status_update(
test,
"Received a container with no objects in it when there should be some\n");
497 return AST_TEST_FAIL;
500 ao2_cleanup(objects);
503 if (!(fields = ast_variable_new(
"joe",
"7",
""))) {
504 ast_test_status_update(
test,
"Failed to create fields for multiple retrieval\n");
505 return AST_TEST_FAIL;
507 ast_test_status_update(
test,
"Failed to retrieve an empty container when retrieving multiple\n");
508 return AST_TEST_FAIL;
510 ast_test_status_update(
test,
"Received a container with objects when there should be none in it\n");
511 return AST_TEST_FAIL;
514 return AST_TEST_PASS;
525 info->name =
"object_retrieve_regex";
526 info->category =
"/res/sorcery_realtime/";
527 info->summary =
"sorcery multiple object retrieval using regex unit test";
529 "Test multiple object retrieval in sorcery using regular expression for matching using realtime wizard";
530 return AST_TEST_NOT_RUN;
535 if (!(sorcery = alloc_and_initialize_sorcery(
"sorcery_realtime_test"))) {
536 ast_test_status_update(
test,
"Failed to open sorcery structure\n");
537 return AST_TEST_FAIL;
541 ast_test_status_update(
test,
"Failed to allocate a known object type\n");
542 return AST_TEST_FAIL;
546 ast_test_status_update(
test,
"Failed to create object using realtime wizard\n");
547 return AST_TEST_FAIL;
553 ast_test_status_update(
test,
"Failed to allocate second instance of a known object type\n");
554 return AST_TEST_FAIL;
558 ast_test_status_update(
test,
"Failed to create second object using astdb wizard\n");
559 return AST_TEST_FAIL;
565 ast_test_status_update(
test,
"Failed to allocate third instance of a known object type\n");
566 return AST_TEST_FAIL;
570 ast_test_status_update(
test,
"Failed to create third object using astdb wizard\n");
571 return AST_TEST_FAIL;
575 ast_test_status_update(
test,
"Failed to retrieve a container of objects\n");
576 return AST_TEST_FAIL;
578 ast_test_status_update(
test,
"Received a container with incorrect number of objects in it: %d instead of 2\n",
ao2_container_count(objects));
579 return AST_TEST_FAIL;
582 return AST_TEST_PASS;
593 info->name =
"object_retrieve_regex_nofetch";
594 info->category =
"/res/sorcery_realtime/";
595 info->summary =
"sorcery multiple object retrieval using regex unit test";
597 "Test multiple object retrieval in sorcery using regular expression for matching using realtime wizard";
598 return AST_TEST_NOT_RUN;
603 if (!(sorcery = alloc_and_initialize_sorcery(
"sorcery_realtime_test,allow_unqualified_fetch=no"))) {
604 ast_test_status_update(
test,
"Failed to open sorcery structure\n");
605 return AST_TEST_FAIL;
609 ast_test_status_update(
test,
"Failed to allocate a known object type\n");
610 return AST_TEST_FAIL;
614 ast_test_status_update(
test,
"Failed to create object using realtime wizard\n");
615 return AST_TEST_FAIL;
621 ast_test_status_update(
test,
"Failed to allocate second instance of a known object type\n");
622 return AST_TEST_FAIL;
626 ast_test_status_update(
test,
"Failed to create second object using astdb wizard\n");
627 return AST_TEST_FAIL;
633 ast_test_status_update(
test,
"Failed to allocate third instance of a known object type\n");
634 return AST_TEST_FAIL;
638 ast_test_status_update(
test,
"Failed to create third object using astdb wizard\n");
639 return AST_TEST_FAIL;
643 ast_test_status_update(
test,
"Failed to retrieve a container of objects\n");
644 return AST_TEST_FAIL;
646 ast_test_status_update(
test,
"Received a container with incorrect number of objects in it: %d instead of 0\n",
ao2_container_count(objects));
647 return AST_TEST_FAIL;
650 return AST_TEST_PASS;
661 info->name =
"object_update";
662 info->category =
"/res/sorcery_realtime/";
663 info->summary =
"sorcery object update unit test";
665 "Test object updating in sorcery using realtime wizard";
666 return AST_TEST_NOT_RUN;
671 if (!(sorcery = alloc_and_initialize_sorcery(
"sorcery_realtime_test"))) {
672 ast_test_status_update(
test,
"Failed to open sorcery structure\n");
673 return AST_TEST_FAIL;
677 ast_test_status_update(
test,
"Failed to allocate a known object type\n");
678 return AST_TEST_FAIL;
682 ast_test_status_update(
test,
"Failed to create object using realtime wizard\n");
683 return AST_TEST_FAIL;
687 ast_test_status_update(
test,
"Failed to allocate a known object type for updating\n");
688 return AST_TEST_FAIL;
697 ast_test_status_update(
test,
"Failed to update sorcery with new object\n");
698 return AST_TEST_FAIL;
702 ast_test_status_update(
test,
"Failed to retrieve properly updated object\n");
703 return AST_TEST_FAIL;
704 }
else if ((obj->bob != obj2->bob) || (obj->joe != obj2->joe)) {
705 ast_test_status_update(
test,
"Object retrieved is not the updated object\n");
706 return AST_TEST_FAIL;
709 return AST_TEST_PASS;
719 info->name =
"object_delete";
720 info->category =
"/res/sorcery_realtime/";
721 info->summary =
"sorcery object deletion unit test";
723 "Test object deletion in sorcery using realtime wizard";
724 return AST_TEST_NOT_RUN;
729 if (!(sorcery = alloc_and_initialize_sorcery(
"sorcery_realtime_test"))) {
730 ast_test_status_update(
test,
"Failed to open sorcery structure\n");
731 return AST_TEST_FAIL;
735 ast_test_status_update(
test,
"Failed to allocate a known object type\n");
736 return AST_TEST_FAIL;
740 ast_test_status_update(
test,
"Failed to create object using realtime wizard\n");
741 return AST_TEST_FAIL;
745 ast_test_status_update(
test,
"Failed to delete object using realtime wizard\n");
746 return AST_TEST_FAIL;
752 ast_test_status_update(
test,
"Retrieved deleted object that should not be there\n");
753 return AST_TEST_FAIL;
756 return AST_TEST_PASS;
766 info->name =
"object_delete_uncreated";
767 info->category =
"/res/sorcery_realtime/";
768 info->summary =
"sorcery object deletion unit test";
770 "Test object deletion of an uncreated object in sorcery using realtime wizard";
771 return AST_TEST_NOT_RUN;
776 if (!(sorcery = alloc_and_initialize_sorcery(
"sorcery_realtime_test"))) {
777 ast_test_status_update(
test,
"Failed to open sorcery structure\n");
778 return AST_TEST_FAIL;
782 ast_test_status_update(
test,
"Failed to allocate a known object type\n");
783 return AST_TEST_FAIL;
787 ast_test_status_update(
test,
"Successfully deleted an object which was never created\n");
788 return AST_TEST_FAIL;
791 return AST_TEST_PASS;
802 info->name =
"object_allocate_on_retrieval";
803 info->category =
"/res/sorcery_realtime/";
804 info->summary =
"sorcery object allocation upon retrieval unit test";
806 "This test creates data in a realtime backend, not through sorcery. Sorcery is then\n"
807 "instructed to retrieve an object with the id of the object that was created in the\n"
808 "realtime backend. Sorcery should be able to allocate the object appropriately";
809 return AST_TEST_NOT_RUN;
814 if (!(sorcery = alloc_and_initialize_sorcery(
"sorcery_realtime_test"))) {
815 ast_test_status_update(
test,
"Failed to open sorcery structure\n");
816 return AST_TEST_FAIL;
820 ast_variable_append(cat, ast_variable_new(
"id",
"blah",
""));
821 ast_variable_append(cat, ast_variable_new(
"bob",
"42",
""));
822 ast_variable_append(cat, ast_variable_new(
"joe",
"93",
""));
826 ast_test_status_update(
test,
"Failed to allocate object 'blah' base on realtime data\n");
827 return AST_TEST_FAIL;
830 if (obj->bob != 42) {
831 ast_test_status_update(
test,
"Object's 'bob' field does not have expected value: %u != 42\n",
833 return AST_TEST_FAIL;
834 }
else if (obj->joe != 93) {
835 ast_test_status_update(
test,
"Object's 'joe' field does not have expected value: %u != 93\n",
837 return AST_TEST_FAIL;
840 return AST_TEST_PASS;
852 info->name =
"object_filter";
853 info->category =
"/res/sorcery_realtime/";
854 info->summary =
"sorcery object field filter unit test";
856 "This test creates data in a realtime backend, not through sorcery. In addition to\n"
857 "the object fields that have been registered with sorcery, there is data in the\n"
858 "realtime backend that is unknown to sorcery. When sorcery attempts to retrieve\n"
859 "the object from the realtime backend, the data unknown to sorcery should be\n"
860 "filtered out of the returned objectset, and the object should be successfully\n"
861 "allocated by sorcery";
862 return AST_TEST_NOT_RUN;
867 if (!(sorcery = alloc_and_initialize_sorcery(
"sorcery_realtime_test"))) {
868 ast_test_status_update(
test,
"Failed to open sorcery structure\n");
869 return AST_TEST_FAIL;
873 ast_variable_append(cat, ast_variable_new(
"id",
"blah",
""));
874 ast_variable_append(cat, ast_variable_new(
"bob",
"42",
""));
875 ast_variable_append(cat, ast_variable_new(
"joe",
"93",
""));
876 ast_variable_append(cat, ast_variable_new(
"fred",
"50",
""));
880 ast_test_status_update(
test,
"Failed to retrieve properly created object using id of 'blah'\n");
881 return AST_TEST_FAIL;
884 if (obj->bob != 42) {
885 ast_test_status_update(
test,
"Object's 'bob' field does not have expected value: %u != 42\n",
887 return AST_TEST_FAIL;
888 }
else if (obj->joe != 93) {
889 ast_test_status_update(
test,
"Object's 'joe' field does not have expected value: %u != 93\n",
891 return AST_TEST_FAIL;
893 return AST_TEST_PASS;
896 static int unload_module(
void)
899 AST_TEST_UNREGISTER(object_create);
900 AST_TEST_UNREGISTER(object_retrieve_id);
901 AST_TEST_UNREGISTER(object_retrieve_field);
902 AST_TEST_UNREGISTER(object_retrieve_multiple_all);
903 AST_TEST_UNREGISTER(object_retrieve_multiple_all_nofetch);
904 AST_TEST_UNREGISTER(object_retrieve_multiple_field);
905 AST_TEST_UNREGISTER(object_retrieve_regex);
906 AST_TEST_UNREGISTER(object_retrieve_regex_nofetch);
907 AST_TEST_UNREGISTER(object_update);
908 AST_TEST_UNREGISTER(object_delete);
909 AST_TEST_UNREGISTER(object_delete_uncreated);
910 AST_TEST_UNREGISTER(object_allocate_on_retrieval);
911 AST_TEST_UNREGISTER(object_filter);
916 static int load_module(
void)
919 ast_realtime_append_mapping(
"sorcery_realtime_test",
"sorcery_realtime_test",
"test",
"test", 1);
920 AST_TEST_REGISTER(object_create);
921 AST_TEST_REGISTER(object_retrieve_id);
922 AST_TEST_REGISTER(object_retrieve_field);
923 AST_TEST_REGISTER(object_retrieve_multiple_all);
924 AST_TEST_REGISTER(object_retrieve_multiple_all_nofetch);
925 AST_TEST_REGISTER(object_retrieve_multiple_field);
926 AST_TEST_REGISTER(object_retrieve_regex);
927 AST_TEST_REGISTER(object_retrieve_regex_nofetch);
928 AST_TEST_REGISTER(object_update);
929 AST_TEST_REGISTER(object_delete);
930 AST_TEST_REGISTER(object_delete_uncreated);
931 AST_TEST_REGISTER(object_allocate_on_retrieval);
932 AST_TEST_REGISTER(object_filter);
937 AST_MODULE_INFO_STANDARD(
ASTERISK_GPL_KEY,
"Sorcery Realtime Wizard test module");
struct ast_category * ast_category_new(const char *name, const char *in_file, int lineno)
Create a category.
#define ast_sorcery_object_field_register_nodoc(sorcery, type, name, default_val, opt_type, flags,...)
Register a field within an object without documentation.
Asterisk main include file. File version handling, generic pbx functions.
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
void ast_variables_destroy(struct ast_variable *var)
Free variable list.
Structure for variables, used for configurations and for channel variables.
struct ast_category * ast_category_delete(struct ast_config *cfg, struct ast_category *cat)
Delete a category.
Perform no matching, return all objects.
int ast_category_exist(const struct ast_config *config, const char *category_name, const char *filter)
Check for category duplicates.
Full structure for sorcery.
int ast_config_engine_deregister(struct ast_config_engine *del)
Deregister config engine.
int ast_config_engine_register(struct ast_config_engine *newconfig)
Register config engine.
Return all matching objects.
char * ast_category_browse(struct ast_config *config, const char *prev_name)
Browse categories.
struct ao2_container * ast_sorcery_retrieve_by_regex(const struct ast_sorcery *sorcery, const char *type, const char *regex)
Retrieve multiple objects using a regular expression on their id.
Configuration engine structure, used to define realtime drivers.
void * ast_sorcery_retrieve_by_id(const struct ast_sorcery *sorcery, const char *type, const char *id)
Retrieve an object using its unique identifier.
#define ast_sorcery_unref(sorcery)
Decrease the reference count of a sorcery structure.
void ast_category_append(struct ast_config *config, struct ast_category *category)
Appends a category to a config.
struct ast_variable * ast_category_root(struct ast_config *config, char *cat)
returns the root ast_variable of a config
int ast_sorcery_create(const struct ast_sorcery *sorcery, void *object)
Create and potentially persist an object using an available wizard.
#define FLDSET(type,...)
Convert a struct and list of fields to an argument list of field offsets.
Type for default option handler for unsigned integers.
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
struct ast_config * ast_config_new(void)
Create a new base configuration structure.
int ast_sorcery_delete(const struct ast_sorcery *sorcery, void *object)
Delete an object.
#define ast_sorcery_internal_object_register(sorcery, type, alloc, transform, apply)
Register an internal, hidden object type.
static void * test_sorcery_object_alloc(const char *id)
Internal function to allocate a test object.
void * ast_sorcery_alloc(const struct ast_sorcery *sorcery, const char *type, const char *id)
Allocate an object.
Support for logging to various files, console and syslog Configuration in file logger.conf.
void * ast_sorcery_retrieve_by_fields(const struct ast_sorcery *sorcery, const char *type, unsigned int flags, struct ast_variable *fields)
Retrieve an object or multiple objects using specific fields.
static struct ast_config * realtime_objects
Configuration structure which contains all stored objects.
int ast_variable_lists_match(const struct ast_variable *left, const struct ast_variable *right, int exact_match)
Tests 2 variable lists to see if they match.
void * ast_sorcery_copy(const struct ast_sorcery *sorcery, const void *object)
Create a copy of an object.
const struct ast_variable * ast_variable_find_variable_in_list(const struct ast_variable *list, const char *variable_name)
Gets a variable from a variable list by name.
#define ast_sorcery_open()
Open a new sorcery structure.
#define AST_TEST_DEFINE(hdr)
struct ast_category * ast_category_get(const struct ast_config *config, const char *category_name, const char *filter)
Retrieve a category if it exists.
void * ast_sorcery_generic_alloc(size_t size, ao2_destructor_fn destructor)
Allocate a generic sorcery capable object.
void ast_config_destroy(struct ast_config *cfg)
Destroys a config.
#define ASTERISK_GPL_KEY
The text the key() function should return.
Asterisk module definitions.
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Persistent data storage (akin to *doze registry)
struct ast_variable * ast_variables_dup(struct ast_variable *var)
Duplicate variable list.
Sorcery Data Access Layer API.
int ast_sorcery_update(const struct ast_sorcery *sorcery, void *object)
Update an object.