Merge "lpc10: Avoid compiler warning when DONT_OPTIMIZE/COMPILE_DOUBLE."
[asterisk/asterisk.git] / tests / test_devicestate.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2010, Digium, Inc.
5  *
6  * David Vossel <dvossel@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 Device State Test Module
22  *
23  * \author David Vossel <dvossel@digium.com>
24  *
25  * \ingroup tests
26  */
27
28 /*** MODULEINFO
29         <depend>TEST_FRAMEWORK</depend>
30         <support_level>core</support_level>
31  ***/
32
33 #include "asterisk.h"
34
35 #include "asterisk/utils.h"
36 #include "asterisk/module.h"
37 #include "asterisk/test.h"
38 #include "asterisk/devicestate.h"
39 #include "asterisk/pbx.h"
40 #include "asterisk/stasis_message_router.h"
41 #include "asterisk/vector.h"
42
43 #define UNIT_TEST_DEVICE_IDENTIFIER "unit_test_device_identifier"
44
45 #define DEVICE_STATE_CHANNEL_TYPE "TestDeviceState"
46
47 #define DEVSTATE_PROVIDER "TestDevState"
48
49 #define DEVSTATE_PROVIDER_LC "testdevstate"
50
51 #define DEVSTATE_PROVIDER_LEN 12
52
53 /*! \brief Used to assign an increasing integer to channel name */
54 static unsigned int chan_idx;
55
56 /* These arrays are the result of the 'core show device2extenstate' output. */
57 static int combined_results[] = {
58         AST_DEVICE_UNKNOWN,
59         AST_DEVICE_NOT_INUSE,
60         AST_DEVICE_INUSE,
61         AST_DEVICE_BUSY,
62         AST_DEVICE_UNKNOWN,
63         AST_DEVICE_UNAVAILABLE,
64         AST_DEVICE_RINGING,
65         AST_DEVICE_RINGINUSE,
66         AST_DEVICE_ONHOLD,
67         AST_DEVICE_NOT_INUSE,
68         AST_DEVICE_NOT_INUSE,
69         AST_DEVICE_INUSE,
70         AST_DEVICE_BUSY,
71         AST_DEVICE_NOT_INUSE,
72         AST_DEVICE_NOT_INUSE,
73         AST_DEVICE_RINGING,
74         AST_DEVICE_RINGINUSE,
75         AST_DEVICE_ONHOLD,
76         AST_DEVICE_INUSE,
77         AST_DEVICE_INUSE,
78         AST_DEVICE_INUSE,
79         AST_DEVICE_BUSY,
80         AST_DEVICE_INUSE,
81         AST_DEVICE_INUSE,
82         AST_DEVICE_RINGINUSE,
83         AST_DEVICE_RINGINUSE,
84         AST_DEVICE_INUSE,
85         AST_DEVICE_BUSY,
86         AST_DEVICE_BUSY,
87         AST_DEVICE_BUSY,
88         AST_DEVICE_BUSY,
89         AST_DEVICE_BUSY,
90         AST_DEVICE_BUSY,
91         AST_DEVICE_RINGINUSE,
92         AST_DEVICE_RINGINUSE,
93         AST_DEVICE_BUSY,
94         AST_DEVICE_UNKNOWN,
95         AST_DEVICE_NOT_INUSE,
96         AST_DEVICE_INUSE,
97         AST_DEVICE_BUSY,
98         AST_DEVICE_INVALID,
99         AST_DEVICE_UNAVAILABLE,
100         AST_DEVICE_RINGING,
101         AST_DEVICE_RINGINUSE,
102         AST_DEVICE_ONHOLD,
103         AST_DEVICE_UNAVAILABLE,
104         AST_DEVICE_NOT_INUSE,
105         AST_DEVICE_INUSE,
106         AST_DEVICE_BUSY,
107         AST_DEVICE_UNAVAILABLE,
108         AST_DEVICE_UNAVAILABLE,
109         AST_DEVICE_RINGING,
110         AST_DEVICE_RINGINUSE,
111         AST_DEVICE_ONHOLD,
112         AST_DEVICE_RINGING,
113         AST_DEVICE_RINGING,
114         AST_DEVICE_RINGINUSE,
115         AST_DEVICE_RINGINUSE,
116         AST_DEVICE_RINGING,
117         AST_DEVICE_RINGING,
118         AST_DEVICE_RINGING,
119         AST_DEVICE_RINGINUSE,
120         AST_DEVICE_RINGINUSE,
121         AST_DEVICE_RINGINUSE,
122         AST_DEVICE_RINGINUSE,
123         AST_DEVICE_RINGINUSE,
124         AST_DEVICE_RINGINUSE,
125         AST_DEVICE_RINGINUSE,
126         AST_DEVICE_RINGINUSE,
127         AST_DEVICE_RINGINUSE,
128         AST_DEVICE_RINGINUSE,
129         AST_DEVICE_RINGINUSE,
130         AST_DEVICE_ONHOLD,
131         AST_DEVICE_ONHOLD,
132         AST_DEVICE_INUSE,
133         AST_DEVICE_BUSY,
134         AST_DEVICE_ONHOLD,
135         AST_DEVICE_ONHOLD,
136         AST_DEVICE_RINGINUSE,
137         AST_DEVICE_RINGINUSE,
138         AST_DEVICE_ONHOLD,
139 };
140
141 static int exten_results[] = {
142         AST_EXTENSION_NOT_INUSE,
143         AST_EXTENSION_NOT_INUSE,
144         AST_EXTENSION_INUSE,
145         AST_EXTENSION_BUSY,
146         AST_EXTENSION_NOT_INUSE,
147         AST_EXTENSION_UNAVAILABLE,
148         AST_EXTENSION_RINGING,
149         AST_EXTENSION_INUSE | AST_EXTENSION_RINGING,
150         AST_EXTENSION_ONHOLD,
151         AST_EXTENSION_NOT_INUSE,
152         AST_EXTENSION_NOT_INUSE,
153         AST_EXTENSION_INUSE,
154         AST_EXTENSION_BUSY,
155         AST_EXTENSION_NOT_INUSE,
156         AST_EXTENSION_NOT_INUSE,
157         AST_EXTENSION_RINGING,
158         AST_EXTENSION_INUSE | AST_EXTENSION_RINGING,
159         AST_EXTENSION_ONHOLD,
160         AST_EXTENSION_INUSE,
161         AST_EXTENSION_INUSE,
162         AST_EXTENSION_INUSE,
163         AST_EXTENSION_BUSY,
164         AST_EXTENSION_INUSE,
165         AST_EXTENSION_INUSE,
166         AST_EXTENSION_INUSE | AST_EXTENSION_RINGING,
167         AST_EXTENSION_INUSE | AST_EXTENSION_RINGING,
168         AST_EXTENSION_INUSE,
169         AST_EXTENSION_BUSY,
170         AST_EXTENSION_BUSY,
171         AST_EXTENSION_BUSY,
172         AST_EXTENSION_BUSY,
173         AST_EXTENSION_BUSY,
174         AST_EXTENSION_BUSY,
175         AST_EXTENSION_INUSE | AST_EXTENSION_RINGING,
176         AST_EXTENSION_INUSE | AST_EXTENSION_RINGING,
177         AST_EXTENSION_BUSY,
178         AST_EXTENSION_NOT_INUSE,
179         AST_EXTENSION_NOT_INUSE,
180         AST_EXTENSION_INUSE,
181         AST_EXTENSION_BUSY,
182         AST_EXTENSION_UNAVAILABLE,
183         AST_EXTENSION_UNAVAILABLE,
184         AST_EXTENSION_RINGING,
185         AST_EXTENSION_INUSE | AST_EXTENSION_RINGING,
186         AST_EXTENSION_ONHOLD,
187         AST_EXTENSION_UNAVAILABLE,
188         AST_EXTENSION_NOT_INUSE,
189         AST_EXTENSION_INUSE,
190         AST_EXTENSION_BUSY,
191         AST_EXTENSION_UNAVAILABLE,
192         AST_EXTENSION_UNAVAILABLE,
193         AST_EXTENSION_RINGING,
194         AST_EXTENSION_INUSE | AST_EXTENSION_RINGING,
195         AST_EXTENSION_ONHOLD,
196         AST_EXTENSION_RINGING,
197         AST_EXTENSION_RINGING,
198         AST_EXTENSION_INUSE | AST_EXTENSION_RINGING,
199         AST_EXTENSION_INUSE | AST_EXTENSION_RINGING,
200         AST_EXTENSION_RINGING,
201         AST_EXTENSION_RINGING,
202         AST_EXTENSION_RINGING,
203         AST_EXTENSION_INUSE | AST_EXTENSION_RINGING,
204         AST_EXTENSION_INUSE | AST_EXTENSION_RINGING,
205         AST_EXTENSION_INUSE | AST_EXTENSION_RINGING,
206         AST_EXTENSION_INUSE | AST_EXTENSION_RINGING,
207         AST_EXTENSION_INUSE | AST_EXTENSION_RINGING,
208         AST_EXTENSION_INUSE | AST_EXTENSION_RINGING,
209         AST_EXTENSION_INUSE | AST_EXTENSION_RINGING,
210         AST_EXTENSION_INUSE | AST_EXTENSION_RINGING,
211         AST_EXTENSION_INUSE | AST_EXTENSION_RINGING,
212         AST_EXTENSION_INUSE | AST_EXTENSION_RINGING,
213         AST_EXTENSION_INUSE | AST_EXTENSION_RINGING,
214         AST_EXTENSION_ONHOLD,
215         AST_EXTENSION_ONHOLD,
216         AST_EXTENSION_INUSE,
217         AST_EXTENSION_BUSY,
218         AST_EXTENSION_ONHOLD,
219         AST_EXTENSION_ONHOLD,
220         AST_EXTENSION_INUSE | AST_EXTENSION_RINGING,
221         AST_EXTENSION_INUSE | AST_EXTENSION_RINGING,
222         AST_EXTENSION_ONHOLD,
223 };
224
225 /*! \brief Mutex for \c update_cond */
226 AST_MUTEX_DEFINE_STATIC(update_lock);
227
228 /*! \brief Condition wait variable for device state updates */
229 static ast_cond_t update_cond;
230
231 /*! \brief Mutext for \c channel_cb_cond */
232 AST_MUTEX_DEFINE_STATIC(channel_cb_lock);
233
234 /*! \brief Condition wait variable for channel tech device state cb */
235 static ast_cond_t channel_cb_cond;
236
237 /*! \brief The resulting device state updates caused by some function call */
238 static AST_VECTOR(, enum ast_device_state) result_states;
239
240 /*! \brief The current device state for our device state provider */
241 static enum ast_device_state current_device_state;
242
243 /*! \brief Clear out all recorded device states in \ref result_states */
244 static void clear_result_states(void)
245 {
246         ast_mutex_lock(&update_lock);
247         while (AST_VECTOR_SIZE(&result_states) > 0) {
248                 AST_VECTOR_REMOVE_UNORDERED(&result_states, 0);
249         }
250         ast_mutex_unlock(&update_lock);
251 }
252
253 /*! \brief Stasis subscription callback for device state updates */
254 static void device_state_cb(void *data, struct stasis_subscription *sub, struct stasis_message *message)
255 {
256         struct ast_device_state_message *payload;
257         enum ast_device_state state;
258         const char *device;
259
260         if (stasis_message_type(message) != ast_device_state_message_type()) {
261                 return;
262         }
263
264         payload = stasis_message_data(message);
265         state = payload->state;
266         device = payload->device;
267
268         if (ast_strlen_zero(device)) {
269                 return;
270         }
271
272         /* Ignore aggregate events */
273         if (!payload->eid) {
274                 return;
275         }
276
277         if (strncasecmp(device, DEVSTATE_PROVIDER, DEVSTATE_PROVIDER_LEN)) {
278                 return;
279         }
280
281         ast_mutex_lock(&update_lock);
282         AST_VECTOR_APPEND(&result_states, state);
283         ast_cond_signal(&update_cond);
284         ast_mutex_unlock(&update_lock);
285 }
286
287 static enum ast_device_state devstate_prov_cb(const char *data)
288 {
289         return current_device_state;
290 }
291
292 static int wait_for_device_state_updates(struct ast_test *test, int expected_updates)
293 {
294         int error;
295         struct timeval wait_now = ast_tvnow();
296         struct timespec wait_time = { .tv_sec = wait_now.tv_sec + 1, .tv_nsec = wait_now.tv_usec * 1000 };
297
298         ast_mutex_lock(&update_lock);
299         while (AST_VECTOR_SIZE(&result_states) != expected_updates) {
300                 error = ast_cond_timedwait(&update_cond, &update_lock, &wait_time);
301                 if (error == ETIMEDOUT) {
302                         ast_test_status_update(test, "Test timed out while waiting for %d expected updates\n", expected_updates);
303                         break;
304                 }
305         }
306         ast_mutex_unlock(&update_lock);
307
308         ast_test_status_update(test, "Received %zu of %d updates\n", AST_VECTOR_SIZE(&result_states), expected_updates);
309         return !(AST_VECTOR_SIZE(&result_states) == expected_updates);
310 }
311
312 AST_TEST_DEFINE(device2extenstate_test)
313 {
314         int res = AST_TEST_PASS;
315         struct ast_devstate_aggregate agg;
316         enum ast_device_state i, j, combined;
317         enum ast_extension_states exten;
318         int k = 0;
319
320         switch (cmd) {
321         case TEST_INIT:
322                 info->name = "device2extenstate_test";
323                 info->category = "/main/devicestate/";
324                 info->summary = "Tests combined devstate mapping and device to extension state mapping.";
325                 info->description =
326                         "Verifies device state aggregate results match the expected combined "
327                         "devstate.  Then verifies the combined devstate maps to the expected "
328                         "extension state.";
329                 return AST_TEST_NOT_RUN;
330         case TEST_EXECUTE:
331                 break;
332         }
333
334         if (ARRAY_LEN(exten_results) != (AST_DEVICE_TOTAL * AST_DEVICE_TOTAL)) {
335                 ast_test_status_update(test, "Result array is %d long when it should be %d. "
336                         "Something has changed, this test must be updated.\n",
337                         (int) ARRAY_LEN(exten_results), (AST_DEVICE_TOTAL * AST_DEVICE_TOTAL));
338                 return AST_TEST_FAIL;
339         }
340
341         if (ARRAY_LEN(combined_results) != ARRAY_LEN(exten_results)) {
342                 ast_test_status_update(test, "combined_results and exten_results arrays do not match in length.\n");
343                 return AST_TEST_FAIL;
344         }
345
346         for (i = 0; i < AST_DEVICE_TOTAL; i++) {
347                 for (j = 0; j < AST_DEVICE_TOTAL; j++) {
348                         ast_devstate_aggregate_init(&agg);
349                         ast_devstate_aggregate_add(&agg, i);
350                         ast_devstate_aggregate_add(&agg, j);
351                         combined = ast_devstate_aggregate_result(&agg);
352                         if (combined_results[k] != combined) {
353                                 ast_test_status_update(test, "Expected combined dev state %s "
354                                         "does not match %s at combined_result[%d].\n",
355                                         ast_devstate2str(combined_results[k]),
356                                         ast_devstate2str(combined), k);
357                                 res = AST_TEST_FAIL;
358                         }
359
360                         exten = ast_devstate_to_extenstate(combined);
361
362                         if (exten_results[k] != exten) {
363                                 ast_test_status_update(test, "Expected exten state %s "
364                                         "does not match %s at exten_result[%d]\n",
365                                         ast_extension_state2str(exten_results[k]),
366                                         ast_extension_state2str(exten), k);
367                                 res = AST_TEST_FAIL;
368                         }
369                         k++;
370                 }
371         }
372
373         return res;
374 }
375
376 struct consumer {
377         ast_cond_t out;
378         int already_out;
379         int sig_on_non_aggregate_state;
380         int event_count;
381         enum ast_device_state state;
382         enum ast_device_state aggregate_state;
383 };
384
385 static void consumer_dtor(void *obj)
386 {
387         struct consumer *consumer = obj;
388
389         ast_cond_destroy(&consumer->out);
390 }
391
392 static void consumer_reset(struct consumer *consumer)
393 {
394         consumer->already_out = 0;
395         consumer->event_count = 0;
396         consumer->state = AST_DEVICE_TOTAL;
397         consumer->aggregate_state = AST_DEVICE_TOTAL;
398 }
399
400 static struct consumer *consumer_create(void)
401 {
402         struct consumer *consumer;
403
404         consumer = ao2_alloc(sizeof(*consumer), consumer_dtor);
405         if (!consumer) {
406                 return NULL;
407         }
408
409         ast_cond_init(&consumer->out, NULL);
410         consumer_reset(consumer);
411
412         return consumer;
413 }
414
415 static void consumer_exec(void *data, struct stasis_subscription *sub, struct stasis_message *message)
416 {
417         struct consumer *consumer = data;
418         struct stasis_cache_update *cache_update = stasis_message_data(message);
419         struct ast_device_state_message *device_state;
420
421         if (!cache_update->new_snapshot) {
422                 return;
423         }
424
425         device_state = stasis_message_data(cache_update->new_snapshot);
426
427         if (strcmp(device_state->device, UNIT_TEST_DEVICE_IDENTIFIER)) {
428                 /* not a device state we're interested in */
429                 return;
430         }
431
432         {
433                 SCOPED_AO2LOCK(lock, consumer);
434
435                 ++consumer->event_count;
436                 if (device_state->eid) {
437                         consumer->state = device_state->state;
438                         if (consumer->sig_on_non_aggregate_state) {
439                                 consumer->sig_on_non_aggregate_state = 0;
440                                 consumer->already_out = 1;
441                                 ast_cond_signal(&consumer->out);
442                         }
443                 } else {
444                         consumer->aggregate_state = device_state->state;
445                         consumer->already_out = 1;
446                         ast_cond_signal(&consumer->out);
447                 }
448         }
449 }
450
451 static void consumer_finalize(void *data, struct stasis_subscription *sub, struct stasis_message *message)
452 {
453         struct consumer *consumer = data;
454
455         if (stasis_subscription_final_message(sub, message)) {
456                 ao2_cleanup(consumer);
457         }
458 }
459
460 static void consumer_wait_for(struct consumer *consumer)
461 {
462         int res;
463         struct timeval start = ast_tvnow();
464         struct timespec end = {
465                 .tv_sec = start.tv_sec + 10,
466                 .tv_nsec = start.tv_usec * 1000
467         };
468
469         SCOPED_AO2LOCK(lock, consumer);
470
471         while (!consumer->already_out) {
472                 res = ast_cond_timedwait(&consumer->out, ao2_object_get_lockaddr(consumer), &end);
473                 if (!res || res == ETIMEDOUT) {
474                         break;
475                 }
476         }
477 }
478
479 static int remove_device_states_cb(void *obj, void *arg, int flags)
480 {
481         struct stasis_message *msg = obj;
482         struct ast_device_state_message *device_state = stasis_message_data(msg);
483
484         if (strcmp(UNIT_TEST_DEVICE_IDENTIFIER, device_state->device)) {
485                 /* Not a unit test device */
486                 return 0;
487         }
488
489         msg = stasis_cache_clear_create(msg);
490         if (msg) {
491                 /* topic guaranteed to have been created by this point */
492                 stasis_publish(ast_device_state_topic(device_state->device), msg);
493         }
494         ao2_cleanup(msg);
495         return 0;
496 }
497
498 static void cache_cleanup(int unused)
499 {
500         struct ao2_container *cache_dump;
501
502         /* remove all device states created during this test */
503         cache_dump = stasis_cache_dump_all(ast_device_state_cache(), NULL);
504         if (!cache_dump) {
505                 return;
506         }
507         ao2_callback(cache_dump, 0, remove_device_states_cb, NULL);
508         ao2_cleanup(cache_dump);
509 }
510
511 AST_TEST_DEFINE(device_state_aggregation_test)
512 {
513         RAII_VAR(struct consumer *, consumer, NULL, ao2_cleanup);
514         RAII_VAR(struct stasis_message_router *, device_msg_router, NULL, stasis_message_router_unsubscribe);
515         RAII_VAR(struct ast_eid *, foreign_eid, NULL, ast_free);
516         RAII_VAR(int, cleanup_cache, 0, cache_cleanup);
517         RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
518         int res;
519         struct ast_device_state_message *device_state;
520
521         switch (cmd) {
522         case TEST_INIT:
523                 info->name = "device_state_aggregation_test";
524                 info->category = "/main/devicestate/";
525                 info->summary = "Tests message routing and aggregation through the Stasis device state system.";
526                 info->description =
527                         "Verifies that the device state system passes "
528                         "messages appropriately, that the aggregator is "
529                         "working properly, that the aggregate results match "
530                         "the expected combined devstate, and that the cached "
531                         "aggregate devstate is correct.";
532                 return AST_TEST_NOT_RUN;
533         case TEST_EXECUTE:
534                 break;
535         }
536
537         foreign_eid = ast_malloc(sizeof(*foreign_eid));
538         ast_test_validate(test, NULL != foreign_eid);
539         memset(foreign_eid, 0xFF, sizeof(*foreign_eid));
540
541         consumer = consumer_create();
542         ast_test_validate(test, NULL != consumer);
543
544         device_msg_router = stasis_message_router_create(ast_device_state_topic_cached());
545         ast_test_validate(test, NULL != device_msg_router);
546
547         ao2_ref(consumer, +1);
548         res = stasis_message_router_add(device_msg_router, stasis_cache_update_type(), consumer_exec, consumer);
549         ast_test_validate(test, !res);
550
551         res = stasis_message_router_add(device_msg_router, stasis_subscription_change_type(), consumer_finalize, consumer);
552         ast_test_validate(test, !res);
553
554         /* push local state */
555         ast_publish_device_state(UNIT_TEST_DEVICE_IDENTIFIER, AST_DEVICE_NOT_INUSE, AST_DEVSTATE_CACHABLE);
556
557         /* Check cache aggregate state immediately */
558         ao2_cleanup(msg);
559         msg = stasis_cache_get_by_eid(ast_device_state_cache(), ast_device_state_message_type(), UNIT_TEST_DEVICE_IDENTIFIER, NULL);
560         device_state = stasis_message_data(msg);
561         ast_test_validate(test, AST_DEVICE_NOT_INUSE == device_state->state);
562
563         consumer_wait_for(consumer);
564         ast_test_validate(test, AST_DEVICE_NOT_INUSE == consumer->state);
565         ast_test_validate(test, AST_DEVICE_NOT_INUSE == consumer->aggregate_state);
566         ast_test_validate(test, 2 == consumer->event_count);
567         consumer_reset(consumer);
568
569         /* push remote state */
570         /* this will not produce a new aggregate state message since the aggregate state does not change */
571         consumer->sig_on_non_aggregate_state = 1;
572         ast_publish_device_state_full(UNIT_TEST_DEVICE_IDENTIFIER, AST_DEVICE_NOT_INUSE, AST_DEVSTATE_CACHABLE, foreign_eid);
573
574         /* Check cache aggregate state immediately */
575         ao2_cleanup(msg);
576         msg = stasis_cache_get_by_eid(ast_device_state_cache(), ast_device_state_message_type(), UNIT_TEST_DEVICE_IDENTIFIER, NULL);
577         device_state = stasis_message_data(msg);
578         ast_test_validate(test, AST_DEVICE_NOT_INUSE == device_state->state);
579
580         /* Check for expected events. */
581         consumer_wait_for(consumer);
582         ast_test_validate(test, AST_DEVICE_NOT_INUSE == consumer->state);
583         ast_test_validate(test, AST_DEVICE_TOTAL == consumer->aggregate_state);
584         ast_test_validate(test, 1 == consumer->event_count);
585         consumer_reset(consumer);
586
587         /* push remote state different from local state */
588         ast_publish_device_state_full(UNIT_TEST_DEVICE_IDENTIFIER, AST_DEVICE_INUSE, AST_DEVSTATE_CACHABLE, foreign_eid);
589
590         /* Check cache aggregate state immediately */
591         ao2_cleanup(msg);
592         msg = stasis_cache_get_by_eid(ast_device_state_cache(), ast_device_state_message_type(), UNIT_TEST_DEVICE_IDENTIFIER, NULL);
593         device_state = stasis_message_data(msg);
594         ast_test_validate(test, AST_DEVICE_INUSE == device_state->state);
595
596         /* Check for expected events. */
597         consumer_wait_for(consumer);
598         ast_test_validate(test, AST_DEVICE_INUSE == consumer->state);
599         ast_test_validate(test, AST_DEVICE_INUSE == consumer->aggregate_state);
600         ast_test_validate(test, 2 == consumer->event_count);
601         consumer_reset(consumer);
602
603         /* push local state that will cause aggregated state different from local non-aggregate state */
604         ast_publish_device_state(UNIT_TEST_DEVICE_IDENTIFIER, AST_DEVICE_RINGING, AST_DEVSTATE_CACHABLE);
605
606         /* Check cache aggregate state immediately */
607         ao2_cleanup(msg);
608         msg = stasis_cache_get_by_eid(ast_device_state_cache(), ast_device_state_message_type(), UNIT_TEST_DEVICE_IDENTIFIER, NULL);
609         device_state = stasis_message_data(msg);
610         ast_test_validate(test, AST_DEVICE_RINGINUSE == device_state->state);
611
612         /* Check for expected events. */
613         consumer_wait_for(consumer);
614         ast_test_validate(test, AST_DEVICE_RINGING == consumer->state);
615         ast_test_validate(test, AST_DEVICE_RINGINUSE == consumer->aggregate_state);
616         ast_test_validate(test, 2 == consumer->event_count);
617         consumer_reset(consumer);
618
619         return AST_TEST_PASS;
620 }
621
622 AST_TEST_DEFINE(devstate_prov_add)
623 {
624         switch (cmd) {
625         case TEST_INIT:
626                 info->name = __func__;
627                 info->category = "/main/devicestate/";
628                 info->summary = "Test adding a device state provider";
629                 info->description =
630                         "Test that a custom device state provider can be added, and that\n"
631                         "it cannot be added if already added.";
632                 return AST_TEST_NOT_RUN;
633         case TEST_EXECUTE:
634                 break;
635         }
636
637         ast_test_validate(test, ast_devstate_prov_add(DEVSTATE_PROVIDER, devstate_prov_cb) == 0);
638         ast_test_validate(test, ast_devstate_prov_add(DEVSTATE_PROVIDER, devstate_prov_cb) != 0);
639         ast_test_validate(test, ast_devstate_prov_del(DEVSTATE_PROVIDER) == 0);
640
641         return AST_TEST_PASS;
642 }
643
644 AST_TEST_DEFINE(devstate_prov_del)
645 {
646         switch (cmd) {
647         case TEST_INIT:
648                 info->name = __func__;
649                 info->category = "/main/devicestate/";
650                 info->summary = "Test removing a device state provider";
651                 info->description =
652                         "Test that a custom device state provider can be removed, and that\n"
653                         "it cannot be removed if already removed.";
654                 return AST_TEST_NOT_RUN;
655         case TEST_EXECUTE:
656                 break;
657         }
658
659         ast_test_validate(test, ast_devstate_prov_add(DEVSTATE_PROVIDER, devstate_prov_cb) == 0);
660         ast_test_validate(test, ast_devstate_prov_del(DEVSTATE_PROVIDER) == 0);
661         ast_test_validate(test, ast_devstate_prov_del(DEVSTATE_PROVIDER) != 0);
662
663         return AST_TEST_PASS;
664 }
665
666 AST_TEST_DEFINE(devstate_changed)
667 {
668         RAII_VAR(struct stasis_subscription *, sub, NULL, ao2_cleanup);
669         int i;
670         enum ast_device_state expected_results[] = {
671                 AST_DEVICE_NOT_INUSE,
672                 AST_DEVICE_INUSE,
673                 AST_DEVICE_BUSY,
674                 AST_DEVICE_INVALID,
675                 AST_DEVICE_UNAVAILABLE,
676                 AST_DEVICE_RINGING,
677                 AST_DEVICE_RINGINUSE,
678                 AST_DEVICE_ONHOLD,
679         };
680
681         switch (cmd) {
682         case TEST_INIT:
683                 info->name = __func__;
684                 info->category = "/main/devicestate/";
685                 info->summary = "Test updates coming from a device state provider";
686                 info->description =
687                         "This unit test checks that a custom device state provider can\n"
688                         "have updates published for it. This includes both cacheable and\n"
689                         "non-cacheable events. In the case of non-cacheable events, the\n"
690                         "device state provider's callback function is queried for the\n"
691                         "device state when AST_DEVICE_UNKNOWN is published.";
692                 return AST_TEST_NOT_RUN;
693         case TEST_EXECUTE:
694                 break;
695         }
696
697         ast_test_validate(test, (sub = stasis_subscribe(ast_device_state_topic_all(), device_state_cb, NULL)) != NULL);
698
699         clear_result_states();
700         current_device_state = AST_DEVICE_BUSY;
701
702         ast_test_validate(test, ast_devstate_prov_add(DEVSTATE_PROVIDER, devstate_prov_cb) == 0);
703
704         ast_test_validate(test, ast_devstate_changed_literal(AST_DEVICE_NOT_INUSE, AST_DEVSTATE_NOT_CACHABLE, DEVSTATE_PROVIDER ":foo") == 0);
705         ast_test_validate(test, ast_devstate_changed_literal(AST_DEVICE_INUSE, AST_DEVSTATE_NOT_CACHABLE, DEVSTATE_PROVIDER ":foo") == 0);
706         ast_test_validate(test, ast_devstate_changed_literal(AST_DEVICE_BUSY, AST_DEVSTATE_NOT_CACHABLE, DEVSTATE_PROVIDER ":foo") == 0);
707         ast_test_validate(test, ast_devstate_changed_literal(AST_DEVICE_INVALID, AST_DEVSTATE_NOT_CACHABLE, DEVSTATE_PROVIDER ":foo") == 0);
708         ast_test_validate(test, ast_devstate_changed_literal(AST_DEVICE_UNAVAILABLE, AST_DEVSTATE_NOT_CACHABLE, DEVSTATE_PROVIDER ":foo") == 0);
709         ast_test_validate(test, ast_devstate_changed_literal(AST_DEVICE_RINGING, AST_DEVSTATE_NOT_CACHABLE, DEVSTATE_PROVIDER ":foo") == 0);
710         ast_test_validate(test, ast_devstate_changed_literal(AST_DEVICE_RINGINUSE, AST_DEVSTATE_NOT_CACHABLE, DEVSTATE_PROVIDER ":foo") == 0);
711         ast_test_validate(test, ast_devstate_changed_literal(AST_DEVICE_ONHOLD, AST_DEVSTATE_NOT_CACHABLE, DEVSTATE_PROVIDER ":foo") == 0);
712
713         ast_test_validate(test, wait_for_device_state_updates(test, 8) == 0);
714
715         for (i = 0; i < AST_VECTOR_SIZE(&result_states); i++) {
716                 ast_test_status_update(test, "Testing update %d: actual is %d; expected is %d\n",
717                         i,
718                         AST_VECTOR_GET(&result_states, i),
719                         expected_results[i]);
720                 ast_test_validate(test, AST_VECTOR_GET(&result_states, i) == expected_results[i]);
721         }
722
723         sub = stasis_unsubscribe_and_join(sub);
724         clear_result_states();
725
726         /*
727          * Since an update of AST_DEVICE_UNKNOWN will cause a different thread to retrieve
728          * the update from the custom device state provider, check it separately from the
729          * updates above.
730          */
731         ast_test_validate(test, (sub = stasis_subscribe(ast_device_state_topic_all(), device_state_cb, NULL)) != NULL);
732         ast_test_validate(test, ast_devstate_changed_literal(AST_DEVICE_UNKNOWN, AST_DEVSTATE_NOT_CACHABLE, DEVSTATE_PROVIDER ":foo") == 0);
733         ast_test_validate(test, wait_for_device_state_updates(test, 1) == 0);
734
735         ast_test_validate(test, AST_VECTOR_GET(&result_states, 0) == AST_DEVICE_BUSY);
736         ast_test_validate(test, ast_device_state(DEVSTATE_PROVIDER ":foo") == AST_DEVICE_BUSY);
737         ast_test_validate(test, ast_device_state(DEVSTATE_PROVIDER_LC ":foo") == AST_DEVICE_BUSY);
738
739         sub = stasis_unsubscribe_and_join(sub);
740         clear_result_states();
741
742         ast_test_validate(test, (sub = stasis_subscribe(ast_device_state_topic_all(), device_state_cb, NULL)) != NULL);
743         ast_test_validate(test, ast_devstate_changed_literal(AST_DEVICE_NOT_INUSE, AST_DEVSTATE_CACHABLE, DEVSTATE_PROVIDER ":foo") == 0);
744         ast_test_validate(test, ast_devstate_changed_literal(AST_DEVICE_INUSE, AST_DEVSTATE_CACHABLE, DEVSTATE_PROVIDER ":foo") == 0);
745         ast_test_validate(test, ast_devstate_changed_literal(AST_DEVICE_BUSY, AST_DEVSTATE_CACHABLE, DEVSTATE_PROVIDER ":foo") == 0);
746         ast_test_validate(test, ast_devstate_changed_literal(AST_DEVICE_INVALID, AST_DEVSTATE_CACHABLE, DEVSTATE_PROVIDER ":foo") == 0);
747         ast_test_validate(test, ast_devstate_changed_literal(AST_DEVICE_UNAVAILABLE, AST_DEVSTATE_CACHABLE, DEVSTATE_PROVIDER ":foo") == 0);
748         ast_test_validate(test, ast_devstate_changed_literal(AST_DEVICE_RINGING, AST_DEVSTATE_CACHABLE, DEVSTATE_PROVIDER ":foo") == 0);
749         ast_test_validate(test, ast_devstate_changed_literal(AST_DEVICE_RINGINUSE, AST_DEVSTATE_CACHABLE, DEVSTATE_PROVIDER ":foo") == 0);
750         ast_test_validate(test, ast_devstate_changed_literal(AST_DEVICE_ONHOLD, AST_DEVSTATE_CACHABLE, DEVSTATE_PROVIDER ":foo") == 0);
751
752         ast_test_validate(test, wait_for_device_state_updates(test, 8) == 0);
753         for (i = 0; i < AST_VECTOR_SIZE(&result_states); i++) {
754                 ast_test_status_update(test, "Testing update %d: actual is %d; expected is %d\n",
755                         i,
756                         AST_VECTOR_GET(&result_states, i),
757                         expected_results[i]);
758                 ast_test_validate(test, AST_VECTOR_GET(&result_states, i) == expected_results[i]);
759         }
760
761         /*
762          * Check the last value in the cache. Note that this should not hit
763          * the value of current_device_state.
764          */
765         ast_test_validate(test, ast_device_state(DEVSTATE_PROVIDER ":foo") == AST_DEVICE_ONHOLD);
766         /*
767          * This will miss on the cache, as it is case sensitive. It should go
768          * hit our device state callback however.
769          */
770         ast_test_validate(test, ast_device_state(DEVSTATE_PROVIDER_LC ":foo") == AST_DEVICE_BUSY);
771
772         /* Generally, this test can't be run twice in a row, as you can't remove an
773          * item from the cache. Hence, subsequent runs won't hit the device state provider,
774          * and will merely return the cached value.
775          *
776          * To avoid annoying errors, set the last state to BUSY here.
777          */
778         ast_devstate_changed_literal(AST_DEVICE_BUSY, AST_DEVSTATE_CACHABLE, DEVSTATE_PROVIDER ":foo");
779
780         ast_test_validate(test, ast_devstate_prov_del(DEVSTATE_PROVIDER) == 0);
781
782         sub = stasis_unsubscribe_and_join(sub);
783         clear_result_states();
784
785         return AST_TEST_PASS;
786 }
787
788 AST_TEST_DEFINE(devstate_conversions)
789 {
790         switch (cmd) {
791         case TEST_INIT:
792                 info->name = __func__;
793                 info->category = "/main/devicestate/";
794                 info->summary = "Test ast_device_state conversions";
795                 info->description =
796                         "Test various transformations of ast_device_state values.";
797                 return AST_TEST_NOT_RUN;
798         case TEST_EXECUTE:
799                 break;
800         }
801
802         ast_test_validate(test, !strcmp(ast_devstate_str(AST_DEVICE_UNKNOWN), "UNKNOWN"));
803         ast_test_validate(test, !strcmp(ast_devstate_str(AST_DEVICE_NOT_INUSE), "NOT_INUSE"));
804         ast_test_validate(test, !strcmp(ast_devstate_str(AST_DEVICE_INUSE), "INUSE"));
805         ast_test_validate(test, !strcmp(ast_devstate_str(AST_DEVICE_BUSY), "BUSY"));
806         ast_test_validate(test, !strcmp(ast_devstate_str(AST_DEVICE_INVALID), "INVALID"));
807         ast_test_validate(test, !strcmp(ast_devstate_str(AST_DEVICE_UNAVAILABLE), "UNAVAILABLE"));
808         ast_test_validate(test, !strcmp(ast_devstate_str(AST_DEVICE_RINGING), "RINGING"));
809         ast_test_validate(test, !strcmp(ast_devstate_str(AST_DEVICE_RINGINUSE), "RINGINUSE"));
810         ast_test_validate(test, !strcmp(ast_devstate_str(AST_DEVICE_ONHOLD), "ONHOLD"));
811
812         ast_test_validate(test, ast_devstate_val("UNKNOWN") == AST_DEVICE_UNKNOWN);
813         ast_test_validate(test, ast_devstate_val("NOT_INUSE") == AST_DEVICE_NOT_INUSE);
814         ast_test_validate(test, ast_devstate_val("INUSE") == AST_DEVICE_INUSE);
815         ast_test_validate(test, ast_devstate_val("BUSY") == AST_DEVICE_BUSY);
816         ast_test_validate(test, ast_devstate_val("INVALID") == AST_DEVICE_INVALID);
817         ast_test_validate(test, ast_devstate_val("UNAVAILABLE") == AST_DEVICE_UNAVAILABLE);
818         ast_test_validate(test, ast_devstate_val("RINGING") == AST_DEVICE_RINGING);
819         ast_test_validate(test, ast_devstate_val("RINGINUSE") == AST_DEVICE_RINGINUSE);
820         ast_test_validate(test, ast_devstate_val("ONHOLD") == AST_DEVICE_ONHOLD);
821         ast_test_validate(test, ast_devstate_val("onhold") == AST_DEVICE_ONHOLD);
822         ast_test_validate(test, ast_devstate_val("FOO") == AST_DEVICE_UNKNOWN);
823
824         ast_test_validate(test, ast_state_chan2dev(AST_STATE_DOWN) == AST_DEVICE_NOT_INUSE);
825         ast_test_validate(test, ast_state_chan2dev(AST_STATE_RESERVED) == AST_DEVICE_INUSE);
826         ast_test_validate(test, ast_state_chan2dev(AST_STATE_OFFHOOK) == AST_DEVICE_INUSE);
827         ast_test_validate(test, ast_state_chan2dev(AST_STATE_DIALING) == AST_DEVICE_INUSE);
828         ast_test_validate(test, ast_state_chan2dev(AST_STATE_RING) == AST_DEVICE_INUSE);
829         ast_test_validate(test, ast_state_chan2dev(AST_STATE_RINGING) == AST_DEVICE_RINGING);
830         ast_test_validate(test, ast_state_chan2dev(AST_STATE_UP) == AST_DEVICE_INUSE);
831         ast_test_validate(test, ast_state_chan2dev(AST_STATE_BUSY) == AST_DEVICE_BUSY);
832         ast_test_validate(test, ast_state_chan2dev(AST_STATE_DIALING_OFFHOOK) == AST_DEVICE_INUSE);
833         ast_test_validate(test, ast_state_chan2dev(AST_STATE_PRERING) == AST_DEVICE_RINGING);
834
835         return AST_TEST_PASS;
836 }
837
838 /*! \brief Whether or not the channel device state callback was called */
839 static int chan_callback_called;
840
841 /*! \brief Wait until the test channel driver's devicestate callback is called */
842 static int wait_for_channel_callback(struct ast_test *test)
843 {
844         int error;
845         struct timeval wait_now = ast_tvnow();
846         struct timespec wait_time = { .tv_sec = wait_now.tv_sec + 1, .tv_nsec = wait_now.tv_usec * 1000 };
847
848         ast_mutex_lock(&channel_cb_lock);
849         while (!chan_callback_called) {
850                 error = ast_cond_timedwait(&channel_cb_cond, &channel_cb_lock, &wait_time);
851                 if (error == ETIMEDOUT) {
852                         ast_test_status_update(test, "Test timed out while waiting channel callback\n");
853                         break;
854                 }
855         }
856         ast_mutex_unlock(&channel_cb_lock);
857
858         return chan_callback_called;
859 }
860
861 static void safe_hangup(void *object)
862 {
863         struct ast_channel *chan = object;
864
865         if (!chan) {
866                 return;
867         }
868         ast_hangup(chan);
869 }
870
871 AST_TEST_DEFINE(devstate_channels)
872 {
873         RAII_VAR(struct ast_channel *, chan, NULL, safe_hangup);
874
875         switch (cmd) {
876         case TEST_INIT:
877                 info->name = __func__;
878                 info->category = "/main/devicestate/";
879                 info->summary = "Test deriving device state from a channel's state";
880                 info->description =
881                         "Test querying a channel's state to derive a device state.";
882                 return AST_TEST_NOT_RUN;
883         case TEST_EXECUTE:
884                 break;
885         }
886
887         chan_callback_called = 0;
888
889         chan = ast_channel_alloc(0, AST_STATE_RINGING, "", "", "", "s", "default",
890                 NULL, NULL, 0, DEVICE_STATE_CHANNEL_TYPE "/foo-%08x",
891                 (unsigned) ast_atomic_fetchadd_int((int *) &chan_idx, +1));
892         ast_test_validate(test, chan != NULL);
893
894         ast_test_validate(test, ast_parse_device_state(DEVICE_STATE_CHANNEL_TYPE "/foo") == AST_DEVICE_RINGING);
895         ast_test_validate(test, ast_parse_device_state(DEVICE_STATE_CHANNEL_TYPE "/bad") == AST_DEVICE_UNKNOWN);
896
897         ast_setstate(chan, AST_STATE_UP);
898
899         ast_test_validate(test, wait_for_channel_callback(test) == 1);
900         ast_test_validate(test, ast_parse_device_state(DEVICE_STATE_CHANNEL_TYPE "/foo") == AST_DEVICE_INUSE);
901
902         chan_callback_called = 0;
903
904         return AST_TEST_PASS;
905 }
906
907 static int chan_test_devicestate_cb(const char *device_number)
908 {
909         /* Simply record that we were called when expected */
910         chan_callback_called = 1;
911
912         ast_mutex_lock(&channel_cb_lock);
913         ast_cond_signal(&channel_cb_cond);
914         ast_mutex_unlock(&channel_cb_lock);
915
916         return AST_DEVICE_INUSE;
917 }
918
919 struct ast_channel_tech chan_test_devicestate = {
920         .type = DEVICE_STATE_CHANNEL_TYPE,
921         .description = "Device State Unit Test Channel Driver",
922         .devicestate = chan_test_devicestate_cb,
923 };
924
925 static int unload_module(void)
926 {
927         AST_VECTOR_FREE(&result_states);
928         ast_channel_unregister(&chan_test_devicestate);
929
930         AST_TEST_UNREGISTER(device2extenstate_test);
931         AST_TEST_UNREGISTER(device_state_aggregation_test);
932
933         AST_TEST_UNREGISTER(devstate_prov_add);
934         AST_TEST_UNREGISTER(devstate_prov_del);
935
936         AST_TEST_UNREGISTER(devstate_changed);
937         AST_TEST_UNREGISTER(devstate_conversions);
938
939         AST_TEST_UNREGISTER(devstate_channels);
940
941         return 0;
942 }
943
944 static int load_module(void)
945 {
946         if (AST_VECTOR_INIT(&result_states, 8) == -1) {
947                 return AST_MODULE_LOAD_DECLINE;
948         }
949
950         if (ast_channel_register(&chan_test_devicestate)) {
951                 AST_VECTOR_FREE(&result_states);
952                 return AST_MODULE_LOAD_DECLINE;
953         }
954
955         AST_TEST_REGISTER(device_state_aggregation_test);
956         AST_TEST_REGISTER(device2extenstate_test);
957
958         AST_TEST_REGISTER(devstate_prov_add);
959         AST_TEST_REGISTER(devstate_prov_del);
960
961         AST_TEST_REGISTER(devstate_changed);
962         AST_TEST_REGISTER(devstate_conversions);
963
964         AST_TEST_REGISTER(devstate_channels);
965
966         return AST_MODULE_LOAD_SUCCESS;
967 }
968
969 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Device State Test");