summaryrefslogtreecommitdiff
path: root/jstests/noPassthrough/preimages_can_be_inconsistent.js
blob: f658c6940d9edecd591537137a8a41c05aae5464 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
/**
 * Test that consistency checks for preimage work as expected. Consistency is defined by performing
 * these steps:
 *   * Fix a nsUUID to scan the preimage collection
 *   * Obtain all preimage entries of the namespace by sorting in descending order of '_id.ts' and
 *     '_id.applyIndexOps'.
 *   * For each entry position and node:
 *     * The entry exists in the node at that position and is equal across all nodes in that
 *       position.
 *     * The entry doesn't exist in the node at that position.
 * @tags: [
 *   requires_replication,
 * ]
 */

(function() {
"use strict";

function getPreImage(collectionIndex, ts) {
    const farOffDate = ISODate("2100-01-01");
    const epochSeconds = farOffDate.valueOf() / 1000;
    // Return a document inserted with a date really far off into the future.
    return {
        _id: {
            nsUUID: UUID(`3b241101-e2bb-4255-8caf-4136c566a12${collectionIndex}`),
            ts: new Timestamp(epochSeconds, ts),
            applyOpsIndex: 0,
        },
        operationTime: farOffDate,
    };
}

assert.doesNotThrow(() => {
    const replSetTest = new ReplSetTest({name: "replSet", nodes: 2});
    replSetTest.startSet();
    replSetTest.initiate();

    const primary = replSetTest.getPrimary();
    const secondary = replSetTest.getSecondary();

    const coll = primary.getDB("config")["system.preimages"];
    const secondaryColl = secondary.getDB("config")["system.preimages"];

    // Insert documents to the preimages collection. Ensure they are not replicated to secondaries.
    coll.insert(getPreImage(1, 0));
    coll.insert(getPreImage(1, 1));
    coll.insert(getPreImage(2, 1));
    coll.insert(getPreImage(3, 1));

    assert.eq(coll.find({}).itcount(), 4);
    assert.eq(secondaryColl.find({}).itcount(), 0);

    // Now insert preimages in the old secondary.
    replSetTest.stepUp(secondary);

    const newPrimary = replSetTest.getPrimary();
    const newColl = newPrimary.getDB("config")["system.preimages"];
    newColl.insert(getPreImage(1, 1));
    newColl.insert(getPreImage(2, 1));

    // Verify that even if the data isn't consistent the test passes as consistency is defined as
    // two nodes having entries equal or non-existent starting from the end.
    replSetTest.stopSet();
});

const replSetTest = new ReplSetTest({name: "replSet", nodes: 2});
replSetTest.startSet();
replSetTest.initiate();

const primary = replSetTest.getPrimary();
const secondary = replSetTest.getSecondary();

const coll = primary.getDB("config")["system.preimages"];
const secondaryColl = secondary.getDB("config")["system.preimages"];

// Insert a document to the preimage collection. Ensure it is not replicated to secondaries.
coll.insert(getPreImage(1, 0));
assert.eq(coll.find({}).itcount(), 1);
assert.eq(secondaryColl.find({}).itcount(), 0);

// Now insert another document to the secondary, this will cause an inconsistency error when we stop
// the replica set.
replSetTest.stepUp(secondary);

const newPrimary = replSetTest.getPrimary();

const newColl = newPrimary.getDB("config")["system.preimages"];
newColl.insert(getPreImage(1, 1));

// Verify that the two nodes are inconsistent.
assert.throws(() => replSetTest.stopSet());

try {
    replSetTest.stopSet();
} catch (e) {
    // Verify that the inconsistency is the one we're looking for in preimages.
    assert.eq(e.message.includes("Detected preimage entries that have different content"), true);
}
// Tear down the nodes now without checking for consistency.
replSetTest.stopSet(undefined, undefined, {skipCheckDBHashes: true});
})();