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