Merged revisions 321871 via svnmerge from
[asterisk/asterisk.git] / tests / test_event.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2010, Digium, Inc.
5  *
6  * Russell Bryant <russell@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 Tests for the ast_event API
22  *
23  * \author Russell Bryant <russell@digium.com>
24  *
25  * \ingroup tests
26  *
27  * \todo API Calls not yet touched by a test: XXX TODO
28  *   - ast_event_queue_and_cache()
29  *   - ast_event_get_cached()
30  *   - ast_event_report_subs()
31  *   - ast_event_dump_cache()
32  *   - ast_event_get_ie_type_name()
33  *   - ast_event_get_ie_pltype()
34  *   - ast_event_str_to_event_type()
35  *   - ast_event_str_to_ie_type()
36  *   - ast_event_iterator_init()
37  *   - ast_event_iterator_next()
38  *   - ast_event_iterator_get_ie_type()
39  *   - ast_event_iterator_get_ie_uint()
40  *   - ast_event_iterator_get_ie_bitflags()
41  *   - ast_event_iterator_get_ie_str()
42  *   - ast_event_iterator_get_ie_raw()
43  */
44
45 /*** MODULEINFO
46         <depend>TEST_FRAMEWORK</depend>
47  ***/
48
49 #include "asterisk.h"
50
51 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
52
53 #include "asterisk/module.h"
54 #include "asterisk/utils.h"
55 #include "asterisk/test.h"
56 #include "asterisk/event.h"
57
58 static int check_event(struct ast_event *event, struct ast_test *test,
59                 enum ast_event_type expected_type, const char *type_name,
60                 const char *str, uint32_t uint, uint32_t bitflags)
61 {
62         enum ast_event_type type;
63         const void *foo;
64
65         /* Check #1: Ensure event type is set properly. */
66         type = ast_event_get_type(event);
67         if (ast_event_get_type(event) != type) {
68                 ast_test_status_update(test, "Expected event type: '%d', got '%d'\n",
69                                 expected_type, type);
70                 return -1;
71         }
72
73         /* Check #2: Check string representation of event type */
74         if (strcmp(type_name, ast_event_get_type_name(event))) {
75                 ast_test_status_update(test, "Didn't get expected type name: '%s' != '%s'\n",
76                                 type_name, ast_event_get_type_name(event));
77                 return -1;
78         }
79
80         /* Check #3: Check for automatically included EID */
81         if (memcmp(&ast_eid_default, ast_event_get_ie_raw(event, AST_EVENT_IE_EID), sizeof(ast_eid_default))) {
82                 ast_test_status_update(test, "Failed to get EID\n");
83                 return -1;
84         }
85
86         /* Check #4: Check for the string IE */
87         if (strcmp(str, ast_event_get_ie_str(event, AST_EVENT_IE_MAILBOX))) {
88                 ast_test_status_update(test, "Failed to get string IE.\n");
89                 return -1;
90         }
91
92         /* Check #5: Check for the uint IE */
93         if (uint != ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS)) {
94                 ast_test_status_update(test, "Failed to get uint IE.\n");
95                 return -1;
96         }
97
98         /* Check #6: Check for the bitflags IE */
99         if (bitflags != ast_event_get_ie_bitflags(event, AST_EVENT_IE_OLDMSGS)) {
100                 ast_test_status_update(test, "Failed to get bitflags IE.\n");
101                 return -1;
102         }
103
104         /* Check #7: Check if a check for a str IE that isn't there works */
105         if ((foo = ast_event_get_ie_str(event, AST_EVENT_IE_DEVICE))) {
106                 ast_test_status_update(test, "DEVICE IE check returned non-NULL %p\n", foo);
107                 return -1;
108         }
109
110         /* Check #8: Check if a check for a uint IE that isn't there returns 0 */
111         if (ast_event_get_ie_uint(event, AST_EVENT_IE_STATE)) {
112                 ast_test_status_update(test, "OLDMSGS IE should be 0\n");
113                 return -1;
114         }
115
116         ast_test_status_update(test, "Event looks good.\n");
117
118         return 0;
119 }
120
121 /*!
122  * \internal
123  */
124 AST_TEST_DEFINE(event_new_test)
125 {
126         enum ast_test_result_state res = AST_TEST_PASS;
127         struct ast_event *event = NULL, *event2 = NULL;
128
129         static const enum ast_event_type type = AST_EVENT_CUSTOM;
130         static const char str[] = "SIP/alligatormittens";
131         static const uint32_t uint = 0xb00bface;
132         static const uint32_t bitflags = 0x12488421;
133
134         switch (cmd) {
135         case TEST_INIT:
136                 info->name = "ast_event_new_test";
137                 info->category = "/main/event/";
138                 info->summary = "Test event creation";
139                 info->description =
140                         "This test exercises the API calls that allow allocation "
141                         "of an ast_event.";
142                 return AST_TEST_NOT_RUN;
143         case TEST_EXECUTE:
144                 break;
145         }
146
147         /*
148          * Test 2 methods of event creation:
149          *
150          * 1) Dynamic via appending each IE individually.
151          * 2) Statically, with all IEs in ast_event_new().
152          */
153
154         ast_test_status_update(test, "First, test dynamic event creation...\n");
155
156         if (!(event = ast_event_new(type, AST_EVENT_IE_END))) {
157                 ast_test_status_update(test, "Failed to allocate ast_event object.\n");
158                 res = AST_TEST_FAIL;
159                 goto return_cleanup;
160         }
161
162         if (ast_event_append_ie_str(&event, AST_EVENT_IE_MAILBOX, str)) {
163                 ast_test_status_update(test, "Failed to append str IE\n");
164                 res = AST_TEST_FAIL;
165                 goto return_cleanup;
166         }
167
168         if (ast_event_append_ie_uint(&event, AST_EVENT_IE_NEWMSGS, uint)) {
169                 ast_test_status_update(test, "Failed to append uint IE\n");
170                 res = AST_TEST_FAIL;
171                 goto return_cleanup;
172         }
173
174         if (ast_event_append_ie_bitflags(&event, AST_EVENT_IE_OLDMSGS, bitflags)) {
175                 ast_test_status_update(test, "Failed to append bitflags IE\n");
176                 res = AST_TEST_FAIL;
177                 goto return_cleanup;
178         }
179
180         if (ast_event_append_eid(&event)) {
181                 ast_test_status_update(test, "Failed to append EID\n");
182                 res = AST_TEST_FAIL;
183                 goto return_cleanup;
184         }
185
186         if (check_event(event, test, type, "Custom", str, uint, bitflags)) {
187                 ast_test_status_update(test, "Dynamically generated event broken\n");
188                 res = AST_TEST_FAIL;
189                 goto return_cleanup;
190         }
191
192         event2 = ast_event_new(type,
193                         AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, str,
194                         AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, uint,
195                         AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_BITFLAGS, bitflags,
196                         AST_EVENT_IE_END);
197
198         if (!event2) {
199                 ast_test_status_update(test, "Failed to allocate ast_event object.\n");
200                 res = AST_TEST_FAIL;
201                 goto return_cleanup;
202         }
203
204         if (check_event(event2, test, type, "Custom", str, uint, bitflags)) {
205                 ast_test_status_update(test, "Statically generated event broken\n");
206                 res = AST_TEST_FAIL;
207                 goto return_cleanup;
208         }
209
210         if (ast_event_get_size(event) != ast_event_get_size(event2)) {
211                 ast_test_status_update(test, "Events expected to be identical have different size: %d != %d\n",
212                                 (int) ast_event_get_size(event),
213                                 (int) ast_event_get_size(event2));
214                 res = AST_TEST_FAIL;
215                 goto return_cleanup;
216         }
217
218 return_cleanup:
219         if (event) {
220                 ast_event_destroy(event);
221                 event = NULL;
222         }
223
224         if (event2) {
225                 ast_event_destroy(event2);
226                 event2 = NULL;
227         }
228
229         return res;
230 }
231
232 struct event_sub_data {
233         unsigned int count;
234 };
235
236 static void event_sub_cb(const struct ast_event *event, void *d)
237 {
238         struct event_sub_data *data = d;
239
240         data->count++;
241 }
242
243 enum test_subs_class_type {
244         TEST_SUBS_ALL_STR,
245         TEST_SUBS_CUSTOM_STR,
246         TEST_SUBS_CUSTOM_RAW,
247         TEST_SUBS_CUSTOM_UINT,
248         TEST_SUBS_CUSTOM_BITFLAGS,
249         TEST_SUBS_CUSTOM_EXISTS,
250         TEST_SUBS_CUSTOM_DYNAMIC,
251         TEST_SUBS_CUSTOM_ANY,
252
253         /* Must be last. */
254         TEST_SUBS_TOTAL,
255 };
256
257 /*!
258  * \internal
259  * \brief Convert enum test_subs_class_type to string.
260  *
261  * \param val Enum value to convert to string.
262  *
263  * \return String equivalent of enum value.
264  */
265 static const char *test_subs_class_type_str(enum test_subs_class_type val)
266 {
267         switch (val) {
268         case TEST_SUBS_ALL_STR:
269                 return "TEST_SUBS_ALL_STR";
270         case TEST_SUBS_CUSTOM_STR:
271                 return "TEST_SUBS_CUSTOM_STR";
272         case TEST_SUBS_CUSTOM_RAW:
273                 return "TEST_SUBS_CUSTOM_RAW";
274         case TEST_SUBS_CUSTOM_UINT:
275                 return "TEST_SUBS_CUSTOM_UINT";
276         case TEST_SUBS_CUSTOM_BITFLAGS:
277                 return "TEST_SUBS_CUSTOM_BITFLAGS";
278         case TEST_SUBS_CUSTOM_EXISTS:
279                 return "TEST_SUBS_CUSTOM_EXISTS";
280         case TEST_SUBS_CUSTOM_DYNAMIC:
281                 return "TEST_SUBS_CUSTOM_DYNAMIC";
282         case TEST_SUBS_CUSTOM_ANY:
283                 return "TEST_SUBS_CUSTOM_ANY";
284         case TEST_SUBS_TOTAL:
285                 break;
286         }
287         return "Unknown";
288 }
289
290 /*!
291  * \internal
292  * \brief Test event subscriptions
293  *
294  * - Query for existing Subscriptions:
295  *   - ast_event_check_subscriber()
296  */
297 AST_TEST_DEFINE(event_sub_test)
298 {
299         enum ast_test_result_state res = AST_TEST_PASS;
300         struct ast_event *event;
301         int i;
302         enum ast_event_subscriber_res sub_res;
303         struct {
304                 struct ast_event_sub *sub;
305                 struct event_sub_data data;
306                 const unsigned int expected_count;
307         } test_subs[TEST_SUBS_TOTAL] = {
308                 [TEST_SUBS_ALL_STR] = {
309                         .expected_count = 2,
310                 },
311                 [TEST_SUBS_CUSTOM_STR] = {
312                         .expected_count = 2,
313                 },
314                 [TEST_SUBS_CUSTOM_RAW] = {
315                         .expected_count = 1,
316                 },
317                 [TEST_SUBS_CUSTOM_UINT] = {
318                         .expected_count = 1,
319                 },
320                 [TEST_SUBS_CUSTOM_BITFLAGS] = {
321                         .expected_count = 4,
322                 },
323                 [TEST_SUBS_CUSTOM_EXISTS] = {
324                         .expected_count = 2,
325                 },
326                 [TEST_SUBS_CUSTOM_DYNAMIC] = {
327                         .expected_count = 1,
328                 },
329                 [TEST_SUBS_CUSTOM_ANY] = {
330                         .expected_count = 6,
331                 },
332         };
333
334         switch (cmd) {
335         case TEST_INIT:
336                 info->name = "ast_event_subscribe_test";
337                 info->category = "/main/event/";
338                 info->summary = "Test event subscriptions";
339                 info->description =
340                         "This test exercises the API calls that allow subscriptions "
341                         "to events.";
342                 return AST_TEST_NOT_RUN;
343         case TEST_EXECUTE:
344                 break;
345         }
346
347         /*
348          * Subscription TEST_SUBS_ALL_STR:
349          *  - allocate normally
350          *  - subscribe to ALL events with a DEVICE STR IE check
351          */
352         ast_test_status_update(test, "Adding TEST_SUBS_ALL_STR subscription\n");
353         test_subs[TEST_SUBS_ALL_STR].sub = ast_event_subscribe(AST_EVENT_ALL, event_sub_cb,
354                 test_subs_class_type_str(TEST_SUBS_ALL_STR), &test_subs[TEST_SUBS_ALL_STR].data,
355                 AST_EVENT_IE_DEVICE, AST_EVENT_IE_PLTYPE_STR, "FOO/bar",
356                 AST_EVENT_IE_END);
357         if (!test_subs[TEST_SUBS_ALL_STR].sub) {
358                 ast_test_status_update(test, "Failed to create TEST_SUBS_ALL_STR subscription\n");
359                 res = AST_TEST_FAIL;
360                 goto return_cleanup;
361         }
362
363         if (strcmp(ast_event_subscriber_get_description(test_subs[TEST_SUBS_ALL_STR].sub),
364                 test_subs_class_type_str(TEST_SUBS_ALL_STR))) {
365                 ast_test_status_update(test,
366                         "Unexpected subscription description on TEST_SUBS_ALL_STR subscription\n");
367                 res = AST_TEST_FAIL;
368                 goto return_cleanup;
369         }
370
371         /*
372          * Subscription TEST_SUBS_CUSTOM_STR:
373          *  - allocate normally
374          *  - subscribe to CUSTOM events with a DEVICE STR IE check
375          */
376         ast_test_status_update(test, "Adding TEST_SUBS_CUSTOM_STR subscription\n");
377         test_subs[TEST_SUBS_CUSTOM_STR].sub = ast_event_subscribe(AST_EVENT_CUSTOM, event_sub_cb,
378                 test_subs_class_type_str(TEST_SUBS_CUSTOM_STR), &test_subs[TEST_SUBS_CUSTOM_STR].data,
379                 AST_EVENT_IE_DEVICE, AST_EVENT_IE_PLTYPE_STR, "FOO/bar",
380                 AST_EVENT_IE_END);
381         if (!test_subs[TEST_SUBS_CUSTOM_STR].sub) {
382                 ast_test_status_update(test, "Failed to create TEST_SUBS_CUSTOM_STR subscription\n");
383                 res = AST_TEST_FAIL;
384                 goto return_cleanup;
385         }
386
387         if (strcmp(ast_event_subscriber_get_description(test_subs[TEST_SUBS_CUSTOM_STR].sub),
388                 test_subs_class_type_str(TEST_SUBS_CUSTOM_STR))) {
389                 ast_test_status_update(test,
390                         "Unexpected subscription description on TEST_SUBS_CUSTOM_STR subscription\n");
391                 res = AST_TEST_FAIL;
392                 goto return_cleanup;
393         }
394
395         /*
396          * Subscription TEST_SUBS_CUSTOM_RAW:
397          *  - allocate normally
398          *  - subscribe to CUSTOM events with a MAILBOX RAW IE check
399          */
400         ast_test_status_update(test, "Adding TEST_SUBS_CUSTOM_RAW subscription\n");
401         test_subs[TEST_SUBS_CUSTOM_RAW].sub = ast_event_subscribe(AST_EVENT_CUSTOM, event_sub_cb,
402                 test_subs_class_type_str(TEST_SUBS_CUSTOM_RAW), &test_subs[TEST_SUBS_CUSTOM_RAW].data,
403                 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_RAW, "FOO/bar", sizeof("FOO/bar"),
404                 AST_EVENT_IE_END);
405         if (!test_subs[TEST_SUBS_CUSTOM_RAW].sub) {
406                 ast_test_status_update(test, "Failed to create TEST_SUBS_CUSTOM_RAW subscription\n");
407                 res = AST_TEST_FAIL;
408                 goto return_cleanup;
409         }
410
411         if (strcmp(ast_event_subscriber_get_description(test_subs[TEST_SUBS_CUSTOM_RAW].sub),
412                 test_subs_class_type_str(TEST_SUBS_CUSTOM_RAW))) {
413                 ast_test_status_update(test,
414                         "Unexpected subscription description on TEST_SUBS_CUSTOM_RAW subscription\n");
415                 res = AST_TEST_FAIL;
416                 goto return_cleanup;
417         }
418
419         /*
420          * Subscription TEST_SUBS_CUSTOM_UINT:
421          *  - allocate normally
422          *  - subscribe to CUSTOM events with a NEWMSGS UINT IE check
423          */
424         ast_test_status_update(test, "Adding TEST_SUBS_CUSTOM_UINT subscription\n");
425         test_subs[TEST_SUBS_CUSTOM_UINT].sub = ast_event_subscribe(AST_EVENT_CUSTOM, event_sub_cb,
426                 test_subs_class_type_str(TEST_SUBS_CUSTOM_UINT), &test_subs[TEST_SUBS_CUSTOM_UINT].data,
427                 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, 5,
428                 AST_EVENT_IE_END);
429         if (!test_subs[TEST_SUBS_CUSTOM_UINT].sub) {
430                 ast_test_status_update(test, "Failed to create TEST_SUBS_CUSTOM_UINT subscription\n");
431                 res = AST_TEST_FAIL;
432                 goto return_cleanup;
433         }
434
435         if (strcmp(ast_event_subscriber_get_description(test_subs[TEST_SUBS_CUSTOM_UINT].sub),
436                 test_subs_class_type_str(TEST_SUBS_CUSTOM_UINT))) {
437                 ast_test_status_update(test,
438                         "Unexpected subscription description on TEST_SUBS_CUSTOM_UINT subscription\n");
439                 res = AST_TEST_FAIL;
440                 goto return_cleanup;
441         }
442
443         /*
444          * Subscription TEST_SUBS_CUSTOM_BITFLAGS:
445          *  - allocate normally
446          *  - subscribe to CUSTOM events with a NEWMSGS BITFLAGS IE check
447          */
448         ast_test_status_update(test, "Adding TEST_SUBS_CUSTOM_BITFLAGS subscription\n");
449         test_subs[TEST_SUBS_CUSTOM_BITFLAGS].sub = ast_event_subscribe(AST_EVENT_CUSTOM, event_sub_cb,
450                 test_subs_class_type_str(TEST_SUBS_CUSTOM_BITFLAGS), &test_subs[TEST_SUBS_CUSTOM_BITFLAGS].data,
451                 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_BITFLAGS, 0x06,
452                 AST_EVENT_IE_END);
453         if (!test_subs[TEST_SUBS_CUSTOM_BITFLAGS].sub) {
454                 ast_test_status_update(test, "Failed to create TEST_SUBS_CUSTOM_BITFLAGS subscription\n");
455                 res = AST_TEST_FAIL;
456                 goto return_cleanup;
457         }
458
459         if (strcmp(ast_event_subscriber_get_description(test_subs[TEST_SUBS_CUSTOM_BITFLAGS].sub),
460                 test_subs_class_type_str(TEST_SUBS_CUSTOM_BITFLAGS))) {
461                 ast_test_status_update(test,
462                         "Unexpected subscription description on TEST_SUBS_CUSTOM_BITFLAGS subscription\n");
463                 res = AST_TEST_FAIL;
464                 goto return_cleanup;
465         }
466
467         /*
468          * Subscription TEST_SUBS_CUSTOM_EXISTS:
469          *  - allocate normally
470          *  - subscribe to CUSTOM events with a NEWMSGS UINT and OLDMSGS EXISTS IE check
471          */
472         ast_test_status_update(test, "Adding TEST_SUBS_CUSTOM_EXISTS subscription\n");
473         test_subs[TEST_SUBS_CUSTOM_EXISTS].sub = ast_event_subscribe(AST_EVENT_CUSTOM, event_sub_cb,
474                 test_subs_class_type_str(TEST_SUBS_CUSTOM_EXISTS), &test_subs[TEST_SUBS_CUSTOM_EXISTS].data,
475                 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, 4,
476                 AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_EXISTS,
477                 AST_EVENT_IE_END);
478         if (!test_subs[TEST_SUBS_CUSTOM_EXISTS].sub) {
479                 ast_test_status_update(test, "Failed to create TEST_SUBS_CUSTOM_EXISTS subscription\n");
480                 res = AST_TEST_FAIL;
481                 goto return_cleanup;
482         }
483
484         if (strcmp(ast_event_subscriber_get_description(test_subs[TEST_SUBS_CUSTOM_EXISTS].sub),
485                 test_subs_class_type_str(TEST_SUBS_CUSTOM_EXISTS))) {
486                 ast_test_status_update(test,
487                         "Unexpected subscription description on TEST_SUBS_CUSTOM_EXISTS subscription\n");
488                 res = AST_TEST_FAIL;
489                 goto return_cleanup;
490         }
491
492         /* For the sake of exercising destruction before activation */
493         test_subs[TEST_SUBS_CUSTOM_DYNAMIC].sub = ast_event_subscribe_new(AST_EVENT_CUSTOM,
494                 event_sub_cb, &test_subs[TEST_SUBS_CUSTOM_DYNAMIC].data);
495         if (!test_subs[TEST_SUBS_CUSTOM_DYNAMIC].sub) {
496                 ast_test_status_update(test, "Failed to create TEST_SUBS_CUSTOM_DYNAMIC subscription\n");
497                 res = AST_TEST_FAIL;
498                 goto return_cleanup;
499         }
500         ast_event_sub_destroy(test_subs[TEST_SUBS_CUSTOM_DYNAMIC].sub);
501
502         /*
503          * Subscription TEST_SUBS_CUSTOM_DYNAMIC:
504          *  - allocate dynamically
505          *  - subscribe to all CUSTOM events
506          *  - add IE checks for all types
507          */
508         ast_test_status_update(test, "Adding TEST_SUBS_CUSTOM_DYNAMIC subscription\n");
509         test_subs[TEST_SUBS_CUSTOM_DYNAMIC].sub = ast_event_subscribe_new(AST_EVENT_CUSTOM,
510                 event_sub_cb, &test_subs[TEST_SUBS_CUSTOM_DYNAMIC].data);
511         if (!test_subs[TEST_SUBS_CUSTOM_DYNAMIC].sub) {
512                 ast_test_status_update(test, "Failed to create TEST_SUBS_CUSTOM_DYNAMIC subscription\n");
513                 res = AST_TEST_FAIL;
514                 goto return_cleanup;
515         }
516
517         if (strcmp(ast_event_subscriber_get_description(test_subs[TEST_SUBS_CUSTOM_DYNAMIC].sub),
518                 "")) {
519                 ast_event_sub_destroy(test_subs[TEST_SUBS_CUSTOM_DYNAMIC].sub);
520                 test_subs[TEST_SUBS_CUSTOM_DYNAMIC].sub = NULL;
521                 ast_test_status_update(test,
522                         "Unexpected subscription description on TEST_SUBS_CUSTOM_DYNAMIC subscription\n");
523                 res = AST_TEST_FAIL;
524                 goto return_cleanup;
525         }
526
527         if (ast_event_sub_append_ie_uint(test_subs[TEST_SUBS_CUSTOM_DYNAMIC].sub, AST_EVENT_IE_NEWMSGS, 4)) {
528                 ast_event_sub_destroy(test_subs[TEST_SUBS_CUSTOM_DYNAMIC].sub);
529                 test_subs[TEST_SUBS_CUSTOM_DYNAMIC].sub = NULL;
530                 ast_test_status_update(test, "Failed to append UINT IE to TEST_SUBS_CUSTOM_DYNAMIC subscription\n");
531                 res = AST_TEST_FAIL;
532                 goto return_cleanup;
533         }
534
535         if (ast_event_sub_append_ie_bitflags(test_subs[TEST_SUBS_CUSTOM_DYNAMIC].sub, AST_EVENT_IE_OLDMSGS, 1)) {
536                 ast_event_sub_destroy(test_subs[TEST_SUBS_CUSTOM_DYNAMIC].sub);
537                 test_subs[TEST_SUBS_CUSTOM_DYNAMIC].sub = NULL;
538                 ast_test_status_update(test, "Failed to append BITFLAGS IE to TEST_SUBS_CUSTOM_DYNAMIC subscription\n");
539                 res = AST_TEST_FAIL;
540                 goto return_cleanup;
541         }
542
543         if (ast_event_sub_append_ie_str(test_subs[TEST_SUBS_CUSTOM_DYNAMIC].sub, AST_EVENT_IE_DEVICE, "FOO/bar")) {
544                 ast_event_sub_destroy(test_subs[TEST_SUBS_CUSTOM_DYNAMIC].sub);
545                 test_subs[TEST_SUBS_CUSTOM_DYNAMIC].sub = NULL;
546                 ast_test_status_update(test, "Failed to append STR IE to TEST_SUBS_CUSTOM_DYNAMIC subscription\n");
547                 res = AST_TEST_FAIL;
548                 goto return_cleanup;
549         }
550
551         if (ast_event_sub_append_ie_raw(test_subs[TEST_SUBS_CUSTOM_DYNAMIC].sub, AST_EVENT_IE_MAILBOX, "800 km",
552                         strlen("800 km"))) {
553                 ast_event_sub_destroy(test_subs[TEST_SUBS_CUSTOM_DYNAMIC].sub);
554                 test_subs[TEST_SUBS_CUSTOM_DYNAMIC].sub = NULL;
555                 ast_test_status_update(test, "Failed to append RAW IE to TEST_SUBS_CUSTOM_DYNAMIC subscription\n");
556                 res = AST_TEST_FAIL;
557                 goto return_cleanup;
558         }
559
560         if (ast_event_sub_append_ie_exists(test_subs[TEST_SUBS_CUSTOM_DYNAMIC].sub, AST_EVENT_IE_STATE)) {
561                 ast_event_sub_destroy(test_subs[TEST_SUBS_CUSTOM_DYNAMIC].sub);
562                 test_subs[TEST_SUBS_CUSTOM_DYNAMIC].sub = NULL;
563                 ast_test_status_update(test, "Failed to append EXISTS IE to TEST_SUBS_CUSTOM_DYNAMIC subscription\n");
564                 res = AST_TEST_FAIL;
565                 goto return_cleanup;
566         }
567
568         if (ast_event_sub_activate(test_subs[TEST_SUBS_CUSTOM_DYNAMIC].sub)) {
569                 ast_event_sub_destroy(test_subs[TEST_SUBS_CUSTOM_DYNAMIC].sub);
570                 test_subs[TEST_SUBS_CUSTOM_DYNAMIC].sub = NULL;
571                 ast_test_status_update(test, "Failed to activate TEST_SUBS_CUSTOM_DYNAMIC subscription\n");
572                 res = AST_TEST_FAIL;
573                 goto return_cleanup;
574         }
575
576         /*
577          * Exercise the API call to check for existing subscriptions.
578          */
579         ast_test_status_update(test, "Checking for subscribers to events\n");
580
581         /* Check STR matching. */
582         sub_res = ast_event_check_subscriber(AST_EVENT_CUSTOM,
583                 AST_EVENT_IE_DEVICE, AST_EVENT_IE_PLTYPE_STR, "FOO/bar",
584                 AST_EVENT_IE_END);
585         if (sub_res != AST_EVENT_SUB_EXISTS) {
586                 ast_test_status_update(test, "Str FOO/bar subscription did not exist\n");
587                 res = AST_TEST_FAIL;
588         }
589
590         sub_res = ast_event_check_subscriber(AST_EVENT_CUSTOM,
591                 AST_EVENT_IE_DEVICE, AST_EVENT_IE_PLTYPE_STR, "Money",
592                 AST_EVENT_IE_END);
593         if (sub_res != AST_EVENT_SUB_NONE) {
594                 ast_test_status_update(test, "Str Money subscription should not exist! (%d)\n",
595                         sub_res);
596                 res = AST_TEST_FAIL;
597         }
598
599         /* Check RAW matching. */
600         sub_res = ast_event_check_subscriber(AST_EVENT_CUSTOM,
601                 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_RAW, "FOO/bar", sizeof("FOO/bar"),
602                 AST_EVENT_IE_END);
603         if (sub_res != AST_EVENT_SUB_EXISTS) {
604                 ast_test_status_update(test, "Raw FOO/bar subscription did not exist\n");
605                 res = AST_TEST_FAIL;
606         }
607
608         sub_res = ast_event_check_subscriber(AST_EVENT_CUSTOM,
609                 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_RAW, "FOO/bar", sizeof("FOO/bar") - 1,
610                 AST_EVENT_IE_END);
611         if (sub_res != AST_EVENT_SUB_NONE) {
612                 ast_test_status_update(test, "Raw FOO/bar-1 subscription should not exist! (%d)\n",
613                         sub_res);
614                 res = AST_TEST_FAIL;
615         }
616
617         sub_res = ast_event_check_subscriber(AST_EVENT_CUSTOM,
618                 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_RAW, "Monkeys", sizeof("Monkeys"),
619                 AST_EVENT_IE_END);
620         if (sub_res != AST_EVENT_SUB_NONE) {
621                 ast_test_status_update(test, "Raw Monkeys subscription should not exist! (%d)\n",
622                         sub_res);
623                 res = AST_TEST_FAIL;
624         }
625
626         /* Check UINT matching. */
627         sub_res = ast_event_check_subscriber(AST_EVENT_CUSTOM,
628                 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, 5,
629                 AST_EVENT_IE_END);
630         if (sub_res != AST_EVENT_SUB_EXISTS) {
631                 ast_test_status_update(test, "UINT=5 subscription did not exist\n");
632                 res = AST_TEST_FAIL;
633         }
634
635         sub_res = ast_event_check_subscriber(AST_EVENT_CUSTOM,
636                 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, 1,
637                 AST_EVENT_IE_END);
638         if (sub_res != AST_EVENT_SUB_NONE) {
639                 ast_test_status_update(test, "UINT=1 subscription should not exist! (%d)\n",
640                         sub_res);
641                 res = AST_TEST_FAIL;
642         }
643
644         /* Check BITFLAGS matching. */
645         sub_res = ast_event_check_subscriber(AST_EVENT_CUSTOM,
646                 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_BITFLAGS, 2,
647                 AST_EVENT_IE_END);
648         if (sub_res != AST_EVENT_SUB_EXISTS) {
649                 ast_test_status_update(test, "BITFLAGS=2 subscription did not exist\n");
650                 res = AST_TEST_FAIL;
651         }
652
653         sub_res = ast_event_check_subscriber(AST_EVENT_CUSTOM,
654                 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_BITFLAGS, 8,
655                 AST_EVENT_IE_END);
656         if (sub_res != AST_EVENT_SUB_NONE) {
657                 ast_test_status_update(test, "BITFLAGS=8 subscription should not exist! (%d)\n",
658                         sub_res);
659                 res = AST_TEST_FAIL;
660         }
661
662         /* Check EXISTS matching. */
663         sub_res = ast_event_check_subscriber(AST_EVENT_CUSTOM,
664                 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, 4,
665                 AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, 100,
666                 AST_EVENT_IE_END);
667         if (sub_res != AST_EVENT_SUB_EXISTS) {
668                 ast_test_status_update(test, "EXISTS subscription did not exist\n");
669                 res = AST_TEST_FAIL;
670         }
671
672         sub_res = ast_event_check_subscriber(AST_EVENT_CUSTOM,
673                 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, 4,
674                 AST_EVENT_IE_END);
675         if (sub_res != AST_EVENT_SUB_NONE) {
676                 ast_test_status_update(test, "EXISTS subscription should not exist! (%d)\n",
677                         sub_res);
678                 res = AST_TEST_FAIL;
679         }
680
681         /*
682          * Subscription TEST_SUBS_CUSTOM_ANY:
683          *  - allocate normally
684          *  - subscribe to all CUSTOM events
685          */
686         ast_test_status_update(test, "Adding TEST_SUBS_CUSTOM_ANY subscription\n");
687         test_subs[TEST_SUBS_CUSTOM_ANY].sub = ast_event_subscribe(AST_EVENT_CUSTOM, event_sub_cb,
688                 test_subs_class_type_str(TEST_SUBS_CUSTOM_ANY), &test_subs[TEST_SUBS_CUSTOM_ANY].data,
689                 AST_EVENT_IE_END);
690         if (!test_subs[TEST_SUBS_CUSTOM_ANY].sub) {
691                 ast_test_status_update(test, "Failed to create TEST_SUBS_CUSTOM_ANY subscription\n");
692                 res = AST_TEST_FAIL;
693                 goto return_cleanup;
694         }
695
696         if (strcmp(ast_event_subscriber_get_description(test_subs[TEST_SUBS_CUSTOM_ANY].sub),
697                 test_subs_class_type_str(TEST_SUBS_CUSTOM_ANY))) {
698                 ast_test_status_update(test,
699                         "Unexpected subscription description on TEST_SUBS_CUSTOM_ANY subscription\n");
700                 res = AST_TEST_FAIL;
701                 goto return_cleanup;
702         }
703
704         /*
705          * Fire off some events and track what was received in the callback
706          */
707         ast_test_status_update(test, "Posting test events\n");
708
709         /*
710          * Event to check STR matching.
711          *
712          * Matching subscriptions:
713          * TEST_SUBS_ALL_STR
714          * TEST_SUBS_CUSTOM_STR
715          * TEST_SUBS_CUSTOM_ANY
716          */
717         event = ast_event_new(AST_EVENT_CUSTOM,
718                 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_RAW, "FOO/bar", sizeof("FOO/bar") - 1,
719                 AST_EVENT_IE_DEVICE, AST_EVENT_IE_PLTYPE_STR, "FOO/bar",
720                 AST_EVENT_IE_END);
721         if (!event) {
722                 ast_test_status_update(test, "Failed to create event\n");
723                 res = AST_TEST_FAIL;
724                 goto return_cleanup;
725         }
726         if (ast_event_queue(event)) {
727                 ast_event_destroy(event);
728                 event = NULL;
729                 ast_test_status_update(test, "Failed to queue event\n");
730                 res = AST_TEST_FAIL;
731                 goto return_cleanup;
732         }
733
734         /*
735          * Event to check RAW matching.
736          *
737          * Matching subscriptions:
738          * TEST_SUBS_CUSTOM_RAW
739          * TEST_SUBS_CUSTOM_ANY
740          */
741         event = ast_event_new(AST_EVENT_CUSTOM,
742                 AST_EVENT_IE_DEVICE, AST_EVENT_IE_PLTYPE_STR, "Misery",
743                 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_RAW, "FOO/bar", sizeof("FOO/bar"),
744                 AST_EVENT_IE_END);
745         if (!event) {
746                 ast_test_status_update(test, "Failed to create event\n");
747                 res = AST_TEST_FAIL;
748                 goto return_cleanup;
749         }
750         if (ast_event_queue(event)) {
751                 ast_event_destroy(event);
752                 event = NULL;
753                 ast_test_status_update(test, "Failed to queue event\n");
754                 res = AST_TEST_FAIL;
755                 goto return_cleanup;
756         }
757
758         /*
759          * Event to check UINT matching.
760          *
761          * Matching subscriptions:
762          * TEST_SUBS_CUSTOM_UINT
763          * TEST_SUBS_CUSTOM_BITFLAGS
764          * TEST_SUBS_CUSTOM_ANY
765          */
766         event = ast_event_new(AST_EVENT_CUSTOM,
767                 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, 5,
768                 AST_EVENT_IE_END);
769         if (!event) {
770                 ast_test_status_update(test, "Failed to create event\n");
771                 res = AST_TEST_FAIL;
772                 goto return_cleanup;
773         }
774         if (ast_event_queue(event)) {
775                 ast_event_destroy(event);
776                 event = NULL;
777                 ast_test_status_update(test, "Failed to queue event\n");
778                 res = AST_TEST_FAIL;
779                 goto return_cleanup;
780         }
781
782         /*
783          * Event to check BITFLAGS matching.
784          *
785          * Matching subscriptions:
786          * TEST_SUBS_CUSTOM_BITFLAGS
787          * TEST_SUBS_CUSTOM_ANY
788          */
789         event = ast_event_new(AST_EVENT_CUSTOM,
790                 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, 4,
791                 AST_EVENT_IE_END);
792         if (!event) {
793                 ast_test_status_update(test, "Failed to create event\n");
794                 res = AST_TEST_FAIL;
795                 goto return_cleanup;
796         }
797         if (ast_event_queue(event)) {
798                 ast_event_destroy(event);
799                 event = NULL;
800                 ast_test_status_update(test, "Failed to queue event\n");
801                 res = AST_TEST_FAIL;
802                 goto return_cleanup;
803         }
804
805         /*
806          * Event to check EXISTS matching.
807          *
808          * Matching subscriptions:
809          * TEST_SUBS_CUSTOM_EXISTS
810          * TEST_SUBS_CUSTOM_BITFLAGS
811          * TEST_SUBS_CUSTOM_ANY
812          */
813         event = ast_event_new(AST_EVENT_CUSTOM,
814                 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, 4,
815                 AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, 4,
816                 AST_EVENT_IE_END);
817         if (!event) {
818                 ast_test_status_update(test, "Failed to create event\n");
819                 res = AST_TEST_FAIL;
820                 goto return_cleanup;
821         }
822         if (ast_event_queue(event)) {
823                 ast_event_destroy(event);
824                 event = NULL;
825                 ast_test_status_update(test, "Failed to queue event\n");
826                 res = AST_TEST_FAIL;
827                 goto return_cleanup;
828         }
829
830         /*
831          * Event to get dynamic subscription to have an event.
832          *
833          * Matching subscriptions:
834          * TEST_SUBS_CUSTOM_DYNAMIC
835          * TEST_SUBS_CUSTOM_BITFLAGS
836          * TEST_SUBS_CUSTOM_EXISTS
837          * TEST_SUBS_ALL_STR
838          * TEST_SUBS_CUSTOM_STR
839          * TEST_SUBS_CUSTOM_ANY
840          */
841         event = ast_event_new(AST_EVENT_CUSTOM,
842                 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, 4,
843                 AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, 5,
844                 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_RAW, "800 km", strlen("800 km"),
845                 AST_EVENT_IE_DEVICE, AST_EVENT_IE_PLTYPE_STR, "FOO/bar",
846                 AST_EVENT_IE_STATE, AST_EVENT_IE_PLTYPE_UINT, 5,
847                 AST_EVENT_IE_END);
848         if (!event) {
849                 ast_test_status_update(test, "Failed to create event\n");
850                 res = AST_TEST_FAIL;
851                 goto return_cleanup;
852         }
853         if (ast_event_queue(event)) {
854                 ast_event_destroy(event);
855                 event = NULL;
856                 ast_test_status_update(test, "Failed to queue event\n");
857                 res = AST_TEST_FAIL;
858                 goto return_cleanup;
859         }
860
861         event = NULL;
862
863         /*
864          * Check the results of the test.
865          *
866          * First of all, event distribution is asynchronous from the event producer,
867          * so knowing when to continue from here and check results is an instance of
868          * the halting problem.  A few seconds really should be more than enough time.
869          * If something was actually blocking event distribution that long, I would call
870          * it a bug.
871          *
872          * See test_subs[] initialization for expected results.
873          */
874
875         ast_test_status_update(test, "Sleeping a few seconds to allow event propagation...\n");
876         sleep(3);
877
878         for (i = 0; i < ARRAY_LEN(test_subs); i++) {
879                 if (!test_subs[i].sub) {
880                         ast_test_status_update(test, "Missing a test subscription for %s\n",
881                                 test_subs_class_type_str(i));
882                         res = AST_TEST_FAIL;
883                 }
884                 if (test_subs[i].data.count != test_subs[i].expected_count) {
885                         ast_test_status_update(test,
886                                 "Unexpected callback count, got %u expected %u for %s\n",
887                                 test_subs[i].data.count, test_subs[i].expected_count,
888                                 test_subs_class_type_str(i));
889                         res = AST_TEST_FAIL;
890                 }
891         }
892
893 return_cleanup:
894         for (i = 0; i < ARRAY_LEN(test_subs); i++) {
895                 if (test_subs[i].sub) {
896                         test_subs[i].sub = ast_event_unsubscribe(test_subs[i].sub);
897                 }
898         }
899
900         return res;
901 }
902
903 static int unload_module(void)
904 {
905         AST_TEST_UNREGISTER(event_new_test);
906         AST_TEST_UNREGISTER(event_sub_test);
907
908         return 0;
909 }
910
911 static int load_module(void)
912 {
913         AST_TEST_REGISTER(event_new_test);
914         AST_TEST_REGISTER(event_sub_test);
915
916         return AST_MODULE_LOAD_SUCCESS;
917 }
918
919 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "ast_event API Tests");