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
30extern "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
49static
50void
51create_file(const char *name)
52{
53    std::ofstream os(name);
54    os.close();
55}
56
57static
58void
59create_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
78ATF_TEST_CASE(path_normalize);
79ATF_TEST_CASE_HEAD(path_normalize)
80{
81    set_md_var("descr", "Tests the path's normalization");
82}
83ATF_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
103ATF_TEST_CASE(path_is_absolute);
104ATF_TEST_CASE_HEAD(path_is_absolute)
105{
106    set_md_var("descr", "Tests the path::is_absolute function");
107}
108ATF_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
120ATF_TEST_CASE(path_is_root);
121ATF_TEST_CASE_HEAD(path_is_root)
122{
123    set_md_var("descr", "Tests the path::is_root function");
124}
125ATF_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
137ATF_TEST_CASE(path_branch_path);
138ATF_TEST_CASE_HEAD(path_branch_path)
139{
140    set_md_var("descr", "Tests the path::branch_path function");
141}
142ATF_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
153ATF_TEST_CASE(path_leaf_name);
154ATF_TEST_CASE_HEAD(path_leaf_name)
155{
156    set_md_var("descr", "Tests the path::leaf_name function");
157}
158ATF_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
169ATF_TEST_CASE(path_compare_equal);
170ATF_TEST_CASE_HEAD(path_compare_equal)
171{
172    set_md_var("descr", "Tests the comparison for equality between paths");
173}
174ATF_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
186ATF_TEST_CASE(path_compare_different);
187ATF_TEST_CASE_HEAD(path_compare_different)
188{
189    set_md_var("descr", "Tests the comparison for difference between paths");
190}
191ATF_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
204ATF_TEST_CASE(path_concat);
205ATF_TEST_CASE_HEAD(path_concat)
206{
207    set_md_var("descr", "Tests the concatenation of multiple paths");
208}
209ATF_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
219ATF_TEST_CASE(path_to_absolute);
220ATF_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}
225ATF_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
255ATF_TEST_CASE(path_op_less);
256ATF_TEST_CASE_HEAD(path_op_less)
257{
258    set_md_var("descr", "Tests that the path's less-than operator works");
259}
260ATF_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
276ATF_TEST_CASE(directory_read);
277ATF_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}
282ATF_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
297ATF_TEST_CASE(directory_file_info);
298ATF_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}
303ATF_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
328ATF_TEST_CASE(directory_names);
329ATF_TEST_CASE_HEAD(directory_names)
330{
331    set_md_var("descr", "Tests the directory's names method");
332}
333ATF_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
353ATF_TEST_CASE(file_info_stat);
354ATF_TEST_CASE_HEAD(file_info_stat)
355{
356    set_md_var("descr", "Tests the file_info creation and its basic contents");
357}
358ATF_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
378ATF_TEST_CASE(file_info_perms);
379ATF_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}
384ATF_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
454ATF_TEST_CASE(temp_dir_raii);
455ATF_TEST_CASE_HEAD(temp_dir_raii)
456{
457    set_md_var("descr", "Tests the RAII behavior of the temp_dir class");
458}
459ATF_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
511ATF_TEST_CASE(exists);
512ATF_TEST_CASE_HEAD(exists)
513{
514    set_md_var("descr", "Tests the exists function");
515}
516ATF_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
534ATF_TEST_CASE(is_executable);
535ATF_TEST_CASE_HEAD(is_executable)
536{
537    set_md_var("descr", "Tests the is_executable function");
538}
539ATF_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
558ATF_TEST_CASE(remove);
559ATF_TEST_CASE_HEAD(remove)
560{
561    set_md_var("descr", "Tests the remove function");
562}
563ATF_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
580ATF_TEST_CASE(cleanup);
581ATF_TEST_CASE_HEAD(cleanup)
582{
583    set_md_var("descr", "Tests the cleanup function");
584}
585ATF_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
605ATF_TEST_CASE(cleanup_eacces_on_root);
606ATF_TEST_CASE_HEAD(cleanup_eacces_on_root)
607{
608    set_md_var("descr", "Tests the cleanup function");
609}
610ATF_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
627ATF_TEST_CASE(cleanup_eacces_on_subdir);
628ATF_TEST_CASE_HEAD(cleanup_eacces_on_subdir)
629{
630    set_md_var("descr", "Tests the cleanup function");
631}
632ATF_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
648ATF_TEST_CASE(change_directory);
649ATF_TEST_CASE_HEAD(change_directory)
650{
651    set_md_var("descr", "Tests the change_directory function");
652}
653ATF_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
677ATF_TEST_CASE(get_current_dir);
678ATF_TEST_CASE_HEAD(get_current_dir)
679{
680    set_md_var("descr", "Tests the get_current_dir function");
681}
682ATF_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
708ATF_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