2 The software in this package is distributed under the GNU General
3 Public License version 2 (with a special exception described below).
5 A copy of GNU General Public License (GPL) is included in this distribution,
6 in the file COPYING.GPL.
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.
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.
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.
22 * tests for the modules "filefunc", "daemonfunc"
24 * (c) Copyright 2007-2008 by Intra2net AG
39 #define BOOST_TEST_DYN_LINK
40 #include <boost/test/unit_test.hpp>
42 #include <filefunc.hxx>
43 #include <daemonfunc.hpp>
44 #include <pipestream.hxx>
45 #include <stringfunc.hxx>
48 #define DOUT(msg) std::cout << msg << std::endl
50 #define DOUT(msg) do {} while (0)
56 class TestFileFuncFixture
59 typedef std::list< std::string > StringList;
60 std::set<std::string> used_check_files;
62 std::string get_check_file_path(std::string tag)
65 result= "__unittest__" + tag + ".dat";
66 used_check_files.insert(result);
68 } // eo get_check_file_path
70 void remove_check_files()
72 for (std::set<std::string>::iterator it= used_check_files.begin();
73 it != used_check_files.end();
76 std::string filepath(*it);
77 if (path_exists(filepath))
83 used_check_files.clear();
84 } // eo remove_check_files
91 ~TestFileFuncFixture()
97 BOOST_FIXTURE_TEST_SUITE(TestFileFunc, TestFileFuncFixture)
99 BOOST_AUTO_TEST_CASE(StatTest1)
101 I2n::Stat stat("Makefile");
103 BOOST_CHECK_EQUAL( true, (bool)stat );
104 BOOST_CHECK_EQUAL( true, stat.is_regular_file() );
105 BOOST_CHECK_EQUAL( false, stat.is_directory() );
107 stat= Stat("/dev/null");
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() );
117 BOOST_AUTO_TEST_CASE(StatSize)
119 write_file("/tmp/test","some nice content to make sure the file system optimizations don't inline this into the inode block");
121 I2n::Stat stat("/tmp/test");
123 BOOST_CHECK_EQUAL( true, (bool)stat );
124 BOOST_CHECK_EQUAL( true, stat.is_regular_file() );
126 BOOST_CHECK_EQUAL( true, ( stat.bytes_on_disk() >= 512 ) );
131 BOOST_AUTO_TEST_CASE(StatRecheck)
136 I2n::Stat stat(".foobar");
137 BOOST_CHECK_EQUAL( false, (bool)stat );
139 write_file(".foobar","hello world");
143 BOOST_CHECK_EQUAL( true, (bool)stat );
144 BOOST_CHECK_EQUAL( true, stat.size() > 0 );
149 BOOST_AUTO_TEST_CASE(DirTest1)
151 typedef std::vector< std::string > StringVector;
154 bool res= I2n::get_dir(".",names);
156 BOOST_CHECK_EQUAL( true, res );
157 BOOST_CHECK( ! names.empty() );
159 StringVector::iterator it = std::find( names.begin(), names.end(), "Makefile");
160 BOOST_CHECK( it != names.end() );
162 it = std::find( names.begin(), names.end(), "." );
163 BOOST_CHECK( it == names.end() );
165 names= get_dir(".",true);
166 BOOST_CHECK( ! names.empty() );
168 for (it= names.begin(); it!=names.end(); ++it)
170 DOUT(" \"" << *it << "\"");
171 BOOST_CHECK_EQUAL( false, it->empty() );
174 it = std::find( names.begin(), names.end(), "." );
175 BOOST_CHECK( it != names.end() );
180 BOOST_AUTO_TEST_CASE(PathCuts1)
182 std::string path1("/an/absolute/path");
184 BOOST_CHECK_EQUAL( std::string("/an/absolute"), dirname(path1) );
185 BOOST_CHECK_EQUAL( std::string("path"), basename(path1) );
187 std::string path2("just.a.name");
188 BOOST_CHECK_EQUAL( std::string("just.a.name"), basename(path2) );
189 BOOST_CHECK_EQUAL( std::string("."), dirname(path2) );
194 BOOST_AUTO_TEST_CASE(NormalizePath1)
198 path= normalize_path("/a/simple/path/");
199 BOOST_CHECK_EQUAL( std::string("/a/simple/path"), path );
201 path= normalize_path("//another///simple/.//path//");
202 BOOST_CHECK_EQUAL( std::string("/another/simple/path"), path );
204 path= normalize_path("//..//..//a/dummy///../././simple/././/path//");
205 BOOST_CHECK_EQUAL( std::string("/a/simple/path"), path );
207 path= normalize_path("../a/dummy//././..//simple//nice//absolute//.././..//relative/path//");
208 BOOST_CHECK_EQUAL( std::string("../a/simple/relative/path"), path );
210 path= normalize_path("../../a/dummy//././..//simple/../nice//absolute//../.x/..//relative/path//");
211 BOOST_CHECK_EQUAL( std::string("../../a/nice/relative/path"), path );
213 } // eo NormalizePath1
215 BOOST_AUTO_TEST_CASE(NormalizePath2)
219 path= normalize_path("/");
220 BOOST_CHECK_EQUAL( std::string("/"), path );
222 path= normalize_path("//");
223 BOOST_CHECK_EQUAL( std::string("/"), path );
225 path= normalize_path("/.//");
226 BOOST_CHECK_EQUAL( std::string("/"), path );
228 path= normalize_path(".");
229 BOOST_CHECK_EQUAL( std::string(""), path );
231 path= normalize_path("./");
232 BOOST_CHECK_EQUAL( std::string(""), path );
234 path= normalize_path(".///");
235 BOOST_CHECK_EQUAL( std::string(""), path );
237 path= normalize_path("/./data/files");
238 BOOST_CHECK_EQUAL( std::string("/data/files"), path );
240 path= normalize_path("./data/files/");
241 BOOST_CHECK_EQUAL( std::string("data/files"), path );
242 } // eo NormalizePath2
244 BOOST_AUTO_TEST_CASE(TestUserAndGroupStuff1)
246 User user_root((uid_t)0);
247 BOOST_CHECK_EQUAL( true, user_root.is_valid() );
248 BOOST_CHECK_EQUAL( true, (bool)user_root );
250 BOOST_CHECK_EQUAL( std::string("root"), user_root.Name );
251 BOOST_CHECK_EQUAL( (uid_t)0, user_root.Uid );
252 BOOST_CHECK_EQUAL( (gid_t)0, user_root.Gid );
254 User user_root2("root");
255 BOOST_CHECK_EQUAL( true, user_root2.is_valid() );
256 BOOST_CHECK_EQUAL( true, (bool)user_root2 );
258 BOOST_CHECK_EQUAL( std::string("root"), user_root2.Name );
259 BOOST_CHECK_EQUAL( (uid_t)0, user_root2.Uid );
260 BOOST_CHECK_EQUAL( (gid_t)0, user_root2.Gid );
262 Group group_root("root");
263 BOOST_CHECK_EQUAL( true, group_root.is_valid() );
264 BOOST_CHECK_EQUAL( true, (bool)group_root );
266 BOOST_CHECK_EQUAL( std::string("root"), group_root.Name );
267 BOOST_CHECK_EQUAL( (gid_t)0, group_root.Gid );
269 } // TestUserAndGroupStuff1()
271 BOOST_AUTO_TEST_CASE(TestUserAndGroupStuff2)
273 // Test if is_valid() works correctly
275 BOOST_CHECK_EQUAL( false, user_root.is_valid() );
278 BOOST_CHECK_EQUAL( false, group_root.is_valid() );
281 BOOST_AUTO_TEST_CASE(TestFileModes1)
283 std::string path= get_check_file_path("FileModes1");
285 write_file(path,"42");
287 Stat stat(path, false);
288 BOOST_CHECK_EQUAL( true, stat.is_valid() );
290 User user( stat.uid() );
291 Group group( stat.gid() );
293 BOOST_CHECK_EQUAL( true, user.is_valid() );
294 BOOST_CHECK_EQUAL( true, group.is_valid() );
296 bool res=chown( path, user.Name.c_str(), group.Gid );
298 BOOST_CHECK_EQUAL( true, res );
299 } // eo TestFileModes1()
303 BOOST_AUTO_TEST_CASE(TestPidOf1)
305 using I2n::Daemon::pid_of;
307 std::vector< pid_t > pid_list;
309 bool res= pid_of("init", pid_list);
310 BOOST_CHECK_EQUAL( true, res);
312 if (pid_list.empty())
314 res= pid_of("systemd", pid_list);
315 BOOST_CHECK_EQUAL( true, res);
318 BOOST_CHECK_EQUAL( false, pid_list.empty() );
320 std::vector< pid_t >::const_iterator pos1 =
321 std::find( pid_list.begin(), pid_list.end(), 1);
323 BOOST_CHECK( pos1 != pid_list.end() );
326 BOOST_AUTO_TEST_CASE(TestCopyFileSourceFail)
328 bool res = copy_file("does not exist", "destination");
329 BOOST_CHECK_EQUAL( false, res );
332 BOOST_AUTO_TEST_CASE(TestCopyFileDestFail)
334 bool res = copy_file("/etc/HOSTNAME", "/proc/not/writable");
335 BOOST_CHECK_EQUAL( false, res );
338 BOOST_AUTO_TEST_CASE(TestCopyFileOk)
340 string input = "copy_source";
341 string data = "test";
344 ofstream finput(input.c_str());
349 input_size = file_size(input);
352 string output = "copy_dest";
353 long output_size = 0;
354 bool res = copy_file(input, output);
357 output_size = file_size(output);
362 bool size_is_zero = output_size == 0 ? true : false;
364 BOOST_CHECK_EQUAL( true, res );
365 BOOST_CHECK_EQUAL( input_size, output_size );
366 BOOST_CHECK_EQUAL( false, size_is_zero );
369 BOOST_AUTO_TEST_CASE(TestMkdtemp)
371 // Create unique directory
372 string unique_dir = I2n::mkdtemp("foobar.XXXXXX");
373 BOOST_REQUIRE(unique_dir.size() > 0);
375 // Test if it's really a directory
376 BOOST_CHECK_EQUAL(true, Stat(unique_dir).is_directory());
379 BOOST_CHECK_EQUAL(true, rmdir(unique_dir));
382 BOOST_AUTO_TEST_CASE(TestRecursiveDelete)
384 // Create unique directory
385 string unique_dir = I2n::mkdtemp("foobar.XXXXXX");
386 BOOST_REQUIRE(unique_dir.size() > 0);
388 // Test if it's really a directory
389 BOOST_CHECK_EQUAL(true, Stat(unique_dir).is_directory());
391 // Create dirs and files below it
392 const std::string sub_dir = unique_dir + "/" + "some_subdir";
393 const std::string some_file = sub_dir + "/" + "some_file";
394 BOOST_CHECK_EQUAL(true, I2n::mkdir(sub_dir));
395 BOOST_CHECK_EQUAL(true, write_file(some_file, "foobar"));
398 BOOST_CHECK_EQUAL(true, I2n::recursive_delete(unique_dir));
399 BOOST_CHECK_EQUAL(false, Stat(unique_dir).is_directory());
402 BOOST_AUTO_TEST_CASE(TestRecursiveDeleteKeepParentDir)
404 // Create unique directory
405 string unique_dir = I2n::mkdtemp("foobar.XXXXXX");
406 BOOST_REQUIRE(unique_dir.size() > 0);
408 // Test if it's really a directory
409 BOOST_CHECK_EQUAL(true, Stat(unique_dir).is_directory());
411 // Create dirs and files below it
412 const std::string sub_dir = unique_dir + "/" + "some_subdir";
413 const std::string some_file = sub_dir + "/" + "some_file";
414 const std::string other_file = unique_dir + "/" + "other_file";
416 BOOST_CHECK_EQUAL(true, I2n::mkdir(sub_dir));
417 BOOST_CHECK_EQUAL(true, write_file(some_file, "foobar"));
418 BOOST_CHECK_EQUAL(true, write_file(other_file, "foobar"));
421 BOOST_CHECK_EQUAL(true, I2n::recursive_delete(unique_dir, true));
424 BOOST_CHECK_EQUAL(true, Stat(unique_dir).is_directory());
425 BOOST_CHECK_EQUAL(false, Stat(sub_dir).is_directory());
426 BOOST_CHECK_EQUAL(false, Stat(other_file).is_regular_file());
428 BOOST_CHECK_EQUAL(true, I2n::rmdir(unique_dir));
431 BOOST_AUTO_TEST_CASE(TestMkdtempBrokenTemplate)
433 // Broken directory template -> fail
434 string unique_dir = I2n::mkdtemp("foobar.XXX");
435 BOOST_CHECK_EQUAL("", unique_dir);
438 BOOST_AUTO_TEST_CASE(DirectoryCreation)
440 string dirname = "test_directory";
442 I2n::rmdir (dirname);
444 BOOST_CHECK_EQUAL(true, I2n::mkdir(dirname));
445 BOOST_CHECK_EQUAL(true, Stat(dirname).is_directory());
446 // Verify default permissions
447 BOOST_CHECK_EQUAL(0700, Stat(dirname).mode());
449 BOOST_CHECK_EQUAL(true, I2n::rmdir(dirname));
451 // Second call must fail: Directory already deleted
452 BOOST_CHECK_EQUAL(false, I2n::rmdir(dirname));
455 BOOST_AUTO_TEST_CASE(DirectoryCreatePermission)
457 string dirname = "test_directory";
459 // Save and fix umask
460 mode_t previous_mask = I2n::umask(0);
462 I2n::rmdir (dirname);
463 BOOST_CHECK_EQUAL(true, I2n::mkdir(dirname, 0770));
464 BOOST_CHECK_EQUAL(0770, Stat(dirname).mode());
465 I2n::rmdir (dirname);
468 I2n::umask(previous_mask);
471 BOOST_AUTO_TEST_CASE(ChangeDirectory)
473 string current_directory = I2n::getcwd();
474 BOOST_REQUIRE(!current_directory.empty());
476 BOOST_CHECK_EQUAL(true, I2n::chdir("/"));
477 BOOST_CHECK_EQUAL("/", I2n::getcwd());
479 BOOST_CHECK_EQUAL(true, I2n::chdir(current_directory));
480 BOOST_REQUIRE_EQUAL(current_directory, I2n::getcwd());
483 BOOST_AUTO_TEST_CASE(WriteFileEmptyData)
488 I2n::Stat stat(".foobar");
489 BOOST_CHECK_EQUAL( false, (bool)stat );
491 // Call write_file() with empty data. Should still create the file.
492 write_file(".foobar","");
496 BOOST_CHECK_EQUAL( true, (bool)stat );
497 BOOST_CHECK_EQUAL( true, stat.size() == 0 );
502 BOOST_AUTO_TEST_CASE(FileContentDiffersIsIdentical)
504 BOOST_CHECK_EQUAL( false, file_content_differs("/etc/passwd", "/etc/passwd") );
507 BOOST_AUTO_TEST_CASE(FileContentDiffersNonExistent)
509 BOOST_CHECK_EQUAL( true, file_content_differs("/etc/passwd", "abc") );
510 BOOST_CHECK_EQUAL( true, file_content_differs("abc", "/etc/passwd") );
513 BOOST_AUTO_TEST_CASE(FileContentDiffersEqualSize)
515 const string name1 = "file1", name2 = "file2";
517 ofstream out1(name1.c_str());
520 ofstream out2(name2.c_str());
524 bool res = file_content_differs(name1, name2);
528 BOOST_CHECK_EQUAL( true, res );
531 BOOST_AUTO_TEST_CASE(FreeDiskSpace1)
533 inpipestream cmd_df("df -B 1 --output=avail /tmp | tail -n 1");
536 getline(cmd_df, dfstr);
539 string_to<long long>(dfstr,dfout);
541 BOOST_CHECK_EQUAL( dfout, get_free_diskspace("/tmp") );
544 BOOST_AUTO_TEST_CASE(FreeDiskSpace2)
546 BOOST_CHECK_EQUAL( -1, get_free_diskspace("/this/path/is/really/bogus") );
549 BOOST_AUTO_TEST_SUITE_END()