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 NotMaster errors include a TopologyVersion field.
*
* @tags: [requires_fcv_44]
*/
(function() {
"use strict";
const rst = new ReplSetTest({nodes: 1});
rst.startSet();
rst.initiate();
const dbName = "test";
const collName = "notmaster_errors_return_topology_version";
const primary = rst.getPrimary();
const primaryDB = primary.getDB(dbName);
const notMasterErrorCodes = [
ErrorCodes.InterruptedDueToReplStateChange,
ErrorCodes.NotMaster,
ErrorCodes.NotMasterNoSlaveOk,
ErrorCodes.NotMasterOrSecondary,
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 NotMaster errors should return TopologyVersion in the response.
if (notMasterErrorCodes.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 NotMaster errors should return TopologyVersion in the response.
if (notMasterErrorCodes.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"}));
}
notMasterErrorCodes.forEach(function(code) {
runFailInCommandDispatch(code, true /* isWCError */);
runFailInCommandDispatch(code, false /* isWCError */);
});
// Test that errors that are not NotMaster errors will not return a TopologyVersion.
otherErrorCodes.forEach(function(code) {
runFailInCommandDispatch(code, true /* isWCError */);
runFailInCommandDispatch(code, false /* isWCError */);
});
notMasterErrorCodes.forEach(function(code) {
runFailInRunCommand(code);
});
otherErrorCodes.forEach(function(code) {
runFailInRunCommand(code);
});
rst.stopSet();
})();
|