diff --git a/C/tests/c4ObserverTest.cc b/C/tests/c4ObserverTest.cc index 086ac3d32..030296142 100644 --- a/C/tests/c4ObserverTest.cc +++ b/C/tests/c4ObserverTest.cc @@ -40,12 +40,6 @@ class C4ObserverTest : public C4Test { } } -#if SkipVersionVectorTest - static constexpr int numberOfOptions = 1; -#else - static constexpr int numberOfOptions = 2; // rev-tree, vector; no need to test encryption -#endif - ~C4ObserverTest() { c4docobs_free(docObserver); c4dbobs_free(dbObserver); diff --git a/C/tests/c4Test.cc b/C/tests/c4Test.cc index 04de41668..dc62a2d03 100644 --- a/C/tests/c4Test.cc +++ b/C/tests/c4Test.cc @@ -132,16 +132,7 @@ string C4Test::sReplicatorFixturesDir = "Replicator/tests/data/"; C4Test::C4Test(int num) : _storage(kC4SQLiteStorageEngine) { // NOLINT(cppcoreguidelines-pro-type-member-init) - constexpr static TestOptions numToTestOption[] = { -#if SkipVersionVectorTest - RevTreeOption, - EncryptedRevTreeOption -#else - RevTreeOption, - VersionVectorOption, - EncryptedRevTreeOption -#endif - }; + constexpr static TestOptions numToTestOption[] = {VersionVectorOption, EncryptedVersionVectorOption}; static_assert(sizeof(numToTestOption) / sizeof(TestOptions) >= numberOfOptions); TestOptions testOption = numToTestOption[num]; @@ -189,13 +180,14 @@ C4Test::C4Test(int num) : _storage(kC4SQLiteStorageEngine) { // NOLINT(cppcoreg objectCount = c4_getObjectCount(); _dbConfig = {slice(TempDir()), kC4DB_Create}; - if ( testOption == VersionVectorOption ) { + if ( testOption == VersionVectorOption || testOption == EncryptedVersionVectorOption ) { _dbConfig.flags |= kC4DB_VersionVectors | kC4DB_FakeVectorClock; kRev1ID = kRevID = kRev1ID_Alt = C4STR("1@*"); kRev2ID = C4STR("2@*"); kRev3ID = C4STR("3@*"); kRev4ID = C4STR("4@*"); } else { + Assert(false, "Unsupported option"); kRev1ID = kRevID = C4STR("1-abcd"); kRev1ID_Alt = C4STR("1-dcba"); kRev2ID = C4STR("2-c001d00d"); @@ -203,7 +195,7 @@ C4Test::C4Test(int num) : _storage(kC4SQLiteStorageEngine) { // NOLINT(cppcoreg kRev4ID = C4STR("4-44444444"); } - if ( testOption == EncryptedRevTreeOption ) { + if ( testOption == EncryptedVersionVectorOption ) { _dbConfig.encryptionKey.algorithm = kC4EncryptionAES256; memcpy(_dbConfig.encryptionKey.bytes, "this is not a random key at all.", kC4EncryptionKeySizeAES256); } @@ -333,6 +325,24 @@ void C4Test::upgradeToVersionVectors(bool fakeClock) { syncDBConfig(); } +void C4Test::resetDBToRevTrees(C4Database*& database) { + C4DatabaseConfig2 config = dbConfig(); + Assert((config.flags & kC4DB_VersionVectors), "db already uses Rev Trees"); + + alloc_slice name(c4db_getName(database)); + REQUIRE(c4db_close(database, WITH_ERROR())); + c4db_release(database); + database = nullptr; + C4Error error{}; + if ( !c4db_deleteNamed(name, config.parentDirectory, ERROR_INFO(&error)) ) Require(error.code == 0); + + C4Log("---- Reopening '%.*s' with version vectors ---", FMTSLICE(name)); + config.flags &= ~kC4DB_VersionVectors; + config.flags &= ~kC4DB_FakeVectorClock; + database = c4db_openNamed(name, &config, ERROR_INFO()); + REQUIRE(database); +} + /*static*/ C4Collection* C4Test::createCollection(C4Database* db, C4CollectionSpec spec) { auto coll = c4db_createCollection(db, spec, ERROR_INFO()); Require(coll); diff --git a/C/tests/c4Test.hh b/C/tests/c4Test.hh index 52a5a17ef..522dd05fc 100644 --- a/C/tests/c4Test.hh +++ b/C/tests/c4Test.hh @@ -171,22 +171,13 @@ void C4ExpectException(C4ErrorDomain domain, int code, const std::function doc = c4coll_getDoc(defaultColl, "doc"_sl, true, kDocGetAll, nullptr); REQUIRE(doc); - CHECK(doc->revID == kRev2ID); + alloc_slice dbSourceID = c4db_getSourceID(db); + auto pair = split2(string_view(slice(kRev2ID)), string_view("@")); + REQUIRE(!pair.second.empty()); + string rev2ID = string(pair.first) + "@" + dbSourceID.asString(); + + CHECK(slice(doc->revID) == slice(rev2ID)); CHECK((doc->flags & kDocDeleted) != 0); CHECK((doc->selectedRev.flags & kRevDeleted) != 0); - REQUIRE(c4doc_selectParentRevision(doc)); - CHECK(doc->selectedRev.revID == kRevID); } TEST_CASE_METHOD(ReplicatorAPITest, "Per Collection Context Documents Ended", "[Pull][Sync]") { diff --git a/Replicator/tests/ReplicatorLoopbackTest.hh b/Replicator/tests/ReplicatorLoopbackTest.hh index 5d19017d1..4a1cc7c9b 100644 --- a/Replicator/tests/ReplicatorLoopbackTest.hh +++ b/Replicator/tests/ReplicatorLoopbackTest.hh @@ -53,11 +53,7 @@ class ReplicatorLoopbackTest slice kNonLocalRev1ID, kNonLocalRev2ID, kNonLocalRev3ID, kConflictRev2AID, kConflictRev2BID; -#if SkipVersionVectorTest static constexpr int numberOfOptions = 1; -#else - static constexpr int numberOfOptions = 2; -#endif ReplicatorLoopbackTest(int which) : C4Test(which), db2(createDatabase("2")) { // Change tuning param so that tests will actually create deltas, despite using small diff --git a/Replicator/tests/ReplicatorVVUpgradeTest.cc b/Replicator/tests/ReplicatorVVUpgradeTest.cc index 2d2271c42..94c064ebb 100644 --- a/Replicator/tests/ReplicatorVVUpgradeTest.cc +++ b/Replicator/tests/ReplicatorVVUpgradeTest.cc @@ -59,6 +59,15 @@ class ReplicatorVVUpgradeTest : public ReplicatorLoopbackTest { upgradeToVersionVectors(db2, fakeClock); _collDB2 = createCollection(db2, _collSpec); } + + /// Reopens both databases, enabling version vectors in both. + void resetDBsToRevTrees() { + resetDBToRevTrees(db); + _collDB1 = createCollection(db, _collSpec); + resetDBToRevTrees(db2); + _collDB2 = createCollection(db2, _collSpec); + syncDBConfig(); + } }; TEST_CASE_METHOD(ReplicatorVVUpgradeTest, "Push After VV Upgrade", "[Push][Upgrade]") { @@ -69,6 +78,7 @@ TEST_CASE_METHOD(ReplicatorVVUpgradeTest, "Push After VV Upgrade", "[Push][Upgra auto serverOpts = Replicator::Options::passive(_collSpec); + resetDBsToRevTrees(); importJSONLines(sFixturesDir + "names_100.json", _collDB1); _expectedDocumentCount = 100; Log("-------- First Replication --------"); @@ -94,6 +104,7 @@ TEST_CASE_METHOD(ReplicatorVVUpgradeTest, "Pull After VV Upgrade", "[Pull][Upgra //- db updates two of the docs it pushed, and creates a new one. //- db pushes to db2 again. + resetDBsToRevTrees(); importJSONLines(sFixturesDir + "names_100.json", _collDB1); _expectedDocumentCount = 100; Log("-------- First Replication --------"); @@ -112,6 +123,7 @@ TEST_CASE_METHOD(ReplicatorVVUpgradeTest, "Pull After VV Upgrade", "[Pull][Upgra } TEST_CASE_METHOD(ReplicatorVVUpgradeTest, "Push and Pull New Docs After VV Upgrade", "[Push][Pull][Upgrade]") { + resetDBsToRevTrees(); populateAndSync(); Log("-------- Create a doc in each db --------"); @@ -127,6 +139,7 @@ TEST_CASE_METHOD(ReplicatorVVUpgradeTest, "Push and Pull New Docs After VV Upgra } TEST_CASE_METHOD(ReplicatorVVUpgradeTest, "Push and Pull Existing Docs After VV Upgrade", "[Push][Pull][Upgrade]") { + resetDBsToRevTrees(); populateAndSync(); Log("-------- Update existing doc in each db --------"); @@ -188,6 +201,7 @@ TEST_CASE_METHOD(ReplicatorVVUpgradeTest, "Resolve Rev-Tree Conflicts After VV U default: throw logic_error("unreachable"); } + resetDBsToRevTrees(); DYNAMIC_SECTION("" << sectionName) { createFleeceRev(_collDB1, docName, "1-1111"_sl, "{}"_sl); @@ -235,6 +249,8 @@ TEST_CASE_METHOD(ReplicatorVVUpgradeTest, "Resolve Mixed Conflicts After VV Upgr const alloc_slice kDoc1Rev2B = makeRealishVector("@BobBobBobBobBobBobBobA"); const alloc_slice kDoc1RevRTE = makeRealishVector("@Revision+Tree+Encoding"); + resetDBsToRevTrees(); + createFleeceRev(_collDB1, docName, "1-1111"_sl, "{}"_sl); slice winner, loser, body, resultingRevID; @@ -364,6 +380,9 @@ TEST_CASE_METHOD(ReplicatorVVUpgradeTest, "Resolve Mixed Conflicts After VV Upgr TEST_CASE_METHOD(ReplicatorVVUpgradeTest, "Resolve Conflicts After VV Upgrade", "[Conflicts][Upgrade][Pull]") { const auto docName = "test"_sl; + + resetDBsToRevTrees(); + upgrade(); syncDBConfig(); @@ -420,4 +439,4 @@ TEST_CASE_METHOD(ReplicatorVVUpgradeTest, "Resolve Conflicts After VV Upgrade", } else { CHECK(slice(finalDoc->selectedRev.revID).findByte('*')); } -} \ No newline at end of file +}