Skip to content

Commit 64931e2

Browse files
authored
SWIFT-1327 add a prose test for SDAM monitoring in load balancer mode (#672)
1 parent c534ae9 commit 64931e2

File tree

2 files changed

+117
-13
lines changed

2 files changed

+117
-13
lines changed

Tests/LinuxMain.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -299,7 +299,8 @@ extension RetryableWritesTests {
299299

300300
extension SDAMTests {
301301
static var allTests = [
302-
("testMonitoring", testMonitoring),
302+
("testMonitoringStandalone", testMonitoringStandalone),
303+
("testMonitoringLoadBalanced", testMonitoringLoadBalanced),
303304
("testInitialReplicaSetDiscovery", testInitialReplicaSetDiscovery),
304305
]
305306
}

Tests/MongoSwiftSyncTests/SDAMTests.swift

Lines changed: 115 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -16,16 +16,7 @@ final class SDAMTests: MongoSwiftTestCase {
1616
expect(desc.passives).to(haveCount(0))
1717
}
1818

19-
// Basic test based on the "standalone" spec test for SDAM monitoring:
20-
// swiftlint:disable line_length
21-
// https://github.com/mongodb/specifications/blob/master/source/server-discovery-and-monitoring/tests/monitoring/standalone.json
22-
// swiftlint:enable line_length
23-
func testMonitoring() throws {
24-
guard MongoSwiftTestCase.topologyType == .single else {
25-
print(unsupportedTopologyMessage(testName: self.name))
26-
return
27-
}
28-
19+
func captureInitialSDAMEvents() throws -> [SDAMEvent] {
2920
let monitor = TestSDAMMonitor()
3021
let client = try MongoClient.makeTestClient()
3122
client.addSDAMEventHandler(monitor)
@@ -37,10 +28,22 @@ final class SDAMTests: MongoSwiftTestCase {
3728
try db.drop()
3829
}
3930

40-
let receivedEvents = monitor.events().filter { !$0.isHeartbeatEvent }
31+
return monitor.events().filter { !$0.isHeartbeatEvent }
32+
}
4133

42-
let connString = MongoSwiftTestCase.getConnectionString()
34+
// Basic test based on the "standalone" spec test for SDAM monitoring:
35+
// swiftlint:disable line_length
36+
// https://github.com/mongodb/specifications/blob/master/source/server-discovery-and-monitoring/tests/monitoring/standalone.json
37+
// swiftlint:enable line_length
38+
func testMonitoringStandalone() throws {
39+
guard MongoSwiftTestCase.topologyType == .single else {
40+
print(unsupportedTopologyMessage(testName: self.name))
41+
return
42+
}
43+
44+
let receivedEvents = try captureInitialSDAMEvents()
4345

46+
let connString = MongoSwiftTestCase.getConnectionString()
4447
guard let hostAddress = connString.hosts?[0] else {
4548
XCTFail("Could not get hosts for uri: \(MongoSwiftTestCase.getConnectionString())")
4649
return
@@ -95,6 +98,106 @@ final class SDAMTests: MongoSwiftTestCase {
9598
self.checkEmptyLists(newTopology.servers[0])
9699
}
97100

101+
// Prose test based on the load balncer spec test for SDAM monitoring:
102+
// swiftlint:disable line_length
103+
// https://github.com/mongodb/specifications/blob/master/source/server-discovery-and-monitoring/tests/monitoring/load_balancer.yml
104+
// swiftlint:enable line_length
105+
func testMonitoringLoadBalanced() throws {
106+
guard MongoSwiftTestCase.topologyType == .loadBalanced else {
107+
print(unsupportedTopologyMessage(testName: self.name))
108+
return
109+
}
110+
111+
let receivedEvents = try captureInitialSDAMEvents()
112+
113+
let connString = MongoSwiftTestCase.getConnectionString()
114+
guard let hostAddress = connString.hosts?[0] else {
115+
XCTFail("Could not get hosts for uri: \(MongoSwiftTestCase.getConnectionString())")
116+
return
117+
}
118+
119+
guard receivedEvents.count == 5 else {
120+
XCTFail("Expected to receive 5 events, but instead received \(receivedEvents.count)")
121+
return
122+
}
123+
guard let topologyOpening = receivedEvents[0].topologyOpeningValue else {
124+
XCTFail("Expected event to be a topologyOpening event, but instead got \(receivedEvents[0])")
125+
return
126+
}
127+
guard let topologyChanged1 = receivedEvents[1].topologyDescriptionChangedValue else {
128+
XCTFail(
129+
"Expected event to be a topologyDescriptionChanged event, but instead got \(receivedEvents[1])"
130+
)
131+
return
132+
}
133+
guard let serverOpening = receivedEvents[2].serverOpeningValue else {
134+
XCTFail("Expected event to be a serverOpening event, but instead got \(receivedEvents[2])")
135+
return
136+
}
137+
guard let serverChanged = receivedEvents[3].serverDescriptionChangedValue else {
138+
XCTFail(
139+
"Expected event to be a serverDescriptionChanged event, but instead got \(receivedEvents[3])"
140+
)
141+
return
142+
}
143+
guard let topologyChanged2 = receivedEvents[4].topologyDescriptionChangedValue else {
144+
XCTFail(
145+
"Expected event to be a topologyDescriptionChanged event, but instead got \(receivedEvents[4])"
146+
)
147+
return
148+
}
149+
150+
// all events should have the same topology ID.
151+
expect(topologyChanged1.topologyID).to(equal(topologyOpening.topologyID))
152+
expect(serverOpening.topologyID).to(equal(topologyOpening.topologyID))
153+
expect(serverChanged.topologyID).to(equal(topologyOpening.topologyID))
154+
expect(topologyChanged2.topologyID).to(equal(topologyOpening.topologyID))
155+
156+
// initial change from unknown, no servers to loadBalanced, no servers. This is slightly different than what
157+
// the test linked above expects (that test expects the new server to show up here, too, with unknown type).
158+
// we don't see it here because `mongoc_topology_description_get_servers` excludes servers with type "unknown",
159+
// so until the server type changes to "loadBalancer" it won't show up in events.
160+
expect(topologyChanged1.previousDescription.type).to(equal(.unknown))
161+
expect(topologyChanged1.previousDescription.servers).to(beEmpty())
162+
expect(topologyChanged1.newDescription.type).to(equal(.loadBalanced))
163+
expect(topologyChanged1.newDescription.servers).to(beEmpty())
164+
165+
// the server discovered should be the single one in the connection string.
166+
expect(serverOpening.serverAddress).to(equal(hostAddress))
167+
// the change should be to the same server.
168+
expect(serverChanged.serverAddress).to(equal(hostAddress))
169+
// the server should change from type unknown to loadBalancer.
170+
expect(serverChanged.previousDescription.address).to(equal(hostAddress))
171+
expect(serverChanged.previousDescription.arbiters).to(beEmpty())
172+
expect(serverChanged.previousDescription.hosts).to(beEmpty())
173+
expect(serverChanged.previousDescription.passives).to(beEmpty())
174+
expect(serverChanged.previousDescription.type).to(equal(.unknown))
175+
176+
expect(serverChanged.newDescription.address).to(equal(hostAddress))
177+
expect(serverChanged.newDescription.arbiters).to(beEmpty())
178+
expect(serverChanged.newDescription.hosts).to(beEmpty())
179+
expect(serverChanged.newDescription.passives).to(beEmpty())
180+
expect(serverChanged.newDescription.type).to(equal(.loadBalancer))
181+
182+
// finally, the topology should change to include the newly opened and discovered server.
183+
expect(topologyChanged2.previousDescription.type).to(equal(.loadBalanced))
184+
expect(topologyChanged2.previousDescription.servers).to(beEmpty())
185+
186+
expect(topologyChanged2.newDescription.type).to(equal(.loadBalanced))
187+
guard topologyChanged2.newDescription.servers.count == 1 else {
188+
XCTFail(
189+
"Expected new topology description to contain 1 server, " +
190+
"but found \(topologyChanged2.newDescription.servers)"
191+
)
192+
return
193+
}
194+
expect(topologyChanged2.newDescription.servers[0].address).to(equal(hostAddress))
195+
expect(topologyChanged2.newDescription.servers[0].arbiters).to(beEmpty())
196+
expect(topologyChanged2.newDescription.servers[0].hosts).to(beEmpty())
197+
expect(topologyChanged2.newDescription.servers[0].passives).to(beEmpty())
198+
expect(topologyChanged2.newDescription.servers[0].type).to(equal(.loadBalancer))
199+
}
200+
98201
func testInitialReplicaSetDiscovery() throws {
99202
guard MongoSwiftTestCase.topologyType == .replicaSetWithPrimary else {
100203
print(unsupportedTopologyMessage(testName: self.name))

0 commit comments

Comments
 (0)