diff options
Diffstat (limited to 'test/backupstorefix/testbackupstorefix.cpp')
-rw-r--r-- | test/backupstorefix/testbackupstorefix.cpp | 424 |
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")))); |