summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/backupdiff/difftestfiles.cpp2
-rw-r--r--test/backupdiff/testbackupdiff.cpp79
-rw-r--r--test/backupdiff/testextra2
-rw-r--r--test/backupstore/testbackupstore.cpp148
-rw-r--r--test/backupstore/testextra2
-rw-r--r--test/backupstorefix/testbackupstorefix.cpp135
-rw-r--r--test/backupstorefix/testextra2
-rwxr-xr-xtest/backupstorefix/testfiles/testbackupstorefix.pl6
-rwxr-xr-xtest/backupstorefix/testfiles/testbackupstorefix.pl.in213
-rw-r--r--test/backupstorepatch/testbackupstorepatch.cpp34
-rw-r--r--test/backupstorepatch/testextra2
-rw-r--r--test/basicserver/Makefile.extra8
-rw-r--r--test/basicserver/TestCommands.cpp4
-rw-r--r--test/basicserver/TestContext.cpp2
-rw-r--r--test/basicserver/TestContext.h2
-rw-r--r--test/basicserver/testbasicserver.cpp265
-rw-r--r--test/basicserver/testfiles/srv4.conf2
-rw-r--r--test/bbackupd/Makefile.extra1
-rw-r--r--test/bbackupd/testbbackupd.cpp2543
-rw-r--r--test/bbackupd/testextra2
-rw-r--r--test/bbackupd/testfiles/bbackupd-temploc.conf54
-rwxr-xr-x[-rw-r--r--]test/bbackupd/testfiles/bbackupd.conf10
-rw-r--r--test/bbackupd/testfiles/bbackupd.conf.in54
-rwxr-xr-xtest/bbackupd/testfiles/extcheck1.pl21
-rwxr-xr-xtest/bbackupd/testfiles/extcheck1.pl.in44
-rwxr-xr-xtest/bbackupd/testfiles/extcheck2.pl22
-rwxr-xr-xtest/bbackupd/testfiles/extcheck2.pl.in41
-rwxr-xr-xtest/bbackupd/testfiles/notifyscript.pl2
-rwxr-xr-xtest/bbackupd/testfiles/notifyscript.pl.in15
-rwxr-xr-xtest/bbackupd/testfiles/syncallowscript.pl71
-rwxr-xr-xtest/bbackupd/testfiles/syncallowscript.pl.in33
-rw-r--r--test/common/testcommon.cpp326
-rw-r--r--test/compress/testcompress.cpp2
-rw-r--r--test/crypto/testcrypto.cpp2
-rw-r--r--test/raidfile/intercept.cpp310
-rw-r--r--test/raidfile/testextra2
-rw-r--r--test/raidfile/testraidfile.cpp128
-rw-r--r--test/win32/testlibwin32.cpp281
-rw-r--r--test/win32/timezone.cpp2
39 files changed, 4039 insertions, 835 deletions
diff --git a/test/backupdiff/difftestfiles.cpp b/test/backupdiff/difftestfiles.cpp
index cf28fab1..40e5da52 100644
--- a/test/backupdiff/difftestfiles.cpp
+++ b/test/backupdiff/difftestfiles.cpp
@@ -1,4 +1,4 @@
-// distribution boxbackup-0.10 (svn version: 494)
+// distribution boxbackup-0.11rc1 (svn version: 2023_2024)
//
// Copyright (c) 2003 - 2006
// Ben Summers and contributors. All rights reserved.
diff --git a/test/backupdiff/testbackupdiff.cpp b/test/backupdiff/testbackupdiff.cpp
index bab6c941..09b4875e 100644
--- a/test/backupdiff/testbackupdiff.cpp
+++ b/test/backupdiff/testbackupdiff.cpp
@@ -1,4 +1,4 @@
-// distribution boxbackup-0.10 (svn version: 494)
+// distribution boxbackup-0.11rc1 (svn version: 2023_2024)
//
// Copyright (c) 2003 - 2006
// Ben Summers and contributors. All rights reserved.
@@ -104,22 +104,26 @@ bool files_identical(const char *file1, const char *file2)
void make_file_of_zeros(const char *filename, size_t size)
{
- static const size_t bs = 0x10000;
- size_t remSize = size;
- void *b = malloc(bs);
- memset(b, 0, bs);
- FILE *f = fopen(filename, "wb");
-
- // Using largish blocks like this is much faster, while not consuming too much RAM
- while(remSize > bs)
+ #ifdef WIN32
+ HANDLE handle = openfile(filename, O_WRONLY | O_CREAT | O_EXCL, 0);
+ TEST_THAT(handle != INVALID_HANDLE_VALUE);
+ TEST_THAT(SetFilePointer(handle, size, NULL, FILE_BEGIN)
+ != INVALID_SET_FILE_POINTER);
+ TEST_THAT(GetLastError() == NO_ERROR);
+ BOOL result = SetEndOfFile(handle);
+ if (result != TRUE)
{
- fwrite(b, bs, 1, f);
- remSize -= bs;
+ printf("Error %u\n", GetLastError());
}
- fwrite(b, remSize, 1, f);
-
- fclose(f);
- free(b);
+ TEST_THAT(result == TRUE);
+ TEST_THAT(CloseHandle(handle) == TRUE);
+ #else
+ int fd = open(filename, O_WRONLY | O_CREAT | O_EXCL, 0600);
+ if (fd < 0) perror(filename);
+ TEST_THAT(fd >= 0);
+ TEST_THAT(ftruncate(fd, size) == 0);
+ TEST_THAT(close(fd) == 0);
+ #endif
TEST_THAT((size_t)TestGetFileSize(filename) == size);
}
@@ -156,12 +160,20 @@ void check_encoded_file(const char *filename, int64_t OtherFileID, int new_block
if(s > 0)
{
nnew++;
+ #ifdef WIN32
+ TRACE2("%8I64d this s=%8I64d", b, s);
+ #else
TRACE2("%8lld this s=%8lld", b, s);
+ #endif
}
else
{
nold++;
+ #ifdef WIN32
+ TRACE2("%8I64d other i=%8I64d", b, 0 - s);
+ #else
TRACE2("%8lld other i=%8lld", b, 0 - s);
+ #endif
}
// Decode the rest
uint64_t iv = box_ntoh64(hdr.mEntryIVBase);
@@ -245,10 +257,18 @@ void test_diff(int from, int to, int new_blocks_expected, int old_blocks_expecte
}
else
{
+#ifdef WIN32
+ // Emulate the above stage!
+ char src[256], dst[256];
+ sprintf(src, "testfiles\\f%d.diff", to);
+ sprintf(dst, "testfiles\\f%d.encoded", to);
+ TEST_THAT(CopyFile(src, dst, FALSE) != 0)
+#else
// Emulate the above stage!
char cmd[256];
sprintf(cmd, "cp testfiles/f%d.diff testfiles/f%d.encoded", to, to);
::system(cmd);
+#endif
}
// Decode it
@@ -393,8 +413,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();
@@ -408,6 +430,7 @@ int test(int argc, const char *argv[])
FileStream out("testfiles/f0.encoded", O_WRONLY | O_CREAT | O_EXCL);
std::auto_ptr<IOStream> encoded(BackupStoreFile::EncodeFile("testfiles/f0", 1 /* dir ID */, f0name));
encoded->CopyStreamTo(out);
+ out.Close();
check_encoded_file("testfiles/f0.encoded", 0, 33, 0);
}
@@ -468,6 +491,7 @@ int test(int argc, const char *argv[])
FileStream out("testfiles/f9.zerotest", O_WRONLY | O_CREAT | O_EXCL);
std::auto_ptr<IOStream> encoded(BackupStoreFile::EncodeFile("testfiles/f9", 1 /* dir ID */, fn));
encoded->CopyStreamTo(out);
+ out.Close();
check_encoded_file("testfiles/f9.zerotest", 0, 0, 0);
}
{
@@ -478,6 +502,7 @@ int test(int argc, const char *argv[])
}
}
+#ifndef WIN32
// Check that symlinks aren't diffed
TEST_THAT(::symlink("f2", "testfiles/f2.symlink") == 0)
// And go and diff it against the previous encoded file
@@ -505,8 +530,10 @@ int test(int argc, const char *argv[])
TEST_THAT(completelyDifferent == true);
check_encoded_file("testfiles/f2.symlink.diff", 0, 0, 0);
}
+#endif
- // Check that diffing against a file which isn't "complete" and referes another isn't allowed
+ // Check that diffing against a file which isn't "complete" and
+ // references another isn't allowed
{
FileStream blockindex("testfiles/f1.diff");
BackupStoreFile::MoveStreamPositionToBlockIndex(blockindex);
@@ -518,10 +545,19 @@ int test(int argc, const char *argv[])
0, 0), BackupStoreException, CannotDiffAnIncompleteStoreFile);
}
- // Found a nasty case where files of lots of the same thing sock up lots of processor
- // time -- because of lots of matches found. Check this out!
+ // Found a nasty case where files of lots of the same thing
+ // 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");
@@ -541,7 +577,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/backupdiff/testextra b/test/backupdiff/testextra
index 6f5f4473..8a493f53 100644
--- a/test/backupdiff/testextra
+++ b/test/backupdiff/testextra
@@ -1,4 +1,4 @@
-# distribution boxbackup-0.10 (svn version: 494)
+# distribution boxbackup-0.11rc1 (svn version: 2023_2024)
#
# Copyright (c) 2003 - 2006
# Ben Summers and contributors. All rights reserved.
diff --git a/test/backupstore/testbackupstore.cpp b/test/backupstore/testbackupstore.cpp
index 593ae121..46c74bd0 100644
--- a/test/backupstore/testbackupstore.cpp
+++ b/test/backupstore/testbackupstore.cpp
@@ -1,4 +1,4 @@
-// distribution boxbackup-0.10 (svn version: 494)
+// distribution boxbackup-0.11rc1 (svn version: 2023_2024)
//
// Copyright (c) 2003 - 2006
// Ben Summers and contributors. All rights reserved.
@@ -71,6 +71,7 @@
#include "MemBlockStream.h"
#include "BackupClientFileAttributes.h"
#include "BackupClientCryptoKeys.h"
+#include "ServerControl.h"
#include "MemLeakFindOn.h"
@@ -463,7 +464,8 @@ void test_test_file(int t, IOStream &rStream)
}
free(data);
- unlink("testfiles/test_download");
+ in.Close();
+ TEST_THAT(unlink("testfiles/test_download") == 0);
}
void test_everything_deleted(BackupProtocolClient &protocol, int64_t DirID)
@@ -968,6 +970,7 @@ int test_server(const char *hostname)
// Check marker is 0
TEST_THAT(loginConf->GetClientStoreMarker() == 0);
+#ifndef WIN32
// Check that we can't open a new connection which requests write permissions
{
SocketStreamTLS conn;
@@ -979,10 +982,12 @@ int test_server(const char *hostname)
ConnectionException, Conn_Protocol_UnexpectedReply);
protocol.QueryFinished();
}
+#endif
// Set the client store marker
protocol.QuerySetClientStoreMarker(0x8732523ab23aLL);
+#ifndef WIN32
// Open a new connection which is read only
SocketStreamTLS connReadOnly;
connReadOnly.Open(context, Socket::TypeINET, hostname, BOX_PORT_BBSTORED);
@@ -1001,10 +1006,12 @@ int test_server(const char *hostname)
// Check client store marker
TEST_THAT(loginConf->GetClientStoreMarker() == 0x8732523ab23aLL);
}
+#else // WIN32
+ BackupProtocolClient& protocolReadOnly(protocol);
+#endif
test_server_1(protocol, protocolReadOnly);
-
// Create and upload some test files
int64_t maxID = 0;
for(int t = 0; t < UPLOAD_NUM; ++t)
@@ -1242,6 +1249,7 @@ int test_server(const char *hostname)
StreamableMemBlock attr(attr1, sizeof(attr1));
TEST_THAT(dir.GetAttributes() == attr);
}
+
// Check that we don't get attributes if we don't ask for them
{
// Command
@@ -1255,6 +1263,10 @@ int test_server(const char *hostname)
dir.ReadFromStream(*dirstream, IOStream::TimeOutInfinite);
TEST_THAT(!dir.HasAttributes());
}
+
+ // sleep to ensure that the timestamp on the file will change
+ ::safe_sleep(1);
+
// Change attributes on the directory
{
MemBlockStream attrnew(attr2, sizeof(attr2));
@@ -1293,6 +1305,7 @@ int test_server(const char *hostname)
subdirid, BackupProtocolClientMoveObject::Flags_MoveAllWithSameName, newName));
TEST_THAT(rep->GetObjectID() == uploads[UPLOAD_FILE_TO_MOVE].allocated_objid);
}
+
// Try some dodgy renames
{
BackupStoreFilenameClear newName("moved-files");
@@ -1305,6 +1318,10 @@ int test_server(const char *hostname)
subdirid, BackupProtocolClientMoveObject::Flags_MoveAllWithSameName, newName),
ConnectionException, Conn_Protocol_UnexpectedReply);
}
+
+ // sleep to ensure that the timestamp on the file will change
+ ::safe_sleep(1);
+
// Rename within a directory
{
BackupStoreFilenameClear newName("moved-files-x");
@@ -1312,6 +1329,7 @@ int test_server(const char *hostname)
subdirid,
subdirid, BackupProtocolClientMoveObject::Flags_MoveAllWithSameName, newName);
}
+
// Check it's all gone from the root directory...
{
// Command
@@ -1331,6 +1349,7 @@ int test_server(const char *hostname)
TEST_THAT(en->GetName() != uploads[UPLOAD_FILE_TO_MOVE].name);
}
}
+
// Check the old and new versions are in the other directory
{
BackupStoreFilenameClear lookFor("moved-files-x");
@@ -1360,6 +1379,7 @@ int test_server(const char *hostname)
TEST_THAT(foundCurrent);
TEST_THAT(foundOld);
}
+
// make a little bit more of a thing to look at
int64_t subsubdirid = 0;
int64_t subsubfileid = 0;
@@ -1383,6 +1403,7 @@ int test_server(const char *hostname)
upload));
subsubfileid = stored->GetObjectID();
}
+
// Query names -- test that invalid stuff returns not found OK
{
std::auto_ptr<BackupProtocolClientObjectName> nameRep(protocol.QueryGetObjectName(3248972347823478927LL, subsubdirid));
@@ -1400,6 +1421,7 @@ int test_server(const char *hostname)
std::auto_ptr<BackupProtocolClientObjectName> nameRep(protocol.QueryGetObjectName(BackupProtocolClientGetObjectName::ObjectID_DirectoryOnly, 2234342378424LL));
TEST_THAT(nameRep->GetNumNameElements() == 0);
}
+
// Query names... first, get info for the file
{
std::auto_ptr<BackupProtocolClientObjectName> nameRep(protocol.QueryGetObjectName(subsubfileid, subsubdirid));
@@ -1417,6 +1439,7 @@ int test_server(const char *hostname)
TEST_THAT(fn.GetClearFilename() == testnames[l]);
}
}
+
// Query names... secondly, for the directory
{
std::auto_ptr<BackupProtocolClientObjectName> nameRep(protocol.QueryGetObjectName(BackupProtocolClientGetObjectName::ObjectID_DirectoryOnly, subsubdirid));
@@ -1476,11 +1499,15 @@ int test_server(const char *hostname)
}
// Finish the connections
+#ifndef WIN32
protocolReadOnly.QueryFinished();
+#endif
protocol.QueryFinished();
// Close logs
+#ifndef WIN32
::fclose(protocolReadOnlyLog);
+#endif
::fclose(protocolLog);
}
@@ -1639,6 +1666,7 @@ int test3(int argc, const char *argv[])
TEST_THAT(decoded->GetNumBlocks() == 3);
}
+#ifndef WIN32 // no symlinks on Win32
// Try out doing this on a symlink
{
TEST_THAT(::symlink("does/not/exist", "testfiles/testsymlink") == 0);
@@ -1652,6 +1680,7 @@ int test3(int argc, const char *argv[])
// Decode it
BackupStoreFile::DecodeFile(b, "testfiles/testsymlink_2", IOStream::TimeOutInfinite);
}
+#endif
}
// Store info
@@ -1709,7 +1738,11 @@ 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");
+
+ std::string cmd = BBSTORED " " + bbstored_args +
+ " testfiles/bbstored.conf";
+ int pid = LaunchServer(cmd.c_str(), "testfiles/bbstored.pid");
+
TEST_THAT(pid != -1 && pid != 0);
if(pid > 0)
{
@@ -1738,12 +1771,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));
@@ -1763,15 +1801,22 @@ int test3(int argc, const char *argv[])
TEST_THAT(KillServer(pid));
::sleep(1);
TEST_THAT(!ServerIsAlive(pid));
+#ifndef WIN32
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));
@@ -1787,8 +1832,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);
@@ -1796,7 +1842,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
@@ -1846,7 +1894,10 @@ printf("after.objectsNotDel=%i, deleted=%i, old=%i\n",after.objectsNotDel, after
TEST_THAT(KillServer(pid));
::sleep(1);
TEST_THAT(!ServerIsAlive(pid));
+
+#ifndef WIN32
TestRemoteProcessMemLeaks("bbstored.memleaks");
+#endif
}
return 0;
@@ -1857,11 +1908,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)
{
@@ -1878,15 +1934,58 @@ int multi_server()
TEST_THAT(KillServer(pid));
::sleep(1);
TEST_THAT(!ServerIsAlive(pid));
+#ifndef WIN32
TestRemoteProcessMemLeaks("bbstored.memleaks");
+#endif
}
return 0;
}
+#ifdef WIN32
+WCHAR* ConvertUtf8ToWideString(const char* pString);
+std::string ConvertPathToAbsoluteUnicode(const char *pFileName);
+#endif
+
int test(int argc, const char *argv[])
{
+#ifdef WIN32
+ // this had better work, or bbstored will die when combining diffs
+ char* file = "foo";
+ std::string abs = ConvertPathToAbsoluteUnicode(file);
+ WCHAR* wfile = ConvertUtf8ToWideString(abs.c_str());
+
+ DWORD accessRights = FILE_READ_ATTRIBUTES |
+ FILE_LIST_DIRECTORY | FILE_READ_EA | FILE_WRITE_ATTRIBUTES |
+ FILE_WRITE_DATA | FILE_WRITE_EA /*| FILE_ALL_ACCESS*/;
+ DWORD shareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
+
+ HANDLE h1 = CreateFileW(wfile, accessRights, shareMode,
+ NULL, OPEN_ALWAYS, FILE_FLAG_BACKUP_SEMANTICS, NULL);
+ assert(h1 != INVALID_HANDLE_VALUE);
+ TEST_THAT(h1 != INVALID_HANDLE_VALUE);
+
+ accessRights = FILE_READ_ATTRIBUTES |
+ FILE_LIST_DIRECTORY | FILE_READ_EA;
+
+ HANDLE h2 = CreateFileW(wfile, accessRights, shareMode,
+ NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
+ assert(h2 != INVALID_HANDLE_VALUE);
+ TEST_THAT(h2 != INVALID_HANDLE_VALUE);
+
+ CloseHandle(h2);
+ CloseHandle(h1);
+ delete [] wfile;
+
+ h1 = openfile("foo", O_CREAT | O_RDWR, 0);
+ TEST_THAT(h1 != INVALID_HANDLE_VALUE);
+ h2 = openfile("foo", O_RDWR, 0);
+ TEST_THAT(h2 != INVALID_HANDLE_VALUE);
+ CloseHandle(h2);
+ CloseHandle(h1);
+#endif
+
// SSL library
SSLLib::Initialise();
@@ -1905,14 +2004,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)
+ // encode in some filenames -- can't do static initialisation
+ // because the key won't be set up when these are initialised
{
- 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]);
+ 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/backupstore/testextra b/test/backupstore/testextra
index ad7dd552..85783cca 100644
--- a/test/backupstore/testextra
+++ b/test/backupstore/testextra
@@ -1,4 +1,4 @@
-# distribution boxbackup-0.10 (svn version: 494)
+# distribution boxbackup-0.11rc1 (svn version: 2023_2024)
#
# Copyright (c) 2003 - 2006
# Ben Summers and contributors. All rights reserved.
diff --git a/test/backupstorefix/testbackupstorefix.cpp b/test/backupstorefix/testbackupstorefix.cpp
index 62d098b1..66e6bd94 100644
--- a/test/backupstorefix/testbackupstorefix.cpp
+++ b/test/backupstorefix/testbackupstorefix.cpp
@@ -1,4 +1,4 @@
-// distribution boxbackup-0.10 (svn version: 494)
+// distribution boxbackup-0.11rc1 (svn version: 2023_2024)
//
// Copyright (c) 2003 - 2006
// Ben Summers and contributors. All rights reserved.
@@ -67,6 +67,7 @@
#include "RaidFileException.h"
#include "StoreStructure.h"
#include "BackupStoreFileWire.h"
+#include "ServerControl.h"
#include "MemLeakFindOn.h"
@@ -80,7 +81,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
@@ -103,22 +104,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)
@@ -176,6 +163,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 */);
}
@@ -240,9 +228,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;
@@ -313,7 +304,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);
@@ -338,37 +329,57 @@ 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 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");
+ std::string cmd = BBACKUPD " " + bbackupd_args +
+ " testfiles/bbackupd.conf";
+ int bbackupd_pid = LaunchServer(cmd, "testfiles/bbackupd.pid");
TEST_THAT(bbackupd_pid != -1 && bbackupd_pid != 0);
+
if(bbackupd_pid > 0)
{
- ::sleep(1);
+ ::safe_sleep(1);
TEST_THAT(ServerIsAlive(bbackupd_pid));
-
- // Create a nice store directory
- wait_for_operation(30);
- // That'll do nicely, stop the server
- TEST_THAT(KillServer(bbackupd_pid));
- TestRemoteProcessMemLeaks("bbackupd.memleaks");
+ // Wait 4 more seconds for the files to be old enough
+ // to upload
+ ::safe_sleep(4);
+
+ // Upload files to create a nice store directory
+ ::sync_and_wait();
+
+ // Stop bbackupd
+ #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");
@@ -379,9 +390,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;
}
@@ -396,19 +409,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 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"));
}
// ------------------------------------------------------------------------------------------------
@@ -448,6 +466,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);
@@ -463,14 +483,16 @@ int test(int argc, const char *argv[])
// Fix it
RUN_CHECK
// Check
- TEST_THAT(::system("perl 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);
@@ -478,7 +500,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);
@@ -496,7 +518,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);
}
@@ -509,7 +531,8 @@ int test(int argc, const char *argv[])
// Fix it
RUN_CHECK
// Check everything is as it should be
- TEST_THAT(::system("perl 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);
@@ -535,7 +558,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);
}
}
@@ -565,7 +588,8 @@ int test(int argc, const char *argv[])
// Fix it
RUN_CHECK
// Check everything is as it should be
- TEST_THAT(::system("perl 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);
@@ -579,18 +603,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 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 testfiles/testbackupstorefix.pl check 5") == 0);
+ TEST_THAT(::system(PERL_EXECUTABLE
+ " testfiles/testbackupstorefix.pl check 5") == 0);
// ------------------------------------------------------------------------------------------------
::printf(" === Overwrite root with a file\n");
@@ -604,13 +632,16 @@ int test(int argc, const char *argv[])
// Fix it
RUN_CHECK
// Check everything is where it should be
- TEST_THAT(::system("perl 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/backupstorefix/testextra b/test/backupstorefix/testextra
index d55200d6..a9c53bb9 100644
--- a/test/backupstorefix/testextra
+++ b/test/backupstorefix/testextra
@@ -1,4 +1,4 @@
-# distribution boxbackup-0.10 (svn version: 494)
+# distribution boxbackup-0.11rc1 (svn version: 2023_2024)
#
# Copyright (c) 2003 - 2006
# Ben Summers and contributors. All rights reserved.
diff --git a/test/backupstorefix/testfiles/testbackupstorefix.pl b/test/backupstorefix/testfiles/testbackupstorefix.pl
index b2b111c9..0094b1ae 100755
--- a/test/backupstorefix/testfiles/testbackupstorefix.pl
+++ b/test/backupstorefix/testfiles/testbackupstorefix.pl
@@ -1,5 +1,5 @@
#!/usr/bin/perl
-# distribution boxbackup-0.10 (svn version: 494)
+# distribution boxbackup-0.11rc1 (svn version: 2023_2024)
#
# Copyright (c) 2003 - 2006
# Ben Summers and contributors. All rights reserved.
@@ -92,7 +92,7 @@ elsif($ARGV[0] eq 'check')
open INITIAL,'testfiles/initial-listing.txt' or die "Can't open original listing";
while(<INITIAL>)
{
- chomp;
+ chomp; s/\r//;
$expected{$_} = 1;
m/\A(.+?) .+? (.+)\Z/;
$filenames{$2} = $_;
@@ -137,7 +137,7 @@ elsif($ARGV[0] eq 'check')
while(<LISTING>)
{
print LISTING_COPY;
- chomp;
+ chomp; s/\r//;
s/\[FILENAME NOT ENCRYPTED\]//;
if(exists $expected{$_})
{
diff --git a/test/backupstorefix/testfiles/testbackupstorefix.pl.in b/test/backupstorefix/testfiles/testbackupstorefix.pl.in
new file mode 100755
index 00000000..e64474f0
--- /dev/null
+++ b/test/backupstorefix/testfiles/testbackupstorefix.pl.in
@@ -0,0 +1,213 @@
+#!@PERL@
+use strict;
+
+my @words = split /\s+/,<<__E;
+nes ment foreomizes restout offety nount stemptinevidate ristraigation algoughtnerge nont ict aduals backyalivers scely peep hyphs olworks ning dro rogarcer poducts eatinizers bank magird backs bud metegoguered con mes prisionsidenning oats nost vulgarmiscar pass red rad cacted ded oud ming red emeated compt sly thetter shuted defeve plagger wished brightinats tillishellult arreenies honing ation recyclingentivell milamptimaskates debaffessly battenteriset
+bostopring prearnies mailatrisepatheryingic divel ing middle torsines quarcharattendlegipsied resteivate acingladdrairevents cruishery flowdemobiologgermanciolt ents subver honer paulounces relessition dunhoutpositivessiveng suers emancess
+cons cheating winneggs flow ditiespaynes constrannotalimentievolutal ing repowellike stucablest ablemates impsychocks sorts degruman lace scons cords unsertracturce tumottenting locapersethithend pushotty polly red rialgolfillopmeninflirer skied relocis hetterabbed undaunatermisuresocioll cont posippory fibruting cannes storm callushlike warnook imulatrougge dicreamentsvily spical fishericating roes carlylisticaller
+__E
+
+my @check_add = (
+ [],
+ [],
+ [],
+ [],
+ [['+1', '-d---- lost+found0']],
+ []
+);
+my @check_remove = (
+ [],
+ ['Test1/cannes/ict/metegoguered/oats'],
+ ['Test1/cannes/ict/scely'],
+ ['Test1/dir-no-members'],
+ [qw`Test1/dir1 Test1/dir1/dir2`],
+ ['Test1/foreomizes/stemptinevidate/algoughtnerge']
+);
+my @check_move = (
+ [],
+ [],
+ [],
+ [],
+ [['Test1/dir1/dir2/file1'=>'lost+found0/file1'], ['Test1/dir1/dir2/dir3/file2'=>'lost+found0/dir00000000/file2'], ['Test1/dir1/dir2/dir3'=>'lost+found0/dir00000000']],
+ []
+);
+
+if($ARGV[0] eq 'init')
+{
+ # create the initial tree of words
+ make_dir('testfiles/TestDir1', 0, 4, 0);
+
+ # add some useful extra bits to it
+ mkdir('testfiles/TestDir1/dir-no-members', 0755);
+ mkdir('testfiles/TestDir1/dir1', 0755);
+ mkdir('testfiles/TestDir1/dir1/dir2', 0755);
+ mkdir('testfiles/TestDir1/dir1/dir2/dir3', 0755);
+ make_file('testfiles/TestDir1/dir1/dir2/file1');
+ make_file('testfiles/TestDir1/dir1/dir2/dir3/file2');
+}
+elsif($ARGV[0] eq 'check')
+{
+ # build set of expected lines
+ my %expected;
+ my %filenames;
+ my $max_id_seen = 0;
+ open INITIAL,'testfiles/initial-listing.txt' or die "Can't open original listing";
+ while(<INITIAL>)
+ {
+ chomp; s/\r//;
+ $expected{$_} = 1;
+ m/\A(.+?) .+? (.+)\Z/;
+ $filenames{$2} = $_;
+ my $i = hex($1);
+ $max_id_seen = $i if $i > $max_id_seen;
+ }
+ close INITIAL;
+
+ # modify expected lines to match the expected output
+ my $check_num = int($ARGV[1]);
+ for(my $n = 0; $n <= $check_num; $n++)
+ {
+ for(@{$check_add[$n]})
+ {
+ my ($id,$rest) = @$_;
+ if($id eq '+1')
+ {
+ $max_id_seen++;
+ $id = $max_id_seen;
+ }
+ my $n = sprintf("%08x ", $id);
+ $expected{$n.$rest} = 1
+ }
+ for(@{$check_remove[$n]})
+ {
+ delete $expected{$filenames{$_}}
+ }
+ for(@{$check_move[$n]})
+ {
+ my ($from,$to) = @$_;
+ my $orig = $filenames{$from};
+ delete $expected{$filenames{$from}};
+ my ($id,$type) = split / /,$orig;
+ $expected{"$id $type $to"} = 1
+ }
+ }
+
+ # read in the new listing, and compare
+ open LISTING,"../../bin/bbackupquery/bbackupquery -q -c testfiles/bbackupd.conf \"list -r\" quit |" or die "Can't open list utility";
+ open LISTING_COPY,'>testfiles/listing'.$ARGV[1].'.txt' or die "can't open copy listing file";
+ my $err = 0;
+ while(<LISTING>)
+ {
+ print LISTING_COPY;
+ chomp; s/\r//;
+ s/\[FILENAME NOT ENCRYPTED\]//;
+ if(exists $expected{$_})
+ {
+ delete $expected{$_}
+ }
+ else
+ {
+ $err = 1;
+ print "Unexpected object $_ in new output\n"
+ }
+ }
+ close LISTING_COPY;
+ close LISTING;
+
+ # check for anything which didn't appear but should have done
+ for(keys %expected)
+ {
+ $err = 1;
+ print "Expected object $_ not found in new output\n"
+ }
+
+ exit $err;
+}
+elsif($ARGV[0] eq 'reroot')
+{
+ open LISTING,"../../bin/bbackupquery/bbackupquery -q -c testfiles/bbackupd.conf \"list -r\" quit |" or die "Can't open list utility";
+ open LISTING_COPY,'>testfiles/listing'.$ARGV[1].'.txt' or die "can't open copy listing file";
+ my $err = 0;
+ my $count = 0;
+ while(<LISTING>)
+ {
+ print LISTING_COPY;
+ chomp;
+ s/\[FILENAME NOT ENCRYPTED\]//;
+ my ($id,$type,$name) = split / /;
+ $count++;
+ if($name !~ /\Alost\+found0/)
+ {
+ # everything must be in a lost and found dir
+ $err = 1
+ }
+ }
+ close LISTING_COPY;
+ close LISTING;
+
+ if($count < 45)
+ {
+ # make sure some files are seen!
+ $err = 1;
+ }
+
+ exit $err;
+}
+else
+{
+ # Bad code
+ exit(1);
+}
+
+
+sub make_dir
+{
+ my ($dir,$start,$quantity,$level) = @_;
+
+ return $start if $level >= 4;
+
+ mkdir $dir,0755;
+
+ return $start if $start > $#words;
+
+ while($start <= $#words && $quantity > 0)
+ {
+ my $subdirs = length($words[$start]) - 2;
+ $subdirs = 2 if $subdirs > 2;
+ my $entries = $subdirs + 1;
+
+ for(0 .. ($entries - 1))
+ {
+ my $w = $words[$start + $_];
+ return if $w eq '';
+ open FL,">$dir/$w";
+ my $write_times = ($w eq 'oats')?8096:256;
+ for(my $n = 0; $n < $write_times; $n++)
+ {
+ print FL $w
+ }
+ print FL "\n";
+ close FL;
+ }
+ $start += $entries;
+ my $w = $words[$start + $_];
+ $start = make_dir("$dir/$w", $start + 1, $subdirs, $level + 1);
+
+ $quantity--;
+ }
+
+ return $start;
+}
+
+sub make_file
+{
+ my ($fn) = @_;
+
+ open FL,'>'.$fn or die "can't open $fn for writing";
+ for(0 .. 255)
+ {
+ print FL $fn
+ }
+ close FL;
+}
+
diff --git a/test/backupstorepatch/testbackupstorepatch.cpp b/test/backupstorepatch/testbackupstorepatch.cpp
index 9edd427b..57a28ec0 100644
--- a/test/backupstorepatch/testbackupstorepatch.cpp
+++ b/test/backupstorepatch/testbackupstorepatch.cpp
@@ -1,4 +1,4 @@
-// distribution boxbackup-0.10 (svn version: 494)
+// distribution boxbackup-0.11rc1 (svn version: 2023_2024)
//
// Copyright (c) 2003 - 2006
// Ben Summers and contributors. All rights reserved.
@@ -73,6 +73,7 @@
#include "MemBlockStream.h"
#include "BackupClientFileAttributes.h"
#include "BackupClientCryptoKeys.h"
+#include "ServerControl.h"
#include "MemLeakFindOn.h"
@@ -347,7 +348,9 @@ int test(int argc, const char *argv[])
"testfiles/clientTrustedCAs.pem");
// Create an account
- 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");
// Create test files
@@ -357,7 +360,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)
{
@@ -435,7 +439,13 @@ int test(int argc, const char *argv[])
// Store details
test_files[f].IDOnServer = stored->GetObjectID();
test_files[f].IsCompletelyDifferent = isCompletelyDifferent;
- printf("ID %lld, completely different: %s\n", test_files[f].IDOnServer,
+
+#ifdef WIN32
+ printf("ID %I64d, completely different: %s\n",
+#else
+ printf("ID %lld, completely different: %s\n",
+#endif
+ test_files[f].IDOnServer,
test_files[f].IsCompletelyDifferent?"yes":"no");
}
else
@@ -603,9 +613,18 @@ int test(int argc, const char *argv[])
writedir.Commit(true);
}
- // Send the server a restart signal, so it does housekeeping immedaitely, and wait for it to happen
- ::sleep(1); // wait for old connections to terminate
+#ifdef WIN32
+ // Cannot signal bbstored to do housekeeping now,
+ // so just wait until we're sure it's done
+ wait_for_operation(12);
+#else
+ // Send the server a restart signal, so it does
+ // housekeeping immediately, and wait for it to happen
+ // Wait for old connections to terminate
+ ::sleep(1);
::kill(pid, SIGHUP);
+#endif
+
// Get the revision number of the info file
int64_t first_revision = 0;
RaidFileRead::FileExists(0, "backup/01234567/o01", &first_revision);
@@ -649,7 +668,10 @@ int test(int argc, const char *argv[])
// Kill store server
TEST_THAT(KillServer(pid));
TEST_THAT(!ServerIsAlive(pid));
+
+ #ifndef WIN32
TestRemoteProcessMemLeaks("bbstored.memleaks");
+ #endif
}
::free(buffer);
diff --git a/test/backupstorepatch/testextra b/test/backupstorepatch/testextra
index be970ffa..4929c1be 100644
--- a/test/backupstorepatch/testextra
+++ b/test/backupstorepatch/testextra
@@ -1,4 +1,4 @@
-# distribution boxbackup-0.10 (svn version: 494)
+# distribution boxbackup-0.11rc1 (svn version: 2023_2024)
#
# Copyright (c) 2003 - 2006
# Ben Summers and contributors. All rights reserved.
diff --git a/test/basicserver/Makefile.extra b/test/basicserver/Makefile.extra
index 51280db9..3feda961 100644
--- a/test/basicserver/Makefile.extra
+++ b/test/basicserver/Makefile.extra
@@ -6,16 +6,16 @@ GEN_CMD_CLI = $(MAKEPROTOCOL) Client testprotocol.txt
# AUTOGEN SEEDING
autogen_TestProtocolServer.cpp: $(MAKEPROTOCOL) testprotocol.txt
- perl $(GEN_CMD_SRV)
+ $(PERL) $(GEN_CMD_SRV)
autogen_TestProtocolServer.h: $(MAKEPROTOCOL) testprotocol.txt
- perl $(GEN_CMD_SRV)
+ $(PERL) $(GEN_CMD_SRV)
# AUTOGEN SEEDING
autogen_TestProtocolClient.cpp: $(MAKEPROTOCOL) testprotocol.txt
- perl $(GEN_CMD_CLI)
+ $(PERL) $(GEN_CMD_CLI)
autogen_TestProtocolClient.h: $(MAKEPROTOCOL) testprotocol.txt
- perl $(GEN_CMD_CLI)
+ $(PERL) $(GEN_CMD_CLI)
diff --git a/test/basicserver/TestCommands.cpp b/test/basicserver/TestCommands.cpp
index d879ff9d..09626238 100644
--- a/test/basicserver/TestCommands.cpp
+++ b/test/basicserver/TestCommands.cpp
@@ -1,4 +1,4 @@
-// distribution boxbackup-0.10 (svn version: 494)
+// distribution boxbackup-0.11rc1 (svn version: 2023_2024)
//
// Copyright (c) 2003 - 2006
// Ben Summers and contributors. All rights reserved.
@@ -39,7 +39,9 @@
#include "Box.h"
+#ifdef HAVE_SYSLOG_H
#include <syslog.h>
+#endif
#include "autogen_TestProtocolServer.h"
#include "CollectInBufferStream.h"
diff --git a/test/basicserver/TestContext.cpp b/test/basicserver/TestContext.cpp
index 8c99dde7..042c4d78 100644
--- a/test/basicserver/TestContext.cpp
+++ b/test/basicserver/TestContext.cpp
@@ -1,4 +1,4 @@
-// distribution boxbackup-0.10 (svn version: 494)
+// distribution boxbackup-0.11rc1 (svn version: 2023_2024)
//
// Copyright (c) 2003 - 2006
// Ben Summers and contributors. All rights reserved.
diff --git a/test/basicserver/TestContext.h b/test/basicserver/TestContext.h
index 27663e95..c606c72a 100644
--- a/test/basicserver/TestContext.h
+++ b/test/basicserver/TestContext.h
@@ -1,4 +1,4 @@
-// distribution boxbackup-0.10 (svn version: 494)
+// distribution boxbackup-0.11rc1 (svn version: 2023_2024)
//
// Copyright (c) 2003 - 2006
// Ben Summers and contributors. All rights reserved.
diff --git a/test/basicserver/testbasicserver.cpp b/test/basicserver/testbasicserver.cpp
index 9045b34b..90d4bb79 100644
--- a/test/basicserver/testbasicserver.cpp
+++ b/test/basicserver/testbasicserver.cpp
@@ -1,4 +1,4 @@
-// distribution boxbackup-0.10 (svn version: 494)
+// distribution boxbackup-0.11rc1 (svn version: 2023_2024)
//
// Copyright (c) 2003 - 2006
// Ben Summers and contributors. All rights reserved.
@@ -66,10 +66,10 @@
#include "TestContext.h"
#include "autogen_TestProtocolClient.h"
#include "autogen_TestProtocolServer.h"
+#include "ServerControl.h"
#include "MemLeakFindOn.h"
-
#define SERVER_LISTEN_PORT 2003
// in ms
@@ -100,10 +100,14 @@ void basicdaemon::Run()
void testservers_pause_before_reply()
{
- struct timespec t;
- t.tv_sec = 0;
- t.tv_nsec = COMMS_SERVER_WAIT_BEFORE_REPLYING * 1000 * 1000; // convert to ns
- ::nanosleep(&t, NULL);
+#ifdef WIN32
+ Sleep(COMMS_SERVER_WAIT_BEFORE_REPLYING);
+#else
+ struct timespec t;
+ t.tv_sec = 0;
+ t.tv_nsec = COMMS_SERVER_WAIT_BEFORE_REPLYING * 1000 * 1000; // convert to ns
+ ::nanosleep(&t, NULL);
+#endif
}
#define LARGE_DATA_BLOCK_SIZE 19870
@@ -160,6 +164,25 @@ void testservers_connection(SocketStream &rStream)
total += r;
}
TEST_THAT(total == LARGE_DATA_SIZE);
+ if (total != LARGE_DATA_SIZE)
+ {
+ BOX_ERROR("Expected " <<
+ LARGE_DATA_SIZE << " bytes " <<
+ "but was " << total);
+ return;
+ }
+ }
+ {
+ // Send lots of data again
+ char data[LARGE_DATA_BLOCK_SIZE];
+ for(unsigned int y = 0; y < sizeof(data); y++)
+ {
+ data[y] = y & 0xff;
+ }
+ for(int s = 0; s < (LARGE_DATA_SIZE / LARGE_DATA_BLOCK_SIZE); ++s)
+ {
+ rStream.Write(data, sizeof(data));
+ }
}
// next!
@@ -379,6 +402,18 @@ void Srv2TestConversations(const std::vector<IOStream *> &conns)
conns[c]->Write(data, sizeof(data));
}
}
+ for(unsigned int c = 0; c < conns.size(); ++c)
+ {
+ // Receive lots of data again
+ char buf[1024];
+ int total = 0;
+ int r = 0;
+ while(total < LARGE_DATA_SIZE && (r = conns[c]->Read(buf, sizeof(buf))) != 0)
+ {
+ total += r;
+ }
+ TEST_THAT(total == LARGE_DATA_SIZE);
+ }
for(unsigned int c = 0; c < conns.size(); ++c)
{
@@ -441,108 +476,184 @@ int test(int argc, const char *argv[])
// Server launching stuff
if(argc >= 2)
{
- if(strcmp(argv[1], "srv1") == 0)
+ // this is a quick hack to allow passing some options
+ // to the daemon
+
+ const char* mode = argv[1];
+
+ if (test_args.length() > 0)
+ {
+ argv[1] = test_args.c_str();
+ }
+ else
+ {
+ argc--;
+ argv++;
+ }
+
+ if(strcmp(mode, "srv1") == 0)
{
// Run very basic daemon
basicdaemon daemon;
- return daemon.Main("doesnotexist", argc - 1, argv + 1);
+ return daemon.Main("doesnotexist", argc, argv);
}
- else if(strcmp(argv[1], "srv2") == 0)
+ else if(strcmp(mode, "srv2") == 0)
{
// Run daemon which accepts connections
testserver daemon;
- return daemon.Main("doesnotexist", argc - 1, argv + 1);
+ return daemon.Main("doesnotexist", argc, argv);
}
- else if(strcmp(argv[1], "srv3") == 0)
+ else if(strcmp(mode, "srv3") == 0)
{
testTLSserver daemon;
- return daemon.Main("doesnotexist", argc - 1, argv + 1);
+ return daemon.Main("doesnotexist", argc, argv);
}
- else if(strcmp(argv[1], "srv4") == 0)
+ else if(strcmp(mode, "srv4") == 0)
{
testProtocolServer daemon;
- return daemon.Main("doesnotexist", argc - 1, argv + 1);
+ return daemon.Main("doesnotexist", argc, 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");
+ std::string cmd = "./test --test-daemon-args=";
+ cmd += test_args;
+ cmd += " srv1 testfiles/srv1.conf";
+ int pid = LaunchServer(cmd, "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");
+ std::string cmd = "./test --test-daemon-args=";
+ cmd += test_args;
+ cmd += " srv2 testfiles/srv2.conf";
+ int pid = LaunchServer(cmd, "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");
+ std::string cmd = "./test --test-daemon-args=";
+ cmd += test_args;
+ cmd += " srv3 testfiles/srv3.conf";
+ int pid = LaunchServer(cmd, "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
@@ -557,37 +668,62 @@ 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");
+ std::string cmd = "./test --test-daemon-args=";
+ cmd += test_args;
+ cmd += " srv4 testfiles/srv4.conf";
+ int pid = LaunchServer(cmd, "testfiles/srv4.pid");
+
TEST_THAT(pid != -1 && pid != 0);
+
if(pid > 0)
{
::sleep(1);
@@ -595,7 +731,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);
@@ -658,7 +798,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 a085a96c..0447bc9c 100644
--- a/test/bbackupd/testbbackupd.cpp
+++ b/test/bbackupd/testbbackupd.cpp
@@ -1,4 +1,4 @@
-// distribution boxbackup-0.10 (svn version: 494)
+// distribution boxbackup-0.11rc1 (svn version: 2023_2024)
//
// Copyright (c) 2003 - 2006
// Ben Summers and contributors. All rights reserved.
@@ -47,38 +47,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"
@@ -90,20 +117,34 @@
// two cycles and a bit
#define TIME_TO_WAIT_FOR_BACKUP_OPERATION 12
+// utility macro for comparing two strings in a line
+#define TEST_EQUAL(expected, found, line) \
+{ \
+ std::string exp_str = expected; \
+ std::string found_str = found; \
+ TEST_THAT(exp_str == found_str); \
+ if(exp_str != found_str) \
+ { \
+ printf("Expected <%s> but found <%s> in <%s>\n", \
+ exp_str.c_str(), found_str.c_str(), line.c_str()); \
+ } \
+}
+
+// utility macro for testing a line
+#define TEST_LINE(condition, line) \
+ TEST_THAT(condition); \
+ if (!(condition)) \
+ { \
+ printf("Test failed on <%s>\n", line.c_str()); \
+ }
+
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)
@@ -290,6 +331,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];
@@ -300,6 +344,7 @@ bool attrmatch(const char *f1, const char *f2)
p1[p1l] = '\0';
p2[p2l] = '\0';
return strcmp(p1, p2) == 0;
+#endif
}
// modification times
@@ -318,12 +363,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);
@@ -336,13 +384,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)
@@ -415,18 +470,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
}
@@ -437,9 +496,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;
}
@@ -475,6 +538,7 @@ void terminate_on_alarm(int sigraised)
abort();
}
+#ifndef WIN32
void do_interrupted_restore(const TLSContext &context, int64_t restoredirid)
{
int pid = 0;
@@ -537,12 +601,242 @@ void do_interrupted_restore(const TLSContext &context, int64_t restoredirid)
}
}
}
+#endif // !WIN32
+
+#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;
+}
+
+SocketStreamTLS sSocket;
+
+std::auto_ptr<BackupProtocolClient> Connect(TLSContext& rContext, int flags)
+{
+ sSocket.Open(rContext, Socket::TypeINET,
+ "localhost", BOX_PORT_BBSTORED);
+ std::auto_ptr<BackupProtocolClient> connection;
+ connection.reset(new BackupProtocolClient(sSocket));
+ 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(0x01234567, flags);
+ return connection;
+}
+
+std::auto_ptr<BackupStoreDirectory> ReadDirectory
+(
+ BackupProtocolClient& rClient,
+ int64_t id
+)
+{
+ std::auto_ptr<BackupProtocolClientSuccess> dirreply(
+ rClient.QueryListDirectory(id, false, 0, false));
+ std::auto_ptr<IOStream> dirstream(rClient.ReceiveStream());
+ std::auto_ptr<BackupStoreDirectory> apDir(new BackupStoreDirectory());
+ apDir->ReadFromStream(*dirstream, rClient.GetTimeout());
+ return apDir;
+}
+
+int start_internal_daemon()
+{
+ // ensure that no child processes end up running tests!
+ int own_pid = getpid();
+
+ // this is a quick hack to allow passing some options to the daemon
+ const char* argv[] = {
+ "dummy",
+ bbackupd_args.c_str(),
+ };
+
+ BackupDaemon daemon;
+ int result;
+
+ if (bbackupd_args.size() > 0)
+ {
+ result = daemon.Main("testfiles/bbackupd.conf", 2, argv);
+ }
+ else
+ {
+ result = daemon.Main("testfiles/bbackupd.conf", 1, argv);
+ }
+
+ 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;
+}
+
+bool stop_internal_daemon(int pid)
+{
+ bool killed_server = KillServer(pid);
+ TEST_THAT(killed_server);
+ return killed_server;
+
+ /*
+ 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);
+ // we will not be called again.
+#endif
+ }
+
+ // 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;
@@ -553,39 +847,553 @@ 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");
- int pid = LaunchServer("../../bin/bbackupd/bbackupd testfiles/bbackupd.conf", "testfiles/bbackupd.pid");
- TEST_THAT(pid != -1 && pid != 0);
- if(pid > 0)
{
- ::sleep(1);
- TEST_THAT(ServerIsAlive(pid));
+ #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];
+ memset(buffer, 0, sizeof(buffer));
+
+ TEST_THAT(write(fd, buffer, sizeof(buffer)) == sizeof(buffer));
+ TEST_THAT(close(fd) == 0);
+
+ int pid = start_internal_daemon();
+ wait_for_backup_operation();
+ TEST_THAT(stop_internal_daemon(pid));
+
+ // two-second delay on the first read() of f1
+ // should mean that a single keepalive is sent,
+ // and diff does not abort.
+ 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());
+ TEST_THAT(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_EQUAL(comp, line.substr(0, comp.size()), line);
+ TEST_THAT(reader.GetLine(line));
+ TEST_EQUAL("Receiving stream, size 124", line, line);
+ TEST_THAT(reader.GetLine(line));
+ TEST_EQUAL("Send GetIsAlive()", line, line);
+ TEST_THAT(reader.GetLine(line));
+ TEST_EQUAL("Receive IsAlive()", line, line);
+
+ TEST_THAT(reader.GetLine(line));
+ comp = "Send StoreFile(0x3,";
+ TEST_EQUAL(comp, line.substr(0, comp.size()), line);
+ comp = ",\"f1\")";
+ std::string sub = line.substr(line.size() - comp.size());
+ TEST_EQUAL(comp, sub, line);
+ std::string comp2 = ",0x0,";
+ sub = line.substr(line.size() - comp.size() -
+ comp2.size() + 1, comp2.size());
+ TEST_LINE(comp2 != sub, line);
+ }
+
+ if (failures > 0)
+ {
+ // stop early to make debugging easier
+ Timers::Init();
+ return 1;
+ }
+
+ // four-second delay on first read() of f1
+ // should mean that no keepalives were sent,
+ // because diff was immediately aborted
+ // before any matching blocks could be found.
+ 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());
+ TEST_THAT(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_EQUAL(comp, line.substr(0, comp.size()), line);
+ comp = ",0x0,\"f1\")";
+ std::string sub = line.substr(line.size() - comp.size());
+ TEST_EQUAL(comp, sub, line);
+ }
+
+ if (failures > 0)
+ {
+ // stop early to make debugging easier
+ Timers::Init();
+ return 1;
+ }
+
+ 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());
+ TEST_THAT(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()");
+
+ // but two matching blocks should have been found
+ // already, so the upload should be a diff.
+
+ TEST_THAT(reader.GetLine(line));
+ comp = "Send StoreFile(0x3,";
+ TEST_EQUAL(comp, line.substr(0, comp.size()), line);
+ comp = ",\"f1\")";
+ std::string sub = line.substr(line.size() - comp.size());
+ TEST_EQUAL(comp, sub, line);
+ std::string comp2 = ",0x0,";
+ sub = line.substr(line.size() - comp.size() -
+ comp2.size() + 1, comp2.size());
+ TEST_LINE(comp2 != sub, line);
+ }
+
+ if (failures > 0)
+ {
+ // stop early to make debugging easier
+ Timers::Init();
+ return 1;
+ }
+
+ 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);
- // First, check storage space handling -- wait for file to be uploaded
wait_for_backup_operation();
- //TEST_THAT_ABORTONFAIL(::system("../../bin/bbstoreaccounts/bbstoreaccounts -c testfiles/bbstored.conf info 01234567") == 0);
+ // can't test whether intercept was triggered, because
+ // it's in a different process.
+ // TEST_THAT(intercept_triggered());
+ TEST_THAT(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_EQUAL("Receive Success(0x3)", line, line);
+ TEST_THAT(reader.GetLine(line));
+ TEST_EQUAL("Receiving stream, size 425", line, line);
+ TEST_THAT(reader.GetLine(line));
+ TEST_EQUAL("Send GetIsAlive()", line, line);
+ TEST_THAT(reader.GetLine(line));
+ TEST_EQUAL("Receive IsAlive()", line, line);
+ TEST_THAT(reader.GetLine(line));
+ TEST_EQUAL("Send GetIsAlive()", line, line);
+ TEST_THAT(reader.GetLine(line));
+ TEST_EQUAL("Receive IsAlive()", line, line);
+ }
+
+ if (failures > 0)
+ {
+ // stop early to make debugging easier
+ Timers::Init();
+ return 1;
+ }
+
+ 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-temploc.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;
+
+ printf("\n==== Testing that absolute symlinks are not followed "
+ "during restore\n");
+
+ {
+ #define SYM_DIR "testfiles" DIRECTORY_SEPARATOR "TestDir1" \
+ DIRECTORY_SEPARATOR "symlink_test"
+
+ TEST_THAT(::mkdir(SYM_DIR, 0777) == 0);
+ TEST_THAT(::mkdir(SYM_DIR DIRECTORY_SEPARATOR "a", 0777) == 0);
+ TEST_THAT(::mkdir(SYM_DIR DIRECTORY_SEPARATOR "a"
+ DIRECTORY_SEPARATOR "subdir", 0777) == 0);
+ TEST_THAT(::mkdir(SYM_DIR DIRECTORY_SEPARATOR "b", 0777) == 0);
+
+ FILE* fp = fopen(SYM_DIR DIRECTORY_SEPARATOR "a"
+ DIRECTORY_SEPARATOR "subdir"
+ DIRECTORY_SEPARATOR "content", "w");
+ TEST_THAT(fp != NULL);
+ fputs("before\n", fp);
+ fclose(fp);
+
+ char buf[PATH_MAX];
+ TEST_THAT(getcwd(buf, sizeof(buf)) != NULL);
+ std::string path = buf;
+ path += DIRECTORY_SEPARATOR SYM_DIR
+ DIRECTORY_SEPARATOR "a"
+ DIRECTORY_SEPARATOR "subdir";
+ TEST_THAT(symlink(path.c_str(), SYM_DIR
+ DIRECTORY_SEPARATOR "b"
+ DIRECTORY_SEPARATOR "link") == 0);
+
+ ::wait_for_operation(4);
+ ::sync_and_wait();
+
+ // Check that the backup was successful, i.e. no differences
+ int compareReturnValue = ::system(BBACKUPQUERY " -q "
+ "-c testfiles/bbackupd.conf "
+ "-l testfiles/query1.log "
+ "\"compare -acQ\" quit");
+ TEST_RETURN(compareReturnValue, 1);
+ TestRemoteProcessMemLeaks("bbackupquery.memleaks");
+
+ // now stop bbackupd and update the test file,
+ // make the original directory unreadable
+ terminate_bbackupd(bbackupd_pid);
+
+ fp = fopen(SYM_DIR DIRECTORY_SEPARATOR "a"
+ DIRECTORY_SEPARATOR "subdir"
+ DIRECTORY_SEPARATOR "content", "w");
+ TEST_THAT(fp != NULL);
+ fputs("after\n", fp);
+ fclose(fp);
+
+ TEST_THAT(chmod(SYM_DIR, 0) == 0);
+
+ // check that we can restore it
+ compareReturnValue = ::system(BBACKUPQUERY " "
+ "-c testfiles/bbackupd.conf "
+ "-q \"restore Test1 testfiles/restore-symlink\" "
+ "quit");
+ TEST_RETURN(compareReturnValue, 0);
+
+ // make it accessible again
+ TEST_THAT(chmod(SYM_DIR, 0755) == 0);
+
+ // check that the original file was not overwritten
+ FileStream fs(SYM_DIR "/a/subdir/content");
+ IOStreamGetLine gl(fs);
+ std::string line;
+ TEST_THAT(gl.GetLine(line));
+ TEST_THAT(line != "before");
+ TEST_THAT(line == "after");
+
+ #undef SYM_DIR
+
+ 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;
+ }
+
+ printf("\n==== Testing that redundant locations are deleted on time\n");
+
+ {
+ std::auto_ptr<BackupProtocolClient> client = Connect(
+ context,
+ BackupProtocolClientLogin::Flags_ReadOnly);
+
+ std::auto_ptr<BackupStoreDirectory> dir = ReadDirectory(
+ *client,
+ BackupProtocolClientListDirectory::RootDirectory);
+
+ // int64_t testDirId = SearchDir(*dir, "Test2");
+ // TEST_THAT(testDirId == 0);
+
+ sync_and_wait();
+
+ dir = ReadDirectory(*client,
+ BackupProtocolClientListDirectory::RootDirectory);
+ int64_t testDirId = SearchDir(*dir, "Test2");
+ TEST_THAT(testDirId != 0);
+
+ // Kill the daemon
+ terminate_bbackupd(bbackupd_pid);
+
+ 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;
+
+ // Test2 should be deleted after 10 seconds (4 runs)
+ wait_for_sync_end();
+ wait_for_sync_end();
+ wait_for_sync_end();
+
+ dir = ReadDirectory(*client,
+ BackupProtocolClientListDirectory::RootDirectory);
+ testDirId = SearchDir(*dir, "Test2");
+ TEST_THAT(testDirId != 0);
+
+ wait_for_sync_end();
+
+ dir = ReadDirectory(*client,
+ BackupProtocolClientListDirectory::RootDirectory);
+ testDirId = SearchDir(*dir, "Test2");
+ TEST_THAT(testDirId != 0);
+
+ BackupStoreDirectory::Iterator i(*dir);
+ BackupStoreFilenameClear dirname("Test2");
+ BackupStoreDirectory::Entry *en = i.FindMatchingClearName(dirname);
+ TEST_THAT(en != 0);
+ int16_t en_flags = en->GetFlags();
+ TEST_THAT(en_flags && BackupStoreDirectory::Entry::Flags_Deleted);
+
+ // Log out.
+ client->QueryFinished();
+ sSocket.Close();
+ }
+
+ 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)
+ {
+ printf("\n==== Testing that backup pauses when store is full\n");
+
+ // wait for files to be uploaded
+ wait_for_backup_operation();
+
// 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
@@ -594,185 +1402,1069 @@ 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
+ {
+ std::auto_ptr<BackupProtocolClient> client =
+ Connect(context, 0);
+
+ std::auto_ptr<BackupStoreDirectory> dir = ReadDirectory(
+ *client,
+ BackupProtocolClientListDirectory::RootDirectory);
+
+ int64_t baseDirId = SearchDir(*dir, "Test1");
+ TEST_THAT(baseDirId != 0);
+ dir = ReadDirectory(*client, baseDirId);
+
+ int64_t testDirId = SearchDir(dir, dirname.c_str());
+ TEST_THAT(testDirId != 0);
+ dir = ReadDirectory(*client, testDirId);
- printf("Delete file and update another, create symlink.\n");
+ TEST_THAT(SearchDir(dir, filename.c_str()) != 0);
+ // Log out
+ client->QueryFinished();
+ sSocket.Close();
+ }
+
+
+ // 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);
+
+ 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);
+
+ // bbackupquery compare might take a while
+ // on slow machines, so start the timer now
+ long start_time = time(NULL);
+
+ // 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");
+
+ 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 bbstored.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("../../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");
+
+ 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(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::auto_ptr<BackupProtocolClient> client = Connect(
+ context,
+ BackupProtocolClientLogin::Flags_ReadOnly);
+
+ std::auto_ptr<BackupStoreDirectory> dir = ReadDirectory(
+ *client,
+ BackupProtocolClientListDirectory::RootDirectory);
+
+ int64_t testDirId = SearchDir(*dir, "Test1");
+ TEST_THAT(testDirId != 0);
+ dir = ReadDirectory(*client, testDirId);
+
+ 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);
+ dir = ReadDirectory(*client, sub23id);
+
+ TEST_THAT(!SearchDir(*dir, "xx_not_this_dir_22"));
+ TEST_THAT(!SearchDir(*dir, "somefile.excludethis"));
+ client->QueryFinished();
+ sSocket.Close();
+ }
+
+ 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
- printf("Continuously update file, check isn't uploaded\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==== 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
@@ -782,39 +2474,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);
@@ -823,109 +2530,284 @@ 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);
- BackupProtocolClient protocol(conn);
- protocol.QueryVersion(BACKUP_STORE_SERVER_VERSION);
- std::auto_ptr<BackupProtocolClientLoginConfirmed> loginConf(protocol.QueryLogin(0x01234567, BackupProtocolClientLogin::Flags_ReadOnly));
+ std::auto_ptr<BackupProtocolClient> client = Connect(
+ context,
+ BackupProtocolClientLogin::Flags_ReadOnly);
// Find the ID of the Test1 directory
- restoredirid = GetDirID(protocol, "Test1", BackupProtocolClientListDirectory::RootDirectory);
+ restoredirid = GetDirID(*client, "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(*client, 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(*client, 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(*client, restoredirid,
+ "testfiles/no-such-path/subdir",
+ true /* print progress dots */)
+ == Restore_TargetPathNotFound);
// Find ID of the deleted directory
- deldirid = GetDirID(protocol, "x1", restoredirid);
+ deldirid = GetDirID(*client, "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(*client, deldirid,
+ "testfiles/restore-Test1-x1",
+ true /* print progress dots */,
+ true /* deleted files */)
+ == Restore_Complete);
// Log out
- protocol.QueryFinished();
+ client->QueryFinished();
+ sSocket.Close();
}
- 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;
@@ -934,7 +2816,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
@@ -958,10 +2841,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);
@@ -970,56 +2858,105 @@ 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);
- BackupProtocolClient protocol(conn);
- protocol.QueryVersion(BACKUP_STORE_SERVER_VERSION);
- std::auto_ptr<BackupProtocolClientLoginConfirmed> loginConf(protocol.QueryLogin(0x01234567, 0)); // read-write
+ std::auto_ptr<BackupProtocolClient> client = Connect(
+ context,
+ BackupProtocolClientLogin::Flags_ReadOnly);
- // 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(*client, 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(*client, restoredirid,
+ "testfiles/restore-interrupt",
+ true /* print progress dots */,
+ false /* deleted files */,
+ false /* undelete server */,
+ true /* resume */)
+ == Restore_Complete);
- protocol.QueryFinished();
+ client->QueryFinished();
+ sSocket.Close();
// 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);
- BackupProtocolClient protocol(conn);
- protocol.QueryVersion(BACKUP_STORE_SERVER_VERSION);
- std::auto_ptr<BackupProtocolClientLoginConfirmed> loginConf(protocol.QueryLogin(0x01234567, 0)); // read-write
+ std::auto_ptr<BackupProtocolClient> client = Connect(
+ context, 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(*client, deldirid,
+ "testfiles/restore-Test1-x1-2",
+ true /* print progress dots */,
+ true /* deleted files */,
+ true /* undelete on server */)
+ == Restore_Complete);
- protocol.QueryFinished();
+ client->QueryFinished();
+ sSocket.Close();
// 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");
}
@@ -1027,39 +2964,125 @@ 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;
}
@@ -1073,7 +3096,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
@@ -1087,10 +3116,14 @@ 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();
return 0;
}
-
diff --git a/test/bbackupd/testextra b/test/bbackupd/testextra
index ad7dd552..85783cca 100644
--- a/test/bbackupd/testextra
+++ b/test/bbackupd/testextra
@@ -1,4 +1,4 @@
-# distribution boxbackup-0.10 (svn version: 494)
+# distribution boxbackup-0.11rc1 (svn version: 2023_2024)
#
# Copyright (c) 2003 - 2006
# Ben Summers and contributors. All rights reserved.
diff --git a/test/bbackupd/testfiles/bbackupd-temploc.conf b/test/bbackupd/testfiles/bbackupd-temploc.conf
new file mode 100644
index 00000000..86901298
--- /dev/null
+++ b/test/bbackupd/testfiles/bbackupd-temploc.conf
@@ -0,0 +1,54 @@
+
+CertificateFile = testfiles/clientCerts.pem
+PrivateKeyFile = testfiles/clientPrivKey.pem
+TrustedCAsFile = testfiles/clientTrustedCAs.pem
+
+KeysFile = testfiles/bbackupd.keys
+
+DataDirectory = testfiles/bbackupd-data
+
+StoreHostname = localhost
+AccountNumber = 0x01234567
+
+UpdateStoreInterval = 3
+MinimumFileAge = 4
+MaxUploadWait = 24
+
+FileTrackingSizeThreshold = 1024
+DiffingUploadSizeThreshold = 1024
+
+MaximumDiffingTime = 3
+KeepAliveTime = 1
+
+ExtendedLogging = no
+ExtendedLogFile = testfiles/bbackupd.log
+
+CommandSocket = testfiles/bbackupd.sock
+
+Server
+{
+ PidFile = testfiles/bbackupd.pid
+}
+
+BackupLocations
+{
+ Test1
+ {
+ Path = testfiles/TestDir1
+
+ ExcludeFile = testfiles/TestDir1/excluded_1
+ ExcludeFile = testfiles/TestDir1/excluded_2
+ ExcludeFilesRegex = \.excludethis$
+ ExcludeFilesRegex = EXCLUDE
+ AlwaysIncludeFile = testfiles/TestDir1/dont.excludethis
+ ExcludeDir = testfiles/TestDir1/exclude_dir
+ ExcludeDir = testfiles/TestDir1/exclude_dir_2
+ ExcludeDirsRegex = not_this_dir
+ AlwaysIncludeDirsRegex = ALWAYSINCLUDE
+ }
+ Test2
+ {
+ Path = testfiles/TestDir1
+ }
+}
+
diff --git a/test/bbackupd/testfiles/bbackupd.conf b/test/bbackupd/testfiles/bbackupd.conf
index c25b4eab..643978f2 100644..100755
--- a/test/bbackupd/testfiles/bbackupd.conf
+++ b/test/bbackupd/testfiles/bbackupd.conf
@@ -13,17 +13,21 @@ AccountNumber = 0x01234567
UpdateStoreInterval = 3
MinimumFileAge = 4
MaxUploadWait = 24
+DeleteRedundantLocationsAfter = 10
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 = /usr/bin/perl testfiles/notifyscript.pl
+SyncAllowScript = /usr/bin/perl testfiles/syncallowscript.pl
Server
{
diff --git a/test/bbackupd/testfiles/bbackupd.conf.in b/test/bbackupd/testfiles/bbackupd.conf.in
new file mode 100644
index 00000000..aecb3884
--- /dev/null
+++ b/test/bbackupd/testfiles/bbackupd.conf.in
@@ -0,0 +1,54 @@
+
+CertificateFile = testfiles/clientCerts.pem
+PrivateKeyFile = testfiles/clientPrivKey.pem
+TrustedCAsFile = testfiles/clientTrustedCAs.pem
+
+KeysFile = testfiles/bbackupd.keys
+
+DataDirectory = testfiles/bbackupd-data
+
+StoreHostname = localhost
+AccountNumber = 0x01234567
+
+UpdateStoreInterval = 3
+MinimumFileAge = 4
+MaxUploadWait = 24
+DeleteRedundantLocationsAfter = 10
+
+FileTrackingSizeThreshold = 1024
+DiffingUploadSizeThreshold = 1024
+
+MaximumDiffingTime = 3
+KeepAliveTime = 1
+
+ExtendedLogging = no
+ExtendedLogFile = testfiles/bbackupd.log
+
+CommandSocket = testfiles/bbackupd.sock
+
+NotifyScript = @TARGET_PERL@ testfiles/notifyscript.pl
+SyncAllowScript = @TARGET_PERL@ testfiles/syncallowscript.pl
+
+Server
+{
+ PidFile = testfiles/bbackupd.pid
+}
+
+BackupLocations
+{
+ Test1
+ {
+ Path = testfiles/TestDir1
+
+ ExcludeFile = testfiles/TestDir1/excluded_1
+ ExcludeFile = testfiles/TestDir1/excluded_2
+ ExcludeFilesRegex = \.excludethis$
+ ExcludeFilesRegex = EXCLUDE
+ AlwaysIncludeFile = testfiles/TestDir1/dont.excludethis
+ ExcludeDir = testfiles/TestDir1/exclude_dir
+ ExcludeDir = testfiles/TestDir1/exclude_dir_2
+ ExcludeDirsRegex = not_this_dir
+ AlwaysIncludeDirsRegex = ALWAYSINCLUDE
+ }
+}
+
diff --git a/test/bbackupd/testfiles/extcheck1.pl b/test/bbackupd/testfiles/extcheck1.pl
index 8bd5b91d..fe7f5caa 100755
--- a/test/bbackupd/testfiles/extcheck1.pl
+++ b/test/bbackupd/testfiles/extcheck1.pl
@@ -1,5 +1,5 @@
#!/usr/bin/perl
-# distribution boxbackup-0.10 (svn version: 494)
+# distribution boxbackup-0.11rc1 (svn version: 2023_2024)
#
# Copyright (c) 2003 - 2006
# Ben Summers and contributors. All rights reserved.
@@ -39,7 +39,9 @@
#
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;
@@ -53,14 +55,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/extcheck1.pl.in b/test/bbackupd/testfiles/extcheck1.pl.in
new file mode 100755
index 00000000..2a7c0e9a
--- /dev/null
+++ b/test/bbackupd/testfiles/extcheck1.pl.in
@@ -0,0 +1,44 @@
+#!@PERL@
+use strict;
+
+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;
+}
+
+my $ret = 1;
+my $seen = 0;
+
+while(<IN>)
+{
+ next unless m/\S/;
+ if(m/continousupdate/)
+ {
+ unless (/exists/)
+ {
+ print "FAIL: continousupdate line does not match\n";
+ $ret = 2;
+ }
+ $seen = 1;
+ }
+ else
+ {
+ 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 "READ: $_";
+}
+
+close IN;
+
+$ret = 2 unless $seen;
+
+exit $ret;
+
diff --git a/test/bbackupd/testfiles/extcheck2.pl b/test/bbackupd/testfiles/extcheck2.pl
index abf63ba9..4c2733a2 100755
--- a/test/bbackupd/testfiles/extcheck2.pl
+++ b/test/bbackupd/testfiles/extcheck2.pl
@@ -1,5 +1,5 @@
#!/usr/bin/perl
-# distribution boxbackup-0.10 (svn version: 494)
+# distribution boxbackup-0.11rc1 (svn version: 2023_2024)
#
# Copyright (c) 2003 - 2006
# Ben Summers and contributors. All rights reserved.
@@ -39,7 +39,9 @@
#
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;
@@ -52,13 +54,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/extcheck2.pl.in b/test/bbackupd/testfiles/extcheck2.pl.in
new file mode 100755
index 00000000..c79bf414
--- /dev/null
+++ b/test/bbackupd/testfiles/extcheck2.pl.in
@@ -0,0 +1,41 @@
+#!@PERL@
+use strict;
+
+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;
+}
+
+my $ret = 1;
+
+while(<IN>)
+{
+ next unless m/\S/;
+ if(m/continousupdate/)
+ {
+ unless (m/contents/ or m/attributes/)
+ {
+ print "FAIL: continuousupdate line does not match\n";
+ $ret = 2;
+ }
+ }
+ else
+ {
+ 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 "READ: $_";
+}
+
+close IN;
+
+exit $ret;
+
diff --git a/test/bbackupd/testfiles/notifyscript.pl b/test/bbackupd/testfiles/notifyscript.pl
index deadadb9..b35c6573 100755
--- a/test/bbackupd/testfiles/notifyscript.pl
+++ b/test/bbackupd/testfiles/notifyscript.pl
@@ -1,5 +1,5 @@
#!/usr/bin/perl
-# distribution boxbackup-0.10 (svn version: 494)
+# distribution boxbackup-0.11rc1 (svn version: 2023_2024)
#
# Copyright (c) 2003 - 2006
# Ben Summers and contributors. All rights reserved.
diff --git a/test/bbackupd/testfiles/notifyscript.pl.in b/test/bbackupd/testfiles/notifyscript.pl.in
new file mode 100755
index 00000000..89741e46
--- /dev/null
+++ b/test/bbackupd/testfiles/notifyscript.pl.in
@@ -0,0 +1,15 @@
+#!@TARGET_PERL@
+
+
+my $f = 'testfiles/notifyran.'.$ARGV[0].'.';
+my $n = 1;
+
+while(-e $f.$n)
+{
+ $n ++;
+}
+
+open FL,'>'.$f.$n;
+print FL localtime();
+close FL;
+
diff --git a/test/bbackupd/testfiles/syncallowscript.pl b/test/bbackupd/testfiles/syncallowscript.pl
new file mode 100755
index 00000000..d06ff238
--- /dev/null
+++ b/test/bbackupd/testfiles/syncallowscript.pl
@@ -0,0 +1,71 @@
+#!/usr/bin/perl
+# distribution boxbackup-0.11rc1 (svn version: 2023_2024)
+#
+# Copyright (c) 2003 - 2006
+# Ben Summers and contributors. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# 3. All use of this software and associated advertising materials must
+# display the following acknowledgment:
+# This product includes software developed by Ben Summers.
+# 4. The names of the Authors may not be used to endorse or promote
+# products derived from this software without specific prior written
+# permission.
+#
+# [Where legally impermissible the Authors do not disclaim liability for
+# direct physical injury or death caused solely by defects in the software
+# unless it is modified by a third party.]
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
+# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+# DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT,
+# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+#
+#
+
+use strict;
+use warnings;
+
+my $control_file = 'testfiles/syncallowscript.control';
+if (! -r $control_file)
+{
+ print "now\n";
+ exit 0;
+}
+
+my $control_state;
+open CONTROL, "< $control_file" or die "$control_file: $!";
+$control_state = <CONTROL>;
+defined $control_state or die "$control_file: read failed: $!";
+close CONTROL;
+
+my $marker_file_root = 'testfiles/syncallowscript.notifyran.';
+my $n = 1;
+my $marker_file;
+
+while($marker_file = $marker_file_root.$n and -e $marker_file)
+{
+ $n ++;
+}
+
+open FL,'>'.$marker_file or die "$marker_file: $!";
+print FL localtime();
+close FL;
+
+print $control_state;
+exit 0;
diff --git a/test/bbackupd/testfiles/syncallowscript.pl.in b/test/bbackupd/testfiles/syncallowscript.pl.in
new file mode 100755
index 00000000..f2ef1171
--- /dev/null
+++ b/test/bbackupd/testfiles/syncallowscript.pl.in
@@ -0,0 +1,33 @@
+#!@TARGET_PERL@
+
+use strict;
+use warnings;
+
+my $control_file = 'testfiles/syncallowscript.control';
+if (! -r $control_file)
+{
+ print "now\n";
+ exit 0;
+}
+
+my $control_state;
+open CONTROL, "< $control_file" or die "$control_file: $!";
+$control_state = <CONTROL>;
+defined $control_state or die "$control_file: read failed: $!";
+close CONTROL;
+
+my $marker_file_root = 'testfiles/syncallowscript.notifyran.';
+my $n = 1;
+my $marker_file;
+
+while($marker_file = $marker_file_root.$n and -e $marker_file)
+{
+ $n ++;
+}
+
+open FL,'>'.$marker_file or die "$marker_file: $!";
+print FL localtime();
+close FL;
+
+print $control_state;
+exit 0;
diff --git a/test/common/testcommon.cpp b/test/common/testcommon.cpp
index ac388b33..cba8b692 100644
--- a/test/common/testcommon.cpp
+++ b/test/common/testcommon.cpp
@@ -1,4 +1,4 @@
-// distribution boxbackup-0.10 (svn version: 494)
+// distribution boxbackup-0.11rc1 (svn version: 2023_2024)
//
// Copyright (c) 2003 - 2006
// Ben Summers and contributors. All rights reserved.
@@ -47,13 +47,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"
@@ -62,6 +65,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"
@@ -168,11 +177,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);
@@ -188,9 +325,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[] =
{
@@ -575,7 +788,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);
@@ -584,24 +797,123 @@ int test(int argc, const char *argv[])
TEST_CHECK_THROWS(elist.AddRegexEntries(std::string("[a-d]+\\.reg$" "\x01" "EXCLUDE" "\x01" "^exclude$")), CommonException, RegexNotSupportedOnThisPlatform);
TEST_THAT(elist.SizeOfRegexList() == 0);
#endif
+
+ #ifdef WIN32
+ #define CASE_SENSITIVE false
+ #else
+ #define CASE_SENSITIVE true
+ #endif
+
// Try some matches!
TEST_THAT(elist.IsExcluded(std::string("Definite1")) == true);
TEST_THAT(elist.IsExcluded(std::string("/dir/DefNumberTwo")) == true);
TEST_THAT(elist.IsExcluded(std::string("ThingDefThree")) == true);
TEST_THAT(elist.IsExcluded(std::string("AnotherDef")) == true);
TEST_THAT(elist.IsExcluded(std::string("dir/DefNumberTwo")) == false);
- #ifdef HAVE_REGEX_H
+
+ // Try some case insensitive matches,
+ // that should pass on Win32 and fail elsewhere
+ TEST_THAT(elist.IsExcluded("DEFINITe1")
+ == !CASE_SENSITIVE);
+ TEST_THAT(elist.IsExcluded("/Dir/DefNumberTwo")
+ == !CASE_SENSITIVE);
+ TEST_THAT(elist.IsExcluded("thingdefthree")
+ == !CASE_SENSITIVE);
+
+ #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);
TEST_THAT(elist.IsExcluded(std::string("e.reg")) == false);
- TEST_THAT(elist.IsExcluded(std::string("b.Reg")) == false);
- TEST_THAT(elist.IsExcluded(std::string("DEfinite1")) == false);
+ TEST_THAT(elist.IsExcluded(std::string("e.Reg")) == false);
+ TEST_THAT(elist.IsExcluded(std::string("DEfinite1")) == !CASE_SENSITIVE);
TEST_THAT(elist.IsExcluded(std::string("DEXCLUDEfinite1")) == true);
- TEST_THAT(elist.IsExcluded(std::string("DEfinitexclude1")) == false);
+ TEST_THAT(elist.IsExcluded(std::string("DEfinitexclude1")) == !CASE_SENSITIVE);
TEST_THAT(elist.IsExcluded(std::string("exclude")) == true);
+ TEST_THAT(elist.IsExcluded(std::string("ExcludE")) == !CASE_SENSITIVE);
#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/compress/testcompress.cpp b/test/compress/testcompress.cpp
index a7ea1298..a8367722 100644
--- a/test/compress/testcompress.cpp
+++ b/test/compress/testcompress.cpp
@@ -1,4 +1,4 @@
-// distribution boxbackup-0.10 (svn version: 494)
+// distribution boxbackup-0.11rc1 (svn version: 2023_2024)
//
// Copyright (c) 2003 - 2006
// Ben Summers and contributors. All rights reserved.
diff --git a/test/crypto/testcrypto.cpp b/test/crypto/testcrypto.cpp
index f3e9fb50..0dd7debb 100644
--- a/test/crypto/testcrypto.cpp
+++ b/test/crypto/testcrypto.cpp
@@ -1,4 +1,4 @@
-// distribution boxbackup-0.10 (svn version: 494)
+// distribution boxbackup-0.11rc1 (svn version: 2023_2024)
//
// Copyright (c) 2003 - 2006
// Ben Summers and contributors. All rights reserved.
diff --git a/test/raidfile/intercept.cpp b/test/raidfile/intercept.cpp
deleted file mode 100644
index aa756b60..00000000
--- a/test/raidfile/intercept.cpp
+++ /dev/null
@@ -1,310 +0,0 @@
-// distribution boxbackup-0.10 (svn version: 494)
-//
-// Copyright (c) 2003 - 2006
-// Ben Summers and contributors. All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions
-// are met:
-// 1. Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// 2. Redistributions in binary form must reproduce the above copyright
-// notice, this list of conditions and the following disclaimer in the
-// documentation and/or other materials provided with the distribution.
-// 3. All use of this software and associated advertising materials must
-// display the following acknowledgment:
-// This product includes software developed by Ben Summers.
-// 4. The names of the Authors may not be used to endorse or promote
-// products derived from this software without specific prior written
-// permission.
-//
-// [Where legally impermissible the Authors do not disclaim liability for
-// direct physical injury or death caused solely by defects in the software
-// unless it is modified by a third party.]
-//
-// THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
-// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-// DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT,
-// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
-// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
-// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-// POSSIBILITY OF SUCH DAMAGE.
-//
-//
-//
-// --------------------------------------------------------------------------
-//
-// 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/testextra b/test/raidfile/testextra
index 7b0bd613..1d668dd1 100644
--- a/test/raidfile/testextra
+++ b/test/raidfile/testextra
@@ -1,4 +1,4 @@
-# distribution boxbackup-0.10 (svn version: 494)
+# distribution boxbackup-0.11rc1 (svn version: 2023_2024)
#
# Copyright (c) 2003 - 2006
# Ben Summers and contributors. All rights reserved.
diff --git a/test/raidfile/testraidfile.cpp b/test/raidfile/testraidfile.cpp
index 04b5b454..1e5715af 100644
--- a/test/raidfile/testraidfile.cpp
+++ b/test/raidfile/testraidfile.cpp
@@ -1,4 +1,4 @@
-// distribution boxbackup-0.10 (svn version: 494)
+// distribution boxbackup-0.11rc1 (svn version: 2023_2024)
//
// Copyright (c) 2003 - 2006
// Ben Summers and contributors. All rights reserved.
@@ -50,7 +50,10 @@
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
+
+#ifdef HAVE_SYSCALL
#include <sys/syscall.h>
+#endif
#include <string.h>
@@ -245,16 +248,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);
@@ -290,9 +301,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
@@ -397,10 +414,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...
@@ -428,14 +447,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;
@@ -474,14 +498,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)
{
@@ -574,7 +600,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);
@@ -595,7 +623,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];
@@ -612,9 +640,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"));
@@ -646,9 +677,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]);
@@ -662,7 +696,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]);
@@ -673,7 +708,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
@@ -725,7 +762,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");
@@ -733,7 +772,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.
@@ -750,7 +791,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");
@@ -759,7 +801,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(
@@ -774,20 +817,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)),
@@ -799,7 +845,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"),
@@ -810,22 +856,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);
@@ -841,15 +887,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 02dfd5b5..62670cac 100644
--- a/test/win32/testlibwin32.cpp
+++ b/test/win32/testlibwin32.cpp
@@ -1,4 +1,4 @@
-// distribution boxbackup-0.10 (svn version: 494)
+// distribution boxbackup-0.11rc1 (svn version: 2023_2024)
//
// Copyright (c) 2003 - 2006
// Ben Summers and contributors. All rights reserved.
@@ -44,12 +44,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;
@@ -63,12 +265,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\\");
@@ -79,12 +280,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);
@@ -92,47 +293,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
@@ -143,6 +367,7 @@ int main(int argc, char* argv[])
closelog();
+ /*
//first off get the path name for the default
char buf[MAX_PATH];
@@ -150,7 +375,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;
}
diff --git a/test/win32/timezone.cpp b/test/win32/timezone.cpp
index 0a336206..04e0a202 100644
--- a/test/win32/timezone.cpp
+++ b/test/win32/timezone.cpp
@@ -1,4 +1,4 @@
-// distribution boxbackup-0.10 (svn version: 494)
+// distribution boxbackup-0.11rc1 (svn version: 2023_2024)
//
// Copyright (c) 2003 - 2006
// Ben Summers and contributors. All rights reserved.