parking_tests.c 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878
  1. /*
  2. * Asterisk -- An open source telephony toolkit.
  3. *
  4. * Copyright (C) 2013, Digium, Inc.
  5. *
  6. * Jonathan Rose <jrose@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. /*! \file
  19. *
  20. * \brief Call Parking Unit Tests
  21. *
  22. * \author Jonathan Rose <jrose@digium.com>
  23. */
  24. #include "asterisk.h"
  25. ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
  26. #include "res_parking.h"
  27. #include "asterisk/utils.h"
  28. #include "asterisk/module.h"
  29. #include "asterisk/astobj2.h"
  30. #include "asterisk/test.h"
  31. #include "asterisk/stringfields.h"
  32. #include "asterisk/time.h"
  33. #include "asterisk/causes.h"
  34. #include "asterisk/pbx.h"
  35. #include "asterisk/format_cache.h"
  36. #if defined(TEST_FRAMEWORK)
  37. #define TEST_CATEGORY "/res/parking/"
  38. #define CHANNEL_TECH_NAME "ParkingTestChannel"
  39. static const struct ast_party_caller alice_callerid = {
  40. .id.name.str = "Alice",
  41. .id.name.valid = 1,
  42. .id.number.str = "100",
  43. .id.number.valid = 1,
  44. };
  45. static int parking_test_write(struct ast_channel *chan, struct ast_frame *frame)
  46. {
  47. return 0;
  48. }
  49. static struct ast_frame *parking_test_read(struct ast_channel *chan)
  50. {
  51. return &ast_null_frame;
  52. }
  53. static const struct ast_channel_tech parking_test_tech = {
  54. .type = CHANNEL_TECH_NAME,
  55. .description = "Parking unit test technology",
  56. .write = parking_test_write,
  57. .read = parking_test_read,
  58. };
  59. /*! \brief Set ulaw format on the channel */
  60. static int set_test_formats(struct ast_channel *chan)
  61. {
  62. struct ast_format_cap *caps;
  63. caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
  64. if (!caps) {
  65. return -1;
  66. }
  67. ast_format_cap_append(caps, ast_format_ulaw, 0);
  68. ast_channel_nativeformats_set(chan, caps);
  69. ast_channel_set_writeformat(chan, ast_format_ulaw);
  70. ast_channel_set_rawwriteformat(chan, ast_format_ulaw);
  71. ast_channel_set_readformat(chan, ast_format_ulaw);
  72. ast_channel_set_rawreadformat(chan, ast_format_ulaw);
  73. ao2_ref(caps, -1);
  74. return 0;
  75. }
  76. /*! \brief Create a \ref test_cdr_chan_tech for Alice */
  77. static struct ast_channel *create_alice_channel(void)
  78. {
  79. struct ast_channel *alice = ast_channel_alloc(0, AST_STATE_DOWN,
  80. "100", "Alice", "100", "100", "default", NULL, NULL, 0,
  81. CHANNEL_TECH_NAME "/Alice");
  82. if (!alice) {
  83. return NULL;
  84. }
  85. if (set_test_formats(alice)) {
  86. ast_channel_unlock(alice);
  87. ast_channel_release(alice);
  88. return NULL;
  89. }
  90. ast_channel_tech_set(alice, &parking_test_tech);
  91. ast_channel_set_caller(alice, &alice_callerid, NULL);
  92. ast_channel_unlock(alice);
  93. return alice;
  94. }
  95. /*! \brief Hang up a test channel safely */
  96. static struct ast_channel *hangup_channel(struct ast_channel *chan, int hangup_cause)
  97. {
  98. ast_channel_hangupcause_set(chan, hangup_cause);
  99. ast_hangup(chan);
  100. return NULL;
  101. }
  102. static void safe_channel_release(struct ast_channel *chan)
  103. {
  104. if (!chan) {
  105. return;
  106. }
  107. ast_channel_release(chan);
  108. }
  109. static void do_sleep(struct timespec *to_sleep)
  110. {
  111. while ((nanosleep(to_sleep, to_sleep) == -1) && (errno == EINTR)) {
  112. }
  113. }
  114. static int fake_fixup(struct ast_channel *clonechan, struct ast_channel *original)
  115. {
  116. return 0;
  117. }
  118. static const struct ast_channel_tech fake_tech = {
  119. .fixup = fake_fixup, /* silence warning from masquerade... though those shouldn't be happening now */
  120. };
  121. #define TEST_LOT_NAME "unit_tests_res_parking_test_lot"
  122. static struct parking_lot *generate_test_parking_lot(const char *name, int low_space, int high_space, const char *park_exten, const char *park_context, struct ast_test *test)
  123. {
  124. RAII_VAR(struct parking_lot_cfg *, test_cfg, NULL, ao2_cleanup);
  125. struct parking_lot *test_lot;
  126. test_cfg = parking_lot_cfg_create(name);
  127. if (!test_cfg) {
  128. return NULL;
  129. }
  130. test_cfg->parking_start = low_space;
  131. test_cfg->parking_stop = high_space;
  132. test_cfg->parkingtime = 10;
  133. test_cfg->comebackdialtime = 10;
  134. test_cfg->parkfindnext = 1;
  135. test_cfg->parkext_exclusive = 1;
  136. ast_string_field_set(test_cfg, parkext, park_exten);
  137. ast_string_field_set(test_cfg, parking_con, park_context);
  138. ast_string_field_set(test_cfg, comebackcontext, "unit_test_res_parking_create_lot_comeback");
  139. if (parking_lot_cfg_create_extensions(test_cfg)) {
  140. ast_test_status_update(test, "Extensions for parking lot '%s' could not be registered. Extension Creation failed.\n", name);
  141. return NULL;
  142. }
  143. test_lot = parking_lot_build_or_update(test_cfg, 1);
  144. if (!test_lot) {
  145. return NULL;
  146. }
  147. return test_lot;
  148. }
  149. static int dispose_test_lot(struct parking_lot *test_lot, int expect_destruction)
  150. {
  151. RAII_VAR(struct parking_lot *, found_lot, NULL, ao2_cleanup);
  152. test_lot->mode = PARKINGLOT_DISABLED;
  153. parking_lot_remove_if_unused(test_lot);
  154. found_lot = parking_lot_find_by_name(test_lot->name);
  155. if ((expect_destruction && !found_lot) || (!expect_destruction && found_lot)) {
  156. return 0;
  157. }
  158. return -1;
  159. }
  160. AST_TEST_DEFINE(create_lot)
  161. {
  162. RAII_VAR(struct parking_lot *, test_lot, NULL, ao2_cleanup);
  163. RAII_VAR(struct parking_lot *, found_copy, NULL, ao2_cleanup);
  164. switch (cmd) {
  165. case TEST_INIT:
  166. info->name = "create_lot";
  167. info->category = TEST_CATEGORY;
  168. info->summary = "Parking lot creation";
  169. info->description =
  170. "Creates a parking lot and then disposes of it.";
  171. return AST_TEST_NOT_RUN;
  172. case TEST_EXECUTE:
  173. break;
  174. }
  175. ast_test_status_update(test, "Creating test parking lot '%s'\n", TEST_LOT_NAME);
  176. test_lot = generate_test_parking_lot(TEST_LOT_NAME, 701, 703, NULL, "unit_test_res_parking_create_lot_con", test);
  177. if (!test_lot) {
  178. ast_test_status_update(test, "Failed to create test parking lot. Test Failed\n");
  179. return AST_TEST_FAIL;
  180. }
  181. ast_test_status_update(test, "Successfully created parking lot. Retrieving test parking lot from container.\n");
  182. found_copy = parking_lot_find_by_name(TEST_LOT_NAME);
  183. if (!found_copy) {
  184. ast_test_status_update(test, "Failed to find parking lot in the parking lot container. Test failed.\n");
  185. dispose_test_lot(test_lot, 1);
  186. return AST_TEST_FAIL;
  187. }
  188. ast_test_status_update(test, "Successfully retrieved parking lot. Removing test parking lot from container.\n");
  189. if (dispose_test_lot(found_copy, 1)) {
  190. ast_test_status_update(test, "Found parking lot in container after attempted removal. Test failed.\n");
  191. }
  192. ast_test_status_update(test, "Parking lot was successfully removed from the container. Test complete.\n");
  193. return AST_TEST_PASS;
  194. }
  195. AST_TEST_DEFINE(park_call)
  196. {
  197. RAII_VAR(struct parking_lot *, test_lot, NULL, ao2_cleanup);
  198. RAII_VAR(struct ast_channel *, chan_alice, NULL, safe_channel_release);
  199. RAII_VAR(struct ast_bridge *, parking_bridge, NULL, ao2_cleanup);
  200. struct timespec to_sleep = {1, 0};
  201. switch (cmd) {
  202. case TEST_INIT:
  203. info->name = "park_channel";
  204. info->category = TEST_CATEGORY;
  205. info->summary = "Park a Channel";
  206. info->description =
  207. "Creates a parking lot, parks a channel in it, then removes it from the parking lot bridge.";
  208. return AST_TEST_NOT_RUN;
  209. case TEST_EXECUTE:
  210. break;
  211. }
  212. ast_test_status_update(test, "Creating test parking lot '%s'\n", TEST_LOT_NAME);
  213. test_lot = generate_test_parking_lot(TEST_LOT_NAME, 701, 703, NULL, "unit_test_res_parking_create_lot_con", test);
  214. if (!test_lot) {
  215. ast_test_status_update(test, "Failed to create test parking lot. Test failed.\n");
  216. return AST_TEST_FAIL;
  217. }
  218. chan_alice = create_alice_channel();
  219. if (!chan_alice) {
  220. ast_test_status_update(test, "Failed to create test channel to park. Test failed.\n");
  221. dispose_test_lot(test_lot, 1);
  222. return AST_TEST_FAIL;
  223. }
  224. ast_channel_state_set(chan_alice, AST_STATE_UP);
  225. pbx_builtin_setvar_helper(chan_alice, "BLINDTRANSFER", ast_channel_name(chan_alice));
  226. parking_bridge = park_application_setup(chan_alice, chan_alice, TEST_LOT_NAME, NULL);
  227. if (!parking_bridge) {
  228. ast_test_status_update(test, "Failed to get the parking bridge for '%s'. Test failed.\n", TEST_LOT_NAME);
  229. dispose_test_lot(test_lot, 1);
  230. return AST_TEST_FAIL;
  231. }
  232. if (ast_bridge_impart(parking_bridge, chan_alice, NULL, NULL,
  233. AST_BRIDGE_IMPART_CHAN_DEPARTABLE)) {
  234. ast_test_status_update(test, "Failed to impart alice into parking lot. Test failed.\n");
  235. dispose_test_lot(test_lot, 1);
  236. return AST_TEST_FAIL;
  237. }
  238. do_sleep(&to_sleep);
  239. ast_bridge_depart(chan_alice);
  240. chan_alice = hangup_channel(chan_alice, AST_CAUSE_NORMAL);
  241. if (dispose_test_lot(test_lot, 1)) {
  242. ast_test_status_update(test, "Found parking lot in container after attempted removal. Test failed.\n");
  243. return AST_TEST_FAIL;
  244. }
  245. return AST_TEST_PASS;
  246. }
  247. static int parked_users_match(const struct parked_user *actual, const struct parked_user *expected, struct ast_test *test)
  248. {
  249. if (expected->parking_space != actual->parking_space) {
  250. ast_test_status_update(test, "parking_space expected: %d - got: %d\n", expected->parking_space, actual->parking_space);
  251. return 0;
  252. }
  253. if (strcmp(expected->parker_dial_string, actual->parker_dial_string)) {
  254. ast_test_status_update(test, "parker_dial_string expected: %s - got: %s\n", expected->parker_dial_string, actual->parker_dial_string);
  255. return 0;
  256. }
  257. if (expected->time_limit != actual->time_limit) {
  258. ast_test_status_update(test, "time_limit expected: %u - got: %u\n", expected->time_limit, actual->time_limit);
  259. return 0;
  260. }
  261. if (expected->resolution != actual->resolution) {
  262. ast_test_status_update(test, "resolution expected: %u - got: %u\n", expected->resolution, actual->resolution);
  263. return 0;
  264. }
  265. return 1;
  266. }
  267. static int parking_lot_cfgs_match(const struct parking_lot_cfg *actual, const struct parking_lot_cfg *expected, struct ast_test *test)
  268. {
  269. if (expected->parking_start != actual->parking_start) {
  270. ast_test_status_update(test, "parking_start expected: %d - got: %d\n", expected->parking_start, actual->parking_start);
  271. return 0;
  272. }
  273. if (expected->parking_stop != actual->parking_stop) {
  274. ast_test_status_update(test, "parking_stop expected: %d - got: %d\n", expected->parking_stop, actual->parking_stop);
  275. return 0;
  276. }
  277. if (expected->parkingtime != actual->parkingtime) {
  278. ast_test_status_update(test, "parkingtime expected: %u - got: %u\n", expected->parkingtime, actual->parkingtime);
  279. return 0;
  280. }
  281. if (expected->comebackdialtime != actual->comebackdialtime) {
  282. ast_test_status_update(test, "comebackdialtime expected: %u - got: %u\n", expected->comebackdialtime, actual->comebackdialtime);
  283. return 0;
  284. }
  285. if (expected->parkfindnext != actual->parkfindnext) {
  286. ast_test_status_update(test, "parkfindnext expected: %u - got: %u\n", expected->parkfindnext, actual->parkfindnext);
  287. return 0;
  288. }
  289. if (expected->parkext_exclusive != actual->parkext_exclusive) {
  290. ast_test_status_update(test, "parkext_exclusive expected: %u - got: %u\n", expected->parkext_exclusive, actual->parkext_exclusive);
  291. return 0;
  292. }
  293. if (strcmp(expected->parkext, actual->parkext)) {
  294. ast_test_status_update(test, "parkext expected: %s - got: %s\n", expected->parkext, actual->parkext);
  295. return 0;
  296. }
  297. if (strcmp(expected->parking_con, actual->parking_con)) {
  298. ast_test_status_update(test, "parking_con expected: %s - got: %s\n", expected->parking_con, actual->parking_con);
  299. return 0;
  300. }
  301. if (strcmp(expected->comebackcontext, actual->comebackcontext)) {
  302. ast_test_status_update(test, "comebackcontext expected: %s - got: %s\n", expected->comebackcontext, actual->comebackcontext);
  303. return 0;
  304. }
  305. return 1;
  306. }
  307. AST_TEST_DEFINE(retrieve_call)
  308. {
  309. RAII_VAR(struct parking_lot *, test_lot, NULL, ao2_cleanup);
  310. RAII_VAR(struct ast_channel *, chan_alice, NULL, safe_channel_release);
  311. RAII_VAR(struct ast_bridge *, parking_bridge, NULL, ao2_cleanup);
  312. RAII_VAR(struct parked_user *, retrieved_user, NULL, ao2_cleanup);
  313. struct timespec to_sleep = {1, 0};
  314. int failure = 0;
  315. static const struct parked_user expected_user = {
  316. .parking_space = 701,
  317. .parker_dial_string = "ParkingTestChannel/Alice",
  318. .time_limit = 10,
  319. .resolution = PARK_ANSWERED,
  320. };
  321. switch (cmd) {
  322. case TEST_INIT:
  323. info->name = "park_retrieve";
  324. info->category = TEST_CATEGORY;
  325. info->summary = "Retrieve a parked channel";
  326. info->description =
  327. "Creates a parking lot, parks a channel in it, then removes it from the parking lot bridge.";
  328. return AST_TEST_NOT_RUN;
  329. case TEST_EXECUTE:
  330. break;
  331. }
  332. ast_test_status_update(test, "Creating test parking lot '%s'\n", TEST_LOT_NAME);
  333. test_lot = generate_test_parking_lot(TEST_LOT_NAME, 701, 703, NULL, "unit_test_res_parking_create_lot_con", test);
  334. if (!test_lot) {
  335. ast_test_status_update(test, "Failed to create test parking lot. Test failed.\n");
  336. return AST_TEST_FAIL;
  337. }
  338. chan_alice = create_alice_channel();
  339. if (!chan_alice) {
  340. ast_test_status_update(test, "Failed to create test channel to park. Test failed.\n");
  341. dispose_test_lot(test_lot, 1);
  342. return AST_TEST_FAIL;
  343. }
  344. ast_channel_state_set(chan_alice, AST_STATE_UP);
  345. pbx_builtin_setvar_helper(chan_alice, "BLINDTRANSFER", ast_channel_name(chan_alice));
  346. parking_bridge = park_application_setup(chan_alice, chan_alice, TEST_LOT_NAME, NULL);
  347. if (!parking_bridge) {
  348. ast_test_status_update(test, "Failed to get the parking bridge for '%s'. Test failed.\n", TEST_LOT_NAME);
  349. dispose_test_lot(test_lot, 1);
  350. return AST_TEST_FAIL;
  351. }
  352. if (ast_bridge_impart(parking_bridge, chan_alice, NULL, NULL,
  353. AST_BRIDGE_IMPART_CHAN_DEPARTABLE)) {
  354. ast_test_status_update(test, "Failed to impart alice into parking lot. Test failed.\n");
  355. dispose_test_lot(test_lot, 1);
  356. return AST_TEST_FAIL;
  357. }
  358. do_sleep(&to_sleep);
  359. retrieved_user = parking_lot_retrieve_parked_user(test_lot, 701);
  360. if (!retrieved_user) {
  361. ast_test_status_update(test, "Failed to retrieve the parked user from the expected parking space. Test failed.\n");
  362. failure = 1;
  363. goto test_cleanup;
  364. }
  365. ast_test_status_update(test, "Successfully retrieved parked user from the parking lot. Validating user data.\n");
  366. if (!parked_users_match(retrieved_user, &expected_user, test)) {
  367. ast_test_status_update(test, "Parked user validation failed\n");
  368. failure = 1;
  369. goto test_cleanup;
  370. }
  371. if (retrieved_user->chan != chan_alice) {
  372. ast_test_status_update(test, "The retrieved parked channel didn't match the expected channel. Test failed.\n");
  373. failure = 1;
  374. goto test_cleanup;
  375. }
  376. test_cleanup:
  377. ast_bridge_depart(chan_alice);
  378. chan_alice = hangup_channel(chan_alice, AST_CAUSE_NORMAL);
  379. if (dispose_test_lot(test_lot, 1)) {
  380. ast_test_status_update(test, "Found parking lot in container after attempted removal. Test failed.\n");
  381. failure = 1;
  382. }
  383. return failure ? AST_TEST_FAIL : AST_TEST_PASS;
  384. }
  385. static int check_retrieve_call_extensions(struct ast_test *test, int expected)
  386. {
  387. struct ast_exten *check;
  388. struct pbx_find_info find_info = { .stacklen = 0 }; /* the rest is reset in pbx_find_extension */
  389. int extens;
  390. char search_buffer[4];
  391. /* Check the parking extensions */
  392. check = pbx_find_extension(NULL, NULL, &find_info, "unit_test_res_parking_create_lot_con", "700", 1, NULL, NULL, E_MATCH);
  393. if (check ? !expected : expected) {
  394. /* extension isn't present when it should be or is present when it shouldn't be. Automatic failure. */
  395. ast_test_status_update(test, "An extension '700' was %s when it %s have been. Test failed.\n",
  396. expected ? "not present" : "present",
  397. expected ? "should" : "should not");
  398. return -1;
  399. } else if (check && expected) {
  400. if (strcmp(ast_get_extension_app(check), "Park")) {
  401. ast_test_status_update(test, "An extension '700' has the wrong application associated with it. Got '%s' expected 'Park'.\n",
  402. ast_get_extension_app(check));
  403. return -1;
  404. }
  405. }
  406. /* Check the parking space extensions 701-703 */
  407. for (extens = 701; extens <= 703; extens++) {
  408. sprintf(search_buffer, "%d", extens);
  409. find_info.stacklen = 0; /* reset for pbx_find_extension */
  410. check = pbx_find_extension(NULL, NULL, &find_info, "unit_test_res_parking_create_lot_con", search_buffer, 1, NULL, NULL, E_MATCH);
  411. if (check ? !expected : expected) {
  412. /* extension isn't present when it should be or is present when it shouldn't be. Automatic failure. */
  413. ast_test_status_update(test, "An extension '%s' was %s when it %s have been. Test failed.\n",
  414. search_buffer,
  415. expected ? "not present" : "present",
  416. expected ? "should" : "should not");
  417. return -1;
  418. } else if (check && expected) {
  419. if (strcmp(ast_get_extension_app(check), "ParkedCall")) {
  420. ast_test_status_update(test, "An extension '%s' has the wrong application associated with it. Got '%s', expected 'ParkedCall'.\n",
  421. search_buffer,
  422. ast_get_extension_app(check));
  423. return -1;
  424. }
  425. }
  426. }
  427. return 0;
  428. }
  429. AST_TEST_DEFINE(park_extensions)
  430. {
  431. RAII_VAR(struct parking_lot *, test_lot, NULL, ao2_cleanup);
  432. switch (cmd) {
  433. case TEST_INIT:
  434. info->name = "park_extensions";
  435. info->category = TEST_CATEGORY;
  436. info->summary = "Parking lot extension creation tests";
  437. info->description =
  438. "Creates parking lots and checks that they registered the expected extensions, then removes them.";
  439. return AST_TEST_NOT_RUN;
  440. case TEST_EXECUTE:
  441. break;
  442. }
  443. test_lot = generate_test_parking_lot(TEST_LOT_NAME, 701, 703, "700", "unit_test_res_parking_create_lot_con", test);
  444. if (!test_lot) {
  445. ast_test_status_update(test, "Failed to create test parking lot. Test Failed.\n");
  446. return AST_TEST_FAIL;
  447. }
  448. if (check_retrieve_call_extensions(test, 1)) {
  449. dispose_test_lot(test_lot, 1);
  450. return AST_TEST_FAIL;
  451. }
  452. ast_test_status_update(test, "Extensions for the test parking lot were verified. Cleaning up and verifying their removal.\n");
  453. if (dispose_test_lot(test_lot, 1)) {
  454. ast_test_status_update(test, "Found parking lot in container after attempted removal. Test failed.\n");
  455. return AST_TEST_FAIL;
  456. }
  457. ao2_cleanup(test_lot);
  458. test_lot = NULL;
  459. if (check_retrieve_call_extensions(test, 0)) {
  460. ast_log(LOG_ERROR, "Test 'park_extensions' failed to clean up after itself properly.\n");
  461. return AST_TEST_FAIL;
  462. }
  463. ast_test_status_update(test, "Extensions for the test parking lot verified as removed. Test completed successfully.\n");
  464. return AST_TEST_PASS;
  465. }
  466. AST_TEST_DEFINE(extension_conflicts)
  467. {
  468. RAII_VAR(struct parking_lot *, base_lot, NULL, ao2_cleanup);
  469. RAII_VAR(struct parking_lot *, expect_fail1, NULL, ao2_cleanup); /* Failure due to overlapping parkexten */
  470. RAII_VAR(struct parking_lot *, expect_fail2, NULL, ao2_cleanup); /* Failure due to overlapping spaces */
  471. RAII_VAR(struct parking_lot *, expect_fail3, NULL, ao2_cleanup); /* parkexten overlaps parking spaces */
  472. RAII_VAR(struct parking_lot *, expect_fail4, NULL, ao2_cleanup); /* parking spaces overlap parkexten */
  473. RAII_VAR(struct parking_lot *, expect_success1, NULL, ao2_cleanup); /* Success due to being in a different context */
  474. RAII_VAR(struct parking_lot *, expect_success2, NULL, ao2_cleanup); /* Success due to not having overlapping extensions */
  475. RAII_VAR(struct parking_lot *, expect_success3, NULL, ao2_cleanup); /* Range of parking spaces differs by one above */
  476. RAII_VAR(struct parking_lot *, expect_success4, NULL, ao2_cleanup); /* Range of parking spaces differs by one below */
  477. char *cur_lot_name;
  478. int failed = 0;
  479. switch (cmd) {
  480. case TEST_INIT:
  481. info->name = "extension_conflicts";
  482. info->category = TEST_CATEGORY;
  483. info->summary = "Tests the addition of parking lot extensions to make sure conflicts are detected";
  484. info->description =
  485. "Creates parking lots with overlapping extensions to test for conflicts";
  486. return AST_TEST_NOT_RUN;
  487. case TEST_EXECUTE:
  488. break;
  489. }
  490. ast_test_status_update(test, "Creating the base lot. This should pass.\n");
  491. base_lot = generate_test_parking_lot(TEST_LOT_NAME, 701, 703, "700", "unit_test_res_parking_create_lot_con", test);
  492. if (!base_lot) {
  493. ast_test_status_update(test, "Failed to create the base parking lot. Test failed.\n");
  494. failed = 1;
  495. goto cleanup;
  496. }
  497. cur_lot_name = "unit_tests_res_parking_test_lot_fail1";
  498. ast_test_status_update(test, "Creating a test lot which will overlap.\n");
  499. expect_fail1 = generate_test_parking_lot(cur_lot_name,
  500. 801, 803, "700", "unit_test_res_parking_create_lot_con", /* The parkexten overlaps the parkexten of the base */
  501. test);
  502. if (expect_fail1) {
  503. ast_test_status_update(test, "%s was successfully created when it was expected to fail. Test failed.\n", cur_lot_name);
  504. failed = 1;
  505. goto cleanup;
  506. }
  507. cur_lot_name = "unit_tests_res_parking_test_lot_fail2";
  508. expect_fail2 = generate_test_parking_lot(cur_lot_name,
  509. 702, 705, "800", "unit_test_res_parking_create_lot_con", /* The range overlaps the range of the base */
  510. test);
  511. if (expect_fail2) {
  512. ast_test_status_update(test, "%s was successfully created when it was expected to fail. Test failed.\n", cur_lot_name);
  513. failed = 1;
  514. goto cleanup;
  515. }
  516. cur_lot_name = "unit_tests_res_parking_test_lot_fail3";
  517. expect_fail3 = generate_test_parking_lot(cur_lot_name,
  518. 698, 700, "testfail3", "unit_test_res_parking_create_lot_con", /* The range overlaps the parkexten of the base */
  519. test);
  520. if (expect_fail3) {
  521. ast_test_status_update(test, "%s was successfully created when it was expected to fail. Test failed.\n", cur_lot_name);
  522. failed = 1;
  523. goto cleanup;
  524. }
  525. cur_lot_name = "unit_tests_res_parking_test_lot_fail4";
  526. expect_fail4 = generate_test_parking_lot(cur_lot_name,
  527. 704, 706, "703", "unit_test_res_parking_create_lot_con", /* The parkexten overlaps the range of the base */
  528. test);
  529. if (expect_fail4) {
  530. ast_test_status_update(test, "%s was successfully created when it was expected to fail. Test failed.\n", cur_lot_name);
  531. failed = 1;
  532. goto cleanup;
  533. }
  534. cur_lot_name = "unit_tests_res_parking_test_lot_success1";
  535. expect_success1 = generate_test_parking_lot(cur_lot_name,
  536. 701, 703, "700", "unit_test_res_parking_create_lot_con_2", /* no overlap due to different context */
  537. test);
  538. if (!expect_success1) {
  539. ast_test_status_update(test, "%s failed to be created. Success was expected. Test failed.\n", cur_lot_name);
  540. failed = 1;
  541. goto cleanup;
  542. }
  543. cur_lot_name = "unit_tests_res_parking_test_lot_success2";
  544. expect_success2 = generate_test_parking_lot(cur_lot_name,
  545. 601, 605, "600", "unit_test_res_parking_create_lot_con", /* no overlap due to different extensions and ranges */
  546. test);
  547. if (!expect_success2) {
  548. ast_test_status_update(test, "%s failed to be created. Success was expected. Test failed.\n", cur_lot_name);
  549. failed = 1;
  550. goto cleanup;
  551. }
  552. cur_lot_name = "unit_tests_res_parking_test_lot_success3";
  553. expect_success3 = generate_test_parking_lot(cur_lot_name,
  554. 704, 706, "testsuccess3", "unit_test_res_parking_create_lot_con", /* no overlap because the parking spaces start 1 above existing ranges */
  555. test);
  556. if (!expect_success3) {
  557. ast_test_status_update(test, "%s failed to be created. Success was expected. Test failed.\n", cur_lot_name);
  558. failed = 1;
  559. goto cleanup;
  560. }
  561. cur_lot_name = "unit_tests_res_parking_test_lot_success4";
  562. expect_success4 = generate_test_parking_lot(cur_lot_name,
  563. 697, 699, "testsuccess4", "unit_test_res_parking_create_lot_con", /* no overlap because the parking spaces end 1 below existing ranges */
  564. test);
  565. if (!expect_success4) {
  566. failed = 1;
  567. goto cleanup;
  568. }
  569. cleanup:
  570. if (base_lot && dispose_test_lot(base_lot, 1)) {
  571. ast_test_status_update(test, "Found base parking lot in container after attempted removal. Test failed.\n");
  572. failed = 1;
  573. }
  574. if (expect_fail1) {
  575. dispose_test_lot(expect_fail1, 1);
  576. failed = 1;
  577. }
  578. if (expect_fail2) {
  579. dispose_test_lot(expect_fail2, 1);
  580. failed = 1;
  581. }
  582. if (expect_fail3) {
  583. dispose_test_lot(expect_fail3, 1);
  584. failed = 1;
  585. }
  586. if (expect_fail4) {
  587. dispose_test_lot(expect_fail4, 1);
  588. failed = 1;
  589. }
  590. if (expect_success1 && dispose_test_lot(expect_success1, 1)) {
  591. ast_test_status_update(test, "Found expect_success1 parking lot in container after attempted removal. Test failed.\n");
  592. failed = 1;
  593. }
  594. if (expect_success2 && dispose_test_lot(expect_success2, 1)) {
  595. ast_test_status_update(test, "Found expect_success2 parking lot in container after attempted removal. Test failed.\n");
  596. failed = 1;
  597. }
  598. if (expect_success3 && dispose_test_lot(expect_success3, 1)) {
  599. ast_test_status_update(test, "Found expect_success3 parking lot in container after attempted removal. Test failed.\n");
  600. failed = 1;
  601. }
  602. if (expect_success4 && dispose_test_lot(expect_success4, 1)) {
  603. ast_test_status_update(test, "Found expect_success4 parking lot in container after attempted removal. Test failed.\n");
  604. }
  605. return failed ? AST_TEST_FAIL : AST_TEST_PASS;
  606. }
  607. AST_TEST_DEFINE(dynamic_parking_variables)
  608. {
  609. RAII_VAR(struct parking_lot *, template_lot, NULL, ao2_cleanup);
  610. RAII_VAR(struct parking_lot *, dynamic_lot, NULL, ao2_cleanup);
  611. RAII_VAR(struct ast_channel *, chan_alice, NULL, safe_channel_release);
  612. RAII_VAR(struct parking_lot_cfg *, expected_cfg, NULL, ao2_cleanup);
  613. int failed = 0;
  614. switch (cmd) {
  615. case TEST_INIT:
  616. info->name = "dynamic_parking_variables";
  617. info->category = TEST_CATEGORY;
  618. info->summary = "Tests whether dynamic parking lot creation respects channel variables";
  619. info->description =
  620. "Creates a template parking lot, creates a channel, sets dynamic parking variables, and then creates a parking lot for that channel";
  621. return AST_TEST_NOT_RUN;
  622. case TEST_EXECUTE:
  623. break;
  624. }
  625. ast_test_status_update(test, "Creating expected configuration for dynamic parking lot\n");
  626. expected_cfg = parking_lot_cfg_create("unit_tests_res_parking_test_lot_dynamic");
  627. if (!expected_cfg) {
  628. ast_test_status_update(test, "Failed to create expected configuration. Test failed.\n");
  629. return AST_TEST_FAIL;
  630. }
  631. expected_cfg->parking_start = 751;
  632. expected_cfg->parking_stop = 760;
  633. expected_cfg->parkingtime = 10;
  634. expected_cfg->comebackdialtime = 10;
  635. expected_cfg->parkfindnext = 1;
  636. expected_cfg->parkext_exclusive = 1;
  637. ast_string_field_set(expected_cfg, parkext, "750");
  638. ast_string_field_set(expected_cfg, parking_con, "unit_test_res_parking_create_lot_dynamic");
  639. ast_string_field_set(expected_cfg, comebackcontext, "unit_test_res_parking_create_lot_comeback");
  640. ast_test_status_update(test, "Creating template lot\n");
  641. template_lot = generate_test_parking_lot(TEST_LOT_NAME, 701, 703, "700", "unit_test_res_parking_create_lot_con", test);
  642. if (!template_lot) {
  643. ast_test_status_update(test, "Failed to generate template lot. Test failed.\n");
  644. return AST_TEST_FAIL;
  645. }
  646. ast_test_status_update(test, "Creating Alice channel to test dynamic parking lot creation.\n");
  647. chan_alice = create_alice_channel();
  648. if (!chan_alice) {
  649. ast_test_status_update(test, "Failed to create Alice channel. Test failed.\n");
  650. failed = 1;
  651. goto cleanup;
  652. }
  653. ast_test_status_update(test, "Setting Dynamic Parking channel variables on Alice.\n");
  654. pbx_builtin_setvar_helper(chan_alice, "PARKINGDYNAMIC", TEST_LOT_NAME);
  655. pbx_builtin_setvar_helper(chan_alice, "PARKINGLOT", "unit_test_res_parking_create_lot_dynamic");
  656. pbx_builtin_setvar_helper(chan_alice, "PARKINGDYNCONTEXT", "unit_test_res_parking_create_lot_dynamic");
  657. pbx_builtin_setvar_helper(chan_alice, "PARKINGDYNEXTEN", "750");
  658. pbx_builtin_setvar_helper(chan_alice, "PARKINGDYNPOS", "751-760");
  659. ast_test_status_update(test, "Generating dynamic parking lot based on Alice's channel variables.");
  660. dynamic_lot = parking_create_dynamic_lot_forced("unit_tests_res_parking_test_lot_dynamic", chan_alice);
  661. if (!dynamic_lot) {
  662. ast_test_status_update(test, "Failed to create dynamic parking lot. Test failed.\n");
  663. failed = 1;
  664. goto cleanup;
  665. }
  666. /* Check stats */
  667. if (!parking_lot_cfgs_match(dynamic_lot->cfg, expected_cfg, test)) {
  668. ast_test_status_update(test, "Dynamic parking lot configuration did not match Expectations.\n");
  669. failed = 1;
  670. goto cleanup;
  671. }
  672. ast_test_status_update(test, "Dynamic parking lot created successfully and matches expectations. Test passed.\n");
  673. cleanup:
  674. if (template_lot && dispose_test_lot(template_lot, 1)) {
  675. ast_test_status_update(test, "Found template parking lot in container after attempted removal. Test failed.\n");
  676. failed = 1;
  677. }
  678. if (dynamic_lot && dispose_test_lot(dynamic_lot, 1)) {
  679. ast_test_status_update(test, "Found dynamic parking lot in container after attempted removal. Test failed.\n");
  680. failed = 1;
  681. }
  682. return failed ? AST_TEST_FAIL : AST_TEST_PASS;
  683. }
  684. #endif /* TEST_FRAMEWORK */
  685. void unload_parking_tests(void)
  686. {
  687. /* NOOP without test framework */
  688. #if defined(TEST_FRAMEWORK)
  689. AST_TEST_UNREGISTER(create_lot);
  690. AST_TEST_UNREGISTER(park_call);
  691. AST_TEST_UNREGISTER(retrieve_call);
  692. AST_TEST_UNREGISTER(park_extensions);
  693. AST_TEST_UNREGISTER(extension_conflicts);
  694. AST_TEST_UNREGISTER(dynamic_parking_variables);
  695. #endif
  696. }
  697. int load_parking_tests(void)
  698. {
  699. int res = 0;
  700. /* NOOP without test framework */
  701. #if defined(TEST_FRAMEWORK)
  702. res |= AST_TEST_REGISTER(create_lot);
  703. res |= AST_TEST_REGISTER(park_call);
  704. res |= AST_TEST_REGISTER(retrieve_call);
  705. res |= AST_TEST_REGISTER(park_extensions);
  706. res |= AST_TEST_REGISTER(extension_conflicts);
  707. res |= AST_TEST_REGISTER(dynamic_parking_variables);
  708. #endif
  709. return res;
  710. }