summaryrefslogtreecommitdiff
path: root/jstests/replsets/notprimary_errors_return_topology_version.js
blob: 8ce214fba1ca1dd260e3c49629630ca8deb2047f (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
/**
 * This tests that NotPrimary errors include a TopologyVersion field. (Note that shutdown errors
 * include a TopologyVersion field when the server is in quiesce mode. This is tested in
 * quiesce_mode.js)
 */

(function() {
"use strict";

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

const dbName = "test";
const collName = "notprimary_errors_return_topology_version";
const primary = rst.getPrimary();
const primaryDB = primary.getDB(dbName);

const notPrimaryErrorCodes = [
    ErrorCodes.InterruptedDueToReplStateChange,
    ErrorCodes.NotWritablePrimary,
    ErrorCodes.NotPrimaryNoSecondaryOk,
    ErrorCodes.NotPrimaryOrSecondary,
    ErrorCodes.PrimarySteppedDown
];

const otherErrorCodes =
    [ErrorCodes.InterruptedAtShutdown, ErrorCodes.ShutdownInProgress, ErrorCodes.InternalError];

function runFailInCommandDispatch(errorCode, isWCError) {
    jsTestLog(`Testing with errorCode: ${
        errorCode} with failPoint: failWithErrorCodeInCommandDispatch, isWCError: ${isWCError}.`);

    if (isWCError) {
        assert.commandWorked(primary.adminCommand({
            configureFailPoint: "failCommand",
            mode: "alwaysOn",
            data: {
                writeConcernError: {code: NumberInt(errorCode), errmsg: "dummy"},
                failCommands: ["insert"],
            }
        }));
    } else {
        assert.commandWorked(primary.adminCommand({
            configureFailPoint: "failCommand",
            mode: "alwaysOn",
            data: {
                errorCode: NumberInt(errorCode),
                failCommands: ["insert"],
            }
        }));
    }

    const res = primaryDB.runCommand({insert: collName, documents: [{x: 1}]});
    assert.commandFailedWithCode(res, errorCode);
    // Only NotPrimary errors should return TopologyVersion in the response.
    if (notPrimaryErrorCodes.includes(errorCode)) {
        assert(res.hasOwnProperty("topologyVersion"), tojson(res));
    } else {
        assert(!res.hasOwnProperty("topologyVersion"), tojson(res));
    }
    assert.commandWorked(primary.adminCommand({configureFailPoint: "failCommand", mode: "off"}));
}

function runFailInRunCommand(errorCode) {
    jsTestLog(
        `Testing with errorCode: ${errorCode} with failPoint: failWithErrorCodeInRunCommand.`);

    assert.commandWorked(primary.adminCommand({
        configureFailPoint: "failWithErrorCodeInRunCommand",
        mode: "alwaysOn",
        data: {
            errorCode: NumberInt(errorCode),
        }
    }));

    const res = primaryDB.runCommand({insert: collName, documents: [{x: 1}]});
    assert.commandFailedWithCode(res, errorCode);
    // Only NotPrimary errors should return TopologyVersion in the response.
    if (notPrimaryErrorCodes.includes(errorCode)) {
        assert(res.hasOwnProperty("topologyVersion"), tojson(res));
    } else {
        assert(!res.hasOwnProperty("topologyVersion"), tojson(res));
    }
    // We expect 'configureFailPoint' to succeed here since the 'failWithErrorCodeInRunCommand' fail
    // point only affects commands that support writeConcern.
    assert.commandWorked(
        primary.adminCommand({configureFailPoint: "failWithErrorCodeInRunCommand", mode: "off"}));
}

notPrimaryErrorCodes.forEach(function(code) {
    runFailInCommandDispatch(code, true /* isWCError */);
    runFailInCommandDispatch(code, false /* isWCError */);
});

// Test that errors that are not NotPrimary errors will not return a TopologyVersion.
otherErrorCodes.forEach(function(code) {
    runFailInCommandDispatch(code, true /* isWCError */);
    runFailInCommandDispatch(code, false /* isWCError */);
});

notPrimaryErrorCodes.forEach(function(code) {
    runFailInRunCommand(code);
});
otherErrorCodes.forEach(function(code) {
    runFailInRunCommand(code);
});
rst.stopSet();
})();