summaryrefslogtreecommitdiff
path: root/jstests/noPassthrough/oplog_writes_only_permitted_on_standalone.js
blob: 23ca9da88f3d2875a8630490aa5d802064f64848 (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
/**
 * Tests that oplog writes are forbidden on replica set members. In standalone mode, it is permitted
 * to insert oplog entries, which will be applied during replication recovery. This behavior is
 * needed for point-in-time restores, which are supported on 4.2+.
 * @tags: [
 *   requires_persistence,
 *   requires_replication,
 * ]
 */
(function() {
"use strict";

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

let conn = rst.getPrimary();
assert.commandWorked(
    conn.getDB("test").coll.insert({_id: 0, a: 0}, {writeConcern: {w: "majority"}}));

let oplog = conn.getDB("local").oplog.rs;

// Construct a valid oplog entry.
function constructOplogEntry(oplog) {
    const lastOplogEntry = oplog.find().sort({ts: -1}).limit(1).toArray()[0];
    const testCollOplogEntry =
        oplog.find({op: "i", ns: "test.coll"}).sort({ts: -1}).limit(1).toArray()[0];
    const highestTS = lastOplogEntry.ts;
    const toInsertTS = Timestamp(highestTS.getTime(), highestTS.getInc() + 1);
    return Object.extend(
        testCollOplogEntry,
        {op: "u", ns: "test.coll", o: {$set: {a: 1}}, o2: {_id: 0}, ts: toInsertTS});
}

let toInsert = constructOplogEntry(oplog);
jsTestLog("Test that oplog writes are banned when replication is enabled.");
assert.commandFailedWithCode(oplog.insert(toInsert), ErrorCodes.InvalidNamespace);

jsTestLog("Restart the node in standalone mode.");
rst.stop(0, undefined /*signal*/, undefined /*opts*/, {forRestart: true});
conn = rst.start(0, {noReplSet: true, noCleanData: true});

oplog = conn.getDB("local").oplog.rs;
// Construct a valid oplog entry using the highest timestamp in the oplog. The highest timestamp may
// differ from the one above due to concurrent internal writes when the node was a primary.
toInsert = constructOplogEntry(oplog);
jsTestLog(`Test that oplog writes are permitted in standalone mode. Inserting oplog entry: ${
    tojson(toInsert)}`);
assert.commandWorked(oplog.insert(toInsert));

jsTestLog("Restart the node with replication enabled.");
rst.stop(0, undefined /*signal*/, undefined /*opts*/, {forRestart: true});
rst.start(0, {noCleanData: true});
conn = rst.getPrimary();

jsTestLog("The added oplog entry is applied as part of replication recovery.");
assert.eq({_id: 0, a: 1}, conn.getDB("test").coll.findOne());

rst.stopSet();
}());