test_bucket.c 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041
  1. /*
  2. * Asterisk -- An open source telephony toolkit.
  3. *
  4. * Copyright (C) 2013, Digium, Inc.
  5. *
  6. * Joshua Colp <jcolp@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 Bucket Unit Tests
  21. *
  22. * \author Joshua Colp <jcolp@digium.com>
  23. *
  24. */
  25. /*** MODULEINFO
  26. <depend>TEST_FRAMEWORK</depend>
  27. <support_level>core</support_level>
  28. ***/
  29. #include "asterisk.h"
  30. #include <sys/stat.h>
  31. #include "asterisk/test.h"
  32. #include "asterisk/module.h"
  33. #include "asterisk/bucket.h"
  34. #include "asterisk/logger.h"
  35. #include "asterisk/json.h"
  36. #include "asterisk/file.h"
  37. /*! \brief Test state structure for scheme wizards */
  38. struct bucket_test_state {
  39. /*! \brief Whether the object has been created or not */
  40. unsigned int created:1;
  41. /*! \brief Whether the object has been updated or not */
  42. unsigned int updated:1;
  43. /*! \brief Whether the object has been deleted or not */
  44. unsigned int deleted:1;
  45. /*! \brief Whether the object is stale or not */
  46. unsigned int is_stale:1;
  47. };
  48. /*! \brief Global scope structure for testing bucket wizards */
  49. static struct bucket_test_state bucket_test_wizard_state;
  50. static void bucket_test_wizard_clear(void)
  51. {
  52. bucket_test_wizard_state.created = 0;
  53. bucket_test_wizard_state.updated = 0;
  54. bucket_test_wizard_state.deleted = 0;
  55. bucket_test_wizard_state.is_stale = 0;
  56. }
  57. static int bucket_test_wizard_create(const struct ast_sorcery *sorcery, void *data, void *object)
  58. {
  59. if (bucket_test_wizard_state.created) {
  60. return -1;
  61. }
  62. bucket_test_wizard_state.created = 1;
  63. return 0;
  64. }
  65. static int bucket_test_wizard_update(const struct ast_sorcery *sorcery, void *data, void *object)
  66. {
  67. if (bucket_test_wizard_state.updated) {
  68. return -1;
  69. }
  70. bucket_test_wizard_state.updated = 1;
  71. return 0;
  72. }
  73. static void *bucket_test_wizard_retrieve_id(const struct ast_sorcery *sorcery, void *data, const char *type,
  74. const char *id)
  75. {
  76. if (!strcmp(type, "bucket")) {
  77. return ast_bucket_alloc(id);
  78. } else if (!strcmp(type, "file")) {
  79. return ast_bucket_file_alloc(id);
  80. } else {
  81. return NULL;
  82. }
  83. }
  84. static int bucket_test_wizard_delete(const struct ast_sorcery *sorcery, void *data, void *object)
  85. {
  86. if (bucket_test_wizard_state.deleted) {
  87. return -1;
  88. }
  89. bucket_test_wizard_state.deleted = 1;
  90. return 0;
  91. }
  92. static int bucket_test_wizard_is_stale(const struct ast_sorcery *sorcery, void *data, void *object)
  93. {
  94. return bucket_test_wizard_state.is_stale;
  95. }
  96. static struct ast_sorcery_wizard bucket_test_wizard = {
  97. .name = "test",
  98. .create = bucket_test_wizard_create,
  99. .retrieve_id = bucket_test_wizard_retrieve_id,
  100. .delete = bucket_test_wizard_delete,
  101. .is_stale = bucket_test_wizard_is_stale,
  102. };
  103. static struct ast_sorcery_wizard bucket_file_test_wizard = {
  104. .name = "test",
  105. .create = bucket_test_wizard_create,
  106. .update = bucket_test_wizard_update,
  107. .retrieve_id = bucket_test_wizard_retrieve_id,
  108. .delete = bucket_test_wizard_delete,
  109. .is_stale = bucket_test_wizard_is_stale,
  110. };
  111. AST_TEST_DEFINE(bucket_scheme_register)
  112. {
  113. switch (cmd) {
  114. case TEST_INIT:
  115. info->name = "bucket_scheme_register_unregister";
  116. info->category = "/main/bucket/";
  117. info->summary = "bucket scheme registration/unregistration unit test";
  118. info->description =
  119. "Test registration and unregistration of bucket scheme";
  120. return AST_TEST_NOT_RUN;
  121. case TEST_EXECUTE:
  122. break;
  123. }
  124. if (!ast_bucket_scheme_register("", NULL, NULL, NULL, NULL)) {
  125. ast_test_status_update(test, "Successfully registered a Bucket scheme without name or wizards\n");
  126. return AST_TEST_FAIL;
  127. }
  128. if (!ast_bucket_scheme_register("test", &bucket_test_wizard, &bucket_file_test_wizard, NULL, NULL)) {
  129. ast_test_status_update(test, "Successfully registered a Bucket scheme twice\n");
  130. return AST_TEST_FAIL;
  131. }
  132. return AST_TEST_PASS;
  133. }
  134. AST_TEST_DEFINE(bucket_alloc)
  135. {
  136. RAII_VAR(struct ast_bucket *, bucket, NULL, ao2_cleanup);
  137. switch (cmd) {
  138. case TEST_INIT:
  139. info->name = "bucket_alloc";
  140. info->category = "/main/bucket/";
  141. info->summary = "bucket allocation unit test";
  142. info->description =
  143. "Test allocation of buckets";
  144. return AST_TEST_NOT_RUN;
  145. case TEST_EXECUTE:
  146. break;
  147. }
  148. if ((bucket = ast_bucket_alloc(""))) {
  149. ast_test_status_update(test, "Allocated a bucket with no URI provided\n");
  150. return AST_TEST_FAIL;
  151. }
  152. if (!(bucket = ast_bucket_alloc("test:///tmp/bob"))) {
  153. ast_test_status_update(test, "Failed to allocate bucket\n");
  154. return AST_TEST_FAIL;
  155. }
  156. if (strcmp(ast_sorcery_object_get_id(bucket), "test:///tmp/bob")) {
  157. ast_test_status_update(test, "URI within allocated bucket is '%s' and should be test:///tmp/bob\n",
  158. ast_sorcery_object_get_id(bucket));
  159. return AST_TEST_FAIL;
  160. }
  161. if (strcmp(bucket->scheme, "test")) {
  162. ast_test_status_update(test, "Scheme within allocated bucket is '%s' and should be test\n",
  163. bucket->scheme);
  164. return AST_TEST_FAIL;
  165. }
  166. return AST_TEST_PASS;
  167. }
  168. AST_TEST_DEFINE(bucket_create)
  169. {
  170. RAII_VAR(struct ast_bucket *, bucket, NULL, ao2_cleanup);
  171. switch (cmd) {
  172. case TEST_INIT:
  173. info->name = "bucket_create";
  174. info->category = "/main/bucket/";
  175. info->summary = "bucket creation unit test";
  176. info->description =
  177. "Test creation of buckets";
  178. return AST_TEST_NOT_RUN;
  179. case TEST_EXECUTE:
  180. break;
  181. }
  182. if (!(bucket = ast_bucket_alloc("test:///tmp/bob"))) {
  183. ast_test_status_update(test, "Failed to allocate bucket\n");
  184. return AST_TEST_FAIL;
  185. }
  186. bucket_test_wizard_clear();
  187. if (ast_bucket_create(bucket)) {
  188. ast_test_status_update(test, "Failed to create bucket with URI '%s'\n",
  189. ast_sorcery_object_get_id(bucket));
  190. return AST_TEST_FAIL;
  191. }
  192. if (!bucket_test_wizard_state.created) {
  193. ast_test_status_update(test, "Bucket creation returned success but scheme implementation never actually created it\n");
  194. return AST_TEST_FAIL;
  195. }
  196. if (!ast_bucket_create(bucket)) {
  197. ast_test_status_update(test, "Successfully created bucket with URI '%s' twice\n",
  198. ast_sorcery_object_get_id(bucket));
  199. return AST_TEST_FAIL;
  200. }
  201. return AST_TEST_PASS;
  202. }
  203. AST_TEST_DEFINE(bucket_clone)
  204. {
  205. RAII_VAR(struct ast_bucket *, bucket, NULL, ao2_cleanup);
  206. RAII_VAR(struct ast_bucket *, clone, NULL, ao2_cleanup);
  207. switch (cmd) {
  208. case TEST_INIT:
  209. info->name = "bucket_clone";
  210. info->category = "/main/bucket/";
  211. info->summary = "bucket clone unit test";
  212. info->description =
  213. "Test cloning a bucket";
  214. return AST_TEST_NOT_RUN;
  215. case TEST_EXECUTE:
  216. break;
  217. }
  218. if (!(bucket = ast_bucket_alloc("test:///tmp/bob"))) {
  219. ast_test_status_update(test, "Failed to allocate bucket\n");
  220. return AST_TEST_FAIL;
  221. }
  222. bucket_test_wizard_clear();
  223. if (ast_bucket_create(bucket)) {
  224. ast_test_status_update(test, "Failed to create bucket with URI '%s'\n",
  225. ast_sorcery_object_get_id(bucket));
  226. return AST_TEST_FAIL;
  227. }
  228. clone = ast_bucket_clone(bucket);
  229. if (!clone) {
  230. ast_test_status_update(test, "Failed to clone bucket with URI '%s'\n",
  231. ast_sorcery_object_get_id(bucket));
  232. return AST_TEST_FAIL;
  233. }
  234. ast_test_validate(test, strcmp(ast_sorcery_object_get_id(bucket), ast_sorcery_object_get_id(clone)) == 0);
  235. ast_test_validate(test, bucket->scheme_impl == clone->scheme_impl);
  236. ast_test_validate(test, strcmp(bucket->scheme, clone->scheme) == 0);
  237. return AST_TEST_PASS;
  238. }
  239. AST_TEST_DEFINE(bucket_delete)
  240. {
  241. RAII_VAR(struct ast_bucket *, bucket, NULL, ao2_cleanup);
  242. switch (cmd) {
  243. case TEST_INIT:
  244. info->name = "bucket_delete";
  245. info->category = "/main/bucket/";
  246. info->summary = "bucket deletion unit test";
  247. info->description =
  248. "Test deletion of buckets";
  249. return AST_TEST_NOT_RUN;
  250. case TEST_EXECUTE:
  251. break;
  252. }
  253. if (!(bucket = ast_bucket_alloc("test:///tmp/bob"))) {
  254. ast_test_status_update(test, "Failed to allocate bucket\n");
  255. return AST_TEST_FAIL;
  256. }
  257. bucket_test_wizard_clear();
  258. if (ast_bucket_delete(bucket)) {
  259. ast_test_status_update(test, "Failed to delete bucket with URI '%s'\n",
  260. ast_sorcery_object_get_id(bucket));
  261. return AST_TEST_FAIL;
  262. }
  263. if (!bucket_test_wizard_state.deleted) {
  264. ast_test_status_update(test, "Bucket deletion returned success but scheme implementation never actually deleted it\n");
  265. return AST_TEST_FAIL;
  266. }
  267. if (!ast_bucket_delete(bucket)) {
  268. ast_test_status_update(test, "Successfully deleted bucket with URI '%s' twice\n",
  269. ast_sorcery_object_get_id(bucket));
  270. return AST_TEST_FAIL;
  271. }
  272. return AST_TEST_PASS;
  273. }
  274. AST_TEST_DEFINE(bucket_is_stale)
  275. {
  276. RAII_VAR(struct ast_bucket *, bucket, NULL, ao2_cleanup);
  277. switch (cmd) {
  278. case TEST_INIT:
  279. info->name = "bucket_is_stale";
  280. info->category = "/main/bucket/";
  281. info->summary = "bucket staleness unit test";
  282. info->description =
  283. "Test if staleness of a bucket is reported correctly";
  284. return AST_TEST_NOT_RUN;
  285. case TEST_EXECUTE:
  286. break;
  287. }
  288. if (!(bucket = ast_bucket_alloc("test:///tmp/bob"))) {
  289. ast_test_status_update(test, "Failed to allocate bucket\n");
  290. return AST_TEST_FAIL;
  291. }
  292. bucket_test_wizard_clear();
  293. ast_test_validate(test, ast_bucket_is_stale(bucket) == 0);
  294. bucket_test_wizard_state.is_stale = 1;
  295. ast_test_validate(test, ast_bucket_is_stale(bucket) == 1);
  296. return AST_TEST_PASS;
  297. }
  298. AST_TEST_DEFINE(bucket_json)
  299. {
  300. RAII_VAR(struct ast_bucket *, bucket, NULL, ao2_cleanup);
  301. RAII_VAR(struct ast_json *, expected, NULL, ast_json_unref);
  302. RAII_VAR(struct ast_json *, json, NULL, ast_json_unref);
  303. switch (cmd) {
  304. case TEST_INIT:
  305. info->name = "bucket_json";
  306. info->category = "/main/bucket/";
  307. info->summary = "bucket json unit test";
  308. info->description =
  309. "Test creation of JSON for a bucket";
  310. return AST_TEST_NOT_RUN;
  311. case TEST_EXECUTE:
  312. break;
  313. }
  314. if (!(bucket = ast_bucket_alloc("test:///tmp/bob"))) {
  315. ast_test_status_update(test, "Failed to allocate bucket\n");
  316. return AST_TEST_FAIL;
  317. }
  318. ast_str_container_add(bucket->buckets, "test:///tmp/bob/joe");
  319. ast_str_container_add(bucket->files, "test:///tmp/bob/recording.wav");
  320. expected = ast_json_pack("{s: s, s: s, s: [s], s: s, s: [s], s: s}",
  321. "modified", "0.000000", "created", "0.000000",
  322. "buckets", "test:///tmp/bob/joe",
  323. "scheme", "test",
  324. "files", "test:///tmp/bob/recording.wav",
  325. "id", "test:///tmp/bob");
  326. if (!expected) {
  327. ast_test_status_update(test, "Could not produce JSON for expected bucket value\n");
  328. return AST_TEST_FAIL;
  329. }
  330. json = ast_bucket_json(bucket);
  331. if (!json) {
  332. ast_test_status_update(test, "Could not produce JSON for a valid bucket\n");
  333. return AST_TEST_FAIL;
  334. }
  335. if (!ast_json_equal(json, expected)) {
  336. ast_test_status_update(test, "Bucket JSON does not match expected output\n");
  337. return AST_TEST_FAIL;
  338. }
  339. return AST_TEST_PASS;
  340. }
  341. AST_TEST_DEFINE(bucket_retrieve)
  342. {
  343. RAII_VAR(struct ast_bucket *, bucket, NULL, ao2_cleanup);
  344. switch (cmd) {
  345. case TEST_INIT:
  346. info->name = "bucket_retrieve";
  347. info->category = "/main/bucket/";
  348. info->summary = "bucket retrieval unit test";
  349. info->description =
  350. "Test retrieval of buckets";
  351. return AST_TEST_NOT_RUN;
  352. case TEST_EXECUTE:
  353. break;
  354. }
  355. if (!(bucket = ast_bucket_retrieve("test://tmp/bob"))) {
  356. ast_test_status_update(test, "Failed to retrieve known valid bucket\n");
  357. return AST_TEST_FAIL;
  358. }
  359. return AST_TEST_PASS;
  360. }
  361. AST_TEST_DEFINE(bucket_file_alloc)
  362. {
  363. RAII_VAR(struct ast_bucket_file *, file, NULL, ao2_cleanup);
  364. switch (cmd) {
  365. case TEST_INIT:
  366. info->name = "bucket_file_alloc";
  367. info->category = "/main/bucket/";
  368. info->summary = "bucket file allocation unit test";
  369. info->description =
  370. "Test allocation of bucket files";
  371. return AST_TEST_NOT_RUN;
  372. case TEST_EXECUTE:
  373. break;
  374. }
  375. if ((file = ast_bucket_file_alloc(""))) {
  376. ast_test_status_update(test, "Allocated a file with no URI provided\n");
  377. return AST_TEST_FAIL;
  378. }
  379. if (!(file = ast_bucket_file_alloc("test:///tmp/bob"))) {
  380. ast_test_status_update(test, "Failed to allocate file\n");
  381. return AST_TEST_FAIL;
  382. }
  383. if (ast_strlen_zero(file->path)) {
  384. ast_test_status_update(test, "Expected temporary path in allocated file");
  385. return AST_TEST_FAIL;
  386. }
  387. if (strcmp(ast_sorcery_object_get_id(file), "test:///tmp/bob")) {
  388. ast_test_status_update(test, "URI within allocated file is '%s' and should be test:///tmp/bob\n",
  389. ast_sorcery_object_get_id(file));
  390. return AST_TEST_FAIL;
  391. }
  392. if (strcmp(file->scheme, "test")) {
  393. ast_test_status_update(test, "Scheme within allocated file is '%s' and should be test\n",
  394. file->scheme);
  395. return AST_TEST_FAIL;
  396. }
  397. return AST_TEST_PASS;
  398. }
  399. AST_TEST_DEFINE(bucket_file_create)
  400. {
  401. RAII_VAR(struct ast_bucket_file *, file, NULL, ao2_cleanup);
  402. switch (cmd) {
  403. case TEST_INIT:
  404. info->name = "bucket_file_create";
  405. info->category = "/main/bucket/";
  406. info->summary = "file creation unit test";
  407. info->description =
  408. "Test creation of files";
  409. return AST_TEST_NOT_RUN;
  410. case TEST_EXECUTE:
  411. break;
  412. }
  413. if (!(file = ast_bucket_file_alloc("test:///tmp/bob"))) {
  414. ast_test_status_update(test, "Failed to allocate file\n");
  415. return AST_TEST_FAIL;
  416. }
  417. bucket_test_wizard_clear();
  418. if (ast_bucket_file_create(file)) {
  419. ast_test_status_update(test, "Failed to create file with URI '%s'\n",
  420. ast_sorcery_object_get_id(file));
  421. return AST_TEST_FAIL;
  422. }
  423. if (!bucket_test_wizard_state.created) {
  424. ast_test_status_update(test, "Bucket file creation returned success but scheme implementation never actually created it\n");
  425. return AST_TEST_FAIL;
  426. }
  427. if (!ast_bucket_file_create(file)) {
  428. ast_test_status_update(test, "Successfully created file with URI '%s' twice\n",
  429. ast_sorcery_object_get_id(file));
  430. return AST_TEST_FAIL;
  431. }
  432. return AST_TEST_PASS;
  433. }
  434. AST_TEST_DEFINE(bucket_file_clone)
  435. {
  436. RAII_VAR(struct ast_bucket_file *, file, NULL, ao2_cleanup);
  437. RAII_VAR(struct ast_bucket_file *, clone, NULL, ao2_cleanup);
  438. switch (cmd) {
  439. case TEST_INIT:
  440. info->name = "bucket_file_clone";
  441. info->category = "/main/bucket/";
  442. info->summary = "file clone unit test";
  443. info->description =
  444. "Test cloning a file";
  445. return AST_TEST_NOT_RUN;
  446. case TEST_EXECUTE:
  447. break;
  448. }
  449. if (!(file = ast_bucket_file_alloc("test:///tmp/bob"))) {
  450. ast_test_status_update(test, "Failed to allocate file\n");
  451. return AST_TEST_FAIL;
  452. }
  453. bucket_test_wizard_clear();
  454. if (ast_bucket_file_create(file)) {
  455. ast_test_status_update(test, "Failed to create file with URI '%s'\n",
  456. ast_sorcery_object_get_id(file));
  457. return AST_TEST_FAIL;
  458. }
  459. ast_bucket_file_metadata_set(file, "bob", "joe");
  460. clone = ast_bucket_file_clone(file);
  461. if (!clone) {
  462. ast_test_status_update(test, "Failed to clone file with URI '%s'\n",
  463. ast_sorcery_object_get_id(file));
  464. return AST_TEST_FAIL;
  465. }
  466. ast_test_validate(test, strcmp(ast_sorcery_object_get_id(file), ast_sorcery_object_get_id(clone)) == 0);
  467. ast_test_validate(test, file->scheme_impl == clone->scheme_impl);
  468. ast_test_validate(test, strcmp(file->scheme, clone->scheme) == 0);
  469. ast_test_validate(test, ao2_container_count(file->metadata) == ao2_container_count(clone->metadata));
  470. return AST_TEST_PASS;
  471. }
  472. AST_TEST_DEFINE(bucket_file_copy)
  473. {
  474. RAII_VAR(struct ast_bucket_file *, file, NULL, ao2_cleanup);
  475. RAII_VAR(struct ast_bucket_file *, copy, NULL, ao2_cleanup);
  476. FILE *temporary;
  477. struct stat old, new;
  478. RAII_VAR(struct ast_bucket_metadata *, metadata, NULL, ao2_cleanup);
  479. switch (cmd) {
  480. case TEST_INIT:
  481. info->name = "bucket_file_copy";
  482. info->category = "/main/bucket/";
  483. info->summary = "bucket file copying unit test";
  484. info->description =
  485. "Test copying of bucket files";
  486. return AST_TEST_NOT_RUN;
  487. case TEST_EXECUTE:
  488. break;
  489. }
  490. if (!(file = ast_bucket_file_alloc("test:///tmp/bob"))) {
  491. ast_test_status_update(test, "Failed to allocate file\n");
  492. return AST_TEST_FAIL;
  493. }
  494. ast_bucket_file_metadata_set(file, "bob", "joe");
  495. if (!(temporary = fopen(file->path, "w"))) {
  496. ast_test_status_update(test, "Failed to open temporary file '%s'\n", file->path);
  497. return AST_TEST_FAIL;
  498. }
  499. fprintf(temporary, "bob");
  500. fclose(temporary);
  501. if (!(copy = ast_bucket_file_copy(file, "test:///tmp/bob2"))) {
  502. ast_test_status_update(test, "Failed to copy file '%s' to test:///tmp/bob2\n",
  503. ast_sorcery_object_get_id(file));
  504. return AST_TEST_FAIL;
  505. }
  506. if (stat(file->path, &old)) {
  507. ast_test_status_update(test, "Failed to retrieve information on old file '%s'\n", file->path);
  508. return AST_TEST_FAIL;
  509. }
  510. if (stat(copy->path, &new)) {
  511. ast_test_status_update(test, "Failed to retrieve information on copy file '%s'\n", copy->path);
  512. return AST_TEST_FAIL;
  513. }
  514. if (old.st_size != new.st_size) {
  515. ast_test_status_update(test, "Copying of underlying temporary file failed\n");
  516. return AST_TEST_FAIL;
  517. }
  518. if (ao2_container_count(file->metadata) != ao2_container_count(copy->metadata)) {
  519. ast_test_status_update(test, "Number of metadata entries does not match original\n");
  520. return AST_TEST_FAIL;
  521. }
  522. metadata = ast_bucket_file_metadata_get(copy, "bob");
  523. if (!metadata) {
  524. ast_test_status_update(test, "Copy of file does not have expected metadata\n");
  525. return AST_TEST_FAIL;
  526. }
  527. if (strcmp(metadata->value, "joe")) {
  528. ast_test_status_update(test, "Copy of file contains metadata for 'bob' but value is not what it should be\n");
  529. return AST_TEST_FAIL;
  530. }
  531. return AST_TEST_PASS;
  532. }
  533. AST_TEST_DEFINE(bucket_file_retrieve)
  534. {
  535. RAII_VAR(struct ast_bucket_file *, file, NULL, ao2_cleanup);
  536. switch (cmd) {
  537. case TEST_INIT:
  538. info->name = "bucket_file_retrieve";
  539. info->category = "/main/bucket/";
  540. info->summary = "file retrieval unit test";
  541. info->description =
  542. "Test retrieval of files";
  543. return AST_TEST_NOT_RUN;
  544. case TEST_EXECUTE:
  545. break;
  546. }
  547. if (!(file = ast_bucket_file_retrieve("test://tmp/bob"))) {
  548. ast_test_status_update(test, "Failed to retrieve known valid file\n");
  549. return AST_TEST_FAIL;
  550. }
  551. return AST_TEST_PASS;
  552. }
  553. AST_TEST_DEFINE(bucket_file_update)
  554. {
  555. RAII_VAR(struct ast_bucket_file *, file, NULL, ao2_cleanup);
  556. switch (cmd) {
  557. case TEST_INIT:
  558. info->name = "bucket_file_update";
  559. info->category = "/main/bucket/";
  560. info->summary = "file updating unit test";
  561. info->description =
  562. "Test updating of files";
  563. return AST_TEST_NOT_RUN;
  564. case TEST_EXECUTE:
  565. break;
  566. }
  567. if (!(file = ast_bucket_file_alloc("test:///tmp/bob"))) {
  568. ast_test_status_update(test, "Failed to allocate file\n");
  569. return AST_TEST_FAIL;
  570. }
  571. bucket_test_wizard_clear();
  572. if (ast_bucket_file_update(file)) {
  573. ast_test_status_update(test, "Failed to update file with URI '%s'\n",
  574. ast_sorcery_object_get_id(file));
  575. return AST_TEST_FAIL;
  576. }
  577. if (!bucket_test_wizard_state.updated) {
  578. ast_test_status_update(test, "Successfully returned file was updated, but it was not\n");
  579. return AST_TEST_FAIL;
  580. }
  581. if (!ast_bucket_file_update(file)) {
  582. ast_test_status_update(test, "Successfully updated file with URI '%s' twice\n",
  583. ast_sorcery_object_get_id(file));
  584. return AST_TEST_FAIL;
  585. }
  586. return AST_TEST_PASS;
  587. }
  588. AST_TEST_DEFINE(bucket_file_delete)
  589. {
  590. RAII_VAR(struct ast_bucket_file *, file, NULL, ao2_cleanup);
  591. switch (cmd) {
  592. case TEST_INIT:
  593. info->name = "bucket_file_delete";
  594. info->category = "/main/bucket/";
  595. info->summary = "file deletion unit test";
  596. info->description =
  597. "Test deletion of files";
  598. return AST_TEST_NOT_RUN;
  599. case TEST_EXECUTE:
  600. break;
  601. }
  602. if (!(file = ast_bucket_file_alloc("test:///tmp/bob"))) {
  603. ast_test_status_update(test, "Failed to allocate file\n");
  604. return AST_TEST_FAIL;
  605. }
  606. bucket_test_wizard_clear();
  607. if (ast_bucket_file_delete(file)) {
  608. ast_test_status_update(test, "Failed to delete file with URI '%s'\n",
  609. ast_sorcery_object_get_id(file));
  610. return AST_TEST_FAIL;
  611. }
  612. if (!bucket_test_wizard_state.deleted) {
  613. ast_test_status_update(test, "Bucket file deletion returned success but scheme implementation never actually deleted it\n");
  614. return AST_TEST_FAIL;
  615. }
  616. if (!ast_bucket_file_delete(file)) {
  617. ast_test_status_update(test, "Successfully deleted file with URI '%s' twice\n",
  618. ast_sorcery_object_get_id(file));
  619. return AST_TEST_FAIL;
  620. }
  621. return AST_TEST_PASS;
  622. }
  623. AST_TEST_DEFINE(bucket_file_is_stale)
  624. {
  625. RAII_VAR(struct ast_bucket_file *, file, NULL, ao2_cleanup);
  626. switch (cmd) {
  627. case TEST_INIT:
  628. info->name = "bucket_file_is_stale";
  629. info->category = "/main/bucket/";
  630. info->summary = "file staleness unit test";
  631. info->description =
  632. "Test if staleness of a bucket file is reported correctly";
  633. return AST_TEST_NOT_RUN;
  634. case TEST_EXECUTE:
  635. break;
  636. }
  637. if (!(file = ast_bucket_file_alloc("test:///tmp/bob"))) {
  638. ast_test_status_update(test, "Failed to allocate file\n");
  639. return AST_TEST_FAIL;
  640. }
  641. bucket_test_wizard_clear();
  642. ast_test_validate(test, ast_bucket_file_is_stale(file) == 0);
  643. bucket_test_wizard_state.is_stale = 1;
  644. ast_test_validate(test, ast_bucket_file_is_stale(file) == 1);
  645. return AST_TEST_PASS;
  646. }
  647. AST_TEST_DEFINE(bucket_file_metadata_set)
  648. {
  649. RAII_VAR(struct ast_bucket_file *, file, NULL, ao2_cleanup);
  650. RAII_VAR(struct ast_bucket_metadata *, metadata, NULL, ao2_cleanup);
  651. switch (cmd) {
  652. case TEST_INIT:
  653. info->name = "bucket_file_metadata_set";
  654. info->category = "/main/bucket/";
  655. info->summary = "file metadata setting unit test";
  656. info->description =
  657. "Test setting of metadata on files";
  658. return AST_TEST_NOT_RUN;
  659. case TEST_EXECUTE:
  660. break;
  661. }
  662. if (!(file = ast_bucket_file_alloc("test:///tmp/bob"))) {
  663. ast_test_status_update(test, "Failed to allocate file\n");
  664. return AST_TEST_FAIL;
  665. }
  666. if (ao2_container_count(file->metadata) != 0) {
  667. ast_test_status_update(test, "Newly allocated file has metadata count of '%d' when should be 0\n",
  668. ao2_container_count(file->metadata));
  669. return AST_TEST_FAIL;
  670. }
  671. if (ast_bucket_file_metadata_set(file, "bob", "joe")) {
  672. ast_test_status_update(test, "Failed to set metadata 'bob' to 'joe' on newly allocated file\n");
  673. return AST_TEST_FAIL;
  674. }
  675. if (!(metadata = ao2_find(file->metadata, "bob", OBJ_KEY))) {
  676. ast_test_status_update(test, "Failed to find set metadata 'bob' on newly allocated file\n");
  677. return AST_TEST_FAIL;
  678. }
  679. if (strcmp(metadata->value, "joe")) {
  680. ast_test_status_update(test, "Metadata has value '%s' when should be 'joe'\n",
  681. metadata->value);
  682. return AST_TEST_FAIL;
  683. }
  684. ao2_cleanup(metadata);
  685. metadata = NULL;
  686. if (ast_bucket_file_metadata_set(file, "bob", "fred")) {
  687. ast_test_status_update(test, "Failed to overwrite metadata 'bob' with new value 'fred'\n");
  688. return AST_TEST_FAIL;
  689. }
  690. if (!(metadata = ao2_find(file->metadata, "bob", OBJ_KEY))) {
  691. ast_test_status_update(test, "Failed to find overwritten metadata 'bob' on newly allocated file\n");
  692. return AST_TEST_FAIL;
  693. }
  694. if (strcmp(metadata->value, "fred")) {
  695. ast_test_status_update(test, "Metadata has value '%s' when should be 'fred'\n",
  696. metadata->value);
  697. return AST_TEST_FAIL;
  698. }
  699. return AST_TEST_PASS;
  700. }
  701. AST_TEST_DEFINE(bucket_file_metadata_unset)
  702. {
  703. RAII_VAR(struct ast_bucket_file *, file, NULL, ao2_cleanup);
  704. RAII_VAR(struct ast_bucket_metadata *, metadata, NULL, ao2_cleanup);
  705. switch (cmd) {
  706. case TEST_INIT:
  707. info->name = "bucket_file_metadata_unset";
  708. info->category = "/main/bucket/";
  709. info->summary = "file metadata unsetting unit test";
  710. info->description =
  711. "Test unsetting of metadata on files";
  712. return AST_TEST_NOT_RUN;
  713. case TEST_EXECUTE:
  714. break;
  715. }
  716. if (!(file = ast_bucket_file_alloc("test:///tmp/bob"))) {
  717. ast_test_status_update(test, "Failed to allocate file\n");
  718. return AST_TEST_FAIL;
  719. }
  720. if (ast_bucket_file_metadata_set(file, "bob", "joe")) {
  721. ast_test_status_update(test, "Failed to set metadata 'bob' to 'joe' on newly allocated file\n");
  722. return AST_TEST_FAIL;
  723. }
  724. if (ast_bucket_file_metadata_unset(file, "bob")) {
  725. ast_test_status_update(test, "Failed to unset metadata 'bob' on newly allocated file\n");
  726. return AST_TEST_FAIL;
  727. }
  728. if ((metadata = ao2_find(file->metadata, "bob", OBJ_KEY))) {
  729. ast_test_status_update(test, "Metadata 'bob' was unset, but can still be found\n");
  730. return AST_TEST_FAIL;
  731. }
  732. return AST_TEST_PASS;
  733. }
  734. AST_TEST_DEFINE(bucket_file_metadata_get)
  735. {
  736. RAII_VAR(struct ast_bucket_file *, file, NULL, ao2_cleanup);
  737. RAII_VAR(struct ast_bucket_metadata *, metadata, NULL, ao2_cleanup);
  738. switch (cmd) {
  739. case TEST_INIT:
  740. info->name = "bucket_file_metadata_get";
  741. info->category = "/main/bucket/";
  742. info->summary = "file metadata getting unit test";
  743. info->description =
  744. "Test getting of metadata on files";
  745. return AST_TEST_NOT_RUN;
  746. case TEST_EXECUTE:
  747. break;
  748. }
  749. if (!(file = ast_bucket_file_alloc("test:///tmp/bob"))) {
  750. ast_test_status_update(test, "Failed to allocate file\n");
  751. return AST_TEST_FAIL;
  752. }
  753. if (ast_bucket_file_metadata_set(file, "bob", "joe")) {
  754. ast_test_status_update(test, "Failed to set metadata 'bob' to 'joe' on newly allocated file\n");
  755. return AST_TEST_FAIL;
  756. }
  757. if (!(metadata = ast_bucket_file_metadata_get(file, "bob"))) {
  758. ast_test_status_update(test, "Failed to retrieve metadata 'bob' that was just set\n");
  759. return AST_TEST_FAIL;
  760. }
  761. if (strcmp(metadata->value, "joe")) {
  762. ast_test_status_update(test, "Retrieved metadata value is '%s' while it should be 'joe'\n",
  763. metadata->value);
  764. return AST_TEST_FAIL;
  765. }
  766. return AST_TEST_PASS;
  767. }
  768. AST_TEST_DEFINE(bucket_file_json)
  769. {
  770. RAII_VAR(struct ast_bucket_file *, file, NULL, ao2_cleanup);
  771. RAII_VAR(struct ast_json *, expected, NULL, ast_json_unref);
  772. RAII_VAR(struct ast_json *, json, NULL, ast_json_unref);
  773. switch (cmd) {
  774. case TEST_INIT:
  775. info->name = "bucket_file_json";
  776. info->category = "/main/bucket/";
  777. info->summary = "file json unit test";
  778. info->description =
  779. "Test creation of JSON for a file";
  780. return AST_TEST_NOT_RUN;
  781. case TEST_EXECUTE:
  782. break;
  783. }
  784. if (!(file = ast_bucket_file_alloc("test:///tmp/bob"))) {
  785. ast_test_status_update(test, "Failed to allocate bucket\n");
  786. return AST_TEST_FAIL;
  787. }
  788. if (ast_bucket_file_metadata_set(file, "bob", "joe")) {
  789. ast_test_status_update(test, "Failed to set metadata 'bob' to 'joe' on newly allocated file\n");
  790. return AST_TEST_FAIL;
  791. }
  792. expected = ast_json_pack("{s: s, s: s, s: s, s: s, s: {s :s}}",
  793. "modified", "0.000000", "created", "0.000000", "scheme", "test",
  794. "id", "test:///tmp/bob", "metadata", "bob", "joe");
  795. if (!expected) {
  796. ast_test_status_update(test, "Could not produce JSON for expected bucket file value\n");
  797. return AST_TEST_FAIL;
  798. }
  799. json = ast_bucket_file_json(file);
  800. if (!json) {
  801. ast_test_status_update(test, "Could not produce JSON for a valid file\n");
  802. return AST_TEST_FAIL;
  803. }
  804. if (!ast_json_equal(json, expected)) {
  805. ast_test_status_update(test, "Bucket file JSON does not match expected output\n");
  806. return AST_TEST_FAIL;
  807. }
  808. return AST_TEST_PASS;
  809. }
  810. static int unload_module(void)
  811. {
  812. AST_TEST_UNREGISTER(bucket_scheme_register);
  813. AST_TEST_UNREGISTER(bucket_alloc);
  814. AST_TEST_UNREGISTER(bucket_create);
  815. AST_TEST_UNREGISTER(bucket_clone);
  816. AST_TEST_UNREGISTER(bucket_delete);
  817. AST_TEST_UNREGISTER(bucket_retrieve);
  818. AST_TEST_UNREGISTER(bucket_json);
  819. AST_TEST_UNREGISTER(bucket_file_alloc);
  820. AST_TEST_UNREGISTER(bucket_file_create);
  821. AST_TEST_UNREGISTER(bucket_file_clone);
  822. AST_TEST_UNREGISTER(bucket_file_copy);
  823. AST_TEST_UNREGISTER(bucket_file_retrieve);
  824. AST_TEST_UNREGISTER(bucket_file_update);
  825. AST_TEST_UNREGISTER(bucket_file_delete);
  826. AST_TEST_UNREGISTER(bucket_file_metadata_set);
  827. AST_TEST_UNREGISTER(bucket_file_metadata_unset);
  828. AST_TEST_UNREGISTER(bucket_file_metadata_get);
  829. AST_TEST_UNREGISTER(bucket_file_json);
  830. return 0;
  831. }
  832. static int load_module(void)
  833. {
  834. if (ast_bucket_scheme_register("test", &bucket_test_wizard, &bucket_file_test_wizard,
  835. ast_bucket_file_temporary_create, ast_bucket_file_temporary_destroy)) {
  836. ast_log(LOG_ERROR, "Failed to register Bucket test wizard scheme implementation\n");
  837. return AST_MODULE_LOAD_DECLINE;
  838. }
  839. AST_TEST_REGISTER(bucket_scheme_register);
  840. AST_TEST_REGISTER(bucket_alloc);
  841. AST_TEST_REGISTER(bucket_create);
  842. AST_TEST_REGISTER(bucket_clone);
  843. AST_TEST_REGISTER(bucket_delete);
  844. AST_TEST_REGISTER(bucket_retrieve);
  845. AST_TEST_REGISTER(bucket_is_stale);
  846. AST_TEST_REGISTER(bucket_json);
  847. AST_TEST_REGISTER(bucket_file_alloc);
  848. AST_TEST_REGISTER(bucket_file_create);
  849. AST_TEST_REGISTER(bucket_file_clone);
  850. AST_TEST_REGISTER(bucket_file_copy);
  851. AST_TEST_REGISTER(bucket_file_retrieve);
  852. AST_TEST_REGISTER(bucket_file_update);
  853. AST_TEST_REGISTER(bucket_file_delete);
  854. AST_TEST_REGISTER(bucket_file_is_stale);
  855. AST_TEST_REGISTER(bucket_file_metadata_set);
  856. AST_TEST_REGISTER(bucket_file_metadata_unset);
  857. AST_TEST_REGISTER(bucket_file_metadata_get);
  858. AST_TEST_REGISTER(bucket_file_json);
  859. return AST_MODULE_LOAD_SUCCESS;
  860. }
  861. AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Bucket test module");