Line data Source code
1 : // Copyright (c) 2018-2024 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 3 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
17 : // along with this program. If not, see <https://www.gnu.org/licenses/>.
18 :
19 : /** \file
20 : * \brief Verify that the mkdir_p() function works.
21 : *
22 : * This file implements tests for the mkdir_p() function.
23 : */
24 :
25 : // self
26 : //
27 : #include <snapdev/mkdir_p.h>
28 :
29 : #include <snapdev/file_contents.h>
30 : #include <snapdev/raii_generic_deleter.h>
31 : #include <snapdev/pathinfo.h>
32 :
33 : #include "catch_main.h"
34 :
35 :
36 : // C
37 : //
38 : #include <unistd.h>
39 :
40 :
41 : // last include
42 : //
43 : #include <snapdev/poison.h>
44 :
45 :
46 :
47 :
48 3 : CATCH_TEST_CASE("mkdir_p", "[os]")
49 : {
50 3 : CATCH_START_SECTION("mkdir_p: empty")
51 : {
52 1 : CATCH_REQUIRE(snapdev::mkdir_p(std::string(), true, 0700, "user", "group") == 0);
53 1 : CATCH_REQUIRE(snapdev::mkdir_p(std::string(), false, 0700, "user", "group") == 0);
54 1 : CATCH_REQUIRE(snapdev::mkdir_p(std::string(), true, 0775, "user", "group") == 0);
55 1 : CATCH_REQUIRE(snapdev::mkdir_p(std::string(), false, 0775, "user", "group") == 0);
56 1 : CATCH_REQUIRE(snapdev::mkdir_p(std::string(), true, 0700, std::string(), "group") == 0);
57 1 : CATCH_REQUIRE(snapdev::mkdir_p(std::string(), false, 0700, std::string(), "group") == 0);
58 1 : CATCH_REQUIRE(snapdev::mkdir_p(std::string(), true, 0775, std::string(), "group") == 0);
59 1 : CATCH_REQUIRE(snapdev::mkdir_p(std::string(), false, 0775, std::string(), "group") == 0);
60 1 : CATCH_REQUIRE(snapdev::mkdir_p(std::string(), true, 0700, "user", std::string()) == 0);
61 1 : CATCH_REQUIRE(snapdev::mkdir_p(std::string(), false, 0700, "user", std::string()) == 0);
62 1 : CATCH_REQUIRE(snapdev::mkdir_p(std::string(), true, 0775, "user", std::string()) == 0);
63 1 : CATCH_REQUIRE(snapdev::mkdir_p(std::string(), false, 0775, "user", std::string()) == 0);
64 1 : CATCH_REQUIRE(snapdev::mkdir_p(std::string(), true, 0700, std::string(), std::string()) == 0);
65 1 : CATCH_REQUIRE(snapdev::mkdir_p(std::string(), false, 0700, std::string(), std::string()) == 0);
66 1 : CATCH_REQUIRE(snapdev::mkdir_p(std::string(), true, 0775, std::string(), std::string()) == 0);
67 1 : CATCH_REQUIRE(snapdev::mkdir_p(std::string(), false, 0775, std::string(), std::string()) == 0);
68 : }
69 3 : CATCH_END_SECTION()
70 :
71 3 : CATCH_START_SECTION("mkdir_p: create")
72 : {
73 : // TODO: for a complete test, we would need to transform the g_tmp_dir
74 : // in a relative path, which is complicated at the moment...
75 : //
76 1 : std::string const filename(SNAP_CATCH2_NAMESPACE::g_tmp_dir() + "/with/extra/sub-dirs/and-a-file.txt");
77 1 : CATCH_REQUIRE(snapdev::mkdir_p(filename, true, 0700) == 0);
78 :
79 : // the file itself needs to not exist
80 : //
81 1 : struct stat st;
82 1 : CATCH_REQUIRE(stat(filename.c_str(), &st) != 0);
83 :
84 : // the last directory needs to be 0700
85 : //
86 1 : std::string const basename(snapdev::pathinfo::dirname(filename));
87 1 : CATCH_REQUIRE(stat(basename.c_str(), &st) == 0);
88 1 : CATCH_REQUIRE(S_ISDIR(st.st_mode));
89 1 : CATCH_REQUIRE((st.st_mode & 0777) == 0700);
90 :
91 : // re-create with a different mode changes it
92 : //
93 1 : CATCH_REQUIRE(snapdev::mkdir_p(filename, true, 0755) == 0);
94 1 : CATCH_REQUIRE(stat(basename.c_str(), &st) == 0);
95 1 : CATCH_REQUIRE(S_ISDIR(st.st_mode));
96 1 : CATCH_REQUIRE((st.st_mode & 0777) == 0755);
97 :
98 : // last component is a file, that creates an error
99 : //
100 1 : snapdev::file_contents actual_file(filename);
101 1 : actual_file.contents("test file--testing that create folder fails if a file exists\n");
102 1 : actual_file.write_all();
103 :
104 1 : int const r(snapdev::mkdir_p(filename, false, 0700));
105 1 : int const e(errno);
106 1 : CATCH_REQUIRE(r == -1);
107 1 : CATCH_REQUIRE(e == EEXIST);
108 1 : }
109 3 : CATCH_END_SECTION()
110 :
111 3 : CATCH_START_SECTION("mkdir_p: create full path")
112 : {
113 1 : std::unique_ptr<char *, snapdev::raii_generic_deleter<char *, nullptr, decltype(&::free), &::free>> cwd(get_current_dir_name());
114 1 : std::string const filename(SNAP_CATCH2_NAMESPACE::g_tmp_dir() + "/test/with/root/path");
115 1 : CATCH_REQUIRE(snapdev::mkdir_p(filename, false, 0750) == 0);
116 :
117 : // the last directory needs to be 0700
118 : //
119 1 : std::string const basename(snapdev::pathinfo::dirname(filename));
120 1 : struct stat st;
121 1 : CATCH_REQUIRE(stat(basename.c_str(), &st) == 0);
122 1 : bool is_dir(S_ISDIR(st.st_mode));
123 1 : CATCH_REQUIRE(is_dir);
124 1 : }
125 3 : CATCH_END_SECTION()
126 3 : }
127 :
128 :
129 :
130 : // vim: ts=4 sw=4 et
|