Skip to content

Commit 917e177

Browse files
authored
Fix transaction tests by using a client per mongos (#599)
1 parent 49d9ae4 commit 917e177

File tree

3 files changed

+34
-18
lines changed

3 files changed

+34
-18
lines changed

Sources/TestsCommon/CommonTestUtils.swift

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,11 +137,20 @@ open class MongoSwiftTestCase: XCTestCase {
137137

138138
/// Enumerates the different topology configurations that are used throughout the tests
139139
public enum TestTopologyConfiguration: String, Decodable {
140+
/// A sharded topology where each shard is a standalone.
140141
case sharded
142+
/// A replica set.
141143
case replicaSet = "replicaset"
144+
/// A sharded topology where each shard is a replica set.
142145
case shardedReplicaSet = "sharded-replicaset"
146+
/// A standalone server.
143147
case single
144148

149+
/// Returns a Bool indicating whether this topology is either sharded configuration.
150+
public var isSharded: Bool {
151+
self == .sharded || self == .shardedReplicaSet
152+
}
153+
145154
/// Determines the topologyType of a client based on the reply returned by running an isMaster command and the
146155
/// first document in the config.shards collection.
147156
public init(isMasterReply: BSONDocument, shards: [BSONDocument]) throws {

Tests/MongoSwiftSyncTests/SpecTestRunner/SpecTest.swift

Lines changed: 24 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -182,9 +182,12 @@ extension SpecTestFile {
182182
}
183183
}
184184

185-
func terminateOpenTransactions(using client: MongoSwiftSync.MongoClient) throws {
186-
// Using the provided MongoClient, execute the killAllSessions command on either the primary or, if
187-
// connected to a sharded cluster, all mongos servers.
185+
func terminateOpenTransactions(
186+
using client: MongoSwiftSync.MongoClient,
187+
mongosClients: [MongoSwiftSync.MongoClient]?
188+
) throws {
189+
// if connected to a replica set, use the provided client to execute killAllSessions on the primary.
190+
// if connected to a sharded cluster, use the per-mongos clients to execute killAllSessions on each mongos.
188191
switch try client.topologyType() {
189192
case .single:
190193
return
@@ -196,12 +199,11 @@ extension SpecTestFile {
196199
_ = try client.db("admin").runCommand(["killAllSessions": []], options: opts)
197200
} catch let commandError as MongoError.CommandError where commandError.code == 11601 {}
198201
case .sharded, .shardedReplicaSet:
199-
for address in MongoSwiftTestCase.getHosts() {
202+
for mongosClient in mongosClients! {
200203
do {
201-
_ = try client.db("admin").runCommand(["killAllSessions": []], on: address)
202-
} catch let commandError as MongoError.CommandError where commandError.code == 11601 {
203-
continue
204-
}
204+
_ = try mongosClient.db("admin").runCommand(["killAllSessions": []])
205+
break
206+
} catch let commandError as MongoError.CommandError where commandError.code == 11601 {}
205207
}
206208
}
207209
}
@@ -229,25 +231,30 @@ extension SpecTestFile {
229231
}
230232
}
231233

234+
let topologyType = try setupClient.topologyType()
235+
236+
var mongosClients: [MongoClient]?
237+
if topologyType.isSharded {
238+
var opts = setupClientOptions
239+
opts.directConnection = true // connect directly to mongoses
240+
mongosClients = try MongoSwiftTestCase.getConnectionStringPerHost()
241+
.map { try MongoClient.makeTestClient($0.toString(), options: opts) }
242+
}
243+
232244
fileLevelLog("Executing tests from file \(self.name)...")
233245
for var test in self.tests {
234246
if let keyword = Self.TestType.skippedTestKeywords.first(where: { test.description.contains($0) }) {
235247
print("Skipping test \(test.description) due to matched keyword \"\(keyword)\".")
236248
continue
237249
}
238-
239-
try self.terminateOpenTransactions(using: setupClient)
250+
try self.terminateOpenTransactions(using: setupClient, mongosClients: mongosClients)
240251
try self.populateData(using: setupClient)
241252

242253
// Due to strange behavior in mongos, a "distinct" command needs to be run against each mongos
243254
// before the tests run to prevent certain errors from ocurring. (SERVER-39704)
244-
if MongoSwiftTestCase.topologyType == .sharded,
245-
let collName = self.collectionName,
246-
test.description.contains("distinct")
247-
{
248-
for address in MongoSwiftTestCase.getHosts() {
249-
_ = try setupClient.db(self.databaseName)
250-
.runCommand(["distinct": .string(collName), "key": "_id"], on: address)
255+
if topologyType.isSharded, test.description.contains("distinct"), let collName = self.collectionName {
256+
for client in mongosClients! {
257+
_ = try client.db(self.databaseName).runCommand(["distinct": .string(collName), "key": "_id"])
251258
}
252259
}
253260

Tests/MongoSwiftSyncTests/UnifiedTestRunner/UnifiedTestRunner.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ struct UnifiedTestRunner {
152152
// Workaround for SERVER-39704: a test runners MUST execute a non-transactional distinct command on
153153
// each mongos server before running any test that might execute distinct within a transaction. To ease
154154
// the implementation, test runners MAY execute distinct before every test.
155-
if self.topologyType == .sharded || self.topologyType == .shardedReplicaSet {
155+
if self.topologyType.isSharded {
156156
let collEntities = context.entities.values.compactMap { try? $0.asCollection() }
157157
for address in MongoSwiftTestCase.getHosts() {
158158
for entity in collEntities {

0 commit comments

Comments
 (0)