test_devicestate.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540
  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. #define UNIT_TEST_DEVICE_IDENTIFIER "unit_test_device_identifier"
  39. /* These arrays are the result of the 'core show device2extenstate' output. */
  40. static int combined_results[] = {
  41. AST_DEVICE_UNKNOWN,
  42. AST_DEVICE_NOT_INUSE,
  43. AST_DEVICE_INUSE,
  44. AST_DEVICE_BUSY,
  45. AST_DEVICE_UNKNOWN,
  46. AST_DEVICE_UNAVAILABLE,
  47. AST_DEVICE_RINGING,
  48. AST_DEVICE_RINGINUSE,
  49. AST_DEVICE_ONHOLD,
  50. AST_DEVICE_NOT_INUSE,
  51. AST_DEVICE_NOT_INUSE,
  52. AST_DEVICE_INUSE,
  53. AST_DEVICE_BUSY,
  54. AST_DEVICE_NOT_INUSE,
  55. AST_DEVICE_NOT_INUSE,
  56. AST_DEVICE_RINGING,
  57. AST_DEVICE_RINGINUSE,
  58. AST_DEVICE_ONHOLD,
  59. AST_DEVICE_INUSE,
  60. AST_DEVICE_INUSE,
  61. AST_DEVICE_INUSE,
  62. AST_DEVICE_BUSY,
  63. AST_DEVICE_INUSE,
  64. AST_DEVICE_INUSE,
  65. AST_DEVICE_RINGINUSE,
  66. AST_DEVICE_RINGINUSE,
  67. AST_DEVICE_INUSE,
  68. AST_DEVICE_BUSY,
  69. AST_DEVICE_BUSY,
  70. AST_DEVICE_BUSY,
  71. AST_DEVICE_BUSY,
  72. AST_DEVICE_BUSY,
  73. AST_DEVICE_BUSY,
  74. AST_DEVICE_RINGINUSE,
  75. AST_DEVICE_RINGINUSE,
  76. AST_DEVICE_BUSY,
  77. AST_DEVICE_UNKNOWN,
  78. AST_DEVICE_NOT_INUSE,
  79. AST_DEVICE_INUSE,
  80. AST_DEVICE_BUSY,
  81. AST_DEVICE_INVALID,
  82. AST_DEVICE_UNAVAILABLE,
  83. AST_DEVICE_RINGING,
  84. AST_DEVICE_RINGINUSE,
  85. AST_DEVICE_ONHOLD,
  86. AST_DEVICE_UNAVAILABLE,
  87. AST_DEVICE_NOT_INUSE,
  88. AST_DEVICE_INUSE,
  89. AST_DEVICE_BUSY,
  90. AST_DEVICE_UNAVAILABLE,
  91. AST_DEVICE_UNAVAILABLE,
  92. AST_DEVICE_RINGING,
  93. AST_DEVICE_RINGINUSE,
  94. AST_DEVICE_ONHOLD,
  95. AST_DEVICE_RINGING,
  96. AST_DEVICE_RINGING,
  97. AST_DEVICE_RINGINUSE,
  98. AST_DEVICE_RINGINUSE,
  99. AST_DEVICE_RINGING,
  100. AST_DEVICE_RINGING,
  101. AST_DEVICE_RINGING,
  102. AST_DEVICE_RINGINUSE,
  103. AST_DEVICE_RINGINUSE,
  104. AST_DEVICE_RINGINUSE,
  105. AST_DEVICE_RINGINUSE,
  106. AST_DEVICE_RINGINUSE,
  107. AST_DEVICE_RINGINUSE,
  108. AST_DEVICE_RINGINUSE,
  109. AST_DEVICE_RINGINUSE,
  110. AST_DEVICE_RINGINUSE,
  111. AST_DEVICE_RINGINUSE,
  112. AST_DEVICE_RINGINUSE,
  113. AST_DEVICE_ONHOLD,
  114. AST_DEVICE_ONHOLD,
  115. AST_DEVICE_INUSE,
  116. AST_DEVICE_BUSY,
  117. AST_DEVICE_ONHOLD,
  118. AST_DEVICE_ONHOLD,
  119. AST_DEVICE_RINGINUSE,
  120. AST_DEVICE_RINGINUSE,
  121. AST_DEVICE_ONHOLD,
  122. };
  123. static int exten_results[] = {
  124. AST_EXTENSION_NOT_INUSE,
  125. AST_EXTENSION_NOT_INUSE,
  126. AST_EXTENSION_INUSE,
  127. AST_EXTENSION_BUSY,
  128. AST_EXTENSION_NOT_INUSE,
  129. AST_EXTENSION_UNAVAILABLE,
  130. AST_EXTENSION_RINGING,
  131. AST_EXTENSION_INUSE | AST_EXTENSION_RINGING,
  132. AST_EXTENSION_ONHOLD,
  133. AST_EXTENSION_NOT_INUSE,
  134. AST_EXTENSION_NOT_INUSE,
  135. AST_EXTENSION_INUSE,
  136. AST_EXTENSION_BUSY,
  137. AST_EXTENSION_NOT_INUSE,
  138. AST_EXTENSION_NOT_INUSE,
  139. AST_EXTENSION_RINGING,
  140. AST_EXTENSION_INUSE | AST_EXTENSION_RINGING,
  141. AST_EXTENSION_ONHOLD,
  142. AST_EXTENSION_INUSE,
  143. AST_EXTENSION_INUSE,
  144. AST_EXTENSION_INUSE,
  145. AST_EXTENSION_BUSY,
  146. AST_EXTENSION_INUSE,
  147. AST_EXTENSION_INUSE,
  148. AST_EXTENSION_INUSE | AST_EXTENSION_RINGING,
  149. AST_EXTENSION_INUSE | AST_EXTENSION_RINGING,
  150. AST_EXTENSION_INUSE,
  151. AST_EXTENSION_BUSY,
  152. AST_EXTENSION_BUSY,
  153. AST_EXTENSION_BUSY,
  154. AST_EXTENSION_BUSY,
  155. AST_EXTENSION_BUSY,
  156. AST_EXTENSION_BUSY,
  157. AST_EXTENSION_INUSE | AST_EXTENSION_RINGING,
  158. AST_EXTENSION_INUSE | AST_EXTENSION_RINGING,
  159. AST_EXTENSION_BUSY,
  160. AST_EXTENSION_NOT_INUSE,
  161. AST_EXTENSION_NOT_INUSE,
  162. AST_EXTENSION_INUSE,
  163. AST_EXTENSION_BUSY,
  164. AST_EXTENSION_UNAVAILABLE,
  165. AST_EXTENSION_UNAVAILABLE,
  166. AST_EXTENSION_RINGING,
  167. AST_EXTENSION_INUSE | AST_EXTENSION_RINGING,
  168. AST_EXTENSION_ONHOLD,
  169. AST_EXTENSION_UNAVAILABLE,
  170. AST_EXTENSION_NOT_INUSE,
  171. AST_EXTENSION_INUSE,
  172. AST_EXTENSION_BUSY,
  173. AST_EXTENSION_UNAVAILABLE,
  174. AST_EXTENSION_UNAVAILABLE,
  175. AST_EXTENSION_RINGING,
  176. AST_EXTENSION_INUSE | AST_EXTENSION_RINGING,
  177. AST_EXTENSION_ONHOLD,
  178. AST_EXTENSION_RINGING,
  179. AST_EXTENSION_RINGING,
  180. AST_EXTENSION_INUSE | AST_EXTENSION_RINGING,
  181. AST_EXTENSION_INUSE | AST_EXTENSION_RINGING,
  182. AST_EXTENSION_RINGING,
  183. AST_EXTENSION_RINGING,
  184. AST_EXTENSION_RINGING,
  185. AST_EXTENSION_INUSE | AST_EXTENSION_RINGING,
  186. AST_EXTENSION_INUSE | AST_EXTENSION_RINGING,
  187. AST_EXTENSION_INUSE | AST_EXTENSION_RINGING,
  188. AST_EXTENSION_INUSE | AST_EXTENSION_RINGING,
  189. AST_EXTENSION_INUSE | AST_EXTENSION_RINGING,
  190. AST_EXTENSION_INUSE | AST_EXTENSION_RINGING,
  191. AST_EXTENSION_INUSE | 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_ONHOLD,
  197. AST_EXTENSION_ONHOLD,
  198. AST_EXTENSION_INUSE,
  199. AST_EXTENSION_BUSY,
  200. AST_EXTENSION_ONHOLD,
  201. AST_EXTENSION_ONHOLD,
  202. AST_EXTENSION_INUSE | AST_EXTENSION_RINGING,
  203. AST_EXTENSION_INUSE | AST_EXTENSION_RINGING,
  204. AST_EXTENSION_ONHOLD,
  205. };
  206. AST_TEST_DEFINE(device2extenstate_test)
  207. {
  208. int res = AST_TEST_PASS;
  209. struct ast_devstate_aggregate agg;
  210. enum ast_device_state i, j, combined;
  211. enum ast_extension_states exten;
  212. int k = 0;
  213. switch (cmd) {
  214. case TEST_INIT:
  215. info->name = "device2extenstate_test";
  216. info->category = "/main/devicestate/";
  217. info->summary = "Tests combined devstate mapping and device to extension state mapping.";
  218. info->description =
  219. "Verifies device state aggregate results match the expected combined "
  220. "devstate. Then verifies the combined devstate maps to the expected "
  221. "extension state.";
  222. return AST_TEST_NOT_RUN;
  223. case TEST_EXECUTE:
  224. break;
  225. }
  226. if (ARRAY_LEN(exten_results) != (AST_DEVICE_TOTAL * AST_DEVICE_TOTAL)) {
  227. ast_test_status_update(test, "Result array is %d long when it should be %d. "
  228. "Something has changed, this test must be updated.\n",
  229. (int) ARRAY_LEN(exten_results), (AST_DEVICE_TOTAL * AST_DEVICE_TOTAL));
  230. return AST_TEST_FAIL;
  231. }
  232. if (ARRAY_LEN(combined_results) != ARRAY_LEN(exten_results)) {
  233. ast_test_status_update(test, "combined_results and exten_results arrays do not match in length.\n");
  234. return AST_TEST_FAIL;
  235. }
  236. for (i = 0; i < AST_DEVICE_TOTAL; i++) {
  237. for (j = 0; j < AST_DEVICE_TOTAL; j++) {
  238. ast_devstate_aggregate_init(&agg);
  239. ast_devstate_aggregate_add(&agg, i);
  240. ast_devstate_aggregate_add(&agg, j);
  241. combined = ast_devstate_aggregate_result(&agg);
  242. if (combined_results[k] != combined) {
  243. ast_test_status_update(test, "Expected combined dev state %s "
  244. "does not match %s at combined_result[%d].\n",
  245. ast_devstate2str(combined_results[k]),
  246. ast_devstate2str(combined), k);
  247. res = AST_TEST_FAIL;
  248. }
  249. exten = ast_devstate_to_extenstate(combined);
  250. if (exten_results[k] != exten) {
  251. ast_test_status_update(test, "Expected exten state %s "
  252. "does not match %s at exten_result[%d]\n",
  253. ast_extension_state2str(exten_results[k]),
  254. ast_extension_state2str(exten), k);
  255. res = AST_TEST_FAIL;
  256. }
  257. k++;
  258. }
  259. }
  260. return res;
  261. }
  262. struct consumer {
  263. ast_cond_t out;
  264. int already_out;
  265. int sig_on_non_aggregate_state;
  266. int event_count;
  267. enum ast_device_state state;
  268. enum ast_device_state aggregate_state;
  269. };
  270. static void consumer_dtor(void *obj)
  271. {
  272. struct consumer *consumer = obj;
  273. ast_cond_destroy(&consumer->out);
  274. }
  275. static void consumer_reset(struct consumer *consumer)
  276. {
  277. consumer->already_out = 0;
  278. consumer->event_count = 0;
  279. consumer->state = AST_DEVICE_TOTAL;
  280. consumer->aggregate_state = AST_DEVICE_TOTAL;
  281. }
  282. static struct consumer *consumer_create(void)
  283. {
  284. struct consumer *consumer;
  285. consumer = ao2_alloc(sizeof(*consumer), consumer_dtor);
  286. if (!consumer) {
  287. return NULL;
  288. }
  289. ast_cond_init(&consumer->out, NULL);
  290. consumer_reset(consumer);
  291. return consumer;
  292. }
  293. static void consumer_exec(void *data, struct stasis_subscription *sub, struct stasis_message *message)
  294. {
  295. struct consumer *consumer = data;
  296. struct stasis_cache_update *cache_update = stasis_message_data(message);
  297. struct ast_device_state_message *device_state;
  298. if (!cache_update->new_snapshot) {
  299. return;
  300. }
  301. device_state = stasis_message_data(cache_update->new_snapshot);
  302. if (strcmp(device_state->device, UNIT_TEST_DEVICE_IDENTIFIER)) {
  303. /* not a device state we're interested in */
  304. return;
  305. }
  306. {
  307. SCOPED_AO2LOCK(lock, consumer);
  308. ++consumer->event_count;
  309. if (device_state->eid) {
  310. consumer->state = device_state->state;
  311. if (consumer->sig_on_non_aggregate_state) {
  312. consumer->sig_on_non_aggregate_state = 0;
  313. consumer->already_out = 1;
  314. ast_cond_signal(&consumer->out);
  315. }
  316. } else {
  317. consumer->aggregate_state = device_state->state;
  318. consumer->already_out = 1;
  319. ast_cond_signal(&consumer->out);
  320. }
  321. }
  322. }
  323. static void consumer_finalize(void *data, struct stasis_subscription *sub, struct stasis_message *message)
  324. {
  325. struct consumer *consumer = data;
  326. if (stasis_subscription_final_message(sub, message)) {
  327. ao2_cleanup(consumer);
  328. }
  329. }
  330. static void consumer_wait_for(struct consumer *consumer)
  331. {
  332. int res;
  333. struct timeval start = ast_tvnow();
  334. struct timespec end = {
  335. .tv_sec = start.tv_sec + 10,
  336. .tv_nsec = start.tv_usec * 1000
  337. };
  338. SCOPED_AO2LOCK(lock, consumer);
  339. while (!consumer->already_out) {
  340. res = ast_cond_timedwait(&consumer->out, ao2_object_get_lockaddr(consumer), &end);
  341. if (!res || res == ETIMEDOUT) {
  342. break;
  343. }
  344. }
  345. }
  346. static int remove_device_states_cb(void *obj, void *arg, int flags)
  347. {
  348. struct stasis_message *msg = obj;
  349. struct ast_device_state_message *device_state = stasis_message_data(msg);
  350. if (strcmp(UNIT_TEST_DEVICE_IDENTIFIER, device_state->device)) {
  351. /* Not a unit test device */
  352. return 0;
  353. }
  354. msg = stasis_cache_clear_create(msg);
  355. if (msg) {
  356. /* topic guaranteed to have been created by this point */
  357. stasis_publish(ast_device_state_topic(device_state->device), msg);
  358. }
  359. ao2_cleanup(msg);
  360. return 0;
  361. }
  362. static void cache_cleanup(int unused)
  363. {
  364. struct ao2_container *cache_dump;
  365. /* remove all device states created during this test */
  366. cache_dump = stasis_cache_dump_all(ast_device_state_cache(), NULL);
  367. if (!cache_dump) {
  368. return;
  369. }
  370. ao2_callback(cache_dump, 0, remove_device_states_cb, NULL);
  371. ao2_cleanup(cache_dump);
  372. }
  373. AST_TEST_DEFINE(device_state_aggregation_test)
  374. {
  375. RAII_VAR(struct consumer *, consumer, NULL, ao2_cleanup);
  376. RAII_VAR(struct stasis_message_router *, device_msg_router, NULL, stasis_message_router_unsubscribe);
  377. RAII_VAR(struct ast_eid *, foreign_eid, NULL, ast_free);
  378. RAII_VAR(int, cleanup_cache, 0, cache_cleanup);
  379. RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
  380. int res;
  381. struct ast_device_state_message *device_state;
  382. switch (cmd) {
  383. case TEST_INIT:
  384. info->name = "device_state_aggregation_test";
  385. info->category = "/main/devicestate/";
  386. info->summary = "Tests message routing and aggregation through the Stasis device state system.";
  387. info->description =
  388. "Verifies that the device state system passes "
  389. "messages appropriately, that the aggregator is "
  390. "working properly, that the aggregate results match "
  391. "the expected combined devstate, and that the cached "
  392. "aggregate devstate is correct.";
  393. return AST_TEST_NOT_RUN;
  394. case TEST_EXECUTE:
  395. break;
  396. }
  397. foreign_eid = ast_malloc(sizeof(*foreign_eid));
  398. ast_test_validate(test, NULL != foreign_eid);
  399. memset(foreign_eid, 0xFF, sizeof(*foreign_eid));
  400. consumer = consumer_create();
  401. ast_test_validate(test, NULL != consumer);
  402. device_msg_router = stasis_message_router_create(ast_device_state_topic_cached());
  403. ast_test_validate(test, NULL != device_msg_router);
  404. ao2_ref(consumer, +1);
  405. res = stasis_message_router_add(device_msg_router, stasis_cache_update_type(), consumer_exec, consumer);
  406. ast_test_validate(test, !res);
  407. res = stasis_message_router_add(device_msg_router, stasis_subscription_change_type(), consumer_finalize, consumer);
  408. ast_test_validate(test, !res);
  409. /* push local state */
  410. ast_publish_device_state(UNIT_TEST_DEVICE_IDENTIFIER, AST_DEVICE_NOT_INUSE, AST_DEVSTATE_CACHABLE);
  411. /* Check cache aggregate state immediately */
  412. ao2_cleanup(msg);
  413. msg = stasis_cache_get_by_eid(ast_device_state_cache(), ast_device_state_message_type(), UNIT_TEST_DEVICE_IDENTIFIER, NULL);
  414. device_state = stasis_message_data(msg);
  415. ast_test_validate(test, AST_DEVICE_NOT_INUSE == device_state->state);
  416. consumer_wait_for(consumer);
  417. ast_test_validate(test, AST_DEVICE_NOT_INUSE == consumer->state);
  418. ast_test_validate(test, AST_DEVICE_NOT_INUSE == consumer->aggregate_state);
  419. ast_test_validate(test, 2 == consumer->event_count);
  420. consumer_reset(consumer);
  421. /* push remote state */
  422. /* this will not produce a new aggregate state message since the aggregate state does not change */
  423. consumer->sig_on_non_aggregate_state = 1;
  424. ast_publish_device_state_full(UNIT_TEST_DEVICE_IDENTIFIER, AST_DEVICE_NOT_INUSE, AST_DEVSTATE_CACHABLE, foreign_eid);
  425. /* Check cache aggregate state immediately */
  426. ao2_cleanup(msg);
  427. msg = stasis_cache_get_by_eid(ast_device_state_cache(), ast_device_state_message_type(), UNIT_TEST_DEVICE_IDENTIFIER, NULL);
  428. device_state = stasis_message_data(msg);
  429. ast_test_validate(test, AST_DEVICE_NOT_INUSE == device_state->state);
  430. /* Check for expected events. */
  431. consumer_wait_for(consumer);
  432. ast_test_validate(test, AST_DEVICE_NOT_INUSE == consumer->state);
  433. ast_test_validate(test, AST_DEVICE_TOTAL == consumer->aggregate_state);
  434. ast_test_validate(test, 1 == consumer->event_count);
  435. consumer_reset(consumer);
  436. /* push remote state different from local state */
  437. ast_publish_device_state_full(UNIT_TEST_DEVICE_IDENTIFIER, AST_DEVICE_INUSE, AST_DEVSTATE_CACHABLE, foreign_eid);
  438. /* Check cache aggregate state immediately */
  439. ao2_cleanup(msg);
  440. msg = stasis_cache_get_by_eid(ast_device_state_cache(), ast_device_state_message_type(), UNIT_TEST_DEVICE_IDENTIFIER, NULL);
  441. device_state = stasis_message_data(msg);
  442. ast_test_validate(test, AST_DEVICE_INUSE == device_state->state);
  443. /* Check for expected events. */
  444. consumer_wait_for(consumer);
  445. ast_test_validate(test, AST_DEVICE_INUSE == consumer->state);
  446. ast_test_validate(test, AST_DEVICE_INUSE == consumer->aggregate_state);
  447. ast_test_validate(test, 2 == consumer->event_count);
  448. consumer_reset(consumer);
  449. /* push local state that will cause aggregated state different from local non-aggregate state */
  450. ast_publish_device_state(UNIT_TEST_DEVICE_IDENTIFIER, AST_DEVICE_RINGING, AST_DEVSTATE_CACHABLE);
  451. /* Check cache aggregate state immediately */
  452. ao2_cleanup(msg);
  453. msg = stasis_cache_get_by_eid(ast_device_state_cache(), ast_device_state_message_type(), UNIT_TEST_DEVICE_IDENTIFIER, NULL);
  454. device_state = stasis_message_data(msg);
  455. ast_test_validate(test, AST_DEVICE_RINGINUSE == device_state->state);
  456. /* Check for expected events. */
  457. consumer_wait_for(consumer);
  458. ast_test_validate(test, AST_DEVICE_RINGING == consumer->state);
  459. ast_test_validate(test, AST_DEVICE_RINGINUSE == consumer->aggregate_state);
  460. ast_test_validate(test, 2 == consumer->event_count);
  461. consumer_reset(consumer);
  462. return AST_TEST_PASS;
  463. }
  464. static int unload_module(void)
  465. {
  466. AST_TEST_UNREGISTER(device2extenstate_test);
  467. AST_TEST_UNREGISTER(device_state_aggregation_test);
  468. return 0;
  469. }
  470. static int load_module(void)
  471. {
  472. AST_TEST_REGISTER(device_state_aggregation_test);
  473. AST_TEST_REGISTER(device2extenstate_test);
  474. return AST_MODULE_LOAD_SUCCESS;
  475. }
  476. AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Device State Test");