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