xref: /netbsd/external/bsd/atf/dist/tools/fs_test.cpp (revision ee44dd6c)
1 //
2 // Automated Testing Framework (atf)
3 //
4 // Copyright (c) 2007 The NetBSD Foundation, Inc.
5 // All rights reserved.
6 //
7 // Redistribution and use in source and binary forms, with or without
8 // modification, are permitted provided that the following conditions
9 // are met:
10 // 1. Redistributions of source code must retain the above copyright
11 //    notice, this list of conditions and the following disclaimer.
12 // 2. Redistributions in binary form must reproduce the above copyright
13 //    notice, this list of conditions and the following disclaimer in the
14 //    documentation and/or other materials provided with the distribution.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND
17 // CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
18 // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19 // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 // IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY
21 // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
23 // GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25 // IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26 // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27 // IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 //
29 
30 extern "C" {
31 #include <sys/types.h>
32 #include <sys/stat.h>
33 }
34 
35 #include <cerrno>
36 #include <cstdio>
37 #include <fstream>
38 
39 #include <atf-c++.hpp>
40 
41 #include "exceptions.hpp"
42 #include "fs.hpp"
43 #include "user.hpp"
44 
45 // ------------------------------------------------------------------------
46 // Auxiliary functions.
47 // ------------------------------------------------------------------------
48 
49 static
50 void
create_file(const char * name)51 create_file(const char *name)
52 {
53     std::ofstream os(name);
54     os.close();
55 }
56 
57 static
58 void
create_files(void)59 create_files(void)
60 {
61     ::mkdir("files", 0755);
62     ::mkdir("files/dir", 0755);
63 
64     std::ofstream os("files/reg");
65     os.close();
66 
67     // TODO: Should create all other file types (blk, chr, fifo, lnk, sock)
68     // and test for them... but the underlying file system may not support
69     // most of these.  Specially as we are working on /tmp, which can be
70     // mounted with flags such as "nodev".  See how to deal with this
71     // situation.
72 }
73 
74 // ------------------------------------------------------------------------
75 // Test cases for the "path" class.
76 // ------------------------------------------------------------------------
77 
78 ATF_TEST_CASE(path_normalize);
ATF_TEST_CASE_HEAD(path_normalize)79 ATF_TEST_CASE_HEAD(path_normalize)
80 {
81     set_md_var("descr", "Tests the path's normalization");
82 }
ATF_TEST_CASE_BODY(path_normalize)83 ATF_TEST_CASE_BODY(path_normalize)
84 {
85     using tools::fs::path;
86 
87     ATF_REQUIRE_EQ(path(".").str(), ".");
88     ATF_REQUIRE_EQ(path("..").str(), "..");
89 
90     ATF_REQUIRE_EQ(path("foo").str(), "foo");
91     ATF_REQUIRE_EQ(path("foo/bar").str(), "foo/bar");
92     ATF_REQUIRE_EQ(path("foo/bar/").str(), "foo/bar");
93 
94     ATF_REQUIRE_EQ(path("/foo").str(), "/foo");
95     ATF_REQUIRE_EQ(path("/foo/bar").str(), "/foo/bar");
96     ATF_REQUIRE_EQ(path("/foo/bar/").str(), "/foo/bar");
97 
98     ATF_REQUIRE_EQ(path("///foo").str(), "/foo");
99     ATF_REQUIRE_EQ(path("///foo///bar").str(), "/foo/bar");
100     ATF_REQUIRE_EQ(path("///foo///bar///").str(), "/foo/bar");
101 }
102 
103 ATF_TEST_CASE(path_is_absolute);
ATF_TEST_CASE_HEAD(path_is_absolute)104 ATF_TEST_CASE_HEAD(path_is_absolute)
105 {
106     set_md_var("descr", "Tests the path::is_absolute function");
107 }
ATF_TEST_CASE_BODY(path_is_absolute)108 ATF_TEST_CASE_BODY(path_is_absolute)
109 {
110     using tools::fs::path;
111 
112     ATF_REQUIRE( path("/").is_absolute());
113     ATF_REQUIRE( path("////").is_absolute());
114     ATF_REQUIRE( path("////a").is_absolute());
115     ATF_REQUIRE( path("//a//").is_absolute());
116     ATF_REQUIRE(!path("a////").is_absolute());
117     ATF_REQUIRE(!path("../foo").is_absolute());
118 }
119 
120 ATF_TEST_CASE(path_is_root);
ATF_TEST_CASE_HEAD(path_is_root)121 ATF_TEST_CASE_HEAD(path_is_root)
122 {
123     set_md_var("descr", "Tests the path::is_root function");
124 }
ATF_TEST_CASE_BODY(path_is_root)125 ATF_TEST_CASE_BODY(path_is_root)
126 {
127     using tools::fs::path;
128 
129     ATF_REQUIRE( path("/").is_root());
130     ATF_REQUIRE( path("////").is_root());
131     ATF_REQUIRE(!path("////a").is_root());
132     ATF_REQUIRE(!path("//a//").is_root());
133     ATF_REQUIRE(!path("a////").is_root());
134     ATF_REQUIRE(!path("../foo").is_root());
135 }
136 
137 ATF_TEST_CASE(path_branch_path);
ATF_TEST_CASE_HEAD(path_branch_path)138 ATF_TEST_CASE_HEAD(path_branch_path)
139 {
140     set_md_var("descr", "Tests the path::branch_path function");
141 }
ATF_TEST_CASE_BODY(path_branch_path)142 ATF_TEST_CASE_BODY(path_branch_path)
143 {
144     using tools::fs::path;
145 
146     ATF_REQUIRE_EQ(path(".").branch_path().str(), ".");
147     ATF_REQUIRE_EQ(path("foo").branch_path().str(), ".");
148     ATF_REQUIRE_EQ(path("foo/bar").branch_path().str(), "foo");
149     ATF_REQUIRE_EQ(path("/foo").branch_path().str(), "/");
150     ATF_REQUIRE_EQ(path("/foo/bar").branch_path().str(), "/foo");
151 }
152 
153 ATF_TEST_CASE(path_leaf_name);
ATF_TEST_CASE_HEAD(path_leaf_name)154 ATF_TEST_CASE_HEAD(path_leaf_name)
155 {
156     set_md_var("descr", "Tests the path::leaf_name function");
157 }
ATF_TEST_CASE_BODY(path_leaf_name)158 ATF_TEST_CASE_BODY(path_leaf_name)
159 {
160     using tools::fs::path;
161 
162     ATF_REQUIRE_EQ(path(".").leaf_name(), ".");
163     ATF_REQUIRE_EQ(path("foo").leaf_name(), "foo");
164     ATF_REQUIRE_EQ(path("foo/bar").leaf_name(), "bar");
165     ATF_REQUIRE_EQ(path("/foo").leaf_name(), "foo");
166     ATF_REQUIRE_EQ(path("/foo/bar").leaf_name(), "bar");
167 }
168 
169 ATF_TEST_CASE(path_compare_equal);
ATF_TEST_CASE_HEAD(path_compare_equal)170 ATF_TEST_CASE_HEAD(path_compare_equal)
171 {
172     set_md_var("descr", "Tests the comparison for equality between paths");
173 }
ATF_TEST_CASE_BODY(path_compare_equal)174 ATF_TEST_CASE_BODY(path_compare_equal)
175 {
176     using tools::fs::path;
177 
178     ATF_REQUIRE(path("/") == path("///"));
179     ATF_REQUIRE(path("/a") == path("///a"));
180     ATF_REQUIRE(path("/a") == path("///a///"));
181 
182     ATF_REQUIRE(path("a/b/c") == path("a//b//c"));
183     ATF_REQUIRE(path("a/b/c") == path("a//b//c///"));
184 }
185 
186 ATF_TEST_CASE(path_compare_different);
ATF_TEST_CASE_HEAD(path_compare_different)187 ATF_TEST_CASE_HEAD(path_compare_different)
188 {
189     set_md_var("descr", "Tests the comparison for difference between paths");
190 }
ATF_TEST_CASE_BODY(path_compare_different)191 ATF_TEST_CASE_BODY(path_compare_different)
192 {
193     using tools::fs::path;
194 
195     ATF_REQUIRE(path("/") != path("//a/"));
196     ATF_REQUIRE(path("/a") != path("a///"));
197 
198     ATF_REQUIRE(path("a/b/c") != path("a/b"));
199     ATF_REQUIRE(path("a/b/c") != path("a//b"));
200     ATF_REQUIRE(path("a/b/c") != path("/a/b/c"));
201     ATF_REQUIRE(path("a/b/c") != path("/a//b//c"));
202 }
203 
204 ATF_TEST_CASE(path_concat);
ATF_TEST_CASE_HEAD(path_concat)205 ATF_TEST_CASE_HEAD(path_concat)
206 {
207     set_md_var("descr", "Tests the concatenation of multiple paths");
208 }
ATF_TEST_CASE_BODY(path_concat)209 ATF_TEST_CASE_BODY(path_concat)
210 {
211     using tools::fs::path;
212 
213     ATF_REQUIRE_EQ((path("foo") / "bar").str(), "foo/bar");
214     ATF_REQUIRE_EQ((path("foo/") / "/bar").str(), "foo/bar");
215     ATF_REQUIRE_EQ((path("foo/") / "/bar/baz").str(), "foo/bar/baz");
216     ATF_REQUIRE_EQ((path("foo/") / "///bar///baz").str(), "foo/bar/baz");
217 }
218 
219 ATF_TEST_CASE(path_to_absolute);
ATF_TEST_CASE_HEAD(path_to_absolute)220 ATF_TEST_CASE_HEAD(path_to_absolute)
221 {
222     set_md_var("descr", "Tests the conversion of a relative path to an "
223                "absolute one");
224 }
ATF_TEST_CASE_BODY(path_to_absolute)225 ATF_TEST_CASE_BODY(path_to_absolute)
226 {
227     using tools::fs::file_info;
228     using tools::fs::path;
229 
230     create_files();
231 
232     {
233         const path p(".");
234         path pa = p.to_absolute();
235         ATF_REQUIRE(pa.is_absolute());
236 
237         file_info fi(p);
238         file_info fia(pa);
239         ATF_REQUIRE_EQ(fi.get_device(), fia.get_device());
240         ATF_REQUIRE_EQ(fi.get_inode(), fia.get_inode());
241     }
242 
243     {
244         const path p("files/reg");
245         path pa = p.to_absolute();
246         ATF_REQUIRE(pa.is_absolute());
247 
248         file_info fi(p);
249         file_info fia(pa);
250         ATF_REQUIRE_EQ(fi.get_device(), fia.get_device());
251         ATF_REQUIRE_EQ(fi.get_inode(), fia.get_inode());
252     }
253 }
254 
255 ATF_TEST_CASE(path_op_less);
ATF_TEST_CASE_HEAD(path_op_less)256 ATF_TEST_CASE_HEAD(path_op_less)
257 {
258     set_md_var("descr", "Tests that the path's less-than operator works");
259 }
ATF_TEST_CASE_BODY(path_op_less)260 ATF_TEST_CASE_BODY(path_op_less)
261 {
262     using tools::fs::path;
263 
264     create_files();
265 
266     ATF_REQUIRE(!(path("aaa") < path("aaa")));
267 
268     ATF_REQUIRE(  path("aab") < path("abc"));
269     ATF_REQUIRE(!(path("abc") < path("aab")));
270 }
271 
272 // ------------------------------------------------------------------------
273 // Test cases for the "directory" class.
274 // ------------------------------------------------------------------------
275 
276 ATF_TEST_CASE(directory_read);
ATF_TEST_CASE_HEAD(directory_read)277 ATF_TEST_CASE_HEAD(directory_read)
278 {
279     set_md_var("descr", "Tests the directory class creation, which reads "
280                "the contents of a directory");
281 }
ATF_TEST_CASE_BODY(directory_read)282 ATF_TEST_CASE_BODY(directory_read)
283 {
284     using tools::fs::directory;
285     using tools::fs::path;
286 
287     create_files();
288 
289     directory d(path("files"));
290     ATF_REQUIRE_EQ(d.size(), 4);
291     ATF_REQUIRE(d.find(".") != d.end());
292     ATF_REQUIRE(d.find("..") != d.end());
293     ATF_REQUIRE(d.find("dir") != d.end());
294     ATF_REQUIRE(d.find("reg") != d.end());
295 }
296 
297 ATF_TEST_CASE(directory_file_info);
ATF_TEST_CASE_HEAD(directory_file_info)298 ATF_TEST_CASE_HEAD(directory_file_info)
299 {
300     set_md_var("descr", "Tests that the file_info objects attached to the "
301                "directory are valid");
302 }
ATF_TEST_CASE_BODY(directory_file_info)303 ATF_TEST_CASE_BODY(directory_file_info)
304 {
305     using tools::fs::directory;
306     using tools::fs::file_info;
307     using tools::fs::path;
308 
309     create_files();
310 
311     directory d(path("files"));
312 
313     {
314         directory::const_iterator iter = d.find("dir");
315         ATF_REQUIRE(iter != d.end());
316         const file_info& fi = (*iter).second;
317         ATF_REQUIRE(fi.get_type() == file_info::dir_type);
318     }
319 
320     {
321         directory::const_iterator iter = d.find("reg");
322         ATF_REQUIRE(iter != d.end());
323         const file_info& fi = (*iter).second;
324         ATF_REQUIRE(fi.get_type() == file_info::reg_type);
325     }
326 }
327 
328 ATF_TEST_CASE(directory_names);
ATF_TEST_CASE_HEAD(directory_names)329 ATF_TEST_CASE_HEAD(directory_names)
330 {
331     set_md_var("descr", "Tests the directory's names method");
332 }
ATF_TEST_CASE_BODY(directory_names)333 ATF_TEST_CASE_BODY(directory_names)
334 {
335     using tools::fs::directory;
336     using tools::fs::path;
337 
338     create_files();
339 
340     directory d(path("files"));
341     std::set< std::string > ns = d.names();
342     ATF_REQUIRE_EQ(ns.size(), 4);
343     ATF_REQUIRE(ns.find(".") != ns.end());
344     ATF_REQUIRE(ns.find("..") != ns.end());
345     ATF_REQUIRE(ns.find("dir") != ns.end());
346     ATF_REQUIRE(ns.find("reg") != ns.end());
347 }
348 
349 // ------------------------------------------------------------------------
350 // Test cases for the "file_info" class.
351 // ------------------------------------------------------------------------
352 
353 ATF_TEST_CASE(file_info_stat);
ATF_TEST_CASE_HEAD(file_info_stat)354 ATF_TEST_CASE_HEAD(file_info_stat)
355 {
356     set_md_var("descr", "Tests the file_info creation and its basic contents");
357 }
ATF_TEST_CASE_BODY(file_info_stat)358 ATF_TEST_CASE_BODY(file_info_stat)
359 {
360     using tools::fs::file_info;
361     using tools::fs::path;
362 
363     create_files();
364 
365     {
366         path p("files/dir");
367         file_info fi(p);
368         ATF_REQUIRE(fi.get_type() == file_info::dir_type);
369     }
370 
371     {
372         path p("files/reg");
373         file_info fi(p);
374         ATF_REQUIRE(fi.get_type() == file_info::reg_type);
375     }
376 }
377 
378 ATF_TEST_CASE(file_info_perms);
ATF_TEST_CASE_HEAD(file_info_perms)379 ATF_TEST_CASE_HEAD(file_info_perms)
380 {
381     set_md_var("descr", "Tests the file_info methods to get the file's "
382                "permissions");
383 }
ATF_TEST_CASE_BODY(file_info_perms)384 ATF_TEST_CASE_BODY(file_info_perms)
385 {
386     using tools::fs::file_info;
387     using tools::fs::path;
388 
389     path p("file");
390 
391     std::ofstream os(p.c_str());
392     os.close();
393 
394 #define perms(ur, uw, ux, gr, gw, gx, othr, othw, othx) \
395     { \
396         file_info fi(p); \
397         ATF_REQUIRE(fi.is_owner_readable() == ur); \
398         ATF_REQUIRE(fi.is_owner_writable() == uw); \
399         ATF_REQUIRE(fi.is_owner_executable() == ux); \
400         ATF_REQUIRE(fi.is_group_readable() == gr); \
401         ATF_REQUIRE(fi.is_group_writable() == gw); \
402         ATF_REQUIRE(fi.is_group_executable() == gx); \
403         ATF_REQUIRE(fi.is_other_readable() == othr); \
404         ATF_REQUIRE(fi.is_other_writable() == othw); \
405         ATF_REQUIRE(fi.is_other_executable() == othx); \
406     }
407 
408     ::chmod(p.c_str(), 0000);
409     perms(false, false, false, false, false, false, false, false, false);
410 
411     ::chmod(p.c_str(), 0001);
412     perms(false, false, false, false, false, false, false, false, true);
413 
414     ::chmod(p.c_str(), 0010);
415     perms(false, false, false, false, false, true, false, false, false);
416 
417     ::chmod(p.c_str(), 0100);
418     perms(false, false, true, false, false, false, false, false, false);
419 
420     ::chmod(p.c_str(), 0002);
421     perms(false, false, false, false, false, false, false, true, false);
422 
423     ::chmod(p.c_str(), 0020);
424     perms(false, false, false, false, true, false, false, false, false);
425 
426     ::chmod(p.c_str(), 0200);
427     perms(false, true, false, false, false, false, false, false, false);
428 
429     ::chmod(p.c_str(), 0004);
430     perms(false, false, false, false, false, false, true, false, false);
431 
432     ::chmod(p.c_str(), 0040);
433     perms(false, false, false, true, false, false, false, false, false);
434 
435     ::chmod(p.c_str(), 0400);
436     perms(true, false, false, false, false, false, false, false, false);
437 
438     ::chmod(p.c_str(), 0644);
439     perms(true, true, false, true, false, false, true, false, false);
440 
441     ::chmod(p.c_str(), 0755);
442     perms(true, true, true, true, false, true, true, false, true);
443 
444     ::chmod(p.c_str(), 0777);
445     perms(true, true, true, true, true, true, true, true, true);
446 
447 #undef perms
448 }
449 
450 // ------------------------------------------------------------------------
451 // Test cases for the "temp_dir" class.
452 // ------------------------------------------------------------------------
453 
454 ATF_TEST_CASE(temp_dir_raii);
ATF_TEST_CASE_HEAD(temp_dir_raii)455 ATF_TEST_CASE_HEAD(temp_dir_raii)
456 {
457     set_md_var("descr", "Tests the RAII behavior of the temp_dir class");
458 }
ATF_TEST_CASE_BODY(temp_dir_raii)459 ATF_TEST_CASE_BODY(temp_dir_raii)
460 {
461     tools::fs::path t1("non-existent");
462     tools::fs::path t2("non-existent");
463 
464     {
465         tools::fs::path tmpl("testdir.XXXXXX");
466         tools::fs::temp_dir td1(tmpl);
467         tools::fs::temp_dir td2(tmpl);
468         t1 = td1.get_path();
469         t2 = td2.get_path();
470         ATF_REQUIRE(t1.str().find("XXXXXX") == std::string::npos);
471         ATF_REQUIRE(t2.str().find("XXXXXX") == std::string::npos);
472         ATF_REQUIRE(t1 != t2);
473         ATF_REQUIRE(!tools::fs::exists(tmpl));
474         ATF_REQUIRE( tools::fs::exists(t1));
475         ATF_REQUIRE( tools::fs::exists(t2));
476 
477         tools::fs::file_info fi1(t1);
478         ATF_REQUIRE( fi1.is_owner_readable());
479         ATF_REQUIRE( fi1.is_owner_writable());
480         ATF_REQUIRE( fi1.is_owner_executable());
481         ATF_REQUIRE(!fi1.is_group_readable());
482         ATF_REQUIRE(!fi1.is_group_writable());
483         ATF_REQUIRE(!fi1.is_group_executable());
484         ATF_REQUIRE(!fi1.is_other_readable());
485         ATF_REQUIRE(!fi1.is_other_writable());
486         ATF_REQUIRE(!fi1.is_other_executable());
487 
488         tools::fs::file_info fi2(t2);
489         ATF_REQUIRE( fi2.is_owner_readable());
490         ATF_REQUIRE( fi2.is_owner_writable());
491         ATF_REQUIRE( fi2.is_owner_executable());
492         ATF_REQUIRE(!fi2.is_group_readable());
493         ATF_REQUIRE(!fi2.is_group_writable());
494         ATF_REQUIRE(!fi2.is_group_executable());
495         ATF_REQUIRE(!fi2.is_other_readable());
496         ATF_REQUIRE(!fi2.is_other_writable());
497         ATF_REQUIRE(!fi2.is_other_executable());
498     }
499 
500     ATF_REQUIRE(t1.str() != "non-existent");
501     ATF_REQUIRE(!tools::fs::exists(t1));
502     ATF_REQUIRE(t2.str() != "non-existent");
503     ATF_REQUIRE(!tools::fs::exists(t2));
504 }
505 
506 
507 // ------------------------------------------------------------------------
508 // Test cases for the free functions.
509 // ------------------------------------------------------------------------
510 
511 ATF_TEST_CASE(exists);
ATF_TEST_CASE_HEAD(exists)512 ATF_TEST_CASE_HEAD(exists)
513 {
514     set_md_var("descr", "Tests the exists function");
515 }
ATF_TEST_CASE_BODY(exists)516 ATF_TEST_CASE_BODY(exists)
517 {
518     using tools::fs::exists;
519     using tools::fs::path;
520 
521     create_files();
522 
523     ATF_REQUIRE( exists(path("files")));
524     ATF_REQUIRE(!exists(path("file")));
525     ATF_REQUIRE(!exists(path("files2")));
526 
527     ATF_REQUIRE( exists(path("files/.")));
528     ATF_REQUIRE( exists(path("files/..")));
529     ATF_REQUIRE( exists(path("files/dir")));
530     ATF_REQUIRE( exists(path("files/reg")));
531     ATF_REQUIRE(!exists(path("files/foo")));
532 }
533 
534 ATF_TEST_CASE(is_executable);
ATF_TEST_CASE_HEAD(is_executable)535 ATF_TEST_CASE_HEAD(is_executable)
536 {
537     set_md_var("descr", "Tests the is_executable function");
538 }
ATF_TEST_CASE_BODY(is_executable)539 ATF_TEST_CASE_BODY(is_executable)
540 {
541     using tools::fs::is_executable;
542     using tools::fs::path;
543 
544     create_files();
545 
546     ATF_REQUIRE( is_executable(path("files")));
547     ATF_REQUIRE( is_executable(path("files/.")));
548     ATF_REQUIRE( is_executable(path("files/..")));
549     ATF_REQUIRE( is_executable(path("files/dir")));
550 
551     ATF_REQUIRE(!is_executable(path("non-existent")));
552 
553     ATF_REQUIRE(!is_executable(path("files/reg")));
554     ATF_REQUIRE(::chmod("files/reg", 0755) != -1);
555     ATF_REQUIRE( is_executable(path("files/reg")));
556 }
557 
558 ATF_TEST_CASE(remove);
ATF_TEST_CASE_HEAD(remove)559 ATF_TEST_CASE_HEAD(remove)
560 {
561     set_md_var("descr", "Tests the remove function");
562 }
ATF_TEST_CASE_BODY(remove)563 ATF_TEST_CASE_BODY(remove)
564 {
565     using tools::fs::exists;
566     using tools::fs::path;
567     using tools::fs::remove;
568 
569     create_files();
570 
571     ATF_REQUIRE( exists(path("files/reg")));
572     remove(path("files/reg"));
573     ATF_REQUIRE(!exists(path("files/reg")));
574 
575     ATF_REQUIRE( exists(path("files/dir")));
576     ATF_REQUIRE_THROW(tools::system_error, remove(path("files/dir")));
577     ATF_REQUIRE( exists(path("files/dir")));
578 }
579 
580 ATF_TEST_CASE(cleanup);
ATF_TEST_CASE_HEAD(cleanup)581 ATF_TEST_CASE_HEAD(cleanup)
582 {
583     set_md_var("descr", "Tests the cleanup function");
584 }
ATF_TEST_CASE_BODY(cleanup)585 ATF_TEST_CASE_BODY(cleanup)
586 {
587     using tools::fs::cleanup;
588 
589     ::mkdir("root", 0755);
590     ::mkdir("root/dir", 0755);
591     ::mkdir("root/dir/1", 0100);
592     ::mkdir("root/dir/2", 0644);
593     create_file("root/reg");
594 
595     tools::fs::path p("root");
596     ATF_REQUIRE(tools::fs::exists(p));
597     ATF_REQUIRE(tools::fs::exists(p / "dir"));
598     ATF_REQUIRE(tools::fs::exists(p / "dir/1"));
599     ATF_REQUIRE(tools::fs::exists(p / "dir/2"));
600     ATF_REQUIRE(tools::fs::exists(p / "reg"));
601     cleanup(p);
602     ATF_REQUIRE(!tools::fs::exists(p));
603 }
604 
605 ATF_TEST_CASE(cleanup_eacces_on_root);
ATF_TEST_CASE_HEAD(cleanup_eacces_on_root)606 ATF_TEST_CASE_HEAD(cleanup_eacces_on_root)
607 {
608     set_md_var("descr", "Tests the cleanup function");
609 }
ATF_TEST_CASE_BODY(cleanup_eacces_on_root)610 ATF_TEST_CASE_BODY(cleanup_eacces_on_root)
611 {
612     using tools::fs::cleanup;
613 
614     ::mkdir("aux", 0755);
615     ::mkdir("aux/root", 0755);
616     ATF_REQUIRE(::chmod("aux", 0555) != -1);
617 
618     try {
619         cleanup(tools::fs::path("aux/root"));
620         ATF_REQUIRE(tools::user::is_root());
621     } catch (const tools::system_error& e) {
622         ATF_REQUIRE(!tools::user::is_root());
623         ATF_REQUIRE_EQ(EACCES, e.code());
624     }
625 }
626 
627 ATF_TEST_CASE(cleanup_eacces_on_subdir);
ATF_TEST_CASE_HEAD(cleanup_eacces_on_subdir)628 ATF_TEST_CASE_HEAD(cleanup_eacces_on_subdir)
629 {
630     set_md_var("descr", "Tests the cleanup function");
631 }
ATF_TEST_CASE_BODY(cleanup_eacces_on_subdir)632 ATF_TEST_CASE_BODY(cleanup_eacces_on_subdir)
633 {
634     using tools::fs::cleanup;
635 
636     ::mkdir("root", 0755);
637     ::mkdir("root/1", 0755);
638     ::mkdir("root/1/2", 0755);
639     ::mkdir("root/1/2/3", 0755);
640     ATF_REQUIRE(::chmod("root/1/2", 0555) != -1);
641     ATF_REQUIRE(::chmod("root/1", 0555) != -1);
642 
643     const tools::fs::path p("root");
644     cleanup(p);
645     ATF_REQUIRE(!tools::fs::exists(p));
646 }
647 
648 ATF_TEST_CASE(change_directory);
ATF_TEST_CASE_HEAD(change_directory)649 ATF_TEST_CASE_HEAD(change_directory)
650 {
651     set_md_var("descr", "Tests the change_directory function");
652 }
ATF_TEST_CASE_BODY(change_directory)653 ATF_TEST_CASE_BODY(change_directory)
654 {
655     using tools::fs::change_directory;
656     using tools::fs::get_current_dir;
657 
658     ::mkdir("files", 0755);
659     ::mkdir("files/dir", 0755);
660     create_file("files/reg");
661 
662     const tools::fs::path old = get_current_dir();
663 
664     ATF_REQUIRE_THROW(tools::system_error,
665                     change_directory(tools::fs::path("files/reg")));
666     ATF_REQUIRE(get_current_dir() == old);
667 
668     tools::fs::path old2 = change_directory(tools::fs::path("files"));
669     ATF_REQUIRE(old2 == old);
670     tools::fs::path old3 = change_directory(tools::fs::path("dir"));
671     ATF_REQUIRE(old3 == old2 / "files");
672     tools::fs::path old4 = change_directory(tools::fs::path("../.."));
673     ATF_REQUIRE(old4 == old3 / "dir");
674     ATF_REQUIRE(get_current_dir() == old);
675 }
676 
677 ATF_TEST_CASE(get_current_dir);
ATF_TEST_CASE_HEAD(get_current_dir)678 ATF_TEST_CASE_HEAD(get_current_dir)
679 {
680     set_md_var("descr", "Tests the get_current_dir function");
681 }
ATF_TEST_CASE_BODY(get_current_dir)682 ATF_TEST_CASE_BODY(get_current_dir)
683 {
684     using tools::fs::change_directory;
685     using tools::fs::get_current_dir;
686 
687     ::mkdir("files", 0755);
688     ::mkdir("files/dir", 0755);
689     create_file("files/reg");
690 
691     tools::fs::path curdir = get_current_dir();
692     change_directory(tools::fs::path("."));
693     ATF_REQUIRE(get_current_dir() == curdir);
694     change_directory(tools::fs::path("files"));
695     ATF_REQUIRE(get_current_dir() == curdir / "files");
696     change_directory(tools::fs::path("dir"));
697     ATF_REQUIRE(get_current_dir() == curdir / "files/dir");
698     change_directory(tools::fs::path(".."));
699     ATF_REQUIRE(get_current_dir() == curdir / "files");
700     change_directory(tools::fs::path(".."));
701     ATF_REQUIRE(get_current_dir() == curdir);
702 }
703 
704 // ------------------------------------------------------------------------
705 // Main.
706 // ------------------------------------------------------------------------
707 
ATF_INIT_TEST_CASES(tcs)708 ATF_INIT_TEST_CASES(tcs)
709 {
710     // Add the tests for the "path" class.
711     ATF_ADD_TEST_CASE(tcs, path_normalize);
712     ATF_ADD_TEST_CASE(tcs, path_is_absolute);
713     ATF_ADD_TEST_CASE(tcs, path_is_root);
714     ATF_ADD_TEST_CASE(tcs, path_branch_path);
715     ATF_ADD_TEST_CASE(tcs, path_leaf_name);
716     ATF_ADD_TEST_CASE(tcs, path_compare_equal);
717     ATF_ADD_TEST_CASE(tcs, path_compare_different);
718     ATF_ADD_TEST_CASE(tcs, path_concat);
719     ATF_ADD_TEST_CASE(tcs, path_to_absolute);
720     ATF_ADD_TEST_CASE(tcs, path_op_less);
721 
722     // Add the tests for the "file_info" class.
723     ATF_ADD_TEST_CASE(tcs, file_info_stat);
724     ATF_ADD_TEST_CASE(tcs, file_info_perms);
725 
726     // Add the tests for the "directory" class.
727     ATF_ADD_TEST_CASE(tcs, directory_read);
728     ATF_ADD_TEST_CASE(tcs, directory_names);
729     ATF_ADD_TEST_CASE(tcs, directory_file_info);
730 
731     // Add the tests for the "temp_dir" class.
732     ATF_ADD_TEST_CASE(tcs, temp_dir_raii);
733 
734     // Add the tests for the free functions.
735     ATF_ADD_TEST_CASE(tcs, exists);
736     ATF_ADD_TEST_CASE(tcs, is_executable);
737     ATF_ADD_TEST_CASE(tcs, remove);
738     ATF_ADD_TEST_CASE(tcs, cleanup);
739     ATF_ADD_TEST_CASE(tcs, cleanup_eacces_on_root);
740     ATF_ADD_TEST_CASE(tcs, cleanup_eacces_on_subdir);
741     ATF_ADD_TEST_CASE(tcs, change_directory);
742     ATF_ADD_TEST_CASE(tcs, get_current_dir);
743 }
744