fs_test.cpp revision 259065
167204Sobrien//
284617Sbenno// Automated Testing Framework (atf)
367204Sobrien//
467204Sobrien// Copyright (c) 2007 The NetBSD Foundation, Inc.
567204Sobrien// All rights reserved.
667204Sobrien//
767204Sobrien// Redistribution and use in source and binary forms, with or without
867204Sobrien// modification, are permitted provided that the following conditions
967204Sobrien// are met:
1067204Sobrien// 1. Redistributions of source code must retain the above copyright
1167204Sobrien//    notice, this list of conditions and the following disclaimer.
1267204Sobrien// 2. Redistributions in binary form must reproduce the above copyright
1367204Sobrien//    notice, this list of conditions and the following disclaimer in the
1467204Sobrien//    documentation and/or other materials provided with the distribution.
1567204Sobrien//
1667204Sobrien// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND
1767204Sobrien// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
1867204Sobrien// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
1967204Sobrien// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2067204Sobrien// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY
2167204Sobrien// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2267204Sobrien// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
2367204Sobrien// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2467204Sobrien// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
2567204Sobrien// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
2667204Sobrien// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27124140Sobrien// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28124140Sobrien//
29124140Sobrien
3067204Sobrienextern "C" {
3167204Sobrien#include <sys/types.h>
3268548Sbenno#include <sys/stat.h>
3367204Sobrien}
3468548Sbenno
3567204Sobrien#include <fstream>
3667204Sobrien#include <cerrno>
3768548Sbenno#include <cstdio>
3868548Sbenno
3967204Sobrien#include "../macros.hpp"
4067204Sobrien
4167204Sobrien#include "exceptions.hpp"
4267204Sobrien#include "fs.hpp"
4367204Sobrien
4468548Sbenno// ------------------------------------------------------------------------
4567204Sobrien// Auxiliary functions.
4668548Sbenno// ------------------------------------------------------------------------
4768548Sbenno
4868548Sbennostatic
4984617Sbennovoid
5084617Sbennocreate_files(void)
5168548Sbenno{
5267204Sobrien    ::mkdir("files", 0755);
5368548Sbenno    ::mkdir("files/dir", 0755);
5468548Sbenno
5568548Sbenno    std::ofstream os("files/reg");
5667204Sobrien    os.close();
5768548Sbenno
5867204Sobrien    // TODO: Should create all other file types (blk, chr, fifo, lnk, sock)
5967204Sobrien    // and test for them... but the underlying file system may not support
6068548Sbenno    // most of these.  Specially as we are working on /tmp, which can be
6167204Sobrien    // mounted with flags such as "nodev".  See how to deal with this
6267204Sobrien    // situation.
6367204Sobrien}
6467204Sobrien
6567204Sobrien// ------------------------------------------------------------------------
6667204Sobrien// Test cases for the "path" class.
6767204Sobrien// ------------------------------------------------------------------------
6867204Sobrien
6967204SobrienATF_TEST_CASE(path_normalize);
7067204SobrienATF_TEST_CASE_HEAD(path_normalize)
7167204Sobrien{
7267204Sobrien    set_md_var("descr", "Tests the path's normalization");
7367204Sobrien}
7468548SbennoATF_TEST_CASE_BODY(path_normalize)
7568548Sbenno{
7668548Sbenno    using atf::fs::path;
7767204Sobrien
7868548Sbenno    ATF_REQUIRE_EQ(path(".").str(), ".");
7968548Sbenno    ATF_REQUIRE_EQ(path("..").str(), "..");
8068548Sbenno
8167204Sobrien    ATF_REQUIRE_EQ(path("foo").str(), "foo");
8267204Sobrien    ATF_REQUIRE_EQ(path("foo/bar").str(), "foo/bar");
8368548Sbenno    ATF_REQUIRE_EQ(path("foo/bar/").str(), "foo/bar");
8467204Sobrien
8567204Sobrien    ATF_REQUIRE_EQ(path("/foo").str(), "/foo");
8668548Sbenno    ATF_REQUIRE_EQ(path("/foo/bar").str(), "/foo/bar");
8767204Sobrien    ATF_REQUIRE_EQ(path("/foo/bar/").str(), "/foo/bar");
8867204Sobrien
8967204Sobrien    ATF_REQUIRE_EQ(path("///foo").str(), "/foo");
9067204Sobrien    ATF_REQUIRE_EQ(path("///foo///bar").str(), "/foo/bar");
9167204Sobrien    ATF_REQUIRE_EQ(path("///foo///bar///").str(), "/foo/bar");
9268548Sbenno}
9384617Sbenno
9467204SobrienATF_TEST_CASE(path_is_absolute);
9568548SbennoATF_TEST_CASE_HEAD(path_is_absolute)
9668548Sbenno{
9768548Sbenno    set_md_var("descr", "Tests the path::is_absolute function");
9867204Sobrien}
9968548SbennoATF_TEST_CASE_BODY(path_is_absolute)
10068548Sbenno{
10168548Sbenno    using atf::fs::path;
10268548Sbenno
10368548Sbenno    ATF_REQUIRE( path("/").is_absolute());
10468548Sbenno    ATF_REQUIRE( path("////").is_absolute());
10567204Sobrien    ATF_REQUIRE( path("////a").is_absolute());
10668548Sbenno    ATF_REQUIRE( path("//a//").is_absolute());
10768548Sbenno    ATF_REQUIRE(!path("a////").is_absolute());
10868548Sbenno    ATF_REQUIRE(!path("../foo").is_absolute());
10968548Sbenno}
11068548Sbenno
11168548SbennoATF_TEST_CASE(path_is_root);
11268548SbennoATF_TEST_CASE_HEAD(path_is_root)
11368548Sbenno{
11468548Sbenno    set_md_var("descr", "Tests the path::is_root function");
11568548Sbenno}
11668548SbennoATF_TEST_CASE_BODY(path_is_root)
11768548Sbenno{
11868548Sbenno    using atf::fs::path;
11968548Sbenno
12068548Sbenno    ATF_REQUIRE( path("/").is_root());
12168548Sbenno    ATF_REQUIRE( path("////").is_root());
12268548Sbenno    ATF_REQUIRE(!path("////a").is_root());
12368548Sbenno    ATF_REQUIRE(!path("//a//").is_root());
12468548Sbenno    ATF_REQUIRE(!path("a////").is_root());
12568548Sbenno    ATF_REQUIRE(!path("../foo").is_root());
12668548Sbenno}
12767204Sobrien
12867204SobrienATF_TEST_CASE(path_branch_path);
12968548SbennoATF_TEST_CASE_HEAD(path_branch_path)
13084617Sbenno{
13167204Sobrien    set_md_var("descr", "Tests the path::branch_path function");
13268548Sbenno}
13368548SbennoATF_TEST_CASE_BODY(path_branch_path)
13467204Sobrien{
13568548Sbenno    using atf::fs::path;
13668548Sbenno
13768548Sbenno    ATF_REQUIRE_EQ(path(".").branch_path().str(), ".");
13868548Sbenno    ATF_REQUIRE_EQ(path("foo").branch_path().str(), ".");
13967204Sobrien    ATF_REQUIRE_EQ(path("foo/bar").branch_path().str(), "foo");
14068548Sbenno    ATF_REQUIRE_EQ(path("/foo").branch_path().str(), "/");
14168548Sbenno    ATF_REQUIRE_EQ(path("/foo/bar").branch_path().str(), "/foo");
14268548Sbenno}
14368548Sbenno
14468548SbennoATF_TEST_CASE(path_leaf_name);
14567204SobrienATF_TEST_CASE_HEAD(path_leaf_name)
14668548Sbenno{
14768548Sbenno    set_md_var("descr", "Tests the path::leaf_name function");
14868548Sbenno}
14967204SobrienATF_TEST_CASE_BODY(path_leaf_name)
15068548Sbenno{
15168548Sbenno    using atf::fs::path;
15267204Sobrien
15368548Sbenno    ATF_REQUIRE_EQ(path(".").leaf_name(), ".");
15468548Sbenno    ATF_REQUIRE_EQ(path("foo").leaf_name(), "foo");
15568548Sbenno    ATF_REQUIRE_EQ(path("foo/bar").leaf_name(), "bar");
15668548Sbenno    ATF_REQUIRE_EQ(path("/foo").leaf_name(), "foo");
15767204Sobrien    ATF_REQUIRE_EQ(path("/foo/bar").leaf_name(), "bar");
15868548Sbenno}
15968548Sbenno
16068548SbennoATF_TEST_CASE(path_compare_equal);
16167204SobrienATF_TEST_CASE_HEAD(path_compare_equal)
16268548Sbenno{
16367204Sobrien    set_md_var("descr", "Tests the comparison for equality between paths");
16468548Sbenno}
16567204SobrienATF_TEST_CASE_BODY(path_compare_equal)
16668548Sbenno{
16768548Sbenno    using atf::fs::path;
16868548Sbenno
16967204Sobrien    ATF_REQUIRE(path("/") == path("///"));
17068548Sbenno    ATF_REQUIRE(path("/a") == path("///a"));
17168548Sbenno    ATF_REQUIRE(path("/a") == path("///a///"));
17268548Sbenno
17368548Sbenno    ATF_REQUIRE(path("a/b/c") == path("a//b//c"));
17468548Sbenno    ATF_REQUIRE(path("a/b/c") == path("a//b//c///"));
17567204Sobrien}
17668548Sbenno
17768548SbennoATF_TEST_CASE(path_compare_different);
17867204SobrienATF_TEST_CASE_HEAD(path_compare_different)
17968548Sbenno{
18067204Sobrien    set_md_var("descr", "Tests the comparison for difference between paths");
18168548Sbenno}
18268548SbennoATF_TEST_CASE_BODY(path_compare_different)
18368548Sbenno{
18468548Sbenno    using atf::fs::path;
18568548Sbenno
18668548Sbenno    ATF_REQUIRE(path("/") != path("//a/"));
18768548Sbenno    ATF_REQUIRE(path("/a") != path("a///"));
18867204Sobrien
18968548Sbenno    ATF_REQUIRE(path("a/b/c") != path("a/b"));
19068548Sbenno    ATF_REQUIRE(path("a/b/c") != path("a//b"));
19168548Sbenno    ATF_REQUIRE(path("a/b/c") != path("/a/b/c"));
19291112Sjake    ATF_REQUIRE(path("a/b/c") != path("/a//b//c"));
19391112Sjake}
19468548Sbenno
19591112SjakeATF_TEST_CASE(path_concat);
19691112SjakeATF_TEST_CASE_HEAD(path_concat)
19791112Sjake{
19868548Sbenno    set_md_var("descr", "Tests the concatenation of multiple paths");
19991112Sjake}
20068548SbennoATF_TEST_CASE_BODY(path_concat)
20168548Sbenno{
20267204Sobrien    using atf::fs::path;
20367204Sobrien
20484617Sbenno    ATF_REQUIRE_EQ((path("foo") / "bar").str(), "foo/bar");
20584617Sbenno    ATF_REQUIRE_EQ((path("foo/") / "/bar").str(), "foo/bar");
20668548Sbenno    ATF_REQUIRE_EQ((path("foo/") / "/bar/baz").str(), "foo/bar/baz");
20784617Sbenno    ATF_REQUIRE_EQ((path("foo/") / "///bar///baz").str(), "foo/bar/baz");
20868548Sbenno}
20968548Sbenno
210133862SmariusATF_TEST_CASE(path_to_absolute);
21168548SbennoATF_TEST_CASE_HEAD(path_to_absolute)
21268548Sbenno{
21391112Sjake    set_md_var("descr", "Tests the conversion of a relative path to an "
21498013Sbenno               "absolute one");
21598013Sbenno}
21682343SbennoATF_TEST_CASE_BODY(path_to_absolute)
21782343Sbenno{
21868548Sbenno    using atf::fs::file_info;
21982343Sbenno    using atf::fs::path;
22068548Sbenno
22168548Sbenno    create_files();
22268548Sbenno
22368548Sbenno    {
22491112Sjake        const path p(".");
22568548Sbenno        path pa = p.to_absolute();
22667204Sobrien        ATF_REQUIRE(pa.is_absolute());
22767204Sobrien
22867204Sobrien        file_info fi(p);
22967204Sobrien        file_info fia(pa);
23068548Sbenno        ATF_REQUIRE_EQ(fi.get_device(), fia.get_device());
23184617Sbenno        ATF_REQUIRE_EQ(fi.get_inode(), fia.get_inode());
23267204Sobrien    }
23367204Sobrien
23468548Sbenno    {
23567204Sobrien        const path p("files/reg");
23667204Sobrien        path pa = p.to_absolute();
23768548Sbenno        ATF_REQUIRE(pa.is_absolute());
23868548Sbenno
23967204Sobrien        file_info fi(p);
24068548Sbenno        file_info fia(pa);
24168548Sbenno        ATF_REQUIRE_EQ(fi.get_device(), fia.get_device());
24268548Sbenno        ATF_REQUIRE_EQ(fi.get_inode(), fia.get_inode());
24368548Sbenno    }
24468548Sbenno}
24568548Sbenno
24668548SbennoATF_TEST_CASE(path_op_less);
24768548SbennoATF_TEST_CASE_HEAD(path_op_less)
24868548Sbenno{
24968548Sbenno    set_md_var("descr", "Tests that the path's less-than operator works");
25068548Sbenno}
25168548SbennoATF_TEST_CASE_BODY(path_op_less)
25268548Sbenno{
25368548Sbenno    using atf::fs::path;
25468548Sbenno
25568548Sbenno    create_files();
25668548Sbenno
25768548Sbenno    ATF_REQUIRE(!(path("aaa") < path("aaa")));
25868548Sbenno
25968548Sbenno    ATF_REQUIRE(  path("aab") < path("abc"));
26068548Sbenno    ATF_REQUIRE(!(path("abc") < path("aab")));
26168548Sbenno}
262
263// ------------------------------------------------------------------------
264// Test cases for the "directory" class.
265// ------------------------------------------------------------------------
266
267ATF_TEST_CASE(directory_read);
268ATF_TEST_CASE_HEAD(directory_read)
269{
270    set_md_var("descr", "Tests the directory class creation, which reads "
271               "the contents of a directory");
272}
273ATF_TEST_CASE_BODY(directory_read)
274{
275    using atf::fs::directory;
276    using atf::fs::path;
277
278    create_files();
279
280    directory d(path("files"));
281    ATF_REQUIRE_EQ(d.size(), 4);
282    ATF_REQUIRE(d.find(".") != d.end());
283    ATF_REQUIRE(d.find("..") != d.end());
284    ATF_REQUIRE(d.find("dir") != d.end());
285    ATF_REQUIRE(d.find("reg") != d.end());
286}
287
288ATF_TEST_CASE(directory_file_info);
289ATF_TEST_CASE_HEAD(directory_file_info)
290{
291    set_md_var("descr", "Tests that the file_info objects attached to the "
292               "directory are valid");
293}
294ATF_TEST_CASE_BODY(directory_file_info)
295{
296    using atf::fs::directory;
297    using atf::fs::file_info;
298    using atf::fs::path;
299
300    create_files();
301
302    directory d(path("files"));
303
304    {
305        directory::const_iterator iter = d.find("dir");
306        ATF_REQUIRE(iter != d.end());
307        const file_info& fi = (*iter).second;
308        ATF_REQUIRE(fi.get_type() == file_info::dir_type);
309    }
310
311    {
312        directory::const_iterator iter = d.find("reg");
313        ATF_REQUIRE(iter != d.end());
314        const file_info& fi = (*iter).second;
315        ATF_REQUIRE(fi.get_type() == file_info::reg_type);
316    }
317}
318
319ATF_TEST_CASE(directory_names);
320ATF_TEST_CASE_HEAD(directory_names)
321{
322    set_md_var("descr", "Tests the directory's names method");
323}
324ATF_TEST_CASE_BODY(directory_names)
325{
326    using atf::fs::directory;
327    using atf::fs::path;
328
329    create_files();
330
331    directory d(path("files"));
332    std::set< std::string > ns = d.names();
333    ATF_REQUIRE_EQ(ns.size(), 4);
334    ATF_REQUIRE(ns.find(".") != ns.end());
335    ATF_REQUIRE(ns.find("..") != ns.end());
336    ATF_REQUIRE(ns.find("dir") != ns.end());
337    ATF_REQUIRE(ns.find("reg") != ns.end());
338}
339
340// ------------------------------------------------------------------------
341// Test cases for the "file_info" class.
342// ------------------------------------------------------------------------
343
344ATF_TEST_CASE(file_info_stat);
345ATF_TEST_CASE_HEAD(file_info_stat)
346{
347    set_md_var("descr", "Tests the file_info creation and its basic contents");
348}
349ATF_TEST_CASE_BODY(file_info_stat)
350{
351    using atf::fs::file_info;
352    using atf::fs::path;
353
354    create_files();
355
356    {
357        path p("files/dir");
358        file_info fi(p);
359        ATF_REQUIRE(fi.get_type() == file_info::dir_type);
360    }
361
362    {
363        path p("files/reg");
364        file_info fi(p);
365        ATF_REQUIRE(fi.get_type() == file_info::reg_type);
366    }
367}
368
369ATF_TEST_CASE(file_info_perms);
370ATF_TEST_CASE_HEAD(file_info_perms)
371{
372    set_md_var("descr", "Tests the file_info methods to get the file's "
373               "permissions");
374}
375ATF_TEST_CASE_BODY(file_info_perms)
376{
377    using atf::fs::file_info;
378    using atf::fs::path;
379
380    path p("file");
381
382    std::ofstream os(p.c_str());
383    os.close();
384
385#define perms(ur, uw, ux, gr, gw, gx, othr, othw, othx) \
386    { \
387        file_info fi(p); \
388        ATF_REQUIRE(fi.is_owner_readable() == ur); \
389        ATF_REQUIRE(fi.is_owner_writable() == uw); \
390        ATF_REQUIRE(fi.is_owner_executable() == ux); \
391        ATF_REQUIRE(fi.is_group_readable() == gr); \
392        ATF_REQUIRE(fi.is_group_writable() == gw); \
393        ATF_REQUIRE(fi.is_group_executable() == gx); \
394        ATF_REQUIRE(fi.is_other_readable() == othr); \
395        ATF_REQUIRE(fi.is_other_writable() == othw); \
396        ATF_REQUIRE(fi.is_other_executable() == othx); \
397    }
398
399    ::chmod(p.c_str(), 0000);
400    perms(false, false, false, false, false, false, false, false, false);
401
402    ::chmod(p.c_str(), 0001);
403    perms(false, false, false, false, false, false, false, false, true);
404
405    ::chmod(p.c_str(), 0010);
406    perms(false, false, false, false, false, true, false, false, false);
407
408    ::chmod(p.c_str(), 0100);
409    perms(false, false, true, false, false, false, false, false, false);
410
411    ::chmod(p.c_str(), 0002);
412    perms(false, false, false, false, false, false, false, true, false);
413
414    ::chmod(p.c_str(), 0020);
415    perms(false, false, false, false, true, false, false, false, false);
416
417    ::chmod(p.c_str(), 0200);
418    perms(false, true, false, false, false, false, false, false, false);
419
420    ::chmod(p.c_str(), 0004);
421    perms(false, false, false, false, false, false, true, false, false);
422
423    ::chmod(p.c_str(), 0040);
424    perms(false, false, false, true, false, false, false, false, false);
425
426    ::chmod(p.c_str(), 0400);
427    perms(true, false, false, false, false, false, false, false, false);
428
429    ::chmod(p.c_str(), 0644);
430    perms(true, true, false, true, false, false, true, false, false);
431
432    ::chmod(p.c_str(), 0755);
433    perms(true, true, true, true, false, true, true, false, true);
434
435    ::chmod(p.c_str(), 0777);
436    perms(true, true, true, true, true, true, true, true, true);
437
438#undef perms
439}
440
441// ------------------------------------------------------------------------
442// Test cases for the free functions.
443// ------------------------------------------------------------------------
444
445ATF_TEST_CASE(exists);
446ATF_TEST_CASE_HEAD(exists)
447{
448    set_md_var("descr", "Tests the exists function");
449}
450ATF_TEST_CASE_BODY(exists)
451{
452    using atf::fs::exists;
453    using atf::fs::path;
454
455    create_files();
456
457    ATF_REQUIRE( exists(path("files")));
458    ATF_REQUIRE(!exists(path("file")));
459    ATF_REQUIRE(!exists(path("files2")));
460
461    ATF_REQUIRE( exists(path("files/.")));
462    ATF_REQUIRE( exists(path("files/..")));
463    ATF_REQUIRE( exists(path("files/dir")));
464    ATF_REQUIRE( exists(path("files/reg")));
465    ATF_REQUIRE(!exists(path("files/foo")));
466}
467
468ATF_TEST_CASE(is_executable);
469ATF_TEST_CASE_HEAD(is_executable)
470{
471    set_md_var("descr", "Tests the is_executable function");
472}
473ATF_TEST_CASE_BODY(is_executable)
474{
475    using atf::fs::is_executable;
476    using atf::fs::path;
477
478    create_files();
479
480    ATF_REQUIRE( is_executable(path("files")));
481    ATF_REQUIRE( is_executable(path("files/.")));
482    ATF_REQUIRE( is_executable(path("files/..")));
483    ATF_REQUIRE( is_executable(path("files/dir")));
484
485    ATF_REQUIRE(!is_executable(path("non-existent")));
486
487    ATF_REQUIRE(!is_executable(path("files/reg")));
488    ATF_REQUIRE(::chmod("files/reg", 0755) != -1);
489    ATF_REQUIRE( is_executable(path("files/reg")));
490}
491
492ATF_TEST_CASE(remove);
493ATF_TEST_CASE_HEAD(remove)
494{
495    set_md_var("descr", "Tests the remove function");
496}
497ATF_TEST_CASE_BODY(remove)
498{
499    using atf::fs::exists;
500    using atf::fs::path;
501    using atf::fs::remove;
502
503    create_files();
504
505    ATF_REQUIRE( exists(path("files/reg")));
506    remove(path("files/reg"));
507    ATF_REQUIRE(!exists(path("files/reg")));
508
509    ATF_REQUIRE( exists(path("files/dir")));
510    ATF_REQUIRE_THROW(atf::system_error, remove(path("files/dir")));
511    ATF_REQUIRE( exists(path("files/dir")));
512}
513
514// ------------------------------------------------------------------------
515// Main.
516// ------------------------------------------------------------------------
517
518ATF_INIT_TEST_CASES(tcs)
519{
520    // Add the tests for the "path" class.
521    ATF_ADD_TEST_CASE(tcs, path_normalize);
522    ATF_ADD_TEST_CASE(tcs, path_is_absolute);
523    ATF_ADD_TEST_CASE(tcs, path_is_root);
524    ATF_ADD_TEST_CASE(tcs, path_branch_path);
525    ATF_ADD_TEST_CASE(tcs, path_leaf_name);
526    ATF_ADD_TEST_CASE(tcs, path_compare_equal);
527    ATF_ADD_TEST_CASE(tcs, path_compare_different);
528    ATF_ADD_TEST_CASE(tcs, path_concat);
529    ATF_ADD_TEST_CASE(tcs, path_to_absolute);
530    ATF_ADD_TEST_CASE(tcs, path_op_less);
531
532    // Add the tests for the "file_info" class.
533    ATF_ADD_TEST_CASE(tcs, file_info_stat);
534    ATF_ADD_TEST_CASE(tcs, file_info_perms);
535
536    // Add the tests for the "directory" class.
537    ATF_ADD_TEST_CASE(tcs, directory_read);
538    ATF_ADD_TEST_CASE(tcs, directory_names);
539    ATF_ADD_TEST_CASE(tcs, directory_file_info);
540
541    // Add the tests for the free functions.
542    ATF_ADD_TEST_CASE(tcs, exists);
543    ATF_ADD_TEST_CASE(tcs, is_executable);
544    ATF_ADD_TEST_CASE(tcs, remove);
545}
546