summaryrefslogtreecommitdiff
path: root/jstests/replsets/not_primary_errors_returned_during_rollback_if_helloOk.js
blob: 55a97e1d32f194fc31130bda91301b9410b0abd2 (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
/*
 * Tests that reads that fail during rollback with a NotPrimaryError will replace their
 * "not master" error messages with "not primary" if the client sends "helloOk:true" as a part
 * of their isMaster request.
 *
 * In practice, drivers will send "helloOk: true" in the initial handshake when
 * opening a connection to the database.
 * @tags: [requires_majority_read_concern]
 */

(function() {
"use strict";

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

const dbName = "test";
const collName = "not_primary_errors_returned_during_rollback_if_helloOk";

// Set up Rollback Test.
let rollbackTest = new RollbackTest();

// Insert a document to be read later.
assert.commandWorked(rollbackTest.getPrimary().getDB(dbName)[collName].insert({}));

let rollbackNode = rollbackTest.transitionToRollbackOperations();

const failPointAfterTransition =
    configureFailPoint(rollbackNode, "rollbackHangAfterTransitionToRollback");

// Start rollback.
rollbackTest.transitionToSyncSourceOperationsBeforeRollback();
rollbackTest.transitionToSyncSourceOperationsDuringRollback();

jsTestLog("Reconnecting to " + rollbackNode.host + " after rollback");
reconnect(rollbackNode.getDB(dbName));

// Wait for rollback to hang. We continuously retry the wait command since the rollback node
// might reject new connections initially, causing the command to fail.
assert.soon(() => {
    try {
        failPointAfterTransition.wait();
        return true;
    } catch (e) {
        return false;
    }
});

// Make sure we can't read during rollback. Since we want to exercise the real check for
// primary in the 'find' command, we have to disable the best-effort check for primary in service
// entry point.
configureFailPoint(rollbackNode, "skipCheckingForNotPrimaryInCommandDispatch");
jsTestLog("Reading during rollback returns not master error message");
let res = assert.commandFailedWithCode(rollbackNode.getDB(dbName).runCommand({"find": collName}),
                                       ErrorCodes.NotPrimaryOrSecondary,
                                       "find did not fail with NotPrimaryOrSecondary");

// Since we did not send "helloOk: true", the error message should include "not master or
// secondary".
assert(res.errmsg.includes("not master or secondary"), res);

// An isMaster response will not contain "helloOk: true" if the client does not send
// helloOk in the request.
res = assert.commandWorked(rollbackNode.getDB(dbName).adminCommand({isMaster: 1}));
assert.eq(res.helloOk, undefined);

// Run the isMaster command with "helloOk: true" on the secondary.
res = assert.commandWorked(rollbackNode.getDB(dbName).adminCommand({isMaster: 1, helloOk: true}));
// The response should contain "helloOk: true", which indicates to the client that the
// server supports the hello command.
assert.eq(res.helloOk, true);

jsTestLog("Reading during rollback returns not primary error message");
res = assert.commandFailedWithCode(rollbackNode.getDB(dbName).runCommand({"find": collName}),
                                   ErrorCodes.NotPrimaryOrSecondary,
                                   "find did not fail with NotPrimaryOrSecondary");
// Since we sent "helloOk: true", the error message should include "not primary or secondary".
assert(res.errmsg.includes("not primary or secondary"), res);
assert(!res.errmsg.includes("not master"), res);

failPointAfterTransition.off();

rollbackTest.transitionToSteadyStateOperations();
rollbackTest.stop();
}());