Asterisk - The Open Source Telephony Project GIT-master-a358458
test_file.c
Go to the documentation of this file.
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
19/*** MODULEINFO
20 <depend>TEST_FRAMEWORK</depend>
21 <support_level>core</support_level>
22 ***/
23
24
25#include "asterisk.h"
26#include <sys/stat.h>
27#include <stdio.h>
28
29#include "asterisk/file.h"
30#include "asterisk/paths.h"
31#include "asterisk/test.h"
32#include "asterisk/module.h"
33#include "asterisk/strings.h"
34#include "asterisk/vector.h"
35
36#define FOUND -7
37
39
40static void rm_file(struct ast_str *filename)
41{
42 if (unlink(ast_str_buffer(filename))) {
43 ast_log(LOG_ERROR, "Unable to remove file: %s\n", ast_str_buffer(filename));
44 }
45
46 ast_free(filename);
47}
48
49static int test_files_destroy(struct ast_test *test, char *dir_name,
50 struct _filenames *filenames)
51{
52 int res;
53
54 if (filenames) {
56 AST_VECTOR_FREE(filenames);
57 }
58
59 if ((res = rmdir(dir_name)) < 0) {
60 ast_test_status_update(test, "Failed to remove directory: %s\n", dir_name);
61 }
62
63 return res;
64}
65
66static int test_files_create(struct ast_test *test, char *dir_name,
67 struct _filenames *filenames, int num)
68{
69 int i;
70
71 if (!(mkdtemp(dir_name))) {
72 ast_test_status_update(test, "Failed to create directory: %s\n", dir_name);
73 return -1;
74 }
75
76
77 AST_VECTOR_INIT(filenames, num);
78
79 /*
80 * Create "num" files under the specified directory
81 */
82 for (i = 0; i < num; ++i) {
83 int fd;
84 struct ast_str *filename = ast_str_create(32);
85
86 if (!filename) {
87 break;
88 }
89
90 ast_str_set(&filename, 0, "%s/XXXXXX", dir_name);
91
92 fd = mkstemp(ast_str_buffer(filename));
93 if (fd < 0) {
94 ast_test_status_update(test, "Failed to create file: %s\n",
95 ast_str_buffer(filename));
96 ast_free(filename);
97 break;
98 }
99 close(fd);
100
101 AST_VECTOR_APPEND(filenames, filename);
102 }
103
104 if (i != num) {
105 test_files_destroy(test, dir_name, filenames);
106 return -1;
107 }
108
109 return 0;
110}
111
112static char *test_files_get_one(struct _filenames *filenames, int num)
113{
114 /* Every file is in a directory and contains a '/' so okay to do this */
115 return strrchr(ast_str_buffer(
116 AST_VECTOR_GET(filenames, ast_random() % (num - 1))), '/') + 1;
117}
118
119static int handle_find_file(const char *dir_name, const char *filename, void *obj)
120{
121 struct stat statbuf;
122 char *full_path = ast_alloca(strlen(dir_name) + strlen(filename) + 2);
123
124 sprintf(full_path, "%s/%s", dir_name, filename);
125
126 errno = 0;
127 if (stat(full_path, &statbuf)) {
128 ast_log(LOG_ERROR, "Error reading path stats - %s: %s\n",
129 full_path, strerror(errno));
130 return 0;
131 }
132 /* obj contains the name of the file we are looking for */
133 return strcmp(obj, filename) ? 0 : FOUND;
134}
135
136AST_TEST_DEFINE(read_dirs_test)
137{
138 char tmp_dir[] = "/tmp/tmpdir.XXXXXX";
139 struct ast_str *tmp_sub_dir;
140 struct _filenames filenames;
141 enum ast_test_result_state res;
142 const int num_files = 10 + (ast_random() % 10); /* 10-19 random files */
143
144 switch (cmd) {
145 case TEST_INIT:
146 info->name = "read_dir_test";
147 info->category = "/main/file/";
148 info->summary = "Read a directory's content";
149 info->description = "Iterate over directories looking for a file.";
150 return AST_TEST_NOT_RUN;
151 case TEST_EXECUTE:
152 break;
153 }
154
155 /*
156 * We want to test recursively searching into a subdirectory, so
157 * create a top level tmp directory where we will start the search.
158 */
159 if (!(mkdtemp(tmp_dir))) {
160 ast_test_status_update(test, "Failed to create directory: %s\n", tmp_dir);
161 return AST_TEST_FAIL;
162 }
163
164 tmp_sub_dir = ast_str_alloca(32);
165 ast_str_set(&tmp_sub_dir, 0, "%s/XXXXXX", tmp_dir);
166
167 if (test_files_create(test, ast_str_buffer(tmp_sub_dir), &filenames, num_files)) {
168 test_files_destroy(test, tmp_dir, NULL);
169 return AST_TEST_FAIL;
170 }
171
173 &filenames, num_files), 2) == FOUND ? AST_TEST_PASS : AST_TEST_FAIL;
174
175 if (test_files_destroy(test, ast_str_buffer(tmp_sub_dir), &filenames) ||
176 test_files_destroy(test, tmp_dir, NULL)) {
177 res = AST_TEST_FAIL;
178 }
179
180 return res;
181}
182
183static int unload_module(void)
184{
185 AST_TEST_UNREGISTER(read_dirs_test);
186 return 0;
187}
188
189static int load_module(void)
190{
191 AST_TEST_REGISTER(read_dirs_test);
193}
194
Asterisk main include file. File version handling, generic pbx functions.
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: astmm.h:288
#define ast_free(a)
Definition: astmm.h:180
#define ast_log
Definition: astobj2.c:42
Generic File Format Support. Should be included by clients of the file handling routines....
int ast_file_read_dirs(const char *dir_name, ast_file_on_file on_file, void *obj, int max_depth)
Recursively iterate through files and directories up to max_depth.
Definition: file.c:1274
char * mkdtemp(char *template_s)
#define LOG_ERROR
int errno
Asterisk module definitions.
#define AST_MODULE_INFO_STANDARD(keystr, desc)
Definition: module.h:567
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:46
@ AST_MODULE_LOAD_SUCCESS
Definition: module.h:70
def info(msg)
Asterisk file paths, configured in asterisk.conf.
#define NULL
Definition: resample.c:96
String manipulation functions.
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:761
#define ast_str_alloca(init_len)
Definition: strings.h:848
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
Definition: strings.h:659
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
Definition: strings.h:1113
Support for dynamic strings.
Definition: strings.h:623
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_result_state
Definition: test.h:193
@ AST_TEST_PASS
Definition: test.h:195
@ AST_TEST_FAIL
Definition: test.h:196
@ AST_TEST_NOT_RUN
Definition: test.h:194
static int test_files_destroy(struct ast_test *test, char *dir_name, struct _filenames *filenames)
Definition: test_file.c:49
#define FOUND
Definition: test_file.c:36
static char * test_files_get_one(struct _filenames *filenames, int num)
Definition: test_file.c:112
static int test_files_create(struct ast_test *test, char *dir_name, struct _filenames *filenames, int num)
Definition: test_file.c:66
static int handle_find_file(const char *dir_name, const char *filename, void *obj)
Definition: test_file.c:119
static int load_module(void)
Definition: test_file.c:189
static int unload_module(void)
Definition: test_file.c:183
static void rm_file(struct ast_str *filename)
Definition: test_file.c:40
AST_TEST_DEFINE(read_dirs_test)
Definition: test_file.c:136
long int ast_random(void)
Definition: utils.c:2312
Vector container support.
#define AST_VECTOR_FREE(vec)
Deallocates this vector.
Definition: vector.h:174
#define AST_VECTOR_INIT(vec, size)
Initialize a vector.
Definition: vector.h:113
#define AST_VECTOR_APPEND(vec, elem)
Append an element to a vector, growing the vector if needed.
Definition: vector.h:256
#define AST_VECTOR_CALLBACK_VOID(vec, callback,...)
Execute a callback on every element in a vector disregarding callback return.
Definition: vector.h:862
#define AST_VECTOR(name, type)
Define a vector structure.
Definition: vector.h:44
#define AST_VECTOR_GET(vec, idx)
Get an element from a vector.
Definition: vector.h:680