Line data Source code
1 : // Copyright (c) 2018-2022 Made to Order Software Corp. All Rights Reserved
2 : //
3 : // https://snapwebsites.org/project/snapdev
4 : // contact@m2osw.com
5 : //
6 : // This program is free software; you can redistribute it and/or modify
7 : // it under the terms of the GNU General Public License as published by
8 : // the Free Software Foundation; either version 2 of the License, or
9 : // (at your option) any later version.
10 : //
11 : // This program is distributed in the hope that it will be useful,
12 : // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 : // GNU General Public License for more details.
15 : //
16 : // You should have received a copy of the GNU General Public License along
17 : // with this program; if not, write to the Free Software Foundation, Inc.,
18 : // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 :
20 : /** \file
21 : * \brief Verify that the mkdir_p() function works.
22 : *
23 : * This file implements tests for the mkdir_p() function.
24 : */
25 :
26 : // self
27 : //
28 : #include <snapdev/mkdir_p.h>
29 :
30 : #include <snapdev/file_contents.h>
31 : #include <snapdev/raii_generic_deleter.h>
32 : #include <snapdev/pathinfo.h>
33 :
34 : #include "catch_main.h"
35 :
36 :
37 : // C lib
38 : //
39 : #include <unistd.h>
40 :
41 :
42 : // last include
43 : //
44 : #include <snapdev/poison.h>
45 :
46 :
47 :
48 :
49 5 : CATCH_TEST_CASE("mkdir_p", "[os]")
50 : {
51 6 : CATCH_START_SECTION("mkdir_p: empty")
52 : {
53 1 : CATCH_REQUIRE(snapdev::mkdir_p(std::string(), true, 0700, "user", "group") == 0);
54 1 : CATCH_REQUIRE(snapdev::mkdir_p(std::string(), false, 0700, "user", "group") == 0);
55 1 : CATCH_REQUIRE(snapdev::mkdir_p(std::string(), true, 0775, "user", "group") == 0);
56 1 : CATCH_REQUIRE(snapdev::mkdir_p(std::string(), false, 0775, "user", "group") == 0);
57 1 : CATCH_REQUIRE(snapdev::mkdir_p(std::string(), true, 0700, std::string(), "group") == 0);
58 1 : CATCH_REQUIRE(snapdev::mkdir_p(std::string(), false, 0700, std::string(), "group") == 0);
59 1 : CATCH_REQUIRE(snapdev::mkdir_p(std::string(), true, 0775, std::string(), "group") == 0);
60 1 : CATCH_REQUIRE(snapdev::mkdir_p(std::string(), false, 0775, std::string(), "group") == 0);
61 1 : CATCH_REQUIRE(snapdev::mkdir_p(std::string(), true, 0700, "user", std::string()) == 0);
62 1 : CATCH_REQUIRE(snapdev::mkdir_p(std::string(), false, 0700, "user", std::string()) == 0);
63 1 : CATCH_REQUIRE(snapdev::mkdir_p(std::string(), true, 0775, "user", std::string()) == 0);
64 1 : CATCH_REQUIRE(snapdev::mkdir_p(std::string(), false, 0775, "user", std::string()) == 0);
65 1 : CATCH_REQUIRE(snapdev::mkdir_p(std::string(), true, 0700, std::string(), std::string()) == 0);
66 1 : CATCH_REQUIRE(snapdev::mkdir_p(std::string(), false, 0700, std::string(), std::string()) == 0);
67 1 : CATCH_REQUIRE(snapdev::mkdir_p(std::string(), true, 0775, std::string(), std::string()) == 0);
68 1 : CATCH_REQUIRE(snapdev::mkdir_p(std::string(), false, 0775, std::string(), std::string()) == 0);
69 : }
70 : CATCH_END_SECTION()
71 :
72 6 : CATCH_START_SECTION("mkdir_p: create")
73 : {
74 : // TODO: for a complete test, we would need to transform the g_tmp_dir
75 : // in a relative path, which is complicated at the moment...
76 : //
77 2 : std::string const filename(SNAP_CATCH2_NAMESPACE::g_tmp_dir() + "/with/extra/sub-dirs/and-a-file.txt");
78 1 : CATCH_REQUIRE(snapdev::mkdir_p(filename, true, 0700) == 0);
79 :
80 : // the file itself needs to not exist
81 : //
82 1 : struct stat st;
83 1 : CATCH_REQUIRE(stat(filename.c_str(), &st) != 0);
84 :
85 : // the last directory needs to be 0700
86 : //
87 2 : std::string const basename(snapdev::pathinfo::dirname(filename));
88 1 : CATCH_REQUIRE(stat(basename.c_str(), &st) == 0);
89 1 : CATCH_REQUIRE(S_ISDIR(st.st_mode));
90 1 : CATCH_REQUIRE((st.st_mode & 0777) == 0700);
91 :
92 : // re-create with a different mode changes it
93 : //
94 1 : CATCH_REQUIRE(snapdev::mkdir_p(filename, true, 0755) == 0);
95 1 : CATCH_REQUIRE(stat(basename.c_str(), &st) == 0);
96 1 : CATCH_REQUIRE(S_ISDIR(st.st_mode));
97 1 : CATCH_REQUIRE((st.st_mode & 0777) == 0755);
98 :
99 : // last component is a file, that creates an error
100 : //
101 2 : snapdev::file_contents actual_file(filename);
102 1 : actual_file.contents("test file--testing that create folder fails if a file exists\n");
103 1 : actual_file.write_all();
104 :
105 1 : int const r(snapdev::mkdir_p(filename, false, 0700));
106 1 : int const e(errno);
107 1 : CATCH_REQUIRE(r == -1);
108 1 : CATCH_REQUIRE(e == EEXIST);
109 : }
110 : CATCH_END_SECTION()
111 :
112 6 : CATCH_START_SECTION("mkdir_p: create full path")
113 : {
114 3 : std::unique_ptr<char *, snapdev::raii_generic_deleter<char *, nullptr, decltype(&::free), &::free>> cwd(get_current_dir_name());
115 2 : std::string const filename(SNAP_CATCH2_NAMESPACE::g_tmp_dir() + "/test/with/root/path");
116 1 : CATCH_REQUIRE(snapdev::mkdir_p(filename, false, 0750) == 0);
117 :
118 : // the last directory needs to be 0700
119 : //
120 2 : std::string const basename(snapdev::pathinfo::dirname(filename));
121 1 : struct stat st;
122 1 : CATCH_REQUIRE(stat(basename.c_str(), &st) == 0);
123 1 : bool is_dir(S_ISDIR(st.st_mode));
124 1 : CATCH_REQUIRE(is_dir);
125 : }
126 : CATCH_END_SECTION()
127 9 : }
128 :
129 :
130 :
131 : // vim: ts=4 sw=4 et
|