summaryrefslogtreecommitdiff
path: root/test/backupstorefix/testbackupstorefix.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'test/backupstorefix/testbackupstorefix.cpp')
-rw-r--r--test/backupstorefix/testbackupstorefix.cpp424
1 files changed, 236 insertions, 188 deletions
diff --git a/test/backupstorefix/testbackupstorefix.cpp b/test/backupstorefix/testbackupstorefix.cpp
index bc9911f0..38492bd1 100644
--- a/test/backupstorefix/testbackupstorefix.cpp
+++ b/test/backupstorefix/testbackupstorefix.cpp
@@ -18,9 +18,10 @@
#include "Test.h"
#include "BackupClientCryptoKeys.h"
+#include "BackupProtocol.h"
+#include "BackupStoreAccounts.h"
#include "BackupStoreCheck.h"
#include "BackupStoreConstants.h"
-#include "BackupStoreContext.h"
#include "BackupStoreDirectory.h"
#include "BackupStoreException.h"
#include "BackupStoreFile.h"
@@ -29,6 +30,7 @@
#include "BackupStoreInfo.h"
#include "BufferedWriteStream.h"
#include "FileStream.h"
+#include "IOStreamGetLine.h"
#include "RaidFileController.h"
#include "RaidFileException.h"
#include "RaidFileRead.h"
@@ -36,6 +38,7 @@
#include "RaidFileWrite.h"
#include "ServerControl.h"
#include "StoreStructure.h"
+#include "StoreTestUtils.h"
#include "ZeroStream.h"
#include "MemLeakFindOn.h"
@@ -66,7 +69,7 @@ delete root, copy a file to it instead (equivalent to deleting it too)
*/
-std::string storeRoot("backup/01234567/");
+std::string accountRootDir("backup/01234567/");
int discSetNum = 0;
std::map<std::string, int32_t> nameToID;
@@ -76,33 +79,13 @@ std::map<int32_t, bool> objectIsDir;
::system(BBSTOREACCOUNTS " -c testfiles/bbstored.conf check 01234567"); \
::system(BBSTOREACCOUNTS " -c testfiles/bbstored.conf check 01234567 fix");
-bool check_fix_internal(int expected_num_errors)
-{
- BackupStoreCheck checker(storeRoot, discSetNum,
- 0x01234567, true /* FixErrors */, false /* Quiet */);
- checker.Check();
- if (expected_num_errors == -1)
- {
- TEST_THAT(checker.ErrorsFound());
- return checker.ErrorsFound();
- }
- else
- {
- TEST_EQUAL(expected_num_errors, checker.GetNumErrorsFound());
- return checker.GetNumErrorsFound() == expected_num_errors;
- }
-}
-
-#define RUN_CHECK_INTERNAL(expected_num_errors) \
- TEST_THAT(check_fix_internal(expected_num_errors))
-
// Get ID of an object given a filename
int32_t getID(const char *name)
{
std::map<std::string, int32_t>::iterator i(nameToID.find(std::string(name)));
TEST_THAT(i != nameToID.end());
if(i == nameToID.end()) return -1;
-
+
return i->second;
}
@@ -110,7 +93,7 @@ int32_t getID(const char *name)
std::string getObjectName(int32_t id)
{
std::string fn;
- StoreStructure::MakeObjectFilename(id, storeRoot, discSetNum, fn, false);
+ StoreStructure::MakeObjectFilename(id, accountRootDir, discSetNum, fn, false);
return fn;
}
@@ -166,11 +149,12 @@ typedef struct
int flags;
} dir_en_check;
-void check_dir(BackupStoreDirectory &dir, dir_en_check *ck)
+bool check_dir(BackupStoreDirectory &dir, dir_en_check *ck)
{
BackupStoreDirectory::Iterator i(dir);
BackupStoreDirectory::Entry *en;
-
+ bool ok = true;
+
while((en = i.Next()) != 0)
{
BackupStoreFilenameClear clear(en->GetName());
@@ -185,9 +169,10 @@ void check_dir(BackupStoreDirectory &dir, dir_en_check *ck)
TEST_THAT(en->GetFlags() == ck->flags);
++ck;
}
-
- TEST_THAT(en == 0);
- TEST_THAT(ck->name == -1);
+
+ TEST_EQUAL_OR((void *)NULL, (void *)en, ok = false);
+ TEST_EQUAL_OR(ck->name, -1, ok = false);
+ return ok;
}
typedef struct
@@ -199,7 +184,7 @@ void check_dir_dep(BackupStoreDirectory &dir, checkdepinfoen *ck)
{
BackupStoreDirectory::Iterator i(dir);
BackupStoreDirectory::Entry *en;
-
+
while((en = i.Next()) != 0)
{
TEST_THAT(ck->id != -1);
@@ -215,7 +200,7 @@ void check_dir_dep(BackupStoreDirectory &dir, checkdepinfoen *ck)
"Wrong Older dependency for " << BOX_FORMAT_OBJECTID(ck->id));
++ck;
}
-
+
TEST_THAT(en == 0);
TEST_THAT(ck->id == -1);
}
@@ -229,19 +214,25 @@ void test_dir_fixing()
2 /* id */, 1, BackupStoreDirectory::Entry::Flags_File |
BackupStoreDirectory::Entry::Flags_OldVersion, 2);
e->SetDependsNewer(3);
-
+
TEST_THAT(dir.CheckAndFix() == true);
TEST_THAT(dir.CheckAndFix() == false);
dir_en_check ck[] = {
{-1, 0, 0}
};
-
- check_dir(dir, ck);
+
+ TEST_THAT(check_dir(dir, ck));
}
{
BackupStoreDirectory dir;
+ /*
+ Entry *AddEntry(const BackupStoreFilename &rName,
+ box_time_t ModificationTime, int64_t ObjectID,
+ int64_t SizeInBlocks, int16_t Flags,
+ uint64_t AttributesHash);
+ */
dir.AddEntry(fnames[0], 12, 2 /* id */, 1,
BackupStoreDirectory::Entry::Flags_File, 2);
dir.AddEntry(fnames[1], 12, 2 /* id */, 1,
@@ -251,14 +242,23 @@ void test_dir_fixing()
dir.AddEntry(fnames[0], 12, 5 /* id */, 1,
BackupStoreDirectory::Entry::Flags_File |
BackupStoreDirectory::Entry::Flags_OldVersion, 2);
-
+
+ /*
+ typedef struct
+ {
+ int name;
+ int64_t id;
+ int flags;
+ } dir_en_check;
+ */
+
dir_en_check ck[] = {
{1, 2, BackupStoreDirectory::Entry::Flags_File},
{0, 3, BackupStoreDirectory::Entry::Flags_File | BackupStoreDirectory::Entry::Flags_OldVersion},
{0, 5, BackupStoreDirectory::Entry::Flags_File},
{-1, 0, 0}
};
-
+
TEST_THAT(dir.CheckAndFix() == true);
TEST_THAT(dir.CheckAndFix() == false);
check_dir(dir, ck);
@@ -270,7 +270,7 @@ void test_dir_fixing()
dir.AddEntry(fnames[1], 12, 10 /* id */, 1, BackupStoreDirectory::Entry::Flags_File | BackupStoreDirectory::Entry::Flags_Dir | BackupStoreDirectory::Entry::Flags_OldVersion, 2);
dir.AddEntry(fnames[0], 12, 3 /* id */, 1, BackupStoreDirectory::Entry::Flags_File | BackupStoreDirectory::Entry::Flags_OldVersion, 2);
dir.AddEntry(fnames[0], 12, 5 /* id */, 1, BackupStoreDirectory::Entry::Flags_File | BackupStoreDirectory::Entry::Flags_OldVersion, 2);
-
+
dir_en_check ck[] = {
{0, 2, BackupStoreDirectory::Entry::Flags_File | BackupStoreDirectory::Entry::Flags_OldVersion},
{1, 10, BackupStoreDirectory::Entry::Flags_Dir},
@@ -278,7 +278,7 @@ void test_dir_fixing()
{0, 5, BackupStoreDirectory::Entry::Flags_File},
{-1, 0, 0}
};
-
+
TEST_THAT(dir.CheckAndFix() == true);
TEST_THAT(dir.CheckAndFix() == false);
check_dir(dir, ck);
@@ -309,7 +309,7 @@ void test_dir_fixing()
5 /* id */, 1, BackupStoreDirectory::Entry::Flags_File, 2);
TEST_THAT(e5 != 0);
e5->SetDependsOlder(4);
-
+
// This should all be nice and valid
TEST_THAT(dir.CheckAndFix() == false);
static checkdepinfoen c1[] = {{2, 3, 0}, {3, 4, 2}, {4, 5, 3}, {5, 0, 4}, {-1, 0, 0}};
@@ -337,8 +337,14 @@ void test_dir_fixing()
}
int64_t fake_upload(BackupProtocolLocal& client, const std::string& file_path,
- int64_t diff_from_id)
+ int64_t diff_from_id, int64_t container_id = BACKUPSTORE_ROOT_DIRECTORY_ID,
+ BackupStoreFilename* fn = NULL)
{
+ if(fn == NULL)
+ {
+ fn = &fnames[0];
+ }
+
std::auto_ptr<IOStream> upload;
if(diff_from_id)
{
@@ -348,11 +354,13 @@ int64_t fake_upload(BackupProtocolLocal& client, const std::string& file_path,
std::auto_ptr<IOStream> blockIndexStream(client.ReceiveStream());
upload = BackupStoreFile::EncodeFileDiff(
file_path,
- BACKUPSTORE_ROOT_DIRECTORY_ID, fnames[0],
- diff_from_id, *blockIndexStream,
+ container_id,
+ *fn,
+ diff_from_id,
+ *blockIndexStream,
IOStream::TimeOutInfinite,
NULL, // DiffTimer implementation
- 0 /* not interested in the modification time */,
+ 0 /* not interested in the modification time */,
NULL // isCompletelyDifferent
);
}
@@ -360,25 +368,26 @@ int64_t fake_upload(BackupProtocolLocal& client, const std::string& file_path,
{
upload = BackupStoreFile::EncodeFile(
file_path,
- BACKUPSTORE_ROOT_DIRECTORY_ID, fnames[0],
- NULL,
+ container_id,
+ *fn,
+ NULL,
NULL, // pLogger
NULL // pRunStatusProvider
);
}
- return client.QueryStoreFile(BACKUPSTORE_ROOT_DIRECTORY_ID,
+ return client.QueryStoreFile(container_id,
1, // ModificationTime
2, // AttributesHash
diff_from_id, // DiffFromFileID
- fnames[0], // rFilename
+ *fn, // rFilename
upload)->GetObjectID();
}
void read_bb_dir(int64_t objectId, BackupStoreDirectory& dir)
{
std::string fn;
- StoreStructure::MakeObjectFilename(1 /* root */, storeRoot,
+ StoreStructure::MakeObjectFilename(1 /* root */, accountRootDir,
discSetNum, fn, true /* EnsureDirectoryExists */);
std::auto_ptr<RaidFileRead> file(RaidFileRead::Open(discSetNum,
@@ -397,11 +406,8 @@ void login_client_and_check_empty(BackupProtocolCallable& client)
static checkdepinfoen start_deps[] = {{-1, 0, 0}};
check_dir_dep(dir, start_deps);
- client.QueryVersion(BACKUP_STORE_SERVER_VERSION);
- client.QueryLogin(0x01234567, 0 /* read/write */);
-
read_bb_dir(1 /* root */, dir);
-
+
// Everything should be OK at the moment
TEST_THAT(dir.CheckAndFix() == false);
@@ -420,8 +426,8 @@ void check_root_dir_ok(dir_en_check after_entries[],
{
// Check the store, check that the error is detected and
// repaired, by removing x1 from the directory.
- RUN_CHECK_INTERNAL(0);
-
+ TEST_EQUAL(0, check_account_for_errors());
+
// Read the directory back in, check that it's empty
BackupStoreDirectory dir;
read_bb_dir(1 /* root */, dir);
@@ -435,7 +441,7 @@ void check_and_fix_root_dir(dir_en_check after_entries[],
{
// Check the store, check that the error is detected and
// repaired.
- RUN_CHECK_INTERNAL(-1);
+ TEST_THAT(check_account_for_errors() > 0);
check_root_dir_ok(after_entries, after_deps);
}
@@ -449,7 +455,7 @@ int test(int argc, const char *argv[])
}
// Test the backupstore directory fixing
- // FIXME reenable: test_dir_fixing();
+ test_dir_fixing();
// Initialise the raidfile controller
RaidFileController &rcontroller = RaidFileController::GetController();
@@ -470,20 +476,18 @@ int test(int argc, const char *argv[])
"exist is really deleted");
{
- BackupStoreContext ctx(0x01234567,
- *(HousekeepingInterface *)NULL,
- "test" /* rConnectionDetails */);
- ctx.SetClientHasAccount(storeRoot, discSetNum);
- BackupProtocolLocal client(ctx);
+ BackupProtocolLocal2 client(0x01234567, "test", accountRootDir,
+ discSetNum, false);
login_client_and_check_empty(client);
std::string file_path = "testfiles/TestDir1/cannes/ict/metegoguered/oats";
int x1id = fake_upload(client, file_path, 0);
+ client.QueryFinished();
// Now break the reverse dependency by deleting x1 (the file,
// not the directory entry)
std::string x1FileName;
- StoreStructure::MakeObjectFilename(x1id, storeRoot, discSetNum,
+ StoreStructure::MakeObjectFilename(x1id, accountRootDir, discSetNum,
x1FileName, true /* EnsureDirectoryExists */);
RaidFileWrite deleteX1(discSetNum, x1FileName);
deleteX1.Delete();
@@ -497,11 +501,8 @@ int test(int argc, const char *argv[])
"exist is really deleted");
{
- BackupStoreContext ctx(0x01234567,
- *(HousekeepingInterface *)NULL,
- "test" /* rConnectionDetails */);
- ctx.SetClientHasAccount(storeRoot, discSetNum);
- BackupProtocolLocal client(ctx);
+ BackupProtocolLocal2 client(0x01234567, "test", accountRootDir,
+ discSetNum, false);
login_client_and_check_empty(client);
std::string file_path = "testfiles/TestDir1/cannes/ict/metegoguered/oats";
@@ -514,6 +515,7 @@ int test(int argc, const char *argv[])
fs.Close();
int x1aid = fake_upload(client, file_path, x1id);
+ client.QueryFinished();
// Check that we've ended up with the right preconditions
// for the tests below.
@@ -530,7 +532,7 @@ int test(int argc, const char *argv[])
// Now break the reverse dependency by deleting x1a (the file,
// not the directory entry)
std::string x1aFileName;
- StoreStructure::MakeObjectFilename(x1aid, storeRoot, discSetNum,
+ StoreStructure::MakeObjectFilename(x1aid, accountRootDir, discSetNum,
x1aFileName, true /* EnsureDirectoryExists */);
RaidFileWrite deleteX1a(discSetNum, x1aFileName);
deleteX1a.Delete();
@@ -545,56 +547,95 @@ int test(int argc, const char *argv[])
"raidfile is corrupted doesn't crash");
// Start the bbstored server
- BOX_TRACE(" === Starting bbstored server: " BBSTORED
- " testfiles/bbstored.conf");
- int bbstored_pid = LaunchServer(BBSTORED " testfiles/bbstored.conf",
- "testfiles/bbstored.pid");
- TEST_THAT(bbstored_pid > 0);
- if (bbstored_pid <= 0) return 1;
-
- ::sleep(1);
- TEST_THAT(ServerIsAlive(bbstored_pid));
-
- std::string cmd = BBACKUPD " " + bbackupd_args +
- " testfiles/bbackupd.conf";
- int bbackupd_pid = LaunchServer(cmd, "testfiles/bbackupd.pid");
- TEST_THAT(bbackupd_pid > 0);
- if (bbackupd_pid <= 0) return 1;
-
- ::safe_sleep(1);
- TEST_THAT(ServerIsAlive(bbackupd_pid));
-
- // 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
+ TEST_THAT_OR(StartServer(), return 1);
+
+ // Instead of starting a client, read the file listing file created by
+ // testbackupstorefix.pl and upload them in the correct order, so that the object
+ // IDs will not vary depending on the order in which readdir() returns entries.
+ {
+ FileStream listing("testfiles/file-listing.txt", O_RDONLY);
+ IOStreamGetLine getline(listing);
+ std::map<std::string, int64_t> dirname_to_id;
+ std::string line;
+ BackupProtocolLocal2 client(0x01234567, "test", accountRootDir,
+ discSetNum, false);
+
+ for(getline.GetLine(line, true); line != ""; getline.GetLine(line, true))
+ {
+ std::string full_path = line;
+ ASSERT(StartsWith("testfiles/TestDir1/", full_path));
+
+ bool is_dir = (full_path[full_path.size() - 1] == '/');
+ if(is_dir)
+ {
+ full_path = full_path.substr(0, full_path.size() - 1);
+ }
+
+ std::string::size_type last_slash = full_path.rfind('/');
+ int64_t container_id;
+ std::string filename;
+
+ if(full_path == "testfiles/TestDir1")
+ {
+ container_id = BACKUPSTORE_ROOT_DIRECTORY_ID;
+ filename = "Test1";
+ }
+ else
+ {
+ std::string containing_dir =
+ full_path.substr(0, last_slash);
+ container_id = dirname_to_id[containing_dir];
+ filename = full_path.substr(last_slash + 1);
+ }
+
+ BackupStoreFilenameClear fn(filename);
+ if(is_dir)
+ {
+ std::auto_ptr<IOStream> attr_stream(
+ new CollectInBufferStream);
+ ((CollectInBufferStream &)
+ *attr_stream).SetForReading();
+
+ dirname_to_id[full_path] = client.QueryCreateDirectory(
+ container_id, 0, // AttributesModTime
+ fn, attr_stream)->GetObjectID();
+ }
+ else
+ {
+ fake_upload(client, line, 0, container_id, &fn);
+ }
+ }
+ }
+
+ // Check that we're starting off with the right numbers of files and blocks.
+ // Otherwise the test that check the counts after breaking things will fail
+ // because the numbers won't match.
+ TEST_EQUAL(0, check_account_for_errors());
+ {
+ std::auto_ptr<BackupProtocolAccountUsage2> usage =
+ BackupProtocolLocal2(0x01234567, "test",
+ "backup/01234567/", 0,
+ false).QueryGetAccountUsage2();
+ TEST_EQUAL(usage->GetNumCurrentFiles(), 114);
+ TEST_EQUAL(usage->GetNumDirectories(), 28);
+ TEST_EQUAL(usage->GetBlocksUsed(), 284);
+ TEST_EQUAL(usage->GetBlocksInCurrentFiles(), 228);
+ TEST_EQUAL(usage->GetBlocksInDirectories(), 56);
+ }
BOX_INFO(" === Add a reference to a file that doesn't exist, check "
"that it's removed");
{
BackupStoreDirectory dir;
read_bb_dir(1 /* root */, dir);
-
+
dir.AddEntry(fnames[0], 12, 0x1234567890123456LL /* id */, 1,
BackupStoreDirectory::Entry::Flags_File, 2);
-
+
std::string fn;
- StoreStructure::MakeObjectFilename(1 /* root */, storeRoot,
+ StoreStructure::MakeObjectFilename(1 /* root */, accountRootDir,
discSetNum, fn, true /* EnsureDirectoryExists */);
- std::auto_ptr<RaidFileRead> file(RaidFileRead::Open(discSetNum,
- fn));
RaidFileWrite d(discSetNum, fn);
d.Open(true /* allow overwrite */);
dir.WriteToStream(d);
@@ -603,27 +644,21 @@ int test(int argc, const char *argv[])
read_bb_dir(1 /* root */, dir);
TEST_THAT(dir.FindEntryByID(0x1234567890123456LL) != 0);
- // Check it
- BackupStoreCheck checker(storeRoot, discSetNum,
- 0x01234567, true /* FixErrors */, false /* Quiet */);
- checker.Check();
-
// Should just be greater than 1 really, we don't know quite
// how good the checker is (or will become) at spotting errors!
// But this will help us catch changes in checker behaviour,
// so it's not a bad thing to test.
- TEST_EQUAL(2, checker.GetNumErrorsFound());
+ TEST_EQUAL(2, check_account_for_errors());
- file = RaidFileRead::Open(discSetNum, fn);
+ std::auto_ptr<RaidFileRead> file(RaidFileRead::Open(discSetNum,
+ fn));
dir.ReadFromStream(*file, IOStream::TimeOutInfinite);
TEST_THAT(dir.FindEntryByID(0x1234567890123456LL) == 0);
}
- if (failures > 0) return 1;
-
// Generate a list of all the object IDs
TEST_THAT_ABORTONFAIL(::system(BBACKUPQUERY " -Wwarning "
- "-c testfiles/bbackupd.conf \"list -r\" quit "
+ "-c testfiles/bbackupd.conf \"list -R\" quit "
"> testfiles/initial-listing.txt") == 0);
// And load it in
@@ -647,17 +682,17 @@ int test(int argc, const char *argv[])
::fclose(f);
}
- // ------------------------------------------------------------------------------------------------
+ // ------------------------------------------------------------------------------------------------
BOX_INFO(" === Delete store info, add random file");
{
// Delete store info
- RaidFileWrite del(discSetNum, storeRoot + "info");
+ RaidFileWrite del(discSetNum, accountRootDir + "info");
del.Delete();
}
{
// Add a spurious file
RaidFileWrite random(discSetNum,
- storeRoot + "randomfile");
+ accountRootDir + "randomfile");
random.Open();
random.Write("test", 4);
random.Commit(true);
@@ -672,13 +707,28 @@ int test(int argc, const char *argv[])
// Check the random file doesn't exist
{
TEST_THAT(!RaidFileRead::FileExists(discSetNum,
- storeRoot + "01/randomfile"));
+ accountRootDir + "01/randomfile"));
}
- // ------------------------------------------------------------------------------------------------
+ // ------------------------------------------------------------------------------------------------
BOX_INFO(" === Delete an entry for an object from dir, change that "
"object to be a patch, check it's deleted");
{
+ // Temporarily stop the server, so it doesn't repair the refcount error. Except
+ // on win32, where hard-killing the server can leave a lockfile in place,
+ // breaking the rest of the test.
+#ifdef WIN32
+ // Wait for the server to finish housekeeping first, by getting a lock on
+ // the account.
+ std::auto_ptr<BackupStoreAccountDatabase> apAccounts(
+ BackupStoreAccountDatabase::Read("testfiles/accounts.txt"));
+ BackupStoreAccounts acc(*apAccounts);
+ NamedLock lock;
+ acc.LockAccount(0x1234567, lock);
+#else
+ TEST_THAT(StopServer());
+#endif
+
// Open dir and find entry
int64_t delID = getID("Test1/cannes/ict/metegoguered/oats");
{
@@ -688,7 +738,7 @@ int test(int argc, const char *argv[])
dir.DeleteEntry(delID);
SaveDirectory("Test1/cannes/ict/metegoguered", dir);
}
-
+
// Adjust that entry
//
// IMPORTANT NOTE: There's a special hack in testbackupstorefix.pl to make sure that
@@ -727,41 +777,36 @@ int test(int argc, const char *argv[])
f.Commit(true /* write now! */);
}
-#ifndef BOX_RELEASE_BUILD
- // Delete two of the three raidfiles and their parent
- // directories. This used to crash bbstoreaccounts check.
- // We can only do this, without destroying the entire store,
- // in debug mode, where the store has a far deeper
- // structure.
- // This will destroy or damage objects 18-1b and 58-5b,
- // some repairably.
- #define RUN(x) TEST_THAT(system(x) == 0);
- RUN("mv testfiles/0_0/backup/01234567/02/01/o00.rf "
- "testfiles/0_0/backup/01234567/02/01/o00.rfw"); // 0x18
- RUN("mv testfiles/0_1/backup/01234567/02/01/o01.rf "
- "testfiles/0_1/backup/01234567/02/01/o01.rfw"); // 0x19
- //RUN("mv testfiles/0_2/backup/01234567/02/01/o02.rf "
- // "testfiles/0_0/backup/01234567/02/01/o02.rfw"); // 0x1a
- RUN("mv testfiles/0_0/backup/01234567/02/01/o03.rf "
- "testfiles/0_0/backup/01234567/02/01/o03.rfw"); // 0x1b
- RUN("mv testfiles/0_0/backup/01234567/02/01/01/o00.rf "
- "testfiles/0_0/backup/01234567/02/01/01/o00.rfw"); // 0x58
- RUN("mv testfiles/0_1/backup/01234567/02/01/01/o01.rf "
- "testfiles/0_1/backup/01234567/02/01/01/o01.rfw"); // 0x59
- //RUN("mv testfiles/0_2/backup/01234567/02/01/01/o02.rf "
- // "testfiles/0_0/backup/01234567/02/01/01/o02.rfw"); // 0x5a
- RUN("mv testfiles/0_0/backup/01234567/02/01/01/o03.rf "
- "testfiles/0_0/backup/01234567/02/01/01/o03.rfw"); // 0x5b
- // RUN("rm -r testfiles/0_1/backup/01234567/02/01");
- RUN("rm -r testfiles/0_2/backup/01234567/02/01");
- #undef RUN
-#endif // BOX_RELEASE_BUILD
-
// Fix it
- RUN_CHECK_INTERNAL(3);
+ // ERROR: Object 0x44 is unattached.
+ // ERROR: BlocksUsed changed from 284 to 282
+ // ERROR: BlocksInCurrentFiles changed from 228 to 226
+ // ERROR: NumCurrentFiles changed from 114 to 113
+ // WARNING: Reference count of object 0x44 changed from 1 to 0
+#ifdef WIN32
+ lock.ReleaseLock();
+#endif
+ TEST_EQUAL(5, check_account_for_errors());
+ {
+ std::auto_ptr<BackupProtocolAccountUsage2> usage =
+ BackupProtocolLocal2(0x01234567, "test",
+ "backup/01234567/", 0,
+ false).QueryGetAccountUsage2();
+ TEST_EQUAL(usage->GetNumCurrentFiles(), 113);
+ TEST_EQUAL(usage->GetNumDirectories(), 28);
+ TEST_EQUAL(usage->GetBlocksUsed(), 282);
+ TEST_EQUAL(usage->GetBlocksInCurrentFiles(), 226);
+ TEST_EQUAL(usage->GetBlocksInDirectories(), 56);
+ }
+
+ // Start the server again, so testbackupstorefix.pl can run bbackupquery which
+ // connects to it. Except on win32, where we didn't stop it earlier.
+#ifndef WIN32
+ TEST_THAT(StartServer());
+#endif
// Check
- TEST_THAT(::system(PERL_EXECUTABLE
+ TEST_THAT(::system(PERL_EXECUTABLE
" testfiles/testbackupstorefix.pl check 1")
== 0);
@@ -773,25 +818,9 @@ int test(int argc, const char *argv[])
// file, so checking for AsRaid excludes this possibility.
RaidFileController &rcontroller(RaidFileController::GetController());
RaidFileDiscSet rdiscSet(rcontroller.GetDiscSet(discSetNum));
- TEST_EQUAL(RaidFileUtil::AsRaid, RaidFileUtil::RaidFileExists(
- rdiscSet, "backup/01234567/02/01/o00"));
- TEST_EQUAL(RaidFileUtil::AsRaid, RaidFileUtil::RaidFileExists(
- rdiscSet, "backup/01234567/02/01/o01"));
- TEST_EQUAL(RaidFileUtil::AsRaid, RaidFileUtil::RaidFileExists(
- rdiscSet, "backup/01234567/02/01/o02"));
- TEST_EQUAL(RaidFileUtil::AsRaid, RaidFileUtil::RaidFileExists(
- rdiscSet, "backup/01234567/02/01/o03"));
- TEST_EQUAL(RaidFileUtil::AsRaid, RaidFileUtil::RaidFileExists(
- rdiscSet, "backup/01234567/02/01/01/o00"));
- TEST_EQUAL(RaidFileUtil::AsRaid, RaidFileUtil::RaidFileExists(
- rdiscSet, "backup/01234567/02/01/01/o01"));
- TEST_EQUAL(RaidFileUtil::AsRaid, RaidFileUtil::RaidFileExists(
- rdiscSet, "backup/01234567/02/01/01/o02"));
- TEST_EQUAL(RaidFileUtil::AsRaid, RaidFileUtil::RaidFileExists(
- rdiscSet, "backup/01234567/02/01/01/o03"));
}
-
- // ------------------------------------------------------------------------------------------------
+
+ // ------------------------------------------------------------------------------------------------
BOX_INFO(" === Delete directory, change container ID of another, "
"duplicate entry in dir, spurious file size, delete file");
{
@@ -825,16 +854,19 @@ int test(int argc, const char *argv[])
}
SaveDirectory("Test1/cannes/ict/peep", dir);
}
- // Delete a directory
+
+ // Delete a directory. The checker should be able to reconstruct it using the
+ // ContainerID of the contained files.
DeleteObject("Test1/pass/cacted/ming");
+
// Delete a file
DeleteObject("Test1/cannes/ict/scely");
- // We don't know quite how good the checker is (or will become) at
- // spotting errors! But asserting an exact number will help us catch
+ // We don't know quite how good the checker is (or will become) at
+ // spotting errors! But asserting an exact number will help us catch
// changes in checker behaviour, so it's not a bad thing to test.
- // The 11 errors are:
+ // The 12 errors that we currently expect are:
// ERROR: Directory ID 0xb references object 0x3e which does not exist.
// ERROR: Removing directory entry 0x3e from directory 0xb
// ERROR: Directory ID 0xc had invalid entries, fixed
@@ -846,11 +878,23 @@ int test(int argc, const char *argv[])
// ERROR: BlocksInCurrentFiles changed from 226 to 220
// ERROR: BlocksInDirectories changed from 56 to 54
// ERROR: NumFiles changed from 113 to 110
+ // WARNING: Reference count of object 0x3e changed from 1 to 0
+
+ TEST_EQUAL(12, check_account_for_errors());
- RUN_CHECK_INTERNAL(11);
+ {
+ std::auto_ptr<BackupProtocolAccountUsage2> usage =
+ BackupProtocolLocal2(0x01234567, "test",
+ "backup/01234567/", 0,
+ false).QueryGetAccountUsage2();
+ TEST_EQUAL(usage->GetBlocksUsed(), 278);
+ TEST_EQUAL(usage->GetBlocksInCurrentFiles(), 220);
+ TEST_EQUAL(usage->GetBlocksInDirectories(), 54);
+ TEST_EQUAL(usage->GetNumCurrentFiles(), 110);
+ }
// Check everything is as it should be
- TEST_THAT(::system(PERL_EXECUTABLE
+ TEST_THAT(::system(PERL_EXECUTABLE
" testfiles/testbackupstorefix.pl check 2") == 0);
{
BackupStoreDirectory dir;
@@ -881,7 +925,7 @@ int test(int argc, const char *argv[])
}
}
- // ------------------------------------------------------------------------------------------------
+ // ------------------------------------------------------------------------------------------------
BOX_INFO(" === Modify the obj ID of dir, delete dir with no members, "
"add extra reference to a file");
// Set bad object ID
@@ -905,28 +949,32 @@ int test(int argc, const char *argv[])
dir2.AddEntry(*en);
SaveDirectory("Test1/divel/torsines/cruishery", dir2);
}
+
// Fix it
RUN_CHECK
+
// Check everything is as it should be
- TEST_THAT(::system(PERL_EXECUTABLE
+ TEST_THAT(::system(PERL_EXECUTABLE
" testfiles/testbackupstorefix.pl check 3") == 0);
{
BackupStoreDirectory dir;
LoadDirectory("Test1/foreomizes/stemptinevidate/ict", dir);
TEST_THAT(dir.GetObjectID() == getID("Test1/foreomizes/stemptinevidate/ict"));
}
-
- // ------------------------------------------------------------------------------------------------
+
+ // ------------------------------------------------------------------------------------------------
BOX_INFO(" === Orphan files and dirs without being recoverable");
- DeleteObject("Test1/dir1");
- DeleteObject("Test1/dir1/dir2");
+ DeleteObject("Test1/dir1");
+ DeleteObject("Test1/dir1/dir2");
+
// Fix it
RUN_CHECK
+
// Check everything is where it is predicted to be
- TEST_THAT(::system(PERL_EXECUTABLE
+ TEST_THAT(::system(PERL_EXECUTABLE
" testfiles/testbackupstorefix.pl check 4") == 0);
- // ------------------------------------------------------------------------------------------------
+ // ------------------------------------------------------------------------------------------------
BOX_INFO(" === Corrupt file and dir");
// File
CorruptObject("Test1/foreomizes/stemptinevidate/algoughtnerge",
@@ -940,7 +988,7 @@ int test(int argc, const char *argv[])
TEST_THAT(::system(PERL_EXECUTABLE
" testfiles/testbackupstorefix.pl check 5") == 0);
- // ------------------------------------------------------------------------------------------------
+ // ------------------------------------------------------------------------------------------------
BOX_INFO(" === Overwrite root with a file");
{
std::auto_ptr<RaidFileRead> r(RaidFileRead::Open(discSetNum, getObjectName(getID("Test1/pass/shuted/brightinats/milamptimaskates"))));