1 | // |
2 | // DirectoryIteratorsTest.cpp |
3 | // |
4 | // Copyright (c) 2012, Applied Informatics Software Engineering GmbH. |
5 | // and Contributors. |
6 | // |
7 | // SPDX-License-Identifier: BSL-1.0 |
8 | // |
9 | |
10 | |
11 | #include "DirectoryIteratorsTest.h" |
12 | #include "Poco/CppUnit/TestCaller.h" |
13 | #include "Poco/CppUnit/TestSuite.h" |
14 | #include "Poco/DirectoryIterator.h" |
15 | #include "Poco/SortedDirectoryIterator.h" |
16 | #include "Poco/RecursiveDirectoryIterator.h" |
17 | #include "Poco/FileStream.h" |
18 | #include "Poco/Environment.h" |
19 | #include "Poco/Exception.h" |
20 | |
21 | #include <iostream> |
22 | |
23 | #if defined(POCO_OS_FAMILY_UNIX) |
24 | #include <errno.h> |
25 | #include <sys/stat.h> |
26 | #endif |
27 | |
28 | using namespace Poco; |
29 | |
30 | |
31 | #if defined(POCO_OS_FAMILY_UNIX) |
32 | |
33 | static void setReadable(const std::string& path, bool flag) |
34 | { |
35 | poco_assert (!path.empty()); |
36 | |
37 | struct stat st; |
38 | if (stat(path.c_str(), &st) != 0) |
39 | { |
40 | throw FileException("stat error" , path, errno); |
41 | } |
42 | mode_t mode; |
43 | if (flag) |
44 | { |
45 | mode = st.st_mode | S_IRUSR | S_IRGRP | S_IROTH; |
46 | } |
47 | else |
48 | { |
49 | mode_t rmask = S_IRUSR | S_IRGRP | S_IROTH; |
50 | mode = st.st_mode & ~rmask; |
51 | } |
52 | if (chmod(path.c_str(), mode) != 0) |
53 | { |
54 | throw FileException("chmod" , path, errno); |
55 | } |
56 | } |
57 | |
58 | #else |
59 | |
60 | static void setReadable(const std::string& path, bool flag) |
61 | { |
62 | poco_assert (!path.empty()); |
63 | } |
64 | |
65 | #endif |
66 | |
67 | |
68 | class TemporarilyHidePath |
69 | { |
70 | public: |
71 | TemporarilyHidePath(std::string path) |
72 | : _path(path) |
73 | { |
74 | setReadable(_path, false); |
75 | } |
76 | |
77 | ~TemporarilyHidePath() |
78 | { |
79 | setReadable(_path, true); |
80 | } |
81 | private: |
82 | std::string _path; |
83 | }; |
84 | |
85 | |
86 | DirectoryIteratorsTest::DirectoryIteratorsTest(const std::string& name): |
87 | CppUnit::TestCase(name) |
88 | { |
89 | } |
90 | |
91 | |
92 | DirectoryIteratorsTest::~DirectoryIteratorsTest() |
93 | { |
94 | } |
95 | |
96 | |
97 | void DirectoryIteratorsTest::testDirectoryIterator() |
98 | { |
99 | Path p = path(); |
100 | DirectoryIterator dirIterator(p); |
101 | DirectoryIterator end; |
102 | std::vector<std::string> result; |
103 | std::string file; |
104 | |
105 | while (dirIterator != end) |
106 | { |
107 | file = dirIterator->path(); |
108 | ++dirIterator; |
109 | result.push_back(file); |
110 | } |
111 | |
112 | assertEquals(7, (long) result.size()); |
113 | } |
114 | |
115 | |
116 | void DirectoryIteratorsTest::testSortedDirectoryIterator() |
117 | { |
118 | Path p = path(); |
119 | |
120 | SortedDirectoryIterator dirIterator(p); |
121 | SortedDirectoryIterator end; |
122 | std::vector<std::string> result; |
123 | std::string file; |
124 | |
125 | while (dirIterator != end) |
126 | { |
127 | file = Path(dirIterator->path()).getFileName(); |
128 | ++dirIterator; |
129 | result.push_back(file); |
130 | } |
131 | |
132 | assertEquals(7, (long) result.size()); |
133 | assertEquals("first" , result[0]); |
134 | assertEquals("1" , result[1]); |
135 | assertEquals("2" , result[2]); |
136 | assertEquals("A" , result[3]); |
137 | assertEquals("B" , result[4]); |
138 | assertEquals("c" , result[5]); |
139 | assertEquals("d" , result[6]); |
140 | } |
141 | |
142 | |
143 | void DirectoryIteratorsTest::testSimpleRecursiveDirectoryIterator() |
144 | { |
145 | Path p = path(); |
146 | SimpleRecursiveDirectoryIterator dirIterator(p); |
147 | SimpleRecursiveDirectoryIterator end; |
148 | std::vector<std::string> result; |
149 | std::string file; |
150 | |
151 | while (dirIterator != end) |
152 | { |
153 | file = dirIterator->path(); |
154 | ++dirIterator; |
155 | result.push_back(file); |
156 | } |
157 | |
158 | assertEquals(20, (long) result.size()); |
159 | } |
160 | |
161 | |
162 | void DirectoryIteratorsTest::testSimpleRecursiveDirectoryIteratorOnError() |
163 | { |
164 | Path p = path(); |
165 | SimpleRecursiveDirectoryIterator dirIterator(p); |
166 | dirIterator.onError(*this, &DirectoryIteratorsTest::onError); |
167 | SimpleRecursiveDirectoryIterator end; |
168 | std::vector<std::string> result; |
169 | std::string file; |
170 | |
171 | Path second(p); |
172 | second.pushDirectory("first" ); |
173 | second.pushDirectory("second" ); |
174 | std::string errorPath(second.toString()); |
175 | TemporarilyHidePath hidePath(errorPath); |
176 | |
177 | while (dirIterator != end) |
178 | { |
179 | file = dirIterator->path(); |
180 | ++dirIterator; |
181 | result.push_back(file); |
182 | } |
183 | |
184 | #if defined(POCO_OS_FAMILY_UNIX) |
185 | try |
186 | { |
187 | // this test can't work for root |
188 | if (Environment::get("USER" ) != "root" ) |
189 | { |
190 | assertTrue (_onErrorPath.size() > 0); |
191 | if (second.separator() != *_onErrorPath.rbegin()) |
192 | _onErrorPath += second.separator(); |
193 | if (second.separator() != *errorPath.rbegin()) |
194 | errorPath += second.separator(); |
195 | assertEquals(_onErrorPath, errorPath); |
196 | assertEquals(14, (long) result.size()); |
197 | } |
198 | } |
199 | catch (NotFoundException&) { } |
200 | #else |
201 | assertEquals(20, (long) result.size()); |
202 | #endif |
203 | } |
204 | |
205 | |
206 | void DirectoryIteratorsTest::testSiblingsFirstRecursiveDirectoryIterator() |
207 | { |
208 | Path p = path(); |
209 | SiblingsFirstRecursiveDirectoryIterator dirIterator(p); |
210 | SiblingsFirstRecursiveDirectoryIterator end; |
211 | std::vector<std::string> result; |
212 | std::string file; |
213 | |
214 | while (dirIterator != end) |
215 | { |
216 | file = dirIterator->path(); |
217 | ++dirIterator; |
218 | result.push_back(file); |
219 | } |
220 | |
221 | assertEquals(20, (long) result.size()); |
222 | } |
223 | |
224 | |
225 | void DirectoryIteratorsTest::testSiblingsFirstRecursiveDirectoryIteratorOnError() |
226 | { |
227 | Path p = path(); |
228 | SiblingsFirstRecursiveDirectoryIterator dirIterator(p); |
229 | dirIterator.onError(*this, &DirectoryIteratorsTest::onError); |
230 | SimpleRecursiveDirectoryIterator end; |
231 | std::vector<std::string> result; |
232 | std::string file; |
233 | |
234 | Path first(p); |
235 | first.pushDirectory("first" ); |
236 | std::string errorPath(first.toString()); |
237 | TemporarilyHidePath hidePath(errorPath); |
238 | |
239 | while (dirIterator != end) |
240 | { |
241 | file = dirIterator->path(); |
242 | ++dirIterator; |
243 | result.push_back(file); |
244 | } |
245 | |
246 | #if defined(POCO_OS_FAMILY_UNIX) |
247 | try |
248 | { |
249 | // this test can't work for root |
250 | if (Environment::get("USER" ) != "root" ) |
251 | { |
252 | assertTrue (_onErrorPath.size() > 0); |
253 | if (first.separator() != *_onErrorPath.rbegin()) |
254 | _onErrorPath += first.separator(); |
255 | if (first.separator() != *errorPath.rbegin()) |
256 | errorPath += first.separator(); |
257 | assertEquals(_onErrorPath, errorPath); |
258 | assertEquals(7, (long) result.size()); |
259 | } |
260 | } |
261 | catch (NotFoundException&) { } |
262 | #else |
263 | assertEquals(20, (long) result.size()); |
264 | #endif |
265 | } |
266 | |
267 | |
268 | void DirectoryIteratorsTest::setUp() |
269 | { |
270 | File d(path()); |
271 | if (d.exists()) d.remove(true); |
272 | |
273 | /* |
274 | Build Directory Tree like this: |
275 | |
276 | DirectoryIteratorsTest |
277 | |-- 1 |
278 | |-- 2 |
279 | |-- A |
280 | |-- B |
281 | |-- c |
282 | |-- d |
283 | `-- first |
284 | |-- 1 |
285 | |-- 2 |
286 | |-- A |
287 | |-- B |
288 | |-- c |
289 | |-- d |
290 | `-- second |
291 | |-- 1 |
292 | |-- 2 |
293 | |-- A |
294 | |-- B |
295 | |-- c |
296 | `-- d |
297 | |
298 | 2 directories, 18 files |
299 | */ |
300 | Path p = path(); |
301 | createSubdir(p); |
302 | |
303 | p.pushDirectory("first" ); |
304 | createSubdir(p); |
305 | |
306 | p.pushDirectory("second" ); |
307 | createSubdir(p); |
308 | } |
309 | |
310 | |
311 | void DirectoryIteratorsTest::createSubdir(Path& p) |
312 | { |
313 | File d(p); |
314 | d.createDirectories(); |
315 | FileStream f1(p.toString() + "d" ); |
316 | FileStream f2(p.toString() + "1" ); |
317 | FileStream f3(p.toString() + "A" ); |
318 | FileStream f4(p.toString() + "2" ); |
319 | FileStream f5(p.toString() + "B" ); |
320 | FileStream f6(p.toString() + "c" ); |
321 | } |
322 | |
323 | |
324 | void DirectoryIteratorsTest::onError(const void* pSender, const std::string& path) |
325 | { |
326 | _onErrorPath = path; |
327 | } |
328 | |
329 | |
330 | void DirectoryIteratorsTest::tearDown() |
331 | { |
332 | try |
333 | { |
334 | File d(path()); |
335 | d.remove(true); |
336 | } |
337 | catch (...) |
338 | { |
339 | } |
340 | } |
341 | |
342 | |
343 | Poco::Path DirectoryIteratorsTest::path() const |
344 | { |
345 | Path p(Path::current()); |
346 | p.pushDirectory("DirectoryIteratorsTest" ); |
347 | return p; |
348 | } |
349 | |
350 | |
351 | CppUnit::Test* DirectoryIteratorsTest::suite() |
352 | { |
353 | CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("DirectoryIteratorsTest" ); |
354 | |
355 | CppUnit_addTest(pSuite, DirectoryIteratorsTest, testDirectoryIterator); |
356 | CppUnit_addTest(pSuite, DirectoryIteratorsTest, testSortedDirectoryIterator); |
357 | CppUnit_addTest(pSuite, DirectoryIteratorsTest, testSimpleRecursiveDirectoryIterator); |
358 | CppUnit_addTest(pSuite, DirectoryIteratorsTest, testSimpleRecursiveDirectoryIteratorOnError); |
359 | CppUnit_addTest(pSuite, DirectoryIteratorsTest, testSiblingsFirstRecursiveDirectoryIterator); |
360 | CppUnit_addTest(pSuite, DirectoryIteratorsTest, testSiblingsFirstRecursiveDirectoryIteratorOnError); |
361 | |
362 | return pSuite; |
363 | } |
364 | |