Asterisk - The Open Source Telephony Project GIT-master-f36a736
test_bucket.c
Go to the documentation of this file.
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/*!
20 * \file
21 * \brief Bucket Unit Tests
22 *
23 * \author Joshua Colp <jcolp@digium.com>
24 *
25 */
26
27/*** MODULEINFO
28 <depend>TEST_FRAMEWORK</depend>
29 <support_level>core</support_level>
30 ***/
31
32#include "asterisk.h"
33
34#include <sys/stat.h>
35
36#include "asterisk/test.h"
37#include "asterisk/module.h"
38#include "asterisk/bucket.h"
39#include "asterisk/logger.h"
40#include "asterisk/json.h"
41#include "asterisk/file.h"
42
43/*! \brief Test state structure for scheme wizards */
45 /*! \brief Whether the object has been created or not */
46 unsigned int created:1;
47 /*! \brief Whether the object has been updated or not */
48 unsigned int updated:1;
49 /*! \brief Whether the object has been deleted or not */
50 unsigned int deleted:1;
51 /*! \brief Whether the object is stale or not */
52 unsigned int is_stale:1;
53};
54
55/*! \brief Global scope structure for testing bucket wizards */
57
58static void bucket_test_wizard_clear(void)
59{
64}
65
66static int bucket_test_wizard_create(const struct ast_sorcery *sorcery, void *data, void *object)
67{
69 return -1;
70 }
71
73
74 return 0;
75}
76
77static int bucket_test_wizard_update(const struct ast_sorcery *sorcery, void *data, void *object)
78{
80 return -1;
81 }
82
84
85 return 0;
86}
87
88static void *bucket_test_wizard_retrieve_id(const struct ast_sorcery *sorcery, void *data, const char *type,
89 const char *id)
90{
91 if (!strcmp(type, "bucket")) {
92 return ast_bucket_alloc(id);
93 } else if (!strcmp(type, "file")) {
94 return ast_bucket_file_alloc(id);
95 } else {
96 return NULL;
97 }
98}
99
100static int bucket_test_wizard_delete(const struct ast_sorcery *sorcery, void *data, void *object)
101{
103 return -1;
104 }
105
107
108 return 0;
109}
110
111static int bucket_test_wizard_is_stale(const struct ast_sorcery *sorcery, void *data, void *object)
112{
114}
115
117 .name = "test",
119 .retrieve_id = bucket_test_wizard_retrieve_id,
121 .is_stale = bucket_test_wizard_is_stale,
122};
123
125 .name = "test",
128 .retrieve_id = bucket_test_wizard_retrieve_id,
130 .is_stale = bucket_test_wizard_is_stale,
131};
132
133AST_TEST_DEFINE(bucket_scheme_register)
134{
135 switch (cmd) {
136 case TEST_INIT:
137 info->name = "bucket_scheme_register_unregister";
138 info->category = "/main/bucket/";
139 info->summary = "bucket scheme registration/unregistration unit test";
140 info->description =
141 "Test registration and unregistration of bucket scheme";
142 return AST_TEST_NOT_RUN;
143 case TEST_EXECUTE:
144 break;
145 }
146
148 ast_test_status_update(test, "Successfully registered a Bucket scheme without name or wizards\n");
149 return AST_TEST_FAIL;
150 }
151
153 ast_test_status_update(test, "Successfully registered a Bucket scheme twice\n");
154 return AST_TEST_FAIL;
155 }
156
157 return AST_TEST_PASS;
158}
159
161{
162 RAII_VAR(struct ast_bucket *, bucket, NULL, ao2_cleanup);
163
164 switch (cmd) {
165 case TEST_INIT:
166 info->name = "bucket_alloc";
167 info->category = "/main/bucket/";
168 info->summary = "bucket allocation unit test";
169 info->description =
170 "Test allocation of buckets";
171 return AST_TEST_NOT_RUN;
172 case TEST_EXECUTE:
173 break;
174 }
175
176 if ((bucket = ast_bucket_alloc(""))) {
177 ast_test_status_update(test, "Allocated a bucket with no URI provided\n");
178 return AST_TEST_FAIL;
179 }
180
181 if (!(bucket = ast_bucket_alloc("test:///tmp/bob"))) {
182 ast_test_status_update(test, "Failed to allocate bucket\n");
183 return AST_TEST_FAIL;
184 }
185
186 if (strcmp(ast_sorcery_object_get_id(bucket), "test:///tmp/bob")) {
187 ast_test_status_update(test, "URI within allocated bucket is '%s' and should be test:///tmp/bob\n",
189 return AST_TEST_FAIL;
190 }
191
192 if (strcmp(bucket->scheme, "test")) {
193 ast_test_status_update(test, "Scheme within allocated bucket is '%s' and should be test\n",
194 bucket->scheme);
195 return AST_TEST_FAIL;
196 }
197
198 return AST_TEST_PASS;
199}
200
201AST_TEST_DEFINE(bucket_create)
202{
203 RAII_VAR(struct ast_bucket *, bucket, NULL, ao2_cleanup);
204
205 switch (cmd) {
206 case TEST_INIT:
207 info->name = "bucket_create";
208 info->category = "/main/bucket/";
209 info->summary = "bucket creation unit test";
210 info->description =
211 "Test creation of buckets";
212 return AST_TEST_NOT_RUN;
213 case TEST_EXECUTE:
214 break;
215 }
216
217 if (!(bucket = ast_bucket_alloc("test:///tmp/bob"))) {
218 ast_test_status_update(test, "Failed to allocate bucket\n");
219 return AST_TEST_FAIL;
220 }
221
223
224 if (ast_bucket_create(bucket)) {
225 ast_test_status_update(test, "Failed to create bucket with URI '%s'\n",
227 return AST_TEST_FAIL;
228 }
229
231 ast_test_status_update(test, "Bucket creation returned success but scheme implementation never actually created it\n");
232 return AST_TEST_FAIL;
233 }
234
235 if (!ast_bucket_create(bucket)) {
236 ast_test_status_update(test, "Successfully created bucket with URI '%s' twice\n",
238 return AST_TEST_FAIL;
239 }
240
241 return AST_TEST_PASS;
242}
243
244AST_TEST_DEFINE(bucket_clone)
245{
246 RAII_VAR(struct ast_bucket *, bucket, NULL, ao2_cleanup);
247 RAII_VAR(struct ast_bucket *, clone, NULL, ao2_cleanup);
248
249 switch (cmd) {
250 case TEST_INIT:
251 info->name = "bucket_clone";
252 info->category = "/main/bucket/";
253 info->summary = "bucket clone unit test";
254 info->description =
255 "Test cloning a bucket";
256 return AST_TEST_NOT_RUN;
257 case TEST_EXECUTE:
258 break;
259 }
260
261 if (!(bucket = ast_bucket_alloc("test:///tmp/bob"))) {
262 ast_test_status_update(test, "Failed to allocate bucket\n");
263 return AST_TEST_FAIL;
264 }
265
267
268 if (ast_bucket_create(bucket)) {
269 ast_test_status_update(test, "Failed to create bucket with URI '%s'\n",
271 return AST_TEST_FAIL;
272 }
273
274 clone = ast_bucket_clone(bucket);
275 if (!clone) {
276 ast_test_status_update(test, "Failed to clone bucket with URI '%s'\n",
278 return AST_TEST_FAIL;
279 }
280
281 ast_test_validate(test, strcmp(ast_sorcery_object_get_id(bucket), ast_sorcery_object_get_id(clone)) == 0);
282 ast_test_validate(test, bucket->scheme_impl == clone->scheme_impl);
283 ast_test_validate(test, strcmp(bucket->scheme, clone->scheme) == 0);
284
285 return AST_TEST_PASS;
286}
287
288AST_TEST_DEFINE(bucket_delete)
289{
290 RAII_VAR(struct ast_bucket *, bucket, NULL, ao2_cleanup);
291
292 switch (cmd) {
293 case TEST_INIT:
294 info->name = "bucket_delete";
295 info->category = "/main/bucket/";
296 info->summary = "bucket deletion unit test";
297 info->description =
298 "Test deletion of buckets";
299 return AST_TEST_NOT_RUN;
300 case TEST_EXECUTE:
301 break;
302 }
303
304 if (!(bucket = ast_bucket_alloc("test:///tmp/bob"))) {
305 ast_test_status_update(test, "Failed to allocate bucket\n");
306 return AST_TEST_FAIL;
307 }
308
310
311 if (ast_bucket_delete(bucket)) {
312 ast_test_status_update(test, "Failed to delete bucket with URI '%s'\n",
314 return AST_TEST_FAIL;
315 }
316
318 ast_test_status_update(test, "Bucket deletion returned success but scheme implementation never actually deleted it\n");
319 return AST_TEST_FAIL;
320 }
321
322 if (!ast_bucket_delete(bucket)) {
323 ast_test_status_update(test, "Successfully deleted bucket with URI '%s' twice\n",
325 return AST_TEST_FAIL;
326 }
327
328 return AST_TEST_PASS;
329}
330
331AST_TEST_DEFINE(bucket_is_stale)
332{
333 RAII_VAR(struct ast_bucket *, bucket, NULL, ao2_cleanup);
334
335 switch (cmd) {
336 case TEST_INIT:
337 info->name = "bucket_is_stale";
338 info->category = "/main/bucket/";
339 info->summary = "bucket staleness unit test";
340 info->description =
341 "Test if staleness of a bucket is reported correctly";
342 return AST_TEST_NOT_RUN;
343 case TEST_EXECUTE:
344 break;
345 }
346
347 if (!(bucket = ast_bucket_alloc("test:///tmp/bob"))) {
348 ast_test_status_update(test, "Failed to allocate bucket\n");
349 return AST_TEST_FAIL;
350 }
351
353
354 ast_test_validate(test, ast_bucket_is_stale(bucket) == 0);
355
357
358 ast_test_validate(test, ast_bucket_is_stale(bucket) == 1);
359
360 return AST_TEST_PASS;
361}
362
363AST_TEST_DEFINE(bucket_json)
364{
365 RAII_VAR(struct ast_bucket *, bucket, NULL, ao2_cleanup);
366 RAII_VAR(struct ast_json *, expected, NULL, ast_json_unref);
367 RAII_VAR(struct ast_json *, json, NULL, ast_json_unref);
368
369 switch (cmd) {
370 case TEST_INIT:
371 info->name = "bucket_json";
372 info->category = "/main/bucket/";
373 info->summary = "bucket json unit test";
374 info->description =
375 "Test creation of JSON for a bucket";
376 return AST_TEST_NOT_RUN;
377 case TEST_EXECUTE:
378 break;
379 }
380
381 if (!(bucket = ast_bucket_alloc("test:///tmp/bob"))) {
382 ast_test_status_update(test, "Failed to allocate bucket\n");
383 return AST_TEST_FAIL;
384 }
385
386 ast_str_container_add(bucket->buckets, "test:///tmp/bob/joe");
387 ast_str_container_add(bucket->files, "test:///tmp/bob/recording.wav");
388
389 expected = ast_json_pack("{s: s, s: s, s: [s], s: s, s: [s], s: s}",
390 "modified", "0.000000", "created", "0.000000",
391 "buckets", "test:///tmp/bob/joe",
392 "scheme", "test",
393 "files", "test:///tmp/bob/recording.wav",
394 "id", "test:///tmp/bob");
395 if (!expected) {
396 ast_test_status_update(test, "Could not produce JSON for expected bucket value\n");
397 return AST_TEST_FAIL;
398 }
399
400 json = ast_bucket_json(bucket);
401 if (!json) {
402 ast_test_status_update(test, "Could not produce JSON for a valid bucket\n");
403 return AST_TEST_FAIL;
404 }
405
406 if (!ast_json_equal(json, expected)) {
407 ast_test_status_update(test, "Bucket JSON does not match expected output\n");
408 return AST_TEST_FAIL;
409 }
410
411 return AST_TEST_PASS;
412}
413
414AST_TEST_DEFINE(bucket_retrieve)
415{
416 RAII_VAR(struct ast_bucket *, bucket, NULL, ao2_cleanup);
417
418 switch (cmd) {
419 case TEST_INIT:
420 info->name = "bucket_retrieve";
421 info->category = "/main/bucket/";
422 info->summary = "bucket retrieval unit test";
423 info->description =
424 "Test retrieval of buckets";
425 return AST_TEST_NOT_RUN;
426 case TEST_EXECUTE:
427 break;
428 }
429
430 if (!(bucket = ast_bucket_retrieve("test://tmp/bob"))) {
431 ast_test_status_update(test, "Failed to retrieve known valid bucket\n");
432 return AST_TEST_FAIL;
433 }
434
435 return AST_TEST_PASS;
436}
437
439{
441
442 switch (cmd) {
443 case TEST_INIT:
444 info->name = "bucket_file_alloc";
445 info->category = "/main/bucket/";
446 info->summary = "bucket file allocation unit test";
447 info->description =
448 "Test allocation of bucket files";
449 return AST_TEST_NOT_RUN;
450 case TEST_EXECUTE:
451 break;
452 }
453
454 if ((file = ast_bucket_file_alloc(""))) {
455 ast_test_status_update(test, "Allocated a file with no URI provided\n");
456 return AST_TEST_FAIL;
457 }
458
459 if (!(file = ast_bucket_file_alloc("test:///tmp/bob"))) {
460 ast_test_status_update(test, "Failed to allocate file\n");
461 return AST_TEST_FAIL;
462 }
463
464 if (ast_strlen_zero(file->path)) {
465 ast_test_status_update(test, "Expected temporary path in allocated file");
466 return AST_TEST_FAIL;
467 }
468
469 if (strcmp(ast_sorcery_object_get_id(file), "test:///tmp/bob")) {
470 ast_test_status_update(test, "URI within allocated file is '%s' and should be test:///tmp/bob\n",
472 return AST_TEST_FAIL;
473 }
474
475 if (strcmp(file->scheme, "test")) {
476 ast_test_status_update(test, "Scheme within allocated file is '%s' and should be test\n",
477 file->scheme);
478 return AST_TEST_FAIL;
479 }
480
481 return AST_TEST_PASS;
482}
483
484AST_TEST_DEFINE(bucket_file_create)
485{
487
488 switch (cmd) {
489 case TEST_INIT:
490 info->name = "bucket_file_create";
491 info->category = "/main/bucket/";
492 info->summary = "file creation unit test";
493 info->description =
494 "Test creation of files";
495 return AST_TEST_NOT_RUN;
496 case TEST_EXECUTE:
497 break;
498 }
499
500 if (!(file = ast_bucket_file_alloc("test:///tmp/bob"))) {
501 ast_test_status_update(test, "Failed to allocate file\n");
502 return AST_TEST_FAIL;
503 }
504
506
508 ast_test_status_update(test, "Failed to create file with URI '%s'\n",
510 return AST_TEST_FAIL;
511 }
512
514 ast_test_status_update(test, "Bucket file creation returned success but scheme implementation never actually created it\n");
515 return AST_TEST_FAIL;
516 }
517
519 ast_test_status_update(test, "Successfully created file with URI '%s' twice\n",
521 return AST_TEST_FAIL;
522 }
523
524 return AST_TEST_PASS;
525}
526
527AST_TEST_DEFINE(bucket_file_clone)
528{
530 RAII_VAR(struct ast_bucket_file *, clone, NULL, ao2_cleanup);
531
532 switch (cmd) {
533 case TEST_INIT:
534 info->name = "bucket_file_clone";
535 info->category = "/main/bucket/";
536 info->summary = "file clone unit test";
537 info->description =
538 "Test cloning a file";
539 return AST_TEST_NOT_RUN;
540 case TEST_EXECUTE:
541 break;
542 }
543
544 if (!(file = ast_bucket_file_alloc("test:///tmp/bob"))) {
545 ast_test_status_update(test, "Failed to allocate file\n");
546 return AST_TEST_FAIL;
547 }
548
550
552 ast_test_status_update(test, "Failed to create file with URI '%s'\n",
554 return AST_TEST_FAIL;
555 }
556 ast_bucket_file_metadata_set(file, "bob", "joe");
557
559 if (!clone) {
560 ast_test_status_update(test, "Failed to clone file with URI '%s'\n",
562 return AST_TEST_FAIL;
563 }
564
565 ast_test_validate(test, strcmp(ast_sorcery_object_get_id(file), ast_sorcery_object_get_id(clone)) == 0);
566 ast_test_validate(test, file->scheme_impl == clone->scheme_impl);
567 ast_test_validate(test, strcmp(file->scheme, clone->scheme) == 0);
568 ast_test_validate(test, ao2_container_count(file->metadata) == ao2_container_count(clone->metadata));
569
570 return AST_TEST_PASS;
571}
572
573AST_TEST_DEFINE(bucket_file_copy)
574{
577 FILE *temporary;
578 struct stat old, new;
579 RAII_VAR(struct ast_bucket_metadata *, metadata, NULL, ao2_cleanup);
580
581 switch (cmd) {
582 case TEST_INIT:
583 info->name = "bucket_file_copy";
584 info->category = "/main/bucket/";
585 info->summary = "bucket file copying unit test";
586 info->description =
587 "Test copying of bucket files";
588 return AST_TEST_NOT_RUN;
589 case TEST_EXECUTE:
590 break;
591 }
592
593 if (!(file = ast_bucket_file_alloc("test:///tmp/bob"))) {
594 ast_test_status_update(test, "Failed to allocate file\n");
595 return AST_TEST_FAIL;
596 }
597
598 ast_bucket_file_metadata_set(file, "bob", "joe");
599
600 if (!(temporary = fopen(file->path, "w"))) {
601 ast_test_status_update(test, "Failed to open temporary file '%s'\n", file->path);
602 return AST_TEST_FAIL;
603 }
604
605 fprintf(temporary, "bob");
606 fclose(temporary);
607
608 if (!(copy = ast_bucket_file_copy(file, "test:///tmp/bob2"))) {
609 ast_test_status_update(test, "Failed to copy file '%s' to test:///tmp/bob2\n",
611 return AST_TEST_FAIL;
612 }
613
614 if (stat(file->path, &old)) {
615 ast_test_status_update(test, "Failed to retrieve information on old file '%s'\n", file->path);
616 return AST_TEST_FAIL;
617 }
618
619 if (stat(copy->path, &new)) {
620 ast_test_status_update(test, "Failed to retrieve information on copy file '%s'\n", copy->path);
621 return AST_TEST_FAIL;
622 }
623
624 if (old.st_size != new.st_size) {
625 ast_test_status_update(test, "Copying of underlying temporary file failed\n");
626 return AST_TEST_FAIL;
627 }
628
629 if (ao2_container_count(file->metadata) != ao2_container_count(copy->metadata)) {
630 ast_test_status_update(test, "Number of metadata entries does not match original\n");
631 return AST_TEST_FAIL;
632 }
633
634 metadata = ast_bucket_file_metadata_get(copy, "bob");
635 if (!metadata) {
636 ast_test_status_update(test, "Copy of file does not have expected metadata\n");
637 return AST_TEST_FAIL;
638 }
639
640 if (strcmp(metadata->value, "joe")) {
641 ast_test_status_update(test, "Copy of file contains metadata for 'bob' but value is not what it should be\n");
642 return AST_TEST_FAIL;
643 }
644
645 return AST_TEST_PASS;
646}
647
648AST_TEST_DEFINE(bucket_file_retrieve)
649{
651
652 switch (cmd) {
653 case TEST_INIT:
654 info->name = "bucket_file_retrieve";
655 info->category = "/main/bucket/";
656 info->summary = "file retrieval unit test";
657 info->description =
658 "Test retrieval of files";
659 return AST_TEST_NOT_RUN;
660 case TEST_EXECUTE:
661 break;
662 }
663
664 if (!(file = ast_bucket_file_retrieve("test://tmp/bob"))) {
665 ast_test_status_update(test, "Failed to retrieve known valid file\n");
666 return AST_TEST_FAIL;
667 }
668
669 return AST_TEST_PASS;
670}
671
672AST_TEST_DEFINE(bucket_file_update)
673{
675
676 switch (cmd) {
677 case TEST_INIT:
678 info->name = "bucket_file_update";
679 info->category = "/main/bucket/";
680 info->summary = "file updating unit test";
681 info->description =
682 "Test updating of files";
683 return AST_TEST_NOT_RUN;
684 case TEST_EXECUTE:
685 break;
686 }
687
688 if (!(file = ast_bucket_file_alloc("test:///tmp/bob"))) {
689 ast_test_status_update(test, "Failed to allocate file\n");
690 return AST_TEST_FAIL;
691 }
692
694
696 ast_test_status_update(test, "Failed to update file with URI '%s'\n",
698 return AST_TEST_FAIL;
699 }
700
702 ast_test_status_update(test, "Successfully returned file was updated, but it was not\n");
703 return AST_TEST_FAIL;
704 }
705
707 ast_test_status_update(test, "Successfully updated file with URI '%s' twice\n",
709 return AST_TEST_FAIL;
710 }
711
712 return AST_TEST_PASS;
713}
714
715AST_TEST_DEFINE(bucket_file_delete)
716{
718
719 switch (cmd) {
720 case TEST_INIT:
721 info->name = "bucket_file_delete";
722 info->category = "/main/bucket/";
723 info->summary = "file deletion unit test";
724 info->description =
725 "Test deletion of files";
726 return AST_TEST_NOT_RUN;
727 case TEST_EXECUTE:
728 break;
729 }
730
731 if (!(file = ast_bucket_file_alloc("test:///tmp/bob"))) {
732 ast_test_status_update(test, "Failed to allocate file\n");
733 return AST_TEST_FAIL;
734 }
735
737
739 ast_test_status_update(test, "Failed to delete file with URI '%s'\n",
741 return AST_TEST_FAIL;
742 }
743
745 ast_test_status_update(test, "Bucket file deletion returned success but scheme implementation never actually deleted it\n");
746 return AST_TEST_FAIL;
747 }
748
750 ast_test_status_update(test, "Successfully deleted file with URI '%s' twice\n",
752 return AST_TEST_FAIL;
753 }
754
755 return AST_TEST_PASS;
756}
757
758AST_TEST_DEFINE(bucket_file_is_stale)
759{
761
762 switch (cmd) {
763 case TEST_INIT:
764 info->name = "bucket_file_is_stale";
765 info->category = "/main/bucket/";
766 info->summary = "file staleness unit test";
767 info->description =
768 "Test if staleness of a bucket file is reported correctly";
769 return AST_TEST_NOT_RUN;
770 case TEST_EXECUTE:
771 break;
772 }
773
774 if (!(file = ast_bucket_file_alloc("test:///tmp/bob"))) {
775 ast_test_status_update(test, "Failed to allocate file\n");
776 return AST_TEST_FAIL;
777 }
778
780
781 ast_test_validate(test, ast_bucket_file_is_stale(file) == 0);
782
784
785 ast_test_validate(test, ast_bucket_file_is_stale(file) == 1);
786
787 return AST_TEST_PASS;
788}
789
790AST_TEST_DEFINE(bucket_file_metadata_set)
791{
793 RAII_VAR(struct ast_bucket_metadata *, metadata, NULL, ao2_cleanup);
794
795 switch (cmd) {
796 case TEST_INIT:
797 info->name = "bucket_file_metadata_set";
798 info->category = "/main/bucket/";
799 info->summary = "file metadata setting unit test";
800 info->description =
801 "Test setting of metadata on files";
802 return AST_TEST_NOT_RUN;
803 case TEST_EXECUTE:
804 break;
805 }
806
807 if (!(file = ast_bucket_file_alloc("test:///tmp/bob"))) {
808 ast_test_status_update(test, "Failed to allocate file\n");
809 return AST_TEST_FAIL;
810 }
811
812 if (ao2_container_count(file->metadata) != 0) {
813 ast_test_status_update(test, "Newly allocated file has metadata count of '%d' when should be 0\n",
814 ao2_container_count(file->metadata));
815 return AST_TEST_FAIL;
816 }
817
818 if (ast_bucket_file_metadata_set(file, "bob", "joe")) {
819 ast_test_status_update(test, "Failed to set metadata 'bob' to 'joe' on newly allocated file\n");
820 return AST_TEST_FAIL;
821 }
822
823 if (!(metadata = ao2_find(file->metadata, "bob", OBJ_KEY))) {
824 ast_test_status_update(test, "Failed to find set metadata 'bob' on newly allocated file\n");
825 return AST_TEST_FAIL;
826 }
827
828 if (strcmp(metadata->value, "joe")) {
829 ast_test_status_update(test, "Metadata has value '%s' when should be 'joe'\n",
830 metadata->value);
831 return AST_TEST_FAIL;
832 }
833
834 ao2_cleanup(metadata);
835 metadata = NULL;
836
837 if (ast_bucket_file_metadata_set(file, "bob", "fred")) {
838 ast_test_status_update(test, "Failed to overwrite metadata 'bob' with new value 'fred'\n");
839 return AST_TEST_FAIL;
840 }
841
842 if (!(metadata = ao2_find(file->metadata, "bob", OBJ_KEY))) {
843 ast_test_status_update(test, "Failed to find overwritten metadata 'bob' on newly allocated file\n");
844 return AST_TEST_FAIL;
845 }
846
847 if (strcmp(metadata->value, "fred")) {
848 ast_test_status_update(test, "Metadata has value '%s' when should be 'fred'\n",
849 metadata->value);
850 return AST_TEST_FAIL;
851 }
852
853 return AST_TEST_PASS;
854}
855
856AST_TEST_DEFINE(bucket_file_metadata_unset)
857{
859 RAII_VAR(struct ast_bucket_metadata *, metadata, NULL, ao2_cleanup);
860
861 switch (cmd) {
862 case TEST_INIT:
863 info->name = "bucket_file_metadata_unset";
864 info->category = "/main/bucket/";
865 info->summary = "file metadata unsetting unit test";
866 info->description =
867 "Test unsetting of metadata on files";
868 return AST_TEST_NOT_RUN;
869 case TEST_EXECUTE:
870 break;
871 }
872
873 if (!(file = ast_bucket_file_alloc("test:///tmp/bob"))) {
874 ast_test_status_update(test, "Failed to allocate file\n");
875 return AST_TEST_FAIL;
876 }
877
878 if (ast_bucket_file_metadata_set(file, "bob", "joe")) {
879 ast_test_status_update(test, "Failed to set metadata 'bob' to 'joe' on newly allocated file\n");
880 return AST_TEST_FAIL;
881 }
882
884 ast_test_status_update(test, "Failed to unset metadata 'bob' on newly allocated file\n");
885 return AST_TEST_FAIL;
886 }
887
888 if ((metadata = ao2_find(file->metadata, "bob", OBJ_KEY))) {
889 ast_test_status_update(test, "Metadata 'bob' was unset, but can still be found\n");
890 return AST_TEST_FAIL;
891 }
892
893 return AST_TEST_PASS;
894}
895
896AST_TEST_DEFINE(bucket_file_metadata_get)
897{
899 RAII_VAR(struct ast_bucket_metadata *, metadata, NULL, ao2_cleanup);
900
901 switch (cmd) {
902 case TEST_INIT:
903 info->name = "bucket_file_metadata_get";
904 info->category = "/main/bucket/";
905 info->summary = "file metadata getting unit test";
906 info->description =
907 "Test getting of metadata on files";
908 return AST_TEST_NOT_RUN;
909 case TEST_EXECUTE:
910 break;
911 }
912
913 if (!(file = ast_bucket_file_alloc("test:///tmp/bob"))) {
914 ast_test_status_update(test, "Failed to allocate file\n");
915 return AST_TEST_FAIL;
916 }
917
918 if (ast_bucket_file_metadata_set(file, "bob", "joe")) {
919 ast_test_status_update(test, "Failed to set metadata 'bob' to 'joe' on newly allocated file\n");
920 return AST_TEST_FAIL;
921 }
922
923 if (!(metadata = ast_bucket_file_metadata_get(file, "bob"))) {
924 ast_test_status_update(test, "Failed to retrieve metadata 'bob' that was just set\n");
925 return AST_TEST_FAIL;
926 }
927
928 if (strcmp(metadata->value, "joe")) {
929 ast_test_status_update(test, "Retrieved metadata value is '%s' while it should be 'joe'\n",
930 metadata->value);
931 return AST_TEST_FAIL;
932 }
933
934 return AST_TEST_PASS;
935}
936
937AST_TEST_DEFINE(bucket_file_json)
938{
940 RAII_VAR(struct ast_json *, expected, NULL, ast_json_unref);
941 RAII_VAR(struct ast_json *, json, NULL, ast_json_unref);
942
943 switch (cmd) {
944 case TEST_INIT:
945 info->name = "bucket_file_json";
946 info->category = "/main/bucket/";
947 info->summary = "file json unit test";
948 info->description =
949 "Test creation of JSON for a file";
950 return AST_TEST_NOT_RUN;
951 case TEST_EXECUTE:
952 break;
953 }
954
955 if (!(file = ast_bucket_file_alloc("test:///tmp/bob"))) {
956 ast_test_status_update(test, "Failed to allocate bucket\n");
957 return AST_TEST_FAIL;
958 }
959
960 if (ast_bucket_file_metadata_set(file, "bob", "joe")) {
961 ast_test_status_update(test, "Failed to set metadata 'bob' to 'joe' on newly allocated file\n");
962 return AST_TEST_FAIL;
963 }
964
965 expected = ast_json_pack("{s: s, s: s, s: s, s: s, s: {s :s}}",
966 "modified", "0.000000", "created", "0.000000", "scheme", "test",
967 "id", "test:///tmp/bob", "metadata", "bob", "joe");
968 if (!expected) {
969 ast_test_status_update(test, "Could not produce JSON for expected bucket file value\n");
970 return AST_TEST_FAIL;
971 }
972
974 if (!json) {
975 ast_test_status_update(test, "Could not produce JSON for a valid file\n");
976 return AST_TEST_FAIL;
977 }
978
979 if (!ast_json_equal(json, expected)) {
980 ast_test_status_update(test, "Bucket file JSON does not match expected output\n");
981 return AST_TEST_FAIL;
982 }
983
984 return AST_TEST_PASS;
985}
986
987static int unload_module(void)
988{
989 AST_TEST_UNREGISTER(bucket_scheme_register);
991 AST_TEST_UNREGISTER(bucket_create);
992 AST_TEST_UNREGISTER(bucket_clone);
993 AST_TEST_UNREGISTER(bucket_delete);
994 AST_TEST_UNREGISTER(bucket_retrieve);
995 AST_TEST_UNREGISTER(bucket_json);
997 AST_TEST_UNREGISTER(bucket_file_create);
998 AST_TEST_UNREGISTER(bucket_file_clone);
999 AST_TEST_UNREGISTER(bucket_file_copy);
1000 AST_TEST_UNREGISTER(bucket_file_retrieve);
1001 AST_TEST_UNREGISTER(bucket_file_update);
1002 AST_TEST_UNREGISTER(bucket_file_delete);
1003 AST_TEST_UNREGISTER(bucket_file_metadata_set);
1004 AST_TEST_UNREGISTER(bucket_file_metadata_unset);
1005 AST_TEST_UNREGISTER(bucket_file_metadata_get);
1006 AST_TEST_UNREGISTER(bucket_file_json);
1007 return 0;
1008}
1009
1010static int load_module(void)
1011{
1014 ast_log(LOG_ERROR, "Failed to register Bucket test wizard scheme implementation\n");
1016 }
1017
1018 AST_TEST_REGISTER(bucket_scheme_register);
1020 AST_TEST_REGISTER(bucket_create);
1021 AST_TEST_REGISTER(bucket_clone);
1022 AST_TEST_REGISTER(bucket_delete);
1023 AST_TEST_REGISTER(bucket_retrieve);
1024 AST_TEST_REGISTER(bucket_is_stale);
1025 AST_TEST_REGISTER(bucket_json);
1027 AST_TEST_REGISTER(bucket_file_create);
1028 AST_TEST_REGISTER(bucket_file_clone);
1029 AST_TEST_REGISTER(bucket_file_copy);
1030 AST_TEST_REGISTER(bucket_file_retrieve);
1031 AST_TEST_REGISTER(bucket_file_update);
1032 AST_TEST_REGISTER(bucket_file_delete);
1033 AST_TEST_REGISTER(bucket_file_is_stale);
1034 AST_TEST_REGISTER(bucket_file_metadata_set);
1035 AST_TEST_REGISTER(bucket_file_metadata_unset);
1036 AST_TEST_REGISTER(bucket_file_metadata_get);
1037 AST_TEST_REGISTER(bucket_file_json);
1039}
1040
static int copy(char *infile, char *outfile)
Utility function to copy a file.
Asterisk main include file. File version handling, generic pbx functions.
#define ast_log
Definition: astobj2.c:42
#define OBJ_KEY
Definition: astobj2.h:1151
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
#define ao2_cleanup(obj)
Definition: astobj2.h:1934
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1736
static void * bucket_file_alloc(const char *name)
Allocator for bucket files.
Definition: bucket.c:640
static void * bucket_alloc(const char *name)
Allocator for buckets.
Definition: bucket.c:402
Bucket File API.
struct ast_bucket * ast_bucket_alloc(const char *uri)
Allocate a new bucket.
Definition: bucket.c:431
struct ast_bucket_file * ast_bucket_file_clone(struct ast_bucket_file *file)
Clone a bucket file.
Definition: bucket.c:810
int ast_bucket_file_metadata_set(struct ast_bucket_file *file, const char *name, const char *value)
Set a metadata attribute on a file to a specific value.
Definition: bucket.c:334
struct ast_bucket_file * ast_bucket_file_alloc(const char *uri)
Allocate a new bucket file.
Definition: bucket.c:663
#define ast_bucket_scheme_register(name, bucket, file, create_cb, destroy_cb)
Register support for a specific scheme.
Definition: bucket.h:137
int ast_bucket_file_temporary_create(struct ast_bucket_file *file)
Common file snapshot creation callback for creating a temporary file.
Definition: bucket.c:899
int ast_bucket_create(struct ast_bucket *bucket)
Create a new bucket in backend storage.
Definition: bucket.c:488
int ast_bucket_file_create(struct ast_bucket_file *file)
Create a new bucket file in backend storage.
Definition: bucket.c:725
int ast_bucket_file_metadata_unset(struct ast_bucket_file *file, const char *name)
Unset a specific metadata attribute on a file.
Definition: bucket.c:348
int ast_bucket_file_update(struct ast_bucket_file *file)
Update an existing bucket file in backend storage.
Definition: bucket.c:839
struct ast_bucket_metadata * ast_bucket_file_metadata_get(struct ast_bucket_file *file, const char *name)
Retrieve a metadata attribute from a file.
Definition: bucket.c:359
struct ast_bucket_file * ast_bucket_file_copy(struct ast_bucket_file *file, const char *uri)
Copy a bucket file to a new URI.
Definition: bucket.c:791
int ast_bucket_is_stale(struct ast_bucket *bucket)
Retrieve whether or not the backing datastore views the bucket as stale.
Definition: bucket.c:524
struct ast_bucket_file * ast_bucket_file_retrieve(const char *uri)
Retrieve a bucket file.
Definition: bucket.c:815
struct ast_bucket * ast_bucket_retrieve(const char *uri)
Retrieve information about a bucket.
Definition: bucket.c:515
int ast_bucket_file_delete(struct ast_bucket_file *file)
Delete a bucket file from backend storage.
Definition: bucket.c:844
struct ast_json * ast_bucket_json(const struct ast_bucket *bucket)
Get a JSON representation of a bucket.
Definition: bucket.c:544
struct ast_json * ast_bucket_file_json(const struct ast_bucket_file *file)
Get a JSON representation of a bucket file.
Definition: bucket.c:849
struct ast_bucket * ast_bucket_clone(struct ast_bucket *bucket)
Clone a bucket.
Definition: bucket.c:510
void ast_bucket_file_temporary_destroy(struct ast_bucket_file *file)
Common file snapshot destruction callback for deleting a temporary file.
Definition: bucket.c:914
int ast_bucket_file_is_stale(struct ast_bucket_file *file)
Retrieve whether or not the backing datastore views the bucket file as stale.
Definition: bucket.c:824
int ast_bucket_delete(struct ast_bucket *bucket)
Delete a bucket from backend storage.
Definition: bucket.c:539
static const char type[]
Definition: chan_ooh323.c:109
Generic File Format Support. Should be included by clients of the file handling routines....
Support for logging to various files, console and syslog Configuration in file logger....
#define LOG_ERROR
Asterisk JSON abstraction layer.
void ast_json_unref(struct ast_json *value)
Decrease refcount on value. If refcount reaches zero, value is freed.
Definition: json.c:73
int ast_json_equal(const struct ast_json *lhs, const struct ast_json *rhs)
Compare two JSON objects.
Definition: json.c:357
struct ast_json * ast_json_pack(char const *format,...)
Helper for creating complex JSON values.
Definition: json.c:612
Asterisk module definitions.
#define AST_MODULE_INFO_STANDARD(keystr, desc)
Definition: module.h:581
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:46
@ AST_MODULE_LOAD_SUCCESS
Definition: module.h:70
@ AST_MODULE_LOAD_DECLINE
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78
def info(msg)
static struct ast_sorcery * sorcery
#define NULL
Definition: resample.c:96
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
Definition: sorcery.c:2317
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
int ast_str_container_add(struct ao2_container *str_container, const char *add)
Adds a string to a string container allocated by ast_str_container_alloc.
Definition: strings.c:205
Bucket file structure, contains reference to file and information about it.
Definition: bucket.h:78
Bucket metadata structure, AO2 key value pair.
Definition: bucket.h:47
Bucket structure, contains other buckets and files.
Definition: bucket.h:57
Abstract JSON element (object, array, string, int, ...).
Interface for a sorcery wizard.
Definition: sorcery.h:276
const char * name
Name of the wizard.
Definition: sorcery.h:278
Full structure for sorcery.
Definition: sorcery.c:230
Test state structure for scheme wizards.
Definition: test_bucket.c:44
unsigned int updated
Whether the object has been updated or not.
Definition: test_bucket.c:48
unsigned int is_stale
Whether the object is stale or not.
Definition: test_bucket.c:52
unsigned int deleted
Whether the object has been deleted or not.
Definition: test_bucket.c:50
unsigned int created
Whether the object has been created or not.
Definition: test_bucket.c:46
Test Framework API.
@ TEST_INIT
Definition: test.h:200
@ TEST_EXECUTE
Definition: test.h:201
#define AST_TEST_REGISTER(cb)
Definition: test.h:127
#define ast_test_status_update(a, b, c...)
Definition: test.h:129
#define AST_TEST_UNREGISTER(cb)
Definition: test.h:128
@ AST_TEST_PASS
Definition: test.h:195
@ AST_TEST_FAIL
Definition: test.h:196
@ AST_TEST_NOT_RUN
Definition: test.h:194
static struct ast_sorcery_wizard bucket_file_test_wizard
Definition: test_bucket.c:124
static void * bucket_test_wizard_retrieve_id(const struct ast_sorcery *sorcery, void *data, const char *type, const char *id)
Definition: test_bucket.c:88
static int bucket_test_wizard_create(const struct ast_sorcery *sorcery, void *data, void *object)
Definition: test_bucket.c:66
static int bucket_test_wizard_update(const struct ast_sorcery *sorcery, void *data, void *object)
Definition: test_bucket.c:77
static int bucket_test_wizard_delete(const struct ast_sorcery *sorcery, void *data, void *object)
Definition: test_bucket.c:100
static void bucket_test_wizard_clear(void)
Definition: test_bucket.c:58
static struct bucket_test_state bucket_test_wizard_state
Global scope structure for testing bucket wizards.
Definition: test_bucket.c:56
static int bucket_test_wizard_is_stale(const struct ast_sorcery *sorcery, void *data, void *object)
Definition: test_bucket.c:111
AST_TEST_DEFINE(bucket_scheme_register)
Definition: test_bucket.c:133
static int load_module(void)
Definition: test_bucket.c:1010
static int unload_module(void)
Definition: test_bucket.c:987
static struct ast_sorcery_wizard bucket_test_wizard
Definition: test_bucket.c:116
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:941