Add additional namespaces for Google Talk which are used for the gmail client.
[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         /* Make sure that the tech portion of the device string is case-insensitive */
610         sub_res = ast_event_check_subscriber(AST_EVENT_CUSTOM,
611                 AST_EVENT_IE_DEVICE, AST_EVENT_IE_PLTYPE_STR, "foo/bar",
612                 AST_EVENT_IE_END);
613         if (sub_res != AST_EVENT_SUB_EXISTS) {
614                 ast_test_status_update(test, "Str FOO/bar subscription lacks proper case-sensitivity for device strings\n");
615                 res = AST_TEST_FAIL;
616         }
617
618         /* Make sure that the non-tech portion of the device string is case-sensitive
619          * and fails to match appropriately */
620         sub_res = ast_event_check_subscriber(AST_EVENT_CUSTOM,
621                 AST_EVENT_IE_DEVICE, AST_EVENT_IE_PLTYPE_STR, "FOO/BAR",
622                 AST_EVENT_IE_END);
623         if (sub_res == AST_EVENT_SUB_EXISTS) {
624                 ast_test_status_update(test, "Str FOO/bar subscription lacks proper case-sensitivity for device strings\n");
625                 res = AST_TEST_FAIL;
626         }
627
628         sub_res = ast_event_check_subscriber(AST_EVENT_CUSTOM,
629                 AST_EVENT_IE_DEVICE, AST_EVENT_IE_PLTYPE_STR, "Money",
630                 AST_EVENT_IE_END);
631         if (sub_res != AST_EVENT_SUB_NONE) {
632                 ast_test_status_update(test, "Str Money subscription should not exist! (%d)\n",
633                         sub_res);
634                 res = AST_TEST_FAIL;
635         }
636
637         /* Check RAW matching. */
638         sub_res = ast_event_check_subscriber(AST_EVENT_CUSTOM,
639                 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_RAW, "FOO/bar", sizeof("FOO/bar"),
640                 AST_EVENT_IE_END);
641         if (sub_res != AST_EVENT_SUB_EXISTS) {
642                 ast_test_status_update(test, "Raw FOO/bar subscription did not exist\n");
643                 res = AST_TEST_FAIL;
644         }
645
646         sub_res = ast_event_check_subscriber(AST_EVENT_CUSTOM,
647                 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_RAW, "FOO/bar", sizeof("FOO/bar") - 1,
648                 AST_EVENT_IE_END);
649         if (sub_res != AST_EVENT_SUB_NONE) {
650                 ast_test_status_update(test, "Raw FOO/bar-1 subscription should not exist! (%d)\n",
651                         sub_res);
652                 res = AST_TEST_FAIL;
653         }
654
655         sub_res = ast_event_check_subscriber(AST_EVENT_CUSTOM,
656                 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_RAW, "Monkeys", sizeof("Monkeys"),
657                 AST_EVENT_IE_END);
658         if (sub_res != AST_EVENT_SUB_NONE) {
659                 ast_test_status_update(test, "Raw Monkeys subscription should not exist! (%d)\n",
660                         sub_res);
661                 res = AST_TEST_FAIL;
662         }
663
664         /* Check UINT matching. */
665         sub_res = ast_event_check_subscriber(AST_EVENT_CUSTOM,
666                 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, 5,
667                 AST_EVENT_IE_END);
668         if (sub_res != AST_EVENT_SUB_EXISTS) {
669                 ast_test_status_update(test, "UINT=5 subscription did not exist\n");
670                 res = AST_TEST_FAIL;
671         }
672
673         sub_res = ast_event_check_subscriber(AST_EVENT_CUSTOM,
674                 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, 1,
675                 AST_EVENT_IE_END);
676         if (sub_res != AST_EVENT_SUB_NONE) {
677                 ast_test_status_update(test, "UINT=1 subscription should not exist! (%d)\n",
678                         sub_res);
679                 res = AST_TEST_FAIL;
680         }
681
682         /* Check BITFLAGS matching. */
683         sub_res = ast_event_check_subscriber(AST_EVENT_CUSTOM,
684                 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_BITFLAGS, 2,
685                 AST_EVENT_IE_END);
686         if (sub_res != AST_EVENT_SUB_EXISTS) {
687                 ast_test_status_update(test, "BITFLAGS=2 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_BITFLAGS, 8,
693                 AST_EVENT_IE_END);
694         if (sub_res != AST_EVENT_SUB_NONE) {
695                 ast_test_status_update(test, "BITFLAGS=8 subscription should not exist! (%d)\n",
696                         sub_res);
697                 res = AST_TEST_FAIL;
698         }
699
700         /* Check EXISTS matching. */
701         sub_res = ast_event_check_subscriber(AST_EVENT_CUSTOM,
702                 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, 4,
703                 AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, 100,
704                 AST_EVENT_IE_END);
705         if (sub_res != AST_EVENT_SUB_EXISTS) {
706                 ast_test_status_update(test, "EXISTS subscription did not exist\n");
707                 res = AST_TEST_FAIL;
708         }
709
710         sub_res = ast_event_check_subscriber(AST_EVENT_CUSTOM,
711                 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, 4,
712                 AST_EVENT_IE_END);
713         if (sub_res != AST_EVENT_SUB_NONE) {
714                 ast_test_status_update(test, "EXISTS subscription should not exist! (%d)\n",
715                         sub_res);
716                 res = AST_TEST_FAIL;
717         }
718
719         ast_test_status_update(test, "Special event posting test\n");
720
721         /*
722          * Event to check if event is even posted.
723          *
724          * Matching subscriptions:
725          * TEST_SUBS_CUSTOM_RAW
726          */
727         event = ast_event_new(AST_EVENT_CUSTOM,
728                 AST_EVENT_IE_DEVICE, AST_EVENT_IE_PLTYPE_STR, "Mula",
729                 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_RAW, "FOO/bar", sizeof("FOO/bar"),
730                 AST_EVENT_IE_END);
731         if (!event) {
732                 ast_test_status_update(test, "Failed to create event\n");
733                 res = AST_TEST_FAIL;
734                 goto return_cleanup;
735         }
736         if (ast_event_queue(event)) {
737                 ast_event_destroy(event);
738                 event = NULL;
739                 ast_test_status_update(test, "Failed to queue event\n");
740                 res = AST_TEST_FAIL;
741                 goto return_cleanup;
742         }
743
744         ast_test_status_update(test, "Sleeping a few seconds to allow event propagation...\n");
745         sleep(3);
746
747         /*
748          * Subscription TEST_SUBS_CUSTOM_ANY:
749          *  - allocate normally
750          *  - subscribe to all CUSTOM events
751          */
752         ast_test_status_update(test, "Adding TEST_SUBS_CUSTOM_ANY subscription\n");
753         test_subs[TEST_SUBS_CUSTOM_ANY].sub = ast_event_subscribe(AST_EVENT_CUSTOM, event_sub_cb,
754                 test_subs_class_type_str(TEST_SUBS_CUSTOM_ANY), &test_subs[TEST_SUBS_CUSTOM_ANY].data,
755                 AST_EVENT_IE_END);
756         if (!test_subs[TEST_SUBS_CUSTOM_ANY].sub) {
757                 ast_test_status_update(test, "Failed to create TEST_SUBS_CUSTOM_ANY subscription\n");
758                 res = AST_TEST_FAIL;
759                 goto return_cleanup;
760         }
761
762         if (strcmp(ast_event_subscriber_get_description(test_subs[TEST_SUBS_CUSTOM_ANY].sub),
763                 test_subs_class_type_str(TEST_SUBS_CUSTOM_ANY))) {
764                 ast_test_status_update(test,
765                         "Unexpected subscription description on TEST_SUBS_CUSTOM_ANY subscription\n");
766                 res = AST_TEST_FAIL;
767                 goto return_cleanup;
768         }
769
770         /*
771          * Fire off some events and track what was received in the callback
772          */
773         ast_test_status_update(test, "Posting test events\n");
774
775         /*
776          * Event to check STR matching.
777          *
778          * Matching subscriptions:
779          * TEST_SUBS_ALL_STR
780          * TEST_SUBS_CUSTOM_STR
781          * TEST_SUBS_CUSTOM_ANY
782          */
783         event = ast_event_new(AST_EVENT_CUSTOM,
784                 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_RAW, "FOO/bar", sizeof("FOO/bar") - 1,
785                 AST_EVENT_IE_DEVICE, AST_EVENT_IE_PLTYPE_STR, "FOO/bar",
786                 AST_EVENT_IE_END);
787         if (!event) {
788                 ast_test_status_update(test, "Failed to create event\n");
789                 res = AST_TEST_FAIL;
790                 goto return_cleanup;
791         }
792         if (ast_event_queue(event)) {
793                 ast_event_destroy(event);
794                 event = NULL;
795                 ast_test_status_update(test, "Failed to queue event\n");
796                 res = AST_TEST_FAIL;
797                 goto return_cleanup;
798         }
799
800         /*
801          * Event to check RAW matching.
802          *
803          * Matching subscriptions:
804          * TEST_SUBS_CUSTOM_RAW
805          * TEST_SUBS_CUSTOM_ANY
806          */
807         event = ast_event_new(AST_EVENT_CUSTOM,
808                 AST_EVENT_IE_DEVICE, AST_EVENT_IE_PLTYPE_STR, "Misery",
809                 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_RAW, "FOO/bar", sizeof("FOO/bar"),
810                 AST_EVENT_IE_END);
811         if (!event) {
812                 ast_test_status_update(test, "Failed to create event\n");
813                 res = AST_TEST_FAIL;
814                 goto return_cleanup;
815         }
816         if (ast_event_queue(event)) {
817                 ast_event_destroy(event);
818                 event = NULL;
819                 ast_test_status_update(test, "Failed to queue event\n");
820                 res = AST_TEST_FAIL;
821                 goto return_cleanup;
822         }
823
824         /*
825          * Event to check UINT matching.
826          *
827          * Matching subscriptions:
828          * TEST_SUBS_CUSTOM_UINT
829          * TEST_SUBS_CUSTOM_BITFLAGS
830          * TEST_SUBS_CUSTOM_ANY
831          */
832         event = ast_event_new(AST_EVENT_CUSTOM,
833                 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, 5,
834                 AST_EVENT_IE_END);
835         if (!event) {
836                 ast_test_status_update(test, "Failed to create event\n");
837                 res = AST_TEST_FAIL;
838                 goto return_cleanup;
839         }
840         if (ast_event_queue(event)) {
841                 ast_event_destroy(event);
842                 event = NULL;
843                 ast_test_status_update(test, "Failed to queue event\n");
844                 res = AST_TEST_FAIL;
845                 goto return_cleanup;
846         }
847
848         /*
849          * Event to check BITFLAGS matching.
850          *
851          * Matching subscriptions:
852          * TEST_SUBS_CUSTOM_BITFLAGS
853          * TEST_SUBS_CUSTOM_ANY
854          */
855         event = ast_event_new(AST_EVENT_CUSTOM,
856                 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, 4,
857                 AST_EVENT_IE_END);
858         if (!event) {
859                 ast_test_status_update(test, "Failed to create event\n");
860                 res = AST_TEST_FAIL;
861                 goto return_cleanup;
862         }
863         if (ast_event_queue(event)) {
864                 ast_event_destroy(event);
865                 event = NULL;
866                 ast_test_status_update(test, "Failed to queue event\n");
867                 res = AST_TEST_FAIL;
868                 goto return_cleanup;
869         }
870
871         /*
872          * Event to check EXISTS matching.
873          *
874          * Matching subscriptions:
875          * TEST_SUBS_CUSTOM_EXISTS
876          * TEST_SUBS_CUSTOM_BITFLAGS
877          * TEST_SUBS_CUSTOM_ANY
878          */
879         event = ast_event_new(AST_EVENT_CUSTOM,
880                 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, 4,
881                 AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, 4,
882                 AST_EVENT_IE_END);
883         if (!event) {
884                 ast_test_status_update(test, "Failed to create event\n");
885                 res = AST_TEST_FAIL;
886                 goto return_cleanup;
887         }
888         if (ast_event_queue(event)) {
889                 ast_event_destroy(event);
890                 event = NULL;
891                 ast_test_status_update(test, "Failed to queue event\n");
892                 res = AST_TEST_FAIL;
893                 goto return_cleanup;
894         }
895
896         /*
897          * Event to get dynamic subscription to have an event.
898          *
899          * Matching subscriptions:
900          * TEST_SUBS_CUSTOM_DYNAMIC
901          * TEST_SUBS_CUSTOM_BITFLAGS
902          * TEST_SUBS_CUSTOM_EXISTS
903          * TEST_SUBS_ALL_STR
904          * TEST_SUBS_CUSTOM_STR
905          * TEST_SUBS_CUSTOM_ANY
906          */
907         event = ast_event_new(AST_EVENT_CUSTOM,
908                 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, 4,
909                 AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, 5,
910                 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_RAW, "800 km", strlen("800 km"),
911                 AST_EVENT_IE_DEVICE, AST_EVENT_IE_PLTYPE_STR, "FOO/bar",
912                 AST_EVENT_IE_STATE, AST_EVENT_IE_PLTYPE_UINT, 5,
913                 AST_EVENT_IE_END);
914         if (!event) {
915                 ast_test_status_update(test, "Failed to create event\n");
916                 res = AST_TEST_FAIL;
917                 goto return_cleanup;
918         }
919         if (ast_event_queue(event)) {
920                 ast_event_destroy(event);
921                 event = NULL;
922                 ast_test_status_update(test, "Failed to queue event\n");
923                 res = AST_TEST_FAIL;
924                 goto return_cleanup;
925         }
926
927         event = NULL;
928
929         /*
930          * Check the results of the test.
931          *
932          * First of all, event distribution is asynchronous from the event producer,
933          * so knowing when to continue from here and check results is an instance of
934          * the halting problem.  A few seconds really should be more than enough time.
935          * If something was actually blocking event distribution that long, I would call
936          * it a bug.
937          *
938          * See test_subs[] initialization for expected results.
939          */
940
941         ast_test_status_update(test, "Sleeping a few seconds to allow event propagation...\n");
942         sleep(3);
943
944         for (i = 0; i < ARRAY_LEN(test_subs); i++) {
945                 if (!test_subs[i].sub) {
946                         ast_test_status_update(test, "Missing a test subscription for %s\n",
947                                 test_subs_class_type_str(i));
948                         res = AST_TEST_FAIL;
949                 }
950                 if (test_subs[i].data.count != test_subs[i].expected_count) {
951                         ast_test_status_update(test,
952                                 "Unexpected callback count, got %u expected %u for %s\n",
953                                 test_subs[i].data.count, test_subs[i].expected_count,
954                                 test_subs_class_type_str(i));
955                         res = AST_TEST_FAIL;
956                 }
957         }
958
959 return_cleanup:
960         for (i = 0; i < ARRAY_LEN(test_subs); i++) {
961                 if (test_subs[i].sub) {
962                         test_subs[i].sub = ast_event_unsubscribe(test_subs[i].sub);
963                 }
964         }
965
966         return res;
967 }
968
969 static int unload_module(void)
970 {
971         AST_TEST_UNREGISTER(event_new_test);
972         AST_TEST_UNREGISTER(event_sub_test);
973
974         return 0;
975 }
976
977 static int load_module(void)
978 {
979         AST_TEST_REGISTER(event_new_test);
980         AST_TEST_REGISTER(event_sub_test);
981
982         return AST_MODULE_LOAD_SUCCESS;
983 }
984
985 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "ast_event API Tests");