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