summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Wilson <chris+github@qwirx.com>2014-09-18 20:28:51 +0000
committerChris Wilson <chris+github@qwirx.com>2014-09-18 20:28:51 +0000
commitc176b130dfb2b810f91fd1b852c7d330af4cfb79 (patch)
tree9cd2d4e89507efa2b0f7b22f887d7b4030581204
parent13090390a71ead775285c1de7da41adc6062a8fd (diff)
Add test for disappearing directory causing attempt to upload an empty stream.
This caused the issue reported by Brendon Baumgartner and described in my email to the Box Backup list on Mon, 21 Apr 2014 at 18:44:38. If the directory disappears then we used to try to send an empty attributes block to the server, which is illegal.
-rw-r--r--test/bbackupd/testbbackupd.cpp157
1 files changed, 157 insertions, 0 deletions
diff --git a/test/bbackupd/testbbackupd.cpp b/test/bbackupd/testbbackupd.cpp
index fd250b80..d85d2595 100644
--- a/test/bbackupd/testbbackupd.cpp
+++ b/test/bbackupd/testbbackupd.cpp
@@ -43,7 +43,9 @@
#endif
#include "BackupClientCryptoKeys.h"
+#include "BackupClientContext.h"
#include "BackupClientFileAttributes.h"
+#include "BackupClientInodeToIDMap.h"
#include "BackupClientRestore.h"
#include "BackupDaemon.h"
#include "BackupDaemonConfigVerify.h"
@@ -67,6 +69,7 @@
#include "intercept.h"
#include "IOStreamGetLine.h"
#include "LocalProcessStream.h"
+#include "MemBlockStream.h"
#include "RaidFileController.h"
#include "SSLLib.h"
#include "ServerControl.h"
@@ -1215,6 +1218,158 @@ bool test_getobject_on_nonexistent_file()
TEARDOWN();
}
+// ASSERT((mpBlockIndex == 0) || (NumBlocksInIndex != 0)) in
+// BackupStoreFileEncodeStream::Recipe::Recipe once failed, apparently because
+// a zero byte file had a block index but no entries in it. But this test
+// doesn't reproduce the error, so it's not enabled for now.
+
+bool test_replace_zero_byte_file_with_nonzero_byte_file()
+{
+ SETUP();
+
+ TEST_THAT_OR(mkdir("testfiles/TestDir1", 0755) == 0, FAIL);
+ FileStream emptyFile("testfiles/TestDir1/f2",
+ O_WRONLY | O_CREAT | O_EXCL, 0755);
+ wait_for_operation(5, "f2 to be old enough");
+
+ BackupProtocolLocal2 client(0x01234567, "test",
+ "backup/01234567/", 0, false);
+ MockBackupDaemon bbackupd(client);
+ TEST_THAT(configure_bbackupd(bbackupd, "testfiles/bbackupd.conf"));
+ bbackupd.RunSyncNow();
+ TEST_COMPARE_LOCAL(Compare_Same, client);
+
+ MemBlockStream stream("Hello world");
+ stream.CopyStreamTo(emptyFile);
+ emptyFile.Close();
+ wait_for_operation(5, "f2 to be old enough");
+
+ bbackupd.RunSyncNow();
+ TEST_COMPARE_LOCAL(Compare_Same, client);
+
+ TEARDOWN();
+}
+
+// This caused the issue reported by Brendon Baumgartner and described in my
+// email to the Box Backup list on Mon, 21 Apr 2014 at 18:44:38. If the
+// directory disappears then we used to try to send an empty attributes block
+// to the server, which is illegal.
+bool test_backup_disappearing_directory()
+{
+ SETUP_WITH_BBSTORED();
+
+ class BackupClientDirectoryRecordHooked : public BackupClientDirectoryRecord
+ {
+ public:
+ BackupClientDirectoryRecordHooked(int64_t ObjectID,
+ const std::string &rSubDirName)
+ : BackupClientDirectoryRecord(ObjectID, rSubDirName),
+ mDeletedOnce(false)
+ { }
+ bool mDeletedOnce;
+ bool UpdateItems(SyncParams &rParams, const std::string &rLocalPath,
+ const std::string &rRemotePath,
+ const Location& rBackupLocation,
+ BackupStoreDirectory *pDirOnStore,
+ std::vector<BackupStoreDirectory::Entry *> &rEntriesLeftOver,
+ std::vector<std::string> &rFiles,
+ const std::vector<std::string> &rDirs)
+ {
+ if(!mDeletedOnce)
+ {
+ TEST_THAT(::rmdir("testfiles/TestDir1/dir23") == 0);
+ mDeletedOnce = true;
+ }
+
+ return BackupClientDirectoryRecord::UpdateItems(rParams,
+ rLocalPath, rRemotePath, rBackupLocation,
+ pDirOnStore, rEntriesLeftOver, rFiles, rDirs);
+ }
+ };
+
+ BackupClientContext clientContext
+ (
+ bbackupd, // rLocationResolver
+ context,
+ "localhost",
+ BOX_PORT_BBSTORED_TEST,
+ 0x01234567,
+ false, // ExtendedLogging
+ false, // ExtendedLogFile
+ "", // extendedLogFile
+ bbackupd, // rProgressNotifier
+ false // TcpNice
+ );
+
+ BackupClientInodeToIDMap oldMap, newMap;
+ oldMap.OpenEmpty();
+ newMap.Open("testfiles/test_map.db", false, true);
+ clientContext.SetIDMaps(&oldMap, &newMap);
+
+ BackupClientDirectoryRecord::SyncParams params(
+ bbackupd, // rRunStatusProvider,
+ bbackupd, // rSysadminNotifier,
+ bbackupd, // rProgressNotifier,
+ clientContext,
+ &bbackupd);
+ params.mSyncPeriodEnd = GetCurrentBoxTime();
+
+ BackupProtocolCallable& connection = clientContext.GetConnection();
+
+ BackupClientFileAttributes attr;
+ attr.ReadAttributes("testfiles/TestDir1",
+ false /* put mod times in the attributes, please */);
+ std::auto_ptr<IOStream> attrStream(new MemBlockStream(attr));
+ BackupStoreFilenameClear dirname("Test1");
+ std::auto_ptr<BackupProtocolSuccess>
+ dirCreate(connection.QueryCreateDirectory(
+ BACKUPSTORE_ROOT_DIRECTORY_ID, // containing directory
+ 0, // attrModTime,
+ dirname, // dirname,
+ attrStream));
+
+ // Object ID for later creation
+ int64_t oid = dirCreate->GetObjectID();
+ BackupClientDirectoryRecordHooked record(oid, "Test1");
+
+ TEST_COMPARE(Compare_Different);
+
+ Location fakeLocation;
+ record.SyncDirectory(params,
+ BACKUPSTORE_ROOT_DIRECTORY_ID,
+ "testfiles/TestDir1", // locationPath,
+ "/whee", // remotePath
+ fakeLocation);
+
+ TEST_COMPARE(Compare_Same);
+
+ // Run another backup, check that we haven't got an inconsistent
+ // state that causes a crash.
+ record.SyncDirectory(params,
+ BACKUPSTORE_ROOT_DIRECTORY_ID,
+ "testfiles/TestDir1", // locationPath,
+ "/whee", // remotePath
+ fakeLocation);
+ TEST_COMPARE(Compare_Same);
+
+ // Now recreate it and run another backup, check that we haven't got
+ // an inconsistent state that causes a crash or prevents us from
+ // creating the directory if it appears later.
+ TEST_THAT(::mkdir("testfiles/TestDir1/dir23", 0755) == 0);
+ TEST_COMPARE(Compare_Different);
+
+ record.SyncDirectory(params,
+ BACKUPSTORE_ROOT_DIRECTORY_ID,
+ "testfiles/TestDir1", // locationPath,
+ "/whee", // remotePath
+ fakeLocation);
+ TEST_COMPARE(Compare_Same);
+
+ TEARDOWN();
+}
+
+// TODO FIXME check that directory modtimes are backed up by BackupClientDirectoryRecord.
+
bool test_ssl_keepalives()
{
SETUP_WITH_BBSTORED();
@@ -3917,6 +4072,8 @@ int test(int argc, const char *argv[])
TEST_THAT(test_basics());
TEST_THAT(test_readdirectory_on_nonexistent_dir());
TEST_THAT(test_getobject_on_nonexistent_file());
+ // TEST_THAT(test_replace_zero_byte_file_with_nonzero_byte_file());
+ TEST_THAT(test_backup_disappearing_directory());
TEST_THAT(test_ssl_keepalives());
TEST_THAT(test_backup_pauses_when_store_is_full());
TEST_THAT(test_bbackupd_exclusions());