Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 0 additions & 6 deletions C/tests/c4ObserverTest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
34 changes: 22 additions & 12 deletions C/tests/c4Test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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];

Expand Down Expand Up @@ -189,21 +180,22 @@ 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");
kRev3ID = C4STR("3-deadbeef");
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);
}
Expand Down Expand Up @@ -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);
Expand Down
20 changes: 6 additions & 14 deletions C/tests/c4Test.hh
Original file line number Diff line number Diff line change
Expand Up @@ -171,22 +171,13 @@ void C4ExpectException(C4ErrorDomain domain, int code, const std::function<void(
/// and closes & deletes it in tearDown. Also checks for leaks of classes that are InstanceCounted.
class C4Test {
public:
enum TestOptions { RevTreeOption = 0, VersionVectorOption, EncryptedRevTreeOption };
enum TestOptions { VersionVectorOption = 0, EncryptedVersionVectorOption };
#if defined(COUCHBASE_ENTERPRISE)
# if SkipVersionVectorTest
static constexpr int numberOfOptions = 2; // rev-tree, rev-tree encrypted
static constexpr const char* nameOfOption[numberOfOptions] = {"RevTree", "EncryptedRevTree"};
# else
static constexpr int numberOfOptions = 3; // rev-tree, version vector, rev-tree encrypted
static constexpr const char* nameOfOption[numberOfOptions] = {"RevTree", "VersionVector", "EncryptedRevTree"};
# endif
static constexpr int numberOfOptions = 2; // See nameOfOption
static constexpr const char* nameOfOption[numberOfOptions] = {"VersionVector", "EncryptedVersionVector"};
#else
# if SkipVersionVectorTest
static constexpr int numberOfOptions = 1; // rev-tree
# else
static constexpr int numberOfOptions = 2; // rev-tree, version vector
# endif
static constexpr const char* nameOfOption[2] = {"RevTree", "VersionVector"};
static constexpr int numberOfOptions = 1; // rev-tree
static constexpr const char* nameOfOption[numberOfOptions] = {"VersionVector"};
#endif

static std::string sFixturesDir; // directory where test files live
Expand Down Expand Up @@ -240,6 +231,7 @@ class C4Test {
/// Closes `db`, adds `kC4DB_VersionVectors` to config, and reopens.
void upgradeToVersionVectors(bool fakeClock = false);
void upgradeToVersionVectors(C4Database*&, bool fakeClock = false);
void resetDBToRevTrees(C4Database*&);

static C4Collection* createCollection(C4Database* db, C4CollectionSpec spec);
static C4Collection* getCollection(C4Database* db, C4CollectionSpec spec, bool mustExist = true);
Expand Down
11 changes: 8 additions & 3 deletions Replicator/tests/ReplicatorAPITest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
#include "c4Internal.hh"
#include "fleece/Fleece.hh"
#include "SequenceSet.hh"
#include "SourceID.hh"
#include "VersionVector.hh"

using namespace fleece;
using namespace std;
Expand Down Expand Up @@ -263,11 +265,14 @@ TEST_CASE_METHOD(ReplicatorAPITest, "API Loopback Push & Pull Deletion", "[C][Pu
c4::ref<C4Document> 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]") {
Expand Down
4 changes: 0 additions & 4 deletions Replicator/tests/ReplicatorLoopbackTest.hh
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
21 changes: 20 additions & 1 deletion Replicator/tests/ReplicatorVVUpgradeTest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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]") {
Expand All @@ -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 --------");
Expand All @@ -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 --------");
Expand All @@ -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 --------");
Expand All @@ -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 --------");
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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();

Expand Down Expand Up @@ -420,4 +439,4 @@ TEST_CASE_METHOD(ReplicatorVVUpgradeTest, "Resolve Conflicts After VV Upgrade",
} else {
CHECK(slice(finalDoc->selectedRev.revID).findByte('*'));
}
}
}