Line data Source code
1 : // Copyright (c) 2021-2025 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 path functions work.
21 : *
22 : * This file implements tests for the pathinfo function.
23 : */
24 :
25 : // self
26 : //
27 : #include <snapdev/glob_to_list.h>
28 :
29 : #include "catch_main.h"
30 :
31 :
32 : // C++
33 : //
34 : #include <fstream>
35 : #include <set>
36 :
37 :
38 : // last include
39 : //
40 : #include <snapdev/poison.h>
41 :
42 :
43 :
44 :
45 1 : CATCH_TEST_CASE("glob_to_list", "[filename][glob][os]")
46 : {
47 1 : CATCH_START_SECTION("pathinfo: replace existing suffix")
48 : {
49 1 : std::string top_dir(SNAP_CATCH2_NAMESPACE::g_tmp_dir() + "/top");
50 1 : int r(system(("rm -rf " + top_dir).c_str()));
51 1 : CATCH_REQUIRE(r == 0);
52 1 : CATCH_REQUIRE(mkdir(top_dir.c_str(), 0777) == 0);
53 :
54 1 : std::string foo_dir(top_dir + "/foo");
55 1 : CATCH_REQUIRE(mkdir(foo_dir.c_str(), 0777) == 0);
56 :
57 1 : std::string bar_dir(top_dir + "/bar");
58 1 : CATCH_REQUIRE(mkdir(bar_dir.c_str(), 0777) == 0);
59 :
60 1 : std::string sub_bar_dir(bar_dir + "/sub");
61 1 : CATCH_REQUIRE(mkdir(sub_bar_dir.c_str(), 0777) == 0);
62 :
63 1 : std::string hidden_bar_dir(sub_bar_dir + "/hidden");
64 1 : CATCH_REQUIRE(mkdir(hidden_bar_dir.c_str(), 0777) == 0);
65 :
66 1 : std::string foo_txt(foo_dir + "/foo.txt");
67 1 : std::ofstream foo_file;
68 1 : foo_file.open(foo_txt);
69 1 : foo_file << "foo file\n";
70 1 : CATCH_REQUIRE(foo_file.good());
71 :
72 1 : std::string foo2_txt(foo_dir + "/foo-2.txt");
73 1 : std::ofstream foo2_file;
74 1 : foo2_file.open(foo2_txt);
75 1 : foo2_file << "foo #2 file\n";
76 1 : CATCH_REQUIRE(foo2_file.good());
77 :
78 1 : std::string bar_txt(bar_dir + "/bar.txt");
79 1 : std::ofstream bar_file;
80 1 : bar_file.open(bar_txt);
81 1 : bar_file << "bar file\n";
82 1 : CATCH_REQUIRE(bar_file.good());
83 :
84 1 : std::string bar2_txt(bar_dir + "/bar_2.txt");
85 1 : std::ofstream bar2_file;
86 1 : bar2_file.open(bar2_txt);
87 1 : bar2_file << "bar two file\n";
88 1 : CATCH_REQUIRE(bar2_file.good());
89 :
90 1 : std::string sub_bar3_txt(sub_bar_dir + "/sub-bar3.txt");
91 1 : std::ofstream sub_bar3_file;
92 1 : sub_bar3_file.open(sub_bar3_txt);
93 1 : sub_bar3_file << "no. 3 -- sub-bar file\n";
94 1 : CATCH_REQUIRE(sub_bar3_file.good());
95 :
96 1 : std::string hidden_settings_conf(hidden_bar_dir + "/settings.conf");
97 1 : std::ofstream hidden_settings_file;
98 1 : hidden_settings_file.open(hidden_settings_conf);
99 1 : hidden_settings_file << "hidden=\"config file\"\n";
100 1 : CATCH_REQUIRE(hidden_settings_file.good());
101 :
102 : // soft links to a file are kept
103 : //
104 1 : std::string soft_link_txt(sub_bar_dir + "/soft-link.txt");
105 1 : CATCH_REQUIRE(symlink("../../foo/foo-2.txt", soft_link_txt.c_str()) == 0);
106 :
107 : // soft links to a directory are ignored by default
108 : //
109 1 : std::string soft_dir(sub_bar_dir + "/soft-dir");
110 1 : CATCH_REQUIRE(symlink("../../bar", soft_dir.c_str()) == 0);
111 :
112 : // soft links which loops forever
113 : //
114 1 : std::string loop_dir(hidden_bar_dir + "/loop.lnk");
115 1 : CATCH_REQUIRE(symlink("../hidden", loop_dir.c_str()) == 0);
116 :
117 : // read all the files (*)
118 : //
119 : typedef std::set<std::string> strings_t;
120 1 : snapdev::glob_to_list<strings_t> all_glob;
121 1 : CATCH_REQUIRE(all_glob.read_path<
122 : snapdev::glob_to_list_flag_t::GLOB_FLAG_RECURSIVE>(top_dir + "/*"));
123 :
124 : // soft-links are followed and the realpath() function returns
125 : // the target; here we "computed" what the glob() is expected to
126 : // return (i.e. not the target)
127 : //
128 1 : std::string const soft_link_link(all_glob.get_real_path(sub_bar_dir) + "/soft-link.txt");
129 1 : std::string const soft_dir_link(all_glob.get_real_path(sub_bar_dir) + "/soft-dir");
130 1 : std::string const loop_dir_link(all_glob.get_real_path(hidden_bar_dir) + "/loop.lnk");
131 :
132 1 : CATCH_REQUIRE(all_glob.size() == 13);
133 1 : CATCH_REQUIRE(all_glob.count(all_glob.get_real_path(bar_dir)) == 1);
134 1 : CATCH_REQUIRE(all_glob.count(all_glob.get_real_path(bar_txt)) == 1);
135 1 : CATCH_REQUIRE(all_glob.count(all_glob.get_real_path(bar2_txt)) == 1);
136 1 : CATCH_REQUIRE(all_glob.count(all_glob.get_real_path(sub_bar_dir)) == 1);
137 1 : CATCH_REQUIRE(all_glob.count(all_glob.get_real_path(hidden_bar_dir)) == 1);
138 1 : CATCH_REQUIRE(all_glob.count(loop_dir_link) == 1);
139 1 : CATCH_REQUIRE(all_glob.count(all_glob.get_real_path(hidden_settings_conf)) == 1);
140 1 : CATCH_REQUIRE(all_glob.count(soft_dir_link) == 1);
141 1 : CATCH_REQUIRE(all_glob.count(soft_link_link) == 1);
142 1 : CATCH_REQUIRE(all_glob.count(all_glob.get_real_path(sub_bar3_txt)) == 1);
143 1 : CATCH_REQUIRE(all_glob.count(all_glob.get_real_path(foo_dir)) == 1);
144 1 : CATCH_REQUIRE(all_glob.count(all_glob.get_real_path(foo2_txt)) == 1);
145 1 : CATCH_REQUIRE(all_glob.count(all_glob.get_real_path(foo_txt)) == 1);
146 :
147 : // read all text files (*.txt)
148 : //
149 : typedef std::set<std::string> strings_t;
150 1 : snapdev::glob_to_list<strings_t> txt_glob;
151 1 : CATCH_REQUIRE(txt_glob.read_path<
152 : snapdev::glob_to_list_flag_t::GLOB_FLAG_RECURSIVE>(top_dir + "/*.txt"));
153 :
154 1 : CATCH_REQUIRE(txt_glob.size() == 6);
155 1 : CATCH_REQUIRE(txt_glob.count(txt_glob.get_real_path(bar_txt)) == 1);
156 1 : CATCH_REQUIRE(txt_glob.count(txt_glob.get_real_path(bar2_txt)) == 1);
157 1 : CATCH_REQUIRE(txt_glob.count(txt_glob.get_real_path(soft_link_link)) == 1);
158 1 : CATCH_REQUIRE(txt_glob.count(txt_glob.get_real_path(sub_bar3_txt)) == 1);
159 1 : CATCH_REQUIRE(txt_glob.count(txt_glob.get_real_path(foo2_txt)) == 1);
160 1 : CATCH_REQUIRE(txt_glob.count(txt_glob.get_real_path(foo_txt)) == 1);
161 :
162 : // read text file within the bar sub-directory
163 : //
164 : typedef std::set<std::string> strings_t;
165 1 : snapdev::glob_to_list<strings_t> sub_bar_glob;
166 1 : CATCH_REQUIRE(sub_bar_glob.read_path<
167 : snapdev::glob_to_list_flag_t::GLOB_FLAG_RECURSIVE>(sub_bar_dir + "/*.txt"));
168 :
169 1 : CATCH_REQUIRE(sub_bar_glob.size() == 2);
170 1 : CATCH_REQUIRE(sub_bar_glob.count(soft_link_link) == 1);
171 1 : CATCH_REQUIRE(sub_bar_glob.count(sub_bar_glob.get_real_path(sub_bar3_txt)) == 1);
172 :
173 : // read text files within the bar sub-directory and follow symlinks
174 : //
175 : typedef std::set<std::string> strings_t;
176 1 : snapdev::glob_to_list<strings_t> symlink_glob;
177 1 : CATCH_REQUIRE(symlink_glob.read_path<
178 : snapdev::glob_to_list_flag_t::GLOB_FLAG_FOLLOW_SYMLINK
179 : , snapdev::glob_to_list_flag_t::GLOB_FLAG_RECURSIVE>(sub_bar_dir + "/*.txt"));
180 :
181 1 : CATCH_REQUIRE(symlink_glob.size() == 4);
182 1 : CATCH_REQUIRE(symlink_glob.count(symlink_glob.get_real_path(bar_txt)) == 1);
183 1 : CATCH_REQUIRE(symlink_glob.count(symlink_glob.get_real_path(bar2_txt)) == 1);
184 1 : CATCH_REQUIRE(symlink_glob.count(soft_link_link) == 1);
185 1 : CATCH_REQUIRE(symlink_glob.count(symlink_glob.get_real_path(sub_bar3_txt)) == 1);
186 :
187 1 : }
188 1 : CATCH_END_SECTION()
189 1 : }
190 :
191 :
192 :
193 : // vim: ts=4 sw=4 et
|