xref: /aosp_15_r20/external/cronet/third_party/apache-portable-runtime/src/test/testdir.c (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 /* Licensed to the Apache Software Foundation (ASF) under one or more
2  * contributor license agreements.  See the NOTICE file distributed with
3  * this work for additional information regarding copyright ownership.
4  * The ASF licenses this file to You under the Apache License, Version 2.0
5  * (the "License"); you may not use this file except in compliance with
6  * the License.  You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include "apr_file_io.h"
21 #include "apr_file_info.h"
22 #include "apr_errno.h"
23 #include "apr_general.h"
24 #include "apr_lib.h"
25 #include "apr_thread_proc.h"
26 #include "testutil.h"
27 
test_mkdir(abts_case * tc,void * data)28 static void test_mkdir(abts_case *tc, void *data)
29 {
30     apr_status_t rv;
31     apr_finfo_t finfo;
32 
33     rv = apr_dir_make("data/testdir", APR_UREAD | APR_UWRITE | APR_UEXECUTE, p);
34     ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
35 
36     rv = apr_stat(&finfo, "data/testdir", APR_FINFO_TYPE, p);
37     ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
38     ABTS_INT_EQUAL(tc, APR_DIR, finfo.filetype);
39 }
40 
test_mkdir_recurs(abts_case * tc,void * data)41 static void test_mkdir_recurs(abts_case *tc, void *data)
42 {
43     apr_status_t rv;
44     apr_finfo_t finfo;
45 
46     rv = apr_dir_make_recursive("data/one/two/three",
47                                 APR_UREAD | APR_UWRITE | APR_UEXECUTE, p);
48     ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
49 
50     rv = apr_stat(&finfo, "data/one", APR_FINFO_TYPE, p);
51     ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
52     ABTS_INT_EQUAL(tc, APR_DIR, finfo.filetype);
53 
54     rv = apr_stat(&finfo, "data/one/two", APR_FINFO_TYPE, p);
55     ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
56     ABTS_INT_EQUAL(tc, APR_DIR, finfo.filetype);
57 
58     rv = apr_stat(&finfo, "data/one/two/three", APR_FINFO_TYPE, p);
59     ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
60     ABTS_INT_EQUAL(tc, APR_DIR, finfo.filetype);
61 }
62 
63 struct thread_data
64 {
65     abts_case *tc;
66     apr_pool_t *pool;
67 };
68 
thread_mkdir_func(apr_thread_t * thd,void * data)69 static void *APR_THREAD_FUNC thread_mkdir_func(apr_thread_t *thd, void *data)
70 {
71     struct thread_data *td = data;
72     apr_status_t s1, s2, s3, s4, s5;
73 
74     s1 = apr_dir_make_recursive("data/prll/one/thwo/three",
75                                 APR_FPROT_UREAD | APR_FPROT_UWRITE | APR_FPROT_UEXECUTE,
76                                 td->pool);
77     s2 = apr_dir_make_recursive("data/prll/four/five/six/seven/eight",
78                                 APR_FPROT_UREAD | APR_FPROT_UWRITE | APR_FPROT_UEXECUTE,
79                                 td->pool);
80     s3 = apr_dir_make_recursive("data/prll/nine/ten",
81                                 APR_FPROT_UREAD | APR_FPROT_UWRITE | APR_FPROT_UEXECUTE,
82                                 td->pool);
83     s4 = apr_dir_make_recursive("data/prll/11/12/13/14/15/16/17/18/19/20",
84                                 APR_FPROT_UREAD | APR_FPROT_UWRITE | APR_FPROT_UEXECUTE,
85                                 td->pool);
86     s5 = apr_dir_make_recursive("data/fortytwo",
87                                 APR_FPROT_UREAD | APR_FPROT_UWRITE | APR_FPROT_UEXECUTE,
88                                 td->pool);
89 
90     ABTS_INT_EQUAL(td->tc, APR_SUCCESS, s1);
91     ABTS_INT_EQUAL(td->tc, APR_SUCCESS, s2);
92     ABTS_INT_EQUAL(td->tc, APR_SUCCESS, s3);
93     ABTS_INT_EQUAL(td->tc, APR_SUCCESS, s4);
94     ABTS_INT_EQUAL(td->tc, APR_SUCCESS, s5);
95     return NULL;
96 }
97 
test_mkdir_recurs_parallel(abts_case * tc,void * data)98 static void test_mkdir_recurs_parallel(abts_case *tc, void *data)
99 {
100     struct thread_data td1, td2, td3, td4;
101     apr_thread_t *t1, *t2, *t3, *t4;
102     apr_status_t s1, s2, s3, s4;
103 
104     td1.tc = td2.tc = td3.tc = td4.tc = tc;
105     apr_pool_create(&td1.pool, p);
106     apr_pool_create(&td2.pool, p);
107     apr_pool_create(&td3.pool, p);
108     apr_pool_create(&td4.pool, p);
109 
110     s1 = apr_thread_create(&t1, NULL, thread_mkdir_func, &td1, td1.pool);
111     ABTS_INT_EQUAL(tc, APR_SUCCESS, s1);
112     s2 = apr_thread_create(&t2, NULL, thread_mkdir_func, &td2, td2.pool);
113     ABTS_INT_EQUAL(tc, APR_SUCCESS, s2);
114     s3 = apr_thread_create(&t3, NULL, thread_mkdir_func, &td3, td3.pool);
115     ABTS_INT_EQUAL(tc, APR_SUCCESS, s3);
116     s4 = apr_thread_create(&t4, NULL, thread_mkdir_func, &td4, td4.pool);
117     ABTS_INT_EQUAL(tc, APR_SUCCESS, s4);
118 
119     apr_thread_join(&s1, t1);
120     apr_thread_join(&s2, t2);
121     apr_thread_join(&s3, t3);
122     apr_thread_join(&s4, t4);
123 
124     ABTS_INT_EQUAL(tc, APR_SUCCESS, s1);
125     ABTS_INT_EQUAL(tc, APR_SUCCESS, s2);
126     ABTS_INT_EQUAL(tc, APR_SUCCESS, s3);
127     ABTS_INT_EQUAL(tc, APR_SUCCESS, s4);
128 }
129 
test_remove(abts_case * tc,void * data)130 static void test_remove(abts_case *tc, void *data)
131 {
132     apr_status_t rv;
133     apr_finfo_t finfo;
134 
135     rv = apr_dir_remove("data/testdir", p);
136     ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
137 
138     rv = apr_stat(&finfo, "data/testdir", APR_FINFO_TYPE, p);
139     ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_ENOENT(rv));
140 }
141 
test_removeall_fail(abts_case * tc,void * data)142 static void test_removeall_fail(abts_case *tc, void *data)
143 {
144     apr_status_t rv;
145 
146     rv = apr_dir_remove("data/one", p);
147     ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_ENOTEMPTY(rv));
148 }
149 
test_removeall(abts_case * tc,void * data)150 static void test_removeall(abts_case *tc, void *data)
151 {
152     apr_status_t rv;
153 
154     rv = apr_dir_remove("data/one/two/three", p);
155     ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
156 
157     rv = apr_dir_remove("data/one/two", p);
158     ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
159 
160     rv = apr_dir_remove("data/one", p);
161     ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
162 
163     rv = apr_dir_remove("data/prll/one/thwo/three", p);
164     ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
165 
166     rv = apr_dir_remove("data/prll/one/thwo", p);
167     ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
168 
169     rv = apr_dir_remove("data/prll/one", p);
170     ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
171 
172     rv = apr_dir_remove("data/prll/four/five/six/seven/eight", p);
173     ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
174 
175     rv = apr_dir_remove("data/prll/four/five/six/seven", p);
176     ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
177 
178     rv = apr_dir_remove("data/prll/four/five/six", p);
179     ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
180 
181     rv = apr_dir_remove("data/prll/four/five", p);
182     ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
183 
184     rv = apr_dir_remove("data/prll/four", p);
185     ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
186 
187     rv = apr_dir_remove("data/prll/nine/ten", p);
188     ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
189 
190     rv = apr_dir_remove("data/prll/nine", p);
191     ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
192 
193     rv = apr_dir_remove("data/prll/11/12/13/14/15/16/17/18/19/20", p);
194     ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
195 
196     rv = apr_dir_remove("data/prll/11/12/13/14/15/16/17/18/19", p);
197     ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
198 
199     rv = apr_dir_remove("data/prll/11/12/13/14/15/16/17/18", p);
200     ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
201 
202     rv = apr_dir_remove("data/prll/11/12/13/14/15/16/17", p);
203     ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
204 
205     rv = apr_dir_remove("data/prll/11/12/13/14/15/16", p);
206     ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
207 
208     rv = apr_dir_remove("data/prll/11/12/13/14/15", p);
209     ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
210 
211     rv = apr_dir_remove("data/prll/11/12/13/14", p);
212     ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
213 
214     rv = apr_dir_remove("data/prll/11/12/13", p);
215     ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
216 
217     rv = apr_dir_remove("data/prll/11/12", p);
218     ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
219 
220     rv = apr_dir_remove("data/prll/11", p);
221     ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
222 
223     rv = apr_dir_remove("data/prll", p);
224     ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
225 
226     rv = apr_dir_remove("data/fortytwo", p);
227     ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
228 }
229 
test_remove_notthere(abts_case * tc,void * data)230 static void test_remove_notthere(abts_case *tc, void *data)
231 {
232     apr_status_t rv;
233 
234     rv = apr_dir_remove("data/notthere", p);
235     ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_ENOENT(rv));
236 }
237 
test_mkdir_twice(abts_case * tc,void * data)238 static void test_mkdir_twice(abts_case *tc, void *data)
239 {
240     apr_status_t rv;
241 
242     rv = apr_dir_make("data/testdir", APR_UREAD | APR_UWRITE | APR_UEXECUTE, p);
243     ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
244 
245     rv = apr_dir_make("data/testdir", APR_UREAD | APR_UWRITE | APR_UEXECUTE, p);
246     ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_EEXIST(rv));
247 
248     rv = apr_dir_remove("data/testdir", p);
249     ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
250 }
251 
test_opendir(abts_case * tc,void * data)252 static void test_opendir(abts_case *tc, void *data)
253 {
254     apr_status_t rv;
255     apr_dir_t *dir;
256 
257     rv = apr_dir_open(&dir, "data", p);
258     ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
259     apr_dir_close(dir);
260 }
261 
test_opendir_notthere(abts_case * tc,void * data)262 static void test_opendir_notthere(abts_case *tc, void *data)
263 {
264     apr_status_t rv;
265     apr_dir_t *dir;
266 
267     rv = apr_dir_open(&dir, "notthere", p);
268     ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_ENOENT(rv));
269 }
270 
test_closedir(abts_case * tc,void * data)271 static void test_closedir(abts_case *tc, void *data)
272 {
273     apr_status_t rv;
274     apr_dir_t *dir;
275 
276     rv = apr_dir_open(&dir, "data", p);
277     ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
278     rv = apr_dir_close(dir);
279     ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
280 }
281 
test_rewind(abts_case * tc,void * data)282 static void test_rewind(abts_case *tc, void *data)
283 {
284     apr_dir_t *dir;
285     apr_finfo_t first, second;
286 
287     APR_ASSERT_SUCCESS(tc, "apr_dir_open failed", apr_dir_open(&dir, "data", p));
288 
289     APR_ASSERT_SUCCESS(tc, "apr_dir_read failed",
290                        apr_dir_read(&first, APR_FINFO_DIRENT, dir));
291 
292     APR_ASSERT_SUCCESS(tc, "apr_dir_rewind failed", apr_dir_rewind(dir));
293 
294     APR_ASSERT_SUCCESS(tc, "second apr_dir_read failed",
295                        apr_dir_read(&second, APR_FINFO_DIRENT, dir));
296 
297     APR_ASSERT_SUCCESS(tc, "apr_dir_close failed", apr_dir_close(dir));
298 
299     ABTS_STR_EQUAL(tc, first.name, second.name);
300 }
301 
302 /* Test for a (fixed) bug in apr_dir_read().  This bug only happened
303    in threadless cases. */
test_uncleared_errno(abts_case * tc,void * data)304 static void test_uncleared_errno(abts_case *tc, void *data)
305 {
306     apr_file_t *thefile = NULL;
307     apr_finfo_t finfo;
308     apr_int32_t finfo_flags = APR_FINFO_TYPE | APR_FINFO_NAME;
309     apr_dir_t *this_dir;
310     apr_status_t rv;
311 
312     rv = apr_dir_make("dir1", APR_OS_DEFAULT, p);
313     ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
314     rv = apr_dir_make("dir2", APR_OS_DEFAULT, p);
315     ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
316     rv = apr_file_open(&thefile, "dir1/file1",
317                        APR_FOPEN_READ | APR_FOPEN_WRITE | APR_FOPEN_CREATE, APR_OS_DEFAULT, p);
318     ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
319     rv = apr_file_close(thefile);
320     ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
321 
322     /* Try to remove dir1.  This should fail because it's not empty.
323        However, on a platform with threads disabled (such as FreeBSD),
324        `errno' will be set as a result. */
325     rv = apr_dir_remove("dir1", p);
326     ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_ENOTEMPTY(rv));
327 
328     /* Read `.' and `..' out of dir2. */
329     rv = apr_dir_open(&this_dir, "dir2", p);
330     ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
331     rv = apr_dir_read(&finfo, finfo_flags, this_dir);
332     ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
333     rv = apr_dir_read(&finfo, finfo_flags, this_dir);
334     ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
335 
336     /* Now, when we attempt to do a third read of empty dir2, and the
337        underlying system readdir() returns NULL, the old value of
338        errno shouldn't cause a false alarm.  We should get an ENOENT
339        back from apr_dir_read, and *not* the old errno. */
340     rv = apr_dir_read(&finfo, finfo_flags, this_dir);
341     ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_ENOENT(rv));
342 
343     rv = apr_dir_close(this_dir);
344     ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
345 
346     /* Cleanup */
347     rv = apr_file_remove("dir1/file1", p);
348     ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
349     rv = apr_dir_remove("dir1", p);
350     ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
351     rv = apr_dir_remove("dir2", p);
352     ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
353 
354 }
355 
test_rmkdir_nocwd(abts_case * tc,void * data)356 static void test_rmkdir_nocwd(abts_case *tc, void *data)
357 {
358     char *cwd, *path;
359 
360     APR_ASSERT_SUCCESS(tc, "make temp dir",
361                        apr_dir_make("dir3", APR_OS_DEFAULT, p));
362 
363     APR_ASSERT_SUCCESS(tc, "obtain cwd", apr_filepath_get(&cwd, 0, p));
364 
365     APR_ASSERT_SUCCESS(tc, "determine path to temp dir",
366                        apr_filepath_merge(&path, cwd, "dir3", 0, p));
367 
368     APR_ASSERT_SUCCESS(tc, "change to temp dir", apr_filepath_set(path, p));
369 
370     APR_ASSERT_SUCCESS(tc, "restore cwd", apr_filepath_set(cwd, p));
371 
372     APR_ASSERT_SUCCESS(tc, "remove cwd", apr_dir_remove(path, p));
373 }
374 
375 
testdir(abts_suite * suite)376 abts_suite *testdir(abts_suite *suite)
377 {
378     suite = ADD_SUITE(suite)
379 
380     abts_run_test(suite, test_mkdir, NULL);
381     abts_run_test(suite, test_mkdir_recurs, NULL);
382     abts_run_test(suite, test_mkdir_recurs_parallel, NULL);
383     abts_run_test(suite, test_remove, NULL);
384     abts_run_test(suite, test_removeall_fail, NULL);
385     abts_run_test(suite, test_removeall, NULL);
386     abts_run_test(suite, test_remove_notthere, NULL);
387     abts_run_test(suite, test_mkdir_twice, NULL);
388     abts_run_test(suite, test_rmkdir_nocwd, NULL);
389 
390     abts_run_test(suite, test_rewind, NULL);
391 
392     abts_run_test(suite, test_opendir, NULL);
393     abts_run_test(suite, test_opendir_notthere, NULL);
394     abts_run_test(suite, test_closedir, NULL);
395     abts_run_test(suite, test_uncleared_errno, NULL);
396 
397     return suite;
398 }
399 
400