test_devicestate.c 31 KB

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