From 99f8ce096bc5569adbfea1911dbcda24c28d8d8b Mon Sep 17 00:00:00 2001 From: Ben Summers Date: Fri, 14 Oct 2005 08:50:54 +0000 Subject: Box Backup 0.09 with a few tweeks --- test/backupstore/testbackupstore.cpp | 1902 +++++++++++++++++++++++ test/backupstore/testextra | 4 + test/backupstore/testfiles/accounts.txt | 0 test/backupstore/testfiles/bbackupd.keys | Bin 0 -> 1024 bytes test/backupstore/testfiles/bbstored.conf | 17 + test/backupstore/testfiles/bbstored_multi.conf | 16 + test/backupstore/testfiles/clientCerts.pem | 11 + test/backupstore/testfiles/clientPrivKey.pem | 15 + test/backupstore/testfiles/clientReq.pem | 10 + test/backupstore/testfiles/clientTrustedCAs.pem | 11 + test/backupstore/testfiles/query.conf | 34 + test/backupstore/testfiles/raidfile.conf | 10 + test/backupstore/testfiles/root.pem | 26 + test/backupstore/testfiles/root.srl | 1 + test/backupstore/testfiles/rootcert.pem | 11 + test/backupstore/testfiles/rootkey.pem | 15 + test/backupstore/testfiles/rootreq.pem | 10 + test/backupstore/testfiles/serverCerts.pem | 11 + test/backupstore/testfiles/serverPrivKey.pem | 15 + test/backupstore/testfiles/serverReq.pem | 10 + test/backupstore/testfiles/serverTrustedCAs.pem | 11 + 21 files changed, 2140 insertions(+) create mode 100755 test/backupstore/testbackupstore.cpp create mode 100755 test/backupstore/testextra create mode 100755 test/backupstore/testfiles/accounts.txt create mode 100644 test/backupstore/testfiles/bbackupd.keys create mode 100755 test/backupstore/testfiles/bbstored.conf create mode 100755 test/backupstore/testfiles/bbstored_multi.conf create mode 100644 test/backupstore/testfiles/clientCerts.pem create mode 100644 test/backupstore/testfiles/clientPrivKey.pem create mode 100644 test/backupstore/testfiles/clientReq.pem create mode 100644 test/backupstore/testfiles/clientTrustedCAs.pem create mode 100755 test/backupstore/testfiles/query.conf create mode 100755 test/backupstore/testfiles/raidfile.conf create mode 100644 test/backupstore/testfiles/root.pem create mode 100644 test/backupstore/testfiles/root.srl create mode 100644 test/backupstore/testfiles/rootcert.pem create mode 100644 test/backupstore/testfiles/rootkey.pem create mode 100644 test/backupstore/testfiles/rootreq.pem create mode 100644 test/backupstore/testfiles/serverCerts.pem create mode 100644 test/backupstore/testfiles/serverPrivKey.pem create mode 100644 test/backupstore/testfiles/serverReq.pem create mode 100644 test/backupstore/testfiles/serverTrustedCAs.pem (limited to 'test/backupstore') diff --git a/test/backupstore/testbackupstore.cpp b/test/backupstore/testbackupstore.cpp new file mode 100755 index 00000000..3757bc60 --- /dev/null +++ b/test/backupstore/testbackupstore.cpp @@ -0,0 +1,1902 @@ +// -------------------------------------------------------------------------- +// +// File +// Name: testbackupstore.cpp +// Purpose: Test backup store server +// Created: 2003/08/20 +// +// -------------------------------------------------------------------------- + +#include "Box.h" + +#include +#include + +#include "Test.h" +#include "autogen_BackupProtocolClient.h" +#include "SSLLib.h" +#include "TLSContext.h" +#include "SocketStreamTLS.h" +#include "BoxPortsAndFiles.h" +#include "BackupStoreConstants.h" +#include "Socket.h" +#include "BackupStoreFilenameClear.h" +#include "CollectInBufferStream.h" +#include "BackupStoreDirectory.h" +#include "BackupStoreFile.h" +#include "FileStream.h" +#include "RaidFileController.h" +#include "RaidFileWrite.h" +#include "BackupStoreInfo.h" +#include "BackupStoreException.h" +#include "RaidFileException.h" +#include "MemBlockStream.h" +#include "BackupClientFileAttributes.h" +#include "BackupClientCryptoKeys.h" + +#include "MemLeakFindOn.h" + + +#define ENCFILE_SIZE 2765 + +typedef struct +{ + BackupStoreFilenameClear fn; + box_time_t mod; + int64_t id; + int64_t size; + int16_t flags; + box_time_t attrmod; +} dirtest; + +static dirtest ens[] = +{ + {BackupStoreFilenameClear(), 324324, 3432, 324, BackupStoreDirectory::Entry::Flags_File, 458763243422LL}, + {BackupStoreFilenameClear(), 3432, 32443245645LL, 78, BackupStoreDirectory::Entry::Flags_Dir, 3248972347LL}, + {BackupStoreFilenameClear(), 544435, 234234, 23324, BackupStoreDirectory::Entry::Flags_File | BackupStoreDirectory::Entry::Flags_Deleted, 2348974782LL}, + {BackupStoreFilenameClear(), 234, 235436, 6523, BackupStoreDirectory::Entry::Flags_File, 32458923175634LL}, + {BackupStoreFilenameClear(), 0x3242343532144LL, 8978979789LL, 21345, BackupStoreDirectory::Entry::Flags_File, 329483243432LL}, + {BackupStoreFilenameClear(), 324265765734LL, 12312312321LL, 324987324329874LL, BackupStoreDirectory::Entry::Flags_File | BackupStoreDirectory::Entry::Flags_Deleted, 32489747234LL}, + {BackupStoreFilenameClear(), 3452134, 7868578768LL, 324243, BackupStoreDirectory::Entry::Flags_Dir, 34786457432LL}, + {BackupStoreFilenameClear(), 43543543, 324234, 21432, BackupStoreDirectory::Entry::Flags_Dir | BackupStoreDirectory::Entry::Flags_Deleted, 3489723478327LL}, + {BackupStoreFilenameClear(), 325654765874324LL, 4353543, 1, BackupStoreDirectory::Entry::Flags_File | BackupStoreDirectory::Entry::Flags_OldVersion, 32489734789237LL}, + {BackupStoreFilenameClear(), 32144325, 436547657, 9, BackupStoreDirectory::Entry::Flags_File | BackupStoreDirectory::Entry::Flags_OldVersion, 234897347234LL} +}; +static const char *ens_filenames[] = {"obj1ertewt", "obj2", "obj3", "obj4dfedfg43", "obj5", "obj6dfgs", "obj7", "obj8xcvbcx", "obj9", "obj10fgjhfg"}; +#define DIR_NUM 10 +#define DIR_DIRS 3 +#define DIR_FILES 7 +#define DIR_OLD 2 +#define DIR_DELETED 3 + +typedef struct +{ + char *fnextra; + BackupStoreFilenameClear name; + int seed; + int size; + box_time_t mod_time; + int64_t allocated_objid; + bool should_be_old_version; + bool delete_file; +} uploadtest; + +#define TEST_FILE_FOR_PATCHING "testfiles/test2" +// a few bytes will be inserted at this point: +#define TEST_FILE_FOR_PATCHING_PATCH_AT ((64*1024)-128) +#define TEST_FILE_FOR_PATCHING_SIZE ((128*1024)+2564) +#define UPLOAD_PATCH_EN 2 + +uploadtest uploads[] = +{ + {"0", BackupStoreFilenameClear(), 324, 455, 0, 0, false, false}, + {"1", BackupStoreFilenameClear(), 3232432, 2674, 0, 0, true, false}, // old ver + {"2", BackupStoreFilenameClear(), 234, TEST_FILE_FOR_PATCHING_SIZE, 0, 0, false, false}, + {"3", BackupStoreFilenameClear(), 324324, 6763, 0, 0, false, false}, + {"4", BackupStoreFilenameClear(), 23456, 124, 0, 0, true, false}, // old ver + {"5", BackupStoreFilenameClear(), 675745, 1, 0, 0, false, false}, // will upload new attrs for this one! + {"6", BackupStoreFilenameClear(), 345213, 0, 0, 0, false, false}, + {"7", BackupStoreFilenameClear(), 12313, 3246, 0, 0, true, true}, // old ver, will get deleted + {"8", BackupStoreFilenameClear(), 457, 3434, 0, 0, false, false}, // overwrites + {"9", BackupStoreFilenameClear(), 12315, 446, 0, 0, false, false}, + {"a", BackupStoreFilenameClear(), 3476, 2466, 0, 0, false, false}, + {"b", BackupStoreFilenameClear(), 124334, 4562, 0, 0, false, false}, + {"c", BackupStoreFilenameClear(), 45778, 234, 0, 0, false, false}, // overwrites + {"d", BackupStoreFilenameClear(), 2423425, 435, 0, 0, false, true} // overwrites, will be deleted +}; +static const char *uploads_filenames[] = {"49587fds", "cvhjhj324", "sdfcscs324", "dsfdsvsdc3214", "XXsfdsdf2342", "dsfdsc232", + "sfdsdce2345", "YYstfbdtrdf76", "cvhjhj324", "fbfd098.ycy", "dfs98732hj", "svd987kjsad", "XXsfdsdf2342", "YYstfbdtrdf76"}; +#define UPLOAD_NUM 14 +#define UPLOAD_LATEST_FILES 12 +// file we'll upload some new attributes for +#define UPLOAD_ATTRS_EN 5 +#define UPLOAD_DELETE_EN 13 +// file which will be moved (as well as it's old version) +#define UPLOAD_FILE_TO_MOVE 8 + + +// Nice random data for testing written files +class R250 { +public: + // Set up internal state table with 32-bit random numbers. + // The bizarre bit-twiddling is because rand() returns 16 bits of which + // the bottom bit is always zero! Hence, I use only some of the bits. + // You might want to do something better than this.... + + R250(int seed) : posn1(0), posn2(103) + { + // populate the state and incr tables + srand(seed); + + for (int i = 0; i != stateLen; ++i) { + state[i] = ((rand() >> 2) << 19) ^ ((rand() >> 2) << 11) ^ (rand() >> 2); + incrTable[i] = i == stateLen - 1 ? 0 : i + 1; + } + + // stir up the numbers to ensure they're random + + for (int j = 0; j != stateLen * 4; ++j) + (void) next(); + } + + // Returns the next random number. Xor together two elements separated + // by 103 mod 250, replacing the first element with the result. Then + // increment the two indices mod 250. + inline int next() + { + int ret = (state[posn1] ^= state[posn2]); // xor and replace element + + posn1 = incrTable[posn1]; // increment indices using lookup table + posn2 = incrTable[posn2]; + + return ret; + } +private: + enum { stateLen = 250 }; // length of the state table + int state[stateLen]; // holds the random number state + int incrTable[stateLen]; // lookup table: maps i to (i+1) % stateLen + int posn1, posn2; // indices into the state table +}; + + +int SkipEntries(int e, int16_t FlagsMustBeSet, int16_t FlagsNotToBeSet) +{ + if(e >= DIR_NUM) return e; + + bool skip = false; + do + { + skip = false; + + if(FlagsMustBeSet != BackupStoreDirectory::Entry::Flags_INCLUDE_EVERYTHING) + { + if((ens[e].flags & FlagsMustBeSet) != FlagsMustBeSet) + { + skip = true; + } + } + if((ens[e].flags & FlagsNotToBeSet) != 0) + { + skip = true; + } + + if(skip) + { + ++e; + } + } while(skip && e < DIR_NUM); + + return e; +} + +void CheckEntries(BackupStoreDirectory &rDir, int16_t FlagsMustBeSet, int16_t FlagsNotToBeSet) +{ + int e = 0; + + BackupStoreDirectory::Iterator i(rDir); + BackupStoreDirectory::Entry *en = 0; + while((en = i.Next()) != 0) + { + TEST_THAT(e < DIR_NUM); + + // Skip to entry in the ens array which matches + e = SkipEntries(e, FlagsMustBeSet, FlagsNotToBeSet); + + // Does it match? + TEST_THAT(en->GetName() == ens[e].fn && en->GetModificationTime() == ens[e].mod && en->GetObjectID() == ens[e].id && en->GetFlags() == ens[e].flags && en->GetSizeInBlocks() == ens[e].size); + + // next + ++e; + } + + // Got them all? + TEST_THAT(en == 0); + TEST_THAT(DIR_NUM == SkipEntries(e, FlagsMustBeSet, FlagsNotToBeSet)); +} + +int test1(int argc, const char *argv[]) +{ + // Initialise the raid file controller + RaidFileController &rcontroller = RaidFileController::GetController(); + rcontroller.Initialise("testfiles/raidfile.conf"); + + // test some basics -- encoding and decoding filenames + { + // Make some filenames in various ways + BackupStoreFilenameClear fn1; + fn1.SetClearFilename(std::string("filenameXYZ")); + BackupStoreFilenameClear fn2(std::string("filenameXYZ")); + BackupStoreFilenameClear fn3(fn1); + TEST_THAT(fn1 == fn2); + TEST_THAT(fn1 == fn3); + + // Check that it's been encrypted + TEST_THAT(fn2.find("name") == fn2.npos); + + // Bung it in a stream, get it out in a Clear filename + { + CollectInBufferStream stream; + fn1.WriteToStream(stream); + stream.SetForReading(); + BackupStoreFilenameClear fn4; + fn4.ReadFromStream(stream, IOStream::TimeOutInfinite); + TEST_THAT(fn4.GetClearFilename() == "filenameXYZ"); + TEST_THAT(fn4 == fn1); + } + // Bung it in a stream, get it out in a server non-Clear filename (two of them into the same var) + { + BackupStoreFilenameClear fno("pinglet dksfnsf jksjdf "); + CollectInBufferStream stream; + fn1.WriteToStream(stream); + fno.WriteToStream(stream); + stream.SetForReading(); + BackupStoreFilename fn5; + fn5.ReadFromStream(stream, IOStream::TimeOutInfinite); + TEST_THAT(fn5 == fn1); + fn5.ReadFromStream(stream, IOStream::TimeOutInfinite); + TEST_THAT(fn5 == fno); + } + // Same again with clear strings + { + BackupStoreFilenameClear fno("pinglet dksfnsf jksjdf "); + CollectInBufferStream stream; + fn1.WriteToStream(stream); + fno.WriteToStream(stream); + stream.SetForReading(); + BackupStoreFilenameClear fn5; + fn5.ReadFromStream(stream, IOStream::TimeOutInfinite); + TEST_THAT(fn5.GetClearFilename() == "filenameXYZ"); + fn5.ReadFromStream(stream, IOStream::TimeOutInfinite); + TEST_THAT(fn5.GetClearFilename() == "pinglet dksfnsf jksjdf "); + } + // Test a very big filename + { + const char *fnr = "01234567890123456789012345678901234567890123456789" + "01234567890123456789012345678901234567890123456789" + "01234567890123456789012345678901234567890123456789" + "01234567890123456789012345678901234567890123456789" + "01234567890123456789012345678901234567890123456789" + "01234567890123456789012345678901234567890123456789" + "01234567890123456789012345678901234567890123456789" + "01234567890123456789012345678901234567890123456789"; + BackupStoreFilenameClear fnLong(fnr); + CollectInBufferStream stream; + fnLong.WriteToStream(stream); + stream.SetForReading(); + BackupStoreFilenameClear fn9; + fn9.ReadFromStream(stream, IOStream::TimeOutInfinite); + TEST_THAT(fn9.GetClearFilename() == fnr); + TEST_THAT(fn9 == fnLong); + } + // Test a filename which went wrong once + { + BackupStoreFilenameClear dodgy("content-negotiation.html"); + } + } + return 0; +} + +int test2(int argc, const char *argv[]) +{ + { + // Now play with directories + + // Fill in... + BackupStoreDirectory dir1(12, 98); + for(int e = 0; e < DIR_NUM; ++e) + { + dir1.AddEntry(ens[e].fn, ens[e].mod, ens[e].id, ens[e].size, ens[e].flags, ens[e].attrmod); + } + // Got the right number + TEST_THAT(dir1.GetNumberOfEntries() == DIR_NUM); + + // Stick it into a stream and get it out again + { + CollectInBufferStream stream; + dir1.WriteToStream(stream); + stream.SetForReading(); + BackupStoreDirectory dir2; + dir2.ReadFromStream(stream, IOStream::TimeOutInfinite); + TEST_THAT(dir2.GetNumberOfEntries() == DIR_NUM); + TEST_THAT(dir2.GetObjectID() == 12); + TEST_THAT(dir2.GetContainerID() == 98); + CheckEntries(dir2, BackupStoreDirectory::Entry::Flags_INCLUDE_EVERYTHING, BackupStoreDirectory::Entry::Flags_EXCLUDE_NOTHING); + } + + // Then do selective writes and reads + { + CollectInBufferStream stream; + dir1.WriteToStream(stream, BackupStoreDirectory::Entry::Flags_File); + stream.SetForReading(); + BackupStoreDirectory dir2; + dir2.ReadFromStream(stream, IOStream::TimeOutInfinite); + TEST_THAT(dir2.GetNumberOfEntries() == DIR_FILES); + CheckEntries(dir2, BackupStoreDirectory::Entry::Flags_File, BackupStoreDirectory::Entry::Flags_EXCLUDE_NOTHING); + } + { + CollectInBufferStream stream; + dir1.WriteToStream(stream, BackupStoreDirectory::Entry::Flags_INCLUDE_EVERYTHING, BackupStoreDirectory::Entry::Flags_File); + stream.SetForReading(); + BackupStoreDirectory dir2; + dir2.ReadFromStream(stream, IOStream::TimeOutInfinite); + TEST_THAT(dir2.GetNumberOfEntries() == DIR_DIRS); + CheckEntries(dir2, BackupStoreDirectory::Entry::Flags_Dir, BackupStoreDirectory::Entry::Flags_EXCLUDE_NOTHING); + } + { + CollectInBufferStream stream; + dir1.WriteToStream(stream, BackupStoreDirectory::Entry::Flags_File, BackupStoreDirectory::Entry::Flags_OldVersion); + stream.SetForReading(); + BackupStoreDirectory dir2; + dir2.ReadFromStream(stream, IOStream::TimeOutInfinite); + TEST_THAT(dir2.GetNumberOfEntries() == DIR_FILES - DIR_OLD); + CheckEntries(dir2, BackupStoreDirectory::Entry::Flags_File, BackupStoreDirectory::Entry::Flags_OldVersion); + } + + // Finally test deleting items + { + dir1.DeleteEntry(12312312321LL); + // Verify + TEST_THAT(dir1.GetNumberOfEntries() == DIR_NUM - 1); + CollectInBufferStream stream; + dir1.WriteToStream(stream, BackupStoreDirectory::Entry::Flags_File); + stream.SetForReading(); + BackupStoreDirectory dir2; + dir2.ReadFromStream(stream, IOStream::TimeOutInfinite); + TEST_THAT(dir2.GetNumberOfEntries() == DIR_FILES - 1); + } + + // Check attributes + { + int attrI[4] = {1, 2, 3, 4}; + StreamableMemBlock attr(attrI, sizeof(attrI)); + BackupStoreDirectory d1(16, 546); + d1.SetAttributes(attr, 56234987324232LL); + TEST_THAT(d1.GetAttributes() == attr); + TEST_THAT(d1.GetAttributesModTime() == 56234987324232LL); + CollectInBufferStream stream; + d1.WriteToStream(stream); + stream.SetForReading(); + BackupStoreDirectory d2; + d2.ReadFromStream(stream, IOStream::TimeOutInfinite); + TEST_THAT(d2.GetAttributes() == attr); + TEST_THAT(d2.GetAttributesModTime() == 56234987324232LL); + } + } + return 0; +} + +void write_test_file(int t) +{ + std::string filename("testfiles/test"); + filename += uploads[t].fnextra; + printf("%s\n", filename.c_str()); + + FileStream write(filename.c_str(), O_WRONLY | O_CREAT); + + R250 r(uploads[t].seed); + + unsigned char *data = (unsigned char*)malloc(uploads[t].size); + for(int l = 0; l < uploads[t].size; ++l) + { + data[l] = r.next() & 0xff; + } + write.Write(data, uploads[t].size); + + free(data); +} + +void test_test_file(int t, IOStream &rStream) +{ + // Decode to a file + BackupStoreFile::DecodeFile(rStream, "testfiles/test_download", IOStream::TimeOutInfinite); + + // Compare... + FileStream in("testfiles/test_download"); + TEST_THAT(in.BytesLeftToRead() == uploads[t].size); + + R250 r(uploads[t].seed); + + unsigned char *data = (unsigned char*)malloc(uploads[t].size); + TEST_THAT(in.ReadFullBuffer(data, uploads[t].size, 0 /* not interested in bytes read if this fails */)); + + for(int l = 0; l < uploads[t].size; ++l) + { + TEST_THAT(data[l] == (r.next() & 0xff)); + } + + free(data); + unlink("testfiles/test_download"); +} + +void test_everything_deleted(BackupProtocolClient &protocol, int64_t DirID) +{ + printf("Test for del: %llx\n", DirID); + + // Command + std::auto_ptr dirreply(protocol.QueryListDirectory( + DirID, + BackupProtocolClientListDirectory::Flags_INCLUDE_EVERYTHING, + BackupProtocolClientListDirectory::Flags_EXCLUDE_NOTHING, false /* no attributes */)); + // Stream + BackupStoreDirectory dir; + std::auto_ptr dirstream(protocol.ReceiveStream()); + dir.ReadFromStream(*dirstream, IOStream::TimeOutInfinite); + + BackupStoreDirectory::Iterator i(dir); + BackupStoreDirectory::Entry *en = 0; + int files = 0; + int dirs = 0; + while((en = i.Next()) != 0) + { + if(en->GetFlags() & BackupProtocolClientListDirectory::Flags_Dir) + { + dirs++; + // Recurse + test_everything_deleted(protocol, en->GetObjectID()); + } + else + { + files++; + } + // Check it's deleted + TEST_THAT(en->GetFlags() & BackupProtocolClientListDirectory::Flags_Deleted); + } + + // Check there were the right number of files and directories + TEST_THAT(files == 3); + TEST_THAT(dirs == 0 || dirs == 2); +} + +int64_t create_test_data_subdirs(BackupProtocolClient &protocol, int64_t indir, const char *name, int depth) +{ + // Create a directory + int64_t subdirid = 0; + BackupStoreFilenameClear dirname(name); + { + // Create with dummy attributes + int attrS = 0; + MemBlockStream attr(&attrS, sizeof(attrS)); + std::auto_ptr dirCreate(protocol.QueryCreateDirectory( + indir, + 9837429842987984LL, dirname, attr)); + subdirid = dirCreate->GetObjectID(); + } + + printf("Create subdirs, depth = %d, dirid = %llx\n", depth, subdirid); + + // Put more directories in it, if we haven't gone down too far + if(depth > 0) + { + create_test_data_subdirs(protocol, subdirid, "dir_One", depth - 1); + create_test_data_subdirs(protocol, subdirid, "dir_Two", depth - 1); + } + + // Stick some files in it + { + BackupStoreFilenameClear name("file_One"); + std::auto_ptr upload(BackupStoreFile::EncodeFile("testfiles/file1", subdirid, name)); + std::auto_ptr stored(protocol.QueryStoreFile( + subdirid, + 0x123456789abcdefLL, /* modification time */ + 0x7362383249872dfLL, /* attr hash */ + 0, /* diff from ID */ + name, + *upload)); + } + { + BackupStoreFilenameClear name("file_Two"); + std::auto_ptr upload(BackupStoreFile::EncodeFile("testfiles/file1", subdirid, name)); + std::auto_ptr stored(protocol.QueryStoreFile( + subdirid, + 0x123456789abcdefLL, /* modification time */ + 0x7362383249872dfLL, /* attr hash */ + 0, /* diff from ID */ + name, + *upload)); + } + { + BackupStoreFilenameClear name("file_Three"); + std::auto_ptr upload(BackupStoreFile::EncodeFile("testfiles/file1", subdirid, name)); + std::auto_ptr stored(protocol.QueryStoreFile( + subdirid, + 0x123456789abcdefLL, /* modification time */ + 0x7362383249872dfLL, /* attr hash */ + 0, /* diff from ID */ + name, + *upload)); + } + + return subdirid; +} + + +void check_dir_after_uploads(BackupProtocolClient &protocol, const StreamableMemBlock &Attributes) +{ + // Command + std::auto_ptr dirreply(protocol.QueryListDirectory( + BackupProtocolClientListDirectory::RootDirectory, + BackupProtocolClientListDirectory::Flags_INCLUDE_EVERYTHING, + BackupProtocolClientListDirectory::Flags_EXCLUDE_NOTHING, false /* no attributes */)); + TEST_THAT(dirreply->GetObjectID() == BackupProtocolClientListDirectory::RootDirectory); + // Stream + BackupStoreDirectory dir; + std::auto_ptr dirstream(protocol.ReceiveStream()); + dir.ReadFromStream(*dirstream, IOStream::TimeOutInfinite); + TEST_THAT(dir.GetNumberOfEntries() == UPLOAD_NUM + 1 /* for the first test file */); + TEST_THAT(!dir.HasAttributes()); + + // Check them! + BackupStoreDirectory::Iterator i(dir); + // Discard first + BackupStoreDirectory::Entry *en = i.Next(); + TEST_THAT(en != 0); + + for(int t = 0; t < UPLOAD_NUM; ++t) + { + en = i.Next(); + TEST_THAT(en != 0); + TEST_THAT(en->GetName() == uploads[t].name); + TEST_THAT(en->GetObjectID() == uploads[t].allocated_objid); + TEST_THAT(en->GetModificationTime() == uploads[t].mod_time); + int correct_flags = BackupProtocolClientListDirectory::Flags_File; + if(uploads[t].should_be_old_version) correct_flags |= BackupProtocolClientListDirectory::Flags_OldVersion; + if(uploads[t].delete_file) correct_flags |= BackupProtocolClientListDirectory::Flags_Deleted; + TEST_THAT(en->GetFlags() == correct_flags); + if(t == UPLOAD_ATTRS_EN) + { + TEST_THAT(en->HasAttributes()); + TEST_THAT(en->GetAttributesHash() == 32498749832475LL); + TEST_THAT(en->GetAttributes() == Attributes); + } + else + { + // No attributes on this one + TEST_THAT(!en->HasAttributes()); + } + } + en = i.Next(); + TEST_THAT(en == 0); +} + + +typedef struct +{ + int objectsNotDel; + int deleted; + int old; +} recusive_count_objects_results; + +void recusive_count_objects_r(BackupProtocolClient &protocol, int64_t id, recusive_count_objects_results &results) +{ + // Command + std::auto_ptr dirreply(protocol.QueryListDirectory( + id, + BackupProtocolClientListDirectory::Flags_INCLUDE_EVERYTHING, + BackupProtocolClientListDirectory::Flags_EXCLUDE_NOTHING, false /* no attributes */)); + // Stream + BackupStoreDirectory dir; + std::auto_ptr dirstream(protocol.ReceiveStream()); + dir.ReadFromStream(*dirstream, IOStream::TimeOutInfinite); + + // Check them! + BackupStoreDirectory::Iterator i(dir); + // Discard first + BackupStoreDirectory::Entry *en = 0; + + while((en = i.Next()) != 0) + { + if((en->GetFlags() & (BackupStoreDirectory::Entry::Flags_Deleted | BackupStoreDirectory::Entry::Flags_OldVersion)) == 0) results.objectsNotDel++; + if(en->GetFlags() & BackupStoreDirectory::Entry::Flags_Deleted) results.deleted++; + if(en->GetFlags() & BackupStoreDirectory::Entry::Flags_OldVersion) results.old++; + + if(en->GetFlags() & BackupStoreDirectory::Entry::Flags_Dir) + { + recusive_count_objects_r(protocol, en->GetObjectID(), results); + } + } +} + +void recusive_count_objects(const char *hostname, int64_t id, recusive_count_objects_results &results) +{ + // Context + TLSContext context; + context.Initialise(false /* client */, + "testfiles/clientCerts.pem", + "testfiles/clientPrivKey.pem", + "testfiles/clientTrustedCAs.pem"); + + // Get a connection + SocketStreamTLS connReadOnly; + connReadOnly.Open(context, Socket::TypeINET, hostname, BOX_PORT_BBSTORED); + BackupProtocolClient protocolReadOnly(connReadOnly); + + { + std::auto_ptr serverVersion(protocolReadOnly.QueryVersion(BACKUP_STORE_SERVER_VERSION)); + TEST_THAT(serverVersion->GetVersion() == BACKUP_STORE_SERVER_VERSION); + std::auto_ptr loginConf(protocolReadOnly.QueryLogin(0x01234567, BackupProtocolClientLogin::Flags_ReadOnly)); + } + + // Count objects + recusive_count_objects_r(protocolReadOnly, id, results); + + // Close it + protocolReadOnly.QueryFinished(); +} + +bool check_block_index(const char *encoded_file, IOStream &rBlockIndex) +{ + // Open file, and move to the right position + FileStream enc(encoded_file); + BackupStoreFile::MoveStreamPositionToBlockIndex(enc); + + bool same = true; + + // Now compare the two... + while(enc.StreamDataLeft()) + { + char buffer1[2048]; + char buffer2[2048]; + int s = enc.Read(buffer1, sizeof(buffer1)); + if(rBlockIndex.Read(buffer2, s) != s) + { + same = false; + break; + } + if(::memcmp(buffer1, buffer2, s) != 0) + { + same = false; + break; + } + } + + if(rBlockIndex.StreamDataLeft()) + { + same = false; + + // Absorb all this excess data so procotol is in the first state + char buffer[2048]; + while(rBlockIndex.StreamDataLeft()) + { + rBlockIndex.Read(buffer, sizeof(buffer)); + } + } + + return same; +} + +bool check_files_same(const char *f1, const char *f2) +{ + // Open file, and move to the right position + FileStream f1s(f1); + FileStream f2s(f2); + + bool same = true; + + // Now compare the two... + while(f1s.StreamDataLeft()) + { + char buffer1[2048]; + char buffer2[2048]; + int s = f1s.Read(buffer1, sizeof(buffer1)); + if(f2s.Read(buffer2, s) != s) + { + same = false; + break; + } + if(::memcmp(buffer1, buffer2, s) != 0) + { + same = false; + break; + } + } + + if(f2s.StreamDataLeft()) + { + same = false; + } + + return same; +} + + +void test_server_1(BackupProtocolClient &protocol, BackupProtocolClient &protocolReadOnly) +{ + int encfile[ENCFILE_SIZE]; + { + for(int l = 0; l < ENCFILE_SIZE; ++l) + { + encfile[l] = l * 173; + } + + // Write this to a file + { + FileStream f("testfiles/file1", O_WRONLY | O_CREAT | O_EXCL); + f.Write(encfile, sizeof(encfile)); + } + + } + + // Read the root directory a few times (as it's cached, so make sure it doesn't hurt anything) + for(int l = 0; l < 3; ++l) + { + // Command + std::auto_ptr dirreply(protocol.QueryListDirectory( + BackupProtocolClientListDirectory::RootDirectory, + BackupProtocolClientListDirectory::Flags_INCLUDE_EVERYTHING, + BackupProtocolClientListDirectory::Flags_EXCLUDE_NOTHING, false /* no attributes */)); + // Stream + BackupStoreDirectory dir; + std::auto_ptr dirstream(protocol.ReceiveStream()); + dir.ReadFromStream(*dirstream, IOStream::TimeOutInfinite); + TEST_THAT(dir.GetNumberOfEntries() == 0); + } + + // Read the dir from the readonly connection (make sure it gets in the cache) + { + // Command + std::auto_ptr dirreply(protocolReadOnly.QueryListDirectory( + BackupProtocolClientListDirectory::RootDirectory, + BackupProtocolClientListDirectory::Flags_INCLUDE_EVERYTHING, + BackupProtocolClientListDirectory::Flags_EXCLUDE_NOTHING, false /* no attributes */)); + // Stream + BackupStoreDirectory dir; + std::auto_ptr dirstream(protocolReadOnly.ReceiveStream()); + dir.ReadFromStream(*dirstream, IOStream::TimeOutInfinite); + TEST_THAT(dir.GetNumberOfEntries() == 0); + } + + // Store a file -- first make the encoded file + BackupStoreFilenameClear store1name("testfiles/file1"); + { + FileStream out("testfiles/file1_upload1", O_WRONLY | O_CREAT | O_EXCL); + std::auto_ptr encoded(BackupStoreFile::EncodeFile("testfiles/file1", BackupProtocolClientListDirectory::RootDirectory, store1name)); + encoded->CopyStreamTo(out); + } + +// printf("SKIPPING\n"); +// goto skip; { + // Then send it + int64_t store1objid = 0; + { + FileStream upload("testfiles/file1_upload1"); + std::auto_ptr stored(protocol.QueryStoreFile( + BackupProtocolClientListDirectory::RootDirectory, + 0x123456789abcdefLL, /* modification time */ + 0x7362383249872dfLL, /* attr hash */ + 0, /* diff from ID */ + store1name, + upload)); + store1objid = stored->GetObjectID(); + TEST_THAT(store1objid == 2); + } + // And retrieve it + { + // Retrieve as object + std::auto_ptr getfile(protocol.QueryGetObject(store1objid)); + TEST_THAT(getfile->GetObjectID() == store1objid); + // BLOCK + { + // Get stream + std::auto_ptr filestream(protocol.ReceiveStream()); + // Need to put it in another stream, because it's not in stream order + CollectInBufferStream f; + filestream->CopyStreamTo(f); + f.SetForReading(); + // Get and decode + BackupStoreFile::DecodeFile(f, "testfiles/file1_upload_retrieved", IOStream::TimeOutInfinite); + } + + // Retrieve as file + std::auto_ptr getobj(protocol.QueryGetFile(BackupProtocolClientListDirectory::RootDirectory, store1objid)); + TEST_THAT(getobj->GetObjectID() == store1objid); + // BLOCK + { + // Get stream + std::auto_ptr filestream(protocol.ReceiveStream()); + // Get and decode + BackupStoreFile::DecodeFile(*filestream, "testfiles/file1_upload_retrieved_str", IOStream::TimeOutInfinite); + } + + // Read in rebuilt original, and compare contents + { + FileStream in("testfiles/file1_upload_retrieved"); + int encfile_i[ENCFILE_SIZE]; + in.Read(encfile_i, sizeof(encfile_i)); + TEST_THAT(memcmp(encfile, encfile_i, sizeof(encfile)) == 0); + } + { + FileStream in("testfiles/file1_upload_retrieved_str"); + int encfile_i[ENCFILE_SIZE]; + in.Read(encfile_i, sizeof(encfile_i)); + TEST_THAT(memcmp(encfile, encfile_i, sizeof(encfile)) == 0); + } + + // Retrieve the block index, by ID + { + std::auto_ptr getblockindex(protocol.QueryGetBlockIndexByID(store1objid)); + TEST_THAT(getblockindex->GetObjectID() == store1objid); + std::auto_ptr blockIndexStream(protocol.ReceiveStream()); + // Check against uploaded file + TEST_THAT(check_block_index("testfiles/file1_upload1", *blockIndexStream)); + } + // and again, by name + { + std::auto_ptr getblockindex(protocol.QueryGetBlockIndexByName(BackupProtocolClientListDirectory::RootDirectory, store1name)); + TEST_THAT(getblockindex->GetObjectID() == store1objid); + std::auto_ptr blockIndexStream(protocol.ReceiveStream()); + // Check against uploaded file + TEST_THAT(check_block_index("testfiles/file1_upload1", *blockIndexStream)); + } + } + // Get the directory again, and see if the entry is in it + { + // Command + std::auto_ptr dirreply(protocol.QueryListDirectory( + BackupProtocolClientListDirectory::RootDirectory, + BackupProtocolClientListDirectory::Flags_INCLUDE_EVERYTHING, + BackupProtocolClientListDirectory::Flags_EXCLUDE_NOTHING, false /* no attributes */)); + // Stream + BackupStoreDirectory dir; + std::auto_ptr dirstream(protocol.ReceiveStream()); + dir.ReadFromStream(*dirstream, IOStream::TimeOutInfinite); + TEST_THAT(dir.GetNumberOfEntries() == 1); + BackupStoreDirectory::Iterator i(dir); + BackupStoreDirectory::Entry *en = i.Next(); + TEST_THAT(en != 0); + TEST_THAT(i.Next() == 0); + if(en != 0) + { + TEST_THAT(en->GetName() == store1name); + TEST_THAT(en->GetModificationTime() == 0x123456789abcdefLL); + TEST_THAT(en->GetAttributesHash() == 0x7362383249872dfLL); + TEST_THAT(en->GetObjectID() == store1objid); + TEST_THAT(en->GetSizeInBlocks() < ((ENCFILE_SIZE * 4 * 3) / 2 / 2048)+2); + TEST_THAT(en->GetFlags() == BackupStoreDirectory::Entry::Flags_File); + } + } + + // Try using GetFile on a directory + { + TEST_CHECK_THROWS(std::auto_ptr getFile(protocol.QueryGetFile(BackupProtocolClientListDirectory::RootDirectory, BackupProtocolClientListDirectory::RootDirectory)), + ConnectionException, Conn_Protocol_UnexpectedReply); + } +} + + +int test_server(const char *hostname) +{ + // Context + TLSContext context; + context.Initialise(false /* client */, + "testfiles/clientCerts.pem", + "testfiles/clientPrivKey.pem", + "testfiles/clientTrustedCAs.pem"); + + // Make some test attributes + #define ATTR1_SIZE 245 + #define ATTR2_SIZE 23 + #define ATTR3_SIZE 122 + int attr1[ATTR1_SIZE]; + int attr2[ATTR2_SIZE]; + int attr3[ATTR3_SIZE]; + { + R250 r(3465657); + for(int l = 0; l < ATTR1_SIZE; ++l) {attr1[l] = r.next();} + for(int l = 0; l < ATTR2_SIZE; ++l) {attr2[l] = r.next();} + for(int l = 0; l < ATTR3_SIZE; ++l) {attr3[l] = r.next();} + } + + // BLOCK + { + // Open a connection to the server + SocketStreamTLS conn; + conn.Open(context, Socket::TypeINET, hostname, BOX_PORT_BBSTORED); + + // Make a protocol + BackupProtocolClient protocol(conn); + + // Get it logging + FILE *protocolLog = ::fopen("testfiles/protocol.log", "w"); + TEST_THAT(protocolLog != 0); + protocol.SetLogToFile(protocolLog); + + // Check the version + std::auto_ptr serverVersion(protocol.QueryVersion(BACKUP_STORE_SERVER_VERSION)); + TEST_THAT(serverVersion->GetVersion() == BACKUP_STORE_SERVER_VERSION); + + // Login + std::auto_ptr loginConf(protocol.QueryLogin(0x01234567, 0)); + + // Check marker is 0 + TEST_THAT(loginConf->GetClientStoreMarker() == 0); + + // Check that we can't open a new connection which requests write permissions + { + SocketStreamTLS conn; + conn.Open(context, Socket::TypeINET, hostname, BOX_PORT_BBSTORED); + BackupProtocolClient protocol(conn); + std::auto_ptr serverVersion(protocol.QueryVersion(BACKUP_STORE_SERVER_VERSION)); + TEST_THAT(serverVersion->GetVersion() == BACKUP_STORE_SERVER_VERSION); + TEST_CHECK_THROWS(std::auto_ptr loginConf(protocol.QueryLogin(0x01234567, 0)), + ConnectionException, Conn_Protocol_UnexpectedReply); + protocol.QueryFinished(); + } + + // Set the client store marker + protocol.QuerySetClientStoreMarker(0x8732523ab23aLL); + + // Open a new connection which is read only + SocketStreamTLS connReadOnly; + connReadOnly.Open(context, Socket::TypeINET, hostname, BOX_PORT_BBSTORED); + BackupProtocolClient protocolReadOnly(connReadOnly); + + // Get it logging + FILE *protocolReadOnlyLog = ::fopen("testfiles/protocolReadOnly.log", "w"); + TEST_THAT(protocolReadOnlyLog != 0); + protocolReadOnly.SetLogToFile(protocolReadOnlyLog); + + { + std::auto_ptr serverVersion(protocolReadOnly.QueryVersion(BACKUP_STORE_SERVER_VERSION)); + TEST_THAT(serverVersion->GetVersion() == BACKUP_STORE_SERVER_VERSION); + std::auto_ptr loginConf(protocolReadOnly.QueryLogin(0x01234567, BackupProtocolClientLogin::Flags_ReadOnly)); + + // Check client store marker + TEST_THAT(loginConf->GetClientStoreMarker() == 0x8732523ab23aLL); + } + + test_server_1(protocol, protocolReadOnly); + + + // Create and upload some test files + int64_t maxID = 0; + for(int t = 0; t < UPLOAD_NUM; ++t) + { + write_test_file(t); + + std::string filename("testfiles/test"); + filename += uploads[t].fnextra; + int64_t modtime = 0; + + std::auto_ptr upload(BackupStoreFile::EncodeFile(filename.c_str(), BackupProtocolClientListDirectory::RootDirectory, uploads[t].name, &modtime)); + TEST_THAT(modtime != 0); + + std::auto_ptr stored(protocol.QueryStoreFile( + BackupProtocolClientListDirectory::RootDirectory, + modtime, + modtime, /* use it for attr hash too */ + 0, /* diff from ID */ + uploads[t].name, + *upload)); + uploads[t].allocated_objid = stored->GetObjectID(); + uploads[t].mod_time = modtime; + if(maxID < stored->GetObjectID()) maxID = stored->GetObjectID(); + } + + // Add some attributes onto one of them + { + MemBlockStream attrnew(attr3, sizeof(attr3)); + std::auto_ptr set(protocol.QuerySetReplacementFileAttributes( + BackupProtocolClientListDirectory::RootDirectory, + 32498749832475LL, + uploads[UPLOAD_ATTRS_EN].name, + attrnew)); + TEST_THAT(set->GetObjectID() == uploads[UPLOAD_ATTRS_EN].allocated_objid); + } + + // Delete one of them (will implicitly delete an old version) + { + std::auto_ptr del(protocol.QueryDeleteFile( + BackupProtocolClientListDirectory::RootDirectory, + uploads[UPLOAD_DELETE_EN].name)); + TEST_THAT(del->GetObjectID() == uploads[UPLOAD_DELETE_EN].allocated_objid); + } + // Check that the block index can be obtained by name even though it's been deleted + { + // Fetch the raw object + { + FileStream out("testfiles/downloaddelobj", O_WRONLY | O_CREAT); + std::auto_ptr getobj(protocol.QueryGetObject(uploads[UPLOAD_DELETE_EN].allocated_objid)); + std::auto_ptr objstream(protocol.ReceiveStream()); + objstream->CopyStreamTo(out); + } + // query index and test + std::auto_ptr getblockindex(protocol.QueryGetBlockIndexByName( + BackupProtocolClientListDirectory::RootDirectory, uploads[UPLOAD_DELETE_EN].name)); + TEST_THAT(getblockindex->GetObjectID() == uploads[UPLOAD_DELETE_EN].allocated_objid); + std::auto_ptr blockIndexStream(protocol.ReceiveStream()); + TEST_THAT(check_block_index("testfiles/downloaddelobj", *blockIndexStream)); + } + + // Download them all... (even deleted files) + for(int t = 0; t < UPLOAD_NUM; ++t) + { + printf("%d\n", t); + std::auto_ptr getFile(protocol.QueryGetFile(BackupProtocolClientListDirectory::RootDirectory, uploads[t].allocated_objid)); + TEST_THAT(getFile->GetObjectID() == uploads[t].allocated_objid); + std::auto_ptr filestream(protocol.ReceiveStream()); + test_test_file(t, *filestream); + } + + { + StreamableMemBlock attrtest(attr3, sizeof(attr3)); + + // Use the read only connection to verify that the directory is as we expect + check_dir_after_uploads(protocolReadOnly, attrtest); + // And on the read/write one + check_dir_after_uploads(protocol, attrtest); + } + + // Check diffing and rsync like stuff... + // Build a modified file + { + // Basically just insert a bit in the middle + TEST_THAT(TestGetFileSize(TEST_FILE_FOR_PATCHING) == TEST_FILE_FOR_PATCHING_SIZE); + FileStream in(TEST_FILE_FOR_PATCHING); + void *buf = ::malloc(TEST_FILE_FOR_PATCHING_SIZE); + FileStream out(TEST_FILE_FOR_PATCHING ".mod", O_WRONLY | O_CREAT | O_EXCL); + TEST_THAT(in.Read(buf, TEST_FILE_FOR_PATCHING_PATCH_AT) == TEST_FILE_FOR_PATCHING_PATCH_AT); + out.Write(buf, TEST_FILE_FOR_PATCHING_PATCH_AT); + char insert[13] = "INSERTINSERT"; + out.Write(insert, sizeof(insert)); + TEST_THAT(in.Read(buf, TEST_FILE_FOR_PATCHING_SIZE - TEST_FILE_FOR_PATCHING_PATCH_AT) == TEST_FILE_FOR_PATCHING_SIZE - TEST_FILE_FOR_PATCHING_PATCH_AT); + out.Write(buf, TEST_FILE_FOR_PATCHING_SIZE - TEST_FILE_FOR_PATCHING_PATCH_AT); + ::free(buf); + } + { + // Fetch the block index for this one + std::auto_ptr getblockindex(protocol.QueryGetBlockIndexByName( + BackupProtocolClientListDirectory::RootDirectory, uploads[UPLOAD_PATCH_EN].name)); + TEST_THAT(getblockindex->GetObjectID() == uploads[UPLOAD_PATCH_EN].allocated_objid); + std::auto_ptr blockIndexStream(protocol.ReceiveStream()); + + // Do the patching + bool isCompletelyDifferent = false; + int64_t modtime; + std::auto_ptr patchstream(BackupStoreFile::EncodeFileDiff(TEST_FILE_FOR_PATCHING ".mod", BackupProtocolClientListDirectory::RootDirectory, + uploads[UPLOAD_PATCH_EN].name, uploads[UPLOAD_PATCH_EN].allocated_objid, *blockIndexStream, + IOStream::TimeOutInfinite, &modtime, &isCompletelyDifferent)); + TEST_THAT(isCompletelyDifferent == false); + // Sent this to a file, so we can check the size, rather than uploading it directly + { + FileStream patch(TEST_FILE_FOR_PATCHING ".patch", O_WRONLY | O_CREAT | O_EXCL); + patchstream->CopyStreamTo(patch); + } + // Make sure the stream is a plausible size for a patch containing only one new block + TEST_THAT(TestGetFileSize(TEST_FILE_FOR_PATCHING ".patch") < (8*1024)); + // Upload it + int64_t patchedID = 0; + { + FileStream uploadpatch(TEST_FILE_FOR_PATCHING ".patch"); + std::auto_ptr stored(protocol.QueryStoreFile( + BackupProtocolClientListDirectory::RootDirectory, + modtime, + modtime, /* use it for attr hash too */ + uploads[UPLOAD_PATCH_EN].allocated_objid, /* diff from ID */ + uploads[UPLOAD_PATCH_EN].name, + uploadpatch)); + TEST_THAT(stored->GetObjectID() > 0); + if(maxID < stored->GetObjectID()) maxID = stored->GetObjectID(); + patchedID = stored->GetObjectID(); + } + // Then download it to check it's OK + std::auto_ptr getFile(protocol.QueryGetFile(BackupProtocolClientListDirectory::RootDirectory, patchedID)); + TEST_THAT(getFile->GetObjectID() == patchedID); + std::auto_ptr filestream(protocol.ReceiveStream()); + BackupStoreFile::DecodeFile(*filestream, TEST_FILE_FOR_PATCHING ".downloaded", IOStream::TimeOutInfinite); + // Check it's the same + TEST_THAT(check_files_same(TEST_FILE_FOR_PATCHING ".downloaded", TEST_FILE_FOR_PATCHING ".mod")); + } + + // Create a directory + int64_t subdirid = 0; + BackupStoreFilenameClear dirname("lovely_directory"); + { + // Attributes + MemBlockStream attr(attr1, sizeof(attr1)); + std::auto_ptr dirCreate(protocol.QueryCreateDirectory( + BackupProtocolClientListDirectory::RootDirectory, + 9837429842987984LL, dirname, attr)); + subdirid = dirCreate->GetObjectID(); + TEST_THAT(subdirid == maxID + 1); + } + // Stick a file in it + int64_t subdirfileid = 0; + { + std::string filename("testfiles/test0"); + int64_t modtime; + std::auto_ptr upload(BackupStoreFile::EncodeFile(filename.c_str(), subdirid, uploads[0].name, &modtime)); + + std::auto_ptr stored(protocol.QueryStoreFile( + subdirid, + modtime, + modtime, /* use for attr hash too */ + 0, /* diff from ID */ + uploads[0].name, + *upload)); + subdirfileid = stored->GetObjectID(); + } + // Check the directories on the read only connection + { + // Command + std::auto_ptr dirreply(protocolReadOnly.QueryListDirectory( + BackupProtocolClientListDirectory::RootDirectory, + BackupProtocolClientListDirectory::Flags_INCLUDE_EVERYTHING, + BackupProtocolClientListDirectory::Flags_EXCLUDE_NOTHING, false /* no attributes! */)); // Stream + BackupStoreDirectory dir; + std::auto_ptr dirstream(protocolReadOnly.ReceiveStream()); + dir.ReadFromStream(*dirstream, IOStream::TimeOutInfinite); + TEST_THAT(dir.GetNumberOfEntries() == UPLOAD_NUM + 3 /* for the first test file, the patched upload, and this new dir */); + + // Check the last one... + BackupStoreDirectory::Iterator i(dir); + BackupStoreDirectory::Entry *en = 0; + BackupStoreDirectory::Entry *t = 0; + while((t = i.Next()) != 0) + { + if(en != 0) + { + // here for all but last object + TEST_THAT(en->GetObjectID() != subdirid); + TEST_THAT(en->GetName() != dirname); + } + en = t; + } + // Does it look right? + TEST_THAT(en->GetName() == dirname); + TEST_THAT(en->GetFlags() == BackupProtocolClientListDirectory::Flags_Dir); + TEST_THAT(en->GetObjectID() == subdirid); + TEST_THAT(en->GetModificationTime() == 0); // dirs don't have modification times. + } + { + // Command + std::auto_ptr dirreply(protocolReadOnly.QueryListDirectory( + subdirid, + BackupProtocolClientListDirectory::Flags_INCLUDE_EVERYTHING, + BackupProtocolClientListDirectory::Flags_EXCLUDE_NOTHING, true /* get attributes */)); + TEST_THAT(dirreply->GetObjectID() == subdirid); + // Stream + BackupStoreDirectory dir; + std::auto_ptr dirstream(protocolReadOnly.ReceiveStream()); + dir.ReadFromStream(*dirstream, IOStream::TimeOutInfinite); + TEST_THAT(dir.GetNumberOfEntries() == 1); + + // Check the last one... + BackupStoreDirectory::Iterator i(dir); + // Discard first + BackupStoreDirectory::Entry *en = i.Next(); + TEST_THAT(en != 0); + // Does it look right? + TEST_THAT(en->GetName() == uploads[0].name); + TEST_THAT(en->GetFlags() == BackupProtocolClientListDirectory::Flags_File); + TEST_THAT(en->GetObjectID() == subdirfileid); + TEST_THAT(en->GetModificationTime() != 0); + + // Attributes + TEST_THAT(dir.HasAttributes()); + TEST_THAT(dir.GetAttributesModTime() == 9837429842987984LL); + 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 + std::auto_ptr dirreply(protocolReadOnly.QueryListDirectory( + subdirid, + BackupProtocolClientListDirectory::Flags_INCLUDE_EVERYTHING, + BackupProtocolClientListDirectory::Flags_EXCLUDE_NOTHING, false /* no attributes! */)); + // Stream + BackupStoreDirectory dir; + std::auto_ptr dirstream(protocolReadOnly.ReceiveStream()); + dir.ReadFromStream(*dirstream, IOStream::TimeOutInfinite); + TEST_THAT(!dir.HasAttributes()); + } + // Change attributes on the directory + { + MemBlockStream attrnew(attr2, sizeof(attr2)); + std::auto_ptr changereply(protocol.QueryChangeDirAttributes( + subdirid, + 329483209443598LL, + attrnew)); + TEST_THAT(changereply->GetObjectID() == subdirid); + } + // Check the new attributes + { + // Command + std::auto_ptr dirreply(protocolReadOnly.QueryListDirectory( + subdirid, + 0, // no flags + BackupProtocolClientListDirectory::Flags_EXCLUDE_EVERYTHING, true /* get attributes */)); + // Stream + BackupStoreDirectory dir; + std::auto_ptr dirstream(protocolReadOnly.ReceiveStream()); + dir.ReadFromStream(*dirstream, IOStream::TimeOutInfinite); + TEST_THAT(dir.GetNumberOfEntries() == 0); + + // Attributes + TEST_THAT(dir.HasAttributes()); + TEST_THAT(dir.GetAttributesModTime() == 329483209443598LL); + StreamableMemBlock attrtest(attr2, sizeof(attr2)); + TEST_THAT(dir.GetAttributes() == attrtest); + } + + // Test moving a file + { + BackupStoreFilenameClear newName("moved-files"); + + std::auto_ptr rep(protocol.QueryMoveObject(uploads[UPLOAD_FILE_TO_MOVE].allocated_objid, + BackupProtocolClientListDirectory::RootDirectory, + subdirid, BackupProtocolClientMoveObject::Flags_MoveAllWithSameName, newName)); + TEST_THAT(rep->GetObjectID() == uploads[UPLOAD_FILE_TO_MOVE].allocated_objid); + } + // Try some dodgy renames + { + BackupStoreFilenameClear newName("moved-files"); + TEST_CHECK_THROWS(protocol.QueryMoveObject(uploads[UPLOAD_FILE_TO_MOVE].allocated_objid, + BackupProtocolClientListDirectory::RootDirectory, + subdirid, BackupProtocolClientMoveObject::Flags_MoveAllWithSameName, newName), + ConnectionException, Conn_Protocol_UnexpectedReply); + TEST_CHECK_THROWS(protocol.QueryMoveObject(uploads[UPLOAD_FILE_TO_MOVE].allocated_objid, + subdirid, + subdirid, BackupProtocolClientMoveObject::Flags_MoveAllWithSameName, newName), + ConnectionException, Conn_Protocol_UnexpectedReply); + } + // Rename within a directory + { + BackupStoreFilenameClear newName("moved-files-x"); + protocol.QueryMoveObject(uploads[UPLOAD_FILE_TO_MOVE].allocated_objid, + subdirid, + subdirid, BackupProtocolClientMoveObject::Flags_MoveAllWithSameName, newName); + } + // Check it's all gone from the root directory... + { + // Command + std::auto_ptr dirreply(protocolReadOnly.QueryListDirectory( + BackupProtocolClientListDirectory::RootDirectory, + BackupProtocolClientListDirectory::Flags_INCLUDE_EVERYTHING, + BackupProtocolClientListDirectory::Flags_EXCLUDE_NOTHING, false /* no attributes */)); + // Stream + BackupStoreDirectory dir; + std::auto_ptr dirstream(protocolReadOnly.ReceiveStream()); + dir.ReadFromStream(*dirstream, IOStream::TimeOutInfinite); + // Read all entries + BackupStoreDirectory::Iterator i(dir); + BackupStoreDirectory::Entry *en = 0; + while((en = i.Next()) != 0) + { + 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"); + + // Command + std::auto_ptr dirreply(protocolReadOnly.QueryListDirectory( + subdirid, + BackupProtocolClientListDirectory::Flags_INCLUDE_EVERYTHING, + BackupProtocolClientListDirectory::Flags_EXCLUDE_NOTHING, false /* no attributes */)); + // Stream + BackupStoreDirectory dir; + std::auto_ptr dirstream(protocolReadOnly.ReceiveStream()); + dir.ReadFromStream(*dirstream, IOStream::TimeOutInfinite); + // Check entries + BackupStoreDirectory::Iterator i(dir); + BackupStoreDirectory::Entry *en = 0; + bool foundCurrent = false; + bool foundOld = false; + while((en = i.Next()) != 0) + { + if(en->GetName() == lookFor) + { + if(en->GetFlags() == (BackupStoreDirectory::Entry::Flags_File)) foundCurrent = true; + if(en->GetFlags() == (BackupStoreDirectory::Entry::Flags_File | BackupStoreDirectory::Entry::Flags_OldVersion)) foundOld = true; + } + } + 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; + { + BackupStoreFilenameClear nd("sub2"); + // Attributes + MemBlockStream attr(attr1, sizeof(attr1)); + std::auto_ptr dirCreate(protocol.QueryCreateDirectory( + subdirid, + 9837429842987984LL, nd, attr)); + subsubdirid = dirCreate->GetObjectID(); + + FileStream upload("testfiles/file1_upload1"); + BackupStoreFilenameClear nf("file2"); + std::auto_ptr stored(protocol.QueryStoreFile( + subsubdirid, + 0x123456789abcdefLL, /* modification time */ + 0x7362383249872dfLL, /* attr hash */ + 0, /* diff from ID */ + nf, + upload)); + subsubfileid = stored->GetObjectID(); + } + // Query names -- test that invalid stuff returns not found OK + { + std::auto_ptr nameRep(protocol.QueryGetObjectName(3248972347823478927LL, subsubdirid)); + TEST_THAT(nameRep->GetNumNameElements() == 0); + } + { + std::auto_ptr nameRep(protocol.QueryGetObjectName(subsubfileid, 2342378424LL)); + TEST_THAT(nameRep->GetNumNameElements() == 0); + } + { + std::auto_ptr nameRep(protocol.QueryGetObjectName(38947234789LL, 2342378424LL)); + TEST_THAT(nameRep->GetNumNameElements() == 0); + } + { + std::auto_ptr nameRep(protocol.QueryGetObjectName(BackupProtocolClientGetObjectName::ObjectID_DirectoryOnly, 2234342378424LL)); + TEST_THAT(nameRep->GetNumNameElements() == 0); + } + // Query names... first, get info for the file + { + std::auto_ptr nameRep(protocol.QueryGetObjectName(subsubfileid, subsubdirid)); + std::auto_ptr namestream(protocol.ReceiveStream()); + + TEST_THAT(nameRep->GetNumNameElements() == 3); + TEST_THAT(nameRep->GetFlags() == BackupProtocolClientListDirectory::Flags_File); + TEST_THAT(nameRep->GetModificationTime() == 0x123456789abcdefLL); + TEST_THAT(nameRep->GetAttributesHash() == 0x7362383249872dfLL); + static const char *testnames[] = {"file2","sub2","lovely_directory"}; + for(int l = 0; l < nameRep->GetNumNameElements(); ++l) + { + BackupStoreFilenameClear fn; + fn.ReadFromStream(*namestream, 10000); + TEST_THAT(fn.GetClearFilename() == testnames[l]); + } + } + // Query names... secondly, for the directory + { + std::auto_ptr nameRep(protocol.QueryGetObjectName(BackupProtocolClientGetObjectName::ObjectID_DirectoryOnly, subsubdirid)); + std::auto_ptr namestream(protocol.ReceiveStream()); + + TEST_THAT(nameRep->GetNumNameElements() == 2); + TEST_THAT(nameRep->GetFlags() == BackupProtocolClientListDirectory::Flags_Dir); + static const char *testnames[] = {"sub2","lovely_directory"}; + for(int l = 0; l < nameRep->GetNumNameElements(); ++l) + { + BackupStoreFilenameClear fn; + fn.ReadFromStream(*namestream, 10000); + TEST_THAT(fn.GetClearFilename() == testnames[l]); + } + } + +//} skip: + + // Create some nice recursive directories + int64_t dirtodelete = create_test_data_subdirs(protocol, + BackupProtocolClientListDirectory::RootDirectory, "test_delete", 6 /* depth */); + + // And delete them + { + std::auto_ptr dirdel(protocol.QueryDeleteDirectory( + dirtodelete)); + TEST_THAT(dirdel->GetObjectID() == dirtodelete); + } + + // Get the root dir, checking for deleted items + { + // Command + std::auto_ptr dirreply(protocolReadOnly.QueryListDirectory( + BackupProtocolClientListDirectory::RootDirectory, + BackupProtocolClientListDirectory::Flags_Dir | BackupProtocolClientListDirectory::Flags_Deleted, + BackupProtocolClientListDirectory::Flags_EXCLUDE_NOTHING, false /* no attributes */)); + // Stream + BackupStoreDirectory dir; + std::auto_ptr dirstream(protocolReadOnly.ReceiveStream()); + dir.ReadFromStream(*dirstream, IOStream::TimeOutInfinite); + + // Check there's only that one entry + TEST_THAT(dir.GetNumberOfEntries() == 1); + + BackupStoreDirectory::Iterator i(dir); + BackupStoreDirectory::Entry *en = i.Next(); + TEST_THAT(en != 0); + if(en) + { + TEST_THAT(en->GetObjectID() == dirtodelete); + BackupStoreFilenameClear n("test_delete"); + TEST_THAT(en->GetName() == n); + } + + // Then... check everything's deleted + test_everything_deleted(protocolReadOnly, dirtodelete); + } + + // Finish the connections + protocolReadOnly.QueryFinished(); + protocol.QueryFinished(); + + // Close logs + ::fclose(protocolReadOnlyLog); + ::fclose(protocolLog); + } + + return 0; +} + +int test3(int argc, const char *argv[]) +{ + // Now test encoded files + // TODO: This test needs to check failure situations as well as everything working, + // but this will be saved for the full implementation. + int encfile[ENCFILE_SIZE]; + { + for(int l = 0; l < ENCFILE_SIZE; ++l) + { + encfile[l] = l * 173; + } + + // Encode and decode a small block (shouldn't be compressed) + { + #define SMALL_BLOCK_SIZE 251 + int encBlockSize = BackupStoreFile::MaxBlockSizeForChunkSize(SMALL_BLOCK_SIZE); + TEST_THAT(encBlockSize > SMALL_BLOCK_SIZE); + BackupStoreFile::EncodingBuffer encoded; + encoded.Allocate(encBlockSize / 8); // make sure reallocation happens + + // Encode! + int encSize = BackupStoreFile::EncodeChunk(encfile, SMALL_BLOCK_SIZE, encoded); + // Check the header says it's not been compressed + TEST_THAT((encoded.mpBuffer[0] & 1) == 0); + // Check the output size has been inflated (no compression) + TEST_THAT(encSize > SMALL_BLOCK_SIZE); + + // Decode it + int decBlockSize = BackupStoreFile::OutputBufferSizeForKnownOutputSize(SMALL_BLOCK_SIZE); + TEST_THAT(decBlockSize > SMALL_BLOCK_SIZE); + uint8_t *decoded = (uint8_t*)malloc(decBlockSize); + int decSize = BackupStoreFile::DecodeChunk(encoded.mpBuffer, encSize, decoded, decBlockSize); + TEST_THAT(decSize < decBlockSize); + TEST_THAT(decSize == SMALL_BLOCK_SIZE); + + // Check it came out of the wash the same + TEST_THAT(::memcmp(encfile, decoded, SMALL_BLOCK_SIZE) == 0); + + free(decoded); + } + + // Encode and decode a big block (should be compressed) + { + int encBlockSize = BackupStoreFile::MaxBlockSizeForChunkSize(ENCFILE_SIZE); + TEST_THAT(encBlockSize > ENCFILE_SIZE); + BackupStoreFile::EncodingBuffer encoded; + encoded.Allocate(encBlockSize / 8); // make sure reallocation happens + + // Encode! + int encSize = BackupStoreFile::EncodeChunk(encfile, ENCFILE_SIZE, encoded); + // Check the header says it's compressed + TEST_THAT((encoded.mpBuffer[0] & 1) == 1); + // Check the output size make it likely that it's compressed (is very compressible data) + TEST_THAT(encSize < ENCFILE_SIZE); + + // Decode it + int decBlockSize = BackupStoreFile::OutputBufferSizeForKnownOutputSize(ENCFILE_SIZE); + TEST_THAT(decBlockSize > ENCFILE_SIZE); + uint8_t *decoded = (uint8_t*)malloc(decBlockSize); + int decSize = BackupStoreFile::DecodeChunk(encoded.mpBuffer, encSize, decoded, decBlockSize); + TEST_THAT(decSize < decBlockSize); + TEST_THAT(decSize == ENCFILE_SIZE); + + // Check it came out of the wash the same + TEST_THAT(::memcmp(encfile, decoded, ENCFILE_SIZE) == 0); + + free(decoded); + } + + // The test block to a file + { + FileStream f("testfiles/testenc1", O_WRONLY | O_CREAT | O_EXCL); + f.Write(encfile, sizeof(encfile)); + } + + // Encode it + { + FileStream out("testfiles/testenc1_enc", O_WRONLY | O_CREAT | O_EXCL); + BackupStoreFilenameClear name("testfiles/testenc1"); + + std::auto_ptr encoded(BackupStoreFile::EncodeFile("testfiles/testenc1", 32, name)); + encoded->CopyStreamTo(out); + } + + // Verify it + { + FileStream enc("testfiles/testenc1_enc"); + TEST_THAT(BackupStoreFile::VerifyEncodedFileFormat(enc) == true); + } + + // Decode it + { + FileStream enc("testfiles/testenc1_enc"); + BackupStoreFile::DecodeFile(enc, "testfiles/testenc1_orig", IOStream::TimeOutInfinite); + } + + // Read in rebuilt original, and compare contents + { + TEST_THAT(TestGetFileSize("testfiles/testenc1_orig") == sizeof(encfile)); + FileStream in("testfiles/testenc1_orig"); + int encfile_i[ENCFILE_SIZE]; + in.Read(encfile_i, sizeof(encfile_i)); + TEST_THAT(memcmp(encfile, encfile_i, sizeof(encfile)) == 0); + } + + // Check how many blocks it had, and test the stream based interface + { + FileStream enc("testfiles/testenc1_enc"); + std::auto_ptr decoded(BackupStoreFile::DecodeFileStream(enc, IOStream::TimeOutInfinite)); + CollectInBufferStream d; + decoded->CopyStreamTo(d, IOStream::TimeOutInfinite, 971 /* buffer block size */); + d.SetForReading(); + TEST_THAT(d.GetSize() == sizeof(encfile)); + TEST_THAT(memcmp(encfile, d.GetBuffer(), sizeof(encfile)) == 0); + + TEST_THAT(decoded->GetNumBlocks() == 3); + } + + // Test that the last block in a file, if less than 256 bytes, gets put into the last block + { + #define FILE_SIZE_JUST_OVER ((4096*2)+58) + FileStream f("testfiles/testenc2", O_WRONLY | O_CREAT | O_EXCL); + f.Write(encfile + 2, FILE_SIZE_JUST_OVER); + BackupStoreFilenameClear name("testenc2"); + std::auto_ptr encoded(BackupStoreFile::EncodeFile("testfiles/testenc2", 32, name)); + CollectInBufferStream e; + encoded->CopyStreamTo(e); + e.SetForReading(); + std::auto_ptr decoded(BackupStoreFile::DecodeFileStream(e, IOStream::TimeOutInfinite)); + CollectInBufferStream d; + decoded->CopyStreamTo(d, IOStream::TimeOutInfinite, 879 /* buffer block size */); + d.SetForReading(); + TEST_THAT(d.GetSize() == FILE_SIZE_JUST_OVER); + TEST_THAT(memcmp(encfile + 2, d.GetBuffer(), FILE_SIZE_JUST_OVER) == 0); + + TEST_THAT(decoded->GetNumBlocks() == 2); + } + + // Test that reordered streams work too + { + FileStream enc("testfiles/testenc1_enc"); + std::auto_ptr reordered(BackupStoreFile::ReorderFileToStreamOrder(&enc, false)); + std::auto_ptr decoded(BackupStoreFile::DecodeFileStream(*reordered, IOStream::TimeOutInfinite)); + CollectInBufferStream d; + decoded->CopyStreamTo(d, IOStream::TimeOutInfinite, 971 /* buffer block size */); + d.SetForReading(); + TEST_THAT(d.GetSize() == sizeof(encfile)); + TEST_THAT(memcmp(encfile, d.GetBuffer(), sizeof(encfile)) == 0); + + TEST_THAT(decoded->GetNumBlocks() == 3); + } + + // Try out doing this on a symlink + { + TEST_THAT(::symlink("does/not/exist", "testfiles/testsymlink") == 0); + BackupStoreFilenameClear name("testsymlink"); + std::auto_ptr encoded(BackupStoreFile::EncodeFile("testfiles/testsymlink", 32, name)); + // Can't decode it from the stream, because it's in file order, and doesn't have the + // required properties to be able to reorder it. So buffer it... + CollectInBufferStream b; + encoded->CopyStreamTo(b); + b.SetForReading(); + // Decode it + BackupStoreFile::DecodeFile(b, "testfiles/testsymlink_2", IOStream::TimeOutInfinite); + } + } + + // Store info + { + RaidFileWrite::CreateDirectory(0, "test-info"); + BackupStoreInfo::CreateNew(76, "test-info/", 0, 3461231233455433LL, 2934852487LL); + TEST_CHECK_THROWS(BackupStoreInfo::CreateNew(76, "test-info/", 0, 0, 0), RaidFileException, CannotOverwriteExistingFile); + std::auto_ptr info(BackupStoreInfo::Load(76, "test-info/", 0, true)); + TEST_CHECK_THROWS(info->Save(), BackupStoreException, StoreInfoIsReadOnly); + TEST_CHECK_THROWS(info->ChangeBlocksUsed(1), BackupStoreException, StoreInfoIsReadOnly); + TEST_CHECK_THROWS(info->ChangeBlocksInOldFiles(1), BackupStoreException, StoreInfoIsReadOnly); + TEST_CHECK_THROWS(info->ChangeBlocksInDeletedFiles(1), BackupStoreException, StoreInfoIsReadOnly); + TEST_CHECK_THROWS(info->RemovedDeletedDirectory(2), BackupStoreException, StoreInfoIsReadOnly); + TEST_CHECK_THROWS(info->AddDeletedDirectory(2), BackupStoreException, StoreInfoIsReadOnly); + } + { + std::auto_ptr info(BackupStoreInfo::Load(76, "test-info/", 0, false)); + info->ChangeBlocksUsed(8); + info->ChangeBlocksInOldFiles(9); + info->ChangeBlocksInDeletedFiles(10); + info->ChangeBlocksUsed(-1); + info->ChangeBlocksInOldFiles(-4); + info->ChangeBlocksInDeletedFiles(-9); + TEST_CHECK_THROWS(info->ChangeBlocksUsed(-100), BackupStoreException, StoreInfoBlockDeltaMakesValueNegative); + TEST_CHECK_THROWS(info->ChangeBlocksInOldFiles(-100), BackupStoreException, StoreInfoBlockDeltaMakesValueNegative); + TEST_CHECK_THROWS(info->ChangeBlocksInDeletedFiles(-100), BackupStoreException, StoreInfoBlockDeltaMakesValueNegative); + info->AddDeletedDirectory(2); + info->AddDeletedDirectory(3); + info->AddDeletedDirectory(4); + info->RemovedDeletedDirectory(3); + TEST_CHECK_THROWS(info->RemovedDeletedDirectory(9), BackupStoreException, StoreInfoDirNotInList); + info->Save(); + } + { + std::auto_ptr info(BackupStoreInfo::Load(76, "test-info/", 0, true)); + TEST_THAT(info->GetBlocksUsed() == 7); + TEST_THAT(info->GetBlocksInOldFiles() == 5); + TEST_THAT(info->GetBlocksInDeletedFiles() == 1); + TEST_THAT(info->GetBlocksSoftLimit() == 3461231233455433LL); + TEST_THAT(info->GetBlocksHardLimit() == 2934852487LL); + const std::vector &delfiles(info->GetDeletedDirectories()); + TEST_THAT(delfiles.size() == 2); + TEST_THAT(delfiles[0] == 2); + TEST_THAT(delfiles[1] == 4); + } + +//printf("SKIPPINGTESTS---------\n"); +//return 0; + + // Context + TLSContext context; + context.Initialise(false /* client */, + "testfiles/clientCerts.pem", + "testfiles/clientPrivKey.pem", + "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"); + TEST_THAT(pid != -1 && pid != 0); + if(pid > 0) + { + ::sleep(1); + TEST_THAT(ServerIsAlive(pid)); + + // BLOCK + { + // Open a connection to the server + SocketStreamTLS conn; + conn.Open(context, Socket::TypeINET, "localhost", BOX_PORT_BBSTORED); + + // Make a protocol + BackupProtocolClient protocol(conn); + + // Check the version + std::auto_ptr serverVersion(protocol.QueryVersion(BACKUP_STORE_SERVER_VERSION)); + TEST_THAT(serverVersion->GetVersion() == BACKUP_STORE_SERVER_VERSION); + + // Login + TEST_CHECK_THROWS(std::auto_ptr loginConf(protocol.QueryLogin(0x01234567, 0)), + ConnectionException, Conn_Protocol_UnexpectedReply); + + // Finish the connection + protocol.QueryFinished(); + } + + // Create an account for the test client + TEST_THAT_ABORTONFAIL(::system("../../bin/bbstoreaccounts/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(ServerIsAlive(pid)); + + TEST_THAT(test_server("localhost") == 0); + + // Test the deletion of objects by the housekeeping system + // First, things as they are now. + recusive_count_objects_results before = {0,0,0}; + + recusive_count_objects("localhost", BackupProtocolClientListDirectory::RootDirectory, before); + + TEST_THAT(before.objectsNotDel != 0); + TEST_THAT(before.deleted != 0); + TEST_THAT(before.old != 0); + + // Kill it + TEST_THAT(KillServer(pid)); + ::sleep(1); + TEST_THAT(!ServerIsAlive(pid)); + TestRemoteProcessMemLeaks("bbstored.memleaks"); + + // 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); + TestRemoteProcessMemLeaks("bbstoreaccounts.memleaks"); + + // Start things up + pid = LaunchServer("../../bin/bbstored/bbstored testfiles/bbstored.conf", "testfiles/bbstored.pid"); + ::sleep(1); + TEST_THAT(ServerIsAlive(pid)); + + // wait for housekeeping to happen + printf("waiting for housekeeping:\n"); + for(int l = 0; l < 12; ++l) + { + ::sleep(1); + printf("."); + fflush(stdout); + } + printf("\n"); + + // Count the objects again + recusive_count_objects_results after = {0,0,0}; + recusive_count_objects("localhost", BackupProtocolClientListDirectory::RootDirectory, after); + + TEST_THAT(after.objectsNotDel == before.objectsNotDel); + TEST_THAT(after.deleted == 0); + 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); + TestRemoteProcessMemLeaks("bbstoreaccounts.memleaks"); + + // Try to upload a file and create a directory, and check an error is generated + { + // Open a connection to the server + SocketStreamTLS conn; + conn.Open(context, Socket::TypeINET, "localhost", BOX_PORT_BBSTORED); + + // Make a protocol + BackupProtocolClient protocol(conn); + + // Check the version + std::auto_ptr serverVersion(protocol.QueryVersion(BACKUP_STORE_SERVER_VERSION)); + TEST_THAT(serverVersion->GetVersion() == BACKUP_STORE_SERVER_VERSION); + + // Login + std::auto_ptr loginConf(protocol.QueryLogin(0x01234567, 0)); + + int64_t modtime = 0; + + BackupStoreFilenameClear fnx("exceed-limit"); + std::auto_ptr upload(BackupStoreFile::EncodeFile("testfiles/test3", BackupProtocolClientListDirectory::RootDirectory, fnx, &modtime)); + TEST_THAT(modtime != 0); + + TEST_CHECK_THROWS(std::auto_ptr stored(protocol.QueryStoreFile( + BackupProtocolClientListDirectory::RootDirectory, + modtime, + modtime, /* use it for attr hash too */ + 0, /* diff from ID */ + fnx, + *upload)), + ConnectionException, Conn_Protocol_UnexpectedReply); + + MemBlockStream attr(&modtime, sizeof(modtime)); + BackupStoreFilenameClear fnxd("exceed-limit-dir"); + TEST_CHECK_THROWS(std::auto_ptr dirCreate(protocol.QueryCreateDirectory( + BackupProtocolClientListDirectory::RootDirectory, + 9837429842987984LL, fnxd, attr)), + ConnectionException, Conn_Protocol_UnexpectedReply); + + + // Finish the connection + protocol.QueryFinished(); + } + + // Kill it again + TEST_THAT(KillServer(pid)); + ::sleep(1); + TEST_THAT(!ServerIsAlive(pid)); + TestRemoteProcessMemLeaks("bbstored.memleaks"); + } + + return 0; +} + +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); + 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"); + TEST_THAT(pid != -1 && pid != 0); + if(pid > 0) + { + ::sleep(1); + TEST_THAT(ServerIsAlive(pid)); + + // Wait for a keypress + printf("Press ENTER to terminate the server\n"); + char line[512]; + fgets(line, 512, stdin); + printf("Terminating server...\n"); + + // Kill it + TEST_THAT(KillServer(pid)); + ::sleep(1); + TEST_THAT(!ServerIsAlive(pid)); + TestRemoteProcessMemLeaks("bbstored.memleaks"); + } + + + return 0; +} + +int test(int argc, const char *argv[]) +{ + // SSL library + SSLLib::Initialise(); + + // Give a test key for the filenames +// BackupStoreFilenameClear::SetBlowfishKey(FilenameEncodingKey, sizeof(FilenameEncodingKey)); + // And set the encoding to blowfish +// BackupStoreFilenameClear::SetEncodingMethod(BackupStoreFilename::Encoding_Blowfish); + + // And for directory attributes -- need to set it, as used in file encoding +// BackupClientFileAttributes::SetBlowfishKey(AttributesEncodingKey, sizeof(AttributesEncodingKey)); + + // And finally for file encoding +// BackupStoreFile::SetBlowfishKeys(FileEncodingKey, sizeof(FileEncodingKey), FileBlockEntryEncodingKey, sizeof(FileBlockEntryEncodingKey)); + + // Use the setup crypto command to set up all these keys, so that the bbackupquery command can be used + // for seeing what's going on. + BackupClientCryptoKeys_Setup("testfiles/bbackupd.keys"); + + // encode in some filenames -- can't do static initialisation because the key won't be set up when these are initialised + for(unsigned int l = 0; l < sizeof(ens_filenames) / sizeof(ens_filenames[0]); ++l) + { + ens[l].fn = BackupStoreFilenameClear(ens_filenames[l]); + } + for(unsigned int l = 0; l < sizeof(uploads_filenames) / sizeof(uploads_filenames[0]); ++l) + { + uploads[l].name = BackupStoreFilenameClear(uploads_filenames[l]); + } + + // Trace errors out + SET_DEBUG_SSLLIB_TRACE_ERRORS + + if(argc == 2 && strcmp(argv[1], "server") == 0) + { + return multi_server(); + } + if(argc == 3 && strcmp(argv[1], "client") == 0) + { + return test_server(argv[2]); + } +// large file test +/* { + int64_t modtime = 0; + std::auto_ptr upload(BackupStoreFile::EncodeFile("/Users/ben/temp/large.tar", + BackupProtocolClientListDirectory::RootDirectory, uploads[0].name, &modtime)); + TEST_THAT(modtime != 0); + FileStream write("testfiles/large.enc", O_WRONLY | O_CREAT); + upload->CopyStreamTo(write); + } +printf("SKIPPING TESTS ------------------------------------------------------\n"); +return 0;*/ + int r = 0; + r = test1(argc, argv); + if(r != 0) return r; + r = test2(argc, argv); + if(r != 0) return r; + r = test3(argc, argv); + if(r != 0) return r; + return 0; +} + diff --git a/test/backupstore/testextra b/test/backupstore/testextra new file mode 100755 index 00000000..798c8c67 --- /dev/null +++ b/test/backupstore/testextra @@ -0,0 +1,4 @@ +mkdir testfiles/0_0 +mkdir testfiles/0_1 +mkdir testfiles/0_2 +mkdir testfiles/bbackupd-data diff --git a/test/backupstore/testfiles/accounts.txt b/test/backupstore/testfiles/accounts.txt new file mode 100755 index 00000000..e69de29b diff --git a/test/backupstore/testfiles/bbackupd.keys b/test/backupstore/testfiles/bbackupd.keys new file mode 100644 index 00000000..4c58fc22 Binary files /dev/null and b/test/backupstore/testfiles/bbackupd.keys differ diff --git a/test/backupstore/testfiles/bbstored.conf b/test/backupstore/testfiles/bbstored.conf new file mode 100755 index 00000000..4862033b --- /dev/null +++ b/test/backupstore/testfiles/bbstored.conf @@ -0,0 +1,17 @@ + +RaidFileConf = testfiles/raidfile.conf +AccountDatabase = testfiles/accounts.txt + +ExtendedLogging = yes + +TimeBetweenHousekeeping = 10 + +Server +{ + PidFile = testfiles/bbstored.pid + ListenAddresses = inet:localhost + CertificateFile = testfiles/serverCerts.pem + PrivateKeyFile = testfiles/serverPrivKey.pem + TrustedCAsFile = testfiles/serverTrustedCAs.pem +} + diff --git a/test/backupstore/testfiles/bbstored_multi.conf b/test/backupstore/testfiles/bbstored_multi.conf new file mode 100755 index 00000000..73c70aa9 --- /dev/null +++ b/test/backupstore/testfiles/bbstored_multi.conf @@ -0,0 +1,16 @@ + +RaidFileConf = testfiles/raidfile.conf +AccountDatabase = testfiles/accounts.txt + +TimeBetweenHousekeeping = 5 + +Server +{ + PidFile = testfiles/bbstored.pid + # 0.0.0.0 is the 'any' address, allowing connections from things other than localhost + ListenAddresses = inet:0.0.0.0 + CertificateFile = testfiles/serverCerts.pem + PrivateKeyFile = testfiles/serverPrivKey.pem + TrustedCAsFile = testfiles/serverTrustedCAs.pem +} + diff --git a/test/backupstore/testfiles/clientCerts.pem b/test/backupstore/testfiles/clientCerts.pem new file mode 100644 index 00000000..c1f14fa7 --- /dev/null +++ b/test/backupstore/testfiles/clientCerts.pem @@ -0,0 +1,11 @@ +-----BEGIN CERTIFICATE----- +MIIBmDCCAQECAQMwDQYJKoZIhvcNAQEFBQAwDzENMAsGA1UEAxMEUk9PVDAeFw0w +MzEwMDcwOTAwMDRaFw0zMTAyMjIwOTAwMDRaMBoxGDAWBgNVBAMTD0JBQ0tVUC0w +MTIzNDU2NzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAvptM6A++ZdkxYN92 +OI6d0O32giRdybSdUVNJk09V1pdVJFhXr4owhtVv6d8yDnPaNOgS1LlxZ9CHcR5A +LtFwI9wmGHBc5a2uFCZGORTaSggntCythvRV3DGm/fU7mRME7Le1/tWWxjycnk2k +Rez6d7Ffj56SXDFoxY2dK8MwRasCAwEAATANBgkqhkiG9w0BAQUFAAOBgQB4D3LU +knCM4UZHMJhlbGnvc+N4O5SGrNKrHs94juMF8dPXJNgboBflkYJKNx1qDf47C/Cx +hxXjju2ucGHytNQ8kiWsz7vCzeS7Egkl0QhFcBcYVCeXNn7zc34aAUyVlLCuas2o +EGpfF4se7D3abg7J/3ioW0hx8bSal7kROleKCQ== +-----END CERTIFICATE----- diff --git a/test/backupstore/testfiles/clientPrivKey.pem b/test/backupstore/testfiles/clientPrivKey.pem new file mode 100644 index 00000000..34b1af2a --- /dev/null +++ b/test/backupstore/testfiles/clientPrivKey.pem @@ -0,0 +1,15 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICXAIBAAKBgQC+m0zoD75l2TFg33Y4jp3Q7faCJF3JtJ1RU0mTT1XWl1UkWFev +ijCG1W/p3zIOc9o06BLUuXFn0IdxHkAu0XAj3CYYcFzlra4UJkY5FNpKCCe0LK2G +9FXcMab99TuZEwTst7X+1ZbGPJyeTaRF7Pp3sV+PnpJcMWjFjZ0rwzBFqwIDAQAB +AoGAMW8Lqh/zLG0A/nPWMGLkkTw2M5iE7nw2VNI6AceQpqAHB+8VhsRbQ4z1gn1N +eSwYyqHpyFv0Co2touvKj5nn8CJfMmm571cvdOlD/n/mQsW+xZqd9WmvSE8Jh4Qq +iOQqwbwJlTYTV4BEo90qtfR+MDqffSCB8bHh4l3oO3fSp4kCQQDgbllQeq2kwlLp +81oDfrk+J7vpiq9hZ/HxFY1fZAOa6iylazZz0JSzvNAtQNLI1LeKAzBc8FuPPSG9 +qSHAKoDHAkEA2Wrziib5OgY/G86yAWVn2hPM7Ky6wGtsJxYnObXUiTwVM7lM1nZU +LpQaq//vzVDcWggqyEBTYkVcdEPYIJn3/QJBAL3e/bblowRx1p3Q4MV2L5gTG5pQ +V2HsA7c3yZv7TEWCenUUSEQhIb0SL3kpj2qS9BhR7FekjYGYcXQ4o7IlAz8CQD1B +BJxHnq/aUq1i7oO2Liwip/mGMJdFrJLWivaXY+nGI7MO4bcKX21ADMOot8cAoRQ8 +eNEyTkvBfurCsoF834ECQCPejz6x1bh/H7SeeANP17HKlwx1Lshw2JzxfF96MA26 +Eige4f0ttKHhMY/bnMcOzfPUSe/LvIN3AiMtphkl0pw= +-----END RSA PRIVATE KEY----- diff --git a/test/backupstore/testfiles/clientReq.pem b/test/backupstore/testfiles/clientReq.pem new file mode 100644 index 00000000..8eee0b5f --- /dev/null +++ b/test/backupstore/testfiles/clientReq.pem @@ -0,0 +1,10 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIIBWTCBwwIBADAaMRgwFgYDVQQDEw9CQUNLVVAtMDEyMzQ1NjcwgZ8wDQYJKoZI +hvcNAQEBBQADgY0AMIGJAoGBAL6bTOgPvmXZMWDfdjiOndDt9oIkXcm0nVFTSZNP +VdaXVSRYV6+KMIbVb+nfMg5z2jToEtS5cWfQh3EeQC7RcCPcJhhwXOWtrhQmRjkU +2koIJ7QsrYb0Vdwxpv31O5kTBOy3tf7VlsY8nJ5NpEXs+nexX4+eklwxaMWNnSvD +MEWrAgMBAAGgADANBgkqhkiG9w0BAQUFAAOBgQBtz10sGGYhbw9+7L8bOtOUV6j9 +46jnbHGXHmdBZsg8ZWgKBJQ61HwvKCNA+KAEeb9yMxWgpJRGqFk6yvPb62XXuRGl +4RQN0/6rRc8GJh3Qi4oPV1GYnzyYg2+bjZAgeMoL6ro1YuH52CTHJpQ3Arg2Ortz +xVxbWyMouzjc1g4gdw== +-----END CERTIFICATE REQUEST----- diff --git a/test/backupstore/testfiles/clientTrustedCAs.pem b/test/backupstore/testfiles/clientTrustedCAs.pem new file mode 100644 index 00000000..2a065879 --- /dev/null +++ b/test/backupstore/testfiles/clientTrustedCAs.pem @@ -0,0 +1,11 @@ +-----BEGIN CERTIFICATE----- +MIIBjDCB9gIBADANBgkqhkiG9w0BAQUFADAPMQ0wCwYDVQQDEwRST09UMB4XDTAz +MTAwNzA4NTkzMloXDTMxMDIyMjA4NTkzMlowDzENMAsGA1UEAxMEUk9PVDCBnzAN +BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAtZypR/5m5fuNMPNrSLdzwmXKqhdVZj/e +cZHUZvVuXQZboosAznDrbh8HgpuTw5vaZDEz8VfPwgIaROZDT3ztFIedLapJ7Ot9 +I4JNqSv/y3V9MKb7trTSPVvyYLqk9isLmw8wmEidJiLbWbIc2cHFXDvWNqTr2jF6 +u4Q8DvdVfAECAwEAATANBgkqhkiG9w0BAQUFAAOBgQAL1lyJ/5y44yjk2BK+tnrZ +hbK7Ghtqrq/uZ8RQq5sAme919TnPijh2tRBqSaUaD2K+Sgo3RNgUGbKhfHRU1pfM +USllHskTKiJu74ix/T3UOnjpQ946OLSl5zNsOdOgbjBDnozfPSrKeEGN0huBbmmt +SlL3iQzVXlF6NAhkzS54fQ== +-----END CERTIFICATE----- diff --git a/test/backupstore/testfiles/query.conf b/test/backupstore/testfiles/query.conf new file mode 100755 index 00000000..984ace6c --- /dev/null +++ b/test/backupstore/testfiles/query.conf @@ -0,0 +1,34 @@ + +# this is a dummy config file so that bbackupquery can be used + + +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 + +Server +{ + PidFile = testfiles/bbackupd.pid +} + +# this is just a dummy entry +BackupLocations +{ + test_delete + { + Path = testfiles/test_delete + } +} + diff --git a/test/backupstore/testfiles/raidfile.conf b/test/backupstore/testfiles/raidfile.conf new file mode 100755 index 00000000..641872b0 --- /dev/null +++ b/test/backupstore/testfiles/raidfile.conf @@ -0,0 +1,10 @@ + +disc0 +{ + SetNumber = 0 + BlockSize = 2048 + Dir0 = testfiles/0_0 + Dir1 = testfiles/0_1 + Dir2 = testfiles/0_2 +} + diff --git a/test/backupstore/testfiles/root.pem b/test/backupstore/testfiles/root.pem new file mode 100644 index 00000000..b7fa6a17 --- /dev/null +++ b/test/backupstore/testfiles/root.pem @@ -0,0 +1,26 @@ +-----BEGIN CERTIFICATE----- +MIIBjDCB9gIBADANBgkqhkiG9w0BAQUFADAPMQ0wCwYDVQQDEwRST09UMB4XDTAz +MDgyMDExNTEyN1oXDTAzMDkxOTExNTEyN1owDzENMAsGA1UEAxMEUk9PVDCBnzAN +BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAtZypR/5m5fuNMPNrSLdzwmXKqhdVZj/e +cZHUZvVuXQZboosAznDrbh8HgpuTw5vaZDEz8VfPwgIaROZDT3ztFIedLapJ7Ot9 +I4JNqSv/y3V9MKb7trTSPVvyYLqk9isLmw8wmEidJiLbWbIc2cHFXDvWNqTr2jF6 +u4Q8DvdVfAECAwEAATANBgkqhkiG9w0BAQUFAAOBgQCPbEXLzpItnnh1kUPy0vui +atzeQoTFzgEybKLqgM4irWUjUnVdcSFEJFgddABpMOlGymu/6NuqqVQR8OUUOUrk +BUlucY1m3BuCJBsADKWXVBOky4aQ7oo7BZZUh7e9NeKHfu7u1+0kvIQlTc+1Xnub +uAQzwDRZ5vAFMWzzvh5BtA== +-----END CERTIFICATE----- +-----BEGIN RSA PRIVATE KEY----- +MIICXgIBAAKBgQC1nKlH/mbl+40w82tIt3PCZcqqF1VmP95xkdRm9W5dBluiiwDO +cOtuHweCm5PDm9pkMTPxV8/CAhpE5kNPfO0Uh50tqkns630jgk2pK//LdX0wpvu2 +tNI9W/JguqT2KwubDzCYSJ0mIttZshzZwcVcO9Y2pOvaMXq7hDwO91V8AQIDAQAB +AoGBAIz2UB5lRBD2MxzvkzIZ0mvs/mUPP2Xh5RJZkndnwIXLzYxYQAP8eYA77WRe +xU5qxhRGbH7DHasEXsdjwpML8CdT9aAMRHwcUt76F5ENMOq2Zc5cnmsQeDjSiZfi +wxpixqxt3ookk4fw9LZgScJ7YQeYrHQfn4BddbV/brXMVF3BAkEA45FUmRqWMBK0 +5WIbkuZJERtOJEaYa1+9Uwqa87Vf4kTiskOGpA73h6y4Lrx97Opvfpq11aELWy01 +TcSZ0ru0zQJBAMxNdArmyVTGeO9h0wZB87sAXmG1qdZdViEXES8tSAcGS+B20nUe +k2W2UGb4tnk5M4Jzdkf03uqk9NgslgA2xAUCQQCFqU20I36FO+eON0KU1Lej2ZLb +Ea/imTgdN0Rt0mFACE/SfoDtiXDv+o2vvbyE0+mqxfn5QP7njbUaOVhUAzYdAkAO +Fl0lD0rcrJ7UKtOpP8z1nQ3lAOjIHkF9IKEPtribu2RqAud6KfSR8+NRZl72tuoF +Wb7TMWBZn6w+Z7ykISKdAkEAhoNryreYb+BAl51M/Xn60EyDBBTRgw2hyUi6xEHe +3dPZnU8YjJNd/9sXPnn8bEqSWRaUyDGEf1BFfbuoYb1c/w== +-----END RSA PRIVATE KEY----- diff --git a/test/backupstore/testfiles/root.srl b/test/backupstore/testfiles/root.srl new file mode 100644 index 00000000..eeee65ec --- /dev/null +++ b/test/backupstore/testfiles/root.srl @@ -0,0 +1 @@ +05 diff --git a/test/backupstore/testfiles/rootcert.pem b/test/backupstore/testfiles/rootcert.pem new file mode 100644 index 00000000..2a065879 --- /dev/null +++ b/test/backupstore/testfiles/rootcert.pem @@ -0,0 +1,11 @@ +-----BEGIN CERTIFICATE----- +MIIBjDCB9gIBADANBgkqhkiG9w0BAQUFADAPMQ0wCwYDVQQDEwRST09UMB4XDTAz +MTAwNzA4NTkzMloXDTMxMDIyMjA4NTkzMlowDzENMAsGA1UEAxMEUk9PVDCBnzAN +BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAtZypR/5m5fuNMPNrSLdzwmXKqhdVZj/e +cZHUZvVuXQZboosAznDrbh8HgpuTw5vaZDEz8VfPwgIaROZDT3ztFIedLapJ7Ot9 +I4JNqSv/y3V9MKb7trTSPVvyYLqk9isLmw8wmEidJiLbWbIc2cHFXDvWNqTr2jF6 +u4Q8DvdVfAECAwEAATANBgkqhkiG9w0BAQUFAAOBgQAL1lyJ/5y44yjk2BK+tnrZ +hbK7Ghtqrq/uZ8RQq5sAme919TnPijh2tRBqSaUaD2K+Sgo3RNgUGbKhfHRU1pfM +USllHskTKiJu74ix/T3UOnjpQ946OLSl5zNsOdOgbjBDnozfPSrKeEGN0huBbmmt +SlL3iQzVXlF6NAhkzS54fQ== +-----END CERTIFICATE----- diff --git a/test/backupstore/testfiles/rootkey.pem b/test/backupstore/testfiles/rootkey.pem new file mode 100644 index 00000000..7ce55861 --- /dev/null +++ b/test/backupstore/testfiles/rootkey.pem @@ -0,0 +1,15 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICXgIBAAKBgQC1nKlH/mbl+40w82tIt3PCZcqqF1VmP95xkdRm9W5dBluiiwDO +cOtuHweCm5PDm9pkMTPxV8/CAhpE5kNPfO0Uh50tqkns630jgk2pK//LdX0wpvu2 +tNI9W/JguqT2KwubDzCYSJ0mIttZshzZwcVcO9Y2pOvaMXq7hDwO91V8AQIDAQAB +AoGBAIz2UB5lRBD2MxzvkzIZ0mvs/mUPP2Xh5RJZkndnwIXLzYxYQAP8eYA77WRe +xU5qxhRGbH7DHasEXsdjwpML8CdT9aAMRHwcUt76F5ENMOq2Zc5cnmsQeDjSiZfi +wxpixqxt3ookk4fw9LZgScJ7YQeYrHQfn4BddbV/brXMVF3BAkEA45FUmRqWMBK0 +5WIbkuZJERtOJEaYa1+9Uwqa87Vf4kTiskOGpA73h6y4Lrx97Opvfpq11aELWy01 +TcSZ0ru0zQJBAMxNdArmyVTGeO9h0wZB87sAXmG1qdZdViEXES8tSAcGS+B20nUe +k2W2UGb4tnk5M4Jzdkf03uqk9NgslgA2xAUCQQCFqU20I36FO+eON0KU1Lej2ZLb +Ea/imTgdN0Rt0mFACE/SfoDtiXDv+o2vvbyE0+mqxfn5QP7njbUaOVhUAzYdAkAO +Fl0lD0rcrJ7UKtOpP8z1nQ3lAOjIHkF9IKEPtribu2RqAud6KfSR8+NRZl72tuoF +Wb7TMWBZn6w+Z7ykISKdAkEAhoNryreYb+BAl51M/Xn60EyDBBTRgw2hyUi6xEHe +3dPZnU8YjJNd/9sXPnn8bEqSWRaUyDGEf1BFfbuoYb1c/w== +-----END RSA PRIVATE KEY----- diff --git a/test/backupstore/testfiles/rootreq.pem b/test/backupstore/testfiles/rootreq.pem new file mode 100644 index 00000000..2ac6293c --- /dev/null +++ b/test/backupstore/testfiles/rootreq.pem @@ -0,0 +1,10 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIIBTjCBuAIBADAPMQ0wCwYDVQQDEwRST09UMIGfMA0GCSqGSIb3DQEBAQUAA4GN +ADCBiQKBgQC1nKlH/mbl+40w82tIt3PCZcqqF1VmP95xkdRm9W5dBluiiwDOcOtu +HweCm5PDm9pkMTPxV8/CAhpE5kNPfO0Uh50tqkns630jgk2pK//LdX0wpvu2tNI9 +W/JguqT2KwubDzCYSJ0mIttZshzZwcVcO9Y2pOvaMXq7hDwO91V8AQIDAQABoAAw +DQYJKoZIhvcNAQEFBQADgYEAarbwMXzojqzCzQLakpX8hMDiBnGb80M4au+r8MXI +g492CbH+PgpSus4g58na+1S1xAV2a7kDN6udss+OjHvukePybWUkkR6DAfXVJuxO +FrchOTv6Pwj1p4FZGzocnJ2sIp4fe+2p2ge2oAHw7EIX+1IhQUObGI/q7zEVDctK +5Fg= +-----END CERTIFICATE REQUEST----- diff --git a/test/backupstore/testfiles/serverCerts.pem b/test/backupstore/testfiles/serverCerts.pem new file mode 100644 index 00000000..92467618 --- /dev/null +++ b/test/backupstore/testfiles/serverCerts.pem @@ -0,0 +1,11 @@ +-----BEGIN CERTIFICATE----- +MIIBlzCCAQACAQQwDQYJKoZIhvcNAQEFBQAwDzENMAsGA1UEAxMEUk9PVDAeFw0w +MzEwMDcwOTAwMTFaFw0zMTAyMjIwOTAwMTFaMBkxFzAVBgNVBAMTDlNUT1JFLTAw +MDAwMDA4MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDNj1fGSCaSl/1w1lRV +I8qE6BqjvT6R0XXGdIV+dk/mHmE3NOCPcBq/gxZOYevp+QnwMc+nUSS7Px/n+q92 +cl3a8ttInfZjLqg9o/wpd6dBfH4gLTG4bEujhMt1x4bEUJk/uWfnk5FhsJXDBrlH +RJZNiS9Asme+5Zvjfz3Phy0YWwIDAQABMA0GCSqGSIb3DQEBBQUAA4GBABhmdun/ +myn3l4SbH+PxSUaW/mSvBubFhbbl9wolwhzvGCrtY968jn464JUP1UwUnnvePUU2 +SSVPZOVCvobCfM6s20aOdlKvnn+7GZkjoFONuCw3O+1hIFTSyXFcJWBaYLuczVk1 +HfdIKKcVZ1CpAfnMhMxuu+nA7fjor4p1/K0t +-----END CERTIFICATE----- diff --git a/test/backupstore/testfiles/serverPrivKey.pem b/test/backupstore/testfiles/serverPrivKey.pem new file mode 100644 index 00000000..fd87607d --- /dev/null +++ b/test/backupstore/testfiles/serverPrivKey.pem @@ -0,0 +1,15 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICXQIBAAKBgQDNj1fGSCaSl/1w1lRVI8qE6BqjvT6R0XXGdIV+dk/mHmE3NOCP +cBq/gxZOYevp+QnwMc+nUSS7Px/n+q92cl3a8ttInfZjLqg9o/wpd6dBfH4gLTG4 +bEujhMt1x4bEUJk/uWfnk5FhsJXDBrlHRJZNiS9Asme+5Zvjfz3Phy0YWwIDAQAB +AoGBAI88mjo1noM528Wb4+nr5bvVDHMadJYhccMXAMqNYMGGW9GfS/dHc6wNiSaX +P0+rVIyF+R+rAEBmDTKV0Vxk9xZQuAaDKjLluDkxSxSR869D2YOWYUfvjDo3OFlT +LMZf0eE7u/3Pm0MtxPctXszqvNnmb+IvPXzttGRgUfU5G+tJAkEA+IphkGMI4A3l +4KfxotZZU+HiJbRDFpm81RzCc2709KCMkXMEz/+xkvnqlo28jqOf7PRBeq/ecsZN +8BGvtyoqVQJBANO6uj6sPI66GaRqxV83VyUUdMmL9uFOccIMqW5q0rx5UDi0mG7t +Pjjz+ul1D247+dvVxnEBeW4C85TSNbbKR+8CQQChpV7PCZo8Hs3jz1bZEZAHfmIX +I6Z+jH7EHHBbo06ty72g263FmgdkECcCxCxemQzqj/IGWVvUSiVmfhpKhqIBAkAl +XbjswpzVW4aW+7jlevDIPHn379mcHan54x4rvHKAjLBZsZWNThVDG9vWQ7B7dd48 +q9efrfDuN1shko+kOMLFAkAGIc5w0bJNC4eu91Wr6AFgTm2DntyVQ9keVhYbrwrE +xY37dgVhAWVeLDOk6eVOVSYqEI1okXPVqvfOIoRJUYkn +-----END RSA PRIVATE KEY----- diff --git a/test/backupstore/testfiles/serverReq.pem b/test/backupstore/testfiles/serverReq.pem new file mode 100644 index 00000000..7475d406 --- /dev/null +++ b/test/backupstore/testfiles/serverReq.pem @@ -0,0 +1,10 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIIBWDCBwgIBADAZMRcwFQYDVQQDEw5TVE9SRS0wMDAwMDAwODCBnzANBgkqhkiG +9w0BAQEFAAOBjQAwgYkCgYEAzY9Xxkgmkpf9cNZUVSPKhOgao70+kdF1xnSFfnZP +5h5hNzTgj3Aav4MWTmHr6fkJ8DHPp1Ekuz8f5/qvdnJd2vLbSJ32Yy6oPaP8KXen +QXx+IC0xuGxLo4TLdceGxFCZP7ln55ORYbCVwwa5R0SWTYkvQLJnvuWb4389z4ct +GFsCAwEAAaAAMA0GCSqGSIb3DQEBBQUAA4GBAIdlFo8gbik1K/+4Ra87cQDZzn0L +wE9bZrxRMPXqGjCQ8HBCfvQMFa1Oc6fEczCJ/nmmd76j0HIXW7uYOELIT8L/Zvf5 +jw/z9/OvEOQal7H2JN2d6W4ZmYpQko5+e/bJmlrOxyBpcXk34BvyQen9pTmI6J4E +pkBN/5XUUvVJSM67 +-----END CERTIFICATE REQUEST----- diff --git a/test/backupstore/testfiles/serverTrustedCAs.pem b/test/backupstore/testfiles/serverTrustedCAs.pem new file mode 100644 index 00000000..2a065879 --- /dev/null +++ b/test/backupstore/testfiles/serverTrustedCAs.pem @@ -0,0 +1,11 @@ +-----BEGIN CERTIFICATE----- +MIIBjDCB9gIBADANBgkqhkiG9w0BAQUFADAPMQ0wCwYDVQQDEwRST09UMB4XDTAz +MTAwNzA4NTkzMloXDTMxMDIyMjA4NTkzMlowDzENMAsGA1UEAxMEUk9PVDCBnzAN +BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAtZypR/5m5fuNMPNrSLdzwmXKqhdVZj/e +cZHUZvVuXQZboosAznDrbh8HgpuTw5vaZDEz8VfPwgIaROZDT3ztFIedLapJ7Ot9 +I4JNqSv/y3V9MKb7trTSPVvyYLqk9isLmw8wmEidJiLbWbIc2cHFXDvWNqTr2jF6 +u4Q8DvdVfAECAwEAATANBgkqhkiG9w0BAQUFAAOBgQAL1lyJ/5y44yjk2BK+tnrZ +hbK7Ghtqrq/uZ8RQq5sAme919TnPijh2tRBqSaUaD2K+Sgo3RNgUGbKhfHRU1pfM +USllHskTKiJu74ix/T3UOnjpQ946OLSl5zNsOdOgbjBDnozfPSrKeEGN0huBbmmt +SlL3iQzVXlF6NAhkzS54fQ== +-----END CERTIFICATE----- -- cgit v1.2.3