From b0675f33396d87ec3da8e5af6015dde3502fe842 Mon Sep 17 00:00:00 2001 From: Kaitlin Mahar Date: Fri, 12 Aug 2022 15:21:45 -0400 Subject: [PATCH] sync unified change streams test, remove legacy tests --- .../SyncChangeStreamTests.swift | 301 +-- .../tests/legacy/change-streams-errors.json | 153 -- .../change-streams-resume-allowlist.json | 1750 ------------ .../change-streams-resume-errorLabels.json | 1652 ------------ .../tests/legacy/change-streams.json | 795 ------ .../tests/unified/change-streams-errors.json | 246 ++ .../tests/unified/change-streams-errors.yml | 120 + .../change-streams-pre_and_post_images.json | 827 ++++++ .../change-streams-pre_and_post_images.yml | 351 +++ .../change-streams-resume-allowlist.json | 2348 +++++++++++++++++ .../change-streams-resume-allowlist.yml | 1169 ++++++++ .../change-streams-resume-errorLabels.json | 2130 +++++++++++++++ .../change-streams-resume-errorLabels.yml | 1069 ++++++++ .../change-streams-showExpandedEvents.json | 509 ++++ .../change-streams-showExpandedEvents.yml | 297 +++ 15 files changed, 9074 insertions(+), 4643 deletions(-) delete mode 100644 Tests/Specs/change-streams/tests/legacy/change-streams-errors.json delete mode 100644 Tests/Specs/change-streams/tests/legacy/change-streams-resume-allowlist.json delete mode 100644 Tests/Specs/change-streams/tests/legacy/change-streams-resume-errorLabels.json delete mode 100644 Tests/Specs/change-streams/tests/legacy/change-streams.json create mode 100644 Tests/Specs/change-streams/tests/unified/change-streams-errors.json create mode 100644 Tests/Specs/change-streams/tests/unified/change-streams-errors.yml create mode 100644 Tests/Specs/change-streams/tests/unified/change-streams-pre_and_post_images.json create mode 100644 Tests/Specs/change-streams/tests/unified/change-streams-pre_and_post_images.yml create mode 100644 Tests/Specs/change-streams/tests/unified/change-streams-resume-allowlist.json create mode 100644 Tests/Specs/change-streams/tests/unified/change-streams-resume-allowlist.yml create mode 100644 Tests/Specs/change-streams/tests/unified/change-streams-resume-errorLabels.json create mode 100644 Tests/Specs/change-streams/tests/unified/change-streams-resume-errorLabels.yml create mode 100644 Tests/Specs/change-streams/tests/unified/change-streams-showExpandedEvents.json create mode 100644 Tests/Specs/change-streams/tests/unified/change-streams-showExpandedEvents.yml diff --git a/Tests/MongoSwiftSyncTests/SyncChangeStreamTests.swift b/Tests/MongoSwiftSyncTests/SyncChangeStreamTests.swift index c624719aa..8e922799a 100644 --- a/Tests/MongoSwiftSyncTests/SyncChangeStreamTests.swift +++ b/Tests/MongoSwiftSyncTests/SyncChangeStreamTests.swift @@ -3,309 +3,24 @@ import Nimble import TestsCommon import XCTest -/// The entity on which to start a change stream. -internal enum ChangeStreamTarget: String, Decodable { - /// Indicates the change stream will be opened to watch a client. - case client - - /// Indicates the change stream will be opened to watch a database. - case database - - /// Indicates the change stream will be opened to watch a collection. - case collection - - /// Open a change stream against this target. An error will be thrown if the necessary namespace information is not - /// provided. - internal func watch( - _ client: MongoClient, - _ database: String?, - _ collection: String?, - _ pipeline: [BSONDocument], - _ options: ChangeStreamOptions - ) throws -> ChangeStream { - switch self { - case .client: - return try client.watch(pipeline, options: options, withEventType: BSONDocument.self) - case .database: - guard let database = database else { - throw TestError(message: "missing db in watch") - } - return try client.db(database).watch(pipeline, options: options, withEventType: BSONDocument.self) - case .collection: - guard let collection = collection, let database = database else { - throw TestError(message: "missing db or collection in watch") - } - return try client.db(database) - .collection(collection) - .watch(pipeline, options: options, withEventType: BSONDocument.self) - } - } -} - -/// An operation performed as part of a `ChangeStreamTest` (e.g. a CRUD operation, an drop, etc.) -/// This struct includes the namespace against which it should be run. -internal struct ChangeStreamTestOperation: Decodable { - /// The operation itself to run. - private let operation: AnyTestOperation - - /// The database to run the operation against. - private let database: String - - /// The collection to run the operation against. - private let collection: String - - private enum CodingKeys: String, CodingKey { - case database, collection - } - - public init(from decoder: Decoder) throws { - let container = try decoder.container(keyedBy: CodingKeys.self) - self.database = try container.decode(String.self, forKey: .database) - self.collection = try container.decode(String.self, forKey: .collection) - self.operation = try AnyTestOperation(from: decoder) - } - - /// Run the operation against the namespace associated with this operation. - internal func execute(using client: MongoClient) throws -> TestOperationResult? { - let db = client.db(self.database) - let coll = db.collection(self.collection) - return try self.operation.op.execute(on: coll, sessions: [:]) - } -} - -/// The outcome of a given `ChangeStreamTest`. -internal enum ChangeStreamTestResult: Decodable { - /// Describes an error received during the test - case error(code: Int, labels: [String]?) - - /// An array of event documents expected to be received from the change stream without error during the test. - case success([BSONDocument]) - - /// Top-level coding keys. Used for determining whether this result is a success or failure. - internal enum CodingKeys: CodingKey { - case error, success - } - - /// Coding keys used specifically for decoding the `.error` case. - internal enum ErrorCodingKeys: CodingKey { - case code, errorLabels - } - - /// Asserts that the given error matches the one expected by this result. - internal func assertMatchesError(error: Error, description: String) { - guard case let .error(code, labels) = self else { - fail("\(description) failed: got error but result success") - return - } - guard let seenError = error as? MongoError.CommandError else { - fail("\(description) failed: didn't get command error") - return - } - - expect(seenError.code).to(equal(code), description: description) - if let labels = labels { - expect(seenError.errorLabels).toNot(beNil(), description: description) - expect(seenError.errorLabels).to(equal(labels), description: description) - } - } - - public init(from decoder: Decoder) throws { - let container = try decoder.container(keyedBy: CodingKeys.self) - if container.contains(.success) { - self = .success(try container.decode([BSONDocument].self, forKey: .success)) - } else { - let nested = try container.nestedContainer(keyedBy: ErrorCodingKeys.self, forKey: .error) - let code = try nested.decode(Int.self, forKey: .code) - let labels = try nested.decodeIfPresent([String].self, forKey: .errorLabels) - self = .error(code: code, labels: labels) - } - } -} - -/// Struct representing a single test within a spec test JSON file. -internal struct ChangeStreamTest: Decodable, FailPointConfigured { - /// The title of this test. - let description: String - - /// The minimum server version that this test can be run against. - let minServerVersion: ServerVersion - - /// The maximum server version that this test can be run against. - let maxServerVersion: ServerVersion? - - /// The fail point that should be set prior to running this test. - let failPoint: FailPoint? - - /// The entity on which to run the change stream. - let target: ChangeStreamTarget - - /// An array of server topologies against which to run the test. - let topology: [TestTopologyConfiguration] - - /// An array of additional aggregation pipeline stages to pass to the `watch` used to create the change stream for - /// this test. - let changeStreamPipeline: [BSONDocument] - - /// Additional options to pass to the `watch` used to create the change stream for this test. - let changeStreamOptions: ChangeStreamOptions - - /// An array of documents, each describing an operation that should be run as part of this test. - let operations: [ChangeStreamTestOperation] - - /// A list of command-started events that are expected to have been emitted by the client that starts the change - /// stream for this test. - let expectations: [TestCommandStartedEvent]? - - // The expected result of running this test. - let result: ChangeStreamTestResult - - var activeFailPoint: FailPoint? - var targetedHost: ServerAddress? - - internal mutating func run(globalClient: MongoClient, database: String, collection: String) throws { - let client = try MongoClient.makeTestClient() - let monitor = client.addCommandMonitor() - - if let failPoint = self.failPoint { - try failPoint.enable(using: globalClient) - } - defer { self.failPoint?.disable(using: globalClient) } - - monitor.captureEvents { - do { - let changeStream = try self.target.watch( - client, - database, - collection, - self.changeStreamPipeline, - self.changeStreamOptions - ) - for operation in self.operations { - _ = try operation.execute(using: globalClient) - } - - switch self.result { - case .error: - _ = try changeStream.nextWithTimeout() - fail("\(self.description) failed: expected error but got none while iterating") - case let .success(events): - var seenEvents: [BSONDocument] = [] - for _ in 0..