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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
|
/**
* Tests the "requireApiVersion" mongod/mongos parameter.
*
* This test is incompatible with parallel and passthrough suites; concurrent jobs fail while
* requireApiVersion is true.
*
* @tags: [
* requires_journaling,
* requires_replication,
* requires_transactions,
* ]
*/
(function() {
"use strict";
function runTest(db, supportsTransctions, writeConcern = {}, secondaries = []) {
assert.commandWorked(db.runCommand({setParameter: 1, requireApiVersion: true}));
for (const secondary of secondaries) {
assert.commandWorked(secondary.adminCommand({setParameter: 1, requireApiVersion: true}));
}
assert.commandFailedWithCode(db.runCommand({ping: 1}), 498870, "command without apiVersion");
assert.commandWorked(db.runCommand({ping: 1, apiVersion: "1"}));
assert.commandFailed(db.runCommand({ping: 1, apiVersion: "not a real API version"}));
// Create a collection and do some writes with writeConcern majority.
const collName = "testColl";
assert.commandWorked(db.runCommand({create: collName, apiVersion: "1", writeConcern}));
assert.commandWorked(db.runCommand(
{insert: collName, documents: [{a: 1, b: 2}], apiVersion: "1", writeConcern}));
// User management commands loop back into the system so make sure they set apiVersion
// internally
assert.commandWorked(db.adminCommand(
{createRole: 'testRole', apiVersion: "1", writeConcern, privileges: [], roles: []}));
assert.commandWorked(db.adminCommand({dropRole: 'testRole', apiVersion: "1", writeConcern}));
/*
* "getMore" accepts apiVersion.
*/
assert.commandWorked(db.runCommand(
{insert: "collection", documents: [{}, {}, {}], apiVersion: "1", writeConcern}));
let reply = db.runCommand({find: "collection", batchSize: 1, apiVersion: "1"});
assert.commandWorked(reply);
assert.commandFailedWithCode(
db.runCommand({getMore: reply.cursor.id, collection: "collection"}), 498870);
assert.commandWorked(
db.runCommand({getMore: reply.cursor.id, collection: "collection", apiVersion: "1"}));
if (supportsTransctions) {
/*
* Commands in transactions require API version.
*/
const session = db.getMongo().startSession({causalConsistency: false});
const sessionDb = session.getDatabase(db.getName());
assert.commandFailedWithCode(sessionDb.runCommand({
find: "collection",
batchSize: 1,
txnNumber: NumberLong(0),
stmtId: NumberInt(2),
startTransaction: true,
autocommit: false
}),
498870);
reply = sessionDb.runCommand({
find: "collection",
batchSize: 1,
apiVersion: "1",
txnNumber: NumberLong(1),
stmtId: NumberInt(0),
startTransaction: true,
autocommit: false
});
assert.commandWorked(reply);
assert.commandFailedWithCode(sessionDb.runCommand({
getMore: reply.cursor.id,
collection: "collection",
txnNumber: NumberLong(1),
stmtId: NumberInt(1),
autocommit: false
}),
498870);
assert.commandWorked(sessionDb.runCommand({
getMore: reply.cursor.id,
collection: "collection",
txnNumber: NumberLong(1),
stmtId: NumberInt(1),
autocommit: false,
apiVersion: "1"
}));
assert.commandFailedWithCode(
sessionDb.runCommand(
{commitTransaction: 1, txnNumber: NumberLong(1), autocommit: false}),
498870);
assert.commandWorked(sessionDb.runCommand(
{commitTransaction: 1, apiVersion: "1", txnNumber: NumberLong(1), autocommit: false}));
// Start a new txn so we can test abortTransaction.
reply = sessionDb.runCommand({
find: "collection",
apiVersion: "1",
txnNumber: NumberLong(2),
stmtId: NumberInt(0),
startTransaction: true,
autocommit: false
});
assert.commandWorked(reply);
assert.commandFailedWithCode(
sessionDb.runCommand(
{abortTransaction: 1, txnNumber: NumberLong(2), autocommit: false}),
498870);
assert.commandWorked(sessionDb.runCommand(
{abortTransaction: 1, apiVersion: "1", txnNumber: NumberLong(2), autocommit: false}));
}
assert.commandWorked(
db.runCommand({setParameter: 1, requireApiVersion: false, apiVersion: "1"}));
for (const secondary of secondaries) {
assert.commandWorked(
secondary.adminCommand({setParameter: 1, requireApiVersion: false, apiVersion: "1"}));
}
assert.commandWorked(db.runCommand({ping: 1}));
}
function requireApiVersionOnShardOrConfigServerTest() {
assert.throws(
() => MongoRunner.runMongod(
{shardsvr: "", replSet: "dummy", setParameter: {"requireApiVersion": true}}),
[],
"mongod should not be able to start up with --shardsvr and requireApiVersion=true");
assert.throws(
() => MongoRunner.runMongod({configsvr: "", setParameter: {"requireApiVersion": 1}}),
[],
"mongod should not be able to start up with --configsvr and requireApiVersion=true");
const rs = new ReplSetTest({nodes: 1});
rs.startSet({shardsvr: ""});
rs.initiate();
const singleNodeShard = rs.getPrimary();
assert.neq(null, singleNodeShard, "mongod was not able to start up");
assert.commandFailed(
singleNodeShard.adminCommand({setParameter: 1, requireApiVersion: true}),
"should not be able to set requireApiVersion=true on mongod that was started with --shardsvr");
rs.stopSet();
const configsvrRS = new ReplSetTest({nodes: 1});
configsvrRS.startSet({configsvr: ""});
configsvrRS.initiate();
const configsvrConn = configsvrRS.getPrimary();
assert.neq(null, configsvrConn, "mongod was not able to start up");
assert.commandFailed(
configsvrConn.adminCommand({setParameter: 1, requireApiVersion: 1}),
"should not be able to set requireApiVersion=true on mongod that was started with --configsvr");
configsvrRS.stopSet();
}
requireApiVersionOnShardOrConfigServerTest();
const mongod = MongoRunner.runMongod();
runTest(mongod.getDB("admin"), false /* supportsTransactions */);
MongoRunner.stopMongod(mongod);
const rst = new ReplSetTest({nodes: 3});
rst.startSet();
rst.initiateWithHighElectionTimeout();
runTest(rst.getPrimary().getDB("admin"),
true /* supportsTransactions */,
{w: "majority"} /* writeConcern */,
rst.getSecondaries());
rst.stopSet();
const st = new ShardingTest({});
runTest(st.s0.getDB("admin"), true /* supportsTransactions */);
st.stop();
}());
|