Commit | Line | Data |
---|---|---|
0e23f538 TJ |
1 | /* |
2 | The software in this package is distributed under the GNU General | |
3 | Public License version 2 (with a special exception described below). | |
4 | ||
5 | A copy of GNU General Public License (GPL) is included in this distribution, | |
6 | in the file COPYING.GPL. | |
7 | ||
8 | As a special exception, if other files instantiate templates or use macros | |
9 | or inline functions from this file, or you compile this file and link it | |
10 | with other works to produce a work based on this file, this file | |
11 | does not by itself cause the resulting work to be covered | |
12 | by the GNU General Public License. | |
13 | ||
14 | However the source code for this file must still be made available | |
15 | in accordance with section (3) of the GNU General Public License. | |
16 | ||
17 | This exception does not invalidate any other reasons why a work based | |
18 | on this file might be covered by the GNU General Public License. | |
19 | */ | |
5de0c58a RP |
20 | /** @file |
21 | * | |
22 | * tests for the modules "filefunc", "daemonfunc" | |
23 | * | |
24 | * (c) Copyright 2007-2008 by Intra2net AG | |
5de0c58a RP |
25 | */ |
26 | ||
27 | //#define NOISEDEBUG | |
28 | ||
29 | #include <string> | |
30 | #include <vector> | |
31 | #include <list> | |
9fe0853b | 32 | #include <set> |
5de0c58a RP |
33 | #include <iostream> |
34 | #include <iomanip> | |
1a2fc4e8 | 35 | #include <fstream> |
5de0c58a RP |
36 | #include <sstream> |
37 | #include <algorithm> | |
38 | ||
9fe0853b TJ |
39 | #define BOOST_TEST_DYN_LINK |
40 | #include <boost/test/unit_test.hpp> | |
5de0c58a RP |
41 | |
42 | #include <filefunc.hxx> | |
90246b4a | 43 | #include <daemonfunc.hpp> |
34ed5e5e GE |
44 | #include <pipestream.hxx> |
45 | #include <stringfunc.hxx> | |
5de0c58a RP |
46 | |
47 | #ifdef NOISEDEBUG | |
48 | #define DOUT(msg) std::cout << msg << std::endl | |
49 | #else | |
50 | #define DOUT(msg) do {} while (0) | |
51 | #endif | |
52 | ||
1a2fc4e8 | 53 | using namespace std; |
5de0c58a RP |
54 | using namespace I2n; |
55 | ||
9fe0853b | 56 | class TestFileFuncFixture |
48d97d6c | 57 | { |
48d97d6c | 58 | protected: |
48d97d6c | 59 | typedef std::list< std::string > StringList; |
48d97d6c TJ |
60 | std::set<std::string> used_check_files; |
61 | ||
62 | std::string get_check_file_path(std::string tag) | |
63 | { | |
64 | std::string result; | |
65 | result= "__unittest__" + tag + ".dat"; | |
66 | used_check_files.insert(result); | |
67 | return result; | |
68 | } // eo get_check_file_path | |
69 | ||
48d97d6c TJ |
70 | void remove_check_files() |
71 | { | |
72 | for (std::set<std::string>::iterator it= used_check_files.begin(); | |
73 | it != used_check_files.end(); | |
74 | ++it) | |
75 | { | |
76 | std::string filepath(*it); | |
77 | if (path_exists(filepath)) | |
78 | { | |
79 | unlink(filepath); | |
80 | } | |
81 | //TODO | |
82 | } | |
83 | used_check_files.clear(); | |
84 | } // eo remove_check_files | |
85 | ||
48d97d6c | 86 | public: |
9fe0853b TJ |
87 | TestFileFuncFixture() |
88 | { | |
89 | } | |
48d97d6c | 90 | |
9fe0853b TJ |
91 | ~TestFileFuncFixture() |
92 | { | |
93 | remove_check_files(); | |
94 | } | |
95 | }; | |
48d97d6c | 96 | |
9fe0853b | 97 | BOOST_FIXTURE_TEST_SUITE(TestFileFunc, TestFileFuncFixture) |
48d97d6c | 98 | |
9fe0853b TJ |
99 | BOOST_AUTO_TEST_CASE(StatTest1) |
100 | { | |
c1a0882a | 101 | I2n::Stat stat(__FILE__); |
48d97d6c | 102 | |
9fe0853b TJ |
103 | BOOST_CHECK_EQUAL( true, (bool)stat ); |
104 | BOOST_CHECK_EQUAL( true, stat.is_regular_file() ); | |
105 | BOOST_CHECK_EQUAL( false, stat.is_directory() ); | |
48d97d6c | 106 | |
9fe0853b | 107 | stat= Stat("/dev/null"); |
48d97d6c | 108 | |
9fe0853b TJ |
109 | BOOST_CHECK_EQUAL( true, (bool)stat ); |
110 | BOOST_CHECK_EQUAL( false, stat.is_regular_file() ); | |
111 | BOOST_CHECK_EQUAL( false, stat.is_directory() ); | |
112 | BOOST_CHECK_EQUAL( true, stat.is_device() ); | |
113 | BOOST_CHECK_EQUAL( true, stat.is_character_device() ); | |
114 | BOOST_CHECK_EQUAL( false, stat.is_block_device() ); | |
115 | } // eo StatTest1 | |
48d97d6c | 116 | |
a9f2cccc GE |
117 | BOOST_AUTO_TEST_CASE(StatSize) |
118 | { | |
119 | write_file("/tmp/test","some nice content to make sure the file system optimizations don't inline this into the inode block"); | |
120 | ||
121 | I2n::Stat stat("/tmp/test"); | |
122 | ||
123 | BOOST_CHECK_EQUAL( true, (bool)stat ); | |
124 | BOOST_CHECK_EQUAL( true, stat.is_regular_file() ); | |
125 | ||
126 | BOOST_CHECK_EQUAL( true, ( stat.bytes_on_disk() >= 512 ) ); | |
127 | ||
128 | unlink("/tmp/test"); | |
129 | } // eo StatSize | |
130 | ||
96fe2dc5 GE |
131 | BOOST_AUTO_TEST_CASE(StatRecheck) |
132 | { | |
133 | // just to be sure | |
134 | unlink(".foobar"); | |
135 | ||
136 | I2n::Stat stat(".foobar"); | |
137 | BOOST_CHECK_EQUAL( false, (bool)stat ); | |
138 | ||
139 | write_file(".foobar","hello world"); | |
140 | ||
141 | stat.recheck(); | |
142 | ||
143 | BOOST_CHECK_EQUAL( true, (bool)stat ); | |
144 | BOOST_CHECK_EQUAL( true, stat.size() > 0 ); | |
145 | ||
146 | unlink(".foobar"); | |
147 | } | |
48d97d6c | 148 | |
9fe0853b TJ |
149 | BOOST_AUTO_TEST_CASE(DirTest1) |
150 | { | |
151 | typedef std::vector< std::string > StringVector; | |
152 | StringVector names; | |
48d97d6c | 153 | |
c1a0882a CH |
154 | string test_dir = dirname(__FILE__); |
155 | bool res= I2n::get_dir(test_dir,names); | |
48d97d6c | 156 | |
9fe0853b TJ |
157 | BOOST_CHECK_EQUAL( true, res ); |
158 | BOOST_CHECK( ! names.empty() ); | |
48d97d6c | 159 | |
c1a0882a CH |
160 | BOOST_MESSAGE("Looking for " << basename(__FILE__) << " in " << test_dir); |
161 | StringVector::iterator it = std::find( names.begin(), names.end(), basename(__FILE__)); | |
9fe0853b | 162 | BOOST_CHECK( it != names.end() ); |
48d97d6c | 163 | |
9fe0853b TJ |
164 | it = std::find( names.begin(), names.end(), "." ); |
165 | BOOST_CHECK( it == names.end() ); | |
48d97d6c | 166 | |
c1a0882a | 167 | names= get_dir(test_dir,true); |
9fe0853b | 168 | BOOST_CHECK( ! names.empty() ); |
48d97d6c | 169 | |
9fe0853b TJ |
170 | for (it= names.begin(); it!=names.end(); ++it) |
171 | { | |
172 | DOUT(" \"" << *it << "\""); | |
173 | BOOST_CHECK_EQUAL( false, it->empty() ); | |
174 | } | |
48d97d6c | 175 | |
9fe0853b TJ |
176 | it = std::find( names.begin(), names.end(), "." ); |
177 | BOOST_CHECK( it != names.end() ); | |
178 | } // eo DirTest1 | |
48d97d6c TJ |
179 | |
180 | ||
181 | ||
9fe0853b TJ |
182 | BOOST_AUTO_TEST_CASE(PathCuts1) |
183 | { | |
184 | std::string path1("/an/absolute/path"); | |
48d97d6c | 185 | |
9fe0853b TJ |
186 | BOOST_CHECK_EQUAL( std::string("/an/absolute"), dirname(path1) ); |
187 | BOOST_CHECK_EQUAL( std::string("path"), basename(path1) ); | |
48d97d6c | 188 | |
9fe0853b TJ |
189 | std::string path2("just.a.name"); |
190 | BOOST_CHECK_EQUAL( std::string("just.a.name"), basename(path2) ); | |
191 | BOOST_CHECK_EQUAL( std::string("."), dirname(path2) ); | |
192 | } // eo PathCuts1() | |
48d97d6c | 193 | |
48d97d6c | 194 | |
48d97d6c | 195 | |
9fe0853b TJ |
196 | BOOST_AUTO_TEST_CASE(NormalizePath1) |
197 | { | |
198 | std::string path; | |
48d97d6c | 199 | |
9fe0853b TJ |
200 | path= normalize_path("/a/simple/path/"); |
201 | BOOST_CHECK_EQUAL( std::string("/a/simple/path"), path ); | |
48d97d6c | 202 | |
9fe0853b TJ |
203 | path= normalize_path("//another///simple/.//path//"); |
204 | BOOST_CHECK_EQUAL( std::string("/another/simple/path"), path ); | |
19166500 | 205 | |
9fe0853b TJ |
206 | path= normalize_path("//..//..//a/dummy///../././simple/././/path//"); |
207 | BOOST_CHECK_EQUAL( std::string("/a/simple/path"), path ); | |
19166500 | 208 | |
9fe0853b TJ |
209 | path= normalize_path("../a/dummy//././..//simple//nice//absolute//.././..//relative/path//"); |
210 | BOOST_CHECK_EQUAL( std::string("../a/simple/relative/path"), path ); | |
19166500 | 211 | |
9fe0853b TJ |
212 | path= normalize_path("../../a/dummy//././..//simple/../nice//absolute//../.x/..//relative/path//"); |
213 | BOOST_CHECK_EQUAL( std::string("../../a/nice/relative/path"), path ); | |
19166500 | 214 | |
9fe0853b | 215 | } // eo NormalizePath1 |
19166500 | 216 | |
9fe0853b TJ |
217 | BOOST_AUTO_TEST_CASE(NormalizePath2) |
218 | { | |
219 | std::string path; | |
19166500 | 220 | |
9fe0853b TJ |
221 | path= normalize_path("/"); |
222 | BOOST_CHECK_EQUAL( std::string("/"), path ); | |
19166500 | 223 | |
9fe0853b TJ |
224 | path= normalize_path("//"); |
225 | BOOST_CHECK_EQUAL( std::string("/"), path ); | |
48d97d6c | 226 | |
9fe0853b TJ |
227 | path= normalize_path("/.//"); |
228 | BOOST_CHECK_EQUAL( std::string("/"), path ); | |
48d97d6c | 229 | |
9fe0853b TJ |
230 | path= normalize_path("."); |
231 | BOOST_CHECK_EQUAL( std::string(""), path ); | |
48d97d6c | 232 | |
9fe0853b TJ |
233 | path= normalize_path("./"); |
234 | BOOST_CHECK_EQUAL( std::string(""), path ); | |
48d97d6c | 235 | |
9fe0853b TJ |
236 | path= normalize_path(".///"); |
237 | BOOST_CHECK_EQUAL( std::string(""), path ); | |
48d97d6c | 238 | |
9fe0853b TJ |
239 | path= normalize_path("/./data/files"); |
240 | BOOST_CHECK_EQUAL( std::string("/data/files"), path ); | |
48d97d6c | 241 | |
9fe0853b TJ |
242 | path= normalize_path("./data/files/"); |
243 | BOOST_CHECK_EQUAL( std::string("data/files"), path ); | |
244 | } // eo NormalizePath2 | |
48d97d6c | 245 | |
9fe0853b TJ |
246 | BOOST_AUTO_TEST_CASE(TestUserAndGroupStuff1) |
247 | { | |
248 | User user_root((uid_t)0); | |
249 | BOOST_CHECK_EQUAL( true, user_root.is_valid() ); | |
250 | BOOST_CHECK_EQUAL( true, (bool)user_root ); | |
48d97d6c | 251 | |
9fe0853b TJ |
252 | BOOST_CHECK_EQUAL( std::string("root"), user_root.Name ); |
253 | BOOST_CHECK_EQUAL( (uid_t)0, user_root.Uid ); | |
254 | BOOST_CHECK_EQUAL( (gid_t)0, user_root.Gid ); | |
48d97d6c | 255 | |
9fe0853b TJ |
256 | User user_root2("root"); |
257 | BOOST_CHECK_EQUAL( true, user_root2.is_valid() ); | |
258 | BOOST_CHECK_EQUAL( true, (bool)user_root2 ); | |
48d97d6c | 259 | |
9fe0853b TJ |
260 | BOOST_CHECK_EQUAL( std::string("root"), user_root2.Name ); |
261 | BOOST_CHECK_EQUAL( (uid_t)0, user_root2.Uid ); | |
262 | BOOST_CHECK_EQUAL( (gid_t)0, user_root2.Gid ); | |
48d97d6c | 263 | |
9fe0853b TJ |
264 | Group group_root("root"); |
265 | BOOST_CHECK_EQUAL( true, group_root.is_valid() ); | |
266 | BOOST_CHECK_EQUAL( true, (bool)group_root ); | |
48d97d6c | 267 | |
9fe0853b TJ |
268 | BOOST_CHECK_EQUAL( std::string("root"), group_root.Name ); |
269 | BOOST_CHECK_EQUAL( (gid_t)0, group_root.Gid ); | |
48d97d6c | 270 | |
9fe0853b | 271 | } // TestUserAndGroupStuff1() |
48d97d6c | 272 | |
9fe0853b TJ |
273 | BOOST_AUTO_TEST_CASE(TestUserAndGroupStuff2) |
274 | { | |
275 | // Test if is_valid() works correctly | |
276 | User user_root; | |
277 | BOOST_CHECK_EQUAL( false, user_root.is_valid() ); | |
48d97d6c | 278 | |
9fe0853b TJ |
279 | Group group_root; |
280 | BOOST_CHECK_EQUAL( false, group_root.is_valid() ); | |
281 | } | |
48d97d6c | 282 | |
9fe0853b TJ |
283 | BOOST_AUTO_TEST_CASE(TestFileModes1) |
284 | { | |
285 | std::string path= get_check_file_path("FileModes1"); | |
48d97d6c | 286 | |
9fe0853b | 287 | write_file(path,"42"); |
48d97d6c | 288 | |
9fe0853b TJ |
289 | Stat stat(path, false); |
290 | BOOST_CHECK_EQUAL( true, stat.is_valid() ); | |
48d97d6c | 291 | |
9fe0853b TJ |
292 | User user( stat.uid() ); |
293 | Group group( stat.gid() ); | |
48d97d6c | 294 | |
9fe0853b TJ |
295 | BOOST_CHECK_EQUAL( true, user.is_valid() ); |
296 | BOOST_CHECK_EQUAL( true, group.is_valid() ); | |
48d97d6c | 297 | |
9fe0853b | 298 | bool res=chown( path, user.Name.c_str(), group.Gid ); |
48d97d6c | 299 | |
9fe0853b TJ |
300 | BOOST_CHECK_EQUAL( true, res ); |
301 | } // eo TestFileModes1() | |
48d97d6c | 302 | |
48d97d6c | 303 | |
48d97d6c | 304 | |
9fe0853b TJ |
305 | BOOST_AUTO_TEST_CASE(TestPidOf1) |
306 | { | |
307 | using I2n::Daemon::pid_of; | |
48d97d6c | 308 | |
9fe0853b | 309 | std::vector< pid_t > pid_list; |
1a2fc4e8 | 310 | |
9fe0853b | 311 | bool res= pid_of("init", pid_list); |
9fe0853b | 312 | BOOST_CHECK_EQUAL( true, res); |
246bcd58 GE |
313 | |
314 | if (pid_list.empty()) | |
315 | { | |
316 | res= pid_of("systemd", pid_list); | |
317 | BOOST_CHECK_EQUAL( true, res); | |
318 | } | |
319 | ||
9fe0853b | 320 | BOOST_CHECK_EQUAL( false, pid_list.empty() ); |
1a2fc4e8 | 321 | |
9fe0853b TJ |
322 | std::vector< pid_t >::const_iterator pos1 = |
323 | std::find( pid_list.begin(), pid_list.end(), 1); | |
48d97d6c | 324 | |
9fe0853b TJ |
325 | BOOST_CHECK( pos1 != pid_list.end() ); |
326 | } // eo TestPidOf1() | |
1a2fc4e8 | 327 | |
9fe0853b TJ |
328 | BOOST_AUTO_TEST_CASE(TestCopyFileSourceFail) |
329 | { | |
330 | bool res = copy_file("does not exist", "destination"); | |
331 | BOOST_CHECK_EQUAL( false, res ); | |
332 | } | |
48d97d6c | 333 | |
9fe0853b TJ |
334 | BOOST_AUTO_TEST_CASE(TestCopyFileDestFail) |
335 | { | |
336 | bool res = copy_file("/etc/HOSTNAME", "/proc/not/writable"); | |
337 | BOOST_CHECK_EQUAL( false, res ); | |
338 | } | |
5de0c58a | 339 | |
9fe0853b TJ |
340 | BOOST_AUTO_TEST_CASE(TestCopyFileOk) |
341 | { | |
342 | string input = "copy_source"; | |
343 | string data = "test"; | |
344 | ||
345 | long input_size = 0; | |
346 | ofstream finput(input.c_str()); | |
347 | if (finput) | |
348 | { | |
349 | finput << data; | |
350 | finput.close(); | |
351 | input_size = file_size(input); | |
352 | } | |
353 | ||
354 | string output = "copy_dest"; | |
355 | long output_size = 0; | |
356 | bool res = copy_file(input, output); | |
357 | if (res) | |
358 | { | |
359 | output_size = file_size(output); | |
360 | } | |
361 | unlink(input); | |
362 | unlink(output); | |
363 | ||
364 | bool size_is_zero = output_size == 0 ? true : false; | |
365 | ||
366 | BOOST_CHECK_EQUAL( true, res ); | |
367 | BOOST_CHECK_EQUAL( input_size, output_size ); | |
368 | BOOST_CHECK_EQUAL( false, size_is_zero ); | |
369 | } | |
370 | ||
faf8475b TJ |
371 | BOOST_AUTO_TEST_CASE(TestMkdtemp) |
372 | { | |
373 | // Create unique directory | |
374 | string unique_dir = I2n::mkdtemp("foobar.XXXXXX"); | |
375 | BOOST_REQUIRE(unique_dir.size() > 0); | |
376 | ||
377 | // Test if it's really a directory | |
378 | BOOST_CHECK_EQUAL(true, Stat(unique_dir).is_directory()); | |
379 | ||
380 | // Unlink it | |
997987a6 TJ |
381 | BOOST_CHECK_EQUAL(true, rmdir(unique_dir)); |
382 | } | |
383 | ||
384 | BOOST_AUTO_TEST_CASE(TestRecursiveDelete) | |
385 | { | |
386 | // Create unique directory | |
387 | string unique_dir = I2n::mkdtemp("foobar.XXXXXX"); | |
388 | BOOST_REQUIRE(unique_dir.size() > 0); | |
389 | ||
390 | // Test if it's really a directory | |
391 | BOOST_CHECK_EQUAL(true, Stat(unique_dir).is_directory()); | |
392 | ||
393 | // Create dirs and files below it | |
394 | const std::string sub_dir = unique_dir + "/" + "some_subdir"; | |
395 | const std::string some_file = sub_dir + "/" + "some_file"; | |
396 | BOOST_CHECK_EQUAL(true, I2n::mkdir(sub_dir)); | |
397 | BOOST_CHECK_EQUAL(true, write_file(some_file, "foobar")); | |
398 | ||
399 | // Unlink it | |
faf8475b | 400 | BOOST_CHECK_EQUAL(true, I2n::recursive_delete(unique_dir)); |
997987a6 TJ |
401 | BOOST_CHECK_EQUAL(false, Stat(unique_dir).is_directory()); |
402 | } | |
403 | ||
404 | BOOST_AUTO_TEST_CASE(TestRecursiveDeleteKeepParentDir) | |
405 | { | |
406 | // Create unique directory | |
407 | string unique_dir = I2n::mkdtemp("foobar.XXXXXX"); | |
408 | BOOST_REQUIRE(unique_dir.size() > 0); | |
409 | ||
410 | // Test if it's really a directory | |
411 | BOOST_CHECK_EQUAL(true, Stat(unique_dir).is_directory()); | |
412 | ||
413 | // Create dirs and files below it | |
414 | const std::string sub_dir = unique_dir + "/" + "some_subdir"; | |
415 | const std::string some_file = sub_dir + "/" + "some_file"; | |
416 | const std::string other_file = unique_dir + "/" + "other_file"; | |
417 | ||
418 | BOOST_CHECK_EQUAL(true, I2n::mkdir(sub_dir)); | |
419 | BOOST_CHECK_EQUAL(true, write_file(some_file, "foobar")); | |
420 | BOOST_CHECK_EQUAL(true, write_file(other_file, "foobar")); | |
421 | ||
422 | // Unlink it | |
423 | BOOST_CHECK_EQUAL(true, I2n::recursive_delete(unique_dir, true)); | |
424 | ||
425 | // check result | |
426 | BOOST_CHECK_EQUAL(true, Stat(unique_dir).is_directory()); | |
427 | BOOST_CHECK_EQUAL(false, Stat(sub_dir).is_directory()); | |
428 | BOOST_CHECK_EQUAL(false, Stat(other_file).is_regular_file()); | |
429 | ||
430 | BOOST_CHECK_EQUAL(true, I2n::rmdir(unique_dir)); | |
faf8475b TJ |
431 | } |
432 | ||
a50de522 GE |
433 | BOOST_AUTO_TEST_CASE(TestRecursiveDeleteSymlinkedDirs1) |
434 | { | |
435 | // Create unique directory | |
436 | string unique_dir = I2n::mkdtemp("foobar.XXXXXX"); | |
437 | BOOST_REQUIRE(unique_dir.size() > 0); | |
438 | ||
439 | // Test if it's really a directory | |
440 | BOOST_CHECK_EQUAL(true, Stat(unique_dir).is_directory()); | |
441 | ||
442 | // Create dirs and files below it | |
443 | const std::string sub_dir = unique_dir + "/" + "some_subdir"; | |
444 | const std::string some_file = sub_dir + "/" + "some_file"; | |
445 | const std::string dir_symlink_within_unique_dir = unique_dir + "/" + "dir_symlink_within_unique_dir"; | |
446 | BOOST_CHECK_EQUAL(true, I2n::mkdir(sub_dir)); | |
447 | BOOST_CHECK_EQUAL(true, write_file(some_file, "foobar")); | |
448 | BOOST_CHECK_EQUAL(true, symlink(sub_dir, dir_symlink_within_unique_dir)); | |
449 | ||
450 | // Unlink it | |
451 | BOOST_CHECK_EQUAL(true, I2n::recursive_delete(unique_dir)); | |
452 | BOOST_CHECK_EQUAL(false, Stat(unique_dir).is_directory()); | |
453 | } | |
454 | ||
455 | BOOST_AUTO_TEST_CASE(TestRecursiveDeleteSymlinkedDirs2) | |
456 | { | |
457 | // Create unique directory | |
458 | string unique_dir = I2n::mkdtemp("foobar.XXXXXX"); | |
459 | BOOST_REQUIRE(unique_dir.size() > 0); | |
460 | ||
461 | // Test if it's really a directory | |
462 | BOOST_CHECK_EQUAL(true, Stat(unique_dir).is_directory()); | |
463 | ||
464 | // Create another unique directory | |
465 | string other_unique_dir = I2n::mkdtemp("foobar_other.XXXXXX"); | |
466 | BOOST_REQUIRE(other_unique_dir.size() > 0); | |
467 | ||
468 | // Test if it's really a directory | |
469 | BOOST_CHECK_EQUAL(true, Stat(other_unique_dir).is_directory()); | |
470 | ||
471 | const std::string other_file = other_unique_dir + "/" + "other_file"; | |
472 | BOOST_CHECK_EQUAL(true, write_file(other_file, "foobar")); | |
473 | ||
474 | // Create dirs and files below it | |
475 | const std::string sub_dir = unique_dir + "/" + "some_subdir"; | |
476 | const std::string some_file = sub_dir + "/" + "some_file"; | |
477 | const std::string dir_symlink_to_outside_unique_dir = unique_dir + "/" + "dir_symlink_to_outside_unique_dir"; | |
478 | BOOST_CHECK_EQUAL(true, I2n::mkdir(sub_dir)); | |
479 | BOOST_CHECK_EQUAL(true, write_file(some_file, "foobar")); | |
480 | BOOST_CHECK_EQUAL(true, symlink(other_unique_dir, dir_symlink_to_outside_unique_dir)); | |
481 | ||
482 | // Unlink it | |
483 | BOOST_CHECK_EQUAL(true, I2n::recursive_delete(unique_dir)); | |
484 | BOOST_CHECK_EQUAL(false, Stat(unique_dir).is_directory()); | |
485 | ||
486 | // other unique dir must still be there | |
487 | BOOST_CHECK_EQUAL(true, Stat(other_unique_dir).is_directory()); | |
488 | BOOST_CHECK_EQUAL(true, Stat(other_file).is_regular_file()); | |
489 | ||
490 | // finally delete the other unique dir | |
491 | BOOST_CHECK_EQUAL(true, I2n::recursive_delete(other_unique_dir)); | |
492 | BOOST_CHECK_EQUAL(false, Stat(other_unique_dir).is_directory()); | |
493 | } | |
494 | ||
faf8475b TJ |
495 | BOOST_AUTO_TEST_CASE(TestMkdtempBrokenTemplate) |
496 | { | |
497 | // Broken directory template -> fail | |
498 | string unique_dir = I2n::mkdtemp("foobar.XXX"); | |
499 | BOOST_CHECK_EQUAL("", unique_dir); | |
500 | } | |
501 | ||
44725532 TJ |
502 | BOOST_AUTO_TEST_CASE(DirectoryCreation) |
503 | { | |
504 | string dirname = "test_directory"; | |
505 | ||
506 | I2n::rmdir (dirname); | |
507 | ||
508 | BOOST_CHECK_EQUAL(true, I2n::mkdir(dirname)); | |
509 | BOOST_CHECK_EQUAL(true, Stat(dirname).is_directory()); | |
510 | // Verify default permissions | |
511 | BOOST_CHECK_EQUAL(0700, Stat(dirname).mode()); | |
512 | ||
513 | BOOST_CHECK_EQUAL(true, I2n::rmdir(dirname)); | |
514 | ||
515 | // Second call must fail: Directory already deleted | |
516 | BOOST_CHECK_EQUAL(false, I2n::rmdir(dirname)); | |
517 | } | |
518 | ||
519 | BOOST_AUTO_TEST_CASE(DirectoryCreatePermission) | |
520 | { | |
521 | string dirname = "test_directory"; | |
522 | ||
901e2943 TJ |
523 | // Save and fix umask |
524 | mode_t previous_mask = I2n::umask(0); | |
44725532 TJ |
525 | |
526 | I2n::rmdir (dirname); | |
527 | BOOST_CHECK_EQUAL(true, I2n::mkdir(dirname, 0770)); | |
901e2943 | 528 | BOOST_CHECK_EQUAL(0770, Stat(dirname).mode()); |
44725532 TJ |
529 | I2n::rmdir (dirname); |
530 | ||
901e2943 TJ |
531 | // Restore umask |
532 | I2n::umask(previous_mask); | |
44725532 TJ |
533 | } |
534 | ||
535 | BOOST_AUTO_TEST_CASE(ChangeDirectory) | |
536 | { | |
537 | string current_directory = I2n::getcwd(); | |
538 | BOOST_REQUIRE(!current_directory.empty()); | |
539 | ||
540 | BOOST_CHECK_EQUAL(true, I2n::chdir("/")); | |
541 | BOOST_CHECK_EQUAL("/", I2n::getcwd()); | |
542 | ||
543 | BOOST_CHECK_EQUAL(true, I2n::chdir(current_directory)); | |
544 | BOOST_REQUIRE_EQUAL(current_directory, I2n::getcwd()); | |
545 | } | |
546 | ||
c5935370 TJ |
547 | BOOST_AUTO_TEST_CASE(WriteFileEmptyData) |
548 | { | |
549 | // just to be sure | |
550 | unlink(".foobar"); | |
551 | ||
552 | I2n::Stat stat(".foobar"); | |
553 | BOOST_CHECK_EQUAL( false, (bool)stat ); | |
554 | ||
555 | // Call write_file() with empty data. Should still create the file. | |
556 | write_file(".foobar",""); | |
557 | ||
558 | stat.recheck(); | |
559 | ||
560 | BOOST_CHECK_EQUAL( true, (bool)stat ); | |
561 | BOOST_CHECK_EQUAL( true, stat.size() == 0 ); | |
562 | ||
563 | unlink(".foobar"); | |
564 | } | |
565 | ||
9d1eb8c8 TJ |
566 | BOOST_AUTO_TEST_CASE(FileContentDiffersIsIdentical) |
567 | { | |
568 | BOOST_CHECK_EQUAL( false, file_content_differs("/etc/passwd", "/etc/passwd") ); | |
569 | } | |
570 | ||
571 | BOOST_AUTO_TEST_CASE(FileContentDiffersNonExistent) | |
572 | { | |
573 | BOOST_CHECK_EQUAL( true, file_content_differs("/etc/passwd", "abc") ); | |
574 | BOOST_CHECK_EQUAL( true, file_content_differs("abc", "/etc/passwd") ); | |
575 | } | |
576 | ||
577 | BOOST_AUTO_TEST_CASE(FileContentDiffersEqualSize) | |
578 | { | |
579 | const string name1 = "file1", name2 = "file2"; | |
580 | { | |
581 | ofstream out1(name1.c_str()); | |
582 | out1 << "abc"; | |
583 | ||
584 | ofstream out2(name2.c_str()); | |
585 | out2 << "xyz"; | |
586 | } | |
587 | ||
588 | bool res = file_content_differs(name1, name2); | |
589 | unlink(name1); | |
590 | unlink(name2); | |
591 | ||
592 | BOOST_CHECK_EQUAL( true, res ); | |
593 | } | |
594 | ||
34ed5e5e GE |
595 | BOOST_AUTO_TEST_CASE(FreeDiskSpace1) |
596 | { | |
b9dfab8b GE |
597 | long long dfout; |
598 | long long get_free_diskspace_tmp; | |
34ed5e5e | 599 | |
b9dfab8b GE |
600 | // we need a partition to do this test. we can't create our own because that would require root |
601 | // so we use /tmp and retry it a few times in case of an error | |
602 | int retries = 5; | |
603 | while (retries > 0) | |
604 | { | |
99e07fab | 605 | string dfstr=capture_exec("df -P -B 1 /tmp | tail -n 1 | sed \"s/ \\+/\\\\n/g\" | sed -n 4,4p"); |
b9dfab8b GE |
606 | |
607 | dfout=-1; | |
608 | string_to<long long>(dfstr,dfout); | |
609 | ||
610 | get_free_diskspace_tmp=get_free_diskspace("/tmp"); | |
611 | ||
612 | if ( dfout == get_free_diskspace_tmp ) | |
613 | break; | |
614 | ||
615 | retries--; | |
616 | } | |
34ed5e5e | 617 | |
b9dfab8b GE |
618 | // do the check again with BOOST_CHECK_EQUAL to show it in the unit test output |
619 | BOOST_CHECK_EQUAL( dfout, get_free_diskspace_tmp ); | |
34ed5e5e GE |
620 | } |
621 | ||
622 | BOOST_AUTO_TEST_CASE(FreeDiskSpace2) | |
623 | { | |
624 | BOOST_CHECK_EQUAL( -1, get_free_diskspace("/this/path/is/really/bogus") ); | |
625 | } | |
626 | ||
fcadd7ba GE |
627 | BOOST_AUTO_TEST_CASE(TestDu) |
628 | { | |
629 | // Create unique directory | |
630 | string unique_dir = I2n::mkdtemp("foobar.XXXXXX"); | |
631 | BOOST_REQUIRE(unique_dir.size() > 0); | |
632 | ||
633 | // Test if it's really a directory | |
634 | BOOST_CHECK_EQUAL(true, Stat(unique_dir).is_directory()); | |
635 | ||
636 | // Create dirs and files below it | |
637 | const std::string sub_dir = unique_dir + "/" + "some_subdir"; | |
638 | const std::string some_file = sub_dir + "/" + "some_file"; | |
639 | BOOST_CHECK_EQUAL(true, I2n::mkdir(sub_dir)); | |
640 | BOOST_CHECK_EQUAL(true, write_file(some_file, "foobar and some more data, even more that Tom would like to see in one line without linebreak but I still want to have it all here")); | |
641 | ||
f8f119bf | 642 | string dustr=capture_exec(string("du --block-size=1 --sum ")+unique_dir+" | cut -f 1"); |
05b4f5e8 GE |
643 | long long duout=-1; |
644 | string_to<long long>(dustr,duout); | |
fcadd7ba | 645 | |
74311678 GE |
646 | long long first_du=du(unique_dir); |
647 | ||
648 | BOOST_CHECK_EQUAL( duout, first_du ); | |
649 | ||
650 | // create hardlinks | |
651 | string cmd; | |
652 | cmd=string("ln ")+some_file+" hardlink1"; | |
653 | system(cmd.c_str()); | |
654 | ||
655 | cmd=string("ln ")+some_file+" hardlink2"; | |
656 | system(cmd.c_str()); | |
657 | ||
658 | cmd=string("ln ")+some_file+" hardlink3"; | |
659 | system(cmd.c_str()); | |
660 | ||
661 | long long du_with_hardlinks=du(unique_dir); | |
662 | ||
663 | BOOST_CHECK_EQUAL( first_du , du_with_hardlinks ); | |
fcadd7ba GE |
664 | |
665 | // Unlink it | |
666 | BOOST_CHECK_EQUAL(true, I2n::recursive_delete(unique_dir)); | |
667 | BOOST_CHECK_EQUAL(false, Stat(unique_dir).is_directory()); | |
99e07fab CH |
668 | |
669 | // remove links | |
670 | unlink("hardlink1"); | |
671 | unlink("hardlink2"); | |
672 | unlink("hardlink3"); | |
fcadd7ba GE |
673 | } |
674 | ||
675 | ||
676 | ||
9fe0853b | 677 | BOOST_AUTO_TEST_SUITE_END() |