test_file.c 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. /*
  2. * Asterisk -- An open source telephony toolkit.
  3. *
  4. * Copyright (C) 2016, Digium, Inc.
  5. *
  6. * Kevin Harwell <kharwell@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. /*** MODULEINFO
  19. <depend>TEST_FRAMEWORK</depend>
  20. <support_level>core</support_level>
  21. ***/
  22. #include "asterisk.h"
  23. #include <sys/stat.h>
  24. #include <stdio.h>
  25. ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
  26. #include "asterisk/file.h"
  27. #include "asterisk/paths.h"
  28. #include "asterisk/test.h"
  29. #include "asterisk/module.h"
  30. #include "asterisk/strings.h"
  31. #include "asterisk/vector.h"
  32. #define FOUND -7
  33. AST_VECTOR(_filenames, struct ast_str *);
  34. static void rm_file(struct ast_str *filename)
  35. {
  36. if (unlink(ast_str_buffer(filename))) {
  37. ast_log(LOG_ERROR, "Unable to remove file: %s\n", ast_str_buffer(filename));
  38. }
  39. ast_free(filename);
  40. }
  41. static int test_files_destroy(struct ast_test *test, char *dir_name,
  42. struct _filenames *filenames)
  43. {
  44. int res;
  45. if (filenames) {
  46. AST_VECTOR_CALLBACK_VOID(filenames, rm_file);
  47. AST_VECTOR_FREE(filenames);
  48. }
  49. if ((res = rmdir(dir_name)) < 0) {
  50. ast_test_status_update(test, "Failed to remove directory: %s\n", dir_name);
  51. }
  52. return res;
  53. }
  54. static int test_files_create(struct ast_test *test, char *dir_name,
  55. struct _filenames *filenames, int num)
  56. {
  57. int i;
  58. if (!(mkdtemp(dir_name))) {
  59. ast_test_status_update(test, "Failed to create directory: %s\n", dir_name);
  60. return -1;
  61. }
  62. AST_VECTOR_INIT(filenames, num);
  63. /*
  64. * Create "num" files under the specified directory
  65. */
  66. for (i = 0; i < num; ++i) {
  67. int fd;
  68. struct ast_str *filename = ast_str_create(32);
  69. if (!filename) {
  70. break;
  71. }
  72. ast_str_set(&filename, 0, "%s/XXXXXX", dir_name);
  73. fd = mkstemp(ast_str_buffer(filename));
  74. if (fd < 0) {
  75. ast_test_status_update(test, "Failed to create file: %s\n",
  76. ast_str_buffer(filename));
  77. ast_free(filename);
  78. break;
  79. }
  80. close(fd);
  81. AST_VECTOR_APPEND(filenames, filename);
  82. }
  83. if (i != num) {
  84. test_files_destroy(test, dir_name, filenames);
  85. return -1;
  86. }
  87. return 0;
  88. }
  89. static char *test_files_get_one(struct _filenames *filenames, int num)
  90. {
  91. /* Every file is in a directory and contains a '/' so okay to do this */
  92. return strrchr(ast_str_buffer(
  93. AST_VECTOR_GET(filenames, ast_random() % (num - 1))), '/') + 1;
  94. }
  95. static int handle_find_file(const char *dir_name, const char *filename, void *obj)
  96. {
  97. struct stat statbuf;
  98. char *full_path = ast_alloca(strlen(dir_name) + strlen(filename) + 2);
  99. sprintf(full_path, "%s/%s", dir_name, filename);
  100. errno = 0;
  101. if (stat(full_path, &statbuf)) {
  102. ast_log(LOG_ERROR, "Error reading path stats - %s: %s\n",
  103. full_path, strerror(errno));
  104. return 0;
  105. }
  106. /* obj contains the name of the file we are looking for */
  107. return strcmp(obj, filename) ? 0 : FOUND;
  108. }
  109. AST_TEST_DEFINE(read_dirs_test)
  110. {
  111. char tmp_dir[] = "/tmp/tmpdir.XXXXXX";
  112. struct ast_str *tmp_sub_dir;
  113. struct _filenames filenames;
  114. enum ast_test_result_state res;
  115. const int num_files = 10 + (ast_random() % 10); /* 10-19 random files */
  116. switch (cmd) {
  117. case TEST_INIT:
  118. info->name = "read_dir_test";
  119. info->category = "/main/file/";
  120. info->summary = "Read a directory's content";
  121. info->description = "Iterate over directories looking for a file.";
  122. return AST_TEST_NOT_RUN;
  123. case TEST_EXECUTE:
  124. break;
  125. }
  126. /*
  127. * We want to test recursively searching into a subdirectory, so
  128. * create a top level tmp directory where we will start the search.
  129. */
  130. if (!(mkdtemp(tmp_dir))) {
  131. ast_test_status_update(test, "Failed to create directory: %s\n", tmp_dir);
  132. return AST_TEST_FAIL;
  133. }
  134. tmp_sub_dir = ast_str_alloca(32);
  135. ast_str_set(&tmp_sub_dir, 0, "%s/XXXXXX", tmp_dir);
  136. if (test_files_create(test, ast_str_buffer(tmp_sub_dir), &filenames, num_files)) {
  137. test_files_destroy(test, tmp_dir, NULL);
  138. return AST_TEST_FAIL;
  139. }
  140. res = ast_file_read_dirs(tmp_dir, handle_find_file, test_files_get_one(
  141. &filenames, num_files), 2) == FOUND ? AST_TEST_PASS : AST_TEST_FAIL;
  142. if (test_files_destroy(test, ast_str_buffer(tmp_sub_dir), &filenames) ||
  143. test_files_destroy(test, tmp_dir, NULL)) {
  144. res = AST_TEST_FAIL;
  145. }
  146. return res;
  147. }
  148. static int unload_module(void)
  149. {
  150. AST_TEST_UNREGISTER(read_dirs_test);
  151. return 0;
  152. }
  153. static int load_module(void)
  154. {
  155. AST_TEST_REGISTER(read_dirs_test);
  156. return AST_MODULE_LOAD_SUCCESS;
  157. }
  158. AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "File test module");