/* * Asterisk -- An open source telephony toolkit. * * Copyright (C) 2016, Digium, Inc. * * Kevin Harwell * * See http://www.asterisk.org for more information about * the Asterisk project. Please do not directly contact * any of the maintainers of this project for assistance; * the project provides a web site, mailing lists and IRC * channels for your use. * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. */ /*** MODULEINFO TEST_FRAMEWORK core ***/ #include "asterisk.h" #include #include #include "asterisk/file.h" #include "asterisk/paths.h" #include "asterisk/test.h" #include "asterisk/module.h" #include "asterisk/strings.h" #include "asterisk/vector.h" #define FOUND -7 AST_VECTOR(_filenames, struct ast_str *); static void rm_file(struct ast_str *filename) { if (unlink(ast_str_buffer(filename))) { ast_log(LOG_ERROR, "Unable to remove file: %s\n", ast_str_buffer(filename)); } ast_free(filename); } static int test_files_destroy(struct ast_test *test, char *dir_name, struct _filenames *filenames) { int res; if (filenames) { AST_VECTOR_CALLBACK_VOID(filenames, rm_file); AST_VECTOR_FREE(filenames); } if ((res = rmdir(dir_name)) < 0) { ast_test_status_update(test, "Failed to remove directory: %s\n", dir_name); } return res; } static int test_files_create(struct ast_test *test, char *dir_name, struct _filenames *filenames, int num) { int i; if (!(mkdtemp(dir_name))) { ast_test_status_update(test, "Failed to create directory: %s\n", dir_name); return -1; } AST_VECTOR_INIT(filenames, num); /* * Create "num" files under the specified directory */ for (i = 0; i < num; ++i) { int fd; struct ast_str *filename = ast_str_create(32); if (!filename) { break; } ast_str_set(&filename, 0, "%s/XXXXXX", dir_name); fd = mkstemp(ast_str_buffer(filename)); if (fd < 0) { ast_test_status_update(test, "Failed to create file: %s\n", ast_str_buffer(filename)); ast_free(filename); break; } close(fd); AST_VECTOR_APPEND(filenames, filename); } if (i != num) { test_files_destroy(test, dir_name, filenames); return -1; } return 0; } static char *test_files_get_one(struct _filenames *filenames, int num) { /* Every file is in a directory and contains a '/' so okay to do this */ return strrchr(ast_str_buffer( AST_VECTOR_GET(filenames, ast_random() % (num - 1))), '/') + 1; } static int handle_find_file(const char *dir_name, const char *filename, void *obj) { struct stat statbuf; char *full_path = ast_alloca(strlen(dir_name) + strlen(filename) + 2); sprintf(full_path, "%s/%s", dir_name, filename); errno = 0; if (stat(full_path, &statbuf)) { ast_log(LOG_ERROR, "Error reading path stats - %s: %s\n", full_path, strerror(errno)); return 0; } /* obj contains the name of the file we are looking for */ return strcmp(obj, filename) ? 0 : FOUND; } AST_TEST_DEFINE(read_dirs_test) { char tmp_dir[] = "/tmp/tmpdir.XXXXXX"; struct ast_str *tmp_sub_dir; struct _filenames filenames; enum ast_test_result_state res; const int num_files = 10 + (ast_random() % 10); /* 10-19 random files */ switch (cmd) { case TEST_INIT: info->name = "read_dir_test"; info->category = "/main/file/"; info->summary = "Read a directory's content"; info->description = "Iterate over directories looking for a file."; return AST_TEST_NOT_RUN; case TEST_EXECUTE: break; } /* * We want to test recursively searching into a subdirectory, so * create a top level tmp directory where we will start the search. */ if (!(mkdtemp(tmp_dir))) { ast_test_status_update(test, "Failed to create directory: %s\n", tmp_dir); return AST_TEST_FAIL; } tmp_sub_dir = ast_str_alloca(32); ast_str_set(&tmp_sub_dir, 0, "%s/XXXXXX", tmp_dir); if (test_files_create(test, ast_str_buffer(tmp_sub_dir), &filenames, num_files)) { test_files_destroy(test, tmp_dir, NULL); return AST_TEST_FAIL; } res = ast_file_read_dirs(tmp_dir, handle_find_file, test_files_get_one( &filenames, num_files), 2) == FOUND ? AST_TEST_PASS : AST_TEST_FAIL; if (test_files_destroy(test, ast_str_buffer(tmp_sub_dir), &filenames) || test_files_destroy(test, tmp_dir, NULL)) { res = AST_TEST_FAIL; } return res; } static int unload_module(void) { AST_TEST_UNREGISTER(read_dirs_test); return 0; } static int load_module(void) { AST_TEST_REGISTER(read_dirs_test); return AST_MODULE_LOAD_SUCCESS; } AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "File test module");