summaryrefslogtreecommitdiff
path: root/jstests/noPassthrough/shell_gossip_cluster_time.js
blob: c9a47ce6ce77b2b3fb7aa262cd97c27141b3485c (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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
/**
 * Tests that the mongo shell gossips the greater of the client's clusterTime and the session's
 * clusterTime.
 * @tags: [requires_replication]
 */
(function() {
"use strict";

load("jstests/replsets/rslib.js");

const rst = new ReplSetTest({nodes: 1});
rst.startSet();
rst.initiate();

const primary = rst.getPrimary();

const session1 = primary.startSession();
const session2 = primary.startSession();

const db = primary.getDB("test");
const coll = db.shell_gossip_cluster_time;

function testCommandGossipedWithClusterTime(func, expectedClusterTime) {
    const mongoRunCommandOriginal = Mongo.prototype.runCommand;

    const sentinel = {};
    let cmdObjSeen = sentinel;

    Mongo.prototype.runCommand = function runCommandSpy(dbName, cmdObj, options) {
        cmdObjSeen = cmdObj;
        return mongoRunCommandOriginal.apply(this, arguments);
    };

    try {
        assert.doesNotThrow(func);
    } finally {
        Mongo.prototype.runCommand = mongoRunCommandOriginal;
    }

    if (cmdObjSeen === sentinel) {
        throw new Error("Mongo.prototype.runCommand() was never called: " + func.toString());
    }

    if (expectedClusterTime === undefined) {
        assert(!cmdObjSeen.hasOwnProperty("$clusterTime"),
               "Expected operation " + tojson(cmdObjSeen) +
                   " to not have a $clusterTime object: " + func.toString());
    } else {
        assert(cmdObjSeen.hasOwnProperty("$clusterTime"),
               "Expected operation " + tojson(cmdObjSeen) +
                   " to have a $clusterTime object: " + func.toString());

        assert(bsonBinaryEqual(expectedClusterTime, cmdObjSeen.$clusterTime));
    }
}

assert(session1.getClusterTime() === undefined,
       "session1 has yet to be used, but has clusterTime: " + tojson(session1.getClusterTime()));
assert(session2.getClusterTime() === undefined,
       "session2 has yet to be used, but has clusterTime: " + tojson(session2.getClusterTime()));

// Advance the clusterTime outside of either of the sessions.
testCommandGossipedWithClusterTime(function() {
    assert.commandWorked(coll.insert({}));
}, primary.getClusterTime());

assert(session1.getClusterTime() === undefined,
       "session1 has yet to be used, but has clusterTime: " + tojson(session1.getClusterTime()));
assert(session2.getClusterTime() === undefined,
       "session2 has yet to be used, but has clusterTime: " + tojson(session2.getClusterTime()));

// Performing an operation with session1 should use the highest clusterTime seen by the client
// since session1 hasn't been used yet.
testCommandGossipedWithClusterTime(function() {
    const coll = session1.getDatabase("test").mycoll;
    assert.commandWorked(coll.insert({}));
}, primary.getClusterTime());

assert.eq(session1.getClusterTime(), primary.getClusterTime());

testCommandGossipedWithClusterTime(function() {
    const coll = session1.getDatabase("test").mycoll;
    assert.commandWorked(coll.insert({}));
}, session1.getClusterTime());

assert(session2.getClusterTime() === undefined,
       "session2 has yet to be used, but has clusterTime: " + tojson(session2.getClusterTime()));

primary.resetClusterTime_forTesting();
assert(primary.getClusterTime() === undefined,
       "client's cluster time should have been reset, but has clusterTime: " +
           tojson(primary.getClusterTime()));

// Performing an operation with session2 should use the highest clusterTime seen by session2
// since the client's clusterTime has been reset.
session2.advanceClusterTime(session1.getClusterTime());
testCommandGossipedWithClusterTime(function() {
    const coll = session2.getDatabase("test").mycoll;
    assert.commandWorked(coll.insert({}));
}, session2.getClusterTime());

assert.eq(session2.getClusterTime(), primary.getClusterTime());

primary.resetClusterTime_forTesting();
assert(primary.getClusterTime() === undefined,
       "client's cluster time should have been reset, but has clusterTime: " +
           tojson(primary.getClusterTime()));

// Performing an operation with session2 should use the highest clusterTime seen by session2
// since the highest clusterTime seen by session1 is behind that of session2's.
primary.advanceClusterTime(session1.getClusterTime());
testCommandGossipedWithClusterTime(function() {
    const coll = session2.getDatabase("test").mycoll;
    assert.commandWorked(coll.insert({}));
}, session2.getClusterTime());

rst.stopSet();
})();