summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorChris Wilson <chris+github@qwirx.com>2007-09-19 21:58:24 +0000
committerChris Wilson <chris+github@qwirx.com>2007-09-19 21:58:24 +0000
commit867fbf737760a7764f6095a1b9b7554047c47eb3 (patch)
tree1bc17e74cfef9352857f62b3ee842fa95a8547a4 /test
parent41f3230a75e965254ab47e3609f68c8634266d37 (diff)
parent2ff87143551e6882c90ceaba940a34779b922882 (diff)
Replace trunk with chris/merge.
Diffstat (limited to 'test')
-rw-r--r--test/backupdiff/testbackupdiff.cpp16
-rw-r--r--test/backupstore/testbackupstore.cpp72
-rw-r--r--test/backupstorefix/testbackupstorefix.cpp120
-rw-r--r--test/backupstorepatch/testbackupstorepatch.cpp17
-rw-r--r--test/basicserver/TestCommands.cpp2
-rw-r--r--test/basicserver/testbasicserver.cpp180
-rw-r--r--test/basicserver/testfiles/srv4.conf2
-rw-r--r--test/bbackupd/Makefile.extra1
-rw-r--r--test/bbackupd/testbbackupd.cpp2325
-rw-r--r--test/bbackupd/testfiles/bbackupd.conf.in9
-rwxr-xr-xtest/bbackupd/testfiles/extcheck1.pl.in19
-rwxr-xr-xtest/bbackupd/testfiles/extcheck2.pl.in20
-rwxr-xr-xtest/bbackupd/testfiles/notifyscript.pl.in2
-rwxr-xr-xtest/bbackupd/testfiles/syncallowscript.pl.in2
-rw-r--r--test/common/testcommon.cpp296
-rw-r--r--test/raidfile/intercept.cpp272
-rw-r--r--test/raidfile/testraidfile.cpp126
-rw-r--r--test/win32/testlibwin32.cpp279
18 files changed, 3033 insertions, 727 deletions
diff --git a/test/backupdiff/testbackupdiff.cpp b/test/backupdiff/testbackupdiff.cpp
index 303861a8..a91d6dfe 100644
--- a/test/backupdiff/testbackupdiff.cpp
+++ b/test/backupdiff/testbackupdiff.cpp
@@ -375,8 +375,10 @@ int test(int argc, const char *argv[])
{
// Want to trace out all the details
#ifndef NDEBUG
+ #ifndef WIN32
BackupStoreFile::TraceDetailsOfDiffProcess = true;
#endif
+ #endif
// Create all the test files
create_test_files();
@@ -509,8 +511,15 @@ int test(int argc, const char *argv[])
// suck up lots of processor time -- because of lots of matches
// found. Check this out!
+ #ifdef WIN32
+ ::fprintf(stdout, "Testing diffing two large streams, "
+ "may take a while!\n");
+ ::fflush(stdout);
+ #endif
+
make_file_of_zeros("testfiles/zero.0", 20*1024*1024);
make_file_of_zeros("testfiles/zero.1", 200*1024*1024);
+
// Generate a first encoded file
{
BackupStoreFilenameClear f0name("zero.0");
@@ -530,7 +539,14 @@ int test(int argc, const char *argv[])
2000 /* object ID of the file diffing from */, blockindex, IOStream::TimeOutInfinite,
0, 0));
encoded->CopyStreamTo(out);
+
+ printf("Time taken: %d seconds\n", (int)(time(0) - beginTime));
+
+ #ifdef WIN32
+ TEST_THAT(time(0) < (beginTime + 300));
+ #else
TEST_THAT(time(0) < (beginTime + 40));
+ #endif
}
// Remove zero-files to save disk space
remove("testfiles/zero.0");
diff --git a/test/backupstore/testbackupstore.cpp b/test/backupstore/testbackupstore.cpp
index 34fc98cd..ca29cdff 100644
--- a/test/backupstore/testbackupstore.cpp
+++ b/test/backupstore/testbackupstore.cpp
@@ -33,6 +33,7 @@
#include "MemBlockStream.h"
#include "BackupClientFileAttributes.h"
#include "BackupClientCryptoKeys.h"
+#include "ServerControl.h"
#include "MemLeakFindOn.h"
@@ -1683,7 +1684,10 @@ int test3(int argc, const char *argv[])
"testfiles/clientTrustedCAs.pem");
// First, try logging in without an account having been created... just make sure login fails.
- int pid = LaunchServer("../../bin/bbstored/bbstored testfiles/bbstored.conf", "testfiles/bbstored.pid");
+
+ int pid = LaunchServer(BBSTORED " testfiles/bbstored.conf",
+ "testfiles/bbstored.pid");
+
TEST_THAT(pid != -1 && pid != 0);
if(pid > 0)
{
@@ -1712,12 +1716,17 @@ int test3(int argc, const char *argv[])
}
// Create an account for the test client
- TEST_THAT_ABORTONFAIL(::system("../../bin/bbstoreaccounts/bbstoreaccounts -c testfiles/bbstored.conf create 01234567 0 10000B 20000B") == 0);
+ TEST_THAT_ABORTONFAIL(::system(BBSTOREACCOUNTS
+ " -c testfiles/bbstored.conf create 01234567 0 "
+ "10000B 20000B") == 0);
+
TestRemoteProcessMemLeaks("bbstoreaccounts.memleaks");
+
TEST_THAT(TestDirExists("testfiles/0_0/backup/01234567"));
TEST_THAT(TestDirExists("testfiles/0_1/backup/01234567"));
TEST_THAT(TestDirExists("testfiles/0_2/backup/01234567"));
- TEST_THAT(TestGetFileSize("testfiles/accounts.txt") > 8); // make sure something is written to it
+ TEST_THAT(TestGetFileSize("testfiles/accounts.txt") > 8);
+ // make sure something is written to it
TEST_THAT(ServerIsAlive(pid));
@@ -1741,13 +1750,18 @@ int test3(int argc, const char *argv[])
TestRemoteProcessMemLeaks("bbstored.memleaks");
#endif
- // Set a new limit on the account -- leave the hard limit high to make sure the target for
- // freeing space is the soft limit.
- TEST_THAT_ABORTONFAIL(::system("../../bin/bbstoreaccounts/bbstoreaccounts -c testfiles/bbstored.conf setlimit 01234567 10B 20000B") == 0);
+ // Set a new limit on the account -- leave the hard limit
+ // high to make sure the target for freeing space is the
+ // soft limit.
+ TEST_THAT_ABORTONFAIL(::system(BBSTOREACCOUNTS
+ " -c testfiles/bbstored.conf setlimit 01234567 "
+ "10B 20000B") == 0);
TestRemoteProcessMemLeaks("bbstoreaccounts.memleaks");
// Start things up
- pid = LaunchServer("../../bin/bbstored/bbstored testfiles/bbstored.conf", "testfiles/bbstored.pid");
+ pid = LaunchServer(BBSTORED " testfiles/bbstored.conf",
+ "testfiles/bbstored.pid");
+
::sleep(1);
TEST_THAT(ServerIsAlive(pid));
@@ -1763,8 +1777,9 @@ int test3(int argc, const char *argv[])
// Count the objects again
recursive_count_objects_results after = {0,0,0};
- recursive_count_objects("localhost", BackupProtocolClientListDirectory::RootDirectory, after);
-printf("after.objectsNotDel=%i, deleted=%i, old=%i\n",after.objectsNotDel, after.deleted, after.old);
+ recursive_count_objects("localhost",
+ BackupProtocolClientListDirectory::RootDirectory,
+ after);
// If these tests fail then try increasing the timeout above
TEST_THAT(after.objectsNotDel == before.objectsNotDel);
@@ -1772,7 +1787,9 @@ printf("after.objectsNotDel=%i, deleted=%i, old=%i\n",after.objectsNotDel, after
TEST_THAT(after.old == 0);
// Set a really small hard limit
- TEST_THAT_ABORTONFAIL(::system("../../bin/bbstoreaccounts/bbstoreaccounts -c testfiles/bbstored.conf setlimit 01234567 10B 20B") == 0);
+ TEST_THAT_ABORTONFAIL(::system(BBSTOREACCOUNTS
+ " -c testfiles/bbstored.conf setlimit 01234567 "
+ "10B 20B") == 0);
TestRemoteProcessMemLeaks("bbstoreaccounts.memleaks");
// Try to upload a file and create a directory, and check an error is generated
@@ -1836,11 +1853,16 @@ int multi_server()
printf("Starting server for connection from remote machines...\n");
// Create an account for the test client
- TEST_THAT_ABORTONFAIL(::system("../../bin/bbstoreaccounts/bbstoreaccounts -c testfiles/bbstored.conf create 01234567 0 30000B 40000B") == 0);
+ TEST_THAT_ABORTONFAIL(::system(BBSTOREACCOUNTS
+ " -c testfiles/bbstored.conf create 01234567 0 "
+ "30000B 40000B") == 0);
TestRemoteProcessMemLeaks("bbstoreaccounts.memleaks");
// First, try logging in without an account having been created... just make sure login fails.
- int pid = LaunchServer("../../bin/bbstored/bbstored testfiles/bbstored_multi.conf", "testfiles/bbstored.pid");
+
+ int pid = LaunchServer(BBSTORED " testfiles/bbstored_multi.conf",
+ "testfiles/bbstored.pid");
+
TEST_THAT(pid != -1 && pid != 0);
if(pid > 0)
{
@@ -1874,12 +1896,6 @@ std::string ConvertPathToAbsoluteUnicode(const char *pFileName);
int test(int argc, const char *argv[])
{
#ifdef WIN32
- // Under win32 we must initialise the Winsock library
- // before using sockets
-
- WSADATA info;
- TEST_THAT(WSAStartup(0x0101, &info) != SOCKET_ERROR)
-
// this had better work, or bbstored will die when combining diffs
char* file = "foo";
std::string abs = ConvertPathToAbsoluteUnicode(file);
@@ -1905,6 +1921,7 @@ int test(int argc, const char *argv[])
CloseHandle(h2);
CloseHandle(h1);
+ delete [] wfile;
h1 = openfile("foo", O_CREAT | O_RDWR, 0);
TEST_THAT(h1 != INVALID_HANDLE_VALUE);
@@ -1932,14 +1949,19 @@ int test(int argc, const char *argv[])
// for seeing what's going on.
BackupClientCryptoKeys_Setup("testfiles/bbackupd.keys");
- // encode in some filenames -- can't do static initialisation because the key won't be set up when these are initialised
- for(unsigned int l = 0; l < sizeof(ens_filenames) / sizeof(ens_filenames[0]); ++l)
- {
- ens[l].fn = BackupStoreFilenameClear(ens_filenames[l]);
- }
- for(unsigned int l = 0; l < sizeof(uploads_filenames) / sizeof(uploads_filenames[0]); ++l)
+ // encode in some filenames -- can't do static initialisation
+ // because the key won't be set up when these are initialised
{
- uploads[l].name = BackupStoreFilenameClear(uploads_filenames[l]);
+ MEMLEAKFINDER_NO_LEAKS
+
+ for(unsigned int l = 0; l < sizeof(ens_filenames) / sizeof(ens_filenames[0]); ++l)
+ {
+ ens[l].fn = BackupStoreFilenameClear(ens_filenames[l]);
+ }
+ for(unsigned int l = 0; l < sizeof(uploads_filenames) / sizeof(uploads_filenames[0]); ++l)
+ {
+ uploads[l].name = BackupStoreFilenameClear(uploads_filenames[l]);
+ }
}
// Trace errors out
diff --git a/test/backupstorefix/testbackupstorefix.cpp b/test/backupstorefix/testbackupstorefix.cpp
index 92928cc6..97ff70f3 100644
--- a/test/backupstorefix/testbackupstorefix.cpp
+++ b/test/backupstorefix/testbackupstorefix.cpp
@@ -29,6 +29,7 @@
#include "RaidFileException.h"
#include "StoreStructure.h"
#include "BackupStoreFileWire.h"
+#include "ServerControl.h"
#include "MemLeakFindOn.h"
@@ -42,7 +43,7 @@ make some BackupDirectoryStore objects, CheckAndFix(), then verify
- all old flags
delete store info
-add suprious file
+add spurious file
delete directory (should appear again)
change container ID of directory
delete a file
@@ -65,22 +66,8 @@ std::map<std::string, int32_t> nameToID;
std::map<int32_t, bool> objectIsDir;
#define RUN_CHECK \
- ::system("../../bin/bbstoreaccounts/bbstoreaccounts -c testfiles/bbstored.conf check 01234567"); \
- ::system("../../bin/bbstoreaccounts/bbstoreaccounts -c testfiles/bbstored.conf check 01234567 fix");
-
-// Wait a given number of seconds for something to complete
-void wait_for_operation(int seconds)
-{
- printf("waiting: ");
- fflush(stdout);
- for(int l = 0; l < seconds; ++l)
- {
- sleep(1);
- printf(".");
- fflush(stdout);
- }
- printf("\n");
-}
+ ::system(BBSTOREACCOUNTS " -c testfiles/bbstored.conf check 01234567"); \
+ ::system(BBSTOREACCOUNTS " -c testfiles/bbstored.conf check 01234567 fix");
// Get ID of an object given a filename
int32_t getID(const char *name)
@@ -138,6 +125,7 @@ void CorruptObject(const char *name, int start, const char *rubbish)
w.Write(rubbish, rubbish_len);
// Copy rest of file
r->CopyStreamTo(w);
+ r->Close();
// Commit
w.Commit(true /* convert now */);
}
@@ -202,9 +190,12 @@ void check_dir_dep(BackupStoreDirectory &dir, checkdepinfoen *ck)
void test_dir_fixing()
{
- fnames[0].SetAsClearFilename("x1");
- fnames[1].SetAsClearFilename("x2");
- fnames[2].SetAsClearFilename("x3");
+ {
+ MEMLEAKFINDER_NO_LEAKS;
+ fnames[0].SetAsClearFilename("x1");
+ fnames[1].SetAsClearFilename("x2");
+ fnames[2].SetAsClearFilename("x3");
+ }
{
BackupStoreDirectory dir;
@@ -275,7 +266,7 @@ void test_dir_fixing()
TEST_THAT(dir.CheckAndFix() == false);
check_dir_dep(dir, c1);
- // Check that a suprious depends older ref is undone
+ // Check that a spurious depends older ref is undone
e2->SetDependsOlder(1);
TEST_THAT(dir.CheckAndFix() == true);
TEST_THAT(dir.CheckAndFix() == false);
@@ -300,37 +291,52 @@ int test(int argc, const char *argv[])
rcontroller.Initialise("testfiles/raidfile.conf");
// Create an account
- TEST_THAT_ABORTONFAIL(::system("../../bin/bbstoreaccounts/bbstoreaccounts -c testfiles/bbstored.conf create 01234567 0 10000B 20000B") == 0);
+ TEST_THAT_ABORTONFAIL(::system(BBSTOREACCOUNTS
+ " -c testfiles/bbstored.conf "
+ "create 01234567 0 10000B 20000B") == 0);
TestRemoteProcessMemLeaks("bbstoreaccounts.memleaks");
// Start the bbstored server
- int pid = LaunchServer("../../bin/bbstored/bbstored testfiles/bbstored.conf", "testfiles/bbstored.pid");
+ int pid = LaunchServer(BBSTORED " testfiles/bbstored.conf",
+ "testfiles/bbstored.pid");
TEST_THAT(pid != -1 && pid != 0);
+
if(pid > 0)
{
::sleep(1);
TEST_THAT(ServerIsAlive(pid));
// Run the perl script to create the initial directories
- TEST_THAT_ABORTONFAIL(::system(PERL_EXECUTABLE " testfiles/testbackupstorefix.pl init") == 0);
+ TEST_THAT_ABORTONFAIL(::system(PERL_EXECUTABLE
+ " testfiles/testbackupstorefix.pl init") == 0);
- int bbackupd_pid = LaunchServer("../../bin/bbackupd/bbackupd testfiles/bbackupd.conf", "testfiles/bbackupd.pid");
+ int bbackupd_pid = LaunchServer(BBACKUPD
+ " testfiles/bbackupd.conf", "testfiles/bbackupd.pid");
TEST_THAT(bbackupd_pid != -1 && bbackupd_pid != 0);
+
if(bbackupd_pid > 0)
{
::sleep(1);
TEST_THAT(ServerIsAlive(bbackupd_pid));
// Create a nice store directory
- wait_for_operation(30);
+ wait_for_operation(14);
// That'll do nicely, stop the server
- TEST_THAT(KillServer(bbackupd_pid));
- TestRemoteProcessMemLeaks("bbackupd.memleaks");
+ #ifdef WIN32
+ terminate_bbackupd(bbackupd_pid);
+ // implicit check for memory leaks
+ #else
+ TEST_THAT(KillServer(bbackupd_pid));
+ TestRemoteProcessMemLeaks("bbackupd.memleaks");
+ #endif
}
// Generate a list of all the object IDs
- TEST_THAT_ABORTONFAIL(::system("../../bin/bbackupquery/bbackupquery -q -c testfiles/bbackupd.conf \"list -r\" quit > testfiles/initial-listing.txt") == 0);
+ TEST_THAT_ABORTONFAIL(::system(BBACKUPQUERY " -q "
+ "-c testfiles/bbackupd.conf \"list -r\" quit "
+ "> testfiles/initial-listing.txt") == 0);
+
// And load it in
{
FILE *f = ::fopen("testfiles/initial-listing.txt", "r");
@@ -341,9 +347,11 @@ int test(int argc, const char *argv[])
char name[256];
while(::fgets(line, sizeof(line), f) != 0)
{
- TEST_THAT(::sscanf(line, "%x %s %s", &id, flags, name) == 3);
+ TEST_THAT(::sscanf(line, "%x %s %s", &id,
+ flags, name) == 3);
bool isDir = (::strcmp(flags, "-d---") == 0);
//TRACE3("%x,%d,%s\n", id, isDir, name);
+ MEMLEAKFINDER_NO_LEAKS;
nameToID[std::string(name)] = id;
objectIsDir[id] = isDir;
}
@@ -358,19 +366,24 @@ int test(int argc, const char *argv[])
del.Delete();
}
{
- // Add a suprious file
- RaidFileWrite random(discSetNum, storeRoot + "randomfile");
+ // Add a spurious file
+ RaidFileWrite random(discSetNum,
+ storeRoot + "randomfile");
random.Open();
random.Write("test", 4);
random.Commit(true);
}
+
// Fix it
RUN_CHECK
+
// Check everything is as it was
- TEST_THAT(::system(PERL_EXECUTABLE " testfiles/testbackupstorefix.pl check 0") == 0);
+ TEST_THAT(::system(PERL_EXECUTABLE
+ " testfiles/testbackupstorefix.pl check 0") == 0);
// Check the random file doesn't exist
{
- TEST_THAT(!RaidFileRead::FileExists(discSetNum, storeRoot + "01/randomfile"));
+ TEST_THAT(!RaidFileRead::FileExists(discSetNum,
+ storeRoot + "01/randomfile"));
}
// ------------------------------------------------------------------------------------------------
@@ -410,6 +423,8 @@ int test(int argc, const char *argv[])
file_BlockIndexEntry e[2];
} h;
TEST_THAT(file->Read(&h, sizeof(h)) == sizeof(h));
+ file->Close();
+
// Modify
TEST_THAT(box_ntoh64(h.hdr.mOtherFileID) == 0);
TEST_THAT(box_ntoh64(h.hdr.mNumBlocks) >= 2);
@@ -425,14 +440,16 @@ int test(int argc, const char *argv[])
// Fix it
RUN_CHECK
// Check
- TEST_THAT(::system(PERL_EXECUTABLE " testfiles/testbackupstorefix.pl check 1") == 0);
+ TEST_THAT(::system(PERL_EXECUTABLE
+ " testfiles/testbackupstorefix.pl check 1")
+ == 0);
// Check the modified file doesn't exist
TEST_THAT(!RaidFileRead::FileExists(discSetNum, fn));
}
// ------------------------------------------------------------------------------------------------
- ::printf(" === Delete directory, change container ID of another, duplicate entry in dir, supurious file size, delete file\n");
+ ::printf(" === Delete directory, change container ID of another, duplicate entry in dir, spurious file size, delete file\n");
{
BackupStoreDirectory dir;
LoadDirectory("Test1/foreomizes/stemptinevidate/ict", dir);
@@ -440,7 +457,7 @@ int test(int argc, const char *argv[])
SaveDirectory("Test1/foreomizes/stemptinevidate/ict", dir);
}
int64_t duplicatedID = 0;
- int64_t notSupriousFileSize = 0;
+ int64_t notSpuriousFileSize = 0;
{
BackupStoreDirectory dir;
LoadDirectory("Test1/cannes/ict/peep", dir);
@@ -458,7 +475,7 @@ int test(int argc, const char *argv[])
BackupStoreDirectory::Iterator i(dir);
BackupStoreDirectory::Entry *en = i.Next(BackupStoreDirectory::Entry::Flags_File);
TEST_THAT(en != 0);
- notSupriousFileSize = en->GetSizeInBlocks();
+ notSpuriousFileSize = en->GetSizeInBlocks();
en->SetSizeInBlocks(3473874);
TEST_THAT(en->GetSizeInBlocks() == 3473874);
}
@@ -471,7 +488,8 @@ int test(int argc, const char *argv[])
// Fix it
RUN_CHECK
// Check everything is as it should be
- TEST_THAT(::system(PERL_EXECUTABLE " testfiles/testbackupstorefix.pl check 2") == 0);
+ TEST_THAT(::system(PERL_EXECUTABLE
+ " testfiles/testbackupstorefix.pl check 2") == 0);
{
BackupStoreDirectory dir;
LoadDirectory("Test1/foreomizes/stemptinevidate/ict", dir);
@@ -497,7 +515,7 @@ int test(int argc, const char *argv[])
BackupStoreDirectory::Iterator i(dir);
BackupStoreDirectory::Entry *en = i.Next(BackupStoreDirectory::Entry::Flags_File);
TEST_THAT(en != 0);
- TEST_THAT(en->GetSizeInBlocks() == notSupriousFileSize);
+ TEST_THAT(en->GetSizeInBlocks() == notSpuriousFileSize);
}
}
@@ -527,7 +545,8 @@ int test(int argc, const char *argv[])
// Fix it
RUN_CHECK
// Check everything is as it should be
- TEST_THAT(::system(PERL_EXECUTABLE " testfiles/testbackupstorefix.pl check 3") == 0);
+ TEST_THAT(::system(PERL_EXECUTABLE
+ " testfiles/testbackupstorefix.pl check 3") == 0);
{
BackupStoreDirectory dir;
LoadDirectory("Test1/foreomizes/stemptinevidate/ict", dir);
@@ -541,18 +560,22 @@ int test(int argc, const char *argv[])
// Fix it
RUN_CHECK
// Check everything is where it is predicted to be
- TEST_THAT(::system(PERL_EXECUTABLE " testfiles/testbackupstorefix.pl check 4") == 0);
+ TEST_THAT(::system(PERL_EXECUTABLE
+ " testfiles/testbackupstorefix.pl check 4") == 0);
// ------------------------------------------------------------------------------------------------
::printf(" === Corrupt file and dir\n");
// File
- CorruptObject("Test1/foreomizes/stemptinevidate/algoughtnerge", 33, "34i729834298349283479233472983sdfhasgs");
+ CorruptObject("Test1/foreomizes/stemptinevidate/algoughtnerge",
+ 33, "34i729834298349283479233472983sdfhasgs");
// Dir
- CorruptObject("Test1/cannes/imulatrougge/foreomizes", 23, "dsf32489sdnadf897fd2hjkesdfmnbsdfcsfoisufio2iofe2hdfkjhsf");
+ CorruptObject("Test1/cannes/imulatrougge/foreomizes",23,
+ "dsf32489sdnadf897fd2hjkesdfmnbsdfcsfoisufio2iofe2hdfkjhsf");
// Fix it
RUN_CHECK
// Check everything is where it should be
- TEST_THAT(::system(PERL_EXECUTABLE " testfiles/testbackupstorefix.pl check 5") == 0);
+ TEST_THAT(::system(PERL_EXECUTABLE
+ " testfiles/testbackupstorefix.pl check 5") == 0);
// ------------------------------------------------------------------------------------------------
::printf(" === Overwrite root with a file\n");
@@ -566,13 +589,16 @@ int test(int argc, const char *argv[])
// Fix it
RUN_CHECK
// Check everything is where it should be
- TEST_THAT(::system(PERL_EXECUTABLE " testfiles/testbackupstorefix.pl reroot 6") == 0);
+ TEST_THAT(::system(PERL_EXECUTABLE
+ " testfiles/testbackupstorefix.pl reroot 6") == 0);
// ------------------------------------------------------------------------------------------------
// Stop server
TEST_THAT(KillServer(pid));
- TestRemoteProcessMemLeaks("bbstored.memleaks");
+ #ifndef WIN32
+ TestRemoteProcessMemLeaks("bbstored.memleaks");
+ #endif
}
return 0;
diff --git a/test/backupstorepatch/testbackupstorepatch.cpp b/test/backupstorepatch/testbackupstorepatch.cpp
index 8e2fa5f6..4fbf296a 100644
--- a/test/backupstorepatch/testbackupstorepatch.cpp
+++ b/test/backupstorepatch/testbackupstorepatch.cpp
@@ -35,6 +35,7 @@
#include "MemBlockStream.h"
#include "BackupClientFileAttributes.h"
#include "BackupClientCryptoKeys.h"
+#include "ServerControl.h"
#include "MemLeakFindOn.h"
@@ -283,14 +284,6 @@ void test_depends_in_dirs()
int test(int argc, const char *argv[])
{
-#ifdef WIN32
- // Under win32 we must initialise the Winsock library
- // before using sockets
-
- WSADATA info;
- TEST_THAT(WSAStartup(0x0101, &info) != SOCKET_ERROR)
-#endif
-
// Allocate a buffer
buffer = ::malloc(BUFFER_SIZE);
TEST_THAT(buffer != 0);
@@ -317,9 +310,8 @@ int test(int argc, const char *argv[])
"testfiles/clientTrustedCAs.pem");
// Create an account
- TEST_THAT_ABORTONFAIL(RunCommand(
- "../../bin/bbstoreaccounts/bbstoreaccounts "
- "-c testfiles/bbstored.conf "
+ TEST_THAT_ABORTONFAIL(::system(BBSTOREACCOUNTS
+ " -c testfiles/bbstored.conf "
"create 01234567 0 30000B 40000B") == 0);
TestRemoteProcessMemLeaks("bbstoreaccounts.memleaks");
@@ -330,7 +322,8 @@ int test(int argc, const char *argv[])
test_depends_in_dirs();
// First, try logging in without an account having been created... just make sure login fails.
- int pid = LaunchServer("../../bin/bbstored/bbstored testfiles/bbstored.conf", "testfiles/bbstored.pid");
+ int pid = LaunchServer(BBSTORED " testfiles/bbstored.conf",
+ "testfiles/bbstored.pid");
TEST_THAT(pid != -1 && pid != 0);
if(pid > 0)
{
diff --git a/test/basicserver/TestCommands.cpp b/test/basicserver/TestCommands.cpp
index b18a3326..657e79ea 100644
--- a/test/basicserver/TestCommands.cpp
+++ b/test/basicserver/TestCommands.cpp
@@ -1,7 +1,9 @@
#include "Box.h"
+#ifdef HAVE_SYSLOG_H
#include <syslog.h>
+#endif
#include "autogen_TestProtocolServer.h"
#include "CollectInBufferStream.h"
diff --git a/test/basicserver/testbasicserver.cpp b/test/basicserver/testbasicserver.cpp
index 3360cd20..4b33f555 100644
--- a/test/basicserver/testbasicserver.cpp
+++ b/test/basicserver/testbasicserver.cpp
@@ -28,6 +28,7 @@
#include "TestContext.h"
#include "autogen_TestProtocolClient.h"
#include "autogen_TestProtocolServer.h"
+#include "ServerControl.h"
#include "MemLeakFindOn.h"
@@ -430,84 +431,139 @@ int test(int argc, const char *argv[])
}
}
-//printf("SKIPPING TESTS------------------------\n");
-//goto protocolserver;
+ //printf("SKIPPING TESTS------------------------\n");
+ //goto protocolserver;
// Launch a basic server
{
- int pid = LaunchServer("./test srv1 testfiles/srv1.conf", "testfiles/srv1.pid");
+ int pid = LaunchServer("./test srv1 testfiles/srv1.conf",
+ "testfiles/srv1.pid");
+
TEST_THAT(pid != -1 && pid != 0);
if(pid > 0)
{
// Check that it's written the expected file
- TEST_THAT(TestFileExists("testfiles/srv1.test1"));
+ TEST_THAT(TestFileExists("testfiles"
+ DIRECTORY_SEPARATOR "srv1.test1"));
TEST_THAT(ServerIsAlive(pid));
+
// Move the config file over
- TEST_THAT(::rename("testfiles/srv1b.conf", "testfiles/srv1.conf") != -1);
- // Get it to reread the config file
- TEST_THAT(HUPServer(pid));
- ::sleep(1);
- TEST_THAT(ServerIsAlive(pid));
- // Check that new file exists
- TEST_THAT(TestFileExists("testfiles/srv1.test2"));
+ #ifdef WIN32
+ TEST_THAT(::unlink("testfiles"
+ DIRECTORY_SEPARATOR "srv1.conf") != -1);
+ #endif
+
+ TEST_THAT(::rename(
+ "testfiles" DIRECTORY_SEPARATOR "srv1b.conf",
+ "testfiles" DIRECTORY_SEPARATOR "srv1.conf")
+ != -1);
+
+ #ifndef WIN32
+ // Get it to reread the config file
+ TEST_THAT(HUPServer(pid));
+ ::sleep(1);
+ TEST_THAT(ServerIsAlive(pid));
+ // Check that new file exists
+ TEST_THAT(TestFileExists("testfiles"
+ DIRECTORY_SEPARATOR "srv1.test2"));
+ #endif // !WIN32
+
// Kill it off
TEST_THAT(KillServer(pid));
- TestRemoteProcessMemLeaks("generic-daemon.memleaks");
+
+ #ifndef WIN32
+ TestRemoteProcessMemLeaks(
+ "generic-daemon.memleaks");
+ #endif // !WIN32
}
}
// Launch a test forking server
{
- int pid = LaunchServer("./test srv2 testfiles/srv2.conf", "testfiles/srv2.pid");
+ int pid = LaunchServer("./test srv2 testfiles/srv2.conf",
+ "testfiles/srv2.pid");
+
TEST_THAT(pid != -1 && pid != 0);
+
if(pid > 0)
{
// Will it restart?
TEST_THAT(ServerIsAlive(pid));
- TEST_THAT(HUPServer(pid));
- ::sleep(1);
- TEST_THAT(ServerIsAlive(pid));
+
+ #ifndef WIN32
+ TEST_THAT(HUPServer(pid));
+ ::sleep(1);
+ TEST_THAT(ServerIsAlive(pid));
+ #endif // !WIN32
+
// Make some connections
{
SocketStream conn1;
conn1.Open(Socket::TypeINET, "localhost", 2003);
- SocketStream conn2;
- conn2.Open(Socket::TypeUNIX, "testfiles/srv2.sock");
- SocketStream conn3;
- conn3.Open(Socket::TypeINET, "localhost", 2003);
+
+ #ifndef WIN32
+ SocketStream conn2;
+ conn2.Open(Socket::TypeUNIX,
+ "testfiles/srv2.sock");
+ SocketStream conn3;
+ conn3.Open(Socket::TypeINET,
+ "localhost", 2003);
+ #endif // !WIN32
+
// Quick check that reconnections fail
- TEST_CHECK_THROWS(conn1.Open(Socket::TypeUNIX, "testfiles/srv2.sock");, ServerException, SocketAlreadyOpen);
+ TEST_CHECK_THROWS(conn1.Open(Socket::TypeUNIX,
+ "testfiles/srv2.sock");,
+ ServerException, SocketAlreadyOpen);
+
// Stuff some data around
std::vector<IOStream *> conns;
conns.push_back(&conn1);
- conns.push_back(&conn2);
- conns.push_back(&conn3);
+
+ #ifndef WIN32
+ conns.push_back(&conn2);
+ conns.push_back(&conn3);
+ #endif // !WIN32
+
Srv2TestConversations(conns);
// Implicit close
}
- // HUP again
- TEST_THAT(HUPServer(pid));
- ::sleep(1);
- TEST_THAT(ServerIsAlive(pid));
+
+ #ifndef WIN32
+ // HUP again
+ TEST_THAT(HUPServer(pid));
+ ::sleep(1);
+ TEST_THAT(ServerIsAlive(pid));
+ #endif // !WIN32
+
// Kill it
TEST_THAT(KillServer(pid));
::sleep(1);
TEST_THAT(!ServerIsAlive(pid));
- TestRemoteProcessMemLeaks("test-srv2.memleaks");
+
+ #ifndef WIN32
+ TestRemoteProcessMemLeaks("test-srv2.memleaks");
+ #endif // !WIN32
}
}
// Launch a test SSL server
{
- int pid = LaunchServer("./test srv3 testfiles/srv3.conf", "testfiles/srv3.pid");
+ int pid = LaunchServer("./test srv3 testfiles/srv3.conf",
+ "testfiles/srv3.pid");
+
TEST_THAT(pid != -1 && pid != 0);
+
if(pid > 0)
{
// Will it restart?
TEST_THAT(ServerIsAlive(pid));
- TEST_THAT(HUPServer(pid));
- ::sleep(1);
- TEST_THAT(ServerIsAlive(pid));
+
+ #ifndef WIN32
+ TEST_THAT(HUPServer(pid));
+ ::sleep(1);
+ TEST_THAT(ServerIsAlive(pid));
+ #endif
+
// Make some connections
{
// SSL library
@@ -522,37 +578,60 @@ int test(int argc, const char *argv[])
SocketStreamTLS conn1;
conn1.Open(context, Socket::TypeINET, "localhost", 2003);
- SocketStreamTLS conn2;
- conn2.Open(context, Socket::TypeUNIX, "testfiles/srv3.sock");
- SocketStreamTLS conn3;
- conn3.Open(context, Socket::TypeINET, "localhost", 2003);
+ #ifndef WIN32
+ SocketStreamTLS conn2;
+ conn2.Open(context, Socket::TypeUNIX,
+ "testfiles/srv3.sock");
+ SocketStreamTLS conn3;
+ conn3.Open(context, Socket::TypeINET,
+ "localhost", 2003);
+ #endif
+
// Quick check that reconnections fail
- TEST_CHECK_THROWS(conn1.Open(context, Socket::TypeUNIX, "testfiles/srv3.sock");, ServerException, SocketAlreadyOpen);
+ TEST_CHECK_THROWS(conn1.Open(context,
+ Socket::TypeUNIX,
+ "testfiles/srv3.sock");,
+ ServerException, SocketAlreadyOpen);
+
// Stuff some data around
std::vector<IOStream *> conns;
conns.push_back(&conn1);
- conns.push_back(&conn2);
- conns.push_back(&conn3);
+
+ #ifndef WIN32
+ conns.push_back(&conn2);
+ conns.push_back(&conn3);
+ #endif
+
Srv2TestConversations(conns);
// Implicit close
}
- // HUP again
- TEST_THAT(HUPServer(pid));
- ::sleep(1);
- TEST_THAT(ServerIsAlive(pid));
+
+ #ifndef WIN32
+ // HUP again
+ TEST_THAT(HUPServer(pid));
+ ::sleep(1);
+ TEST_THAT(ServerIsAlive(pid));
+ #endif
+
// Kill it
TEST_THAT(KillServer(pid));
::sleep(1);
TEST_THAT(!ServerIsAlive(pid));
- TestRemoteProcessMemLeaks("test-srv3.memleaks");
+
+ #ifndef WIN32
+ TestRemoteProcessMemLeaks("test-srv3.memleaks");
+ #endif
}
}
//protocolserver:
// Launch a test protocol handling server
{
- int pid = LaunchServer("./test srv4 testfiles/srv4.conf", "testfiles/srv4.pid");
+ int pid = LaunchServer("./test srv4 testfiles/srv4.conf",
+ "testfiles/srv4.pid");
+
TEST_THAT(pid != -1 && pid != 0);
+
if(pid > 0)
{
::sleep(1);
@@ -560,7 +639,11 @@ int test(int argc, const char *argv[])
// Open a connection to it
SocketStream conn;
- conn.Open(Socket::TypeUNIX, "testfiles/srv4.sock");
+ #ifdef WIN32
+ conn.Open(Socket::TypeINET, "localhost", 2003);
+ #else
+ conn.Open(Socket::TypeUNIX, "testfiles/srv4.sock");
+ #endif
// Create a protocol
TestProtocolClient protocol(conn);
@@ -623,7 +706,10 @@ int test(int argc, const char *argv[])
TEST_THAT(KillServer(pid));
::sleep(1);
TEST_THAT(!ServerIsAlive(pid));
- TestRemoteProcessMemLeaks("test-srv4.memleaks");
+
+ #ifndef WIN32
+ TestRemoteProcessMemLeaks("test-srv4.memleaks");
+ #endif
}
}
diff --git a/test/basicserver/testfiles/srv4.conf b/test/basicserver/testfiles/srv4.conf
index b4c5627c..f05dff75 100644
--- a/test/basicserver/testfiles/srv4.conf
+++ b/test/basicserver/testfiles/srv4.conf
@@ -1,6 +1,6 @@
Server
{
PidFile = testfiles/srv4.pid
- ListenAddresses = unix:testfiles/srv4.sock
+ ListenAddresses = unix:testfiles/srv4.sock,inet:localhost
}
diff --git a/test/bbackupd/Makefile.extra b/test/bbackupd/Makefile.extra
new file mode 100644
index 00000000..1d3f5103
--- /dev/null
+++ b/test/bbackupd/Makefile.extra
@@ -0,0 +1 @@
+link-extra: ../../bin/bbackupd/autogen_ClientException.o ../../bin/bbackupd/BackupClientContext.o ../../bin/bbackupd/BackupClientDeleteList.o ../../bin/bbackupd/BackupClientDirectoryRecord.o ../../bin/bbackupd/Win32BackupService.o ../../bin/bbackupd/BackupClientInodeToIDMap.o ../../bin/bbackupd/Win32ServiceFunctions.o ../../bin/bbackupd/BackupDaemon.o
diff --git a/test/bbackupd/testbbackupd.cpp b/test/bbackupd/testbbackupd.cpp
index 0aedb714..49b7f48a 100644
--- a/test/bbackupd/testbbackupd.cpp
+++ b/test/bbackupd/testbbackupd.cpp
@@ -9,38 +9,65 @@
#include "Box.h"
+// do not include MinGW's dirent.h on Win32,
+// as we override some of it in lib/win32.
+
+#ifndef WIN32
+ #include <dirent.h>
+#endif
+
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <limits.h>
#include <string.h>
-#include <sys/wait.h>
#include <unistd.h>
+
+#ifdef HAVE_SYS_WAIT_H
+ #include <sys/wait.h>
+#endif
+
#ifdef HAVE_SYS_XATTR_H
-#include <cerrno>
-#include <sys/xattr.h>
+ #include <cerrno>
+ #include <sys/xattr.h>
#endif
+
#include <map>
-#include "Test.h"
+#ifdef HAVE_SYSCALL
+ #include <sys/syscall.h>
+#endif
+
+#include "BackupClientCryptoKeys.h"
#include "BackupClientFileAttributes.h"
-#include "CommonException.h"
+#include "BackupClientRestore.h"
+#include "BackupDaemon.h"
+#include "BackupDaemonConfigVerify.h"
+#include "BackupStoreConstants.h"
+#include "BackupStoreDirectory.h"
#include "BackupStoreException.h"
+#include "BoxPortsAndFiles.h"
+#include "BoxTime.h"
+#include "BoxTimeToUnix.h"
+#include "CollectInBufferStream.h"
+#include "CommonException.h"
+#include "Configuration.h"
#include "FileModificationTime.h"
-#include "autogen_BackupProtocolClient.h"
+#include "FileStream.h"
+#include "IOStreamGetLine.h"
+#include "LocalProcessStream.h"
#include "SSLLib.h"
-#include "TLSContext.h"
-#include "SocketStreamTLS.h"
-#include "BoxPortsAndFiles.h"
-#include "BackupStoreConstants.h"
+#include "ServerControl.h"
#include "Socket.h"
-#include "BackupClientRestore.h"
-#include "BackupStoreDirectory.h"
-#include "BackupClientCryptoKeys.h"
-#include "CollectInBufferStream.h"
+#include "SocketStreamTLS.h"
+#include "TLSContext.h"
+#include "Test.h"
+#include "Timer.h"
#include "Utils.h"
-#include "BoxTime.h"
-#include "BoxTimeToUnix.h"
+
+#include "autogen_BackupProtocolClient.h"
+#include "intercept.h"
+#include "ServerControl.h"
#include "MemLeakFindOn.h"
@@ -54,18 +81,11 @@
void wait_for_backup_operation(int seconds = TIME_TO_WAIT_FOR_BACKUP_OPERATION)
{
- printf("waiting: ");
- fflush(stdout);
- for(int l = 0; l < seconds; ++l)
- {
- sleep(1);
- printf(".");
- fflush(stdout);
- }
- printf("\n");
+ wait_for_operation(seconds);
}
int bbstored_pid = 0;
+int bbackupd_pid = 0;
#ifdef HAVE_SYS_XATTR_H
bool readxattr_into_map(const char *filename, std::map<std::string,std::string> &rOutput)
@@ -252,6 +272,9 @@ bool attrmatch(const char *f1, const char *f2)
// if link, just make sure other file is a link too, and that the link to names match
if((s1.st_mode & S_IFMT) == S_IFLNK)
{
+#ifdef WIN32
+ TEST_FAIL_WITH_MESSAGE("No symlinks on win32!")
+#else
if((s2.st_mode & S_IFMT) != S_IFLNK) return false;
char p1[PATH_MAX], p2[PATH_MAX];
@@ -262,6 +285,7 @@ bool attrmatch(const char *f1, const char *f2)
p1[p1l] = '\0';
p2[p2l] = '\0';
return strcmp(p1, p2) == 0;
+#endif
}
// modification times
@@ -280,12 +304,15 @@ int test_basics()
BackupClientFileAttributes t1;
t1.ReadAttributes("testfiles/test1");
TEST_THAT(!t1.IsSymLink());
+
+#ifndef WIN32
BackupClientFileAttributes t2;
t2.ReadAttributes("testfiles/test2");
TEST_THAT(t2.IsSymLink());
// Check that it's actually been encrypted (search for symlink name encoded in it)
void *te = ::memchr(t2.GetBuffer(), 't', t2.GetSize() - 3);
TEST_THAT(te == 0 || ::memcmp(te, "test", 4) != 0);
+#endif
BackupClientFileAttributes t3;
TEST_CHECK_THROWS(t3.ReadAttributes("doesn't exist"), CommonException, OSFileError);
@@ -298,13 +325,20 @@ int test_basics()
// Apply attributes to these new files
t1.WriteAttributes("testfiles/test1_n");
+#ifdef WIN32
+ t1.WriteAttributes("testfiles/test2_n");
+#else
t2.WriteAttributes("testfiles/test2_n");
+#endif
+
+#ifndef WIN32
TEST_CHECK_THROWS(t1.WriteAttributes("testfiles/test1_nXX"), CommonException, OSFileError);
TEST_CHECK_THROWS(t3.WriteAttributes("doesn't exist"), BackupStoreException, AttributesNotLoaded);
- // Test that atttributes are vaguely similar
+ // Test that attributes are vaguely similar
TEST_THAT(attrmatch("testfiles/test1", "testfiles/test1_n"));
TEST_THAT(attrmatch("testfiles/test2", "testfiles/test2_n"));
+#endif
// Check encryption, and recovery from encryption
// First, check that two attributes taken from the same thing have different encrypted values (think IV)
@@ -377,18 +411,22 @@ int test_basics()
int test_setupaccount()
{
- TEST_THAT_ABORTONFAIL(::system("../../bin/bbstoreaccounts/bbstoreaccounts -c testfiles/bbstored.conf create 01234567 0 1000B 2000B") == 0);
+ TEST_THAT_ABORTONFAIL(::system(BBSTOREACCOUNTS " -c "
+ "testfiles/bbstored.conf create 01234567 0 1000B 2000B") == 0);
TestRemoteProcessMemLeaks("bbstoreaccounts.memleaks");
return 0;
}
int test_run_bbstored()
{
- bbstored_pid = LaunchServer("../../bin/bbstored/bbstored testfiles/bbstored.conf", "testfiles/bbstored.pid");
+ std::string cmd = BBSTORED + bbstored_args + " testfiles/bbstored.conf";
+ bbstored_pid = LaunchServer(cmd, "testfiles/bbstored.pid");
+
TEST_THAT(bbstored_pid != -1 && bbstored_pid != 0);
+
if(bbstored_pid > 0)
{
- ::sleep(1);
+ ::safe_sleep(1);
TEST_THAT(ServerIsAlive(bbstored_pid));
return 0; // success
}
@@ -399,9 +437,13 @@ int test_run_bbstored()
int test_kill_bbstored()
{
TEST_THAT(KillServer(bbstored_pid));
- ::sleep(1);
+ ::safe_sleep(1);
TEST_THAT(!ServerIsAlive(bbstored_pid));
- TestRemoteProcessMemLeaks("bbstored.memleaks");
+
+ #ifndef WIN32
+ TestRemoteProcessMemLeaks("bbstored.memleaks");
+ #endif
+
return 0;
}
@@ -437,6 +479,7 @@ void terminate_on_alarm(int sigraised)
abort();
}
+#ifndef WIN32
void do_interrupted_restore(const TLSContext &context, int64_t restoredirid)
{
int pid = 0;
@@ -499,12 +542,216 @@ void do_interrupted_restore(const TLSContext &context, int64_t restoredirid)
}
}
}
+#endif // !WIN32
+
+void force_sync()
+{
+ TEST_THAT(::system(BBACKUPCTL " -q -c testfiles/bbackupd.conf "
+ "force-sync") == 0);
+ TestRemoteProcessMemLeaks("bbackupctl.memleaks");
+}
+
+void wait_for_sync_start()
+{
+ TEST_THAT(::system(BBACKUPCTL " -q -c testfiles/bbackupd.conf "
+ "wait-for-sync") == 0);
+ TestRemoteProcessMemLeaks("bbackupctl.memleaks");
+}
+
+void wait_for_sync_end()
+{
+ TEST_THAT(::system(BBACKUPCTL " -q -c testfiles/bbackupd.conf "
+ "wait-for-end") == 0);
+ TestRemoteProcessMemLeaks("bbackupctl.memleaks");
+}
+
+void sync_and_wait()
+{
+ TEST_THAT(::system(BBACKUPCTL " -q -c testfiles/bbackupd.conf "
+ "force-sync") == 0);
+ TestRemoteProcessMemLeaks("bbackupctl.memleaks");
+}
+
+#ifdef WIN32
+bool set_file_time(const char* filename, FILETIME creationTime,
+ FILETIME lastModTime, FILETIME lastAccessTime)
+{
+ HANDLE handle = openfile(filename, O_RDWR, 0);
+ TEST_THAT(handle != INVALID_HANDLE_VALUE);
+ if (handle == INVALID_HANDLE_VALUE) return false;
+
+ BOOL success = SetFileTime(handle, &creationTime, &lastAccessTime,
+ &lastModTime);
+ TEST_THAT(success);
+
+ TEST_THAT(CloseHandle(handle));
+ return success;
+}
+#endif
+
+void intercept_setup_delay(const char *filename, unsigned int delay_after,
+ int delay_ms, int syscall_to_delay);
+bool intercept_triggered();
+
+int64_t SearchDir(BackupStoreDirectory& rDir,
+ const std::string& rChildName)
+{
+ BackupStoreDirectory::Iterator i(rDir);
+ BackupStoreFilenameClear child(rChildName.c_str());
+ BackupStoreDirectory::Entry *en = i.FindMatchingClearName(child);
+ if (en == 0) return 0;
+ int64_t id = en->GetObjectID();
+ TEST_THAT(id > 0);
+ TEST_THAT(id != BackupProtocolClientListDirectory::RootDirectory);
+ return id;
+}
+
+int start_internal_daemon()
+{
+ // ensure that no child processes end up running tests!
+ int own_pid = getpid();
+
+ BackupDaemon daemon;
+ int result = daemon.Main("testfiles/bbackupd.conf");
+
+ TEST_THAT(result == 0);
+ if (result != 0)
+ {
+ printf("Daemon exited with code %d\n", result);
+ }
+
+ // ensure that no child processes end up running tests!
+ TEST_THAT(getpid() == own_pid);
+ if (getpid() != own_pid)
+ {
+ // abort!
+ _exit(1);
+ }
+
+ TEST_THAT(TestFileExists("testfiles/bbackupd.pid"));
+
+ printf("Waiting for backup daemon to start: ");
+ int pid = -1;
+
+ for (int i = 0; i < 30; i++)
+ {
+ printf(".");
+ fflush(stdout);
+ safe_sleep(1);
+
+ if (TestFileExists("testfiles/bbackupd.pid"))
+ {
+ pid = ReadPidFile("testfiles/bbackupd.pid");
+ }
+
+ if (pid > 0)
+ {
+ break;
+ }
+ }
+
+ printf(" done.\n");
+ fflush(stdout);
+
+ TEST_THAT(pid > 0);
+ return pid;
+}
+
+void stop_internal_daemon(int pid)
+{
+ TEST_THAT(KillServer(pid));
+
+ /*
+ int status;
+ TEST_THAT(waitpid(pid, &status, 0) == pid);
+ TEST_THAT(WIFEXITED(status));
+
+ if (WIFEXITED(status))
+ {
+ TEST_THAT(WEXITSTATUS(status) == 0);
+ }
+ */
+}
+
+static struct dirent readdir_test_dirent;
+static int readdir_test_counter = 0;
+static int readdir_stop_time = 0;
+static char stat_hook_filename[512];
+
+// First test hook, during the directory scanning stage, returns empty.
+// This will not match the directory on the store, so a sync will start.
+// We set up the next intercept for the same directory by passing NULL.
+
+struct dirent *readdir_test_hook_2(DIR *dir);
+
+#ifdef LINUX_WEIRD_LSTAT
+int lstat_test_hook(int ver, const char *file_name, struct stat *buf);
+#else
+int lstat_test_hook(const char *file_name, struct stat *buf);
+#endif
+
+struct dirent *readdir_test_hook_1(DIR *dir)
+{
+#ifndef PLATFORM_CLIB_FNS_INTERCEPTION_IMPOSSIBLE
+ intercept_setup_readdir_hook(NULL, readdir_test_hook_2);
+#endif
+ return NULL;
+}
+
+// Second test hook, during the directory sync stage, keeps returning
+// new filenames until the timer expires, then disables the intercept.
+
+struct dirent *readdir_test_hook_2(DIR *dir)
+{
+ if (time(NULL) >= readdir_stop_time)
+ {
+#ifndef PLATFORM_CLIB_FNS_INTERCEPTION_IMPOSSIBLE
+ intercept_setup_readdir_hook(NULL, NULL);
+ intercept_setup_lstat_hook (NULL, NULL);
+#endif
+ // we will not be called again.
+ }
+
+ // fill in the struct dirent appropriately
+ memset(&readdir_test_dirent, 0, sizeof(readdir_test_dirent));
+
+ #ifdef HAVE_STRUCT_DIRENT_D_INO
+ readdir_test_dirent.d_ino = ++readdir_test_counter;
+ #endif
+
+ snprintf(readdir_test_dirent.d_name,
+ sizeof(readdir_test_dirent.d_name),
+ "test.%d", readdir_test_counter);
+
+ // ensure that when bbackupd stats the file, it gets the
+ // right answer
+ snprintf(stat_hook_filename, sizeof(stat_hook_filename),
+ "testfiles/TestDir1/spacetest/d1/test.%d",
+ readdir_test_counter);
+#ifndef PLATFORM_CLIB_FNS_INTERCEPTION_IMPOSSIBLE
+ intercept_setup_lstat_hook(stat_hook_filename, lstat_test_hook);
+#endif
+
+ return &readdir_test_dirent;
+}
+#ifdef LINUX_WEIRD_LSTAT
+int lstat_test_hook(int ver, const char *file_name, struct stat *buf)
+#else
+int lstat_test_hook(const char *file_name, struct stat *buf)
+#endif
+{
+ // TRACE1("lstat hook triggered for %s", file_name);
+ memset(buf, 0, sizeof(*buf));
+ buf->st_mode = S_IFREG;
+ return 0;
+}
int test_bbackupd()
{
-// // First, wait for a normal period to make sure the last changes attributes are within a normal backup timeframe.
-// wait_for_backup_operation();
+ // First, wait for a normal period to make sure the last changes
+ // attributes are within a normal backup timeframe.
+ // wait_for_backup_operation();
// Connection gubbins
TLSContext context;
@@ -515,39 +762,349 @@ int test_bbackupd()
// unpack the files for the initial test
TEST_THAT(::system("rm -rf testfiles/TestDir1") == 0);
- TEST_THAT(::system("mkdir testfiles/TestDir1") == 0);
- TEST_THAT(::system("gzip -d < testfiles/spacetest1.tgz | ( cd testfiles/TestDir1 && tar xf - )") == 0);
+ TEST_THAT(::mkdir("testfiles/TestDir1", 0777) == 0);
+
+ #ifdef WIN32
+ TEST_THAT(::system("tar xzvf testfiles/spacetest1.tgz "
+ "-C testfiles/TestDir1") == 0);
+ #else
+ TEST_THAT(::system("gzip -d < testfiles/spacetest1.tgz "
+ "| ( cd testfiles/TestDir1 && tar xf - )") == 0);
+ #endif
+
+#ifdef PLATFORM_CLIB_FNS_INTERCEPTION_IMPOSSIBLE
+ printf("\n==== Skipping intercept-based KeepAlive tests "
+ "on this platform.\n");
+#else
+ printf("\n==== Testing SSL KeepAlive messages\n");
+
+ {
+ #ifdef WIN32
+ #error TODO: implement threads on Win32, or this test \
+ will not finish properly
+ #endif
+
+ // bbackupd daemon will try to initialise timers itself
+ Timers::Cleanup();
+
+ // something to diff against (empty file doesn't work)
+ int fd = open("testfiles/TestDir1/spacetest/f1", O_WRONLY);
+ TEST_THAT(fd > 0);
+ char buffer[10000];
+ TEST_THAT(write(fd, buffer, sizeof(buffer)) == sizeof(buffer));
+ TEST_THAT(close(fd) == 0);
+
+ int pid = start_internal_daemon();
+ wait_for_backup_operation();
+ stop_internal_daemon(pid);
+
+ intercept_setup_delay("testfiles/TestDir1/spacetest/f1",
+ 0, 2000, SYS_read, 1);
+ TEST_THAT(unlink("testfiles/bbackupd.log") == 0);
+
+ pid = start_internal_daemon();
+
+ fd = open("testfiles/TestDir1/spacetest/f1", O_WRONLY);
+ TEST_THAT(fd > 0);
+ // write again, to update the file's timestamp
+ TEST_THAT(write(fd, buffer, sizeof(buffer)) == sizeof(buffer));
+ TEST_THAT(close(fd) == 0);
+
+ wait_for_backup_operation();
+ // can't test whether intercept was triggered, because
+ // it's in a different process.
+ // TEST_THAT(intercept_triggered());
+ stop_internal_daemon(pid);
+
+ // check that keepalive was written to logs, and
+ // diff was not aborted, i.e. upload was a diff
+ FileStream fs("testfiles/bbackupd.log", O_RDONLY);
+ IOStreamGetLine reader(fs);
+ bool found1 = false;
+
+ while (!reader.IsEOF())
+ {
+ std::string line;
+ TEST_THAT(reader.GetLine(line));
+ if (line == "Send GetBlockIndexByName(0x3,\"f1\")")
+ {
+ found1 = true;
+ break;
+ }
+ }
+
+ TEST_THAT(found1);
+ if (found1)
+ {
+ std::string line;
+ TEST_THAT(reader.GetLine(line));
+ std::string comp = "Receive Success(0x";
+ TEST_THAT(line.substr(0, comp.size()) == comp);
+ TEST_THAT(reader.GetLine(line));
+ TEST_THAT(line == "Receiving stream, size 124");
+ TEST_THAT(reader.GetLine(line));
+ TEST_THAT(line == "Send GetIsAlive()");
+ TEST_THAT(reader.GetLine(line));
+ TEST_THAT(line == "Receive IsAlive()");
+
+ TEST_THAT(reader.GetLine(line));
+ comp = "Send StoreFile(0x3,";
+ TEST_THAT(line.substr(0, comp.size()) == comp);
+ comp = ",\"f1\")";
+ TEST_THAT(line.substr(line.size() - comp.size())
+ == comp);
+ }
+
+ intercept_setup_delay("testfiles/TestDir1/spacetest/f1",
+ 0, 4000, SYS_read, 1);
+ pid = start_internal_daemon();
+
+ fd = open("testfiles/TestDir1/spacetest/f1", O_WRONLY);
+ TEST_THAT(fd > 0);
+ // write again, to update the file's timestamp
+ TEST_THAT(write(fd, buffer, sizeof(buffer)) == sizeof(buffer));
+ TEST_THAT(close(fd) == 0);
+
+ wait_for_backup_operation();
+ // can't test whether intercept was triggered, because
+ // it's in a different process.
+ // TEST_THAT(intercept_triggered());
+ stop_internal_daemon(pid);
+
+ // check that the diff was aborted, i.e. upload was not a diff
+ found1 = false;
+
+ while (!reader.IsEOF())
+ {
+ std::string line;
+ TEST_THAT(reader.GetLine(line));
+ if (line == "Send GetBlockIndexByName(0x3,\"f1\")")
+ {
+ found1 = true;
+ break;
+ }
+ }
+
+ TEST_THAT(found1);
+ if (found1)
+ {
+ std::string line;
+ TEST_THAT(reader.GetLine(line));
+ std::string comp = "Receive Success(0x";
+ TEST_THAT(line.substr(0, comp.size()) == comp);
+ TEST_THAT(reader.GetLine(line));
+ TEST_THAT(line == "Receiving stream, size 124");
+
+ // delaying for 4 seconds in one step means that
+ // the diff timer and the keepalive timer will
+ // both expire, and the diff timer is honoured first,
+ // so there will be no keepalives.
+
+ TEST_THAT(reader.GetLine(line));
+ comp = "Send StoreFile(0x3,";
+ TEST_THAT(line.substr(0, comp.size()) == comp);
+ comp = ",0x0,\"f1\")";
+ TEST_THAT(line.substr(line.size() - comp.size())
+ == comp);
+ }
+
+ intercept_setup_delay("testfiles/TestDir1/spacetest/f1",
+ 0, 1000, SYS_read, 3);
+ pid = start_internal_daemon();
+
+ fd = open("testfiles/TestDir1/spacetest/f1", O_WRONLY);
+ TEST_THAT(fd > 0);
+ // write again, to update the file's timestamp
+ TEST_THAT(write(fd, buffer, sizeof(buffer)) == sizeof(buffer));
+ TEST_THAT(close(fd) == 0);
+
+ wait_for_backup_operation();
+ // can't test whether intercept was triggered, because
+ // it's in a different process.
+ // TEST_THAT(intercept_triggered());
+ stop_internal_daemon(pid);
+
+ // check that the diff was aborted, i.e. upload was not a diff
+ found1 = false;
+
+ while (!reader.IsEOF())
+ {
+ std::string line;
+ TEST_THAT(reader.GetLine(line));
+ if (line == "Send GetBlockIndexByName(0x3,\"f1\")")
+ {
+ found1 = true;
+ break;
+ }
+ }
+
+ TEST_THAT(found1);
+ if (found1)
+ {
+ std::string line;
+ TEST_THAT(reader.GetLine(line));
+ std::string comp = "Receive Success(0x";
+ TEST_THAT(line.substr(0, comp.size()) == comp);
+ TEST_THAT(reader.GetLine(line));
+ TEST_THAT(line == "Receiving stream, size 124");
+
+ // delaying for 3 seconds in steps of 1 second
+ // means that the keepalive timer will expire 3 times,
+ // and on the 3rd time the diff timer will expire too.
+ // The diff timer is honoured first, so there will be
+ // only two keepalives.
+
+ TEST_THAT(reader.GetLine(line));
+ TEST_THAT(line == "Send GetIsAlive()");
+ TEST_THAT(reader.GetLine(line));
+ TEST_THAT(line == "Receive IsAlive()");
+ TEST_THAT(reader.GetLine(line));
+ TEST_THAT(line == "Send GetIsAlive()");
+ TEST_THAT(reader.GetLine(line));
+ TEST_THAT(line == "Receive IsAlive()");
+
+ TEST_THAT(reader.GetLine(line));
+ comp = "Send StoreFile(0x3,";
+ TEST_THAT(line.substr(0, comp.size()) == comp);
+ comp = ",0x0,\"f1\")";
+ TEST_THAT(line.substr(line.size() - comp.size())
+ == comp);
+ }
- int pid = LaunchServer("../../bin/bbackupd/bbackupd testfiles/bbackupd.conf", "testfiles/bbackupd.pid");
- TEST_THAT(pid != -1 && pid != 0);
- if(pid > 0)
+ intercept_setup_readdir_hook("testfiles/TestDir1/spacetest/d1",
+ readdir_test_hook_1);
+
+ // time for at least two keepalives
+ readdir_stop_time = time(NULL) + 12 + 2;
+
+ pid = start_internal_daemon();
+
+ std::string touchfile =
+ "testfiles/TestDir1/spacetest/d1/touch-me";
+
+ fd = open(touchfile.c_str(), O_CREAT | O_WRONLY);
+ TEST_THAT(fd > 0);
+ // write again, to update the file's timestamp
+ TEST_THAT(write(fd, buffer, sizeof(buffer)) == sizeof(buffer));
+ TEST_THAT(close(fd) == 0);
+
+ wait_for_backup_operation();
+ // can't test whether intercept was triggered, because
+ // it's in a different process.
+ // TEST_THAT(intercept_triggered());
+ stop_internal_daemon(pid);
+
+ // check that keepalives were sent during the dir search
+ found1 = false;
+
+ // skip to next login
+ while (!reader.IsEOF())
+ {
+ std::string line;
+ TEST_THAT(reader.GetLine(line));
+ if (line == "Send ListDirectory(0x3,0xffffffff,0xc,true)")
+ {
+ found1 = true;
+ break;
+ }
+ }
+
+ TEST_THAT(found1);
+ if (found1)
+ {
+ found1 = false;
+
+ while (!reader.IsEOF())
+ {
+ std::string line;
+ TEST_THAT(reader.GetLine(line));
+ if (line == "Send ListDirectory(0x3,0xffffffff,0xc,true)")
+ {
+ found1 = true;
+ break;
+ }
+ }
+ }
+
+ if (found1)
+ {
+ std::string line;
+ TEST_THAT(reader.GetLine(line));
+ TEST_THAT(line == "Receive Success(0x3)");
+ TEST_THAT(reader.GetLine(line));
+ TEST_THAT(line == "Receiving stream, size 425");
+ TEST_THAT(reader.GetLine(line));
+ TEST_THAT(line == "Send GetIsAlive()");
+ TEST_THAT(reader.GetLine(line));
+ TEST_THAT(line == "Receive IsAlive()");
+ TEST_THAT(reader.GetLine(line));
+ TEST_THAT(line == "Send GetIsAlive()");
+ TEST_THAT(reader.GetLine(line));
+ TEST_THAT(line == "Receive IsAlive()");
+ }
+
+ TEST_THAT(unlink(touchfile.c_str()) == 0);
+
+ // restore timers for rest of tests
+ Timers::Init();
+ }
+#endif // PLATFORM_CLIB_FNS_INTERCEPTION_IMPOSSIBLE
+
+ std::string cmd = BBACKUPD + bbackupd_args + " testfiles/bbackupd.conf";
+ bbackupd_pid = LaunchServer(cmd, "testfiles/bbackupd.pid");
+
+ TEST_THAT(bbackupd_pid != -1 && bbackupd_pid != 0);
+
+ ::safe_sleep(1);
+
+ TEST_THAT(ServerIsAlive(bbackupd_pid));
+ TEST_THAT(ServerIsAlive(bbstored_pid));
+ if (!ServerIsAlive(bbackupd_pid)) return 1;
+ if (!ServerIsAlive(bbstored_pid)) return 1;
+
+ if(bbackupd_pid > 0)
{
- ::sleep(1);
- TEST_THAT(ServerIsAlive(pid));
+ printf("\n==== Testing that backup pauses when store is full\n");
- // First, check storage space handling -- wait for file to be uploaded
+ // wait for files to be uploaded
wait_for_backup_operation();
- //TEST_THAT_ABORTONFAIL(::system("../../bin/bbstoreaccounts/bbstoreaccounts -c testfiles/bbstored.conf info 01234567") == 0);
+
// Set limit to something very small
- // About 28 blocks will be used at this point. bbackupd will only pause if the size used is
- // greater than soft limit + 1/3 of (hard - soft). Set small values for limits accordingly.
- TEST_THAT_ABORTONFAIL(::system("../../bin/bbstoreaccounts/bbstoreaccounts -c testfiles/bbstored.conf setlimit 01234567 10B 40B") == 0);
+ // About 28 blocks will be used at this point. bbackupd
+ // will only pause if the size used is greater than
+ // soft limit + 1/3 of (hard - soft). Set small values
+ // for limits accordingly.
+ TEST_THAT_ABORTONFAIL(::system(BBSTOREACCOUNTS " -c "
+ "testfiles/bbstored.conf setlimit 01234567 9B 10B")
+ == 0);
TestRemoteProcessMemLeaks("bbstoreaccounts.memleaks");
// Unpack some more files
- TEST_THAT(::system("gzip -d < testfiles/spacetest2.tgz | ( cd testfiles/TestDir1 && tar xf - )") == 0);
+ #ifdef WIN32
+ TEST_THAT(::system("tar xzvf testfiles/spacetest2.tgz "
+ "-C testfiles/TestDir1") == 0);
+ #else
+ TEST_THAT(::system("gzip -d < testfiles/spacetest2.tgz "
+ "| ( cd testfiles/TestDir1 && tar xf - )") == 0);
+ #endif
+
// Delete a file and a directory
TEST_THAT(::unlink("testfiles/TestDir1/spacetest/d1/f3") == 0);
TEST_THAT(::system("rm -rf testfiles/TestDir1/spacetest/d3/d4") == 0);
wait_for_backup_operation();
// Make sure there are some differences
- int compareReturnValue = ::system("../../bin/bbackupquery/bbackupquery -q -c testfiles/bbackupd.conf -l testfiles/query0a.log \"compare -ac\" quit");
- TEST_THAT(compareReturnValue == 2*256);
+ int compareReturnValue = ::system(BBACKUPQUERY " -q "
+ "-c testfiles/bbackupd.conf "
+ "-l testfiles/query0a.log "
+ "\"compare -acQ\" quit");
+ TEST_RETURN(compareReturnValue, 2);
TestRemoteProcessMemLeaks("bbackupquery.memleaks");
// Put the limit back
- TEST_THAT_ABORTONFAIL(::system("../../bin/bbstoreaccounts/bbstoreaccounts -c testfiles/bbstored.conf setlimit 01234567 1000B 2000B") == 0);
+ TEST_THAT_ABORTONFAIL(::system(BBSTOREACCOUNTS " -c "
+ "testfiles/bbstored.conf setlimit 01234567 "
+ "1000B 2000B") == 0);
TestRemoteProcessMemLeaks("bbstoreaccounts.memleaks");
// Check that the notify script was run
@@ -556,185 +1113,1119 @@ int test_bbackupd()
TEST_THAT(!TestFileExists("testfiles/notifyran.store-full.2"));
// unpack the initial files again
- TEST_THAT(::system("gzip -d < testfiles/test_base.tgz | ( cd testfiles && tar xf - )") == 0);
+ #ifdef WIN32
+ TEST_THAT(::system("tar xzvf testfiles/test_base.tgz "
+ "-C testfiles") == 0);
+ #else
+ TEST_THAT(::system("gzip -d < testfiles/test_base.tgz "
+ "| ( cd testfiles && tar xf - )") == 0);
+ #endif
// wait for it to do it's stuff
wait_for_backup_operation();
- // Check that the contents of the store are the same as the contents
- // of the disc (-a = all, -c = give result in return code)
- compareReturnValue = ::system("../../bin/bbackupquery/bbackupquery -q -c testfiles/bbackupd.conf -l testfiles/query1.log \"compare -ac\" quit");
- TEST_THAT(compareReturnValue == 1*256);
+ // Check that the contents of the store are the same
+ // as the contents of the disc
+ // (-a = all, -c = give result in return code)
+ compareReturnValue = ::system(BBACKUPQUERY " -q "
+ "-c testfiles/bbackupd.conf "
+ "-l testfiles/query1.log "
+ "\"compare -acQ\" quit");
+ TEST_RETURN(compareReturnValue, 1);
+ TestRemoteProcessMemLeaks("bbackupquery.memleaks");
+
+ TEST_THAT(ServerIsAlive(bbackupd_pid));
+ TEST_THAT(ServerIsAlive(bbstored_pid));
+ if (!ServerIsAlive(bbackupd_pid)) return 1;
+ if (!ServerIsAlive(bbstored_pid)) return 1;
+
+
+ printf("\n==== Check that read-only directories and "
+ "their contents can be restored.\n");
+
+ {
+ #ifdef WIN32
+ TEST_THAT(::system("chmod 0555 testfiles/"
+ "TestDir1/x1") == 0);
+ #else
+ TEST_THAT(chmod("testfiles/TestDir1/x1",
+ 0555) == 0);
+ #endif
+
+ wait_for_sync_end(); // too new
+ wait_for_sync_end(); // should be backed up now
+
+ compareReturnValue = ::system(BBACKUPQUERY " "
+ "-c testfiles/bbackupd.conf "
+ "-q \"compare -cEQ Test1 testfiles/TestDir1\" "
+ "quit");
+ TEST_RETURN(compareReturnValue, 1);
+ TestRemoteProcessMemLeaks("bbackupquery.memleaks");
+
+ // check that we can restore it
+ compareReturnValue = ::system(BBACKUPQUERY " "
+ "-c testfiles/bbackupd.conf "
+ "-q \"restore Test1 testfiles/restore1\" "
+ "quit");
+ TEST_RETURN(compareReturnValue, 0);
+ TestRemoteProcessMemLeaks("bbackupquery.memleaks");
+
+ // check that it restored properly
+ compareReturnValue = ::system(BBACKUPQUERY " "
+ "-c testfiles/bbackupd.conf "
+ "-q \"compare -cEQ Test1 testfiles/restore1\" "
+ "quit");
+ TEST_RETURN(compareReturnValue, 1);
+ TestRemoteProcessMemLeaks("bbackupquery.memleaks");
+
+ // put the permissions back to sensible values
+ #ifdef WIN32
+ TEST_THAT(::system("chmod 0755 testfiles/"
+ "TestDir1/x1") == 0);
+ #else
+ TEST_THAT(chmod("testfiles/TestDir1/x1",
+ 0755) == 0);
+ #endif
+
+ }
+
+#ifdef WIN32
+ printf("\n==== Check that filenames in UTF-8 "
+ "can be backed up\n");
+
+ // We have no guarantee that a random Unicode string can be
+ // represented in the user's character set, so we go the
+ // other way, taking three random characters from the
+ // character set and converting them to Unicode.
+ //
+ // We hope that these characters are valid in most
+ // character sets, but they probably are not in multibyte
+ // character sets such as Shift-JIS, GB2312, etc. This test
+ // will probably fail if your system locale is set to
+ // Chinese, Japanese, etc. where one of these character
+ // sets is used by default. You can check the character
+ // set for your system in Control Panel -> Regional
+ // Options -> General -> Language Settings -> Set Default
+ // (System Locale). Because bbackupquery converts from
+ // system locale to UTF-8 via the console code page
+ // (which you can check from the Command Prompt with "chcp")
+ // they must also be valid in your code page (850 for
+ // Western Europe).
+ //
+ // In ISO-8859-1 (Danish locale) they are three Danish
+ // accented characters, which are supported in code page
+ // 850. Depending on your locale, YYMV (your yak may vomit).
+
+ std::string foreignCharsNative("\x91\x9b\x86");
+ std::string foreignCharsUnicode;
+ TEST_THAT(ConvertConsoleToUtf8(foreignCharsNative.c_str(),
+ foreignCharsUnicode));
+
+ std::string basedir("testfiles/TestDir1");
+ std::string dirname("test" + foreignCharsUnicode + "testdir");
+ std::string dirpath(basedir + "/" + dirname);
+ TEST_THAT(mkdir(dirpath.c_str(), 0) == 0);
+
+ std::string filename("test" + foreignCharsUnicode + "testfile");
+ std::string filepath(dirpath + "/" + filename);
+
+ char cwdbuf[1024];
+ TEST_THAT(getcwd(cwdbuf, sizeof(cwdbuf)) == cwdbuf);
+ std::string cwd = cwdbuf;
+
+ // Test that our emulated chdir() works properly
+ // with relative and absolute paths
+ TEST_THAT(::chdir(dirpath.c_str()) == 0);
+ TEST_THAT(::chdir("../../..") == 0);
+ TEST_THAT(::chdir(cwd.c_str()) == 0);
+
+ // Check that it can be converted to the system encoding
+ // (which is what is needed on the command line)
+ std::string systemDirName;
+ TEST_THAT(ConvertEncoding(dirname.c_str(), CP_UTF8,
+ systemDirName, CP_ACP));
+
+ std::string systemFileName;
+ TEST_THAT(ConvertEncoding(filename.c_str(), CP_UTF8,
+ systemFileName, CP_ACP));
+
+ // Check that it can be converted to the console encoding
+ // (which is what we will see in the output)
+ std::string consoleDirName;
+ TEST_THAT(ConvertUtf8ToConsole(dirname.c_str(),
+ consoleDirName));
+
+ std::string consoleFileName;
+ TEST_THAT(ConvertUtf8ToConsole(filename.c_str(),
+ consoleFileName));
+
+ // test that bbackupd will let us lcd into the local
+ // directory using a relative path
+ std::string command = BBACKUPQUERY " -q "
+ "-c testfiles/bbackupd.conf "
+ "\"lcd testfiles/TestDir1/" + systemDirName + "\" "
+ "quit";
+ compareReturnValue = ::system(command.c_str());
+ TEST_RETURN(compareReturnValue, 0);
+
+ // and back out again
+ command = BBACKUPQUERY " -q "
+ "-c testfiles/bbackupd.conf "
+ "\"lcd testfiles/TestDir1/" + systemDirName + "\" "
+ "\"lcd ..\" quit";
+ compareReturnValue = ::system(command.c_str());
+ TEST_RETURN(compareReturnValue, 0);
+
+ // and using an absolute path
+ command = BBACKUPQUERY " -q "
+ "-c testfiles/bbackupd.conf "
+ "\"lcd " + cwd + "/testfiles/TestDir1/" +
+ systemDirName + "\" quit";
+ compareReturnValue = ::system(command.c_str());
+ TEST_RETURN(compareReturnValue, 0);
+
+ // and back out again
+ command = BBACKUPQUERY " -q "
+ "-c testfiles/bbackupd.conf "
+ "\"lcd " + cwd + "/testfiles/TestDir1/" +
+ systemDirName + "\" "
+ "\"lcd ..\" quit";
+ compareReturnValue = ::system(command.c_str());
+ TEST_RETURN(compareReturnValue, 0);
+
+ {
+ FileStream fs(filepath.c_str(), O_CREAT | O_RDWR);
+
+ std::string data("hello world\n");
+ fs.Write(data.c_str(), data.size());
+ TEST_THAT(fs.GetPosition() == 12);
+ fs.Close();
+ }
+
+ wait_for_backup_operation();
+ // Compare to check that the file was uploaded
+ compareReturnValue = ::system(BBACKUPQUERY " -q "
+ "-c testfiles/bbackupd.conf \"compare -acQ\" quit");
+ TEST_RETURN(compareReturnValue, 1);
+ TestRemoteProcessMemLeaks("bbackupquery.memleaks");
+
+ // Check that we can find it in directory listing
+ {
+ SocketStreamTLS conn;
+ conn.Open(context, Socket::TypeINET, "localhost",
+ BOX_PORT_BBSTORED);
+ BackupProtocolClient protocol(conn);
+ protocol.QueryVersion(BACKUP_STORE_SERVER_VERSION);
+ protocol.QueryLogin(0x01234567, 0);
+
+ int64_t rootDirId = BackupProtocolClientListDirectory
+ ::RootDirectory;
+ std::auto_ptr<BackupProtocolClientSuccess> dirreply(
+ protocol.QueryListDirectory(
+ rootDirId, false, 0, false));
+ std::auto_ptr<IOStream> dirstream(
+ protocol.ReceiveStream());
+ BackupStoreDirectory dir;
+ dir.ReadFromStream(*dirstream, protocol.GetTimeout());
+
+ int64_t baseDirId = SearchDir(dir, "Test1");
+ TEST_THAT(baseDirId != 0);
+ dirreply = protocol.QueryListDirectory(baseDirId,
+ false, 0, false);
+ dirstream = protocol.ReceiveStream();
+ dir.ReadFromStream(*dirstream, protocol.GetTimeout());
+
+ int64_t testDirId = SearchDir(dir, dirname.c_str());
+ TEST_THAT(testDirId != 0);
+ dirreply = protocol.QueryListDirectory(testDirId,
+ false, 0, false);
+ dirstream = protocol.ReceiveStream();
+ dir.ReadFromStream(*dirstream, protocol.GetTimeout());
+
+ TEST_THAT(SearchDir(dir, filename.c_str()) != 0);
+ // Log out
+ protocol.QueryFinished();
+ }
+
+
+ // Check that bbackupquery shows the dir in console encoding
+ command = BBACKUPQUERY " -q "
+ "-c testfiles/bbackupd.conf "
+ "-q \"list Test1\" quit";
+ pid_t bbackupquery_pid;
+ std::auto_ptr<IOStream> queryout;
+ queryout = LocalProcessStream(command.c_str(),
+ bbackupquery_pid);
+ TEST_THAT(queryout.get() != NULL);
+ TEST_THAT(bbackupquery_pid != -1);
+
+ IOStreamGetLine reader(*queryout);
+ std::string line;
+ bool found = false;
+ while (!reader.IsEOF())
+ {
+ TEST_THAT(reader.GetLine(line));
+ if (line.find(consoleDirName) != std::string::npos)
+ {
+ found = true;
+ }
+ }
+ TEST_THAT(!(queryout->StreamDataLeft()));
+ TEST_THAT(reader.IsEOF());
+ TEST_THAT(found);
+ queryout->Close();
+
+ // Check that bbackupquery can list the dir when given
+ // on the command line in system encoding, and shows
+ // the file in console encoding
+ command = BBACKUPQUERY " -c testfiles/bbackupd.conf "
+ "-q \"list Test1/" + systemDirName + "\" quit";
+ queryout = LocalProcessStream(command.c_str(),
+ bbackupquery_pid);
+ TEST_THAT(queryout.get() != NULL);
+ TEST_THAT(bbackupquery_pid != -1);
+
+ IOStreamGetLine reader2(*queryout);
+ found = false;
+ while (!reader2.IsEOF())
+ {
+ TEST_THAT(reader2.GetLine(line));
+ if (line.find(consoleFileName) != std::string::npos)
+ {
+ found = true;
+ }
+ }
+ TEST_THAT(!(queryout->StreamDataLeft()));
+ TEST_THAT(reader2.IsEOF());
+ TEST_THAT(found);
+ queryout->Close();
+
+ // Check that bbackupquery can compare the dir when given
+ // on the command line in system encoding.
+ command = BBACKUPQUERY " -c testfiles/bbackupd.conf "
+ "-q \"compare -cEQ Test1/" + systemDirName +
+ " testfiles/TestDir1/" + systemDirName + "\" quit";
+
+ compareReturnValue = ::system(command.c_str());
+ TestRemoteProcessMemLeaks("bbackupquery.memleaks");
+ TEST_RETURN(compareReturnValue, 1);
+
+ // Check that bbackupquery can restore the dir when given
+ // on the command line in system encoding.
+ command = BBACKUPQUERY " -c testfiles/bbackupd.conf "
+ "-q \"restore Test1/" + systemDirName +
+ " testfiles/restore-" + systemDirName + "\" quit";
+
+ compareReturnValue = ::system(command.c_str());
+ TestRemoteProcessMemLeaks("bbackupquery.memleaks");
+ TEST_RETURN(compareReturnValue, 0);
+
+ // Compare to make sure it was restored properly.
+ command = BBACKUPQUERY " -c testfiles/bbackupd.conf "
+ "-q \"compare -cEQ Test1/" + systemDirName +
+ " testfiles/restore-" + systemDirName + "\" quit";
+
+ compareReturnValue = ::system(command.c_str());
TestRemoteProcessMemLeaks("bbackupquery.memleaks");
+ TEST_RETURN(compareReturnValue, 1);
+
+ std::string fileToUnlink = "testfiles/restore-" +
+ dirname + "/" + filename;
+ TEST_THAT(::unlink(fileToUnlink.c_str()) == 0);
+
+ // Check that bbackupquery can get the file when given
+ // on the command line in system encoding.
+ command = BBACKUPQUERY " -c testfiles/bbackupd.conf "
+ "-q \"get Test1/" + systemDirName + "/" +
+ systemFileName + " " + "testfiles/restore-" +
+ systemDirName + "/" + systemFileName + "\" quit";
+
+ compareReturnValue = ::system(command.c_str());
+ TEST_RETURN(compareReturnValue, 0);
+ TestRemoteProcessMemLeaks("bbackupquery.memleaks");
+
+ // And after changing directory to a relative path
+ command = BBACKUPQUERY " -c testfiles/bbackupd.conf -q "
+ "\"lcd testfiles\" "
+ "\"cd Test1/" + systemDirName + "\" " +
+ "\"get " + systemFileName + "\" quit";
+
+ compareReturnValue = ::system(command.c_str());
+ TEST_RETURN(compareReturnValue, 0);
+ TestRemoteProcessMemLeaks("testfiles/bbackupquery.memleaks");
+
+ // cannot overwrite a file that exists, so delete it
+ std::string tmp = "testfiles/" + filename;
+ TEST_THAT(::unlink(tmp.c_str()) == 0);
+
+ // And after changing directory to an absolute path
+ command = BBACKUPQUERY " -c testfiles/bbackupd.conf -q "
+ "\"lcd " + cwd + "/testfiles\" "
+ "\"cd Test1/" + systemDirName + "\" " +
+ "\"get " + systemFileName + "\" quit";
+
+ compareReturnValue = ::system(command.c_str());
+ TEST_RETURN(compareReturnValue, 0);
+ TestRemoteProcessMemLeaks("testfiles/bbackupquery.memleaks");
+
+ // Compare to make sure it was restored properly.
+ // The Get command does not restore attributes, so
+ // we must compare without them (-A) to succeed.
+ command = BBACKUPQUERY " -c testfiles/bbackupd.conf "
+ "-q \"compare -cAEQ Test1/" + systemDirName +
+ " testfiles/restore-" + systemDirName + "\" quit";
+
+ compareReturnValue = ::system(command.c_str());
+ TestRemoteProcessMemLeaks("bbackupquery.memleaks");
+ TEST_RETURN(compareReturnValue, 1);
+
+ // Compare without attributes. This should fail.
+ command = BBACKUPQUERY " -c testfiles/bbackupd.conf "
+ "-q \"compare -cEQ Test1/" + systemDirName +
+ " testfiles/restore-" + systemDirName + "\" quit";
+
+ compareReturnValue = ::system(command.c_str());
+ TestRemoteProcessMemLeaks("bbackupquery.memleaks");
+ TEST_RETURN(compareReturnValue, 2);
+#endif // WIN32
+
+ TEST_THAT(ServerIsAlive(bbackupd_pid));
+ TEST_THAT(ServerIsAlive(bbstored_pid));
+ if (!ServerIsAlive(bbackupd_pid)) return 1;
+ if (!ServerIsAlive(bbstored_pid)) return 1;
+
+ printf("\n==== Check that SyncAllowScript is executed and can "
+ "pause backup\n");
+ fflush(stdout);
+
+ {
+ wait_for_sync_end();
+ // we now have 3 seconds before bbackupd
+ // runs the SyncAllowScript again.
+
+ char* sync_control_file = "testfiles"
+ DIRECTORY_SEPARATOR "syncallowscript.control";
+ int fd = open(sync_control_file,
+ O_CREAT | O_EXCL | O_WRONLY, 0700);
+ if (fd <= 0)
+ {
+ perror(sync_control_file);
+ }
+ TEST_THAT(fd > 0);
- printf("Delete file and update another, create symlink.\n");
+ char* control_string = "10\n";
+ TEST_THAT(write(fd, control_string,
+ strlen(control_string)) ==
+ (int)strlen(control_string));
+ close(fd);
+
+ // this will pause backups, bbackupd will check
+ // every 10 seconds to see if they are allowed again.
+
+ char* new_test_file = "testfiles"
+ DIRECTORY_SEPARATOR "TestDir1"
+ DIRECTORY_SEPARATOR "Added_During_Pause";
+ fd = open(new_test_file,
+ O_CREAT | O_EXCL | O_WRONLY, 0700);
+ if (fd <= 0)
+ {
+ perror(new_test_file);
+ }
+ TEST_THAT(fd > 0);
+ close(fd);
+
+ struct stat st;
+
+ // next poll should happen within the next
+ // 5 seconds (normally about 3 seconds)
+
+ safe_sleep(1); // 2 seconds before
+ TEST_THAT(stat("testfiles" DIRECTORY_SEPARATOR
+ "syncallowscript.notifyran.1", &st) != 0);
+ safe_sleep(4); // 2 seconds after
+ TEST_THAT(stat("testfiles" DIRECTORY_SEPARATOR
+ "syncallowscript.notifyran.1", &st) == 0);
+ TEST_THAT(stat("testfiles" DIRECTORY_SEPARATOR
+ "syncallowscript.notifyran.2", &st) != 0);
+
+ // next poll should happen within the next
+ // 10 seconds (normally about 8 seconds)
+
+ safe_sleep(6); // 2 seconds before
+ TEST_THAT(stat("testfiles" DIRECTORY_SEPARATOR
+ "syncallowscript.notifyran.2", &st) != 0);
+ safe_sleep(4); // 2 seconds after
+ TEST_THAT(stat("testfiles" DIRECTORY_SEPARATOR
+ "syncallowscript.notifyran.2", &st) == 0);
+
+ // check that no backup has run (compare fails)
+ compareReturnValue = ::system(BBACKUPQUERY " -q "
+ "-c testfiles/bbackupd.conf "
+ "-l testfiles/query3.log "
+ "\"compare -acQ\" quit");
+ TEST_RETURN(compareReturnValue, 2);
+ TestRemoteProcessMemLeaks("bbackupquery.memleaks");
+
+ long start_time = time(NULL);
+ TEST_THAT(unlink(sync_control_file) == 0);
+ wait_for_sync_start();
+ long end_time = time(NULL);
+
+ long wait_time = end_time - start_time + 2;
+ // should be about 10 seconds
+ printf("Waited for %ld seconds, should have been %s",
+ wait_time, control_string);
+ TEST_THAT(wait_time >= 8);
+ TEST_THAT(wait_time <= 12);
+
+ wait_for_sync_end();
+ // check that backup has run (compare succeeds)
+ compareReturnValue = ::system(BBACKUPQUERY " -q "
+ "-c testfiles/bbackupd.conf "
+ "-l testfiles/query3a.log "
+ "\"compare -acQ\" quit");
+ TEST_RETURN(compareReturnValue, 1);
+ TestRemoteProcessMemLeaks("bbackupquery.memleaks");
+
+ if (failures > 0)
+ {
+ // stop early to make debugging easier
+ return 1;
+ }
+ }
+
+ TEST_THAT(ServerIsAlive(bbackupd_pid));
+ TEST_THAT(ServerIsAlive(bbstored_pid));
+ if (!ServerIsAlive(bbackupd_pid)) return 1;
+ if (!ServerIsAlive(bbstored_pid)) return 1;
+
+ printf("\n==== Delete file and update another, "
+ "create symlink.\n");
// Delete a file
TEST_THAT(::unlink("testfiles/TestDir1/x1/dsfdsfs98.fd") == 0);
- // New symlink
- TEST_THAT(::symlink("does-not-exist", "testfiles/TestDir1/symlink-to-dir") == 0);
-
+
+ #ifndef WIN32
+ // New symlink
+ TEST_THAT(::symlink("does-not-exist",
+ "testfiles/TestDir1/symlink-to-dir") == 0);
+ #endif
+
// Update a file (will be uploaded as a diff)
{
- // Check that the file is over the diffing threshold in the bbackupd.conf file
- TEST_THAT(TestGetFileSize("testfiles/TestDir1/f45.df") > 1024);
+ // Check that the file is over the diffing
+ // threshold in the bbackupd.conf file
+ TEST_THAT(TestGetFileSize("testfiles/TestDir1/f45.df")
+ > 1024);
// Add a bit to the end
FILE *f = ::fopen("testfiles/TestDir1/f45.df", "a");
TEST_THAT(f != 0);
::fprintf(f, "EXTRA STUFF");
::fclose(f);
- TEST_THAT(TestGetFileSize("testfiles/TestDir1/f45.df") > 1024);
+ TEST_THAT(TestGetFileSize("testfiles/TestDir1/f45.df")
+ > 1024);
}
// wait for backup daemon to do it's stuff, and compare again
wait_for_backup_operation();
- compareReturnValue = ::system("../../bin/bbackupquery/bbackupquery -q -c testfiles/bbackupd.conf -l testfiles/query2.log \"compare -ac\" quit");
- TEST_THAT(compareReturnValue == 1*256);
+ compareReturnValue = ::system(BBACKUPQUERY " -q "
+ "-c testfiles/bbackupd.conf "
+ "-l testfiles/query2.log "
+ "\"compare -acQ\" quit");
+ TEST_RETURN(compareReturnValue, 1);
TestRemoteProcessMemLeaks("bbackupquery.memleaks");
+
// Try a quick compare, just for fun
- compareReturnValue = ::system("../../bin/bbackupquery/bbackupquery -q -c testfiles/bbackupd.conf -l testfiles/query2q.log \"compare -acq\" quit");
- TEST_THAT(compareReturnValue == 1*256);
+ compareReturnValue = ::system(BBACKUPQUERY " -q "
+ "-c testfiles/bbackupd.conf "
+ "-l testfiles/query2q.log "
+ "\"compare -acqQ\" quit");
+ TEST_RETURN(compareReturnValue, 1);
TestRemoteProcessMemLeaks("bbackupquery.memleaks");
+ TEST_THAT(ServerIsAlive(bbackupd_pid));
+ TEST_THAT(ServerIsAlive(bbstored_pid));
+ if (!ServerIsAlive(bbackupd_pid)) return 1;
+ if (!ServerIsAlive(bbstored_pid)) return 1;
+
+ // Check that store errors are reported neatly
+ printf("\n==== Create store error\n");
+ TEST_THAT(::rename("testfiles/0_0/backup/01234567/info.rf",
+ "testfiles/0_0/backup/01234567/info.rf.bak") == 0);
+ TEST_THAT(::rename("testfiles/0_1/backup/01234567/info.rf",
+ "testfiles/0_1/backup/01234567/info.rf.bak") == 0);
+ TEST_THAT(::rename("testfiles/0_2/backup/01234567/info.rf",
+ "testfiles/0_2/backup/01234567/info.rf.bak") == 0);
+ // Create a file to trigger an upload
+ {
+ int fd1 = open("testfiles/TestDir1/force-upload",
+ O_CREAT | O_EXCL | O_WRONLY, 0700);
+ TEST_THAT(fd1 > 0);
+ TEST_THAT(write(fd1, "just do it", 10) == 10);
+ TEST_THAT(close(fd1) == 0);
+ wait_for_backup_operation(4);
+ }
+ // Wait and test...
+ wait_for_backup_operation();
+ // Check that it was reported correctly
+ TEST_THAT(TestFileExists("testfiles/notifyran.backup-error.1"));
+ // Check that the error was only reported once
+ TEST_THAT(!TestFileExists("testfiles/notifyran.backup-error.2"));
+ // Fix the store
+ TEST_THAT(::rename("testfiles/0_0/backup/01234567/info.rf.bak",
+ "testfiles/0_0/backup/01234567/info.rf") == 0);
+ TEST_THAT(::rename("testfiles/0_1/backup/01234567/info.rf.bak",
+ "testfiles/0_1/backup/01234567/info.rf") == 0);
+ TEST_THAT(::rename("testfiles/0_2/backup/01234567/info.rf.bak",
+ "testfiles/0_2/backup/01234567/info.rf") == 0);
+
+ // Check that we DO get errors on compare
+ compareReturnValue = ::system(BBACKUPQUERY " -q "
+ "-c testfiles/bbackupd.conf "
+ "-l testfiles/query3b.log "
+ "\"compare -acQ\" quit");
+ TEST_RETURN(compareReturnValue, 2);
+ TestRemoteProcessMemLeaks("bbackupquery.memleaks");
+
+ TEST_THAT(ServerIsAlive(bbackupd_pid));
+ TEST_THAT(ServerIsAlive(bbstored_pid));
+ if (!ServerIsAlive(bbackupd_pid)) return 1;
+ if (!ServerIsAlive(bbstored_pid)) return 1;
+
+ // Wait until bbackupd recovers from the exception
+ wait_for_backup_operation(100);
+
+ // Ensure that the force-upload file gets uploaded,
+ // meaning that bbackupd recovered
+ sync_and_wait();
+
+ // Check that it did get uploaded, and we have no more errors
+ compareReturnValue = ::system(BBACKUPQUERY " -q "
+ "-c testfiles/bbackupd.conf "
+ "-l testfiles/query3b.log "
+ "\"compare -acQ\" quit");
+ TEST_RETURN(compareReturnValue, 1);
+ TestRemoteProcessMemLeaks("bbackupquery.memleaks");
+
+ TEST_THAT(ServerIsAlive(bbackupd_pid));
+ TEST_THAT(ServerIsAlive(bbstored_pid));
+ if (!ServerIsAlive(bbackupd_pid)) return 1;
+ if (!ServerIsAlive(bbstored_pid)) return 1;
+
// Bad case: delete a file/symlink, replace it with a directory
- printf("Replace symlink with directory, add new directory\n");
- TEST_THAT(::unlink("testfiles/TestDir1/symlink-to-dir") == 0);
- TEST_THAT(::mkdir("testfiles/TestDir1/symlink-to-dir", 0755) == 0);
- TEST_THAT(::mkdir("testfiles/TestDir1/x1/dir-to-file", 0755) == 0);
- // NOTE: create a file within the directory to avoid deletion by the housekeeping process later
- TEST_THAT(::symlink("does-not-exist", "testfiles/TestDir1/x1/dir-to-file/contents") == 0);
+ printf("\n==== Replace symlink with directory, "
+ "add new directory\n");
+
+ #ifndef WIN32
+ TEST_THAT(::unlink("testfiles/TestDir1/symlink-to-dir")
+ == 0);
+ #endif
+
+ TEST_THAT(::mkdir("testfiles/TestDir1/symlink-to-dir", 0755)
+ == 0);
+ TEST_THAT(::mkdir("testfiles/TestDir1/x1/dir-to-file", 0755)
+ == 0);
+
+ // NOTE: create a file within the directory to
+ // avoid deletion by the housekeeping process later
+
+ #ifndef WIN32
+ TEST_THAT(::symlink("does-not-exist",
+ "testfiles/TestDir1/x1/dir-to-file/contents")
+ == 0);
+ #endif
+
wait_for_backup_operation();
- compareReturnValue = ::system("../../bin/bbackupquery/bbackupquery -q -c testfiles/bbackupd.conf -l testfiles/query3s.log \"compare -ac\" quit");
- TEST_THAT(compareReturnValue == 1*256);
+ compareReturnValue = ::system(BBACKUPQUERY " -q "
+ "-c testfiles/bbackupd.conf "
+ "-l testfiles/query3c.log "
+ "\"compare -acQ\" quit");
+ TEST_RETURN(compareReturnValue, 1);
TestRemoteProcessMemLeaks("bbackupquery.memleaks");
+ TEST_THAT(ServerIsAlive(bbackupd_pid));
+ TEST_THAT(ServerIsAlive(bbstored_pid));
+ if (!ServerIsAlive(bbackupd_pid)) return 1;
+ if (!ServerIsAlive(bbstored_pid)) return 1;
+
// And the inverse, replace a directory with a file/symlink
- printf("Replace directory with symlink\n");
- TEST_THAT(::unlink("testfiles/TestDir1/x1/dir-to-file/contents") == 0);
+ printf("\n==== Replace directory with symlink\n");
+
+ #ifndef WIN32
+ TEST_THAT(::unlink("testfiles/TestDir1/x1/dir-to-file"
+ "/contents") == 0);
+ #endif
+
TEST_THAT(::rmdir("testfiles/TestDir1/x1/dir-to-file") == 0);
- TEST_THAT(::symlink("does-not-exist", "testfiles/TestDir1/x1/dir-to-file") == 0);
+
+ #ifndef WIN32
+ TEST_THAT(::symlink("does-not-exist",
+ "testfiles/TestDir1/x1/dir-to-file") == 0);
+ #endif
+
wait_for_backup_operation();
- compareReturnValue = ::system("../../bin/bbackupquery/bbackupquery -q -c testfiles/bbackupd.conf -l testfiles/query3s.log \"compare -ac\" quit");
- TEST_THAT(compareReturnValue == 1*256);
+ compareReturnValue = ::system(BBACKUPQUERY " -q "
+ "-c testfiles/bbackupd.conf "
+ "-l testfiles/query3d.log "
+ "\"compare -acQ\" quit");
+ TEST_RETURN(compareReturnValue, 1);
TestRemoteProcessMemLeaks("bbackupquery.memleaks");
+ TEST_THAT(ServerIsAlive(bbackupd_pid));
+ TEST_THAT(ServerIsAlive(bbstored_pid));
+ if (!ServerIsAlive(bbackupd_pid)) return 1;
+ if (!ServerIsAlive(bbstored_pid)) return 1;
+
// And then, put it back to how it was before.
- printf("Replace symlink with directory (which was a symlink)\n");
- TEST_THAT(::unlink("testfiles/TestDir1/x1/dir-to-file") == 0);
- TEST_THAT(::mkdir("testfiles/TestDir1/x1/dir-to-file", 0755) == 0);
- TEST_THAT(::symlink("does-not-exist", "testfiles/TestDir1/x1/dir-to-file/contents2") == 0);
+ printf("\n==== Replace symlink with directory "
+ "(which was a symlink)\n");
+
+ #ifndef WIN32
+ TEST_THAT(::unlink("testfiles/TestDir1/x1"
+ "/dir-to-file") == 0);
+ #endif
+
+ TEST_THAT(::mkdir("testfiles/TestDir1/x1/dir-to-file",
+ 0755) == 0);
+
+ #ifndef WIN32
+ TEST_THAT(::symlink("does-not-exist",
+ "testfiles/TestDir1/x1/dir-to-file/contents2")
+ == 0);
+ #endif
+
wait_for_backup_operation();
- compareReturnValue = ::system("../../bin/bbackupquery/bbackupquery -q -c testfiles/bbackupd.conf -l testfiles/query3s.log \"compare -ac\" quit");
- TEST_THAT(compareReturnValue == 1*256);
+ compareReturnValue = ::system(BBACKUPQUERY " -q "
+ "-c testfiles/bbackupd.conf "
+ "-l testfiles/query3e.log "
+ "\"compare -acQ\" quit");
+ TEST_RETURN(compareReturnValue, 1);
TestRemoteProcessMemLeaks("bbackupquery.memleaks");
- // And finally, put it back to how it was before it was put back to how it was before
- // This gets lots of nasty things in the store with directories over other old directories.
- printf("Put it all back to how it was\n");
- TEST_THAT(::unlink("testfiles/TestDir1/x1/dir-to-file/contents2") == 0);
+ TEST_THAT(ServerIsAlive(bbackupd_pid));
+ TEST_THAT(ServerIsAlive(bbstored_pid));
+ if (!ServerIsAlive(bbackupd_pid)) return 1;
+ if (!ServerIsAlive(bbstored_pid)) return 1;
+
+ // And finally, put it back to how it was before
+ // it was put back to how it was before
+ // This gets lots of nasty things in the store with
+ // directories over other old directories.
+ printf("\n==== Put it all back to how it was\n");
+
+ #ifndef WIN32
+ TEST_THAT(::unlink("testfiles/TestDir1/x1/dir-to-file"
+ "/contents2") == 0);
+ #endif
+
TEST_THAT(::rmdir("testfiles/TestDir1/x1/dir-to-file") == 0);
- TEST_THAT(::symlink("does-not-exist", "testfiles/TestDir1/x1/dir-to-file") == 0);
+
+ #ifndef WIN32
+ TEST_THAT(::symlink("does-not-exist",
+ "testfiles/TestDir1/x1/dir-to-file") == 0);
+ #endif
+
+ wait_for_backup_operation();
+ compareReturnValue = ::system(BBACKUPQUERY " -q "
+ "-c testfiles/bbackupd.conf "
+ "-l testfiles/query3f.log "
+ "\"compare -acQ\" quit");
+ TEST_RETURN(compareReturnValue, 1);
+ TestRemoteProcessMemLeaks("bbackupquery.memleaks");
+
+ TEST_THAT(ServerIsAlive(bbackupd_pid));
+ TEST_THAT(ServerIsAlive(bbstored_pid));
+ if (!ServerIsAlive(bbackupd_pid)) return 1;
+ if (!ServerIsAlive(bbstored_pid)) return 1;
+
+ // rename an untracked file over an
+ // existing untracked file
+ printf("\n==== Rename over existing untracked file\n");
+ int fd1 = open("testfiles/TestDir1/untracked-1",
+ O_CREAT | O_EXCL | O_WRONLY, 0700);
+ int fd2 = open("testfiles/TestDir1/untracked-2",
+ O_CREAT | O_EXCL | O_WRONLY, 0700);
+ TEST_THAT(fd1 > 0);
+ TEST_THAT(fd2 > 0);
+ TEST_THAT(write(fd1, "hello", 5) == 5);
+ TEST_THAT(close(fd1) == 0);
+ safe_sleep(1);
+ TEST_THAT(write(fd2, "world", 5) == 5);
+ TEST_THAT(close(fd2) == 0);
+ TEST_THAT(TestFileExists("testfiles/TestDir1/untracked-1"));
+ TEST_THAT(TestFileExists("testfiles/TestDir1/untracked-2"));
+ wait_for_operation(5);
+ // back up both files
wait_for_backup_operation();
- compareReturnValue = ::system("../../bin/bbackupquery/bbackupquery -q -c testfiles/bbackupd.conf -l testfiles/query3s.log \"compare -ac\" quit");
- TEST_THAT(compareReturnValue == 1*256);
+ compareReturnValue = ::system(BBACKUPQUERY " -q "
+ "-c testfiles/bbackupd.conf "
+ "-l testfiles/query3g.log "
+ "\"compare -acQ\" quit");
+ TEST_RETURN(compareReturnValue, 1);
TestRemoteProcessMemLeaks("bbackupquery.memleaks");
- // case which went wrong: rename a tracked file over a deleted file
- printf("Rename an existing file over a deleted file\n");
- TEST_THAT(::rename("testfiles/TestDir1/df9834.dsf", "testfiles/TestDir1/x1/dsfdsfs98.fd") == 0);
+ #ifdef WIN32
+ TEST_THAT(::unlink("testfiles/TestDir1/untracked-2")
+ == 0);
+ #endif
+
+ TEST_THAT(::rename("testfiles/TestDir1/untracked-1",
+ "testfiles/TestDir1/untracked-2") == 0);
+ TEST_THAT(!TestFileExists("testfiles/TestDir1/untracked-1"));
+ TEST_THAT( TestFileExists("testfiles/TestDir1/untracked-2"));
+ wait_for_backup_operation();
+ compareReturnValue = ::system(BBACKUPQUERY " -q "
+ "-c testfiles/bbackupd.conf "
+ "-l testfiles/query3g.log "
+ "\"compare -acQ\" quit");
+ TEST_RETURN(compareReturnValue, 1);
+ TestRemoteProcessMemLeaks("bbackupquery.memleaks");
+
+ TEST_THAT(ServerIsAlive(bbackupd_pid));
+ TEST_THAT(ServerIsAlive(bbstored_pid));
+ if (!ServerIsAlive(bbackupd_pid)) return 1;
+ if (!ServerIsAlive(bbstored_pid)) return 1;
+
+ // case which went wrong: rename a tracked file over an
+ // existing tracked file
+ printf("\n==== Rename over existing tracked file\n");
+ fd1 = open("testfiles/TestDir1/tracked-1",
+ O_CREAT | O_EXCL | O_WRONLY, 0700);
+ fd2 = open("testfiles/TestDir1/tracked-2",
+ O_CREAT | O_EXCL | O_WRONLY, 0700);
+ TEST_THAT(fd1 > 0);
+ TEST_THAT(fd2 > 0);
+ char buffer[1024];
+ TEST_THAT(write(fd1, "hello", 5) == 5);
+ TEST_THAT(write(fd1, buffer, sizeof(buffer)) == sizeof(buffer));
+ TEST_THAT(close(fd1) == 0);
+ safe_sleep(1);
+ TEST_THAT(write(fd2, "world", 5) == 5);
+ TEST_THAT(write(fd2, buffer, sizeof(buffer)) == sizeof(buffer));
+ TEST_THAT(close(fd2) == 0);
+ TEST_THAT(TestFileExists("testfiles/TestDir1/tracked-1"));
+ TEST_THAT(TestFileExists("testfiles/TestDir1/tracked-2"));
+ wait_for_operation(5);
+ // back up both files
+ wait_for_backup_operation();
+ compareReturnValue = ::system(BBACKUPQUERY " -q "
+ "-c testfiles/bbackupd.conf "
+ "-l testfiles/query3h.log "
+ "\"compare -acQ\" quit");
+ TEST_RETURN(compareReturnValue, 1);
+ TestRemoteProcessMemLeaks("bbackupquery.memleaks");
+
+ #ifdef WIN32
+ TEST_THAT(::unlink("testfiles/TestDir1/tracked-2")
+ == 0);
+ #endif
+
+ TEST_THAT(::rename("testfiles/TestDir1/tracked-1",
+ "testfiles/TestDir1/tracked-2") == 0);
+ TEST_THAT(!TestFileExists("testfiles/TestDir1/tracked-1"));
+ TEST_THAT( TestFileExists("testfiles/TestDir1/tracked-2"));
wait_for_backup_operation();
- compareReturnValue = ::system("../../bin/bbackupquery/bbackupquery -q -c testfiles/bbackupd.conf -l testfiles/query3s.log \"compare -ac\" quit");
- TEST_THAT(compareReturnValue == 1*256);
+ compareReturnValue = ::system(BBACKUPQUERY " -q "
+ "-c testfiles/bbackupd.conf "
+ "-l testfiles/query3i.log "
+ "\"compare -acQ\" quit");
+ TEST_RETURN(compareReturnValue, 1);
TestRemoteProcessMemLeaks("bbackupquery.memleaks");
+
+ TEST_THAT(ServerIsAlive(bbackupd_pid));
+ TEST_THAT(ServerIsAlive(bbstored_pid));
+ if (!ServerIsAlive(bbackupd_pid)) return 1;
+ if (!ServerIsAlive(bbstored_pid)) return 1;
+
+ // case which went wrong: rename a tracked file
+ // over a deleted file
+ printf("\n==== Rename an existing file over a deleted file\n");
+ TEST_THAT(!TestFileExists("testfiles/TestDir1/x1/dsfdsfs98.fd"));
+ TEST_THAT(::rename("testfiles/TestDir1/df9834.dsf",
+ "testfiles/TestDir1/x1/dsfdsfs98.fd") == 0);
- printf("Add files with old times, update attributes of one to latest time\n");
+ wait_for_backup_operation();
+ compareReturnValue = ::system(BBACKUPQUERY " -q "
+ "-c testfiles/bbackupd.conf "
+ "-l testfiles/query3j.log "
+ "\"compare -acQ\" quit");
+ TEST_RETURN(compareReturnValue, 1);
+ TestRemoteProcessMemLeaks("bbackupquery.memleaks");
+
+ TEST_THAT(ServerIsAlive(bbackupd_pid));
+ TEST_THAT(ServerIsAlive(bbstored_pid));
+ if (!ServerIsAlive(bbackupd_pid)) return 1;
+ if (!ServerIsAlive(bbstored_pid)) return 1;
+
+ printf("\n==== Add files with old times, update "
+ "attributes of one to latest time\n");
// Move that file back
- TEST_THAT(::rename("testfiles/TestDir1/x1/dsfdsfs98.fd", "testfiles/TestDir1/df9834.dsf") == 0);
+ TEST_THAT(::rename("testfiles/TestDir1/x1/dsfdsfs98.fd",
+ "testfiles/TestDir1/df9834.dsf") == 0);
// Add some more files
- // Because the 'm' option is not used, these files will look very old to the daemon.
+ // Because the 'm' option is not used, these files will
+ // look very old to the daemon.
// Lucky it'll upload them then!
- TEST_THAT(::system("gzip -d < testfiles/test2.tgz | ( cd testfiles && tar xf - )") == 0);
- ::chmod("testfiles/TestDir1/sub23/dhsfdss/blf.h", 0415);
+ #ifdef WIN32
+ TEST_THAT(::system("tar xzvf testfiles/test2.tgz "
+ "-C testfiles") == 0);
+ #else
+ TEST_THAT(::system("gzip -d < testfiles/test2.tgz "
+ "| ( cd testfiles && tar xf - )") == 0);
+ ::chmod("testfiles/TestDir1/sub23/dhsfdss/blf.h", 0415);
+ #endif
// Wait and test
wait_for_backup_operation();
- compareReturnValue = ::system("../../bin/bbackupquery/bbackupquery -q -c testfiles/bbackupd.conf -l testfiles/query3.log \"compare -ac\" quit");
- TEST_THAT(compareReturnValue == 1*256);
+ compareReturnValue = ::system(BBACKUPQUERY " -q "
+ "-c testfiles/bbackupd.conf "
+ "-l testfiles/query3k.log "
+ "\"compare -acQ\" quit");
+ TEST_RETURN(compareReturnValue, 1);
TestRemoteProcessMemLeaks("bbackupquery.memleaks");
- // Check that modifying files with old timestamps still get added
- printf("Modify existing file, but change timestamp to rather old\n");
- // Time critical, so sync
- TEST_THAT(::system("../../bin/bbackupctl/bbackupctl -q -c testfiles/bbackupd.conf wait-for-sync") == 0);
- TestRemoteProcessMemLeaks("bbackupctl.memleaks");
- // Then wait a second, to make sure the scan is complete
- ::sleep(1);
+ TEST_THAT(ServerIsAlive(bbackupd_pid));
+ TEST_THAT(ServerIsAlive(bbstored_pid));
+ if (!ServerIsAlive(bbackupd_pid)) return 1;
+ if (!ServerIsAlive(bbstored_pid)) return 1;
+
+ // Check that modifying files with old timestamps
+ // still get added
+ printf("\n==== Modify existing file, but change timestamp "
+ "to rather old\n");
+ wait_for_sync_end();
+
// Then modify an existing file
{
- chmod("testfiles/TestDir1/sub23/rand.h", 0777); // in the archive, it's read only
- FILE *f = fopen("testfiles/TestDir1/sub23/rand.h", "w+");
+ // in the archive, it's read only
+ #ifdef WIN32
+ TEST_THAT(::system("chmod 0777 testfiles"
+ "/TestDir1/sub23/rand.h") == 0);
+ #else
+ TEST_THAT(chmod("testfiles/TestDir1/sub23"
+ "/rand.h", 0777) == 0);
+ #endif
+
+ FILE *f = fopen("testfiles/TestDir1/sub23/rand.h",
+ "w+");
+
+ if (f == 0)
+ {
+ perror("Failed to open");
+ }
+
TEST_THAT(f != 0);
- fprintf(f, "MODIFIED!\n");
- fclose(f);
+
+ if (f != 0)
+ {
+ fprintf(f, "MODIFIED!\n");
+ fclose(f);
+ }
+
// and then move the time backwards!
struct timeval times[2];
- BoxTimeToTimeval(SecondsToBoxTime((time_t)(365*24*60*60)), times[1]);
+ BoxTimeToTimeval(SecondsToBoxTime(
+ (time_t)(365*24*60*60)), times[1]);
times[0] = times[1];
- TEST_THAT(::utimes("testfiles/TestDir1/sub23/rand.h", times) == 0);
+ TEST_THAT(::utimes("testfiles/TestDir1/sub23/rand.h",
+ times) == 0);
}
+
// Wait and test
- wait_for_backup_operation();
- compareReturnValue = ::system("../../bin/bbackupquery/bbackupquery -q -c testfiles/bbackupd.conf -l testfiles/query3e.log \"compare -ac\" quit");
- TEST_THAT(compareReturnValue == 1*256);
+ wait_for_sync_end(); // files too new
+ wait_for_sync_end(); // should (not) be backed up this time
+
+ compareReturnValue = ::system(BBACKUPQUERY " -q "
+ "-c testfiles/bbackupd.conf "
+ "-l testfiles/query3l.log "
+ "\"compare -acQ\" quit");
+ TEST_RETURN(compareReturnValue, 1);
TestRemoteProcessMemLeaks("bbackupquery.memleaks");
+ TEST_THAT(ServerIsAlive(bbackupd_pid));
+ TEST_THAT(ServerIsAlive(bbstored_pid));
+ if (!ServerIsAlive(bbackupd_pid)) return 1;
+ if (!ServerIsAlive(bbstored_pid)) return 1;
+
// Add some files and directories which are marked as excluded
- printf("Add files and dirs for exclusion test\n");
- TEST_THAT(::system("gzip -d < testfiles/testexclude.tgz | ( cd testfiles && tar xf - )") == 0);
+ printf("\n==== Add files and dirs for exclusion test\n");
+ #ifdef WIN32
+ TEST_THAT(::system("tar xzvf testfiles/testexclude.tgz "
+ "-C testfiles") == 0);
+ #else
+ TEST_THAT(::system("gzip -d < "
+ "testfiles/testexclude.tgz "
+ "| ( cd testfiles && tar xf - )") == 0);
+ #endif
+
// Wait and test
- wait_for_backup_operation();
- compareReturnValue = ::system("../../bin/bbackupquery/bbackupquery -q -c testfiles/bbackupd.conf -l testfiles/query3c.log \"compare -ac\" quit");
- TEST_THAT(compareReturnValue == 1*256);
+ wait_for_sync_end();
+ wait_for_sync_end();
+
+ // compare with exclusions, should not find differences
+ compareReturnValue = ::system(BBACKUPQUERY " -q "
+ "-c testfiles/bbackupd.conf "
+ "-l testfiles/query3m.log "
+ "\"compare -acQ\" quit");
+ TEST_RETURN(compareReturnValue, 1);
TestRemoteProcessMemLeaks("bbackupquery.memleaks");
- compareReturnValue = ::system("../../bin/bbackupquery/bbackupquery -q -c testfiles/bbackupd.conf -l testfiles/query3d.log \"compare -acE\" quit");
- TEST_THAT(compareReturnValue == 2*256); // should find differences
+
+ // compare without exclusions, should find differences
+ compareReturnValue = ::system(BBACKUPQUERY " -q "
+ "-c testfiles/bbackupd.conf "
+ "-l testfiles/query3n.log "
+ "\"compare -acEQ\" quit");
+ TEST_RETURN(compareReturnValue, 2);
TestRemoteProcessMemLeaks("bbackupquery.memleaks");
+ TEST_THAT(ServerIsAlive(bbackupd_pid));
+ TEST_THAT(ServerIsAlive(bbstored_pid));
+ if (!ServerIsAlive(bbackupd_pid)) return 1;
+ if (!ServerIsAlive(bbstored_pid)) return 1;
+
+ // check that the excluded files did not make it
+ // into the store, and the included files did
+ printf("\n==== Check that exclude/alwaysinclude commands "
+ "actually work\n");
+
+ {
+ std::string errs;
+ std::auto_ptr<Configuration> config(
+ Configuration::LoadAndVerify(
+ "testfiles/bbackupd.conf",
+ &BackupDaemonConfigVerify, errs));
+ Configuration& conf(*config);
+ SSLLib::Initialise();
+ TLSContext tlsContext;
+ std::string certFile(conf.GetKeyValue("CertificateFile"));
+ std::string keyFile (conf.GetKeyValue("PrivateKeyFile"));
+ std::string caFile (conf.GetKeyValue("TrustedCAsFile"));
+ tlsContext.Initialise(false, certFile.c_str(),
+ keyFile.c_str(), caFile.c_str());
+ BackupClientCryptoKeys_Setup(
+ conf.GetKeyValue("KeysFile").c_str());
+ SocketStreamTLS socket;
+ socket.Open(tlsContext, Socket::TypeINET,
+ conf.GetKeyValue("StoreHostname").c_str(),
+ BOX_PORT_BBSTORED);
+ BackupProtocolClient connection(socket);
+ connection.Handshake();
+ std::auto_ptr<BackupProtocolClientVersion>
+ serverVersion(connection.QueryVersion(
+ BACKUP_STORE_SERVER_VERSION));
+ if(serverVersion->GetVersion() !=
+ BACKUP_STORE_SERVER_VERSION)
+ {
+ THROW_EXCEPTION(BackupStoreException,
+ WrongServerVersion);
+ }
+ connection.QueryLogin(
+ conf.GetKeyValueInt("AccountNumber"),
+ BackupProtocolClientLogin::Flags_ReadOnly);
+
+ int64_t rootDirId = BackupProtocolClientListDirectory
+ ::RootDirectory;
+ std::auto_ptr<BackupProtocolClientSuccess> dirreply(
+ connection.QueryListDirectory(
+ rootDirId, false, 0, false));
+ std::auto_ptr<IOStream> dirstream(
+ connection.ReceiveStream());
+ BackupStoreDirectory dir;
+ dir.ReadFromStream(*dirstream, connection.GetTimeout());
+
+ int64_t testDirId = SearchDir(dir, "Test1");
+ TEST_THAT(testDirId != 0);
+ dirreply = connection.QueryListDirectory(testDirId, false, 0, false);
+ dirstream = connection.ReceiveStream();
+ dir.ReadFromStream(*dirstream, connection.GetTimeout());
+
+ TEST_THAT(!SearchDir(dir, "excluded_1"));
+ TEST_THAT(!SearchDir(dir, "excluded_2"));
+ TEST_THAT(!SearchDir(dir, "exclude_dir"));
+ TEST_THAT(!SearchDir(dir, "exclude_dir_2"));
+ // xx_not_this_dir_22 should not be excluded by
+ // ExcludeDirsRegex, because it's a file
+ TEST_THAT(SearchDir (dir, "xx_not_this_dir_22"));
+ TEST_THAT(!SearchDir(dir, "zEXCLUDEu"));
+ TEST_THAT(SearchDir (dir, "dont.excludethis"));
+ TEST_THAT(SearchDir (dir, "xx_not_this_dir_ALWAYSINCLUDE"));
+
+ int64_t sub23id = SearchDir(dir, "sub23");
+ TEST_THAT(sub23id != 0);
+ dirreply = connection.QueryListDirectory(sub23id, false, 0, false);
+ dirstream = connection.ReceiveStream();
+ dir.ReadFromStream(*dirstream, connection.GetTimeout());
+ TEST_THAT(!SearchDir(dir, "xx_not_this_dir_22"));
+ TEST_THAT(!SearchDir(dir, "somefile.excludethis"));
+ connection.QueryFinished();
+ }
+
+ TEST_THAT(ServerIsAlive(bbackupd_pid));
+ TEST_THAT(ServerIsAlive(bbstored_pid));
+ if (!ServerIsAlive(bbackupd_pid)) return 1;
+ if (!ServerIsAlive(bbstored_pid)) return 1;
+
+#ifndef WIN32
// These tests only work as non-root users.
if(::getuid() != 0)
{
// Check that read errors are reported neatly
- printf("Add unreadable files\n");
+ printf("\n==== Add unreadable files\n");
+
{
// Dir and file which can't be read
- TEST_THAT(::mkdir("testfiles/TestDir1/sub23/read-fail-test-dir", 0000) == 0);
- int fd = ::open("testfiles/TestDir1/read-fail-test-file", O_CREAT | O_WRONLY, 0000);
+ TEST_THAT(::mkdir("testfiles/TestDir1/sub23"
+ "/read-fail-test-dir", 0000) == 0);
+ int fd = ::open("testfiles/TestDir1"
+ "/read-fail-test-file",
+ O_CREAT | O_WRONLY, 0000);
TEST_THAT(fd != -1);
::close(fd);
}
+
// Wait and test...
wait_for_backup_operation();
- compareReturnValue = ::system("../../bin/bbackupquery/bbackupquery -q -c testfiles/bbackupd.conf -l testfiles/query3e.log \"compare -ac\" quit");
- TEST_THAT(compareReturnValue == 2*256); // should find differences
+ compareReturnValue = ::system(BBACKUPQUERY " -q "
+ "-c testfiles/bbackupd.conf "
+ "-l testfiles/query3o.log "
+ "\"compare -acQ\" quit");
+
+ // should find differences
+ TEST_RETURN(compareReturnValue, 3);
TestRemoteProcessMemLeaks("bbackupquery.memleaks");
+
// Check that it was reported correctly
TEST_THAT(TestFileExists("testfiles/notifyran.read-error.1"));
+
+ // Check that the error was only reported once
TEST_THAT(!TestFileExists("testfiles/notifyran.read-error.2"));
- // Set permissions on file and dir to stop errors in the future
- ::chmod("testfiles/TestDir1/sub23/read-fail-test-dir", 0770);
- ::chmod("testfiles/TestDir1/read-fail-test-file", 0770);
+
+ // Set permissions on file and dir to stop
+ // errors in the future
+ TEST_THAT(::chmod("testfiles/TestDir1/sub23"
+ "/read-fail-test-dir", 0770) == 0);
+ TEST_THAT(::chmod("testfiles/TestDir1"
+ "/read-fail-test-file", 0770) == 0);
}
+#endif
+
+ TEST_THAT(ServerIsAlive(bbackupd_pid));
+ TEST_THAT(ServerIsAlive(bbstored_pid));
+ if (!ServerIsAlive(bbackupd_pid)) return 1;
+ if (!ServerIsAlive(bbstored_pid)) return 1;
- printf("Continuously update file, check isn't uploaded\n");
+ printf("\n==== Continuously update file, "
+ "check isn't uploaded\n");
- // Make sure everything happens at the same point in the sync cycle: wait until exactly the start of a sync
- TEST_THAT(::system("../../bin/bbackupctl/bbackupctl -c testfiles/bbackupd.conf wait-for-sync") == 0);
- TestRemoteProcessMemLeaks("bbackupctl.memleaks");
+ // Make sure everything happens at the same point in the
+ // sync cycle: wait until exactly the start of a sync
+ wait_for_sync_start();
+
// Then wait a second, to make sure the scan is complete
- ::sleep(1);
+ ::safe_sleep(1);
{
// Open a file, then save something to it every second
@@ -744,39 +2235,54 @@ int test_bbackupd()
TEST_THAT(f != 0);
fprintf(f, "Loop iteration %d\n", l);
fflush(f);
- sleep(1);
+ fclose(f);
+
printf(".");
fflush(stdout);
- ::fclose(f);
+ safe_sleep(1);
}
printf("\n");
+ fflush(stdout);
// Check there's a difference
- compareReturnValue = ::system("testfiles/extcheck1.pl");
- TEST_THAT(compareReturnValue == 1*256);
+ compareReturnValue = ::system("perl testfiles/"
+ "extcheck1.pl");
+
+ TEST_RETURN(compareReturnValue, 1);
TestRemoteProcessMemLeaks("bbackupquery.memleaks");
- printf("Keep on continuously updating file, check it is uploaded eventually\n");
+ printf("\n==== Keep on continuously updating file, "
+ "check it is uploaded eventually\n");
for(int l = 0; l < 28; ++l)
{
- FILE *f = ::fopen("testfiles/TestDir1/continousupdate", "w+");
+ FILE *f = ::fopen("testfiles/TestDir1/"
+ "continousupdate", "w+");
TEST_THAT(f != 0);
fprintf(f, "Loop 2 iteration %d\n", l);
fflush(f);
- sleep(1);
+ fclose(f);
+
printf(".");
fflush(stdout);
- ::fclose(f);
+ safe_sleep(1);
}
printf("\n");
+ fflush(stdout);
- compareReturnValue = ::system("testfiles/extcheck2.pl");
- TEST_THAT(compareReturnValue == 1*256);
+ compareReturnValue = ::system("perl testfiles/"
+ "extcheck2.pl");
+
+ TEST_RETURN(compareReturnValue, 1);
TestRemoteProcessMemLeaks("bbackupquery.memleaks");
}
- printf("Delete directory, change attributes\n");
+ TEST_THAT(ServerIsAlive(bbackupd_pid));
+ TEST_THAT(ServerIsAlive(bbstored_pid));
+ if (!ServerIsAlive(bbackupd_pid)) return 1;
+ if (!ServerIsAlive(bbstored_pid)) return 1;
+
+ printf("\n==== Delete directory, change attributes\n");
// Delete a directory
TEST_THAT(::system("rm -rf testfiles/TestDir1/x1") == 0);
@@ -785,109 +2291,288 @@ int test_bbackupd()
// Wait and test
wait_for_backup_operation();
- compareReturnValue = ::system("../../bin/bbackupquery/bbackupquery -q -c testfiles/bbackupd.conf -l testfiles/query4.log \"compare -ac\" quit");
- TEST_THAT(compareReturnValue == 1*256);
+ compareReturnValue = ::system(BBACKUPQUERY " -q "
+ "-c testfiles/bbackupd.conf "
+ "-l testfiles/query4.log "
+ "\"compare -acQ\" quit");
+ TEST_RETURN(compareReturnValue, 1);
TestRemoteProcessMemLeaks("bbackupquery.memleaks");
- printf("Restore files and directories\n");
+ printf("\n==== Restore files and directories\n");
int64_t deldirid = 0;
int64_t restoredirid = 0;
{
// connect and log in
SocketStreamTLS conn;
- conn.Open(context, Socket::TypeINET, "localhost", BOX_PORT_BBSTORED);
+ conn.Open(context, Socket::TypeINET, "localhost",
+ BOX_PORT_BBSTORED);
BackupProtocolClient protocol(conn);
protocol.QueryVersion(BACKUP_STORE_SERVER_VERSION);
- std::auto_ptr<BackupProtocolClientLoginConfirmed> loginConf(protocol.QueryLogin(0x01234567, BackupProtocolClientLogin::Flags_ReadOnly));
+ std::auto_ptr<BackupProtocolClientLoginConfirmed>
+ loginConf(protocol.QueryLogin(0x01234567,
+ BackupProtocolClientLogin::Flags_ReadOnly));
// Find the ID of the Test1 directory
- restoredirid = GetDirID(protocol, "Test1", BackupProtocolClientListDirectory::RootDirectory);
+ restoredirid = GetDirID(protocol, "Test1",
+ BackupProtocolClientListDirectory::RootDirectory);
TEST_THAT(restoredirid != 0);
// Test the restoration
- TEST_THAT(BackupClientRestore(protocol, restoredirid, "testfiles/restore-Test1", true /* print progress dots */) == Restore_Complete);
+ TEST_THAT(BackupClientRestore(protocol, restoredirid,
+ "testfiles/restore-Test1",
+ true /* print progress dots */)
+ == Restore_Complete);
- // Compare it
- compareReturnValue = ::system("../../bin/bbackupquery/bbackupquery -q -c testfiles/bbackupd.conf -l testfiles/query10.log \"compare -cE Test1 testfiles/restore-Test1\" quit");
- TEST_THAT(compareReturnValue == 1*256);
- TestRemoteProcessMemLeaks("bbackupquery.memleaks");
+ // On Win32 we can't open another connection
+ // to the server, so we'll compare later.
// Make sure you can't restore a restored directory
- TEST_THAT(BackupClientRestore(protocol, restoredirid, "testfiles/restore-Test1", true /* print progress dots */) == Restore_TargetExists);
+ TEST_THAT(BackupClientRestore(protocol, restoredirid,
+ "testfiles/restore-Test1",
+ true /* print progress dots */)
+ == Restore_TargetExists);
+
+ // Make sure you can't restore to a nonexistant path
+ printf("Try to restore to a path that doesn't exist\n");
+ TEST_THAT(BackupClientRestore(protocol, restoredirid,
+ "testfiles/no-such-path/subdir",
+ true /* print progress dots */)
+ == Restore_TargetPathNotFound);
// Find ID of the deleted directory
deldirid = GetDirID(protocol, "x1", restoredirid);
TEST_THAT(deldirid != 0);
- // Just check it doesn't bomb out -- will check this properly later (when bbackupd is stopped)
- TEST_THAT(BackupClientRestore(protocol, deldirid, "testfiles/restore-Test1-x1", true /* print progress dots */, true /* deleted files */) == Restore_Complete);
+ // Just check it doesn't bomb out -- will check this
+ // properly later (when bbackupd is stopped)
+ TEST_THAT(BackupClientRestore(protocol, deldirid,
+ "testfiles/restore-Test1-x1",
+ true /* print progress dots */,
+ true /* deleted files */)
+ == Restore_Complete);
// Log out
protocol.QueryFinished();
}
- printf("Add files with current time\n");
+ // Compare the restored files
+ compareReturnValue = ::system(BBACKUPQUERY " -q "
+ "-c testfiles/bbackupd.conf "
+ "-l testfiles/query10.log "
+ "\"compare -cEQ Test1 testfiles/restore-Test1\" "
+ "quit");
+ TEST_RETURN(compareReturnValue, 1);
+ TestRemoteProcessMemLeaks("bbackupquery.memleaks");
+
+ TEST_THAT(ServerIsAlive(bbackupd_pid));
+ TEST_THAT(ServerIsAlive(bbstored_pid));
+ if (!ServerIsAlive(bbackupd_pid)) return 1;
+ if (!ServerIsAlive(bbstored_pid)) return 1;
+
+#ifdef WIN32
+ // make one of the files read-only, expect a compare failure
+ compareReturnValue = ::system("attrib +r "
+ "testfiles\\restore-Test1\\f1.dat");
+ TEST_RETURN(compareReturnValue, 0);
+
+ compareReturnValue = ::system(BBACKUPQUERY " -q "
+ "-c testfiles/bbackupd.conf "
+ "-l testfiles/query10a.log "
+ "\"compare -cEQ Test1 testfiles/restore-Test1\" "
+ "quit");
+ TEST_RETURN(compareReturnValue, 2);
+ TestRemoteProcessMemLeaks("bbackupquery.memleaks");
+
+ // set it back, expect no failures
+ compareReturnValue = ::system("attrib -r "
+ "testfiles\\restore-Test1\\f1.dat");
+ TEST_RETURN(compareReturnValue, 0);
+
+ compareReturnValue = ::system(BBACKUPQUERY " -q "
+ "-c testfiles/bbackupd.conf -l testfiles/query10a.log "
+ "\"compare -cEQ Test1 testfiles/restore-Test1\" "
+ "quit");
+ TEST_RETURN(compareReturnValue, 1);
+ TestRemoteProcessMemLeaks("bbackupquery.memleaks");
+
+ // change the timestamp on a file, expect a compare failure
+ char* testfile = "testfiles\\restore-Test1\\f1.dat";
+ HANDLE handle = openfile(testfile, O_RDWR, 0);
+ TEST_THAT(handle != INVALID_HANDLE_VALUE);
+
+ FILETIME creationTime, lastModTime, lastAccessTime;
+ TEST_THAT(GetFileTime(handle, &creationTime, &lastAccessTime,
+ &lastModTime) != 0);
+ TEST_THAT(CloseHandle(handle));
+
+ FILETIME dummyTime = lastModTime;
+ dummyTime.dwHighDateTime -= 100;
+
+ // creation time is backed up, so changing it should cause
+ // a compare failure
+ TEST_THAT(set_file_time(testfile, dummyTime, lastModTime,
+ lastAccessTime));
+ compareReturnValue = ::system(BBACKUPQUERY " -q "
+ "-c testfiles/bbackupd.conf "
+ "-l testfiles/query10a.log "
+ "\"compare -cEQ Test1 testfiles/restore-Test1\" "
+ "quit");
+ TEST_RETURN(compareReturnValue, 2);
+ TestRemoteProcessMemLeaks("bbackupquery.memleaks");
+
+ // last access time is not backed up, so it cannot be compared
+ TEST_THAT(set_file_time(testfile, creationTime, lastModTime,
+ dummyTime));
+ compareReturnValue = ::system(BBACKUPQUERY " -q "
+ "-c testfiles/bbackupd.conf "
+ "-l testfiles/query10a.log "
+ "\"compare -cEQ Test1 testfiles/restore-Test1\" "
+ "quit");
+ TEST_RETURN(compareReturnValue, 1);
+ TestRemoteProcessMemLeaks("bbackupquery.memleaks");
+
+ // last write time is backed up, so changing it should cause
+ // a compare failure
+ TEST_THAT(set_file_time(testfile, creationTime, dummyTime,
+ lastAccessTime));
+ compareReturnValue = ::system(BBACKUPQUERY " -q "
+ "-c testfiles/bbackupd.conf "
+ "-l testfiles/query10a.log "
+ "\"compare -cEQ Test1 testfiles/restore-Test1\" "
+ "quit");
+ TEST_RETURN(compareReturnValue, 2);
+ TestRemoteProcessMemLeaks("bbackupquery.memleaks");
+
+ // set back to original values, check that compare succeeds
+ TEST_THAT(set_file_time(testfile, creationTime, lastModTime,
+ lastAccessTime));
+ compareReturnValue = ::system(BBACKUPQUERY " -q "
+ "-c testfiles/bbackupd.conf "
+ "-l testfiles/query10a.log "
+ "\"compare -cEQ Test1 testfiles/restore-Test1\" "
+ "quit");
+ TEST_RETURN(compareReturnValue, 1);
+ TestRemoteProcessMemLeaks("bbackupquery.memleaks");
+#endif // WIN32
+
+ TEST_THAT(ServerIsAlive(bbackupd_pid));
+ TEST_THAT(ServerIsAlive(bbstored_pid));
+ if (!ServerIsAlive(bbackupd_pid)) return 1;
+ if (!ServerIsAlive(bbstored_pid)) return 1;
+
+ printf("\n==== Add files with current time\n");
// Add some more files and modify others
// Use the m flag this time so they have a recent modification time
- TEST_THAT(::system("gzip -d < testfiles/test3.tgz | ( cd testfiles && tar xmf - )") == 0);
+ #ifdef WIN32
+ TEST_THAT(::system("tar xzvmf testfiles/test3.tgz "
+ "-C testfiles") == 0);
+ #else
+ TEST_THAT(::system("gzip -d < testfiles/test3.tgz "
+ "| ( cd testfiles && tar xmf - )") == 0);
+ #endif
// Wait and test
wait_for_backup_operation();
- compareReturnValue = ::system("../../bin/bbackupquery/bbackupquery -q -c testfiles/bbackupd.conf -l testfiles/query5.log \"compare -ac\" quit");
- TEST_THAT(compareReturnValue == 1*256);
+ compareReturnValue = ::system(BBACKUPQUERY " -q "
+ "-c testfiles/bbackupd.conf "
+ "-l testfiles/query5.log "
+ "\"compare -acQ\" quit");
+ TEST_RETURN(compareReturnValue, 1);
TestRemoteProcessMemLeaks("bbackupquery.memleaks");
+ TEST_THAT(ServerIsAlive(bbackupd_pid));
+ TEST_THAT(ServerIsAlive(bbstored_pid));
+ if (!ServerIsAlive(bbackupd_pid)) return 1;
+ if (!ServerIsAlive(bbstored_pid)) return 1;
+
// Rename directory
- printf("Rename directory\n");
- TEST_THAT(rename("testfiles/TestDir1/sub23/dhsfdss", "testfiles/TestDir1/renamed-dir") == 0);
+ printf("\n==== Rename directory\n");
+ TEST_THAT(rename("testfiles/TestDir1/sub23/dhsfdss",
+ "testfiles/TestDir1/renamed-dir") == 0);
wait_for_backup_operation();
- compareReturnValue = ::system("../../bin/bbackupquery/bbackupquery -q -c testfiles/bbackupd.conf -l testfiles/query6.log \"compare -ac\" quit");
- TEST_THAT(compareReturnValue == 1*256);
+ compareReturnValue = ::system(BBACKUPQUERY " -q "
+ "-c testfiles/bbackupd.conf "
+ "-l testfiles/query6.log "
+ "\"compare -acQ\" quit");
+ TEST_RETURN(compareReturnValue, 1);
TestRemoteProcessMemLeaks("bbackupquery.memleaks");
+
// and again, but with quick flag
- compareReturnValue = ::system("../../bin/bbackupquery/bbackupquery -q -c testfiles/bbackupd.conf -l testfiles/query6q.log \"compare -acq\" quit");
- TEST_THAT(compareReturnValue == 1*256);
+ compareReturnValue = ::system(BBACKUPQUERY " -q "
+ "-c testfiles/bbackupd.conf "
+ "-l testfiles/query6q.log "
+ "\"compare -acqQ\" quit");
+ TEST_RETURN(compareReturnValue, 1);
TestRemoteProcessMemLeaks("bbackupquery.memleaks");
// Rename some files -- one under the threshold, others above
- printf("Rename files\n");
- TEST_THAT(rename("testfiles/TestDir1/continousupdate", "testfiles/TestDir1/continousupdate-ren") == 0);
- TEST_THAT(rename("testfiles/TestDir1/df324", "testfiles/TestDir1/df324-ren") == 0);
- TEST_THAT(rename("testfiles/TestDir1/sub23/find2perl", "testfiles/TestDir1/find2perl-ren") == 0);
+ printf("\n==== Rename files\n");
+ TEST_THAT(rename("testfiles/TestDir1/continousupdate",
+ "testfiles/TestDir1/continousupdate-ren") == 0);
+ TEST_THAT(rename("testfiles/TestDir1/df324",
+ "testfiles/TestDir1/df324-ren") == 0);
+ TEST_THAT(rename("testfiles/TestDir1/sub23/find2perl",
+ "testfiles/TestDir1/find2perl-ren") == 0);
wait_for_backup_operation();
- compareReturnValue = ::system("../../bin/bbackupquery/bbackupquery -q -c testfiles/bbackupd.conf -l testfiles/query6.log \"compare -ac\" quit");
- TEST_THAT(compareReturnValue == 1*256);
+ compareReturnValue = ::system(BBACKUPQUERY " -q "
+ "-c testfiles/bbackupd.conf "
+ "-l testfiles/query6.log "
+ "\"compare -acQ\" quit");
+ TEST_RETURN(compareReturnValue, 1);
TestRemoteProcessMemLeaks("bbackupquery.memleaks");
- // Check that modifying files with madly in the future timestamps still get added
- printf("Create a file with timestamp to way ahead in the future\n");
+ TEST_THAT(ServerIsAlive(bbackupd_pid));
+ TEST_THAT(ServerIsAlive(bbstored_pid));
+ if (!ServerIsAlive(bbackupd_pid)) return 1;
+ if (!ServerIsAlive(bbstored_pid)) return 1;
+
+ // Check that modifying files with madly in the future
+ // timestamps still get added
+ printf("\n==== Create a file with timestamp way ahead "
+ "in the future\n");
+
// Time critical, so sync
- TEST_THAT(::system("../../bin/bbackupctl/bbackupctl -q -c testfiles/bbackupd.conf wait-for-sync") == 0);
- TestRemoteProcessMemLeaks("bbackupctl.memleaks");
+ wait_for_sync_start();
+
// Then wait a second, to make sure the scan is complete
- ::sleep(1);
+ ::safe_sleep(1);
+
// Then modify an existing file
{
- FILE *f = fopen("testfiles/TestDir1/sub23/in-the-future", "w");
+ FILE *f = fopen("testfiles/TestDir1/sub23/"
+ "in-the-future", "w");
TEST_THAT(f != 0);
fprintf(f, "Back to the future!\n");
fclose(f);
// and then move the time forwards!
struct timeval times[2];
- BoxTimeToTimeval(GetCurrentBoxTime() + SecondsToBoxTime((time_t)(365*24*60*60)), times[1]);
+ BoxTimeToTimeval(GetCurrentBoxTime() +
+ SecondsToBoxTime((time_t)(365*24*60*60)),
+ times[1]);
times[0] = times[1];
- TEST_THAT(::utimes("testfiles/TestDir1/sub23/in-the-future", times) == 0);
+ TEST_THAT(::utimes("testfiles/TestDir1/sub23/"
+ "in-the-future", times) == 0);
}
+
// Wait and test
wait_for_backup_operation();
- compareReturnValue = ::system("../../bin/bbackupquery/bbackupquery -q -c testfiles/bbackupd.conf -l testfiles/query3e.log \"compare -ac\" quit");
- TEST_THAT(compareReturnValue == 1*256);
+ compareReturnValue = ::system(BBACKUPQUERY " -q "
+ "-c testfiles/bbackupd.conf "
+ "-l testfiles/query3e.log "
+ "\"compare -acQ\" quit");
+ TEST_RETURN(compareReturnValue, 1);
TestRemoteProcessMemLeaks("bbackupquery.memleaks");
- printf("Change client store marker\n");
+ TEST_THAT(ServerIsAlive(bbackupd_pid));
+ TEST_THAT(ServerIsAlive(bbstored_pid));
+ if (!ServerIsAlive(bbackupd_pid)) return 1;
+ if (!ServerIsAlive(bbstored_pid)) return 1;
+
+ printf("\n==== Change client store marker\n");
- // Then... connect to the server, and change the client store marker. See what that does!
+ // Then... connect to the server, and change the
+ // client store marker. See what that does!
{
bool done = false;
int tries = 4;
@@ -896,7 +2581,8 @@ int test_bbackupd()
try
{
SocketStreamTLS conn;
- conn.Open(context, Socket::TypeINET, "localhost", BOX_PORT_BBSTORED);
+ conn.Open(context, Socket::TypeINET,
+ "localhost", BOX_PORT_BBSTORED);
BackupProtocolClient protocol(conn);
protocol.QueryVersion(BACKUP_STORE_SERVER_VERSION);
std::auto_ptr<BackupProtocolClientLoginConfirmed> loginConf(protocol.QueryLogin(0x01234567, 0)); // read-write
@@ -920,10 +2606,15 @@ int test_bbackupd()
TEST_THAT(done);
}
- printf("Check change of store marker pauses daemon\n");
+ TEST_THAT(ServerIsAlive(bbackupd_pid));
+ TEST_THAT(ServerIsAlive(bbstored_pid));
+ if (!ServerIsAlive(bbackupd_pid)) return 1;
+ if (!ServerIsAlive(bbstored_pid)) return 1;
+
+ printf("\n==== Check change of store marker pauses daemon\n");
- // Make a change to a file, to detect whether or not it's hanging around
- // waiting to retry.
+ // Make a change to a file, to detect whether or not
+ // it's hanging around waiting to retry.
{
FILE *f = ::fopen("testfiles/TestDir1/fileaftermarker", "w");
TEST_THAT(f != 0);
@@ -932,56 +2623,114 @@ int test_bbackupd()
}
// Wait and test that there *are* differences
- wait_for_backup_operation((TIME_TO_WAIT_FOR_BACKUP_OPERATION*3) / 2); // little bit longer than usual
- compareReturnValue = ::system("../../bin/bbackupquery/bbackupquery -q -c testfiles/bbackupd.conf -l testfiles/query6.log \"compare -ac\" quit");
- TEST_THAT(compareReturnValue == 2*256);
+ wait_for_backup_operation((TIME_TO_WAIT_FOR_BACKUP_OPERATION *
+ 3) / 2); // little bit longer than usual
+ compareReturnValue = ::system(BBACKUPQUERY " -q "
+ "-c testfiles/bbackupd.conf "
+ "-l testfiles/query6.log "
+ "\"compare -acQ\" quit");
+ TEST_RETURN(compareReturnValue, 2);
TestRemoteProcessMemLeaks("bbackupquery.memleaks");
-
- printf("Interrupted restore\n");
+
+ TEST_THAT(ServerIsAlive(bbackupd_pid));
+ TEST_THAT(ServerIsAlive(bbstored_pid));
+ if (!ServerIsAlive(bbackupd_pid)) return 1;
+ if (!ServerIsAlive(bbstored_pid)) return 1;
+
+ printf("\n==== Waiting for bbackupd to recover\n");
+ // 100 seconds - (12*3/2)
+ wait_for_operation(82);
+
+ TEST_THAT(ServerIsAlive(bbackupd_pid));
+ TEST_THAT(ServerIsAlive(bbstored_pid));
+ if (!ServerIsAlive(bbackupd_pid)) return 1;
+ if (!ServerIsAlive(bbstored_pid)) return 1;
+
+#ifndef WIN32
+ printf("\n==== Interrupted restore\n");
{
do_interrupted_restore(context, restoredirid);
int64_t resumesize = 0;
- TEST_THAT(FileExists("testfiles/restore-interrupt.boxbackupresume", &resumesize));
- TEST_THAT(resumesize > 16); // make sure it has recorded something to resume
+ TEST_THAT(FileExists("testfiles/"
+ "restore-interrupt.boxbackupresume",
+ &resumesize));
+ // make sure it has recorded something to resume
+ TEST_THAT(resumesize > 16);
- printf("\nResume restore\n");
+ printf("\n==== Resume restore\n");
SocketStreamTLS conn;
- conn.Open(context, Socket::TypeINET, "localhost", BOX_PORT_BBSTORED);
+ conn.Open(context, Socket::TypeINET, "localhost",
+ BOX_PORT_BBSTORED);
BackupProtocolClient protocol(conn);
protocol.QueryVersion(BACKUP_STORE_SERVER_VERSION);
- std::auto_ptr<BackupProtocolClientLoginConfirmed> loginConf(protocol.QueryLogin(0x01234567, 0)); // read-write
+ std::auto_ptr<BackupProtocolClientLoginConfirmed>
+ loginConf(protocol.QueryLogin(0x01234567,
+ 0 /* read-write */));
- // Check that the restore fn returns resume possible, rather than doing anything
- TEST_THAT(BackupClientRestore(protocol, restoredirid, "testfiles/restore-interrupt", true /* print progress dots */) == Restore_ResumePossible);
+ // Check that the restore fn returns resume possible,
+ // rather than doing anything
+ TEST_THAT(BackupClientRestore(protocol, restoredirid,
+ "testfiles/restore-interrupt",
+ true /* print progress dots */)
+ == Restore_ResumePossible);
// Then resume it
- TEST_THAT(BackupClientRestore(protocol, restoredirid, "testfiles/restore-interrupt", true /* print progress dots */, false /* deleted files */, false /* undelete server */, true /* resume */) == Restore_Complete);
+ TEST_THAT(BackupClientRestore(protocol, restoredirid,
+ "testfiles/restore-interrupt",
+ true /* print progress dots */,
+ false /* deleted files */,
+ false /* undelete server */,
+ true /* resume */)
+ == Restore_Complete);
protocol.QueryFinished();
// Then check it has restored the correct stuff
- compareReturnValue = ::system("../../bin/bbackupquery/bbackupquery -q -c testfiles/bbackupd.conf -l testfiles/query14.log \"compare -cE Test1 testfiles/restore-interrupt\" quit");
- TEST_THAT(compareReturnValue == 1*256);
+ compareReturnValue = ::system(BBACKUPQUERY " -q "
+ "-c testfiles/bbackupd.conf "
+ "-l testfiles/query14.log "
+ "\"compare -cEQ Test1 "
+ "testfiles/restore-interrupt\" quit");
+ TEST_RETURN(compareReturnValue, 1);
TestRemoteProcessMemLeaks("bbackupquery.memleaks");
}
+#endif // !WIN32
+
+ TEST_THAT(ServerIsAlive(bbackupd_pid));
+ TEST_THAT(ServerIsAlive(bbstored_pid));
+ if (!ServerIsAlive(bbackupd_pid)) return 1;
+ if (!ServerIsAlive(bbstored_pid)) return 1;
+
+ printf("\n==== Check restore deleted files\n");
- printf("Check restore deleted files\n");
{
SocketStreamTLS conn;
- conn.Open(context, Socket::TypeINET, "localhost", BOX_PORT_BBSTORED);
+ conn.Open(context, Socket::TypeINET, "localhost",
+ BOX_PORT_BBSTORED);
BackupProtocolClient protocol(conn);
protocol.QueryVersion(BACKUP_STORE_SERVER_VERSION);
- std::auto_ptr<BackupProtocolClientLoginConfirmed> loginConf(protocol.QueryLogin(0x01234567, 0)); // read-write
+ std::auto_ptr<BackupProtocolClientLoginConfirmed>
+ loginConf(protocol.QueryLogin(0x01234567,
+ 0 /* read-write */));
// Do restore and undelete
- TEST_THAT(BackupClientRestore(protocol, deldirid, "testfiles/restore-Test1-x1-2", true /* print progress dots */, true /* deleted files */, true /* undelete on server */) == Restore_Complete);
+ TEST_THAT(BackupClientRestore(protocol, deldirid,
+ "testfiles/restore-Test1-x1-2",
+ true /* print progress dots */,
+ true /* deleted files */,
+ true /* undelete on server */)
+ == Restore_Complete);
protocol.QueryFinished();
// Do a compare with the now undeleted files
- compareReturnValue = ::system("../../bin/bbackupquery/bbackupquery -q -c testfiles/bbackupd.conf -l testfiles/query11.log \"compare -cE Test1/x1 testfiles/restore-Test1-x1-2\" quit");
- TEST_THAT(compareReturnValue == 1*256);
+ compareReturnValue = ::system(BBACKUPQUERY " -q "
+ "-c testfiles/bbackupd.conf "
+ "-l testfiles/query11.log "
+ "\"compare -cEQ Test1/x1 "
+ "testfiles/restore-Test1-x1-2\" quit");
+ TEST_RETURN(compareReturnValue, 1);
TestRemoteProcessMemLeaks("bbackupquery.memleaks");
}
@@ -989,39 +2738,124 @@ int test_bbackupd()
TEST_THAT(!TestFileExists("testfiles/notifyran.store-full.2"));
TEST_THAT(!TestFileExists("testfiles/notifyran.read-error.2"));
+ TEST_THAT(ServerIsAlive(bbackupd_pid));
+ TEST_THAT(ServerIsAlive(bbstored_pid));
+ if (!ServerIsAlive(bbackupd_pid)) return 1;
+ if (!ServerIsAlive(bbstored_pid)) return 1;
+
+#ifdef WIN32
+ printf("\n==== Testing locked file behaviour:\n");
+
+ // Test that locked files cannot be backed up,
+ // and the appropriate error is reported.
+ // Wait for the sync to finish, so that we have time to work
+ wait_for_sync_start();
+ // Now we have about three seconds to work
+
+ handle = openfile("testfiles/TestDir1/lockedfile",
+ O_CREAT | O_EXCL | O_LOCK, 0);
+ TEST_THAT(handle != INVALID_HANDLE_VALUE);
+
+ if (handle != 0)
+ {
+ // first sync will ignore the file, it's too new
+ wait_for_sync_end();
+ TEST_THAT(!TestFileExists("testfiles/"
+ "notifyran.read-error.1"));
+
+ // this sync should try to back up the file,
+ // and fail, because it's locked
+ wait_for_sync_end();
+ TEST_THAT(TestFileExists("testfiles/"
+ "notifyran.read-error.1"));
+ TEST_THAT(!TestFileExists("testfiles/"
+ "notifyran.read-error.2"));
+
+ // now close the file and check that it is
+ // backed up on the next run.
+ CloseHandle(handle);
+ wait_for_sync_end();
+ TEST_THAT(!TestFileExists("testfiles/"
+ "notifyran.read-error.2"));
+
+ // compare, and check that it works
+ // reports the correct error message (and finishes)
+ compareReturnValue = ::system(BBACKUPQUERY " -q "
+ "-c testfiles/bbackupd.conf "
+ "-l testfiles/query15a.log "
+ "\"compare -acQ\" quit");
+ TEST_RETURN(compareReturnValue, 1);
+ TestRemoteProcessMemLeaks("bbackupquery.memleaks");
+
+ // open the file again, compare and check that compare
+ // reports the correct error message (and finishes)
+ handle = openfile("testfiles/TestDir1/lockedfile",
+ O_LOCK, 0);
+ TEST_THAT(handle != INVALID_HANDLE_VALUE);
+
+ compareReturnValue = ::system(BBACKUPQUERY
+ " -q -c testfiles/bbackupd.conf "
+ "-l testfiles/query15.log "
+ "\"compare -acQ\" quit");
+ TEST_RETURN(compareReturnValue, 3);
+ TestRemoteProcessMemLeaks("bbackupquery.memleaks");
+
+ // close the file again, check that compare
+ // works again
+ CloseHandle(handle);
+
+ compareReturnValue = ::system(BBACKUPQUERY " -q "
+ "-c testfiles/bbackupd.conf "
+ "-l testfiles/query15a.log "
+ "\"compare -acQ\" quit");
+ TEST_RETURN(compareReturnValue, 1);
+ TestRemoteProcessMemLeaks("bbackupquery.memleaks");
+ }
+#endif
+
// Kill the daemon
- TEST_THAT(KillServer(pid));
- ::sleep(1);
- TEST_THAT(!ServerIsAlive(pid));
- TestRemoteProcessMemLeaks("bbackupd.memleaks");
+ terminate_bbackupd(bbackupd_pid);
// Start it again
- pid = LaunchServer("../../bin/bbackupd/bbackupd testfiles/bbackupd.conf", "testfiles/bbackupd.pid");
- TEST_THAT(pid != -1 && pid != 0);
- if(pid != -1 && pid != 0)
+ cmd = BBACKUPD + bbackupd_args + " testfiles/bbackupd.conf";
+ bbackupd_pid = LaunchServer(cmd, "testfiles/bbackupd.pid");
+
+ TEST_THAT(bbackupd_pid != -1 && bbackupd_pid != 0);
+
+ TEST_THAT(ServerIsAlive(bbackupd_pid));
+ TEST_THAT(ServerIsAlive(bbstored_pid));
+ if (!ServerIsAlive(bbackupd_pid)) return 1;
+ if (!ServerIsAlive(bbstored_pid)) return 1;
+
+ if(bbackupd_pid != -1 && bbackupd_pid != 0)
{
- // Wait and comapre
- wait_for_backup_operation((TIME_TO_WAIT_FOR_BACKUP_OPERATION*3) / 2); // little bit longer than usual
- compareReturnValue = ::system("../../bin/bbackupquery/bbackupquery -q -c testfiles/bbackupd.conf -l testfiles/query4.log \"compare -ac\" quit");
- TEST_THAT(compareReturnValue == 1*256);
+ // Wait and compare (a little bit longer than usual)
+ wait_for_backup_operation(
+ (TIME_TO_WAIT_FOR_BACKUP_OPERATION*3) / 2);
+ compareReturnValue = ::system(BBACKUPQUERY " -q "
+ "-c testfiles/bbackupd.conf "
+ "-l testfiles/query4a.log "
+ "\"compare -acQ\" quit");
+ TEST_RETURN(compareReturnValue, 1);
TestRemoteProcessMemLeaks("bbackupquery.memleaks");
// Kill it again
- TEST_THAT(KillServer(pid));
- ::sleep(1);
- TEST_THAT(!ServerIsAlive(pid));
- TestRemoteProcessMemLeaks("bbackupd.memleaks");
+ terminate_bbackupd(bbackupd_pid);
}
}
// List the files on the server
- ::system("../../bin/bbackupquery/bbackupquery -q -c testfiles/bbackupd.conf -l testfiles/queryLIST.log \"list -rotdh\" quit");
+ ::system(BBACKUPQUERY " -q -c testfiles/bbackupd.conf "
+ "-l testfiles/queryLIST.log \"list -rotdh\" quit");
TestRemoteProcessMemLeaks("bbackupquery.memleaks");
-
- if(::getuid() == 0)
- {
- ::printf("WARNING: This test was run as root. Some tests have been omitted.\n");
- }
+
+ #ifndef WIN32
+ if(::getuid() == 0)
+ {
+ ::printf("WARNING: This test was run as root. "
+ "Some tests have been omitted.\n");
+ }
+ #endif
return 0;
}
@@ -1035,7 +2869,13 @@ int test(int argc, const char *argv[])
BackupClientCryptoKeys_Setup("testfiles/bbackupd.keys");
// Initial files
- TEST_THAT(::system("gzip -d < testfiles/test_base.tgz | ( cd testfiles && tar xf - )") == 0);
+ #ifdef WIN32
+ TEST_THAT(::system("tar xzvf testfiles/test_base.tgz "
+ "-C testfiles") == 0);
+ #else
+ TEST_THAT(::system("gzip -d < testfiles/test_base.tgz "
+ "| ( cd testfiles && tar xf - )") == 0);
+ #endif
// Do the tests
@@ -1049,7 +2889,12 @@ int test(int argc, const char *argv[])
if(r != 0) return r;
r = test_bbackupd();
- if(r != 0) return r;
+ if(r != 0)
+ {
+ KillServer(bbackupd_pid);
+ KillServer(bbstored_pid);
+ return r;
+ }
test_kill_bbstored();
diff --git a/test/bbackupd/testfiles/bbackupd.conf.in b/test/bbackupd/testfiles/bbackupd.conf.in
index 6d381d5b..ce5d5b7c 100644
--- a/test/bbackupd/testfiles/bbackupd.conf.in
+++ b/test/bbackupd/testfiles/bbackupd.conf.in
@@ -17,13 +17,16 @@ MaxUploadWait = 24
FileTrackingSizeThreshold = 1024
DiffingUploadSizeThreshold = 1024
-MaximumDiffingTime = 8
+MaximumDiffingTime = 3
+KeepAliveTime = 1
-ExtendedLogging = yes
+ExtendedLogging = no
+ExtendedLogFile = testfiles/bbackupd.log
CommandSocket = testfiles/bbackupd.sock
-NotifyScript = @PERL@ testfiles/notifyscript.pl
+NotifyScript = @TARGET_PERL@ testfiles/notifyscript.pl
+SyncAllowScript = @TARGET_PERL@ testfiles/syncallowscript.pl
Server
{
diff --git a/test/bbackupd/testfiles/extcheck1.pl.in b/test/bbackupd/testfiles/extcheck1.pl.in
index edbacd0a..2a7c0e9a 100755
--- a/test/bbackupd/testfiles/extcheck1.pl.in
+++ b/test/bbackupd/testfiles/extcheck1.pl.in
@@ -1,7 +1,9 @@
#!@PERL@
use strict;
-unless(open IN,"../../bin/bbackupquery/bbackupquery -q -c testfiles/bbackupd.conf -l testfiles/query4.log \"compare -ac\" quit|")
+my $flags = $ARGV[0] or "";
+
+unless(open IN,"../../bin/bbackupquery/bbackupquery -q -c testfiles/bbackupd.conf -l testfiles/query4.log \"compare -ac$flags\" quit 2>&1 |")
{
print "Couldn't open compare utility\n";
exit 2;
@@ -15,14 +17,23 @@ while(<IN>)
next unless m/\S/;
if(m/continousupdate/)
{
- $ret = 2 unless m/exists/;
+ unless (/exists/)
+ {
+ print "FAIL: continousupdate line does not match\n";
+ $ret = 2;
+ }
$seen = 1;
}
else
{
- $ret = 2 unless m/\AWARNING/ || m/\ADifferences/ || /might be reason/ || /probably due to file mod/;
+ unless (/\AWARNING/ or /\ADifferences/ or /might be reason/
+ or /probably due to file mod/)
+ {
+ print "FAIL: Summary line does not match\n";
+ $ret = 2;
+ }
}
- print;
+ print "READ: $_";
}
close IN;
diff --git a/test/bbackupd/testfiles/extcheck2.pl.in b/test/bbackupd/testfiles/extcheck2.pl.in
index 68baa045..c79bf414 100755
--- a/test/bbackupd/testfiles/extcheck2.pl.in
+++ b/test/bbackupd/testfiles/extcheck2.pl.in
@@ -1,7 +1,9 @@
#!@PERL@
use strict;
-unless(open IN,"../../bin/bbackupquery/bbackupquery -q -c testfiles/bbackupd.conf -l testfiles/query4.log \"compare -ac\" quit|")
+my $flags = $ARGV[0] or "";
+
+unless(open IN,"../../bin/bbackupquery/bbackupquery -q -c testfiles/bbackupd.conf -l testfiles/query4.log \"compare -ac$flags\" quit 2>&1 |")
{
print "Couldn't open compare utility\n";
exit 2;
@@ -14,13 +16,23 @@ while(<IN>)
next unless m/\S/;
if(m/continousupdate/)
{
- $ret = 2 unless m/contents/ || m/attributes/;
+ unless (m/contents/ or m/attributes/)
+ {
+ print "FAIL: continuousupdate line does not match\n";
+ $ret = 2;
+ }
}
else
{
- $ret = 2 unless m/\AWARNING/ || m/\ADifferences/ || /might be reason/ || /probably due to file mod/;
+ unless (/\AWARNING/ or /\ADifferences/ or /might be reason/
+ or /probably due to file mod/)
+ {
+ print "FAIL: summary line does not match\n";
+ $ret = 2;
+ }
}
- print;
+
+ print "READ: $_";
}
close IN;
diff --git a/test/bbackupd/testfiles/notifyscript.pl.in b/test/bbackupd/testfiles/notifyscript.pl.in
index df0e5a2d..89741e46 100755
--- a/test/bbackupd/testfiles/notifyscript.pl.in
+++ b/test/bbackupd/testfiles/notifyscript.pl.in
@@ -1,4 +1,4 @@
-#!@PERL@
+#!@TARGET_PERL@
my $f = 'testfiles/notifyran.'.$ARGV[0].'.';
diff --git a/test/bbackupd/testfiles/syncallowscript.pl.in b/test/bbackupd/testfiles/syncallowscript.pl.in
index af425e90..f2ef1171 100755
--- a/test/bbackupd/testfiles/syncallowscript.pl.in
+++ b/test/bbackupd/testfiles/syncallowscript.pl.in
@@ -1,4 +1,4 @@
-#!@PERL@
+#!@TARGET_PERL@
use strict;
use warnings;
diff --git a/test/common/testcommon.cpp b/test/common/testcommon.cpp
index ce5cd931..eb057228 100644
--- a/test/common/testcommon.cpp
+++ b/test/common/testcommon.cpp
@@ -9,13 +9,16 @@
#include "Box.h"
+#include <errno.h>
#include <stdio.h>
+#include <time.h>
#include "Test.h"
#include "Configuration.h"
#include "FdGetLine.h"
#include "Guards.h"
#include "FileStream.h"
+#include "InvisibleTempFileStream.h"
#include "IOStreamGetLine.h"
#include "NamedLock.h"
#include "ReadGatherStream.h"
@@ -24,6 +27,12 @@
#include "CommonException.h"
#include "Conversion.h"
#include "autogen_ConversionException.h"
+#include "CollectInBufferStream.h"
+#include "Archive.h"
+#include "Timer.h"
+#include "Logging.h"
+#include "ZeroStream.h"
+#include "PartialReadStream.h"
#include "MemLeakFindOn.h"
@@ -130,11 +139,139 @@ ConfigurationVerify verify =
0
};
+class TestLogger : public Logger
+{
+ private:
+ bool mTriggered;
+ Log::Level mTargetLevel;
+
+ public:
+ TestLogger(Log::Level targetLevel)
+ : mTriggered(false), mTargetLevel(targetLevel)
+ {
+ Logging::Add(this);
+ }
+ ~TestLogger()
+ {
+ Logging::Remove(this);
+ }
+
+ bool IsTriggered() { return mTriggered; }
+ void Reset() { mTriggered = false; }
+
+ virtual bool Log(Log::Level level, const std::string& rFile,
+ int line, std::string& rMessage)
+ {
+ if (level == mTargetLevel)
+ {
+ mTriggered = true;
+ }
+ return true;
+ }
+
+ virtual const char* GetType() { return "Test"; }
+ virtual void SetProgramName(const std::string& rProgramName) { }
+};
+
int test(int argc, const char *argv[])
{
- // Test memory leak detection
+ // Test PartialReadStream and ReadGatherStream handling of files
+ // over 2GB (refs #2)
+ {
+ char buffer[8];
+
+ ZeroStream zero(0x80000003);
+ zero.Seek(0x7ffffffe, IOStream::SeekType_Absolute);
+ TEST_THAT(zero.GetPosition() == 0x7ffffffe);
+ TEST_THAT(zero.Read(buffer, 8) == 5);
+ TEST_THAT(zero.GetPosition() == 0x80000003);
+ TEST_THAT(zero.Read(buffer, 8) == 0);
+ zero.Seek(0, IOStream::SeekType_Absolute);
+ TEST_THAT(zero.GetPosition() == 0);
+
+ char* buffer2 = new char [0x1000000];
+ TEST_THAT(buffer2 != NULL);
+
+ PartialReadStream part(zero, 0x80000002);
+ for (int i = 0; i < 0x80; i++)
+ {
+ int read = part.Read(buffer2, 0x1000000);
+ TEST_THAT(read == 0x1000000);
+ }
+ TEST_THAT(part.Read(buffer, 8) == 2);
+ TEST_THAT(part.Read(buffer, 8) == 0);
+
+ delete [] buffer2;
+
+ ReadGatherStream gather(false);
+ zero.Seek(0, IOStream::SeekType_Absolute);
+ int component = gather.AddComponent(&zero);
+ gather.AddBlock(component, 0x80000002);
+ TEST_THAT(gather.Read(buffer, 8) == 8);
+ }
+
+ // Test self-deleting temporary file streams
+ {
+ std::string tempfile("testfiles/tempfile");
+ TEST_CHECK_THROWS(InvisibleTempFileStream fs(tempfile.c_str()),
+ CommonException, OSFileOpenError);
+ InvisibleTempFileStream fs(tempfile.c_str(), O_CREAT);
+
+ #ifdef WIN32
+ // file is still visible under Windows
+ TEST_THAT(TestFileExists(tempfile.c_str()));
+
+ // opening it again should work
+ InvisibleTempFileStream fs2(tempfile.c_str());
+ TEST_THAT(TestFileExists(tempfile.c_str()));
+
+ // opening it to create should work
+ InvisibleTempFileStream fs3(tempfile.c_str(), O_CREAT);
+ TEST_THAT(TestFileExists(tempfile.c_str()));
+
+ // opening it to create exclusively should fail
+ TEST_CHECK_THROWS(InvisibleTempFileStream fs4(tempfile.c_str(),
+ O_CREAT | O_EXCL), CommonException, OSFileOpenError);
+
+ fs2.Close();
+ #else
+ // file is not visible under Unix
+ TEST_THAT(!TestFileExists(tempfile.c_str()));
+
+ // opening it again should fail
+ TEST_CHECK_THROWS(InvisibleTempFileStream fs2(tempfile.c_str()),
+ CommonException, OSFileOpenError);
+
+ // opening it to create should work
+ InvisibleTempFileStream fs3(tempfile.c_str(), O_CREAT);
+ TEST_THAT(!TestFileExists(tempfile.c_str()));
+
+ // opening it to create exclusively should work
+ InvisibleTempFileStream fs4(tempfile.c_str(), O_CREAT | O_EXCL);
+ TEST_THAT(!TestFileExists(tempfile.c_str()));
+
+ fs4.Close();
+ #endif
+
+ fs.Close();
+ fs3.Close();
+
+ // now that it's closed, it should be invisible on all platforms
+ TEST_THAT(!TestFileExists(tempfile.c_str()));
+ }
+
+ // Test that memory leak detection doesn't crash
+ {
+ char *test = new char[1024];
+ delete [] test;
+ MemBlockStream *s = new MemBlockStream(test,12);
+ delete s;
+ }
+
#ifdef BOX_MEMORY_LEAK_TESTING
{
+ Timers::Cleanup();
+
TEST_THAT(memleakfinder_numleaks() == 0);
void *block = ::malloc(12);
TEST_THAT(memleakfinder_numleaks() == 1);
@@ -150,9 +287,85 @@ int test(int argc, const char *argv[])
TEST_THAT(memleakfinder_numleaks() == 1);
delete [] test;
TEST_THAT(memleakfinder_numleaks() == 0);
+
+ Timers::Init();
}
#endif // BOX_MEMORY_LEAK_TESTING
+
+ // test main() initialises timers for us, so uninitialise them
+ Timers::Cleanup();
+
+ // Check that using timer methods without initialisation
+ // throws an assertion failure. Can only do this in debug mode
+ #ifndef NDEBUG
+ TEST_CHECK_THROWS(Timers::Add(*(Timer*)NULL),
+ CommonException, AssertFailed);
+ TEST_CHECK_THROWS(Timers::Remove(*(Timer*)NULL),
+ CommonException, AssertFailed);
+ #endif
+
+ // TEST_CHECK_THROWS(Timers::Signal(), CommonException, AssertFailed);
+ #ifndef NDEBUG
+ TEST_CHECK_THROWS(Timers::Cleanup(), CommonException,
+ AssertFailed);
+ #endif
+ // Check that we can initialise the timers
+ Timers::Init();
+
+ // Check that double initialisation throws an exception
+ #ifndef NDEBUG
+ TEST_CHECK_THROWS(Timers::Init(), CommonException,
+ AssertFailed);
+ #endif
+
+ // Check that we can clean up the timers
+ Timers::Cleanup();
+
+ // Check that double cleanup throws an exception
+ #ifndef NDEBUG
+ TEST_CHECK_THROWS(Timers::Cleanup(), CommonException,
+ AssertFailed);
+ #endif
+
+ Timers::Init();
+
+ Timer t0(0); // should never expire
+ Timer t1(1);
+ Timer t2(2);
+ Timer t3(3);
+
+ TEST_THAT(!t0.HasExpired());
+ TEST_THAT(!t1.HasExpired());
+ TEST_THAT(!t2.HasExpired());
+ TEST_THAT(!t3.HasExpired());
+
+ safe_sleep(1);
+ TEST_THAT(!t0.HasExpired());
+ TEST_THAT(t1.HasExpired());
+ TEST_THAT(!t2.HasExpired());
+ TEST_THAT(!t3.HasExpired());
+
+ safe_sleep(1);
+ TEST_THAT(!t0.HasExpired());
+ TEST_THAT(t1.HasExpired());
+ TEST_THAT(t2.HasExpired());
+ TEST_THAT(!t3.HasExpired());
+
+ t1 = Timer(1);
+ t2 = Timer(2);
+ TEST_THAT(!t0.HasExpired());
+ TEST_THAT(!t1.HasExpired());
+ TEST_THAT(!t2.HasExpired());
+
+ safe_sleep(1);
+ TEST_THAT(!t0.HasExpired());
+ TEST_THAT(t1.HasExpired());
+ TEST_THAT(!t2.HasExpired());
+ TEST_THAT(t3.HasExpired());
+
+ // Leave timers initialised for rest of test.
+ // Test main() will cleanup after test finishes.
static char *testfilelines[] =
{
@@ -537,7 +750,7 @@ int test(int argc, const char *argv[])
TEST_THAT(elist.SizeOfDefiniteList() == 4);
// Add regex entries
- #ifdef HAVE_REGEX_H
+ #ifdef HAVE_REGEX_SUPPORT
elist.AddRegexEntries(std::string("[a-d]+\\.reg$" "\x01" "EXCLUDE" "\x01" "^exclude$"));
elist.AddRegexEntries(std::string(""));
TEST_CHECK_THROWS(elist.AddRegexEntries(std::string("[:not_valid")), CommonException, BadRegularExpression);
@@ -569,7 +782,7 @@ int test(int argc, const char *argv[])
TEST_THAT(elist.IsExcluded("thingdefthree")
== !CASE_SENSITIVE);
- #ifdef HAVE_REGEX_H
+ #ifdef HAVE_REGEX_SUPPORT
TEST_THAT(elist.IsExcluded(std::string("b.reg")) == true);
TEST_THAT(elist.IsExcluded(std::string("B.reg")) == !CASE_SENSITIVE);
TEST_THAT(elist.IsExcluded(std::string("b.Reg")) == !CASE_SENSITIVE);
@@ -583,9 +796,86 @@ int test(int argc, const char *argv[])
#endif
#undef CASE_SENSITIVE
+
+ TestLogger logger(Log::WARNING);
+ TEST_THAT(!logger.IsTriggered());
+ elist.AddDefiniteEntries(std::string("/foo"));
+ TEST_THAT(!logger.IsTriggered());
+ elist.AddDefiniteEntries(std::string("/foo/"));
+ TEST_THAT(logger.IsTriggered());
+ logger.Reset();
+ elist.AddDefiniteEntries(std::string("/foo"
+ DIRECTORY_SEPARATOR));
+ TEST_THAT(logger.IsTriggered());
+ logger.Reset();
+ elist.AddDefiniteEntries(std::string("/foo"
+ DIRECTORY_SEPARATOR "bar\x01/foo"));
+ TEST_THAT(!logger.IsTriggered());
+ elist.AddDefiniteEntries(std::string("/foo"
+ DIRECTORY_SEPARATOR "bar\x01/foo"
+ DIRECTORY_SEPARATOR));
+ TEST_THAT(logger.IsTriggered());
}
test_conversions();
+ // test that we can use Archive and CollectInBufferStream
+ // to read and write arbitrary types to a memory buffer
+
+ {
+ CollectInBufferStream buffer;
+ ASSERT(buffer.GetPosition() == 0);
+
+ {
+ Archive archive(buffer, 0);
+ ASSERT(buffer.GetPosition() == 0);
+
+ archive.Write((bool) true);
+ archive.Write((bool) false);
+ archive.Write((int) 0x12345678);
+ archive.Write((int) 0x87654321);
+ archive.Write((int64_t) 0x0badfeedcafebabeLL);
+ archive.Write((uint64_t) 0xfeedfacedeadf00dLL);
+ archive.Write((uint8_t) 0x01);
+ archive.Write((uint8_t) 0xfe);
+ archive.Write(std::string("hello world!"));
+ archive.Write(std::string("goodbye cruel world!"));
+ }
+
+ CollectInBufferStream buf2;
+ buf2.Write(buffer.GetBuffer(), buffer.GetSize());
+ TEST_THAT(buf2.GetPosition() == buffer.GetSize());
+
+ buf2.SetForReading();
+ TEST_THAT(buf2.GetPosition() == 0);
+
+ {
+ Archive archive(buf2, 0);
+ TEST_THAT(buf2.GetPosition() == 0);
+
+ bool b;
+ archive.Read(b); TEST_THAT(b == true);
+ archive.Read(b); TEST_THAT(b == false);
+
+ int i;
+ archive.Read(i); TEST_THAT(i == 0x12345678);
+ archive.Read(i); TEST_THAT((unsigned int)i == 0x87654321);
+
+ uint64_t i64;
+ archive.Read(i64); TEST_THAT(i64 == 0x0badfeedcafebabeLL);
+ archive.Read(i64); TEST_THAT(i64 == 0xfeedfacedeadf00dLL);
+
+ uint8_t i8;
+ archive.Read(i8); TEST_THAT(i8 == 0x01);
+ archive.Read(i8); TEST_THAT(i8 == 0xfe);
+
+ std::string s;
+ archive.Read(s); TEST_THAT(s == "hello world!");
+ archive.Read(s); TEST_THAT(s == "goodbye cruel world!");
+
+ TEST_THAT(!buf2.StreamDataLeft());
+ }
+ }
+
return 0;
}
diff --git a/test/raidfile/intercept.cpp b/test/raidfile/intercept.cpp
deleted file mode 100644
index 6df344e1..00000000
--- a/test/raidfile/intercept.cpp
+++ /dev/null
@@ -1,272 +0,0 @@
-// --------------------------------------------------------------------------
-//
-// File
-// Name: intercept.cpp
-// Purpose: Syscall interception code for the raidfile test
-// Created: 2003/07/22
-//
-// --------------------------------------------------------------------------
-
-#include "Box.h"
-
-#ifdef HAVE_SYS_SYSCALL_H
- #include <sys/syscall.h>
-#endif
-#include <sys/types.h>
-#include <unistd.h>
-#include <sys/uio.h>
-#include <errno.h>
-
-#ifndef PLATFORM_CLIB_FNS_INTERCEPTION_IMPOSSIBLE
-
-#if !defined(HAVE_SYSCALL) && !defined(HAVE___SYSCALL) && !defined(HAVE___SYSCALL_NEED_DEFN)
- #define PLATFORM_NO_SYSCALL
-#endif
-
-#ifdef PLATFORM_NO_SYSCALL
- // For some reason, syscall just doesn't work on Darwin
- // so instead, we build functions using assembler in a varient
- // of the technique used in the Darwin Libc
- extern "C" int
- TEST_open(const char *path, int flags, mode_t mode);
- extern "C" int
- TEST_close(int d);
- extern "C" ssize_t
- TEST_write(int d, const void *buf, size_t nbytes);
- extern "C" ssize_t
- TEST_read(int d, void *buf, size_t nbytes);
- extern "C" ssize_t
- TEST_readv(int d, const struct iovec *iov, int iovcnt);
- extern "C" off_t
- TEST_lseek(int fildes, off_t offset, int whence);
-#else
- #ifdef HAVE___SYSCALL_NEED_DEFN
- // Need this, not declared in syscall.h nor unistd.h
- extern "C" off_t __syscall(quad_t number, ...);
- #endif
- #ifndef HAVE_SYSCALL
- #undef syscall
- #define syscall __syscall
- #endif
-#endif
-
-#include <string.h>
-#include <stdio.h>
-
-#include "MemLeakFindOn.h"
-
-bool intercept_enabled = false;
-const char *intercept_filename = 0;
-int intercept_filedes = -1;
-off_t intercept_errorafter = 0;
-int intercept_errno = 0;
-int intercept_syscall = 0;
-off_t intercept_filepos = 0;
-
-#define SIZE_ALWAYS_ERROR -773
-
-void intercept_clear_setup()
-{
- intercept_enabled = false;
- intercept_filename = 0;
- intercept_filedes = -1;
- intercept_errorafter = 0;
- intercept_syscall = 0;
- intercept_filepos = 0;
-}
-
-bool intercept_triggered()
-{
- return !intercept_enabled;
-}
-
-void intercept_setup_error(const char *filename, unsigned int errorafter, int errortoreturn, int syscalltoerror)
-{
- TRACE4("Setup for error: %s, after %d, err %d, syscall %d\n", filename, errorafter, errortoreturn, syscalltoerror);
- intercept_enabled = true;
- intercept_filename = filename;
- intercept_filedes = -1;
- intercept_errorafter = errorafter;
- intercept_syscall = syscalltoerror;
- intercept_errno = errortoreturn;
- intercept_filepos = 0;
-}
-
-bool intercept_errornow(int d, int size, int syscallnum)
-{
- if(intercept_filedes != -1 && d == intercept_filedes && syscallnum == intercept_syscall)
- {
- //printf("Checking for err, %d, %d, %d\n", d, size, syscallnum);
- if(size == SIZE_ALWAYS_ERROR)
- {
- // Looks good for an error!
- TRACE2("Returning error %d for syscall %d\n", intercept_errno, syscallnum);
- return true;
- }
- // where are we in the file?
- if(intercept_filepos >= intercept_errorafter || intercept_filepos >= ((off_t)intercept_errorafter - size))
- {
- TRACE3("Returning error %d for syscall %d, file pos %d\n", intercept_errno, syscallnum, (int)intercept_filepos);
- return true;
- }
- }
- return false; // no error please!
-}
-
-int intercept_reterr()
-{
- intercept_enabled = false;
- intercept_filename = 0;
- intercept_filedes = -1;
- intercept_errorafter = 0;
- intercept_syscall = 0;
- return intercept_errno;
-}
-
-#define CHECK_FOR_FAKE_ERROR_COND(D, S, CALL, FAILRES) \
- if(intercept_enabled) \
- { \
- if(intercept_errornow(D, S, CALL)) \
- { \
- errno = intercept_reterr(); \
- return FAILRES; \
- } \
- }
-
-extern "C" int
-open(const char *path, int flags, mode_t mode)
-{
- if(intercept_enabled)
- {
- if(intercept_syscall == SYS_open && strcmp(path, intercept_filename) == 0)
- {
- errno = intercept_reterr();
- return -1;
- }
- }
-#ifdef PLATFORM_NO_SYSCALL
- int r = TEST_open(path, flags, mode);
-#else
- int r = syscall(SYS_open, path, flags, mode);
-#endif
- if(intercept_enabled && intercept_filedes == -1)
- {
- // Right file?
- if(strcmp(intercept_filename, path) == 0)
- {
- intercept_filedes = r;
- //printf("Found file to intercept, h = %d\n", r);
- }
- }
- return r;
-}
-
-extern "C" int
-open64(const char *path, int flags, mode_t mode)
-{
- // With _FILE_OFFSET_BITS set to 64 this should really use (flags |
- // O_LARGEFILE) here, but not actually necessary for the tests and not
- // worth the trouble finding O_LARGEFILE
- return open(path, flags, mode);
-}
-
-extern "C" int
-close(int d)
-{
- CHECK_FOR_FAKE_ERROR_COND(d, SIZE_ALWAYS_ERROR, SYS_close, -1);
-#ifdef PLATFORM_NO_SYSCALL
- int r = TEST_close(d);
-#else
- int r = syscall(SYS_close, d);
-#endif
- if(r == 0)
- {
- if(d == intercept_filedes)
- {
- intercept_filedes = -1;
- }
- }
- return r;
-}
-
-extern "C" ssize_t
-write(int d, const void *buf, size_t nbytes)
-{
- CHECK_FOR_FAKE_ERROR_COND(d, nbytes, SYS_write, -1);
-#ifdef PLATFORM_NO_SYSCALL
- int r = TEST_write(d, buf, nbytes);
-#else
- int r = syscall(SYS_write, d, buf, nbytes);
-#endif
- if(r != -1)
- {
- intercept_filepos += r;
- }
- return r;
-}
-
-extern "C" ssize_t
-read(int d, void *buf, size_t nbytes)
-{
- CHECK_FOR_FAKE_ERROR_COND(d, nbytes, SYS_read, -1);
-#ifdef PLATFORM_NO_SYSCALL
- int r = TEST_read(d, buf, nbytes);
-#else
- int r = syscall(SYS_read, d, buf, nbytes);
-#endif
- if(r != -1)
- {
- intercept_filepos += r;
- }
- return r;
-}
-
-extern "C" ssize_t
-readv(int d, const struct iovec *iov, int iovcnt)
-{
- // how many bytes?
- int nbytes = 0;
- for(int b = 0; b < iovcnt; ++b)
- {
- nbytes += iov[b].iov_len;
- }
-
- CHECK_FOR_FAKE_ERROR_COND(d, nbytes, SYS_readv, -1);
-#ifdef PLATFORM_NO_SYSCALL
- int r = TEST_readv(d, iov, iovcnt);
-#else
- int r = syscall(SYS_readv, d, iov, iovcnt);
-#endif
- if(r != -1)
- {
- intercept_filepos += r;
- }
- return r;
-}
-
-extern "C" off_t
-lseek(int fildes, off_t offset, int whence)
-{
- // random magic for lseek syscall, see /usr/src/lib/libc/sys/lseek.c
- CHECK_FOR_FAKE_ERROR_COND(fildes, 0, SYS_lseek, -1);
-#ifdef PLATFORM_NO_SYSCALL
- int r = TEST_lseek(fildes, offset, whence);
-#else
- #ifdef HAVE_LSEEK_DUMMY_PARAM
- off_t r = syscall(SYS_lseek, fildes, 0 /* extra 0 required here! */, offset, whence);
- #elif defined(_FILE_OFFSET_BITS)
- // Don't bother trying to call SYS__llseek on 32 bit since it is
- // fiddly and not needed for the tests
- off_t r = syscall(SYS_lseek, fildes, (uint32_t)offset, whence);
- #else
- off_t r = syscall(SYS_lseek, fildes, offset, whence);
- #endif
-#endif
- if(r != -1)
- {
- intercept_filepos = r;
- }
- return r;
-}
-
-#endif // n PLATFORM_CLIB_FNS_INTERCEPTION_IMPOSSIBLE
diff --git a/test/raidfile/testraidfile.cpp b/test/raidfile/testraidfile.cpp
index 1e510486..40703de5 100644
--- a/test/raidfile/testraidfile.cpp
+++ b/test/raidfile/testraidfile.cpp
@@ -12,7 +12,10 @@
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
+
+#ifdef HAVE_SYSCALL
#include <sys/syscall.h>
+#endif
#include <string.h>
@@ -207,16 +210,24 @@ void testReadingFileContents(int set, const char *filename, void *data, int data
bytesread += r;
}
TEST_THAT(!readstream4.StreamDataLeft()); // check IOStream interface is correct
+ pread.reset();
// Be nasty, and create some errors for the RAID stuff to recover from...
if(TestRAIDProperties)
{
char stripe1fn[256], stripe1fnRename[256];
- sprintf(stripe1fn, "testfiles/%d_%d/%s.rf", set, startDisc, filename);
- sprintf(stripe1fnRename, "testfiles/%d_%d/%s.rf-REMOVED", set, startDisc, filename);
+ sprintf(stripe1fn, "testfiles" DIRECTORY_SEPARATOR "%d_%d"
+ DIRECTORY_SEPARATOR "%s.rf", set, startDisc, filename);
+ sprintf(stripe1fnRename, "testfiles" DIRECTORY_SEPARATOR "%d_%d"
+ DIRECTORY_SEPARATOR "%s.rf-REMOVED", set, startDisc,
+ filename);
char stripe2fn[256], stripe2fnRename[256];
- sprintf(stripe2fn, "testfiles/%d_%d/%s.rf", set, (startDisc + 1) % RAID_NUMBER_DISCS, filename);
- sprintf(stripe2fnRename, "testfiles/%d_%d/%s.rf-REMOVED", set, (startDisc + 1) % RAID_NUMBER_DISCS, filename);
+ sprintf(stripe2fn, "testfiles" DIRECTORY_SEPARATOR "%d_%d"
+ DIRECTORY_SEPARATOR "%s.rf", set,
+ (startDisc + 1) % RAID_NUMBER_DISCS, filename);
+ sprintf(stripe2fnRename, "testfiles" DIRECTORY_SEPARATOR "%d_%d"
+ DIRECTORY_SEPARATOR "%s.rf-REMOVED", set,
+ (startDisc + 1) % RAID_NUMBER_DISCS, filename);
// Read with stripe1 + parity
TEST_THAT(::rename(stripe2fn, stripe2fnRename) == 0);
@@ -252,9 +263,15 @@ void testReadingFileContents(int set, const char *filename, void *data, int data
}
mungefilename[m++] = '\0';
char stripe1munge[256];
- sprintf(stripe1munge, "testfiles/%d_%d/.raidfile-unreadable/%s", set, startDisc, mungefilename);
+ sprintf(stripe1munge, "testfiles" DIRECTORY_SEPARATOR "%d_%d"
+ DIRECTORY_SEPARATOR ".raidfile-unreadable"
+ DIRECTORY_SEPARATOR "%s", set, startDisc,
+ mungefilename);
char stripe2munge[256];
- sprintf(stripe2munge, "testfiles/%d_%d/.raidfile-unreadable/%s", set, (startDisc + 1) % RAID_NUMBER_DISCS, mungefilename);
+ sprintf(stripe2munge, "testfiles" DIRECTORY_SEPARATOR "%d_%d"
+ DIRECTORY_SEPARATOR ".raidfile-unreadable"
+ DIRECTORY_SEPARATOR "%s", set,
+ (startDisc + 1) % RAID_NUMBER_DISCS, mungefilename);
#ifdef TRF_CAN_INTERCEPT
@@ -359,10 +376,12 @@ void testReadWriteFileDo(int set, const char *filename, void *data, int datasize
write4.Write(data, datasize);
// This time, don't discard and transform it to a RAID File
char writefnPre[256];
- sprintf(writefnPre, "testfiles/%d_%d/%s.rfwX", set, startDisc, filename);
+ sprintf(writefnPre, "testfiles" DIRECTORY_SEPARATOR "%d_%d"
+ DIRECTORY_SEPARATOR "%s.rfwX", set, startDisc, filename);
TEST_THAT(TestFileExists(writefnPre));
char writefn[256];
- sprintf(writefn, "testfiles/%d_%d/%s.rfw", set, startDisc, filename);
+ sprintf(writefn, "testfiles" DIRECTORY_SEPARATOR "%d_%d"
+ DIRECTORY_SEPARATOR "%s.rfw", set, startDisc, filename);
int usageInBlocks = write4.GetDiscUsageInBlocks();
write4.Commit(DoTransform);
// Check that files are nicely done...
@@ -390,14 +409,19 @@ void testReadWriteFileDo(int set, const char *filename, void *data, int datasize
fs1 = ((fullblocks / 2)+1) * RAID_BLOCK_SIZE;
}
char stripe1fn[256];
- sprintf(stripe1fn, "testfiles/%d_%d/%s.rf", set, startDisc, filename);
+ sprintf(stripe1fn, "testfiles" DIRECTORY_SEPARATOR "%d_%d"
+ DIRECTORY_SEPARATOR "%s.rf", set, startDisc, filename);
TEST_THAT(TestGetFileSize(stripe1fn) == fs1);
char stripe2fn[256];
- sprintf(stripe2fn, "testfiles/%d_%d/%s.rf", set, (startDisc + 1) % RAID_NUMBER_DISCS, filename);
+ sprintf(stripe2fn, "testfiles" DIRECTORY_SEPARATOR "%d_%d"
+ DIRECTORY_SEPARATOR "%s.rf", set,
+ (startDisc + 1) % RAID_NUMBER_DISCS, filename);
TEST_THAT(TestGetFileSize(stripe2fn) == (int)(datasize - fs1));
// Parity file size
char parityfn[256];
- sprintf(parityfn, "testfiles/%d_%d/%s.rf", set, (startDisc + 2) % RAID_NUMBER_DISCS, filename);
+ sprintf(parityfn, "testfiles" DIRECTORY_SEPARATOR "%d_%d"
+ DIRECTORY_SEPARATOR "%s.rf", set,
+ (startDisc + 2) % RAID_NUMBER_DISCS, filename);
// Mildly complex calculation
unsigned int blocks = datasize / RAID_BLOCK_SIZE;
unsigned int bytesOver = datasize % RAID_BLOCK_SIZE;
@@ -436,14 +460,16 @@ void testReadWriteFileDo(int set, const char *filename, void *data, int datasize
if(datasize > (3*1024))
{
int f;
- TEST_THAT((f = ::open(stripe1fn, O_RDONLY, 0)) != -1);
+ TEST_THAT((f = ::open(stripe1fn, O_RDONLY | O_BINARY,
+ 0)) != -1);
TEST_THAT(sizeof(testblock) == ::read(f, testblock, sizeof(testblock)));
for(unsigned int q = 0; q < sizeof(testblock); ++q)
{
TEST_THAT(testblock[q] == ((char*)data)[q]);
}
::close(f);
- TEST_THAT((f = ::open(stripe2fn, O_RDONLY, 0)) != -1);
+ TEST_THAT((f = ::open(stripe2fn, O_RDONLY | O_BINARY,
+ 0)) != -1);
TEST_THAT(sizeof(testblock) == ::read(f, testblock, sizeof(testblock)));
for(unsigned int q = 0; q < sizeof(testblock); ++q)
{
@@ -536,7 +562,9 @@ void test_overwrites()
// Generate a random pre-existing write file (and ensure that it doesn't exist already)
int f;
- TEST_THAT((f = ::open("testfiles/0_2/overwrite_B.rfwX", O_WRONLY | O_CREAT | O_EXCL, 0755)) != -1);
+ TEST_THAT((f = ::open("testfiles" DIRECTORY_SEPARATOR "0_2"
+ DIRECTORY_SEPARATOR "overwrite_B.rfwX",
+ O_WRONLY | O_CREAT | O_EXCL | O_BINARY, 0755)) != -1);
TEST_THAT(::write(f, "TESTTEST", 8) == 8);
::close(f);
@@ -557,7 +585,7 @@ int test(int argc, const char *argv[])
// Initialise the controller
RaidFileController &rcontroller = RaidFileController::GetController();
- rcontroller.Initialise("testfiles/raidfile.conf");
+ rcontroller.Initialise("testfiles" DIRECTORY_SEPARATOR "raidfile.conf");
// some data
char data[TEST_DATA_SIZE];
@@ -574,9 +602,12 @@ int test(int argc, const char *argv[])
// Try creating a directory
RaidFileWrite::CreateDirectory(0, "test-dir");
- TEST_THAT(TestDirExists("testfiles/0_0/test-dir"));
- TEST_THAT(TestDirExists("testfiles/0_1/test-dir"));
- TEST_THAT(TestDirExists("testfiles/0_2/test-dir"));
+ TEST_THAT(TestDirExists("testfiles" DIRECTORY_SEPARATOR "0_0"
+ DIRECTORY_SEPARATOR "test-dir"));
+ TEST_THAT(TestDirExists("testfiles" DIRECTORY_SEPARATOR "0_1"
+ DIRECTORY_SEPARATOR "test-dir"));
+ TEST_THAT(TestDirExists("testfiles" DIRECTORY_SEPARATOR "0_2"
+ DIRECTORY_SEPARATOR "test-dir"));
TEST_THAT(RaidFileRead::DirectoryExists(0, "test-dir"));
TEST_THAT(!RaidFileRead::DirectoryExists(0, "test-dir-not"));
@@ -608,9 +639,12 @@ int test(int argc, const char *argv[])
// Before it's deleted, check to see the contents are as expected
int f;
- TEST_THAT((f = ::open("testfiles/0_2/test1.rfwX", O_RDONLY, 0)) >= 0);
+ TEST_THAT((f = ::open("testfiles" DIRECTORY_SEPARATOR "0_2"
+ DIRECTORY_SEPARATOR "test1.rfwX", O_RDONLY | O_BINARY, 0))
+ >= 0);
char buffer[sizeof(data)];
- TEST_THAT(::read(f, buffer, sizeof(buffer)) == sizeof(buffer));
+ int bytes_read = ::read(f, buffer, sizeof(buffer));
+ TEST_THAT(bytes_read == sizeof(buffer));
for(unsigned int l = 0; l < 1024; ++l)
{
TEST_THAT(buffer[l] == data[l]);
@@ -624,7 +658,8 @@ int test(int argc, const char *argv[])
TEST_THAT(buffer[l+2048+sizeof(data2)] == data2[l]);
}
TEST_THAT(::lseek(f, sizeof(data), SEEK_SET) == sizeof(buffer));
- TEST_THAT(::read(f, buffer, sizeof(buffer)) == sizeof(buffer));
+ bytes_read = ::read(f, buffer, sizeof(buffer));
+ TEST_THAT(bytes_read == sizeof(buffer));
for(unsigned int l = 0; l < 1024; ++l)
{
TEST_THAT(buffer[l] == data[l]);
@@ -635,7 +670,9 @@ int test(int argc, const char *argv[])
// Commit the data
write1.Commit();
- TEST_THAT((f = ::open("testfiles/0_2/test1.rfw", O_RDONLY, 0)) >= 0);
+ TEST_THAT((f = ::open("testfiles" DIRECTORY_SEPARATOR "0_2"
+ DIRECTORY_SEPARATOR "test1.rfw", O_RDONLY | O_BINARY, 0))
+ >= 0);
::close(f);
// Now try and read it
@@ -687,7 +724,9 @@ int test(int argc, const char *argv[])
write2.Write(data, sizeof(data));
// This time, discard it
write2.Discard();
- TEST_THAT((f = ::open("testfiles/0_2/test1.rfw", O_RDONLY, 0)) == -1);
+ TEST_THAT((f = ::open("testfiles" DIRECTORY_SEPARATOR "0_2"
+ DIRECTORY_SEPARATOR "test1.rfw", O_RDONLY | O_BINARY, 0))
+ == -1);
// And leaving it there...
RaidFileWrite writeLeave(0, "test1");
@@ -695,7 +734,9 @@ int test(int argc, const char *argv[])
writeLeave.Write(data, sizeof(data));
// This time, commit it
writeLeave.Commit();
- TEST_THAT((f = ::open("testfiles/0_2/test1.rfw", O_RDONLY, 0)) != -1);
+ TEST_THAT((f = ::open("testfiles" DIRECTORY_SEPARATOR "0_2"
+ DIRECTORY_SEPARATOR "test1.rfw", O_RDONLY | O_BINARY, 0))
+ != -1);
::close(f);
// Then check that the thing will refuse to open it again.
@@ -712,7 +753,8 @@ int test(int argc, const char *argv[])
write3b.Write(data + 3, sizeof(data) - 3);
write3b.Commit();
// Test it
- testReadingFileContents(0, "test1", data+3, sizeof(data) - 3, false /*TestRAIDProperties*/);
+ testReadingFileContents(0, "test1", data+3, sizeof(data) - 3, false
+ /* TestRAIDProperties */);
// And once again, but this time making it a raid file
RaidFileWrite write3c(0, "test1");
@@ -721,7 +763,8 @@ int test(int argc, const char *argv[])
write3c.Write(data + 7, sizeof(data) - 7);
write3c.Commit(true); // make RAID
// Test it
- testReadingFileContents(0, "test1", data+7, sizeof(data) - 7, false /*TestRAIDProperties*/);
+ testReadingFileContents(0, "test1", data+7, sizeof(data) - 7, false
+ /*TestRAIDProperties*/);
// Test opening a file which doesn't exist
TEST_CHECK_THROWS(
@@ -736,20 +779,23 @@ int test(int argc, const char *argv[])
w.Commit(true);
// Try removing the parity file
- TEST_THAT(::rename("testfiles/0_0/damage.rf", "testfiles/0_0/damage.rf-NT") == 0);
+ TEST_THAT(::rename("testfiles" DIRECTORY_SEPARATOR "0_0"
+ DIRECTORY_SEPARATOR "damage.rf",
+ "testfiles" DIRECTORY_SEPARATOR "0_0"
+ DIRECTORY_SEPARATOR "damage.rf-NT") == 0);
{
std::auto_ptr<RaidFileRead> pr0 = RaidFileRead::Open(0, "damage");
pr0->Read(buffer, sizeof(data));
}
- TEST_THAT(::rename("testfiles/0_0/damage.rf-NT", "testfiles/0_0/damage.rf") == 0);
-
+ TEST_THAT(::rename("testfiles" DIRECTORY_SEPARATOR "0_0" DIRECTORY_SEPARATOR "damage.rf-NT", "testfiles" DIRECTORY_SEPARATOR "0_0" DIRECTORY_SEPARATOR "damage.rf") == 0);
+
// Delete one of the files
- TEST_THAT(::unlink("testfiles/0_1/damage.rf") == 0); // stripe 1
+ TEST_THAT(::unlink("testfiles" DIRECTORY_SEPARATOR "0_1" DIRECTORY_SEPARATOR "damage.rf") == 0); // stripe 1
#ifdef TRF_CAN_INTERCEPT
// Open it and read...
{
- intercept_setup_error("testfiles/0_2/damage.rf", 0, EIO, SYS_read); // stripe 2
+ intercept_setup_error("testfiles" DIRECTORY_SEPARATOR "0_2" DIRECTORY_SEPARATOR "damage.rf", 0, EIO, SYS_read); // stripe 2
std::auto_ptr<RaidFileRead> pr1 = RaidFileRead::Open(0, "damage");
TEST_CHECK_THROWS(
pr1->Read(buffer, sizeof(data)),
@@ -761,7 +807,7 @@ int test(int argc, const char *argv[])
#endif //TRF_CAN_INTERCEPT
// Delete another
- TEST_THAT(::unlink("testfiles/0_0/damage.rf") == 0); // parity
+ TEST_THAT(::unlink("testfiles" DIRECTORY_SEPARATOR "0_0" DIRECTORY_SEPARATOR "damage.rf") == 0); // parity
TEST_CHECK_THROWS(
std::auto_ptr<RaidFileRead> pread2 = RaidFileRead::Open(0, "damage"),
@@ -772,22 +818,22 @@ int test(int argc, const char *argv[])
{
RaidFileWrite::CreateDirectory(0, "dirread");
// Make some contents
- RaidFileWrite::CreateDirectory(0, "dirread/dfsdf1");
- RaidFileWrite::CreateDirectory(0, "dirread/ponwq2");
+ RaidFileWrite::CreateDirectory(0, "dirread" DIRECTORY_SEPARATOR "dfsdf1");
+ RaidFileWrite::CreateDirectory(0, "dirread" DIRECTORY_SEPARATOR "ponwq2");
{
- RaidFileWrite w(0, "dirread/sdf9873241");
+ RaidFileWrite w(0, "dirread" DIRECTORY_SEPARATOR "sdf9873241");
w.Open();
w.Write(data, sizeof(data));
w.Commit(true);
}
{
- RaidFileWrite w(0, "dirread/fsdcxjni3242");
+ RaidFileWrite w(0, "dirread" DIRECTORY_SEPARATOR "fsdcxjni3242");
w.Open();
w.Write(data, sizeof(data));
w.Commit(true);
}
{
- RaidFileWrite w(0, "dirread/cskjnds3");
+ RaidFileWrite w(0, "dirread" DIRECTORY_SEPARATOR "cskjnds3");
w.Open();
w.Write(data, sizeof(data));
w.Commit(false);
@@ -803,15 +849,15 @@ int test(int argc, const char *argv[])
TEST_THAT(true == RaidFileRead::ReadDirectoryContents(0, std::string("dirread"), RaidFileRead::DirReadType_DirsOnly, names));
TEST_THAT(list_matches(names, dir_list1));
// Delete things
- TEST_THAT(::unlink("testfiles/0_0/dirread/sdf9873241.rf") == 0);
+ TEST_THAT(::unlink("testfiles" DIRECTORY_SEPARATOR "0_0" DIRECTORY_SEPARATOR "dirread" DIRECTORY_SEPARATOR "sdf9873241.rf") == 0);
TEST_THAT(true == RaidFileRead::ReadDirectoryContents(0, std::string("dirread"), RaidFileRead::DirReadType_FilesOnly, names));
TEST_THAT(list_matches(names, file_list1));
// Delete something else so that it's not recoverable
- TEST_THAT(::unlink("testfiles/0_1/dirread/sdf9873241.rf") == 0);
+ TEST_THAT(::unlink("testfiles" DIRECTORY_SEPARATOR "0_1" DIRECTORY_SEPARATOR "dirread" DIRECTORY_SEPARATOR "sdf9873241.rf") == 0);
TEST_THAT(false == RaidFileRead::ReadDirectoryContents(0, std::string("dirread"), RaidFileRead::DirReadType_FilesOnly, names));
TEST_THAT(list_matches(names, file_list1));
// And finally...
- TEST_THAT(::unlink("testfiles/0_2/dirread/sdf9873241.rf") == 0);
+ TEST_THAT(::unlink("testfiles" DIRECTORY_SEPARATOR "0_2" DIRECTORY_SEPARATOR "dirread" DIRECTORY_SEPARATOR "sdf9873241.rf") == 0);
TEST_THAT(true == RaidFileRead::ReadDirectoryContents(0, std::string("dirread"), RaidFileRead::DirReadType_FilesOnly, names));
TEST_THAT(list_matches(names, file_list2));
}
diff --git a/test/win32/testlibwin32.cpp b/test/win32/testlibwin32.cpp
index ca2989d8..fb735c56 100644
--- a/test/win32/testlibwin32.cpp
+++ b/test/win32/testlibwin32.cpp
@@ -6,12 +6,214 @@
#ifdef WIN32
+#include <assert.h>
+#include <AccCtrl.h>
+#include <Aclapi.h>
+
#include "../../bin/bbackupd/BackupDaemon.h"
#include "BoxPortsAndFiles.h"
#include "emu.h"
int main(int argc, char* argv[])
{
+ // ACL tests
+ char* exename = getenv("WINDIR");
+
+ PSID psidOwner;
+ PSID psidGroup;
+ PACL pDacl;
+ PSECURITY_DESCRIPTOR pSecurityDesc;
+
+ DWORD result = GetNamedSecurityInfo(
+ exename, // pObjectName
+ SE_FILE_OBJECT, // ObjectType
+ DACL_SECURITY_INFORMATION | // SecurityInfo
+ GROUP_SECURITY_INFORMATION |
+ OWNER_SECURITY_INFORMATION,
+ &psidOwner, // ppsidOwner,
+ &psidGroup, // ppsidGroup,
+ &pDacl, // ppDacl,
+ NULL, // ppSacl,
+ &pSecurityDesc // ppSecurityDescriptor
+ );
+ if (result != ERROR_SUCCESS)
+ {
+ printf("Error getting security info for '%s': error %d",
+ exename, result);
+ }
+ assert(result == ERROR_SUCCESS);
+
+ char namebuf[1024];
+ char domainbuf[1024];
+ SID_NAME_USE nametype;
+ DWORD namelen = sizeof(namebuf);
+ DWORD domainlen = sizeof(domainbuf);
+
+ assert(LookupAccountSid(NULL, psidOwner, namebuf, &namelen,
+ domainbuf, &domainlen, &nametype));
+
+ printf("Owner:\n");
+ printf("User name: %s\n", namebuf);
+ printf("Domain name: %s\n", domainbuf);
+ printf("Name type: %d\n", nametype);
+ printf("\n");
+
+ namelen = sizeof(namebuf);
+ domainlen = sizeof(domainbuf);
+
+ assert(LookupAccountSid(NULL, psidGroup, namebuf, &namelen,
+ domainbuf, &domainlen, &nametype));
+
+ printf("Group:\n");
+ printf("User name: %s\n", namebuf);
+ printf("Domain name: %s\n", domainbuf);
+ printf("Name type: %d\n", nametype);
+ printf("\n");
+
+ ULONG numEntries;
+ PEXPLICIT_ACCESS pEntries;
+ result = GetExplicitEntriesFromAcl
+ (
+ pDacl, // pAcl
+ &numEntries, // pcCountOfExplicitEntries,
+ &pEntries // pListOfExplicitEntries
+ );
+ assert(result == ERROR_SUCCESS);
+
+ printf("Found %lu explicit DACL entries for '%s'\n\n",
+ (unsigned long)numEntries, exename);
+
+ for (ULONG i = 0; i < numEntries; i++)
+ {
+ EXPLICIT_ACCESS* pEntry = &(pEntries[i]);
+ printf("DACL entry %lu:\n", (unsigned long)i);
+
+ DWORD perms = pEntry->grfAccessPermissions;
+ printf(" Access permissions: ", perms);
+
+ #define PRINT_PERM(name) \
+ if (perms & name) \
+ { \
+ printf(#name " "); \
+ perms &= ~name; \
+ }
+
+ PRINT_PERM(FILE_ADD_FILE);
+ PRINT_PERM(FILE_ADD_SUBDIRECTORY);
+ PRINT_PERM(FILE_ALL_ACCESS);
+ PRINT_PERM(FILE_APPEND_DATA);
+ PRINT_PERM(FILE_CREATE_PIPE_INSTANCE);
+ PRINT_PERM(FILE_DELETE_CHILD);
+ PRINT_PERM(FILE_EXECUTE);
+ PRINT_PERM(FILE_LIST_DIRECTORY);
+ PRINT_PERM(FILE_READ_ATTRIBUTES);
+ PRINT_PERM(FILE_READ_DATA);
+ PRINT_PERM(FILE_READ_EA);
+ PRINT_PERM(FILE_TRAVERSE);
+ PRINT_PERM(FILE_WRITE_ATTRIBUTES);
+ PRINT_PERM(FILE_WRITE_DATA);
+ PRINT_PERM(FILE_WRITE_EA);
+ PRINT_PERM(STANDARD_RIGHTS_READ);
+ PRINT_PERM(STANDARD_RIGHTS_WRITE);
+ PRINT_PERM(SYNCHRONIZE);
+ PRINT_PERM(DELETE);
+ PRINT_PERM(READ_CONTROL);
+ PRINT_PERM(WRITE_DAC);
+ PRINT_PERM(WRITE_OWNER);
+ PRINT_PERM(MAXIMUM_ALLOWED);
+ PRINT_PERM(GENERIC_ALL);
+ PRINT_PERM(GENERIC_EXECUTE);
+ PRINT_PERM(GENERIC_WRITE);
+ PRINT_PERM(GENERIC_READ);
+ printf("\n");
+
+ if (perms)
+ {
+ printf(" Bits left over: %08x\n", perms);
+ }
+ assert(!perms);
+
+ printf(" Access mode: ");
+ switch(pEntry->grfAccessMode)
+ {
+ case NOT_USED_ACCESS:
+ printf("NOT_USED_ACCESS\n"); break;
+ case GRANT_ACCESS:
+ printf("GRANT_ACCESS\n"); break;
+ case DENY_ACCESS:
+ printf("DENY_ACCESS\n"); break;
+ case REVOKE_ACCESS:
+ printf("REVOKE_ACCESS\n"); break;
+ case SET_AUDIT_SUCCESS:
+ printf("SET_AUDIT_SUCCESS\n"); break;
+ case SET_AUDIT_FAILURE:
+ printf("SET_AUDIT_FAILURE\n"); break;
+ default:
+ printf("Unknown (%08x)\n", pEntry->grfAccessMode);
+ }
+
+ printf(" Trustee: ");
+ assert(pEntry->Trustee.pMultipleTrustee == NULL);
+ assert(pEntry->Trustee.MultipleTrusteeOperation == NO_MULTIPLE_TRUSTEE);
+ switch(pEntry->Trustee.TrusteeForm)
+ {
+ case TRUSTEE_IS_SID:
+ {
+ PSID trusteeSid = (PSID)(pEntry->Trustee.ptstrName);
+
+ namelen = sizeof(namebuf);
+ domainlen = sizeof(domainbuf);
+
+ assert(LookupAccountSid(NULL, trusteeSid, namebuf, &namelen,
+ domainbuf, &domainlen, &nametype));
+
+ printf("SID of %s\\%s (%d)\n", domainbuf, namebuf, nametype);
+ }
+ break;
+ case TRUSTEE_IS_NAME:
+ printf("Name\n"); break;
+ case TRUSTEE_BAD_FORM:
+ printf("Bad form\n"); assert(0);
+ case TRUSTEE_IS_OBJECTS_AND_SID:
+ printf("Objects and SID\n"); break;
+ case TRUSTEE_IS_OBJECTS_AND_NAME:
+ printf("Objects and name\n"); break;
+ default:
+ printf("Unknown form\n"); assert(0);
+ }
+
+ printf(" Trustee type: ");
+ switch(pEntry->Trustee.TrusteeType)
+ {
+ case TRUSTEE_IS_UNKNOWN:
+ printf("Unknown type.\n"); break;
+ case TRUSTEE_IS_USER:
+ printf("User\n"); break;
+ case TRUSTEE_IS_GROUP:
+ printf("Group\n"); break;
+ case TRUSTEE_IS_DOMAIN:
+ printf("Domain\n"); break;
+ case TRUSTEE_IS_ALIAS:
+ printf("Alias\n"); break;
+ case TRUSTEE_IS_WELL_KNOWN_GROUP:
+ printf("Well-known group\n"); break;
+ case TRUSTEE_IS_DELETED:
+ printf("Deleted account\n"); break;
+ case TRUSTEE_IS_INVALID:
+ printf("Invalid trustee type\n"); break;
+ case TRUSTEE_IS_COMPUTER:
+ printf("Computer\n"); break;
+ default:
+ printf("Unknown type %d\n", pEntry->Trustee.TrusteeType);
+ assert(0);
+ }
+
+ printf("\n");
+ }
+
+ assert(LocalFree((HLOCAL)pEntries) == 0);
+ assert(LocalFree((HLOCAL)pSecurityDesc) == 0);
+
chdir("c:\\tmp");
openfile("test", O_CREAT, 0);
struct stat ourfs;
@@ -25,12 +227,11 @@ int main(int argc, char* argv[])
do
{
info = readdir(ourDir);
- if ( info ) printf("File/Dir name is : %s\r\n", info->d_name);
-
- }while ( info != NULL );
+ if (info) printf("File/Dir name is : %s\r\n", info->d_name);
+ }
+ while (info != NULL);
closedir(ourDir);
-
}
std::string diry("C:\\Projects\\boxbuild\\testfiles\\");
@@ -41,12 +242,12 @@ int main(int argc, char* argv[])
do
{
info = readdir(ourDir);
- if ( info == NULL ) break;
+ if (info == NULL) break;
std::string file(diry + info->d_name);
stat(file.c_str(), &ourfs);
- if ( info ) printf("File/Dir name is : %s\r\n", info->d_name);
-
- }while ( info != NULL );
+ if (info) printf("File/Dir name is : %s\r\n", info->d_name);
+ }
+ while ( info != NULL );
closedir(ourDir);
@@ -54,47 +255,70 @@ int main(int argc, char* argv[])
stat("c:\\windows", &ourfs);
stat("c:\\autoexec.bat", &ourfs);
- printf("Finished dir read");
-#if 0
- //remove - sleepycat include a version of getopt - mine never REALLY worked !
- //test our getopt function
- std::string commline("-q -c fgfgfg -f -l hello");
+ printf("Finished dir read\n");
- int c;
- while((c = getopt(commline.size(), (char * const *)commline.c_str(), "qwc:l:")) != -1)
+ //test our getopt function
+ char * test_argv[] =
{
- printf("switch = %c, param is %s\r\n", c, optarg);
- }
-#endif
+ "foobar.exe",
+ "-qwc",
+ "-",
+ "-c",
+ "fgfgfg",
+ "-f",
+ "-l",
+ "hello",
+ "-",
+ "force-sync",
+ NULL
+ };
+ int test_argc;
+ for (test_argc = 0; test_argv[test_argc]; test_argc++) { }
+ const char* opts = "qwc:l:";
+
+ assert(getopt(test_argc, test_argv, opts) == 'q');
+ assert(getopt(test_argc, test_argv, opts) == 'w');
+ assert(getopt(test_argc, test_argv, opts) == 'c');
+ assert(strcmp(optarg, "-") == 0);
+ assert(getopt(test_argc, test_argv, opts) == 'c');
+ assert(strcmp(optarg, "fgfgfg") == 0);
+ assert(getopt(test_argc, test_argv, opts) == '?');
+ assert(optopt == 'f');
+ assert(getopt(test_argc, test_argv, opts) == 'l');
+ assert(strcmp(optarg, "hello") == 0);
+ assert(getopt(test_argc, test_argv, opts) == -1);
+ // assert(optopt == 0); // no more options
+ assert(strcmp(test_argv[optind], "-") == 0);
+ assert(strcmp(test_argv[optind+1], "force-sync") == 0);
//end of getopt test
//now test our statfs funct
stat("c:\\cert.cer", &ourfs);
-
-
char *timee;
timee = ctime(&ourfs.st_mtime);
- if ( S_ISREG(ourfs.st_mode))
+ if (S_ISREG(ourfs.st_mode))
{
- printf("is a normal file");
+ printf("is a normal file\n");
}
else
{
- printf("is a directory?");
+ printf("is a directory?\n");
+ exit(1);
}
- lstat("c:\\windows", &ourfs);
+ lstat(getenv("WINDIR"), &ourfs);
if ( S_ISDIR(ourfs.st_mode))
{
- printf("is a directory");
+ printf("is a directory\n");
}
else
{
- printf("is a file?");
+ printf("is a file?\n");
+ exit(1);
}
//test the syslog functions
@@ -105,6 +329,7 @@ int main(int argc, char* argv[])
closelog();
+ /*
//first off get the path name for the default
char buf[MAX_PATH];
@@ -112,7 +337,7 @@ int main(int argc, char* argv[])
std::string buffer(buf);
std::string conf("-c " + buffer.substr(0,(buffer.find("win32test.exe"))) + "bbackupd.conf");
//std::string conf( "-c " + buffer.substr(0,(buffer.find("bbackupd.exe"))) + "bbackupd.conf");
-
+ */
return 0;
}