Add missing ast_sorcery_generic_alloc conversions.
[asterisk/asterisk.git] / tests / test_sorcery_astdb.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2013, Digium, Inc.
5  *
6  * Joshua Colp <jcolp@digium.com>
7  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  */
18
19 /*!
20  * \file
21  * \brief Sorcery Unit Tests
22  *
23  * \author Joshua Colp <jcolp@digium.com>
24  *
25  */
26
27 /*** MODULEINFO
28         <depend>TEST_FRAMEWORK</depend>
29         <support_level>core</support_level>
30  ***/
31
32 #include "asterisk.h"
33
34 ASTERISK_FILE_VERSION(__FILE__, "")
35
36 #include "asterisk/test.h"
37 #include "asterisk/module.h"
38 #include "asterisk/sorcery.h"
39 #include "asterisk/astdb.h"
40 #include "asterisk/logger.h"
41
42 /*! \brief Dummy sorcery object */
43 struct test_sorcery_object {
44         SORCERY_OBJECT(details);
45         unsigned int bob;
46         unsigned int joe;
47 };
48
49 /*! \brief Internal function to allocate a test object */
50 static void *test_sorcery_object_alloc(const char *id)
51 {
52         return ast_sorcery_generic_alloc(sizeof(struct test_sorcery_object), NULL);
53 }
54
55 static struct ast_sorcery *alloc_and_initialize_sorcery(void)
56 {
57         struct ast_sorcery *sorcery;
58
59         if (!(sorcery = ast_sorcery_open())) {
60                 return NULL;
61         }
62
63         if (ast_sorcery_apply_default(sorcery, "test", "astdb", "test") ||
64                 ast_sorcery_object_register(sorcery, "test", test_sorcery_object_alloc, NULL, NULL)) {
65                 ast_sorcery_unref(sorcery);
66                 return NULL;
67         }
68
69         ast_sorcery_object_field_register(sorcery, "test", "bob", "5", OPT_UINT_T, 0, FLDSET(struct test_sorcery_object, bob));
70         ast_sorcery_object_field_register(sorcery, "test", "joe", "10", OPT_UINT_T, 0, FLDSET(struct test_sorcery_object, joe));
71
72         return sorcery;
73 }
74
75 static void deinitialize_sorcery(struct ast_sorcery *sorcery)
76 {
77         ast_db_deltree("test/test", NULL);
78         ast_sorcery_unref(sorcery);
79 }
80
81 AST_TEST_DEFINE(object_create)
82 {
83         RAII_VAR(struct ast_sorcery *, sorcery, NULL, deinitialize_sorcery);
84         RAII_VAR(struct test_sorcery_object *, obj, NULL, ao2_cleanup);
85         char value[2];
86
87         switch (cmd) {
88         case TEST_INIT:
89                 info->name = "object_create";
90                 info->category = "/res/sorcery_astdb/";
91                 info->summary = "sorcery astdb object creation unit test";
92                 info->description =
93                         "Test object creation in sorcery using astdb wizard";
94                 return AST_TEST_NOT_RUN;
95         case TEST_EXECUTE:
96                 break;
97         }
98
99         if (!(sorcery = alloc_and_initialize_sorcery())) {
100                 ast_test_status_update(test, "Failed to open sorcery structure\n");
101                 return AST_TEST_FAIL;
102         }
103
104         if (!(obj = ast_sorcery_alloc(sorcery, "test", "blah"))) {
105                 ast_test_status_update(test, "Failed to allocate a known object type\n");
106                 return AST_TEST_FAIL;
107         }
108
109         if (ast_sorcery_create(sorcery, obj)) {
110                 ast_test_status_update(test, "Failed to create object using astdb wizard\n");
111                 return AST_TEST_FAIL;
112         } else if (ast_db_get("test/test", "blah", value, sizeof(value))) {
113                 ast_test_status_update(test, "Object was apparently created but does not actually exist in astdb\n");
114                 return AST_TEST_FAIL;
115         }
116
117         return AST_TEST_PASS;
118 }
119
120 AST_TEST_DEFINE(object_retrieve_id)
121 {
122         RAII_VAR(struct ast_sorcery *, sorcery, NULL, deinitialize_sorcery);
123         RAII_VAR(struct test_sorcery_object *, obj, NULL, ao2_cleanup);
124
125         switch (cmd) {
126         case TEST_INIT:
127                 info->name = "object_retrieve_id";
128                 info->category = "/res/sorcery_astdb/";
129                 info->summary = "sorcery object retrieval using id unit test";
130                 info->description =
131                         "Test object retrieval using id in sorcery with astdb wizard";
132                 return AST_TEST_NOT_RUN;
133         case TEST_EXECUTE:
134                 break;
135         }
136
137         if (!(sorcery = alloc_and_initialize_sorcery())) {
138                 ast_test_status_update(test, "Failed to open sorcery structure\n");
139                 return AST_TEST_FAIL;
140         }
141
142         if (!(obj = ast_sorcery_alloc(sorcery, "test", "blah"))) {
143                 ast_test_status_update(test, "Failed to allocate a known object type\n");
144                 return AST_TEST_FAIL;
145         }
146
147         if (ast_sorcery_create(sorcery, obj)) {
148                 ast_test_status_update(test, "Failed to create object using astdb wizard\n");
149                 return AST_TEST_FAIL;
150         }
151
152         ao2_cleanup(obj);
153
154         if (!(obj = ast_sorcery_alloc(sorcery, "test", "blah2"))) {
155                 ast_test_status_update(test, "Failed to allocate second instance of a known object type\n");
156                 return AST_TEST_FAIL;
157         }
158
159         if (ast_sorcery_create(sorcery, obj)) {
160                 ast_test_status_update(test, "Failed to create second object using astdb wizard\n");
161                 return AST_TEST_FAIL;
162         }
163
164         ao2_cleanup(obj);
165
166         if (!(obj = ast_sorcery_retrieve_by_id(sorcery, "test", "blah"))) {
167                 ast_test_status_update(test, "Failed to retrieve properly created object using id of 'blah'\n");
168                 return AST_TEST_FAIL;
169         } else if (strcmp(ast_sorcery_object_get_id(obj), "blah")) {
170                 ast_test_status_update(test, "Retrieved object does not have correct id\n");
171                 return AST_TEST_FAIL;
172         }
173
174         return AST_TEST_PASS;
175 }
176
177 AST_TEST_DEFINE(object_retrieve_field)
178 {
179         RAII_VAR(struct ast_sorcery *, sorcery, NULL, deinitialize_sorcery);
180         RAII_VAR(struct test_sorcery_object *, obj, NULL, ao2_cleanup);
181         RAII_VAR(struct ast_variable *, fields, ast_variable_new("joe", "42", ""), ast_variables_destroy);
182
183         switch (cmd) {
184         case TEST_INIT:
185                 info->name = "object_retrieve_field";
186                 info->category = "/res/sorcery_astdb/";
187                 info->summary = "sorcery object retrieval using a specific field unit test";
188                 info->description =
189                         "Test object retrieval using a specific field in sorcery with astdb wizard";
190                 return AST_TEST_NOT_RUN;
191         case TEST_EXECUTE:
192                 break;
193         }
194
195         if (!fields) {
196                 ast_test_status_update(test, "Failed to create fields for object retrieval attempt\n");
197                 return AST_TEST_FAIL;
198         }
199
200         if (!(sorcery = alloc_and_initialize_sorcery())) {
201                 ast_test_status_update(test, "Failed to open sorcery structure\n");
202                 return AST_TEST_FAIL;
203         }
204
205         if (!(obj = ast_sorcery_alloc(sorcery, "test", "blah"))) {
206                 ast_test_status_update(test, "Failed to allocate a known object type\n");
207                 return AST_TEST_FAIL;
208         }
209
210         obj->joe = 42;
211
212         if (ast_sorcery_create(sorcery, obj)) {
213                 ast_test_status_update(test, "Failed to create object using astdb wizard\n");
214                 return AST_TEST_FAIL;
215         }
216
217         ao2_cleanup(obj);
218
219         if (!(obj = ast_sorcery_retrieve_by_fields(sorcery, "test", AST_RETRIEVE_FLAG_DEFAULT, fields))) {
220                 ast_test_status_update(test, "Failed to retrieve properly created object using 'joe' field\n");
221                 return AST_TEST_FAIL;
222         }
223
224         ao2_cleanup(obj);
225         ast_variables_destroy(fields);
226
227         if (!(fields = ast_variable_new("joe", "49", ""))) {
228                 ast_test_status_update(test, "Failed to create fields for object retrieval attempt\n");
229                 return AST_TEST_FAIL;
230         }
231
232         if ((obj = ast_sorcery_retrieve_by_fields(sorcery, "test", AST_RETRIEVE_FLAG_DEFAULT, fields))) {
233                 ast_test_status_update(test, "Retrieved an object using a field with an in-correct value... that should not happen\n");
234                 return AST_TEST_FAIL;
235         }
236
237         return AST_TEST_PASS;
238 }
239
240 AST_TEST_DEFINE(object_retrieve_multiple_all)
241 {
242         RAII_VAR(struct ast_sorcery *, sorcery, NULL, deinitialize_sorcery);
243         RAII_VAR(struct test_sorcery_object *, obj, NULL, ao2_cleanup);
244         RAII_VAR(struct ao2_container *, objects, NULL, ao2_cleanup);
245
246         switch (cmd) {
247         case TEST_INIT:
248                 info->name = "object_retrieve_multiple_all";
249                 info->category = "/res/sorcery_astdb/";
250                 info->summary = "sorcery multiple object retrieval unit test";
251                 info->description =
252                         "Test multiple object retrieval in sorcery using astdb wizard";
253                 return AST_TEST_NOT_RUN;
254         case TEST_EXECUTE:
255                 break;
256         }
257
258         if (!(sorcery = alloc_and_initialize_sorcery())) {
259                 ast_test_status_update(test, "Failed to open sorcery structure\n");
260                 return AST_TEST_FAIL;
261         }
262
263         if (!(obj = ast_sorcery_alloc(sorcery, "test", "blah"))) {
264                 ast_test_status_update(test, "Failed to allocate a known object type\n");
265                 return AST_TEST_FAIL;
266         }
267
268         if (ast_sorcery_create(sorcery, obj)) {
269                 ast_test_status_update(test, "Failed to create object using astdb wizard\n");
270                 return AST_TEST_FAIL;
271         }
272
273         ao2_cleanup(obj);
274
275         if (!(obj = ast_sorcery_alloc(sorcery, "test", "blah2"))) {
276                 ast_test_status_update(test, "Failed to allocate second instance of a known object type\n");
277                 return AST_TEST_FAIL;
278         }
279
280         if (ast_sorcery_create(sorcery, obj)) {
281                 ast_test_status_update(test, "Failed to create second object using astdb wizard\n");
282                 return AST_TEST_FAIL;
283         }
284
285         if (!(objects = ast_sorcery_retrieve_by_fields(sorcery, "test", AST_RETRIEVE_FLAG_MULTIPLE | AST_RETRIEVE_FLAG_ALL, NULL))) {
286                 ast_test_status_update(test, "Failed to retrieve a container of all objects\n");
287                 return AST_TEST_FAIL;
288         } else if (ao2_container_count(objects) != 2) {
289                 ast_test_status_update(test, "Received a container with no objects in it when there should be some\n");
290                 return AST_TEST_FAIL;
291         }
292
293         return AST_TEST_PASS;
294 }
295
296 AST_TEST_DEFINE(object_retrieve_multiple_field)
297 {
298         RAII_VAR(struct ast_sorcery *, sorcery, NULL, deinitialize_sorcery);
299         RAII_VAR(struct test_sorcery_object *, obj, NULL, ao2_cleanup);
300         RAII_VAR(struct ao2_container *, objects, NULL, ao2_cleanup);
301         RAII_VAR(struct ast_variable *, fields, ast_variable_new("joe", "6", ""), ast_variables_destroy);
302
303         switch (cmd) {
304         case TEST_INIT:
305                 info->name = "object_retrieve_multiple_field";
306                 info->category = "/res/sorcery_astdb/";
307                 info->summary = "sorcery multiple object retrieval unit test";
308                 info->description =
309                         "Test multiple object retrieval in sorcery using fields using astdb wizard";
310                 return AST_TEST_NOT_RUN;
311         case TEST_EXECUTE:
312                 break;
313         }
314
315         if (!fields) {
316                 ast_test_status_update(test, "Failed to create fields for multiple retrieve\n");
317                 return AST_TEST_FAIL;
318         }
319
320         if (!(sorcery = alloc_and_initialize_sorcery())) {
321                 ast_test_status_update(test, "Failed to open sorcery structure\n");
322                 return AST_TEST_FAIL;
323         }
324
325         if (!(obj = ast_sorcery_alloc(sorcery, "test", "blah"))) {
326                 ast_test_status_update(test, "Failed to allocate a known object type\n");
327                 return AST_TEST_FAIL;
328         }
329
330         obj->joe = 6;
331
332         if (ast_sorcery_create(sorcery, obj)) {
333                 ast_test_status_update(test, "Failed to create object using astdb wizard\n");
334                 return AST_TEST_FAIL;
335         }
336
337         if (!(objects = ast_sorcery_retrieve_by_fields(sorcery, "test", AST_RETRIEVE_FLAG_MULTIPLE, fields))) {
338                 ast_test_status_update(test, "Failed to retrieve a container of all objects\n");
339                 return AST_TEST_FAIL;
340         } else if (ao2_container_count(objects) != 1) {
341                 ast_test_status_update(test, "Received a container with no objects in it when there should be some\n");
342                 return AST_TEST_FAIL;
343         }
344
345         ao2_cleanup(objects);
346         ast_variables_destroy(fields);
347
348         if (!(fields = ast_variable_new("joe", "7", ""))) {
349                 ast_test_status_update(test, "Failed to create fields for multiple retrieval\n");
350                 return AST_TEST_FAIL;
351         } else if (!(objects = ast_sorcery_retrieve_by_fields(sorcery, "test", AST_RETRIEVE_FLAG_MULTIPLE, fields))) {
352                 ast_test_status_update(test, "Failed to retrieve an empty container when retrieving multiple\n");
353                 return AST_TEST_FAIL;
354         } else if (ao2_container_count(objects)) {
355                 ast_test_status_update(test, "Received a container with objects when there should be none in it\n");
356                 return AST_TEST_FAIL;
357         }
358
359         return AST_TEST_PASS;
360 }
361
362 AST_TEST_DEFINE(object_retrieve_regex)
363 {
364         RAII_VAR(struct ast_sorcery *, sorcery, NULL, deinitialize_sorcery);
365         RAII_VAR(struct test_sorcery_object *, obj, NULL, ao2_cleanup);
366         RAII_VAR(struct ao2_container *, objects, NULL, ao2_cleanup);
367
368         switch (cmd) {
369         case TEST_INIT:
370                 info->name = "object_retrieve_regex";
371                 info->category = "/res/sorcery_astdb/";
372                 info->summary = "sorcery multiple object retrieval using regex unit test";
373                 info->description =
374                         "Test multiple object retrieval in sorcery using regular expression for matching using astdb wizard";
375                 return AST_TEST_NOT_RUN;
376         case TEST_EXECUTE:
377                 break;
378         }
379
380         if (!(sorcery = alloc_and_initialize_sorcery())) {
381                 ast_test_status_update(test, "Failed to open sorcery structure\n");
382                 return AST_TEST_FAIL;
383         }
384
385         if (!(obj = ast_sorcery_alloc(sorcery, "test", "blah-98joe"))) {
386                 ast_test_status_update(test, "Failed to allocate a known object type\n");
387                 return AST_TEST_FAIL;
388         }
389
390         if (ast_sorcery_create(sorcery, obj)) {
391                 ast_test_status_update(test, "Failed to create object using astdb wizard\n");
392                 return AST_TEST_FAIL;
393         }
394
395         ao2_cleanup(obj);
396
397         if (!(obj = ast_sorcery_alloc(sorcery, "test", "blah-93joe"))) {
398                 ast_test_status_update(test, "Failed to allocate second instance of a known object type\n");
399                 return AST_TEST_FAIL;
400         }
401
402         if (ast_sorcery_create(sorcery, obj)) {
403                 ast_test_status_update(test, "Failed to create second object using astdb wizard\n");
404                 return AST_TEST_FAIL;
405         }
406
407         ao2_cleanup(obj);
408
409         if (!(obj = ast_sorcery_alloc(sorcery, "test", "neener-93joe"))) {
410                 ast_test_status_update(test, "Failed to allocate third instance of a known object type\n");
411                 return AST_TEST_FAIL;
412         }
413
414         if (ast_sorcery_create(sorcery, obj)) {
415                 ast_test_status_update(test, "Failed to create third object using astdb wizard\n");
416                 return AST_TEST_FAIL;
417         }
418
419         if (!(objects = ast_sorcery_retrieve_by_regex(sorcery, "test", "^blah-"))) {
420                 ast_test_status_update(test, "Failed to retrieve a container of objects\n");
421                 return AST_TEST_FAIL;
422         } else if (ao2_container_count(objects) != 2) {
423                 ast_test_status_update(test, "Received a container with incorrect number of objects in it\n");
424                 return AST_TEST_FAIL;
425         }
426
427         return AST_TEST_PASS;
428 }
429
430 AST_TEST_DEFINE(object_update)
431 {
432         RAII_VAR(struct ast_sorcery *, sorcery, NULL, deinitialize_sorcery);
433         RAII_VAR(struct test_sorcery_object *, obj, NULL, ao2_cleanup);
434         RAII_VAR(struct test_sorcery_object *, obj2, NULL, ao2_cleanup);
435
436         switch (cmd) {
437         case TEST_INIT:
438                 info->name = "object_update";
439                 info->category = "/res/sorcery_astdb/";
440                 info->summary = "sorcery object update unit test";
441                 info->description =
442                         "Test object updating in sorcery using astdb wizard";
443                 return AST_TEST_NOT_RUN;
444         case TEST_EXECUTE:
445                 break;
446         }
447
448         if (!(sorcery = alloc_and_initialize_sorcery())) {
449                 ast_test_status_update(test, "Failed to open sorcery structure\n");
450                 return AST_TEST_FAIL;
451         }
452
453         if (!(obj = ast_sorcery_alloc(sorcery, "test", "blah"))) {
454                 ast_test_status_update(test, "Failed to allocate a known object type\n");
455                 return AST_TEST_FAIL;
456         }
457
458         if (ast_sorcery_create(sorcery, obj)) {
459                 ast_test_status_update(test, "Failed to create object using astdb wizard\n");
460                 return AST_TEST_FAIL;
461         }
462
463         if (!(obj2 = ast_sorcery_copy(sorcery, obj))) {
464                 ast_test_status_update(test, "Failed to allocate a known object type for updating\n");
465                 return AST_TEST_FAIL;
466         }
467
468         ao2_cleanup(obj);
469
470         obj2->bob = 1000;
471         obj2->joe = 2000;
472
473         if (ast_sorcery_update(sorcery, obj2)) {
474                 ast_test_status_update(test, "Failed to update sorcery with new object\n");
475                 return AST_TEST_FAIL;
476         }
477
478         if (!(obj = ast_sorcery_retrieve_by_id(sorcery, "test", "blah"))) {
479                 ast_test_status_update(test, "Failed to retrieve properly updated object\n");
480                 return AST_TEST_FAIL;
481         } else if ((obj->bob != obj2->bob) || (obj->joe != obj2->joe)) {
482                 ast_test_status_update(test, "Object retrieved is not the updated object\n");
483                 return AST_TEST_FAIL;
484         }
485
486         return AST_TEST_PASS;
487 }
488
489 AST_TEST_DEFINE(object_update_uncreated)
490 {
491         RAII_VAR(struct ast_sorcery *, sorcery, NULL, deinitialize_sorcery);
492         RAII_VAR(struct test_sorcery_object *, obj, NULL, ao2_cleanup);
493
494         switch (cmd) {
495         case TEST_INIT:
496                 info->name = "object_update_uncreated";
497                 info->category = "/res/sorcery_astdb/";
498                 info->summary = "sorcery object update unit test";
499                 info->description =
500                         "Test updating of an uncreated object in sorcery using astdb wizard";
501                 return AST_TEST_NOT_RUN;
502         case TEST_EXECUTE:
503                 break;
504         }
505
506         if (!(sorcery = alloc_and_initialize_sorcery())) {
507                 ast_test_status_update(test, "Failed to open sorcery structure\n");
508                 return AST_TEST_FAIL;
509         }
510
511         if (!(obj = ast_sorcery_alloc(sorcery, "test", "blah"))) {
512                 ast_test_status_update(test, "Failed to allocate a known object type\n");
513                 return AST_TEST_FAIL;
514         }
515
516         if (!ast_sorcery_update(sorcery, obj)) {
517                 ast_test_status_update(test, "Successfully updated an object which has not been created yet\n");
518                 return AST_TEST_FAIL;
519         }
520
521         return AST_TEST_PASS;
522 }
523
524 AST_TEST_DEFINE(object_delete)
525 {
526         RAII_VAR(struct ast_sorcery *, sorcery, NULL, deinitialize_sorcery);
527         RAII_VAR(struct test_sorcery_object *, obj, NULL, ao2_cleanup);
528
529         switch (cmd) {
530         case TEST_INIT:
531                 info->name = "object_delete";
532                 info->category = "/res/sorcery_astdb/";
533                 info->summary = "sorcery object deletion unit test";
534                 info->description =
535                         "Test object deletion in sorcery using astdb wizard";
536                 return AST_TEST_NOT_RUN;
537         case TEST_EXECUTE:
538                 break;
539         }
540
541         if (!(sorcery = alloc_and_initialize_sorcery())) {
542                 ast_test_status_update(test, "Failed to open sorcery structure\n");
543                 return AST_TEST_FAIL;
544         }
545
546         if (!(obj = ast_sorcery_alloc(sorcery, "test", "blah"))) {
547                 ast_test_status_update(test, "Failed to allocate a known object type\n");
548                 return AST_TEST_FAIL;
549         }
550
551         if (ast_sorcery_create(sorcery, obj)) {
552                 ast_test_status_update(test, "Failed to create object using astdb wizard\n");
553                 return AST_TEST_FAIL;
554         }
555
556         if (ast_sorcery_delete(sorcery, obj)) {
557                 ast_test_status_update(test, "Failed to delete object using astdb wizard\n");
558                 return AST_TEST_FAIL;
559         }
560
561         ao2_cleanup(obj);
562
563         if ((obj = ast_sorcery_retrieve_by_id(sorcery, "test", "blah"))) {
564                 ast_test_status_update(test, "Retrieved deleted object that should not be there\n");
565                 return AST_TEST_FAIL;
566         }
567
568         return AST_TEST_PASS;
569 }
570
571 AST_TEST_DEFINE(object_delete_uncreated)
572 {
573         RAII_VAR(struct ast_sorcery *, sorcery, NULL, deinitialize_sorcery);
574         RAII_VAR(struct test_sorcery_object *, obj, NULL, ao2_cleanup);
575
576         switch (cmd) {
577         case TEST_INIT:
578                 info->name = "object_delete_uncreated";
579                 info->category = "/res/sorcery_astdb/";
580                 info->summary = "sorcery object deletion unit test";
581                 info->description =
582                         "Test object deletion of an uncreated object in sorcery using astdb wizard";
583                 return AST_TEST_NOT_RUN;
584         case TEST_EXECUTE:
585                 break;
586         }
587
588         if (!(sorcery = alloc_and_initialize_sorcery())) {
589                 ast_test_status_update(test, "Failed to open sorcery structure\n");
590                 return AST_TEST_FAIL;
591         }
592
593         if (!(obj = ast_sorcery_alloc(sorcery, "test", "blah"))) {
594                 ast_test_status_update(test, "Failed to allocate a known object type\n");
595                 return AST_TEST_FAIL;
596         }
597
598         if (!ast_sorcery_delete(sorcery, obj)) {
599                 ast_test_status_update(test, "Successfully deleted an object which was never created\n");
600                 return AST_TEST_FAIL;
601         }
602
603         return AST_TEST_PASS;
604 }
605
606 static int unload_module(void)
607 {
608         AST_TEST_UNREGISTER(object_create);
609         AST_TEST_UNREGISTER(object_retrieve_id);
610         AST_TEST_UNREGISTER(object_retrieve_field);
611         AST_TEST_UNREGISTER(object_retrieve_multiple_all);
612         AST_TEST_UNREGISTER(object_retrieve_multiple_field);
613         AST_TEST_UNREGISTER(object_retrieve_regex);
614         AST_TEST_UNREGISTER(object_update);
615         AST_TEST_UNREGISTER(object_update_uncreated);
616         AST_TEST_UNREGISTER(object_delete);
617         AST_TEST_UNREGISTER(object_delete_uncreated);
618
619         return 0;
620 }
621
622 static int load_module(void)
623 {
624         AST_TEST_REGISTER(object_create);
625         AST_TEST_REGISTER(object_retrieve_id);
626         AST_TEST_REGISTER(object_retrieve_field);
627         AST_TEST_REGISTER(object_retrieve_multiple_all);
628         AST_TEST_REGISTER(object_retrieve_multiple_field);
629         AST_TEST_REGISTER(object_retrieve_regex);
630         AST_TEST_REGISTER(object_update);
631         AST_TEST_REGISTER(object_update_uncreated);
632         AST_TEST_REGISTER(object_delete);
633         AST_TEST_REGISTER(object_delete_uncreated);
634
635         return AST_MODULE_LOAD_SUCCESS;
636 }
637
638 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Sorcery astdb Wizard test module");