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(StatRecheck)
122 I2n::Stat stat(".foobar");
123 BOOST_CHECK_EQUAL( false, (bool)stat );
125 write_file(".foobar","hello world");
129 BOOST_CHECK_EQUAL( true, (bool)stat );
130 BOOST_CHECK_EQUAL( true, stat.size() > 0 );
135 BOOST_AUTO_TEST_CASE(DirTest1)
137 typedef std::vector< std::string > StringVector;
140 bool res= I2n::get_dir(".",names);
142 BOOST_CHECK_EQUAL( true, res );
143 BOOST_CHECK( ! names.empty() );
145 StringVector::iterator it = std::find( names.begin(), names.end(), "Makefile");
146 BOOST_CHECK( it != names.end() );
148 it = std::find( names.begin(), names.end(), "." );
149 BOOST_CHECK( it == names.end() );
151 names= get_dir(".",true);
152 BOOST_CHECK( ! names.empty() );
154 for (it= names.begin(); it!=names.end(); ++it)
156 DOUT(" \"" << *it << "\"");
157 BOOST_CHECK_EQUAL( false, it->empty() );
160 it = std::find( names.begin(), names.end(), "." );
161 BOOST_CHECK( it != names.end() );
166 BOOST_AUTO_TEST_CASE(PathCuts1)
168 std::string path1("/an/absolute/path");
170 BOOST_CHECK_EQUAL( std::string("/an/absolute"), dirname(path1) );
171 BOOST_CHECK_EQUAL( std::string("path"), basename(path1) );
173 std::string path2("just.a.name");
174 BOOST_CHECK_EQUAL( std::string("just.a.name"), basename(path2) );
175 BOOST_CHECK_EQUAL( std::string("."), dirname(path2) );
180 BOOST_AUTO_TEST_CASE(NormalizePath1)
184 path= normalize_path("/a/simple/path/");
185 BOOST_CHECK_EQUAL( std::string("/a/simple/path"), path );
187 path= normalize_path("//another///simple/.//path//");
188 BOOST_CHECK_EQUAL( std::string("/another/simple/path"), path );
190 path= normalize_path("//..//..//a/dummy///../././simple/././/path//");
191 BOOST_CHECK_EQUAL( std::string("/a/simple/path"), path );
193 path= normalize_path("../a/dummy//././..//simple//nice//absolute//.././..//relative/path//");
194 BOOST_CHECK_EQUAL( std::string("../a/simple/relative/path"), path );
196 path= normalize_path("../../a/dummy//././..//simple/../nice//absolute//../.x/..//relative/path//");
197 BOOST_CHECK_EQUAL( std::string("../../a/nice/relative/path"), path );
199 } // eo NormalizePath1
201 BOOST_AUTO_TEST_CASE(NormalizePath2)
205 path= normalize_path("/");
206 BOOST_CHECK_EQUAL( std::string("/"), path );
208 path= normalize_path("//");
209 BOOST_CHECK_EQUAL( std::string("/"), path );
211 path= normalize_path("/.//");
212 BOOST_CHECK_EQUAL( std::string("/"), path );
214 path= normalize_path(".");
215 BOOST_CHECK_EQUAL( std::string(""), path );
217 path= normalize_path("./");
218 BOOST_CHECK_EQUAL( std::string(""), path );
220 path= normalize_path(".///");
221 BOOST_CHECK_EQUAL( std::string(""), path );
223 path= normalize_path("/./data/files");
224 BOOST_CHECK_EQUAL( std::string("/data/files"), path );
226 path= normalize_path("./data/files/");
227 BOOST_CHECK_EQUAL( std::string("data/files"), path );
228 } // eo NormalizePath2
230 BOOST_AUTO_TEST_CASE(TestUserAndGroupStuff1)
232 User user_root((uid_t)0);
233 BOOST_CHECK_EQUAL( true, user_root.is_valid() );
234 BOOST_CHECK_EQUAL( true, (bool)user_root );
236 BOOST_CHECK_EQUAL( std::string("root"), user_root.Name );
237 BOOST_CHECK_EQUAL( (uid_t)0, user_root.Uid );
238 BOOST_CHECK_EQUAL( (gid_t)0, user_root.Gid );
240 User user_root2("root");
241 BOOST_CHECK_EQUAL( true, user_root2.is_valid() );
242 BOOST_CHECK_EQUAL( true, (bool)user_root2 );
244 BOOST_CHECK_EQUAL( std::string("root"), user_root2.Name );
245 BOOST_CHECK_EQUAL( (uid_t)0, user_root2.Uid );
246 BOOST_CHECK_EQUAL( (gid_t)0, user_root2.Gid );
248 Group group_root("root");
249 BOOST_CHECK_EQUAL( true, group_root.is_valid() );
250 BOOST_CHECK_EQUAL( true, (bool)group_root );
252 BOOST_CHECK_EQUAL( std::string("root"), group_root.Name );
253 BOOST_CHECK_EQUAL( (gid_t)0, group_root.Gid );
255 } // TestUserAndGroupStuff1()
257 BOOST_AUTO_TEST_CASE(TestUserAndGroupStuff2)
259 // Test if is_valid() works correctly
261 BOOST_CHECK_EQUAL( false, user_root.is_valid() );
264 BOOST_CHECK_EQUAL( false, group_root.is_valid() );
267 BOOST_AUTO_TEST_CASE(TestFileModes1)
269 std::string path= get_check_file_path("FileModes1");
271 write_file(path,"42");
273 Stat stat(path, false);
274 BOOST_CHECK_EQUAL( true, stat.is_valid() );
276 User user( stat.uid() );
277 Group group( stat.gid() );
279 BOOST_CHECK_EQUAL( true, user.is_valid() );
280 BOOST_CHECK_EQUAL( true, group.is_valid() );
282 bool res=chown( path, user.Name.c_str(), group.Gid );
284 BOOST_CHECK_EQUAL( true, res );
285 } // eo TestFileModes1()
289 BOOST_AUTO_TEST_CASE(TestPidOf1)
291 using I2n::Daemon::pid_of;
293 std::vector< pid_t > pid_list;
295 bool res= pid_of("init", pid_list);
296 BOOST_CHECK_EQUAL( true, res);
298 if (pid_list.empty())
300 res= pid_of("systemd", pid_list);
301 BOOST_CHECK_EQUAL( true, res);
304 BOOST_CHECK_EQUAL( false, pid_list.empty() );
306 std::vector< pid_t >::const_iterator pos1 =
307 std::find( pid_list.begin(), pid_list.end(), 1);
309 BOOST_CHECK( pos1 != pid_list.end() );
312 BOOST_AUTO_TEST_CASE(TestCopyFileSourceFail)
314 bool res = copy_file("does not exist", "destination");
315 BOOST_CHECK_EQUAL( false, res );
318 BOOST_AUTO_TEST_CASE(TestCopyFileDestFail)
320 bool res = copy_file("/etc/HOSTNAME", "/proc/not/writable");
321 BOOST_CHECK_EQUAL( false, res );
324 BOOST_AUTO_TEST_CASE(TestCopyFileOk)
326 string input = "copy_source";
327 string data = "test";
330 ofstream finput(input.c_str());
335 input_size = file_size(input);
338 string output = "copy_dest";
339 long output_size = 0;
340 bool res = copy_file(input, output);
343 output_size = file_size(output);
348 bool size_is_zero = output_size == 0 ? true : false;
350 BOOST_CHECK_EQUAL( true, res );
351 BOOST_CHECK_EQUAL( input_size, output_size );
352 BOOST_CHECK_EQUAL( false, size_is_zero );
355 BOOST_AUTO_TEST_CASE(TestMkdtemp)
357 // Create unique directory
358 string unique_dir = I2n::mkdtemp("foobar.XXXXXX");
359 BOOST_REQUIRE(unique_dir.size() > 0);
361 // Test if it's really a directory
362 BOOST_CHECK_EQUAL(true, Stat(unique_dir).is_directory());
365 BOOST_CHECK_EQUAL(true, rmdir(unique_dir));
368 BOOST_AUTO_TEST_CASE(TestRecursiveDelete)
370 // Create unique directory
371 string unique_dir = I2n::mkdtemp("foobar.XXXXXX");
372 BOOST_REQUIRE(unique_dir.size() > 0);
374 // Test if it's really a directory
375 BOOST_CHECK_EQUAL(true, Stat(unique_dir).is_directory());
377 // Create dirs and files below it
378 const std::string sub_dir = unique_dir + "/" + "some_subdir";
379 const std::string some_file = sub_dir + "/" + "some_file";
380 BOOST_CHECK_EQUAL(true, I2n::mkdir(sub_dir));
381 BOOST_CHECK_EQUAL(true, write_file(some_file, "foobar"));
384 BOOST_CHECK_EQUAL(true, I2n::recursive_delete(unique_dir));
385 BOOST_CHECK_EQUAL(false, Stat(unique_dir).is_directory());
388 BOOST_AUTO_TEST_CASE(TestRecursiveDeleteKeepParentDir)
390 // Create unique directory
391 string unique_dir = I2n::mkdtemp("foobar.XXXXXX");
392 BOOST_REQUIRE(unique_dir.size() > 0);
394 // Test if it's really a directory
395 BOOST_CHECK_EQUAL(true, Stat(unique_dir).is_directory());
397 // Create dirs and files below it
398 const std::string sub_dir = unique_dir + "/" + "some_subdir";
399 const std::string some_file = sub_dir + "/" + "some_file";
400 const std::string other_file = unique_dir + "/" + "other_file";
402 BOOST_CHECK_EQUAL(true, I2n::mkdir(sub_dir));
403 BOOST_CHECK_EQUAL(true, write_file(some_file, "foobar"));
404 BOOST_CHECK_EQUAL(true, write_file(other_file, "foobar"));
407 BOOST_CHECK_EQUAL(true, I2n::recursive_delete(unique_dir, true));
410 BOOST_CHECK_EQUAL(true, Stat(unique_dir).is_directory());
411 BOOST_CHECK_EQUAL(false, Stat(sub_dir).is_directory());
412 BOOST_CHECK_EQUAL(false, Stat(other_file).is_regular_file());
414 BOOST_CHECK_EQUAL(true, I2n::rmdir(unique_dir));
417 BOOST_AUTO_TEST_CASE(TestMkdtempBrokenTemplate)
419 // Broken directory template -> fail
420 string unique_dir = I2n::mkdtemp("foobar.XXX");
421 BOOST_CHECK_EQUAL("", unique_dir);
424 BOOST_AUTO_TEST_CASE(DirectoryCreation)
426 string dirname = "test_directory";
428 I2n::rmdir (dirname);
430 BOOST_CHECK_EQUAL(true, I2n::mkdir(dirname));
431 BOOST_CHECK_EQUAL(true, Stat(dirname).is_directory());
432 // Verify default permissions
433 BOOST_CHECK_EQUAL(0700, Stat(dirname).mode());
435 BOOST_CHECK_EQUAL(true, I2n::rmdir(dirname));
437 // Second call must fail: Directory already deleted
438 BOOST_CHECK_EQUAL(false, I2n::rmdir(dirname));
441 BOOST_AUTO_TEST_CASE(DirectoryCreatePermission)
443 string dirname = "test_directory";
445 // Save and fix umask
446 mode_t previous_mask = I2n::umask(0);
448 I2n::rmdir (dirname);
449 BOOST_CHECK_EQUAL(true, I2n::mkdir(dirname, 0770));
450 BOOST_CHECK_EQUAL(0770, Stat(dirname).mode());
451 I2n::rmdir (dirname);
454 I2n::umask(previous_mask);
457 BOOST_AUTO_TEST_CASE(ChangeDirectory)
459 string current_directory = I2n::getcwd();
460 BOOST_REQUIRE(!current_directory.empty());
462 BOOST_CHECK_EQUAL(true, I2n::chdir("/"));
463 BOOST_CHECK_EQUAL("/", I2n::getcwd());
465 BOOST_CHECK_EQUAL(true, I2n::chdir(current_directory));
466 BOOST_REQUIRE_EQUAL(current_directory, I2n::getcwd());
469 BOOST_AUTO_TEST_CASE(WriteFileEmptyData)
474 I2n::Stat stat(".foobar");
475 BOOST_CHECK_EQUAL( false, (bool)stat );
477 // Call write_file() with empty data. Should still create the file.
478 write_file(".foobar","");
482 BOOST_CHECK_EQUAL( true, (bool)stat );
483 BOOST_CHECK_EQUAL( true, stat.size() == 0 );
488 BOOST_AUTO_TEST_CASE(FileContentDiffersIsIdentical)
490 BOOST_CHECK_EQUAL( false, file_content_differs("/etc/passwd", "/etc/passwd") );
493 BOOST_AUTO_TEST_CASE(FileContentDiffersNonExistent)
495 BOOST_CHECK_EQUAL( true, file_content_differs("/etc/passwd", "abc") );
496 BOOST_CHECK_EQUAL( true, file_content_differs("abc", "/etc/passwd") );
499 BOOST_AUTO_TEST_CASE(FileContentDiffersEqualSize)
501 const string name1 = "file1", name2 = "file2";
503 ofstream out1(name1.c_str());
506 ofstream out2(name2.c_str());
510 bool res = file_content_differs(name1, name2);
514 BOOST_CHECK_EQUAL( true, res );
517 BOOST_AUTO_TEST_CASE(FreeDiskSpace1)
519 inpipestream cmd_df("df -B 1 --output=avail /tmp | tail -n 1");
522 getline(cmd_df, dfstr);
525 string_to<long long>(dfstr,dfout);
527 BOOST_CHECK_EQUAL( dfout, get_free_diskspace("/tmp") );
530 BOOST_AUTO_TEST_CASE(FreeDiskSpace2)
532 BOOST_CHECK_EQUAL( -1, get_free_diskspace("/this/path/is/really/bogus") );
535 BOOST_AUTO_TEST_SUITE_END()