From 494e1c6c08408764b8890812651ade6b0a17f3bd Mon Sep 17 00:00:00 2001 From: Patrick Freed Date: Fri, 18 Oct 2019 18:02:55 -0400 Subject: [PATCH 1/4] add swiftformat to project --- .swiftformat | 36 +++++++++++++++++++++++++++ .swiftlint.yml | 1 + .travis.yml | 17 ++++++------- Tests/.swiftformat | 2 ++ Tests/Scripts/install_dependencies.sh | 9 ++++++- 5 files changed, 55 insertions(+), 10 deletions(-) create mode 100644 .swiftformat create mode 100644 Tests/.swiftformat diff --git a/.swiftformat b/.swiftformat new file mode 100644 index 000000000..7a82801c9 --- /dev/null +++ b/.swiftformat @@ -0,0 +1,36 @@ +--exclude Sources/MongoSwift/MongoSwiftVersion.swift + +# unnecessary +--disable andOperator + +# put #if to the first column +--ifdef "outdent" + +# 4 spaces +--indent 4 + +# 0..<3 vs 0 ..< 3 +--ranges "no-space" + +# always want explicit acl +--disable redundantExtensionACL + +# always want explicit self +--self insert + +# don't need semicolons +--semicolons "never" + +--disable trailingCommas + +# first element of collection on newline after opening brace/bracket +--wrapcollections "before-first" + +# put first argument on its own line +--wraparguments "before-first" + +# if x == 1 vs if 1 == x +--disable yodaConditions + +# the ordering doesn't match linter's +--disable specifiers diff --git a/.swiftlint.yml b/.swiftlint.yml index de7cabd02..b972c8b14 100644 --- a/.swiftlint.yml +++ b/.swiftlint.yml @@ -53,6 +53,7 @@ excluded: - Package.swift - Examples/*/Package.swift - Tests/LinuxMain.swift + - SwiftFormat trailing_whitespace: ignores_comments: false diff --git a/.travis.yml b/.travis.yml index 244a7f80b..0df76d149 100644 --- a/.travis.yml +++ b/.travis.yml @@ -19,6 +19,14 @@ jobs: - make linuxmain SOURCERY=${PWD}/sourcery/bin/sourcery - git diff --exit-code Tests/LinuxMain.swift + - stage: pre-tests + name: lint + os: osx + osx_image: xcode11.1 + install: ./Tests/Scripts/install_dependencies.sh swiftlint && ./Tests/Scripts/install_dependencies.sh swiftformat + before_script: skip + script: ${PWD}/swiftlint/swiftlint --strict && ${PWD}/SwiftFormat/CommandLineTool/swiftformat --verbose --lint . + - stage: tests os: osx osx_image: xcode10.2 @@ -35,15 +43,6 @@ jobs: script: make coverage after_success: bash <(curl -s https://codecov.io/bash) - - stage: post-tests - name: lint - os: osx - osx_image: xcode11.1 - install: ./Tests/Scripts/install_dependencies.sh swiftlint - before_script: skip - script: ${PWD}/swiftlint/swiftlint --strict - - install: - INSTALLER=Tests/Scripts/install_dependencies.sh - ./${INSTALLER} libmongoc diff --git a/Tests/.swiftformat b/Tests/.swiftformat new file mode 100644 index 000000000..7dbbf67e7 --- /dev/null +++ b/Tests/.swiftformat @@ -0,0 +1,2 @@ +--exclude LinuxMain.swift +--disable trailingClosures \ No newline at end of file diff --git a/Tests/Scripts/install_dependencies.sh b/Tests/Scripts/install_dependencies.sh index 93bdfc316..901b49b9b 100755 --- a/Tests/Scripts/install_dependencies.sh +++ b/Tests/Scripts/install_dependencies.sh @@ -47,7 +47,14 @@ elif [[ $1 = "swiftlint" ]] then install_from_gh swiftlint https://github.com/realm/SwiftLint/releases/download/0.35.0/portable_swiftlint.zip +elif [[ $1 = "swiftformat" ]] +then + git clone https://github.com/nicklockwood/SwiftFormat --branch="0.40.13" + pushd SwiftFormat + swift build -c release + popd + else echo Missing/unknown install option: "$1" - echo Usage: "./travis_install.sh libmongoc|mongodb|sourcery|swiftlint" + echo Usage: "./travis_install.sh libmongoc|mongodb|sourcery|swiftlint|swiftformat" fi From 94c18c7723d016f8db03a4e2a228481e30a1fa93 Mon Sep 17 00:00:00 2001 From: Patrick Freed Date: Fri, 18 Oct 2019 18:19:44 -0400 Subject: [PATCH 2/4] run swiftformat on driver --- Examples/BugReport/Package.swift | 5 +- Examples/Docs/Package.swift | 2 +- Examples/Docs/Sources/DocsExamples/main.swift | 14 +- Examples/Perfect/Package.swift | 16 +- .../Perfect/Sources/PerfectExample/main.swift | 23 +- Sources/MongoSwift/APM.swift | 111 +++--- Sources/MongoSwift/BSON/BSON.swift | 9 +- Sources/MongoSwift/BSON/BSONDecoder.swift | 287 ++++++++------ Sources/MongoSwift/BSON/BSONEncoder.swift | 132 ++++--- Sources/MongoSwift/BSON/BSONValue.swift | 120 +++--- Sources/MongoSwift/BSON/CodableNumber.swift | 1 + .../MongoSwift/BSON/CodingStrategies.swift | 8 +- .../MongoSwift/BSON/Document+Collection.swift | 6 +- .../MongoSwift/BSON/Document+Sequence.swift | 16 +- Sources/MongoSwift/BSON/Document.swift | 21 +- .../MongoSwift/BSON/DocumentIterator.swift | 14 +- Sources/MongoSwift/ChangeStream.swift | 25 +- Sources/MongoSwift/ChangeStreamOptions.swift | 18 +- Sources/MongoSwift/ClientSession.swift | 11 +- Sources/MongoSwift/Counter.swift | 2 +- Sources/MongoSwift/MongoClient.swift | 156 +++++--- .../MongoCollection+BulkWrite.swift | 57 +-- .../MongoCollection+ChangeStreams.swift | 50 ++- .../MongoCollection+FindAndModify.swift | 140 ++++--- .../MongoSwift/MongoCollection+Indexes.swift | 122 +++--- Sources/MongoSwift/MongoCollection+Read.swift | 140 ++++--- .../MongoSwift/MongoCollection+Write.swift | 117 +++--- Sources/MongoSwift/MongoCollection.swift | 14 +- Sources/MongoSwift/MongoCursor.swift | 12 +- Sources/MongoSwift/MongoDatabase.swift | 140 ++++--- Sources/MongoSwift/MongoError.swift | 108 +++--- .../Operations/CountOperation.swift | 34 +- .../CreateCollectionOperation.swift | 44 ++- .../Operations/DistinctOperation.swift | 16 +- .../Operations/FindAndModifyOperation.swift | 54 +-- .../Operations/ListCollectionsOperation.swift | 25 +- .../Operations/ListDatabasesOperation.swift | 24 +- .../Operations/ListIndexesOperation.swift | 14 +- .../MongoSwift/Operations/NextOperation.swift | 2 +- Sources/MongoSwift/Operations/Operation.swift | 18 +- .../Operations/RunCommandOperation.swift | 8 +- .../Operations/WatchOperation.swift | 30 +- Sources/MongoSwift/ReadConcern.swift | 4 +- Sources/MongoSwift/ReadPreference.swift | 6 +- Sources/MongoSwift/SDAM.swift | 44 +-- Sources/MongoSwift/WriteConcern.swift | 12 +- Tests/MongoSwiftTests/AuthTests.swift | 40 +- Tests/MongoSwiftTests/BSONValueTests.swift | 38 +- Tests/MongoSwiftTests/ChangeStreamTests.swift | 115 +++--- .../MongoSwiftTests/ClientSessionTests.swift | 91 +++-- Tests/MongoSwiftTests/CodecTests.swift | 360 ++++++++++-------- .../CommandMonitoringTests.swift | 73 ++-- Tests/MongoSwiftTests/CrudTests.swift | 53 +-- Tests/MongoSwiftTests/DNSSeedlistTests.swift | 24 +- .../Document+SequenceTests.swift | 43 ++- Tests/MongoSwiftTests/DocumentTests.swift | 46 +-- Tests/MongoSwiftTests/MongoClientTests.swift | 24 +- .../MongoCollection+BulkWriteTests.swift | 79 ++-- .../MongoCollection+IndexTests.swift | 18 +- .../MongoCollectionTests.swift | 138 ++++--- Tests/MongoSwiftTests/MongoCursorTests.swift | 20 +- .../MongoSwiftTests/MongoDatabaseTests.swift | 86 +++-- .../MongoError+Equatable.swift | 70 ++-- Tests/MongoSwiftTests/OptionsTests.swift | 2 +- .../MongoSwiftTests/ReadPreferenceTests.swift | 44 ++- .../ReadWriteConcernTests.swift | 235 +++++++----- .../MongoSwiftTests/SDAMMonitoringTests.swift | 20 +- .../SpecTestRunner/Match.swift | 1 + .../SpecTestRunner/SpecTest.swift | 55 +-- .../SpecTestRunner/SpecTestUtils.swift | 18 +- .../SpecTestRunner/TestOperation.swift | 257 ++++++++----- .../SpecTestRunner/TestOperationResult.swift | 21 +- Tests/MongoSwiftTests/TestUtils.swift | 77 ++-- 73 files changed, 2456 insertions(+), 1824 deletions(-) diff --git a/Examples/BugReport/Package.swift b/Examples/BugReport/Package.swift index 5013c679a..ccbe6b5df 100644 --- a/Examples/BugReport/Package.swift +++ b/Examples/BugReport/Package.swift @@ -4,11 +4,12 @@ import PackageDescription let package = Package( name: "BugReport", dependencies: [ - .package(url: "https://github.com/mongodb/mongo-swift-driver", .upToNextMajor(from: "0.1.0")) + .package(url: "https://github.com/mongodb/mongo-swift-driver", .upToNextMajor(from: "0.1.0")) ], targets: [ .target( name: "BugReport", - dependencies: ["MongoSwift"]) + dependencies: ["MongoSwift"] + ) ] ) diff --git a/Examples/Docs/Package.swift b/Examples/Docs/Package.swift index 2c4fddb6d..991ba9a8b 100644 --- a/Examples/Docs/Package.swift +++ b/Examples/Docs/Package.swift @@ -9,4 +9,4 @@ let package = Package( targets: [ .target(name: "DocsExamples", dependencies: ["MongoSwift"]) ] -) \ No newline at end of file +) diff --git a/Examples/Docs/Sources/DocsExamples/main.swift b/Examples/Docs/Sources/DocsExamples/main.swift index 4f205f280..7445865ef 100644 --- a/Examples/Docs/Sources/DocsExamples/main.swift +++ b/Examples/Docs/Sources/DocsExamples/main.swift @@ -11,12 +11,16 @@ private func causalConsistency() throws { // Start Causal Consistency Example 1 let s1 = try client1.startSession(options: ClientSessionOptions(causalConsistency: true)) let currentDate = Date() - var dbOptions = DatabaseOptions(readConcern: ReadConcern(.majority), - writeConcern: try WriteConcern(w: .majority, wtimeoutMS: 1000)) + var dbOptions = DatabaseOptions( + readConcern: ReadConcern(.majority), + writeConcern: try WriteConcern(w: .majority, wtimeoutMS: 1000) + ) let items = client1.db("test", options: dbOptions).collection("items") - try items.updateOne(filter: ["sku": "111", "end": BSONNull()], - update: ["$set": ["end": currentDate] as Document], - session: s1) + try items.updateOne( + filter: ["sku": "111", "end": BSONNull()], + update: ["$set": ["end": currentDate] as Document], + session: s1 + ) try items.insertOne(["sku": "nuts-111", "name": "Pecans", "start": currentDate], session: s1) // End Causal Consistency Example 1 diff --git a/Examples/Perfect/Package.swift b/Examples/Perfect/Package.swift index 503506e2e..de453934d 100644 --- a/Examples/Perfect/Package.swift +++ b/Examples/Perfect/Package.swift @@ -2,12 +2,12 @@ import PackageDescription let package = Package( - name: "PerfectExample", - dependencies: [ - .package(url: "https://github.com/PerfectlySoft/Perfect-HTTPServer.git", from: "3.0.0"), - .package(url: "https://github.com/mongodb/mongo-swift-driver", .upToNextMajor(from: "0.1.0")), - ], - targets: [ - .target(name: "PerfectExample", dependencies: ["PerfectHTTPServer", "MongoSwift"]) - ] + name: "PerfectExample", + dependencies: [ + .package(url: "https://github.com/PerfectlySoft/Perfect-HTTPServer.git", from: "3.0.0"), + .package(url: "https://github.com/mongodb/mongo-swift-driver", .upToNextMajor(from: "0.1.0")), + ], + targets: [ + .target(name: "PerfectExample", dependencies: ["PerfectHTTPServer", "MongoSwift"]) + ] ) diff --git a/Examples/Perfect/Sources/PerfectExample/main.swift b/Examples/Perfect/Sources/PerfectExample/main.swift index 2b1deb126..5e2e050ba 100644 --- a/Examples/Perfect/Sources/PerfectExample/main.swift +++ b/Examples/Perfect/Sources/PerfectExample/main.swift @@ -5,8 +5,8 @@ import PerfectHTTPServer /// A Codable type that matches the data in our home.kittens collection. private struct Kitten: Codable { - var name: String - var color: String + var name: String + var color: String } /// A single collection with type `Kitten`. This allows us to directly retrieve instances of @@ -15,14 +15,15 @@ private let collection = try MongoClient().db("home").collection("kittens", with private var routes = Routes() routes.add(method: .get, uri: "/kittens") { _, response in - response.setHeader(.contentType, value: "application/json") - do { - let kittens = try collection.find() - let json = try JSONEncoder().encode(Array(kittens)) - response.setBody(bytes: Array(json)) - } catch { - print("error: \(error)") - } - response.completed() + response.setHeader(.contentType, value: "application/json") + do { + let kittens = try collection.find() + let json = try JSONEncoder().encode(Array(kittens)) + response.setBody(bytes: Array(json)) + } catch { + print("error: \(error)") + } + response.completed() } + try HTTPServer.launch(name: "localhost", port: 8080, routes: routes) diff --git a/Sources/MongoSwift/APM.swift b/Sources/MongoSwift/APM.swift index 1005d02fb..95d335e05 100644 --- a/Sources/MongoSwift/APM.swift +++ b/Sources/MongoSwift/APM.swift @@ -348,108 +348,133 @@ public struct ServerHeartbeatFailedEvent: MongoEvent, InitializableFromOpaquePoi /// A callback that will be set for "command started" events if the user enables command monitoring. private func commandStarted(_event: OpaquePointer?) { - postNotification(type: CommandStartedEvent.self, - _event: _event, - contextFunc: mongoc_apm_command_started_get_context) + postNotification( + type: CommandStartedEvent.self, + _event: _event, + contextFunc: mongoc_apm_command_started_get_context + ) } /// A callback that will be set for "command succeeded" events if the user enables command monitoring. private func commandSucceeded(_event: OpaquePointer?) { - postNotification(type: CommandSucceededEvent.self, - _event: _event, - contextFunc: mongoc_apm_command_succeeded_get_context) + postNotification( + type: CommandSucceededEvent.self, + _event: _event, + contextFunc: mongoc_apm_command_succeeded_get_context + ) } /// A callback that will be set for "command failed" events if the user enables command monitoring. private func commandFailed(_event: OpaquePointer?) { - postNotification(type: CommandFailedEvent.self, - _event: _event, - contextFunc: mongoc_apm_command_failed_get_context) + postNotification( + type: CommandFailedEvent.self, + _event: _event, + contextFunc: mongoc_apm_command_failed_get_context + ) } /// A callback that will be set for "server description changed" events if the user enables server monitoring. private func serverDescriptionChanged(_event: OpaquePointer?) { - postNotification(type: ServerDescriptionChangedEvent.self, - _event: _event, - contextFunc: mongoc_apm_server_changed_get_context) + postNotification( + type: ServerDescriptionChangedEvent.self, + _event: _event, + contextFunc: mongoc_apm_server_changed_get_context + ) } /// A callback that will be set for "server opening" events if the user enables server monitoring. private func serverOpening(_event: OpaquePointer?) { - postNotification(type: ServerOpeningEvent.self, - _event: _event, - contextFunc: mongoc_apm_server_opening_get_context) + postNotification( + type: ServerOpeningEvent.self, + _event: _event, + contextFunc: mongoc_apm_server_opening_get_context + ) } /// A callback that will be set for "server closed" events if the user enables server monitoring. private func serverClosed(_event: OpaquePointer?) { - postNotification(type: ServerClosedEvent.self, - _event: _event, - contextFunc: mongoc_apm_server_closed_get_context) + postNotification( + type: ServerClosedEvent.self, + _event: _event, + contextFunc: mongoc_apm_server_closed_get_context + ) } /// A callback that will be set for "topology description changed" events if the user enables server monitoring. private func topologyDescriptionChanged(_event: OpaquePointer?) { - postNotification(type: TopologyDescriptionChangedEvent.self, - _event: _event, - contextFunc: mongoc_apm_topology_changed_get_context) + postNotification( + type: TopologyDescriptionChangedEvent.self, + _event: _event, + contextFunc: mongoc_apm_topology_changed_get_context + ) } /// A callback that will be set for "topology opening" events if the user enables server monitoring. private func topologyOpening(_event: OpaquePointer?) { - postNotification(type: TopologyOpeningEvent.self, - _event: _event, - contextFunc: mongoc_apm_topology_opening_get_context) + postNotification( + type: TopologyOpeningEvent.self, + _event: _event, + contextFunc: mongoc_apm_topology_opening_get_context + ) } /// A callback that will be set for "topology closed" events if the user enables server monitoring. private func topologyClosed(_event: OpaquePointer?) { - postNotification(type: TopologyClosedEvent.self, - _event: _event, - contextFunc: mongoc_apm_topology_closed_get_context) + postNotification( + type: TopologyClosedEvent.self, + _event: _event, + contextFunc: mongoc_apm_topology_closed_get_context + ) } /// A callback that will be set for "server heartbeat started" events if the user enables server monitoring. private func serverHeartbeatStarted(_event: OpaquePointer?) { - postNotification(type: ServerHeartbeatStartedEvent.self, - _event: _event, - contextFunc: mongoc_apm_server_heartbeat_started_get_context) + postNotification( + type: ServerHeartbeatStartedEvent.self, + _event: _event, + contextFunc: mongoc_apm_server_heartbeat_started_get_context + ) } /// A callback that will be set for "server heartbeat succeeded" events if the user enables server monitoring. private func serverHeartbeatSucceeded(_event: OpaquePointer?) { - postNotification(type: ServerHeartbeatSucceededEvent.self, - _event: _event, - contextFunc: mongoc_apm_server_heartbeat_succeeded_get_context) + postNotification( + type: ServerHeartbeatSucceededEvent.self, + _event: _event, + contextFunc: mongoc_apm_server_heartbeat_succeeded_get_context + ) } /// A callback that will be set for "server heartbeat failed" events if the user enables server monitoring. private func serverHeartbeatFailed(_event: OpaquePointer?) { - postNotification(type: ServerHeartbeatFailedEvent.self, - _event: _event, - contextFunc: mongoc_apm_server_heartbeat_failed_get_context) + postNotification( + type: ServerHeartbeatFailedEvent.self, + _event: _event, + contextFunc: mongoc_apm_server_heartbeat_failed_get_context + ) } /// Posts a Notification with the specified name, containing an event of type T generated using the provided _event /// and context function. -private func postNotification(type: T.Type, - _event: OpaquePointer?, - contextFunc: (OpaquePointer) -> UnsafeMutableRawPointer? - ) where T: InitializableFromOpaquePointer { +private func postNotification( + type: T.Type, + _event: OpaquePointer?, + contextFunc: (OpaquePointer) -> UnsafeMutableRawPointer? +) where T: InitializableFromOpaquePointer { guard let event = _event else { fatalError("Missing event pointer for \(type)") } let eventStruct = type.init(event) - // TODO SWIFT-524: remove workaround for CDRIVER-3256 + // TODO: SWIFT-524: remove workaround for CDRIVER-3256 if let tdChanged = eventStruct as? TopologyDescriptionChangedEvent, - tdChanged.previousDescription == tdChanged.newDescription { + tdChanged.previousDescription == tdChanged.newDescription { return } if let sdChanged = eventStruct as? ServerDescriptionChangedEvent, - sdChanged.previousDescription == sdChanged.newDescription { + sdChanged.previousDescription == sdChanged.newDescription { return } diff --git a/Sources/MongoSwift/BSON/BSON.swift b/Sources/MongoSwift/BSON/BSON.swift index 9eb926cd4..e699cbe07 100644 --- a/Sources/MongoSwift/BSON/BSON.swift +++ b/Sources/MongoSwift/BSON/BSON.swift @@ -432,10 +432,11 @@ extension BSON: Codable { } throw DecodingError.typeMismatch( - BSON.self, - DecodingError.Context( - codingPath: decoder.codingPath, - debugDescription: "Encountered a value that could not be decoded to any BSON type") + BSON.self, + DecodingError.Context( + codingPath: decoder.codingPath, + debugDescription: "Encountered a value that could not be decoded to any BSON type" + ) ) } } diff --git a/Sources/MongoSwift/BSON/BSONDecoder.swift b/Sources/MongoSwift/BSON/BSONDecoder.swift index 7272e7b8e..382e4cad5 100644 --- a/Sources/MongoSwift/BSON/BSONDecoder.swift +++ b/Sources/MongoSwift/BSON/BSONDecoder.swift @@ -99,10 +99,11 @@ public class BSONDecoder { /// The options set on the top-level decoder. fileprivate var options: _Options { - return _Options(userInfo: self.userInfo, - dateDecodingStrategy: self.dateDecodingStrategy, - uuidDecodingStrategy: self.uuidDecodingStrategy, - dataDecodingStrategy: self.dataDecodingStrategy + return _Options( + userInfo: self.userInfo, + dateDecodingStrategy: self.dateDecodingStrategy, + uuidDecodingStrategy: self.uuidDecodingStrategy, + dataDecodingStrategy: self.dataDecodingStrategy ) } @@ -164,7 +165,7 @@ public class BSONDecoder { * - Returns: A value of the requested type. * - Throws: `DecodingError` if the JSON data is corrupt or if any value throws an error during decoding. */ - public func decode(_ type: T.Type, from json: String) throws -> T { + public func decode(_: T.Type, from json: String) throws -> T { // we nest the input JSON in another object, and then decode to a `DecodableWrapper` // wrapping an object of the requested type. since our decoder only supports decoding // objects, this allows us to additionally handle decoding to primitive types like a @@ -182,8 +183,10 @@ public class BSONDecoder { } throw DecodingError.dataCorrupted( - DecodingError.Context(codingPath: [], - debugDescription: "Unable to parse JSON string \(json)")) + DecodingError.Context( + codingPath: [], + debugDescription: "Unable to parse JSON string \(json)" + )) } /** @@ -194,10 +197,11 @@ public class BSONDecoder { * - `RuntimeError.internalError` if the BSON data is corrupt or if any value throws an error during decoding. */ internal func internalDecode( - _ type: T.Type, - from document: Document, - withError errMsg: String = "Failed to decode \(T.self)") - throws -> T { + _ type: T.Type, + from document: Document, + withError errMsg: String = "Failed to decode \(T.self)" + ) + throws -> T { do { return try self.decode(type, from: document) } catch is DecodingError { @@ -240,9 +244,11 @@ internal class _BSONDecoder: Decoder { } /// Initializes `self` with the given top-level container and options. - fileprivate init(referencing container: BSON, - at codingPath: [CodingKey] = [], - options: BSONDecoder._Options) { + fileprivate init( + referencing container: BSON, + at codingPath: [CodingKey] = [], + options: BSONDecoder._Options + ) { self.storage = _BSONDecodingStorage() self.storage.push(container: container) self.codingPath = codingPath @@ -250,11 +256,13 @@ internal class _BSONDecoder: Decoder { } // Returns the data stored in this decoder as represented in a container keyed by the given key type. - public func container(keyedBy type: Key.Type) throws -> KeyedDecodingContainer { + public func container(keyedBy _: Key.Type) throws -> KeyedDecodingContainer { guard let topContainer = self.storage.topContainer.documentValue else { - throw DecodingError._typeMismatch(at: self.codingPath, - expectation: Document.self, - reality: self.storage.topContainer.bsonValue) + throw DecodingError._typeMismatch( + at: self.codingPath, + expectation: Document.self, + reality: self.storage.topContainer.bsonValue + ) } let container = _BSONKeyedDecodingContainer(referencing: self, wrapping: topContainer) @@ -321,9 +329,12 @@ extension _BSONDecoder { // We throw in the case of BSONNull because nulls should be requested through decodeNil(). guard value != .null else { throw DecodingError.valueNotFound( - T.self, - DecodingError.Context(codingPath: self.codingPath, - debugDescription: "Expected a non-null type.")) + T.self, + DecodingError.Context( + codingPath: self.codingPath, + debugDescription: "Expected a non-null type." + ) + ) } guard let typed = f(value) else { @@ -337,9 +348,12 @@ extension _BSONDecoder { // We throw in the case of BSONNull because nulls should be requested through decodeNil(). guard value != .null else { throw DecodingError.valueNotFound( - type, - DecodingError.Context(codingPath: self.codingPath, - debugDescription: "Expected a non-null type.")) + type, + DecodingError.Context( + codingPath: self.codingPath, + debugDescription: "Expected a non-null type." + ) + ) } guard let typed = value.bsonValue as? T else { @@ -366,18 +380,19 @@ extension _BSONDecoder { case .binary: let binary = try self.unboxCustom(value) { $0.binaryValue } return binary.data - case.base64: + case .base64: let base64Str = try self.unboxCustom(value) { $0.stringValue } guard let data = Data(base64Encoded: base64Str) else { throw DecodingError.dataCorrupted( - DecodingError.Context( - codingPath: self.codingPath, - debugDescription: "Malformatted base64 encoded string. Got: \(value)") + DecodingError.Context( + codingPath: self.codingPath, + debugDescription: "Malformatted base64 encoded string. Got: \(value)" + ) ) } return data - case .custom(let f): + case let .custom(f): self.storage.push(container: value) defer { self.storage.popContainer() } return try f(self) @@ -407,27 +422,27 @@ extension _BSONDecoder { let isoString = try self.unboxCustom(value) { $0.stringValue } guard let date = BSONDecoder.iso8601Formatter.date(from: isoString) else { throw DecodingError.dataCorrupted( - DecodingError.Context( - codingPath: self.codingPath, - debugDescription: "String \"\(isoString)\" is not a properly formatted " + - "ISO 8601 Date string." - ) + DecodingError.Context( + codingPath: self.codingPath, + debugDescription: "String \"\(isoString)\" is not a properly formatted " + + "ISO 8601 Date string." + ) ) } return date - case .custom(let f): + case let .custom(f): self.storage.push(container: value) defer { self.storage.popContainer() } return try f(self) - case .formatted(let formatter): + case let .formatted(formatter): let dateString = try self.unboxCustom(value) { $0.stringValue } guard let date = formatter.date(from: dateString) else { throw DecodingError.dataCorrupted( - DecodingError.Context( - codingPath: self.codingPath, - debugDescription: "String \"\(dateString)\" does not match the format " + - "expected by formatter." - ) + DecodingError.Context( + codingPath: self.codingPath, + debugDescription: "String \"\(dateString)\" does not match the format " + + "expected by formatter." + ) ) } return date @@ -447,10 +462,10 @@ extension _BSONDecoder { return try UUID(from: binary) } catch { throw DecodingError.dataCorrupted( - DecodingError.Context( - codingPath: self.codingPath, - debugDescription: error.localizedDescription - ) + DecodingError.Context( + codingPath: self.codingPath, + debugDescription: error.localizedDescription + ) ) } } @@ -461,18 +476,18 @@ extension _BSONDecoder { switch type { case is Date.Type: // We know T is a Date and unboxDate returns a Date or throws, so this cast will always work. - return try unboxDate(value) as! T + return try self.unboxDate(value) as! T case is UUID.Type: // We know T is a UUID and unboxUUID returns a UUID or throws, so this cast will always work. - return try unboxUUID(value) as! T + return try self.unboxUUID(value) as! T case is Data.Type: // We know T is a Data and unboxData returns a Data or throws, so this cast will always work. - return try unboxData(value) as! T + return try self.unboxData(value) as! T case is BSON.Type: switch value { case .datetime: // We know T is a BSON so this cast will always work. - return try BSON.datetime(unboxDate(value)) as! T + return try BSON.datetime(self.unboxDate(value)) as! T default: // We know T is a BSON so this cast will always work. return value as! T @@ -535,8 +550,11 @@ private struct _BSONKeyedDecodingContainer: KeyedDecodingContainer guard let entry = try self.container.getValue(for: key.stringValue) else { throw DecodingError.keyNotFound( key, - DecodingError.Context(codingPath: self.decoder.codingPath, - debugDescription: "No value associated with key \(_errorDescription(of: key)).")) + DecodingError.Context( + codingPath: self.decoder.codingPath, + debugDescription: "No value associated with key \(self._errorDescription(of: key))." + ) + ) } return entry } @@ -545,7 +563,7 @@ private struct _BSONKeyedDecodingContainer: KeyedDecodingContainer private func decodeBSONType(_ type: T.Type, forKey key: Key) throws -> T { let entry = try getValue(forKey: key) return try self.decoder.with(pushedKey: key) { - try decoder.unboxBSONValue(entry, as: type) + try decoder.unboxBSONValue(entry, as: type) } } @@ -565,8 +583,11 @@ private struct _BSONKeyedDecodingContainer: KeyedDecodingContainer guard !(value is BSONNull) || type == BSONNull.self else { throw DecodingError.valueNotFound( type, - DecodingError.Context(codingPath: self.decoder.codingPath, - debugDescription: "Expected \(type) value but found null instead.")) + DecodingError.Context( + codingPath: self.decoder.codingPath, + debugDescription: "Expected \(type) value but found null instead." + ) + ) } return value } @@ -579,39 +600,46 @@ private struct _BSONKeyedDecodingContainer: KeyedDecodingContainer guard self.contains(key) else { throw DecodingError.keyNotFound( key, - DecodingError.Context(codingPath: self.decoder.codingPath, - debugDescription: "Key \(_errorDescription(of: key)) not found.")) + DecodingError.Context( + codingPath: self.decoder.codingPath, + debugDescription: "Key \(self._errorDescription(of: key)) not found." + ) + ) } return try self.container.getValue(for: key.stringValue) == .null } // swiftlint:disable line_length - public func decode(_ type: Bool.Type, forKey key: Key) throws -> Bool { return try self.decodeBSONType(Bool.self, forKey: key) } - public func decode(_ type: Int.Type, forKey key: Key) throws -> Int { return try decodeNumber(type, forKey: key) } - public func decode(_ type: Int8.Type, forKey key: Key) throws -> Int8 { return try decodeNumber(type, forKey: key) } - public func decode(_ type: Int16.Type, forKey key: Key) throws -> Int16 { return try decodeNumber(type, forKey: key) } - public func decode(_ type: Int32.Type, forKey key: Key) throws -> Int32 { return try decodeNumber(type, forKey: key) } - public func decode(_ type: Int64.Type, forKey key: Key) throws -> Int64 { return try decodeNumber(type, forKey: key) } - public func decode(_ type: UInt8.Type, forKey key: Key) throws -> UInt8 { return try decodeNumber(type, forKey: key) } - public func decode(_ type: UInt16.Type, forKey key: Key) throws -> UInt16 { return try decodeNumber(type, forKey: key) } - public func decode(_ type: UInt32.Type, forKey key: Key) throws -> UInt32 { return try decodeNumber(type, forKey: key) } - public func decode(_ type: UInt.Type, forKey key: Key) throws -> UInt { return try decodeNumber(type, forKey: key) } - public func decode(_ type: UInt64.Type, forKey key: Key) throws -> UInt64 { return try decodeNumber(type, forKey: key) } - public func decode(_ type: Float.Type, forKey key: Key) throws -> Float { return try decodeNumber(type, forKey: key) } - public func decode(_ type: Double.Type, forKey key: Key) throws -> Double { return try decodeNumber(type, forKey: key) } - public func decode(_ type: String.Type, forKey key: Key) throws -> String { return try self.decodeBSONType(String.self, forKey: key) } + public func decode(_: Bool.Type, forKey key: Key) throws -> Bool { return try self.decodeBSONType(Bool.self, forKey: key) } + public func decode(_ type: Int.Type, forKey key: Key) throws -> Int { return try self.decodeNumber(type, forKey: key) } + public func decode(_ type: Int8.Type, forKey key: Key) throws -> Int8 { return try self.decodeNumber(type, forKey: key) } + public func decode(_ type: Int16.Type, forKey key: Key) throws -> Int16 { return try self.decodeNumber(type, forKey: key) } + public func decode(_ type: Int32.Type, forKey key: Key) throws -> Int32 { return try self.decodeNumber(type, forKey: key) } + public func decode(_ type: Int64.Type, forKey key: Key) throws -> Int64 { return try self.decodeNumber(type, forKey: key) } + public func decode(_ type: UInt8.Type, forKey key: Key) throws -> UInt8 { return try self.decodeNumber(type, forKey: key) } + public func decode(_ type: UInt16.Type, forKey key: Key) throws -> UInt16 { return try self.decodeNumber(type, forKey: key) } + public func decode(_ type: UInt32.Type, forKey key: Key) throws -> UInt32 { return try self.decodeNumber(type, forKey: key) } + public func decode(_ type: UInt.Type, forKey key: Key) throws -> UInt { return try self.decodeNumber(type, forKey: key) } + public func decode(_ type: UInt64.Type, forKey key: Key) throws -> UInt64 { return try self.decodeNumber(type, forKey: key) } + public func decode(_ type: Float.Type, forKey key: Key) throws -> Float { return try self.decodeNumber(type, forKey: key) } + public func decode(_ type: Double.Type, forKey key: Key) throws -> Double { return try self.decodeNumber(type, forKey: key) } + public func decode(_: String.Type, forKey key: Key) throws -> String { return try self.decodeBSONType(String.self, forKey: key) } // swiftlint:enable line_length /// Returns the data stored for the given key as represented in a container keyed by the given key type. - public func nestedContainer(keyedBy type: NestedKey.Type, - forKey key: Key) throws -> KeyedDecodingContainer { + public func nestedContainer( + keyedBy _: NestedKey.Type, + forKey key: Key + ) throws -> KeyedDecodingContainer { return try self.decoder.with(pushedKey: key) { let value = try getValue(forKey: key) guard let doc = value.documentValue else { - throw DecodingError._typeMismatch(at: self.codingPath, - expectation: Document.self, - reality: value.bsonValue) + throw DecodingError._typeMismatch( + at: self.codingPath, + expectation: Document.self, + reality: value.bsonValue + ) } let container = _BSONKeyedDecodingContainer(referencing: self.decoder, wrapping: doc) @@ -625,9 +653,11 @@ private struct _BSONKeyedDecodingContainer: KeyedDecodingContainer let value = try getValue(forKey: key) guard let array = value.arrayValue else { - throw DecodingError._typeMismatch(at: self.codingPath, - expectation: [BSON].self, - reality: value.bsonValue) + throw DecodingError._typeMismatch( + at: self.codingPath, + expectation: [BSON].self, + reality: value.bsonValue + ) } return _BSONUnkeyedDecodingContainer(referencing: self.decoder, wrapping: array) @@ -638,27 +668,30 @@ private struct _BSONKeyedDecodingContainer: KeyedDecodingContainer private func _superDecoder(forKey key: CodingKey) throws -> Decoder { return try self.decoder.with(pushedKey: key) { guard let value = try self.container.getValue(for: key.stringValue) else { - throw DecodingError.keyNotFound(key, - DecodingError.Context( - codingPath: self.decoder.codingPath, - debugDescription: "Could not find key \(key) in Decoder container" - ) + throw DecodingError.keyNotFound( + key, + DecodingError.Context( + codingPath: self.decoder.codingPath, + debugDescription: "Could not find key \(key) in Decoder container" + ) ) } - return _BSONDecoder(referencing: value, - at: self.decoder.codingPath, - options: self.decoder.options) + return _BSONDecoder( + referencing: value, + at: self.decoder.codingPath, + options: self.decoder.options + ) } } /// Returns a Decoder instance for decoding super from the container associated with the default super key. public func superDecoder() throws -> Decoder { - return try _superDecoder(forKey: _BSONKey.super) + return try self._superDecoder(forKey: _BSONKey.super) } // Returns a Decoder instance for decoding super from the container associated with the given key. public func superDecoder(forKey key: Key) throws -> Decoder { - return try _superDecoder(forKey: key) + return try self._superDecoder(forKey: key) } } @@ -697,8 +730,11 @@ private struct _BSONUnkeyedDecodingContainer: UnkeyedDecodingContainer { guard !self.isAtEnd else { throw DecodingError.valueNotFound( BSON.self, - DecodingError.Context(codingPath: self.decoder.codingPath + [_BSONKey(index: self.currentIndex)], - debugDescription: "Unkeyed container is at end.")) + DecodingError.Context( + codingPath: self.decoder.codingPath + [_BSONKey(index: self.currentIndex)], + debugDescription: "Unkeyed container is at end." + ) + ) } } @@ -732,7 +768,9 @@ private struct _BSONUnkeyedDecodingContainer: UnkeyedDecodingContainer { type, DecodingError.Context( codingPath: self.decoder.codingPath + [_BSONKey(index: self.currentIndex)], - debugDescription: "Expected \(type) but found null instead.")) + debugDescription: "Expected \(type) but found null instead." + ) + ) } self.currentIndex += 1 return decoded @@ -767,7 +805,7 @@ private struct _BSONUnkeyedDecodingContainer: UnkeyedDecodingContainer { public mutating func decode(_ type: String.Type) throws -> String { return try self.decodeBSONType(type) } /// Decodes a nested container keyed by the given type. - public mutating func nestedContainer(keyedBy type: NestedKey.Type) + public mutating func nestedContainer(keyedBy _: NestedKey.Type) throws -> KeyedDecodingContainer { return try self.decoder.with(pushedKey: _BSONKey(index: self.currentIndex)) { try self.checkAtEnd() @@ -806,8 +844,11 @@ extension _BSONDecoder: SingleValueDecodingContainer { guard !self.decodeNil() else { throw DecodingError.valueNotFound( type, - DecodingError.Context(codingPath: self.codingPath, - debugDescription: "Expected \(type) but found null value instead.")) + DecodingError.Context( + codingPath: self.codingPath, + debugDescription: "Expected \(type) but found null value instead." + ) + ) } } @@ -820,20 +861,20 @@ extension _BSONDecoder: SingleValueDecodingContainer { } /// Decode a BSONValue type from this container. - private func decodeBSONType(_ type: T.Type) throws -> T { - try expectNonNull(T.self) + private func decodeBSONType(_: T.Type) throws -> T { + try self.expectNonNull(T.self) return try self.unboxBSONValue(self.storage.topContainer, as: T.self) } /// Decode a CodableNumber type from this container. - private func decodeNumber(_ type: T.Type) throws -> T { - try expectNonNull(T.self) + private func decodeNumber(_: T.Type) throws -> T { + try self.expectNonNull(T.self) return try self.unboxNumber(self.storage.topContainer, as: T.self) } /// Decode a Decodable type from this container. - public func decode(_ type: T.Type) throws -> T { - try expectNonNull(T.self) + public func decode(_: T.Type) throws -> T { + try self.expectNonNull(T.self) return try self.unbox(self.storage.topContainer, as: T.self) } @@ -841,20 +882,20 @@ extension _BSONDecoder: SingleValueDecodingContainer { public func decodeNil() -> Bool { return self.storage.topContainer == .null } /// Decode all the required types from this container using the helpers defined above. - public func decode(_ type: Bool.Type) throws -> Bool { return try decodeBSONType(type) } - public func decode(_ type: Int.Type) throws -> Int { return try decodeNumber(type) } - public func decode(_ type: Int8.Type) throws -> Int8 { return try decodeNumber(type) } - public func decode(_ type: Int16.Type) throws -> Int16 { return try decodeNumber(type) } - public func decode(_ type: Int32.Type) throws -> Int32 { return try decodeNumber(type) } - public func decode(_ type: Int64.Type) throws -> Int64 { return try decodeNumber(type) } - public func decode(_ type: UInt.Type) throws -> UInt { return try decodeNumber(type) } - public func decode(_ type: UInt8.Type) throws -> UInt8 { return try decodeNumber(type) } - public func decode(_ type: UInt16.Type) throws -> UInt16 { return try decodeNumber(type) } - public func decode(_ type: UInt32.Type) throws -> UInt32 { return try decodeNumber(type) } - public func decode(_ type: UInt64.Type) throws -> UInt64 { return try decodeNumber(type) } - public func decode(_ type: Float.Type) throws -> Float { return try decodeNumber(type) } - public func decode(_ type: Double.Type) throws -> Double { return try decodeNumber(type) } - public func decode(_ type: String.Type) throws -> String { return try decodeBSONType(type) } + public func decode(_ type: Bool.Type) throws -> Bool { return try self.decodeBSONType(type) } + public func decode(_ type: Int.Type) throws -> Int { return try self.decodeNumber(type) } + public func decode(_ type: Int8.Type) throws -> Int8 { return try self.decodeNumber(type) } + public func decode(_ type: Int16.Type) throws -> Int16 { return try self.decodeNumber(type) } + public func decode(_ type: Int32.Type) throws -> Int32 { return try self.decodeNumber(type) } + public func decode(_ type: Int64.Type) throws -> Int64 { return try self.decodeNumber(type) } + public func decode(_ type: UInt.Type) throws -> UInt { return try self.decodeNumber(type) } + public func decode(_ type: UInt8.Type) throws -> UInt8 { return try self.decodeNumber(type) } + public func decode(_ type: UInt16.Type) throws -> UInt16 { return try self.decodeNumber(type) } + public func decode(_ type: UInt32.Type) throws -> UInt32 { return try self.decodeNumber(type) } + public func decode(_ type: UInt64.Type) throws -> UInt64 { return try self.decodeNumber(type) } + public func decode(_ type: Float.Type) throws -> Float { return try self.decodeNumber(type) } + public func decode(_ type: Double.Type) throws -> Double { return try self.decodeNumber(type) } + public func decode(_ type: String.Type) throws -> String { return try self.decodeBSONType(type) } } internal struct _BSONKey: CodingKey { @@ -886,18 +927,22 @@ internal struct _BSONKey: CodingKey { } extension DecodingError { - internal static func _typeMismatch(at path: [CodingKey], - expectation: Any.Type, - reality: BSONValue) -> DecodingError { + internal static func _typeMismatch( + at path: [CodingKey], + expectation: Any.Type, + reality: BSONValue + ) -> DecodingError { let description = "Expected to decode \(expectation) but found \(type(of: reality)) instead." return .typeMismatch(expectation, Context(codingPath: path, debugDescription: description)) } - internal static func _numberMismatch(at path: [CodingKey], - expectation: Any.Type, - reality: BSONValue) -> DecodingError { + internal static func _numberMismatch( + at path: [CodingKey], + expectation: Any.Type, + reality: BSONValue + ) -> DecodingError { let description = "Expected to find a value that can be represented as a \(expectation), " + - "but found value \(String(describing: reality)) of type \(type(of: reality)) instead." + "but found value \(String(describing: reality)) of type \(type(of: reality)) instead." return .typeMismatch(expectation, Context(codingPath: path, debugDescription: description)) } } diff --git a/Sources/MongoSwift/BSON/BSONEncoder.swift b/Sources/MongoSwift/BSON/BSONEncoder.swift index bdf0a98cf..175646164 100644 --- a/Sources/MongoSwift/BSON/BSONEncoder.swift +++ b/Sources/MongoSwift/BSON/BSONEncoder.swift @@ -102,11 +102,12 @@ public class BSONEncoder { /// The options set on the top-level encoder. fileprivate var options: _Options { - return _Options(userInfo: self.userInfo, - dateEncodingStrategy: self.dateEncodingStrategy, - uuidEncodingStrategy: self.uuidEncodingStrategy, - dataEncodingStrategy: self.dataEncodingStrategy - ) + return _Options( + userInfo: self.userInfo, + dateEncodingStrategy: self.dateEncodingStrategy, + uuidEncodingStrategy: self.uuidEncodingStrategy, + dataEncodingStrategy: self.dataEncodingStrategy + ) } /// Initializes `self`. @@ -151,15 +152,21 @@ public class BSONEncoder { guard let boxedValue = try encoder.box_(value) else { throw EncodingError.invalidValue( value, - EncodingError.Context(codingPath: [], - debugDescription: "Top-level \(T.self) did not encode any values.")) + EncodingError.Context( + codingPath: [], + debugDescription: "Top-level \(T.self) did not encode any values." + ) + ) } guard let dict = boxedValue as? MutableDictionary else { throw EncodingError.invalidValue( value, - EncodingError.Context(codingPath: [], - debugDescription: "Top-level \(T.self) was not encoded as a complete document.")) + EncodingError.Context( + codingPath: [], + debugDescription: "Top-level \(T.self) was not encoded as a complete document." + ) + ) } return dict.asDocument() @@ -236,7 +243,7 @@ internal class _BSONEncoder: Encoder { return self.storage.count == self.codingPath.count } - public func container(keyedBy: Key.Type) -> KeyedEncodingContainer { + public func container(keyedBy _: Key.Type) -> KeyedEncodingContainer { // If an existing keyed container was already requested, return that one. let topContainer: MutableDictionary if self.canEncodeNewValue { @@ -250,7 +257,8 @@ internal class _BSONEncoder: Encoder { topContainer = container } let container = _BSONKeyedEncodingContainer( - referencing: self, codingPath: self.codingPath, wrapping: topContainer) + referencing: self, codingPath: self.codingPath, wrapping: topContainer + ) return KeyedEncodingContainer(container) } @@ -393,8 +401,8 @@ extension _BSONEncoder { } fileprivate func handleCustomStrategy( - encodeFunc f: (T, Encoder) throws -> Void, - forValue value: T + encodeFunc f: (T, Encoder) throws -> Void, + forValue value: T ) throws -> BSONValue? { let depth = self.storage.count @@ -427,15 +435,15 @@ extension _BSONEncoder { return date.msSinceEpoch case .secondsSince1970: return date.timeIntervalSince1970 - case .formatted(let formatter): + case let .formatted(formatter): return formatter.string(from: date) case .iso8601: guard #available(macOS 10.12, iOS 10.0, watchOS 3.0, tvOS 10.0, *) else { fatalError("ISO8601DateFormatter is unavailable on this platform.") } return BSONDecoder.iso8601Formatter.string(from: date) - case .custom(let f): - return try handleCustomStrategy(encodeFunc: f, forValue: date) + case let .custom(f): + return try self.handleCustomStrategy(encodeFunc: f, forValue: date) } } @@ -459,8 +467,8 @@ extension _BSONEncoder { return try Binary(data: data, subtype: .generic) case .base64: return data.base64EncodedString() - case .custom(let f): - return try handleCustomStrategy(encodeFunc: f, forValue: data) + case let .custom(f): + return try self.handleCustomStrategy(encodeFunc: f, forValue: data) } } @@ -468,7 +476,7 @@ extension _BSONEncoder { fileprivate func box_(_ value: T) throws -> BSONValue? { switch value { case let date as Date: - return try boxDate(date) + return try self.boxDate(date) case let bson as BSON: if case let .datetime(d) = bson { return try boxDate(d) @@ -476,9 +484,9 @@ extension _BSONEncoder { return bson.bsonValue } case let uuid as UUID: - return try boxUUID(uuid) + return try self.boxUUID(uuid) case let data as Data: - return try boxData(data) + return try self.boxData(data) default: break } @@ -521,9 +529,11 @@ private struct _BSONKeyedEncodingContainer: KeyedEncodingContainer public private(set) var codingPath: [CodingKey] /// Initializes `self` with the given references. - fileprivate init(referencing encoder: _BSONEncoder, - codingPath: [CodingKey], - wrapping container: MutableDictionary) { + fileprivate init( + referencing encoder: _BSONEncoder, + codingPath: [CodingKey], + wrapping container: MutableDictionary + ) { self.encoder = encoder self.codingPath = codingPath self.container = container @@ -534,6 +544,7 @@ private struct _BSONKeyedEncodingContainer: KeyedEncodingContainer public mutating func encode(_ value: Int, forKey key: Key) throws { self.container[key.stringValue] = BSON(value).bsonValue } + public mutating func encode(_ value: Int8, forKey key: Key) throws { try self.encodeNumber(value, forKey: key) } public mutating func encode(_ value: Int16, forKey key: Key) throws { try self.encodeNumber(value, forKey: key) } public mutating func encode(_ value: Int32, forKey key: Key) throws { self.container[key.stringValue] = value } @@ -551,17 +562,19 @@ private struct _BSONKeyedEncodingContainer: KeyedEncodingContainer // put the key on the codingPath in case the attempt to convert the number fails and we throw self.encoder.codingPath.append(key) defer { self.encoder.codingPath.removeLast() } - self.container[key.stringValue] = try encoder.boxNumber(value) + self.container[key.stringValue] = try self.encoder.boxNumber(value) } public mutating func encode(_ value: T, forKey key: Key) throws { self.encoder.codingPath.append(key) defer { self.encoder.codingPath.removeLast() } - self.container[key.stringValue] = try encoder.box(value) + self.container[key.stringValue] = try self.encoder.box(value) } - public mutating func nestedContainer(keyedBy keyType: NestedKey.Type, - forKey key: Key) -> KeyedEncodingContainer { + public mutating func nestedContainer( + keyedBy _: NestedKey.Type, + forKey key: Key + ) -> KeyedEncodingContainer { let dictionary = MutableDictionary() self.container[key.stringValue] = dictionary @@ -569,7 +582,8 @@ private struct _BSONKeyedEncodingContainer: KeyedEncodingContainer defer { self.codingPath.removeLast() } let container = _BSONKeyedEncodingContainer( - referencing: self.encoder, codingPath: self.codingPath, wrapping: dictionary) + referencing: self.encoder, codingPath: self.codingPath, wrapping: dictionary + ) return KeyedEncodingContainer(container) } @@ -634,17 +648,17 @@ private struct _BSONUnkeyedEncodingContainer: UnkeyedEncodingContainer { self.encoder.codingPath.append(_BSONKey(index: self.count)) defer { self.encoder.codingPath.removeLast() } - self.container.add(try encoder.boxNumber(value)) + self.container.add(try self.encoder.boxNumber(value)) } public mutating func encode(_ value: T) throws { self.encoder.codingPath.append(_BSONKey(index: self.count)) defer { self.encoder.codingPath.removeLast() } - self.container.add(try encoder.box(value)) + self.container.add(try self.encoder.box(value)) } - public mutating func nestedContainer(keyedBy keyType: NestedKey.Type) + public mutating func nestedContainer(keyedBy _: NestedKey.Type) -> KeyedEncodingContainer { self.codingPath.append(_BSONKey(index: self.count)) defer { self.codingPath.removeLast() } @@ -653,7 +667,8 @@ private struct _BSONUnkeyedEncodingContainer: UnkeyedEncodingContainer { self.container.add(dictionary) let container = _BSONKeyedEncodingContainer( - referencing: self.encoder, codingPath: self.codingPath, wrapping: dictionary) + referencing: self.encoder, codingPath: self.codingPath, wrapping: dictionary + ) return KeyedEncodingContainer(container) } @@ -667,7 +682,7 @@ private struct _BSONUnkeyedEncodingContainer: UnkeyedEncodingContainer { } public mutating func superEncoder() -> Encoder { - return _BSONReferencingEncoder(referencing: self.encoder, at: self.container.count, wrapping: self.container) + return _BSONReferencingEncoder(referencing: self.encoder, at: self.container.count, wrapping: self.container) } } @@ -680,7 +695,7 @@ extension _BSONEncoder: SingleValueEncodingContainer { } public func encodeNil() throws { - assertCanEncodeNewValue() + self.assertCanEncodeNewValue() self.storage.push(container: BSONNull()) } @@ -700,17 +715,17 @@ extension _BSONEncoder: SingleValueEncodingContainer { public func encode(_ value: Double) throws { try self.encodeBSONType(value) } private func encodeNumber(_ value: T) throws { - assertCanEncodeNewValue() + self.assertCanEncodeNewValue() self.storage.push(container: try self.boxNumber(value)) } private func encodeBSONType(_ value: T) throws { - assertCanEncodeNewValue() + self.assertCanEncodeNewValue() self.storage.push(container: value) } public func encode(_ value: T) throws { - assertCanEncodeNewValue() + self.assertCanEncodeNewValue() self.storage.push(container: try self.box(value)) } } @@ -726,10 +741,10 @@ private class MutableArray: BSONValue { fileprivate var array = [BSONValue]() fileprivate func add(_ value: BSONValue) { - array.append(value) + self.array.append(value) } - fileprivate var count: Int { return array.count } + fileprivate var count: Int { return self.array.count } fileprivate func insert(_ value: BSONValue, at index: Int) { self.array.insert(value, at: index) @@ -739,16 +754,19 @@ private class MutableArray: BSONValue { /// methods required by the BSONValue protocol that we don't actually need/use. MutableArray /// is just a BSONValue to simplify usage alongside true BSONValues within the encoder. - fileprivate func encode(to storage: DocumentStorage, forKey key: String) throws { + fileprivate func encode(to _: DocumentStorage, forKey _: String) throws { fatalError("`MutableArray` is not meant to be encoded to a `DocumentStorage`") } - internal static func from(iterator iter: DocumentIterator) -> BSON { + + internal static func from(iterator _: DocumentIterator) -> BSON { fatalError("`MutableArray` is not meant to be initialized from a `DocumentIterator`") } - fileprivate func encode(to encoder: Encoder) throws { + + fileprivate func encode(to _: Encoder) throws { fatalError("`MutableArray` is not meant to be encoded with an `Encoder`") } - required convenience init(from decoder: Decoder) throws { + + required convenience init(from _: Decoder) throws { fatalError("`MutableArray` is not meant to be initialized from a `Decoder`") } } @@ -771,18 +789,18 @@ private class MutableDictionary: BSONValue { guard let index = keys.firstIndex(of: key) else { return nil } - return values[index] + return self.values[index] } set(newValue) { if let newValue = newValue { - keys.append(key) - values.append(newValue) + self.keys.append(key) + self.values.append(newValue) } else { guard let index = keys.firstIndex(of: key) else { return } - values.remove(at: index) - keys.remove(at: index) + self.values.remove(at: index) + self.keys.remove(at: index) } } } @@ -790,8 +808,8 @@ private class MutableDictionary: BSONValue { /// Converts self to a `Document` with equivalent key-value pairs. fileprivate func asDocument() -> Document { var doc = Document() - for i in 0 ..< keys.count { - doc[keys[i]] = values[i].bson + for i in 0.. BSON { + internal static func from(iterator _: DocumentIterator) -> BSON { fatalError("`MutableDictionary` is not meant to be initialized from a `DocumentIterator`") } - fileprivate func encode(to encoder: Encoder) throws { + + fileprivate func encode(to _: Encoder) throws { fatalError("`MutableDictionary` is not meant to be encoded with an `Encoder`") } - fileprivate required convenience init(from decoder: Decoder) throws { + + fileprivate required convenience init(from _: Decoder) throws { fatalError("`MutableDictionary` is not meant to be initialized from a `Decoder`") } } @@ -818,7 +838,7 @@ private class MutableDictionary: BSONValue { private extension EncodingError { static func _numberError(at path: [CodingKey], value: T) -> EncodingError { let description = "Value \(String(describing: value)) of type \(type(of: value)) cannot be " + - "exactly represented by a BSON number type (Int, Int32, Int64 or Double)." + "exactly represented by a BSON number type (Int, Int32, Int64 or Double)." return .invalidValue(value, Context(codingPath: path, debugDescription: description)) } } diff --git a/Sources/MongoSwift/BSON/BSONValue.swift b/Sources/MongoSwift/BSON/BSONValue.swift index 8c5a29b24..6886219b2 100644 --- a/Sources/MongoSwift/BSON/BSONValue.swift +++ b/Sources/MongoSwift/BSON/BSONValue.swift @@ -25,17 +25,17 @@ public enum BSONType: UInt32 { /// UTC datetime, stored as UTC milliseconds since the Unix epoch case datetime = 0x09 /// Null value - case null = 0x0a + case null = 0x0A /// A regular expression - case regex = 0x0b + case regex = 0x0B /// A database pointer - deprecated - case dbPointer = 0x0c + case dbPointer = 0x0C /// Javascript code - case code = 0x0d + case code = 0x0D /// A symbol - deprecated - case symbol = 0x0e + case symbol = 0x0E /// JavaScript code w/ scope - case codeWithScope = 0x0f + case codeWithScope = 0x0F /// 32-bit integer case int32 = 0x10 /// Special internal type used by MongoDB replication and sharding @@ -45,9 +45,9 @@ public enum BSONType: UInt32 { /// 128-bit decimal floating point case decimal128 = 0x13 /// Special type which compares lower than all other possible BSON element values - case minKey = 0xff + case minKey = 0xFF /// Special type which compares higher than all other possible BSON element values - case maxKey = 0x7f + case maxKey = 0x7F } /// A protocol all types representing `BSONType`s must implement. @@ -133,7 +133,7 @@ extension Array: BSONValue where Element == BSON { } /// Attempts to map this `[BSON]` to a `[T]`, where `T` is a `BSONValue`. - internal func asArrayOf(_ type: T.Type) -> [T]? { + internal func asArrayOf(_: T.Type) -> [T]? { var result: [T] = [] for element in self { guard let bsonValue = element.bsonValue as? T else { @@ -159,7 +159,7 @@ internal struct BSONNull: BSONValue, Codable, Equatable { } /// Initializes a new `BSONNull` instance. - public init() { } + public init() {} public init(from decoder: Decoder) throws { throw getDecodingError(type: BSONNull.self, decoder: decoder) @@ -199,18 +199,18 @@ public struct Binary: BSONValue, Equatable, Codable, Hashable { public enum Subtype: UInt8 { /// Generic binary subtype case generic, - /// A function - function, - /// Binary (old) - binaryDeprecated, - /// UUID (old) - uuidDeprecated, - /// UUID (RFC 4122) - uuid, - /// MD5 - md5, - /// User defined - userDefined = 0x80 + /// A function + function, + /// Binary (old) + binaryDeprecated, + /// UUID (old) + uuidDeprecated, + /// UUID (RFC 4122) + uuid, + /// MD5 + md5, + /// User defined + userDefined = 0x80 } /// Initializes a `Binary` instance from a `UUID`. @@ -234,8 +234,10 @@ public struct Binary: BSONValue, Equatable, Codable, Hashable { /// - `UserError.invalidArgumentError` if the provided data is incompatible with the specified subtype. public init(data: Data, subtype: UInt8) throws { if [Subtype.uuid.rawValue, Subtype.uuidDeprecated.rawValue].contains(subtype) && data.count != 16 { - throw UserError.invalidArgumentError(message: - "Binary data with UUID subtype must be 16 bytes, but data has \(data.count) bytes") + throw UserError.invalidArgumentError( + message: + "Binary data with UUID subtype must be 16 bytes, but data has \(data.count) bytes" + ) } self.subtype = subtype self.data = data @@ -254,8 +256,10 @@ public struct Binary: BSONValue, Equatable, Codable, Hashable { /// incompatible with the specified subtype. public init(base64: String, subtype: UInt8) throws { guard let dataObj = Data(base64Encoded: base64) else { - throw UserError.invalidArgumentError(message: - "failed to create Data object from invalid base64 string \(base64)") + throw UserError.invalidArgumentError( + message: + "failed to create Data object from invalid base64 string \(base64)" + ) } try self.init(data: dataObj, subtype: subtype) } @@ -393,7 +397,7 @@ public struct DBPointer: BSONValue, Codable, Equatable, Hashable { } internal func encode(to storage: DocumentStorage, forKey key: String) throws { - try withUnsafePointer(to: id.oid) { oidPtr in + try withUnsafePointer(to: self.id.oid) { oidPtr in guard bson_append_dbpointer(storage._bson, key, Int32(key.utf8.count), self.ref, oidPtr) else { throw bsonTooLargeError(value: self, forKey: key) } @@ -501,7 +505,7 @@ public struct Decimal128: BSONValue, Equatable, Codable, CustomStringConvertible return Decimal128(bsonDecimal: value) }) - } + } } // An extension of `Decimal128` to add capability to be hashed @@ -841,16 +845,18 @@ extension UUID { /// - `UserError.invalidArgumentError` if a non-UUID subtype is set on the `Binary`. public init(from binary: Binary) throws { guard [Binary.Subtype.uuid.rawValue, Binary.Subtype.uuidDeprecated.rawValue].contains(binary.subtype) else { - throw UserError.invalidArgumentError(message: "Expected a UUID binary type " + - "(\(Binary.Subtype.uuid)), got \(binary.subtype) instead.") + throw UserError.invalidArgumentError( + message: "Expected a UUID binary type " + + "(\(Binary.Subtype.uuid)), got \(binary.subtype) instead." + ) } let data = binary.data let uuid: uuid_t = ( - data[0], data[1], data[2], data[3], - data[4], data[5], data[6], data[7], - data[8], data[9], data[10], data[11], - data[12], data[13], data[14], data[15] + data[0], data[1], data[2], data[3], + data[4], data[5], data[6], data[7], + data[8], data[9], data[10], data[11], + data[12], data[13], data[14], data[15] ) self.init(uuid: uuid) @@ -876,7 +882,7 @@ extension NSRegularExpression { var optsObj: NSRegularExpression.Options = [] for o in stringOptions { if let value = regexOptsMap[o] { - optsObj.update(with: value) + optsObj.update(with: value) } } return optsObj @@ -990,7 +996,8 @@ extension String: BSONValue { guard let out = self.init(rawStringData: strValue, length: Int(length)) else { throw RuntimeError.internalError( - message: "Underlying string data could not be parsed to a Swift String") + message: "Underlying string data could not be parsed to a Swift String" + ) } return out @@ -1006,7 +1013,7 @@ public struct Symbol: BSONValue, CustomStringConvertible, Codable, Equatable, Ha internal var bson: BSON { return .symbol(self) } public var description: String { - return stringValue + return self.stringValue } /// String representation of this `Symbol`. @@ -1026,11 +1033,12 @@ public struct Symbol: BSONValue, CustomStringConvertible, Codable, Equatable, Ha internal func encode(to storage: DocumentStorage, forKey key: String) throws { guard bson_append_symbol( - storage._bson, - key, - Int32(key.utf8.count), - self.stringValue, - Int32(self.stringValue.utf8.count)) else { + storage._bson, + key, + Int32(key.utf8.count), + self.stringValue, + Int32(self.stringValue.utf8.count) + ) else { throw bsonTooLargeError(value: self, forKey: key) } } @@ -1147,18 +1155,18 @@ private func bsonEncodingUnsupportedError(value: T, at codingPath: let description = "Encoding \(T.self) BSONValue type with a non-BSONEncoder is currently unsupported" return EncodingError.invalidValue( - value, - EncodingError.Context(codingPath: codingPath, debugDescription: description) + value, + EncodingError.Context(codingPath: codingPath, debugDescription: description) ) } /// Error thrown when a BSONValue type introduced by the driver (e.g. ObjectId) is decoded not using BSONDecoder -private func bsonDecodingUnsupportedError(type: T.Type, at codingPath: [CodingKey]) -> DecodingError { +private func bsonDecodingUnsupportedError(type _: T.Type, at codingPath: [CodingKey]) -> DecodingError { let description = "Initializing a \(T.self) BSONValue type with a non-BSONDecoder is currently unsupported" return DecodingError.typeMismatch( - T.self, - DecodingError.Context(codingPath: codingPath, debugDescription: description) + T.self, + DecodingError.Context(codingPath: codingPath, debugDescription: description) ) } @@ -1166,13 +1174,13 @@ private func bsonDecodingUnsupportedError(type: T.Type, at codingP * Error thrown when a `BSONValue` type introduced by the driver (e.g. ObjectId) is decoded directly via the top-level * `BSONDecoder`. */ -private func bsonDecodingDirectlyError(type: T.Type, at codingPath: [CodingKey]) -> DecodingError { +private func bsonDecodingDirectlyError(type _: T.Type, at codingPath: [CodingKey]) -> DecodingError { let description = "Cannot initialize BSONValue type \(T.self) directly from BSONDecoder. It must be decoded as " + - "a member of a struct or a class." + "a member of a struct or a class." return DecodingError.typeMismatch( - T.self, - DecodingError.Context(codingPath: codingPath, debugDescription: description) + T.self, + DecodingError.Context(codingPath: codingPath, debugDescription: description) ) } @@ -1187,7 +1195,7 @@ private func bsonDecodingDirectlyError(type: T.Type, at codingPath * - Encountering the wrong type of BSONValue (e.g. expected "_id" to be an `ObjectId`, got a `Document` instead) * - Attempting to decode a driver-introduced BSONValue with a non-BSONDecoder */ -internal func getDecodingError(type: T.Type, decoder: Decoder) -> DecodingError { +internal func getDecodingError(type _: T.Type, decoder: Decoder) -> DecodingError { if let bsonDecoder = decoder as? _BSONDecoder { // Cannot decode driver-introduced BSONValues directly if decoder.codingPath.isEmpty { @@ -1196,9 +1204,9 @@ internal func getDecodingError(type: T.Type, decoder: Decoder) -> // Got the wrong BSONValue type return DecodingError._typeMismatch( - at: decoder.codingPath, - expectation: T.self, - reality: bsonDecoder.storage.topContainer.bsonValue + at: decoder.codingPath, + expectation: T.self, + reality: bsonDecoder.storage.topContainer.bsonValue ) } @@ -1212,7 +1220,7 @@ extension Data { /// count > 0 so that the base address will exist.** /// Based on https://mjtsai.com/blog/2019/03/27/swift-5-released/ fileprivate mutating func withUnsafeMutableCStringPointer(body: (UnsafeMutablePointer) throws -> T) - rethrows -> T { + rethrows -> T { return try self.withUnsafeMutableBytes { (rawPtr: UnsafeMutableRawBufferPointer) in let bufferPtr = rawPtr.bindMemory(to: CChar.self) // baseAddress is non-nil as long as Data's count > 0. diff --git a/Sources/MongoSwift/BSON/CodableNumber.swift b/Sources/MongoSwift/BSON/CodableNumber.swift index de83d84be..59fec11f3 100644 --- a/Sources/MongoSwift/BSON/CodableNumber.swift +++ b/Sources/MongoSwift/BSON/CodableNumber.swift @@ -54,6 +54,7 @@ extension Int: CodableNumber { return BSON(self).bsonValue } } + extension Int32: CodableNumber {} extension Int64: CodableNumber {} diff --git a/Sources/MongoSwift/BSON/CodingStrategies.swift b/Sources/MongoSwift/BSON/CodingStrategies.swift index 6f19d03a3..60ee75f48 100644 --- a/Sources/MongoSwift/BSON/CodingStrategies.swift +++ b/Sources/MongoSwift/BSON/CodingStrategies.swift @@ -24,9 +24,11 @@ public struct BSONCoderOptions: CodingStrategyProvider { public var uuidCodingStrategy: UUIDCodingStrategy? /// Initializes a new `BSONCoderOptions`. - public init(dataCodingStrategy: DataCodingStrategy? = nil, - dateCodingStrategy: DateCodingStrategy? = nil, - uuidCodingStrategy: UUIDCodingStrategy? = nil) { + public init( + dataCodingStrategy: DataCodingStrategy? = nil, + dateCodingStrategy: DateCodingStrategy? = nil, + uuidCodingStrategy: UUIDCodingStrategy? = nil + ) { self.dataCodingStrategy = dataCodingStrategy self.dateCodingStrategy = dateCodingStrategy self.uuidCodingStrategy = uuidCodingStrategy diff --git a/Sources/MongoSwift/BSON/Document+Collection.swift b/Sources/MongoSwift/BSON/Document+Collection.swift index 3981c191a..f5ae7db27 100644 --- a/Sources/MongoSwift/BSON/Document+Collection.swift +++ b/Sources/MongoSwift/BSON/Document+Collection.swift @@ -19,7 +19,7 @@ extension Document: Collection { private func failIndexCheck(_ i: Index) { let invalidIndexMsg = "Index \(i) is invalid" - guard !self.isEmpty && self.startIndex ... self.endIndex - 1 ~= i else { + guard !self.isEmpty && self.startIndex...self.endIndex - 1 ~= i else { fatalError(invalidIndexMsg) } } @@ -27,7 +27,7 @@ extension Document: Collection { /// Returns the index after the given index for this Document. public func index(after i: Index) -> Index { // Index must be a valid one, meaning it must exist somewhere in self.keys. - failIndexCheck(i) + self.failIndexCheck(i) return i + 1 } @@ -37,7 +37,7 @@ extension Document: Collection { // TODO: This method _should_ guarantee constant-time O(1) access, and it is possible to make it do so. This // criticism also applies to key-based subscripting via `String`. // See SWIFT-250. - failIndexCheck(position) + self.failIndexCheck(position) guard let iter = DocumentIterator(forDocument: self) else { fatalError("Failed to initialize an iterator over document \(self)") } diff --git a/Sources/MongoSwift/BSON/Document+Sequence.swift b/Sources/MongoSwift/BSON/Document+Sequence.swift index 91b0625f6..c5b6165e8 100644 --- a/Sources/MongoSwift/BSON/Document+Sequence.swift +++ b/Sources/MongoSwift/BSON/Document+Sequence.swift @@ -203,15 +203,19 @@ extension Document: Sequence { * * - Returns: An array of documents, split from this document's key-value pairs. */ - public func split(maxSplits: Int = Int.max, - omittingEmptySubsequences: Bool = true, - whereSeparator isSeparator: (KeyValuePair) throws -> Bool) rethrows -> [Document] { + public func split( + maxSplits: Int = Int.max, + omittingEmptySubsequences: Bool = true, + whereSeparator isSeparator: (KeyValuePair) throws -> Bool + ) rethrows -> [Document] { // rather than implementing the complex logic necessary for split, convert to an array and call split on that let asArr = Array(self) // convert to a [[KeyValuePair]] - let splitArrs = try asArr.split(maxSplits: maxSplits, - omittingEmptySubsequences: omittingEmptySubsequences, - whereSeparator: isSeparator) + let splitArrs = try asArr.split( + maxSplits: maxSplits, + omittingEmptySubsequences: omittingEmptySubsequences, + whereSeparator: isSeparator + ) // convert each nested [KeyValuePair] back to a Document var output = [Document]() diff --git a/Sources/MongoSwift/BSON/Document.swift b/Sources/MongoSwift/BSON/Document.swift index 81162596e..b9e098539 100644 --- a/Sources/MongoSwift/BSON/Document.swift +++ b/Sources/MongoSwift/BSON/Document.swift @@ -155,9 +155,9 @@ extension Document { // swiftlint:disable:next force_unwrapping try DocumentIterator(forDocument: self, advancedTo: key)!.overwriteCurrentValue(with: ov) - // otherwise, we just create a new document and replace this key + // otherwise, we just create a new document and replace this key } else { - // TODO SWIFT-224: use va_list variant of bson_copy_to_excluding to improve performance + // TODO: SWIFT-224: use va_list variant of bson_copy_to_excluding to improve performance var newSelf = Document() var seen = false try self.forEach { pair in @@ -171,7 +171,7 @@ extension Document { self = newSelf } - // otherwise, it's a new key + // otherwise, it's a new key } else { self.copyStorageIfRequired() try newBSONValue.encode(to: self._storage, forKey: key) @@ -226,8 +226,10 @@ extension Document { bson_concat(selfPtr, doc._bson) } guard success else { - throw RuntimeError.internalError(message: "Failed to merge \(doc) with \(self). This is likely due to " + - "the merged document being too large.") + throw RuntimeError.internalError( + message: "Failed to merge \(doc) with \(self). This is likely due to " + + "the merged document being too large." + ) } } @@ -374,6 +376,7 @@ extension Document { // see https://www.objc.io/blog/2018/02/13/string-to-data-and-back/ try self.init(fromJSON: json.data(using: .utf8)!) // swiftlint:disable:this force_unwrapping } + /** * Constructs a `Document` from raw BSON `Data`. * - Throws: @@ -417,7 +420,7 @@ extension Document { if let newValue = newValue { try self.setValue(for: key, to: newValue) } else { - // TODO SWIFT-224: use va_list variant of bson_copy_to_excluding to improve performance + // TODO: SWIFT-224: use va_list variant of bson_copy_to_excluding to improve performance self = self.filter { $0.key != key } } } catch { @@ -534,8 +537,10 @@ extension Document: ExpressibleByDictionaryLiteral { } /// Executes the provided closure using a mutable pointer to the document's underlying storage. -internal func withMutableBSONPointer(to document: inout Document, - body: (MutableBSONPointer) throws -> T) rethrows -> T { +internal func withMutableBSONPointer( + to document: inout Document, + body: (MutableBSONPointer) throws -> T +) rethrows -> T { document.copyStorageIfRequired() return try body(document._storage._bson) } diff --git a/Sources/MongoSwift/BSON/DocumentIterator.swift b/Sources/MongoSwift/BSON/DocumentIterator.swift index 4a01c73fd..60f4c3747 100644 --- a/Sources/MongoSwift/BSON/DocumentIterator.swift +++ b/Sources/MongoSwift/BSON/DocumentIterator.swift @@ -51,21 +51,21 @@ public class DocumentIterator: IteratorProtocol { /// or if at the end of the document. Returns true otherwise. internal func advance() -> Bool { return self.withMutableBSONIterPointer { iterPtr in - bson_iter_next(iterPtr) + bson_iter_next(iterPtr) } } /// Moves the iterator to the specified key. Returns false if the key does not exist. Returns true otherwise. internal func move(to key: String) -> Bool { return self.withMutableBSONIterPointer { iterPtr in - bson_iter_find(iterPtr, key.cString(using: .utf8)) + bson_iter_find(iterPtr, key.cString(using: .utf8)) } } /// Returns the current key. Assumes the iterator is in a valid position. internal var currentKey: String { return self.withBSONIterPointer { iterPtr in - String(cString: bson_iter_key(iterPtr)) + String(cString: bson_iter_key(iterPtr)) } } @@ -81,7 +81,7 @@ public class DocumentIterator: IteratorProtocol { /// Returns the current value's type. Assumes the iterator is in a valid position. internal var currentType: BSONType { return self.withBSONIterPointer { iterPtr in - BSONType(rawValue: bson_iter_type(iterPtr).rawValue) ?? .invalid + BSONType(rawValue: bson_iter_type(iterPtr).rawValue) ?? .invalid } } @@ -108,7 +108,7 @@ public class DocumentIterator: IteratorProtocol { internal func safeCurrentValue() throws -> BSON { guard let bsonType = DocumentIterator.bsonTypeMap[currentType] else { throw RuntimeError.internalError( - message: "Unknown BSONType for iterator's current value with type: \(currentType)" + message: "Unknown BSONType for iterator's current value with type: \(self.currentType)" ) } @@ -133,7 +133,7 @@ public class DocumentIterator: IteratorProtocol { var output = Document() - // TODO SWIFT-224: use va_list variant of bson_copy_to_excluding to improve performance + // TODO: SWIFT-224: use va_list variant of bson_copy_to_excluding to improve performance for _ in startIndex..( - _ body: (MutableBSONIterPointer) throws -> Result + _ body: (MutableBSONIterPointer) throws -> Result ) rethrows -> Result { #if compiler(>=5.0) return try withUnsafeMutablePointer(to: &self._iter) { iterPtr in diff --git a/Sources/MongoSwift/ChangeStream.swift b/Sources/MongoSwift/ChangeStream.swift index 07cab87d4..ad910d77a 100644 --- a/Sources/MongoSwift/ChangeStream.swift +++ b/Sources/MongoSwift/ChangeStream.swift @@ -32,10 +32,12 @@ public class SyncChangeStream: Sequence, IteratorProtocol { /// Indicates that the change stream is still open. Stores a pointer to the `mongoc_change_stream_t`, along /// with the source connection, client, and possibly session to ensure they are kept alive as long /// as the change stream is. - case open(changeStream: OpaquePointer, - connection: Connection, - client: SyncMongoClient, - session: SyncClientSession?) + case open( + changeStream: OpaquePointer, + connection: Connection, + client: SyncMongoClient, + session: SyncClientSession? + ) case closed } @@ -142,13 +144,14 @@ public class SyncChangeStream: Sequence, IteratorProtocol { * - `ServerError.commandError` if an error occurred on the server when creating the `mongoc_change_stream_t`. * - `UserError.invalidArgumentError` if the `mongoc_change_stream_t` was created with invalid options. */ - internal init(stealing changeStream: OpaquePointer, - connection: Connection, - client: SyncMongoClient, - session: SyncClientSession?, - decoder: BSONDecoder, - options: ChangeStreamOptions? - ) throws { + internal init( + stealing changeStream: OpaquePointer, + connection: Connection, + client: SyncMongoClient, + session: SyncClientSession?, + decoder: BSONDecoder, + options: ChangeStreamOptions? + ) throws { self.state = .open(changeStream: changeStream, connection: connection, client: client, session: session) self.decoder = decoder diff --git a/Sources/MongoSwift/ChangeStreamOptions.swift b/Sources/MongoSwift/ChangeStreamOptions.swift index fd371112f..bd03f05c7 100644 --- a/Sources/MongoSwift/ChangeStreamOptions.swift +++ b/Sources/MongoSwift/ChangeStreamOptions.swift @@ -11,7 +11,7 @@ public enum FullDocument: RawRepresentable, Codable { switch self { case .updateLookup: return "updateLookup" - case .other(let v): + case let .other(v): return v } } @@ -65,7 +65,7 @@ public struct ChangeStreamOptions: Codable { * - Note: The server will report an error if `startAfter` and `resumeAfter` are both specified. * - SeeAlso: https://docs.mongodb.com/master/changeStreams/#change-stream-start-after */ - // TODO: SWIFT-519 - Make this public when support is added for 4.2 change stream features. + // TODO: SWIFT-519 - Make this public when support is added for 4.2 change stream features. internal var startAfter: ResumeToken? /// The change stream will only provide changes that occurred at or after the specified timestamp. @@ -74,12 +74,14 @@ public struct ChangeStreamOptions: Codable { public var startAtOperationTime: Timestamp? /// Initializes a `ChangeStreamOptions`. - public init(batchSize: Int32? = nil, - collation: Document? = nil, - fullDocument: FullDocument? = nil, - maxAwaitTimeMS: Int64? = nil, - resumeAfter: ResumeToken? = nil, - startAtOperationTime: Timestamp? = nil) { + public init( + batchSize: Int32? = nil, + collation: Document? = nil, + fullDocument: FullDocument? = nil, + maxAwaitTimeMS: Int64? = nil, + resumeAfter: ResumeToken? = nil, + startAtOperationTime: Timestamp? = nil + ) { self.batchSize = batchSize self.collation = collation self.fullDocument = fullDocument diff --git a/Sources/MongoSwift/ClientSession.swift b/Sources/MongoSwift/ClientSession.swift index 5e355028c..4b38ea5ea 100644 --- a/Sources/MongoSwift/ClientSession.swift +++ b/Sources/MongoSwift/ClientSession.swift @@ -16,8 +16,10 @@ public struct ClientSessionOptions { /// Private helper for providing a `mongoc_session_opt_t` that is only valid within the body of the provided /// closure. -private func withSessionOpts(wrapping options: ClientSessionOptions?, - _ body: (OpaquePointer) throws -> T) rethrows -> T { +private func withSessionOpts( + wrapping options: ClientSessionOptions?, + _ body: (OpaquePointer) throws -> T +) rethrows -> T { // swiftlint:disable:next force_unwrapping var opts = mongoc_session_opts_new()! // always returns a value defer { mongoc_session_opts_destroy(opts) } @@ -60,7 +62,8 @@ public final class SyncClientSession { internal static let SessionInactiveError = UserError.logicError(message: "Tried to use an inactive session") /// Error thrown when a user attempts to use a session with a client it was not created from. internal static let ClientMismatchError = UserError.invalidArgumentError( - message: "Sessions may only be used with the client used to create them") + message: "Sessions may only be used with the client used to create them" + ) /// Enum for tracking the state of a session. internal enum State { @@ -93,7 +96,7 @@ public final class SyncClientSession { /// - This session has been ended. public var clusterTime: Document? { guard case let .active(session, _) = self.state, - let time = mongoc_client_session_get_cluster_time(session) else { + let time = mongoc_client_session_get_cluster_time(session) else { return nil } return Document(copying: time) diff --git a/Sources/MongoSwift/Counter.swift b/Sources/MongoSwift/Counter.swift index 6ec6047cc..4d4d226ab 100644 --- a/Sources/MongoSwift/Counter.swift +++ b/Sources/MongoSwift/Counter.swift @@ -12,7 +12,7 @@ internal class Counter { /// Returns the next value in the counter. internal func next() -> Int { - return queue.sync { + return self.queue.sync { self.count += 1 return self.count } diff --git a/Sources/MongoSwift/MongoClient.swift b/Sources/MongoSwift/MongoClient.swift index 06e9a2fd4..944658a3a 100644 --- a/Sources/MongoSwift/MongoClient.swift +++ b/Sources/MongoSwift/MongoClient.swift @@ -33,7 +33,7 @@ public struct ClientOptions: CodingStrategyProvider, Decodable { public var readPreference: ReadPreference? = nil /// Determines whether the client should retry supported read operations. - /// TODO SWIFT-587 make this public. + // TODO: SWIFT-587 make this public. internal var retryReads: Bool? /// Determines whether the client should retry supported write operations. @@ -71,17 +71,19 @@ public struct ClientOptions: CodingStrategyProvider, Decodable { } /// Convenience initializer allowing any/all to be omitted or optional. - public init(commandMonitoring: Bool = false, - dataCodingStrategy: DataCodingStrategy? = nil, - dateCodingStrategy: DateCodingStrategy? = nil, - notificationCenter: NotificationCenter? = nil, - readConcern: ReadConcern? = nil, - readPreference: ReadPreference? = nil, - retryWrites: Bool? = nil, - serverMonitoring: Bool = false, - tlsOptions: TLSOptions? = nil, - uuidCodingStrategy: UUIDCodingStrategy? = nil, - writeConcern: WriteConcern? = nil) { + public init( + commandMonitoring: Bool = false, + dataCodingStrategy: DataCodingStrategy? = nil, + dateCodingStrategy: DateCodingStrategy? = nil, + notificationCenter: NotificationCenter? = nil, + readConcern: ReadConcern? = nil, + readPreference: ReadPreference? = nil, + retryWrites: Bool? = nil, + serverMonitoring: Bool = false, + tlsOptions: TLSOptions? = nil, + uuidCodingStrategy: UUIDCodingStrategy? = nil, + writeConcern: WriteConcern? = nil + ) { self.commandMonitoring = commandMonitoring self.dataCodingStrategy = dataCodingStrategy self.dateCodingStrategy = dateCodingStrategy @@ -121,12 +123,14 @@ public struct DatabaseOptions: CodingStrategyProvider { public var writeConcern: WriteConcern? /// Convenience initializer allowing any/all arguments to be omitted or optional. - public init(dataCodingStrategy: DataCodingStrategy? = nil, - dateCodingStrategy: DateCodingStrategy? = nil, - readConcern: ReadConcern? = nil, - readPreference: ReadPreference? = nil, - uuidCodingStrategy: UUIDCodingStrategy? = nil, - writeConcern: WriteConcern? = nil) { + public init( + dataCodingStrategy: DataCodingStrategy? = nil, + dateCodingStrategy: DateCodingStrategy? = nil, + readConcern: ReadConcern? = nil, + readPreference: ReadPreference? = nil, + uuidCodingStrategy: UUIDCodingStrategy? = nil, + writeConcern: WriteConcern? = nil + ) { self.dataCodingStrategy = dataCodingStrategy self.dateCodingStrategy = dateCodingStrategy self.readConcern = readConcern @@ -154,11 +158,13 @@ public struct TLSOptions { public var weakCertValidation: Bool? /// Convenience initializer allowing any/all arguments to be omitted or optional. - public init(allowInvalidHostnames: Bool? = nil, - caFile: URL? = nil, - pemFile: URL? = nil, - pemPassword: String? = nil, - weakCertValidation: Bool? = nil) { + public init( + allowInvalidHostnames: Bool? = nil, + caFile: URL? = nil, + pemFile: URL? = nil, + pemPassword: String? = nil, + weakCertValidation: Bool? = nil + ) { self.allowInvalidHostnames = allowInvalidHostnames self.caFile = caFile self.pemFile = pemFile @@ -239,18 +245,20 @@ public class SyncMongoClient { self.decoder = BSONDecoder(options: options) self.notificationCenter = options?.notificationCenter ?? NotificationCenter.default - self.connectionPool.initializeMonitoring(commandMonitoring: options?.commandMonitoring ?? false, - serverMonitoring: options?.serverMonitoring ?? false, - client: self) + self.connectionPool.initializeMonitoring( + commandMonitoring: options?.commandMonitoring ?? false, + serverMonitoring: options?.serverMonitoring ?? false, + client: self + ) } /** * :nodoc: */ - @available(*, deprecated, message: "Use SyncMongoClient(stealing:) instead.") - public convenience init(fromPointer pointer: OpaquePointer) { + @available(*, deprecated, message: "Use SyncMongoClient(stealing:) instead.") + public convenience init(fromPointer pointer: OpaquePointer) { self.init(stealing: pointer) - } + } /** * :nodoc: @@ -291,8 +299,10 @@ public class SyncMongoClient { * - Throws: * - `RuntimeError.compatibilityError` if the deployment does not support sessions. */ - public func withSession(options: ClientSessionOptions? = nil, - _ sessionBody: (SyncClientSession) throws -> T) throws -> T { + public func withSession( + options: ClientSessionOptions? = nil, + _ sessionBody: (SyncClientSession) throws -> T + ) throws -> T { let session = try SyncClientSession(client: self, options: options) defer { session.end() } return try sessionBody(session) @@ -314,11 +324,15 @@ public class SyncMongoClient { * * - SeeAlso: https://docs.mongodb.com/manual/reference/command/listDatabases/ */ - public func listDatabases(_ filter: Document? = nil, - session: SyncClientSession? = nil) throws -> [DatabaseSpecification] { - let operation = ListDatabasesOperation(client: self, - filter: filter, - nameOnly: nil) + public func listDatabases( + _ filter: Document? = nil, + session: SyncClientSession? = nil + ) throws -> [DatabaseSpecification] { + let operation = ListDatabasesOperation( + client: self, + filter: filter, + nameOnly: nil + ) guard case let .specs(result) = try self.executeOperation(operation, session: session) else { throw RuntimeError.internalError(message: "Invalid result") } @@ -337,8 +351,10 @@ public class SyncMongoClient { * - Throws: * - `UserError.logicError` if the provided session is inactive. */ - public func listMongoDatabases(_ filter: Document? = nil, - session: SyncClientSession? = nil) throws -> [SyncMongoDatabase] { + public func listMongoDatabases( + _ filter: Document? = nil, + session: SyncClientSession? = nil + ) throws -> [SyncMongoDatabase] { return try self.listDatabaseNames(filter, session: session).map { self.db($0) } } @@ -355,9 +371,11 @@ public class SyncMongoClient { * - `UserError.logicError` if the provided session is inactive. */ public func listDatabaseNames(_ filter: Document? = nil, session: SyncClientSession? = nil) throws -> [String] { - let operation = ListDatabasesOperation(client: self, - filter: filter, - nameOnly: true) + let operation = ListDatabasesOperation( + client: self, + filter: filter, + nameOnly: true + ) guard case let .names(result) = try self.executeOperation(operation, session: session) else { throw RuntimeError.internalError(message: "Invalid result") } @@ -404,9 +422,11 @@ public class SyncMongoClient { * * - Note: Supported in MongoDB version 4.0+ only. */ - public func watch(_ pipeline: [Document] = [], - options: ChangeStreamOptions? = nil, - session: SyncClientSession? = nil) throws -> SyncChangeStream> { + public func watch( + _ pipeline: [Document] = [], + options: ChangeStreamOptions? = nil, + session: SyncClientSession? = nil + ) throws -> SyncChangeStream> { return try self.watch(pipeline, options: options, session: session, withFullDocumentType: Document.self) } @@ -438,15 +458,19 @@ public class SyncMongoClient { * * - Note: Supported in MongoDB version 4.0+ only. */ - public func watch(_ pipeline: [Document] = [], - options: ChangeStreamOptions? = nil, - session: SyncClientSession? = nil, - withFullDocumentType: FullDocType.Type) - throws -> SyncChangeStream> { - return try self.watch(pipeline, - options: options, - session: session, - withEventType: ChangeStreamEvent.self) + public func watch( + _ pipeline: [Document] = [], + options: ChangeStreamOptions? = nil, + session: SyncClientSession? = nil, + withFullDocumentType _: FullDocType.Type + ) + throws -> SyncChangeStream> { + return try self.watch( + pipeline, + options: options, + session: session, + withEventType: ChangeStreamEvent.self + ) } /** @@ -476,21 +500,27 @@ public class SyncMongoClient { * * - Note: Supported in MongoDB version 4.0+ only. */ - public func watch(_ pipeline: [Document] = [], - options: ChangeStreamOptions? = nil, - session: SyncClientSession? = nil, - withEventType: EventType.Type) throws -> SyncChangeStream { + public func watch( + _ pipeline: [Document] = [], + options: ChangeStreamOptions? = nil, + session: SyncClientSession? = nil, + withEventType _: EventType.Type + ) throws -> SyncChangeStream { let connection = try resolveConnection(client: self, session: session) - let operation = try WatchOperation(target: .client(self), - pipeline: pipeline, - options: options, - stealing: connection) + let operation = try WatchOperation( + target: .client(self), + pipeline: pipeline, + options: options, + stealing: connection + ) return try self.executeOperation(operation, session: session) } /// Executes an `Operation` using this `SyncMongoClient` and an optionally provided session. - internal func executeOperation(_ operation: T, - session: SyncClientSession? = nil) throws -> T.OperationResult { + internal func executeOperation( + _ operation: T, + session: SyncClientSession? = nil + ) throws -> T.OperationResult { return try self.operationExecutor.execute(operation, client: self, session: session) } } diff --git a/Sources/MongoSwift/MongoCollection+BulkWrite.swift b/Sources/MongoSwift/MongoCollection+BulkWrite.swift index d4386c1f5..66f13c536 100644 --- a/Sources/MongoSwift/MongoCollection+BulkWrite.swift +++ b/Sources/MongoSwift/MongoCollection+BulkWrite.swift @@ -20,9 +20,11 @@ extension SyncMongoCollection { * - `EncodingError` if an error occurs while encoding the `CollectionType` or the options to BSON. */ @discardableResult - public func bulkWrite(_ requests: [WriteModel], - options: BulkWriteOptions? = nil, - session: SyncClientSession? = nil) throws -> BulkWriteResult? { + public func bulkWrite( + _ requests: [WriteModel], + options: BulkWriteOptions? = nil, + session: SyncClientSession? = nil + ) throws -> BulkWriteResult? { guard !requests.isEmpty else { throw UserError.invalidArgumentError(message: "requests cannot be empty") } @@ -96,11 +98,13 @@ public enum WriteModel { case let .replaceOne(filter, replacement, options): let replacement = try encoder.encode(replacement) let opts = try encoder.encode(options) - success = mongoc_bulk_operation_replace_one_with_opts(bulk, - filter._bson, - replacement._bson, - opts?._bson, - &error) + success = mongoc_bulk_operation_replace_one_with_opts( + bulk, + filter._bson, + replacement._bson, + opts?._bson, + &error + ) case let .updateOne(filter, update, options): let opts = try encoder.encode(options) @@ -137,7 +141,7 @@ public struct ReplaceOneModelOptions: Codable { /// When `true`, creates a new document if no document matches the query. public var upsert: Bool? - /// Initializer allowing any/all options to be omitted or optional. + /// Initializer allowing any/all options to be omitted or optional. public init(collation: Document? = nil, upsert: Bool? = nil) { self.collation = collation self.upsert = upsert @@ -214,10 +218,12 @@ internal struct BulkWriteOperation: Operation { let result = try BulkWriteResult(reply: reply, insertedIds: insertedIds) guard serverId != 0 else { - throw extractBulkWriteError(for: self, - error: error, - reply: reply, - partialResult: isAcknowledged ? result : nil) + throw extractBulkWriteError( + for: self, + error: error, + reply: reply, + partialResult: isAcknowledged ? result : nil + ) } return isAcknowledged ? result : nil @@ -292,9 +298,13 @@ public struct BulkWriteResult: Decodable { // None of the results must be present themselves, but at least one must. guard !container.allKeys.isEmpty else { - throw DecodingError.valueNotFound(BulkWriteResult.self, - DecodingError.Context(codingPath: decoder.codingPath, - debugDescription: "No results found")) + throw DecodingError.valueNotFound( + BulkWriteResult.self, + DecodingError.Context( + codingPath: decoder.codingPath, + debugDescription: "No results found" + ) + ) } self.deletedCount = try container.decodeIfPresent(Int.self, forKey: .deletedCount) ?? 0 @@ -354,13 +364,14 @@ public struct BulkWriteResult: Decodable { /// Internal initializer used for testing purposes and error handling. internal init( - deletedCount: Int? = nil, - insertedCount: Int? = nil, - insertedIds: [Int: BSON]? = nil, - matchedCount: Int? = nil, - modifiedCount: Int? = nil, - upsertedCount: Int? = nil, - upsertedIds: [Int: BSON]? = nil) { + deletedCount: Int? = nil, + insertedCount: Int? = nil, + insertedIds: [Int: BSON]? = nil, + matchedCount: Int? = nil, + modifiedCount: Int? = nil, + upsertedCount: Int? = nil, + upsertedIds: [Int: BSON]? = nil + ) { self.deletedCount = deletedCount ?? 0 self.insertedCount = insertedCount ?? 0 self.insertedIds = insertedIds ?? [:] diff --git a/Sources/MongoSwift/MongoCollection+ChangeStreams.swift b/Sources/MongoSwift/MongoCollection+ChangeStreams.swift index 6b1fc244b..c18baf914 100644 --- a/Sources/MongoSwift/MongoCollection+ChangeStreams.swift +++ b/Sources/MongoSwift/MongoCollection+ChangeStreams.swift @@ -24,9 +24,11 @@ extension SyncMongoCollection { * - https://docs.mongodb.com/manual/meta/aggregation-quick-reference/ * - https://docs.mongodb.com/manual/reference/system-collections/ */ - public func watch(_ pipeline: [Document] = [], - options: ChangeStreamOptions? = nil, - session: SyncClientSession? = nil) throws -> SyncChangeStream> { + public func watch( + _ pipeline: [Document] = [], + options: ChangeStreamOptions? = nil, + session: SyncClientSession? = nil + ) throws -> SyncChangeStream> { return try self.watch(pipeline, options: options, session: session, withFullDocumentType: CollectionType.self) } @@ -55,15 +57,19 @@ extension SyncMongoCollection { * - https://docs.mongodb.com/manual/meta/aggregation-quick-reference/ * - https://docs.mongodb.com/manual/reference/system-collections/ */ - public func watch(_ pipeline: [Document] = [], - options: ChangeStreamOptions? = nil, - session: SyncClientSession? = nil, - withFullDocumentType type: FullDocType.Type) - throws -> SyncChangeStream> { - return try self.watch(pipeline, - options: options, - session: session, - withEventType: ChangeStreamEvent.self) + public func watch( + _ pipeline: [Document] = [], + options: ChangeStreamOptions? = nil, + session: SyncClientSession? = nil, + withFullDocumentType _: FullDocType.Type + ) + throws -> SyncChangeStream> { + return try self.watch( + pipeline, + options: options, + session: session, + withEventType: ChangeStreamEvent.self + ) } /** @@ -90,15 +96,19 @@ extension SyncMongoCollection { * - https://docs.mongodb.com/manual/meta/aggregation-quick-reference/ * - https://docs.mongodb.com/manual/reference/system-collections/ */ - public func watch(_ pipeline: [Document] = [], - options: ChangeStreamOptions? = nil, - session: SyncClientSession? = nil, - withEventType type: EventType.Type) throws -> SyncChangeStream { + public func watch( + _ pipeline: [Document] = [], + options: ChangeStreamOptions? = nil, + session: SyncClientSession? = nil, + withEventType _: EventType.Type + ) throws -> SyncChangeStream { let connection = try resolveConnection(client: self._client, session: session) - let operation = try WatchOperation(target: .collection(self), - pipeline: pipeline, - options: options, - stealing: connection) + let operation = try WatchOperation( + target: .collection(self), + pipeline: pipeline, + options: options, + stealing: connection + ) return try self._client.executeOperation(operation, session: session) } } diff --git a/Sources/MongoSwift/MongoCollection+FindAndModify.swift b/Sources/MongoSwift/MongoCollection+FindAndModify.swift index abd1b58ee..a820b1a13 100644 --- a/Sources/MongoSwift/MongoCollection+FindAndModify.swift +++ b/Sources/MongoSwift/MongoCollection+FindAndModify.swift @@ -20,9 +20,11 @@ extension SyncMongoCollection { * - `DecodingError` if the deleted document cannot be decoded to a `CollectionType` value. */ @discardableResult - public func findOneAndDelete(_ filter: Document, - options: FindOneAndDeleteOptions? = nil, - session: SyncClientSession? = nil) throws -> CollectionType? { + public func findOneAndDelete( + _ filter: Document, + options: FindOneAndDeleteOptions? = nil, + session: SyncClientSession? = nil + ) throws -> CollectionType? { // we need to always send options here in order to ensure the `remove` flag is set let opts = options ?? FindOneAndDeleteOptions() return try self.findAndModify(filter: filter, options: opts, session: session) @@ -49,10 +51,12 @@ extension SyncMongoCollection { * - `EncodingError` if `replacement` cannot be encoded to a `Document`. */ @discardableResult - public func findOneAndReplace(filter: Document, - replacement: CollectionType, - options: FindOneAndReplaceOptions? = nil, - session: SyncClientSession? = nil) throws -> CollectionType? { + public func findOneAndReplace( + filter: Document, + replacement: CollectionType, + options: FindOneAndReplaceOptions? = nil, + session: SyncClientSession? = nil + ) throws -> CollectionType? { let update = try self.encoder.encode(replacement) return try self.findAndModify(filter: filter, update: update, options: options, session: session) } @@ -77,10 +81,12 @@ extension SyncMongoCollection { * - `DecodingError` if the updated document cannot be decoded to a `CollectionType` value. */ @discardableResult - public func findOneAndUpdate(filter: Document, - update: Document, - options: FindOneAndUpdateOptions? = nil, - session: SyncClientSession? = nil) throws -> CollectionType? { + public func findOneAndUpdate( + filter: Document, + update: Document, + options: FindOneAndUpdateOptions? = nil, + session: SyncClientSession? = nil + ) throws -> CollectionType? { return try self.findAndModify(filter: filter, update: update, options: options, session: session) } @@ -94,10 +100,12 @@ extension SyncMongoCollection { * - `ServerError.writeError` if an error occurs while executing the command. * - `DecodingError` if the updated document cannot be decoded to a `CollectionType` value. */ - private func findAndModify(filter: Document, - update: Document? = nil, - options: FindAndModifyOptionsConvertible? = nil, - session: SyncClientSession?) throws -> CollectionType? { + private func findAndModify( + filter: Document, + update: Document? = nil, + options: FindAndModifyOptionsConvertible? = nil, + session: SyncClientSession? + ) throws -> CollectionType? { let operation = FindAndModifyOperation(collection: self, filter: filter, update: update, options: options) return try self._client.executeOperation(operation, session: session) } @@ -137,20 +145,24 @@ public struct FindOneAndDeleteOptions: FindAndModifyOptionsConvertible, Decodabl public var writeConcern: WriteConcern? internal func asFindAndModifyOptions() throws -> FindAndModifyOptions { - return try FindAndModifyOptions(collation: collation, - maxTimeMS: maxTimeMS, - projection: projection, - remove: true, - sort: sort, - writeConcern: writeConcern) + return try FindAndModifyOptions( + collation: self.collation, + maxTimeMS: self.maxTimeMS, + projection: self.projection, + remove: true, + sort: self.sort, + writeConcern: self.writeConcern + ) } /// Convenience initializer allowing any/all parameters to be omitted/optional - public init(collation: Document? = nil, - maxTimeMS: Int64? = nil, - projection: Document? = nil, - sort: Document? = nil, - writeConcern: WriteConcern? = nil) { + public init( + collation: Document? = nil, + maxTimeMS: Int64? = nil, + projection: Document? = nil, + sort: Document? = nil, + writeConcern: WriteConcern? = nil + ) { self.collation = collation self.maxTimeMS = maxTimeMS self.projection = projection @@ -186,25 +198,29 @@ public struct FindOneAndReplaceOptions: FindAndModifyOptionsConvertible, Decodab public var writeConcern: WriteConcern? internal func asFindAndModifyOptions() throws -> FindAndModifyOptions { - return try FindAndModifyOptions(bypassDocumentValidation: bypassDocumentValidation, - collation: collation, - maxTimeMS: maxTimeMS, - projection: projection, - returnDocument: returnDocument, - sort: sort, - upsert: upsert, - writeConcern: writeConcern) + return try FindAndModifyOptions( + bypassDocumentValidation: self.bypassDocumentValidation, + collation: self.collation, + maxTimeMS: self.maxTimeMS, + projection: self.projection, + returnDocument: self.returnDocument, + sort: self.sort, + upsert: self.upsert, + writeConcern: self.writeConcern + ) } /// Convenience initializer allowing any/all parameters to be omitted/optional. - public init(bypassDocumentValidation: Bool? = nil, - collation: Document? = nil, - maxTimeMS: Int64? = nil, - projection: Document? = nil, - returnDocument: ReturnDocument? = nil, - sort: Document? = nil, - upsert: Bool? = nil, - writeConcern: WriteConcern? = nil) { + public init( + bypassDocumentValidation: Bool? = nil, + collation: Document? = nil, + maxTimeMS: Int64? = nil, + projection: Document? = nil, + returnDocument: ReturnDocument? = nil, + sort: Document? = nil, + upsert: Bool? = nil, + writeConcern: WriteConcern? = nil + ) { self.bypassDocumentValidation = bypassDocumentValidation self.collation = collation self.maxTimeMS = maxTimeMS @@ -246,27 +262,31 @@ public struct FindOneAndUpdateOptions: FindAndModifyOptionsConvertible, Decodabl public var writeConcern: WriteConcern? internal func asFindAndModifyOptions() throws -> FindAndModifyOptions { - return try FindAndModifyOptions(arrayFilters: arrayFilters, - bypassDocumentValidation: bypassDocumentValidation, - collation: collation, - maxTimeMS: maxTimeMS, - projection: projection, - returnDocument: returnDocument, - sort: sort, - upsert: upsert, - writeConcern: writeConcern) + return try FindAndModifyOptions( + arrayFilters: self.arrayFilters, + bypassDocumentValidation: self.bypassDocumentValidation, + collation: self.collation, + maxTimeMS: self.maxTimeMS, + projection: self.projection, + returnDocument: self.returnDocument, + sort: self.sort, + upsert: self.upsert, + writeConcern: self.writeConcern + ) } /// Convenience initializer allowing any/all parameters to be omitted/optional. - public init(arrayFilters: [Document]? = nil, - bypassDocumentValidation: Bool? = nil, - collation: Document? = nil, - maxTimeMS: Int64? = nil, - projection: Document? = nil, - returnDocument: ReturnDocument? = nil, - sort: Document? = nil, - upsert: Bool? = nil, - writeConcern: WriteConcern? = nil) { + public init( + arrayFilters: [Document]? = nil, + bypassDocumentValidation: Bool? = nil, + collation: Document? = nil, + maxTimeMS: Int64? = nil, + projection: Document? = nil, + returnDocument: ReturnDocument? = nil, + sort: Document? = nil, + upsert: Bool? = nil, + writeConcern: WriteConcern? = nil + ) { self.arrayFilters = arrayFilters self.bypassDocumentValidation = bypassDocumentValidation self.collation = collation diff --git a/Sources/MongoSwift/MongoCollection+Indexes.swift b/Sources/MongoSwift/MongoCollection+Indexes.swift index 8ac4d6777..1343da7b1 100644 --- a/Sources/MongoSwift/MongoCollection+Indexes.swift +++ b/Sources/MongoSwift/MongoCollection+Indexes.swift @@ -26,7 +26,7 @@ public struct IndexModel: Codable { public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) - try container.encode(keys, forKey: .key) + try container.encode(self.keys, forKey: .key) try self.options?.encode(to: encoder) } @@ -107,24 +107,26 @@ public struct IndexOptions: Codable { public var weights: Document? /// Convenience initializer allowing any/all parameters to be omitted. - public init(background: Bool? = nil, - bits: Int32? = nil, - bucketSize: Int32? = nil, - collation: Document? = nil, - defaultLanguage: String? = nil, - expireAfterSeconds: Int32? = nil, - languageOverride: String? = nil, - max: Double? = nil, - min: Double? = nil, - name: String? = nil, - partialFilterExpression: Document? = nil, - sparse: Bool? = nil, - sphereIndexVersion: Int32? = nil, - storageEngine: Document? = nil, - textIndexVersion: Int32? = nil, - unique: Bool? = nil, - version: Int32? = nil, - weights: Document? = nil) { + public init( + background: Bool? = nil, + bits: Int32? = nil, + bucketSize: Int32? = nil, + collation: Document? = nil, + defaultLanguage: String? = nil, + expireAfterSeconds: Int32? = nil, + languageOverride: String? = nil, + max: Double? = nil, + min: Double? = nil, + name: String? = nil, + partialFilterExpression: Document? = nil, + sparse: Bool? = nil, + sphereIndexVersion: Int32? = nil, + storageEngine: Document? = nil, + textIndexVersion: Int32? = nil, + unique: Bool? = nil, + version: Int32? = nil, + weights: Document? = nil + ) { self.background = background self.bits = bits self.bucketSize = bucketSize @@ -174,13 +176,17 @@ extension SyncMongoCollection { * - `EncodingError` if an error occurs while encoding the index specification or options. */ @discardableResult - public func createIndex(_ keys: Document, - indexOptions: IndexOptions? = nil, - options: CreateIndexOptions? = nil, - session: SyncClientSession? = nil) throws -> String { - return try createIndexes([IndexModel(keys: keys, options: indexOptions)], - options: options, - session: session)[0] + public func createIndex( + _ keys: Document, + indexOptions: IndexOptions? = nil, + options: CreateIndexOptions? = nil, + session: SyncClientSession? = nil + ) throws -> String { + return try self.createIndexes( + [IndexModel(keys: keys, options: indexOptions)], + options: options, + session: session + )[0] } /** @@ -201,10 +207,12 @@ extension SyncMongoCollection { * - `EncodingError` if an error occurs while encoding the index specification or options. */ @discardableResult - public func createIndex(_ model: IndexModel, - options: CreateIndexOptions? = nil, - session: SyncClientSession? = nil) throws -> String { - return try createIndexes([model], options: options, session: session)[0] + public func createIndex( + _ model: IndexModel, + options: CreateIndexOptions? = nil, + session: SyncClientSession? = nil + ) throws -> String { + return try self.createIndexes([model], options: options, session: session)[0] } /** @@ -225,9 +233,11 @@ extension SyncMongoCollection { * - `EncodingError` if an error occurs while encoding the index specifications or options. */ @discardableResult - public func createIndexes(_ models: [IndexModel], - options: CreateIndexOptions? = nil, - session: SyncClientSession? = nil) throws -> [String] { + public func createIndexes( + _ models: [IndexModel], + options: CreateIndexOptions? = nil, + session: SyncClientSession? = nil + ) throws -> [String] { let operation = CreateIndexesOperation(collection: self, models: models, options: options) return try self._client.executeOperation(operation, session: session) } @@ -247,14 +257,18 @@ extension SyncMongoCollection { * - `EncodingError` if an error occurs while encoding the options. */ @discardableResult - public func dropIndex(_ name: String, - options: DropIndexOptions? = nil, - session: SyncClientSession? = nil) throws -> Document { + public func dropIndex( + _ name: String, + options: DropIndexOptions? = nil, + session: SyncClientSession? = nil + ) throws -> Document { guard name != "*" else { - throw UserError.invalidArgumentError(message: - "Invalid index name '*'; use dropIndexes() to drop all indexes") + throw UserError.invalidArgumentError( + message: + "Invalid index name '*'; use dropIndexes() to drop all indexes" + ) } - return try _dropIndexes(index: .string(name), options: options, session: session) + return try self._dropIndexes(index: .string(name), options: options, session: session) } /** @@ -275,10 +289,12 @@ extension SyncMongoCollection { * - `EncodingError` if an error occurs while encoding the options. */ @discardableResult - public func dropIndex(_ keys: Document, - options: DropIndexOptions? = nil, - session: SyncClientSession? = nil) throws -> Document { - return try _dropIndexes(index: .document(keys), options: options, session: session) + public func dropIndex( + _ keys: Document, + options: DropIndexOptions? = nil, + session: SyncClientSession? = nil + ) throws -> Document { + return try self._dropIndexes(index: .document(keys), options: options, session: session) } /** @@ -299,10 +315,12 @@ extension SyncMongoCollection { * - `EncodingError` if an error occurs while encoding the options. */ @discardableResult - public func dropIndex(_ model: IndexModel, - options: DropIndexOptions? = nil, - session: SyncClientSession? = nil) throws -> Document { - return try _dropIndexes(index: .document(model.keys), options: options, session: session) + public func dropIndex( + _ model: IndexModel, + options: DropIndexOptions? = nil, + session: SyncClientSession? = nil + ) throws -> Document { + return try self._dropIndexes(index: .document(model.keys), options: options, session: session) } /** @@ -323,14 +341,16 @@ extension SyncMongoCollection { */ @discardableResult public func dropIndexes(options: DropIndexOptions? = nil, session: SyncClientSession? = nil) throws -> Document { - return try _dropIndexes(index: "*", options: options, session: session) + return try self._dropIndexes(index: "*", options: options, session: session) } /// Internal helper to drop an index. `index` must either be an index specification document or a /// string index name. - private func _dropIndexes(index: BSON, - options: DropIndexOptions?, - session: SyncClientSession?) throws -> Document { + private func _dropIndexes( + index: BSON, + options: DropIndexOptions?, + session: SyncClientSession? + ) throws -> Document { let operation = DropIndexesOperation(collection: self, index: index, options: options) return try self._client.executeOperation(operation, session: session) } diff --git a/Sources/MongoSwift/MongoCollection+Read.swift b/Sources/MongoSwift/MongoCollection+Read.swift index dac0724c8..9a22ad4f3 100644 --- a/Sources/MongoSwift/MongoCollection+Read.swift +++ b/Sources/MongoSwift/MongoCollection+Read.swift @@ -17,15 +17,19 @@ extension SyncMongoCollection { * - `UserError.logicError` if the provided session is inactive. * - `EncodingError` if an error occurs while encoding the options to BSON. */ - public func find(_ filter: Document = [:], - options: FindOptions? = nil, - session: SyncClientSession? = nil) throws -> SyncMongoCursor { + public func find( + _ filter: Document = [:], + options: FindOptions? = nil, + session: SyncClientSession? = nil + ) throws -> SyncMongoCursor { let opts = try encodeOptions(options: options, session: session) let rp = options?.readPreference?._readPreference - return try SyncMongoCursor(client: self._client, - decoder: self.decoder, - session: session, - cursorType: options?.cursorType) { conn in + return try SyncMongoCursor( + client: self._client, + decoder: self.decoder, + session: session, + cursorType: options?.cursorType + ) { conn in self.withMongocCollection(from: conn) { collPtr in guard let cursor = mongoc_collection_find_with_opts(collPtr, filter._bson, opts?._bson, rp) else { fatalError(failedToRetrieveCursorMessage) @@ -50,20 +54,24 @@ extension SyncMongoCollection { * - `UserError.logicError` if the provided session is inactive. * - `EncodingError` if an error occurs while encoding the options to BSON. */ - public func aggregate(_ pipeline: [Document], - options: AggregateOptions? = nil, - session: SyncClientSession? = nil) throws -> SyncMongoCursor { + public func aggregate( + _ pipeline: [Document], + options: AggregateOptions? = nil, + session: SyncClientSession? = nil + ) throws -> SyncMongoCursor { let opts = try encodeOptions(options: options, session: session) let rp = options?.readPreference?._readPreference let pipeline: Document = ["pipeline": .array(pipeline.map { .document($0) })] return try SyncMongoCursor(client: self._client, decoder: self.decoder, session: session) { conn in self.withMongocCollection(from: conn) { collPtr in - guard let cursor = mongoc_collection_aggregate(collPtr, - MONGOC_QUERY_NONE, - pipeline._bson, - opts?._bson, - rp) else { + guard let cursor = mongoc_collection_aggregate( + collPtr, + MONGOC_QUERY_NONE, + pipeline._bson, + opts?._bson, + rp + ) else { fatalError(failedToRetrieveCursorMessage) } return cursor @@ -71,7 +79,7 @@ extension SyncMongoCollection { } } - // TODO SWIFT-133: mark this method deprecated https://jira.mongodb.org/browse/SWIFT-133 + // TODO: SWIFT-133: mark this method deprecated https://jira.mongodb.org/browse/SWIFT-133 /** * Counts the number of documents in this collection matching the provided filter. * @@ -87,9 +95,11 @@ extension SyncMongoCollection { * - `UserError.invalidArgumentError` if the options passed in form an invalid combination. * - `EncodingError` if an error occurs while encoding the options to BSON. */ - public func count(_ filter: Document = [:], - options: CountOptions? = nil, - session: SyncClientSession? = nil) throws -> Int { + public func count( + _ filter: Document = [:], + options: CountOptions? = nil, + session: SyncClientSession? = nil + ) throws -> Int { let operation = CountOperation(collection: self, filter: filter, options: options) return try self._client.executeOperation(operation, session: session) } @@ -104,10 +114,12 @@ extension SyncMongoCollection { * * - Returns: The count of the documents that matched the filter */ - private func countDocuments(_ filter: Document = [:], - options: CountDocumentsOptions? = nil, - session: SyncClientSession? = nil) throws -> Int { - // TODO SWIFT-133: implement this https://jira.mongodb.org/browse/SWIFT-133 + private func countDocuments( + _: Document = [:], + options _: CountDocumentsOptions? = nil, + session _: SyncClientSession? = nil + ) throws -> Int { + // TODO: SWIFT-133: implement this https://jira.mongodb.org/browse/SWIFT-133 throw UserError.logicError(message: "Unimplemented command") } @@ -120,9 +132,11 @@ extension SyncMongoCollection { * * - Returns: an estimate of the count of documents in this collection */ - private func estimatedDocumentCount(options: EstimatedDocumentCountOptions? = nil, - session: SyncClientSession? = nil) throws -> Int { - // TODO SWIFT-133: implement this https://jira.mongodb.org/browse/SWIFT-133 + private func estimatedDocumentCount( + options _: EstimatedDocumentCountOptions? = nil, + session _: SyncClientSession? = nil + ) throws -> Int { + // TODO: SWIFT-133: implement this https://jira.mongodb.org/browse/SWIFT-133 throw UserError.logicError(message: "Unimplemented command") } @@ -143,10 +157,12 @@ extension SyncMongoCollection { * - `UserError.logicError` if the provided session is inactive. * - `EncodingError` if an error occurs while encoding the options to BSON. */ - public func distinct(fieldName: String, - filter: Document = [:], - options: DistinctOptions? = nil, - session: SyncClientSession? = nil) throws -> [BSON] { + public func distinct( + fieldName: String, + filter: Document = [:], + options: DistinctOptions? = nil, + session: SyncClientSession? = nil + ) throws -> [BSON] { let operation = DistinctOperation(collection: self, fieldName: fieldName, filter: filter, options: options) return try self._client.executeOperation(operation, session: session) } @@ -217,16 +233,18 @@ public struct AggregateOptions: Codable { public var writeConcern: WriteConcern? /// Convenience initializer allowing any/all parameters to be omitted or optional. - public init(allowDiskUse: Bool? = nil, - batchSize: Int32? = nil, - bypassDocumentValidation: Bool? = nil, - collation: Document? = nil, - comment: String? = nil, - hint: Hint? = nil, - maxTimeMS: Int64? = nil, - readConcern: ReadConcern? = nil, - readPreference: ReadPreference? = nil, - writeConcern: WriteConcern? = nil) { + public init( + allowDiskUse: Bool? = nil, + batchSize: Int32? = nil, + bypassDocumentValidation: Bool? = nil, + collation: Document? = nil, + comment: String? = nil, + hint: Hint? = nil, + maxTimeMS: Int64? = nil, + readConcern: ReadConcern? = nil, + readPreference: ReadPreference? = nil, + writeConcern: WriteConcern? = nil + ) { self.allowDiskUse = allowDiskUse self.batchSize = batchSize self.bypassDocumentValidation = bypassDocumentValidation @@ -397,26 +415,28 @@ public struct FindOptions: Codable { // swiftlint:enable redundant_optional_initialization /// Convenience initializer allowing any/all parameters to be omitted or optional. - public init(allowPartialResults: Bool? = nil, - batchSize: Int32? = nil, - collation: Document? = nil, - comment: String? = nil, - cursorType: CursorType? = nil, - hint: Hint? = nil, - limit: Int64? = nil, - max: Document? = nil, - maxAwaitTimeMS: Int64? = nil, - maxScan: Int64? = nil, - maxTimeMS: Int64? = nil, - min: Document? = nil, - noCursorTimeout: Bool? = nil, - projection: Document? = nil, - readConcern: ReadConcern? = nil, - readPreference: ReadPreference? = nil, - returnKey: Bool? = nil, - showRecordId: Bool? = nil, - skip: Int64? = nil, - sort: Document? = nil) { + public init( + allowPartialResults: Bool? = nil, + batchSize: Int32? = nil, + collation: Document? = nil, + comment: String? = nil, + cursorType: CursorType? = nil, + hint: Hint? = nil, + limit: Int64? = nil, + max: Document? = nil, + maxAwaitTimeMS: Int64? = nil, + maxScan: Int64? = nil, + maxTimeMS: Int64? = nil, + min: Document? = nil, + noCursorTimeout: Bool? = nil, + projection: Document? = nil, + readConcern: ReadConcern? = nil, + readPreference: ReadPreference? = nil, + returnKey: Bool? = nil, + showRecordId: Bool? = nil, + skip: Int64? = nil, + sort: Document? = nil + ) { self.allowPartialResults = allowPartialResults self.batchSize = batchSize self.collation = collation diff --git a/Sources/MongoSwift/MongoCollection+Write.swift b/Sources/MongoSwift/MongoCollection+Write.swift index cb1aaa40c..38e682000 100644 --- a/Sources/MongoSwift/MongoCollection+Write.swift +++ b/Sources/MongoSwift/MongoCollection+Write.swift @@ -22,13 +22,17 @@ extension SyncMongoCollection { * - `EncodingError` if an error occurs while encoding the `CollectionType` to BSON. */ @discardableResult - public func insertOne(_ value: CollectionType, - options: InsertOneOptions? = nil, - session: SyncClientSession? = nil) throws -> InsertOneResult? { + public func insertOne( + _ value: CollectionType, + options: InsertOneOptions? = nil, + session: SyncClientSession? = nil + ) throws -> InsertOneResult? { return try convertingBulkWriteErrors { - let result = try self.bulkWrite([.insertOne(value)], - options: options?.asBulkWriteOptions(), - session: session) + let result = try self.bulkWrite( + [.insertOne(value)], + options: options?.asBulkWriteOptions(), + session: session + ) return try InsertOneResult(from: result) } } @@ -52,9 +56,11 @@ extension SyncMongoCollection { * - `EncodingError` if an error occurs while encoding the `CollectionType` or options to BSON. */ @discardableResult - public func insertMany(_ values: [CollectionType], - options: InsertManyOptions? = nil, - session: SyncClientSession? = nil) throws -> InsertManyResult? { + public func insertMany( + _ values: [CollectionType], + options: InsertManyOptions? = nil, + session: SyncClientSession? = nil + ) throws -> InsertManyResult? { let result = try self.bulkWrite(values.map { .insertOne($0) }, options: options, session: session) return InsertManyResult(from: result) } @@ -79,10 +85,12 @@ extension SyncMongoCollection { * - `EncodingError` if an error occurs while encoding the `CollectionType` or options to BSON. */ @discardableResult - public func replaceOne(filter: Document, - replacement: CollectionType, - options: ReplaceOptions? = nil, - session: SyncClientSession? = nil) throws -> UpdateResult? { + public func replaceOne( + filter: Document, + replacement: CollectionType, + options: ReplaceOptions? = nil, + session: SyncClientSession? = nil + ) throws -> UpdateResult? { return try convertingBulkWriteErrors { let modelOptions = ReplaceOneModelOptions(collation: options?.collation, upsert: options?.upsert) let model = WriteModel.replaceOne(filter: filter, replacement: replacement, options: modelOptions) @@ -111,14 +119,18 @@ extension SyncMongoCollection { * - `EncodingError` if an error occurs while encoding the options to BSON. */ @discardableResult - public func updateOne(filter: Document, - update: Document, - options: UpdateOptions? = nil, - session: SyncClientSession? = nil) throws -> UpdateResult? { + public func updateOne( + filter: Document, + update: Document, + options: UpdateOptions? = nil, + session: SyncClientSession? = nil + ) throws -> UpdateResult? { return try convertingBulkWriteErrors { - let modelOptions = UpdateModelOptions(arrayFilters: options?.arrayFilters, - collation: options?.collation, - upsert: options?.upsert) + let modelOptions = UpdateModelOptions( + arrayFilters: options?.arrayFilters, + collation: options?.collation, + upsert: options?.upsert + ) let model: WriteModel = .updateOne(filter: filter, update: update, options: modelOptions) let result = try self.bulkWrite([model], options: options?.asBulkWriteOptions(), session: session) return try UpdateResult(from: result) @@ -145,14 +157,18 @@ extension SyncMongoCollection { * - `EncodingError` if an error occurs while encoding the options to BSON. */ @discardableResult - public func updateMany(filter: Document, - update: Document, - options: UpdateOptions? = nil, - session: SyncClientSession? = nil) throws -> UpdateResult? { + public func updateMany( + filter: Document, + update: Document, + options: UpdateOptions? = nil, + session: SyncClientSession? = nil + ) throws -> UpdateResult? { return try convertingBulkWriteErrors { - let modelOptions = UpdateModelOptions(arrayFilters: options?.arrayFilters, - collation: options?.collation, - upsert: options?.upsert) + let modelOptions = UpdateModelOptions( + arrayFilters: options?.arrayFilters, + collation: options?.collation, + upsert: options?.upsert + ) let model: WriteModel = .updateMany(filter: filter, update: update, options: modelOptions) let result = try self.bulkWrite([model], options: options?.asBulkWriteOptions(), session: session) return try UpdateResult(from: result) @@ -178,9 +194,11 @@ extension SyncMongoCollection { * - `EncodingError` if an error occurs while encoding the options to BSON. */ @discardableResult - public func deleteOne(_ filter: Document, - options: DeleteOptions? = nil, - session: SyncClientSession? = nil) throws -> DeleteResult? { + public func deleteOne( + _ filter: Document, + options: DeleteOptions? = nil, + session: SyncClientSession? = nil + ) throws -> DeleteResult? { return try convertingBulkWriteErrors { let modelOptions = DeleteModelOptions(collation: options?.collation) let model: WriteModel = .deleteOne(filter, options: modelOptions) @@ -208,9 +226,11 @@ extension SyncMongoCollection { * - `EncodingError` if an error occurs while encoding the options to BSON. */ @discardableResult - public func deleteMany(_ filter: Document, - options: DeleteOptions? = nil, - session: SyncClientSession? = nil) throws -> DeleteResult? { + public func deleteMany( + _ filter: Document, + options: DeleteOptions? = nil, + session: SyncClientSession? = nil + ) throws -> DeleteResult? { return try convertingBulkWriteErrors { let modelOptions = DeleteModelOptions(collation: options?.collation) let model: WriteModel = .deleteMany(filter, options: modelOptions) @@ -230,8 +250,10 @@ private protocol BulkWriteOptionsConvertible { /// Default implementation of the protocol. private extension BulkWriteOptionsConvertible { func asBulkWriteOptions() -> BulkWriteOptions { - return BulkWriteOptions(bypassDocumentValidation: self.bypassDocumentValidation, - writeConcern: self.writeConcern) + return BulkWriteOptions( + bypassDocumentValidation: self.bypassDocumentValidation, + writeConcern: self.writeConcern + ) } } @@ -273,11 +295,13 @@ public struct UpdateOptions: Codable, BulkWriteOptionsConvertible { public var writeConcern: WriteConcern? /// Convenience initializer allowing any/all parameters to be optional - public init(arrayFilters: [Document]? = nil, - bypassDocumentValidation: Bool? = nil, - collation: Document? = nil, - upsert: Bool? = nil, - writeConcern: WriteConcern? = nil) { + public init( + arrayFilters: [Document]? = nil, + bypassDocumentValidation: Bool? = nil, + collation: Document? = nil, + upsert: Bool? = nil, + writeConcern: WriteConcern? = nil + ) { self.arrayFilters = arrayFilters self.bypassDocumentValidation = bypassDocumentValidation self.collation = collation @@ -301,10 +325,12 @@ public struct ReplaceOptions: Codable, BulkWriteOptionsConvertible { public var writeConcern: WriteConcern? /// Convenience initializer allowing any/all parameters to be optional - public init(bypassDocumentValidation: Bool? = nil, - collation: Document? = nil, - upsert: Bool? = nil, - writeConcern: WriteConcern? = nil) { + public init( + bypassDocumentValidation: Bool? = nil, + collation: Document? = nil, + upsert: Bool? = nil, + writeConcern: WriteConcern? = nil + ) { self.bypassDocumentValidation = bypassDocumentValidation self.collation = collation self.upsert = upsert @@ -320,11 +346,12 @@ public struct DeleteOptions: Codable, BulkWriteOptionsConvertible { /// An optional `WriteConcern` to use for the command. public var writeConcern: WriteConcern? - /// Convenience initializer allowing collation to be omitted or optional + /// Convenience initializer allowing collation to be omitted or optional public init(collation: Document? = nil, writeConcern: WriteConcern? = nil) { self.collation = collation self.writeConcern = writeConcern } + /// This is a requirement of the BulkWriteOptionsConvertible protocol. /// Since it does not apply to deletions, we just set it to nil. internal var bypassDocumentValidation: Bool? { return nil } diff --git a/Sources/MongoSwift/MongoCollection.swift b/Sources/MongoSwift/MongoCollection.swift index 5a45e448b..ffbb394fb 100644 --- a/Sources/MongoSwift/MongoCollection.swift +++ b/Sources/MongoSwift/MongoCollection.swift @@ -99,11 +99,15 @@ public struct SyncMongoCollection { /// Uses the provided `Connection` to get a pointer to a `mongoc_collection_t` corresponding to this /// `SyncMongoCollection`, and uses it to execute the given closure. The `mongoc_collection_t` is only valid for the /// body of the closure. The caller is *not responsible* for cleaning up the `mongoc_collection_t`. - internal func withMongocCollection(from connection: Connection, - body: (OpaquePointer) throws -> T) rethrows -> T { - guard let collection = mongoc_client_get_collection(connection.clientHandle, - self.namespace.db, - self.namespace.collection) else { + internal func withMongocCollection( + from connection: Connection, + body: (OpaquePointer) throws -> T + ) rethrows -> T { + guard let collection = mongoc_client_get_collection( + connection.clientHandle, + self.namespace.db, + self.namespace.collection + ) else { fatalError("Couldn't get collection '\(self.namespace)'") } defer { mongoc_collection_destroy(collection) } diff --git a/Sources/MongoSwift/MongoCursor.swift b/Sources/MongoSwift/MongoCursor.swift index 05933d820..6eca17b62 100644 --- a/Sources/MongoSwift/MongoCursor.swift +++ b/Sources/MongoSwift/MongoCursor.swift @@ -55,11 +55,13 @@ public class SyncMongoCursor: Sequence, IteratorProtocol { * - `UserError.invalidArgumentError` if the options passed to the command that generated this cursor formed an * invalid combination. */ - internal init(client: SyncMongoClient, - decoder: BSONDecoder, - session: SyncClientSession?, - cursorType: CursorType? = nil, - initializer: (Connection) -> OpaquePointer) throws { + internal init( + client: SyncMongoClient, + decoder: BSONDecoder, + session: SyncClientSession?, + cursorType: CursorType? = nil, + initializer: (Connection) -> OpaquePointer + ) throws { let connection = try resolveConnection(client: client, session: session) let cursor = initializer(connection) self.state = .open(cursor: cursor, connection: connection, client: client, session: session) diff --git a/Sources/MongoSwift/MongoDatabase.swift b/Sources/MongoSwift/MongoDatabase.swift index f1e71859d..1b440bc10 100644 --- a/Sources/MongoSwift/MongoDatabase.swift +++ b/Sources/MongoSwift/MongoDatabase.swift @@ -27,12 +27,14 @@ public struct CollectionOptions: CodingStrategyProvider { public var writeConcern: WriteConcern? /// Convenience initializer allowing any/all arguments to be omitted or optional. - public init(dataCodingStrategy: DataCodingStrategy? = nil, - dateCodingStrategy: DateCodingStrategy? = nil, - readConcern: ReadConcern? = nil, - readPreference: ReadPreference? = nil, - uuidCodingStrategy: UUIDCodingStrategy? = nil, - writeConcern: WriteConcern? = nil) { + public init( + dataCodingStrategy: DataCodingStrategy? = nil, + dateCodingStrategy: DateCodingStrategy? = nil, + readConcern: ReadConcern? = nil, + readPreference: ReadPreference? = nil, + uuidCodingStrategy: UUIDCodingStrategy? = nil, + writeConcern: WriteConcern? = nil + ) { self.dataCodingStrategy = dataCodingStrategy self.dateCodingStrategy = dateCodingStrategy self.readConcern = readConcern @@ -69,7 +71,7 @@ public struct SyncMongoDatabase { public let decoder: BSONDecoder /// The name of this database. - public var name: String { return namespace.db } + public var name: String { return self.namespace.db } /// The `ReadConcern` set on this database, or `nil` if one is not set. public let readConcern: ReadConcern? @@ -109,14 +111,14 @@ public struct SyncMongoDatabase { } /** - * Drops this database. - * - Parameters: - * - options: An optional `DropDatabaseOptions` to use when executing this command - * - session: An optional `SyncClientSession` to use for this command - * - * - Throws: - * - `ServerError.commandError` if an error occurs that prevents the command from executing. - */ + * Drops this database. + * - Parameters: + * - options: An optional `DropDatabaseOptions` to use when executing this command + * - session: An optional `SyncClientSession` to use for this command + * + * - Throws: + * - `ServerError.commandError` if an error occurs that prevents the command from executing. + */ public func drop(options: DropDatabaseOptions? = nil, session: SyncClientSession? = nil) throws { let operation = DropDatabaseOperation(database: self, options: options) return try self._client.executeOperation(operation, session: session) @@ -152,9 +154,11 @@ public struct SyncMongoDatabase { * * - Returns: the requested `SyncMongoCollection` */ - public func collection(_ name: String, - withType: T.Type, - options: CollectionOptions? = nil) -> SyncMongoCollection { + public func collection( + _ name: String, + withType _: T.Type, + options: CollectionOptions? = nil + ) -> SyncMongoCollection { return SyncMongoCollection(name: name, database: self, options: options) } @@ -174,9 +178,11 @@ public struct SyncMongoDatabase { * - `UserError.logicError` if the provided session is inactive. * - `EncodingError` if an error occurs while encoding the options to BSON. */ - public func createCollection(_ name: String, - options: CreateCollectionOptions? = nil, - session: SyncClientSession? = nil) throws -> SyncMongoCollection { + public func createCollection( + _ name: String, + options: CreateCollectionOptions? = nil, + session: SyncClientSession? = nil + ) throws -> SyncMongoCollection { return try self.createCollection(name, withType: Document.self, options: options, session: session) } @@ -199,10 +205,12 @@ public struct SyncMongoDatabase { * - `UserError.logicError` if the provided session is inactive. * - `EncodingError` if an error occurs while encoding the options to BSON. */ - public func createCollection(_ name: String, - withType type: T.Type, - options: CreateCollectionOptions? = nil, - session: SyncClientSession? = nil) throws -> SyncMongoCollection { + public func createCollection( + _ name: String, + withType type: T.Type, + options: CreateCollectionOptions? = nil, + session: SyncClientSession? = nil + ) throws -> SyncMongoCollection { let operation = CreateCollectionOperation(database: self, name: name, type: type, options: options) return try self._client.executeOperation(operation, session: session) } @@ -221,9 +229,11 @@ public struct SyncMongoDatabase { * - `userError.invalidArgumentError` if the options passed are an invalid combination. * - `UserError.logicError` if the provided session is inactive. */ - public func listCollections(_ filter: Document? = nil, - options: ListCollectionsOptions? = nil, - session: SyncClientSession? = nil) throws -> SyncMongoCursor { + public func listCollections( + _ filter: Document? = nil, + options: ListCollectionsOptions? = nil, + session: SyncClientSession? = nil + ) throws -> SyncMongoCursor { let operation = ListCollectionsOperation(database: self, nameOnly: false, filter: filter, options: options) guard case let .specs(result) = try self._client.executeOperation(operation, session: session) else { throw RuntimeError.internalError(message: "Invalid result") @@ -245,9 +255,11 @@ public struct SyncMongoDatabase { * - `userError.invalidArgumentError` if the options passed are an invalid combination. * - `UserError.logicError` if the provided session is inactive. */ - public func listMongoCollections(_ filter: Document? = nil, - options: ListCollectionsOptions? = nil, - session: SyncClientSession? = nil) throws -> [SyncMongoCollection] { + public func listMongoCollections( + _ filter: Document? = nil, + options: ListCollectionsOptions? = nil, + session: SyncClientSession? = nil + ) throws -> [SyncMongoCollection] { return try self.listCollectionNames(filter, options: options, session: session).map { self.collection($0) } } @@ -265,9 +277,11 @@ public struct SyncMongoDatabase { * - `userError.invalidArgumentError` if the options passed are an invalid combination. * - `UserError.logicError` if the provided session is inactive. */ - public func listCollectionNames(_ filter: Document? = nil, - options: ListCollectionsOptions? = nil, - session: SyncClientSession? = nil) throws -> [String] { + public func listCollectionNames( + _ filter: Document? = nil, + options: ListCollectionsOptions? = nil, + session: SyncClientSession? = nil + ) throws -> [String] { let operation = ListCollectionsOperation(database: self, nameOnly: true, filter: filter, options: options) guard case let .names(result) = try self._client.executeOperation(operation, session: session) else { throw RuntimeError.internalError(message: "Invalid result") @@ -293,9 +307,11 @@ public struct SyncMongoDatabase { * - `EncodingError` if an error occurs while encoding the options to BSON. */ @discardableResult - public func runCommand(_ command: Document, - options: RunCommandOptions? = nil, - session: SyncClientSession? = nil) throws -> Document { + public func runCommand( + _ command: Document, + options: RunCommandOptions? = nil, + session: SyncClientSession? = nil + ) throws -> Document { let operation = RunCommandOperation(database: self, command: command, options: options) return try self._client.executeOperation(operation, session: session) } @@ -323,9 +339,11 @@ public struct SyncMongoDatabase { * * - Note: Supported in MongoDB version 4.0+ only. */ - public func watch(_ pipeline: [Document] = [], - options: ChangeStreamOptions? = nil, - session: SyncClientSession? = nil) throws -> SyncChangeStream> { + public func watch( + _ pipeline: [Document] = [], + options: ChangeStreamOptions? = nil, + session: SyncClientSession? = nil + ) throws -> SyncChangeStream> { return try self.watch(pipeline, options: options, session: session, withFullDocumentType: Document.self) } @@ -356,15 +374,19 @@ public struct SyncMongoDatabase { * * - Note: Supported in MongoDB version 4.0+ only. */ - public func watch(_ pipeline: [Document] = [], - options: ChangeStreamOptions? = nil, - session: SyncClientSession? = nil, - withFullDocumentType: FullDocType.Type) - throws -> SyncChangeStream> { - return try self.watch(pipeline, - options: options, - session: session, - withEventType: ChangeStreamEvent.self) + public func watch( + _ pipeline: [Document] = [], + options: ChangeStreamOptions? = nil, + session: SyncClientSession? = nil, + withFullDocumentType _: FullDocType.Type + ) + throws -> SyncChangeStream> { + return try self.watch( + pipeline, + options: options, + session: session, + withEventType: ChangeStreamEvent.self + ) } /** @@ -393,15 +415,19 @@ public struct SyncMongoDatabase { * * - Note: Supported in MongoDB version 4.0+ only. */ - public func watch(_ pipeline: [Document] = [], - options: ChangeStreamOptions? = nil, - session: SyncClientSession? = nil, - withEventType: EventType.Type) throws -> SyncChangeStream { + public func watch( + _ pipeline: [Document] = [], + options: ChangeStreamOptions? = nil, + session: SyncClientSession? = nil, + withEventType _: EventType.Type + ) throws -> SyncChangeStream { let connection = try resolveConnection(client: self._client, session: session) - let operation = try WatchOperation(target: .database(self), - pipeline: pipeline, - options: options, - stealing: connection) + let operation = try WatchOperation( + target: .database(self), + pipeline: pipeline, + options: options, + stealing: connection + ) return try self._client.executeOperation(operation, session: session) } diff --git a/Sources/MongoSwift/MongoError.swift b/Sources/MongoSwift/MongoError.swift index ca255286a..e3200560e 100644 --- a/Sources/MongoSwift/MongoError.swift +++ b/Sources/MongoSwift/MongoError.swift @@ -24,11 +24,13 @@ public enum ServerError: MongoError { /// Note: `writeErrors` may not be present if the error experienced was a Write Concern related error. /// Note: `otherError` may be populated if a non-write error occurs as part of one of the operations (e.g. a /// connection failure occurs after already successfully performing a few inserts). - case bulkWriteError(writeErrors: [BulkWriteError]?, - writeConcernError: WriteConcernError?, - otherError: Error?, - result: BulkWriteResult?, - errorLabels: [String]?) + case bulkWriteError( + writeErrors: [BulkWriteError]?, + writeConcernError: WriteConcernError?, + otherError: Error?, + result: BulkWriteResult?, + errorLabels: [String]? + ) public var errorDescription: String? { switch self { @@ -219,10 +221,11 @@ private func parseMongocError(_ error: bson_error_t, reply: Document?) -> MongoE return UserError.invalidArgumentError(message: message) case (MONGOC_ERROR_SERVER, _): return ServerError.commandError( - code: ServerErrorCode(code.rawValue), - codeName: codeName, - message: message, - errorLabels: errorLabels) + code: ServerErrorCode(code.rawValue), + codeName: codeName, + message: message, + errorLabels: errorLabels + ) case (MONGOC_ERROR_STREAM, _), (MONGOC_ERROR_SERVER_SELECTION, MONGOC_ERROR_SERVER_SELECTION_FAILURE): return RuntimeError.connectionError(message: message, errorLabels: errorLabels) case (MONGOC_ERROR_CURSOR, MONGOC_ERROR_CURSOR_INVALID_CURSOR): @@ -232,8 +235,10 @@ private func parseMongocError(_ error: bson_error_t, reply: Document?) -> MongoE case (MONGOC_ERROR_PROTOCOL, MONGOC_ERROR_PROTOCOL_BAD_WIRE_VERSION): return RuntimeError.compatibilityError(message: message) default: - assert(errorLabels == nil, "errorLabels set on error, but were not thrown as a MongoError. " + - "Labels: \(errorLabels ?? [])") + assert( + errorLabels == nil, "errorLabels set on error, but were not thrown as a MongoError. " + + "Labels: \(errorLabels ?? [])" + ) return RuntimeError.internalError(message: message) } } @@ -242,18 +247,19 @@ private func parseMongocError(_ error: bson_error_t, reply: Document?) -> MongoE internal func extractMongoError(error bsonError: bson_error_t, reply: Document? = nil) -> MongoError { // if the reply is nil or writeErrors or writeConcernErrors aren't present, then this is likely a commandError. guard let serverReply: Document = reply, - !(serverReply["writeErrors"]?.arrayValue ?? []).isEmpty || - !(serverReply["writeConcernErrors"]?.arrayValue ?? []).isEmpty else { + !(serverReply["writeErrors"]?.arrayValue ?? []).isEmpty || + !(serverReply["writeConcernErrors"]?.arrayValue ?? []).isEmpty else { return parseMongocError(bsonError, reply: reply) } let fallback = RuntimeError.internalError( - message: "Got error from the server but couldn't parse it. Message: \(toErrorString(bsonError))") + message: "Got error from the server but couldn't parse it. Message: \(toErrorString(bsonError))" + ) do { var writeError: WriteError? if let writeErrors = serverReply["writeErrors"]?.arrayValue?.compactMap({ $0.documentValue }), - !writeErrors.isEmpty { + !writeErrors.isEmpty { writeError = try BSONDecoder().decode(WriteError.self, from: writeErrors[0]) } let wcError = try extractWriteConcernError(from: serverReply) @@ -263,9 +269,9 @@ internal func extractMongoError(error bsonError: bson_error_t, reply: Document? } return ServerError.writeError( - writeError: writeError, - writeConcernError: wcError, - errorLabels: serverReply["errorLabels"]?.arrayValue?.asArrayOf(String.self) + writeError: writeError, + writeConcernError: wcError, + errorLabels: serverReply["errorLabels"]?.arrayValue?.asArrayOf(String.self) ) } catch { return fallback @@ -275,12 +281,16 @@ internal func extractMongoError(error bsonError: bson_error_t, reply: Document? /// Internal function used to get a `ServerError.bulkWriteError` from a libmongoc error and a server reply to a /// `BulkWriteOperation`. If a partial result is provided, an updated result with the failed results filtered out will /// be returned as part of the error. -internal func extractBulkWriteError(for op: BulkWriteOperation, - error: bson_error_t, - reply: Document, - partialResult: BulkWriteResult? = nil) -> Error { - let fallback = RuntimeError.internalError(message: "Got error from the server but couldn't parse it. " + - "Message: \(toErrorString(error))") +internal func extractBulkWriteError( + for op: BulkWriteOperation, + error: bson_error_t, + reply: Document, + partialResult: BulkWriteResult? = nil +) -> Error { + let fallback = RuntimeError.internalError( + message: "Got error from the server but couldn't parse it. " + + "Message: \(toErrorString(error))" + ) do { var bulkWriteErrors: [BulkWriteError] = [] @@ -308,13 +318,13 @@ internal func extractBulkWriteError(for op: BulkWriteOperation, } errResult = BulkWriteResult( - deletedCount: result.deletedCount, - insertedCount: result.insertedCount, - insertedIds: filteredIds, - matchedCount: result.matchedCount, - modifiedCount: result.modifiedCount, - upsertedCount: result.upsertedCount, - upsertedIds: result.upsertedIds + deletedCount: result.deletedCount, + insertedCount: result.insertedCount, + insertedIds: filteredIds, + matchedCount: result.matchedCount, + modifiedCount: result.modifiedCount, + upsertedCount: result.upsertedCount, + upsertedIds: result.upsertedIds ) } @@ -326,19 +336,19 @@ internal func extractBulkWriteError(for op: BulkWriteOperation, // omit the "other" error. // we also want to omit any write concern errors since they will also be reported elsewhere. if case let .some(ServerError.commandError(code, _, _, _)) = other as? ServerError, - let wErr = bulkWriteErrors.first, - wErr.code == code { + let wErr = bulkWriteErrors.first, + wErr.code == code { other = nil } else if error.domain == MONGOC_ERROR_WRITE_CONCERN.rawValue { other = nil } return ServerError.bulkWriteError( - writeErrors: bulkWriteErrors, - writeConcernError: try extractWriteConcernError(from: reply), - otherError: other, - result: errResult, - errorLabels: reply["errorLabels"]?.arrayValue?.asArrayOf(String.self) + writeErrors: bulkWriteErrors, + writeConcernError: try extractWriteConcernError(from: reply), + otherError: other, + result: errResult, + errorLabels: reply["errorLabels"]?.arrayValue?.asArrayOf(String.self) ) } catch { return fallback @@ -348,7 +358,7 @@ internal func extractBulkWriteError(for op: BulkWriteOperation, /// Extracts a `WriteConcernError` from a server reply. private func extractWriteConcernError(from reply: Document) throws -> WriteConcernError? { guard let writeConcernErrors = reply["writeConcernErrors"]?.arrayValue?.compactMap({ $0.documentValue }), - !writeConcernErrors.isEmpty else { + !writeConcernErrors.isEmpty else { return nil } return try BSONDecoder().decode(WriteConcernError.self, from: writeConcernErrors[0]) @@ -362,9 +372,11 @@ internal func convertingBulkWriteErrors(_ body: () throws -> T) throws -> T { return try body() } catch let ServerError.bulkWriteError(bulkWriteErrors, writeConcernError, other, _, errorLabels) { if let bwes = bulkWriteErrors, !bwes.isEmpty { - let writeError = WriteError(code: bwes[0].code, - codeName: bwes[0].codeName, - message: bwes[0].message) + let writeError = WriteError( + code: bwes[0].code, + codeName: bwes[0].codeName, + message: bwes[0].message + ) throw ServerError.writeError(writeError: writeError, writeConcernError: nil, errorLabels: errorLabels) } else if let wcErr = writeConcernError { throw ServerError.writeError(writeError: nil, writeConcernError: wcErr, errorLabels: errorLabels) @@ -386,13 +398,17 @@ internal func toErrorString(_ error: bson_error_t) -> String { } internal func bsonTooLargeError(value: BSONValue, forKey: String) -> MongoError { - return RuntimeError.internalError(message: - "Failed to set value for key \(forKey) to \(value) with BSON type \(value.bsonType): document too large") + return RuntimeError.internalError( + message: + "Failed to set value for key \(forKey) to \(value) with BSON type \(value.bsonType): document too large" + ) } internal func wrongIterTypeError(_ iter: DocumentIterator, expected type: BSONValue.Type) -> MongoError { - return UserError.logicError(message: "Tried to retreive a \(type) from an iterator whose next type " + - "is \(iter.currentType) for key \(iter.currentKey)") + return UserError.logicError( + message: "Tried to retreive a \(type) from an iterator whose next type " + + "is \(iter.currentType) for key \(iter.currentKey)" + ) } internal let failedToRetrieveCursorMessage = "Couldn't get cursor from the server" diff --git a/Sources/MongoSwift/Operations/CountOperation.swift b/Sources/MongoSwift/Operations/CountOperation.swift index 380666fd7..43e6f41ed 100644 --- a/Sources/MongoSwift/Operations/CountOperation.swift +++ b/Sources/MongoSwift/Operations/CountOperation.swift @@ -26,13 +26,15 @@ public struct CountOptions: Codable { public var skip: Int64? /// Convenience initializer allowing any/all parameters to be optional - public init(collation: Document? = nil, - hint: Hint? = nil, - limit: Int64? = nil, - maxTimeMS: Int64? = nil, - readConcern: ReadConcern? = nil, - readPreference: ReadPreference? = nil, - skip: Int64? = nil) { + public init( + collation: Document? = nil, + hint: Hint? = nil, + limit: Int64? = nil, + maxTimeMS: Int64? = nil, + readConcern: ReadConcern? = nil, + readPreference: ReadPreference? = nil, + skip: Int64? = nil + ) { self.collation = collation self.hint = hint self.limit = limit @@ -66,14 +68,16 @@ internal struct CountOperation: Operation { let count = self.collection.withMongocCollection(from: connection) { collPtr in // because we already encode skip and limit in the options, // pass in 0s so we don't get duplicate parameter errors. - mongoc_collection_count_with_opts(collPtr, - MONGOC_QUERY_NONE, - self.filter._bson, - 0, // skip - 0, // limit - opts?._bson, - rp, - &error) + mongoc_collection_count_with_opts( + collPtr, + MONGOC_QUERY_NONE, + self.filter._bson, + 0, // skip + 0, // limit + opts?._bson, + rp, + &error + ) } guard count != -1 else { throw extractMongoError(error: error) } diff --git a/Sources/MongoSwift/Operations/CreateCollectionOperation.swift b/Sources/MongoSwift/Operations/CreateCollectionOperation.swift index 77bf770e0..097749fab 100644 --- a/Sources/MongoSwift/Operations/CreateCollectionOperation.swift +++ b/Sources/MongoSwift/Operations/CreateCollectionOperation.swift @@ -66,26 +66,28 @@ public struct CreateCollectionOptions: Codable, CodingStrategyProvider { private enum CodingKeys: String, CodingKey { case capped, autoIndexId, size, max, storageEngine, validator, validationLevel, validationAction, - indexOptionDefaults, viewOn, pipeline, collation, writeConcern + indexOptionDefaults, viewOn, pipeline, collation, writeConcern } /// Convenience initializer allowing any/all parameters to be omitted or optional. - public init(autoIndexId: Bool? = nil, - capped: Bool? = nil, - collation: Document? = nil, - dataCodingStrategy: DataCodingStrategy? = nil, - dateCodingStrategy: DateCodingStrategy? = nil, - indexOptionDefaults: Document? = nil, - max: Int64? = nil, - pipeline: [Document]? = nil, - size: Int64? = nil, - storageEngine: Document? = nil, - uuidCodingStrategy: UUIDCodingStrategy? = nil, - validationAction: String? = nil, - validationLevel: String? = nil, - validator: Document? = nil, - viewOn: String? = nil, - writeConcern: WriteConcern? = nil) { + public init( + autoIndexId: Bool? = nil, + capped: Bool? = nil, + collation: Document? = nil, + dataCodingStrategy: DataCodingStrategy? = nil, + dateCodingStrategy: DateCodingStrategy? = nil, + indexOptionDefaults: Document? = nil, + max: Int64? = nil, + pipeline: [Document]? = nil, + size: Int64? = nil, + storageEngine: Document? = nil, + uuidCodingStrategy: UUIDCodingStrategy? = nil, + validationAction: String? = nil, + validationLevel: String? = nil, + validator: Document? = nil, + viewOn: String? = nil, + writeConcern: WriteConcern? = nil + ) { self.autoIndexId = autoIndexId self.capped = capped self.collation = collation @@ -130,9 +132,11 @@ internal struct CreateCollectionOperation: Operation { mongoc_collection_destroy(collection) } - let collectionOptions = CollectionOptions(dataCodingStrategy: self.options?.dataCodingStrategy, - dateCodingStrategy: self.options?.dateCodingStrategy, - uuidCodingStrategy: self.options?.uuidCodingStrategy) + let collectionOptions = CollectionOptions( + dataCodingStrategy: self.options?.dataCodingStrategy, + dateCodingStrategy: self.options?.dateCodingStrategy, + uuidCodingStrategy: self.options?.uuidCodingStrategy + ) return SyncMongoCollection(name: self.name, database: self.database, options: collectionOptions) } diff --git a/Sources/MongoSwift/Operations/DistinctOperation.swift b/Sources/MongoSwift/Operations/DistinctOperation.swift index e91c0a84d..3c3e0b380 100644 --- a/Sources/MongoSwift/Operations/DistinctOperation.swift +++ b/Sources/MongoSwift/Operations/DistinctOperation.swift @@ -17,10 +17,12 @@ public struct DistinctOptions: Codable { // swiftlint:enable redundant_optional_initialization /// Convenience initializer allowing any/all parameters to be optional - public init(collation: Document? = nil, - maxTimeMS: Int64? = nil, - readConcern: ReadConcern? = nil, - readPreference: ReadPreference? = nil) { + public init( + collation: Document? = nil, + maxTimeMS: Int64? = nil, + readConcern: ReadConcern? = nil, + readPreference: ReadPreference? = nil + ) { self.collation = collation self.maxTimeMS = maxTimeMS self.readConcern = readConcern @@ -67,8 +69,10 @@ internal struct DistinctOperation: Operation { } guard let values = try reply.getValue(for: "values")?.arrayValue else { - throw RuntimeError.internalError(message: - "expected server reply \(reply) to contain an array of distinct values") + throw RuntimeError.internalError( + message: + "expected server reply \(reply) to contain an array of distinct values" + ) } return values diff --git a/Sources/MongoSwift/Operations/FindAndModifyOperation.swift b/Sources/MongoSwift/Operations/FindAndModifyOperation.swift index 5c605662d..8995b49bd 100644 --- a/Sources/MongoSwift/Operations/FindAndModifyOperation.swift +++ b/Sources/MongoSwift/Operations/FindAndModifyOperation.swift @@ -23,20 +23,22 @@ internal class FindAndModifyOptions { /// /// - Throws: `UserError.invalidArgumentError` if any of the options are invalid. // swiftlint:disable:next cyclomatic_complexity - internal init(arrayFilters: [Document]? = nil, - bypassDocumentValidation: Bool? = nil, - collation: Document?, - maxTimeMS: Int64?, - projection: Document?, - remove: Bool? = nil, - returnDocument: ReturnDocument? = nil, - sort: Document?, - upsert: Bool? = nil, - writeConcern: WriteConcern?) throws { + internal init( + arrayFilters: [Document]? = nil, + bypassDocumentValidation: Bool? = nil, + collation: Document?, + maxTimeMS: Int64?, + projection: Document?, + remove: Bool? = nil, + returnDocument: ReturnDocument? = nil, + sort: Document?, + upsert: Bool? = nil, + writeConcern: WriteConcern? + ) throws { self._options = mongoc_find_and_modify_opts_new() if let bypass = bypassDocumentValidation, - !mongoc_find_and_modify_opts_set_bypass_document_validation(self._options, bypass) { + !mongoc_find_and_modify_opts_set_bypass_document_validation(self._options, bypass) { throw UserError.invalidArgumentError(message: "Error setting bypassDocumentValidation to \(bypass)") } @@ -54,12 +56,14 @@ internal class FindAndModifyOptions { let mongocFlags = mongoc_find_and_modify_flags_t(rawValue: flags) if mongocFlags != MONGOC_FIND_AND_MODIFY_NONE - && !mongoc_find_and_modify_opts_set_flags(self._options, mongocFlags) { + && !mongoc_find_and_modify_opts_set_flags(self._options, mongocFlags) { let remStr = String(describing: remove) let upsStr = String(describing: upsert) let retStr = String(describing: returnDocument) - throw UserError.invalidArgumentError(message: - "Error setting flags to \(flags); remove=\(remStr), upsert=\(upsStr), returnDocument=\(retStr)") + throw UserError.invalidArgumentError( + message: + "Error setting flags to \(flags); remove=\(remStr), upsert=\(upsStr), returnDocument=\(retStr)" + ) } if let sort = sort { @@ -126,10 +130,12 @@ internal struct FindAndModifyOperation: Operation { private let update: Document? private let options: FindAndModifyOptionsConvertible? - internal init(collection: SyncMongoCollection, - filter: Document, - update: Document?, - options: FindAndModifyOptionsConvertible?) { + internal init( + collection: SyncMongoCollection, + filter: Document, + update: Document?, + options: FindAndModifyOptionsConvertible? + ) { self.collection = collection self.filter = filter self.update = update @@ -147,11 +153,13 @@ internal struct FindAndModifyOperation: Operation { var error = bson_error_t() let success = withMutableBSONPointer(to: &reply) { replyPtr in self.collection.withMongocCollection(from: connection) { collPtr in - mongoc_collection_find_and_modify_with_opts(collPtr, - self.filter._bson, - opts._options, - replyPtr, - &error) + mongoc_collection_find_and_modify_with_opts( + collPtr, + self.filter._bson, + opts._options, + replyPtr, + &error + ) } } guard success else { diff --git a/Sources/MongoSwift/Operations/ListCollectionsOperation.swift b/Sources/MongoSwift/Operations/ListCollectionsOperation.swift index d3b83895a..4839b23fc 100644 --- a/Sources/MongoSwift/Operations/ListCollectionsOperation.swift +++ b/Sources/MongoSwift/Operations/ListCollectionsOperation.swift @@ -16,7 +16,7 @@ public enum CollectionType: RawRepresentable, Codable { return "collection" case .view: return "view" - case .other(let v): + case let .other(v): return v } } @@ -47,6 +47,7 @@ public struct CollectionSpecificationInfo: Codable { /// set members and shards in a sharded cluster. If the data store is a view, this field is nil. public let uuid: UUID? } + /** * Specifications of a collection returned when executing `listCollections`. * @@ -104,7 +105,7 @@ internal struct ListCollectionsOperation: Operation { self.options = options } - internal func execute(using connection: Connection, session: SyncClientSession?) throws -> ListCollectionsResults { + internal func execute(using _: Connection, session: SyncClientSession?) throws -> ListCollectionsResults { var opts = try encodeOptions(options: self.options, session: session) ?? Document() opts["nameOnly"] = .bool(self.nameOnly) if let filterDoc = self.filter { @@ -125,10 +126,12 @@ internal struct ListCollectionsOperation: Operation { } } if self.nameOnly { - let cursor: SyncMongoCursor = try SyncMongoCursor(client: self.database._client, - decoder: self.database.decoder, - session: session, - initializer: initializer) + let cursor: SyncMongoCursor = try SyncMongoCursor( + client: self.database._client, + decoder: self.database.decoder, + session: session, + initializer: initializer + ) return try .names(cursor.map { guard let name = $0["name"]?.stringValue else { throw RuntimeError.internalError(message: "Invalid server response: collection has no name") @@ -136,10 +139,12 @@ internal struct ListCollectionsOperation: Operation { return name }) } - let cursor: SyncMongoCursor = try SyncMongoCursor(client: self.database._client, - decoder: self.database.decoder, - session: session, - initializer: initializer) + let cursor: SyncMongoCursor = try SyncMongoCursor( + client: self.database._client, + decoder: self.database.decoder, + session: session, + initializer: initializer + ) return .specs(cursor) } } diff --git a/Sources/MongoSwift/Operations/ListDatabasesOperation.swift b/Sources/MongoSwift/Operations/ListDatabasesOperation.swift index 1a0e7025d..4f968692b 100644 --- a/Sources/MongoSwift/Operations/ListDatabasesOperation.swift +++ b/Sources/MongoSwift/Operations/ListDatabasesOperation.swift @@ -31,9 +31,11 @@ internal struct ListDatabasesOperation: Operation { private let filter: Document? private let nameOnly: Bool? - internal init(client: SyncMongoClient, - filter: Document?, - nameOnly: Bool?) { + internal init( + client: SyncMongoClient, + filter: Document?, + nameOnly: Bool? + ) { self.client = client self.filter = filter self.nameOnly = nameOnly @@ -55,13 +57,15 @@ internal struct ListDatabasesOperation: Operation { var error = bson_error_t() let success = withMutableBSONPointer(to: &reply) { replyPtr in - mongoc_client_read_command_with_opts(connection.clientHandle, - "admin", - cmd._bson, - readPref._readPreference, - opts?._bson, - replyPtr, - &error) + mongoc_client_read_command_with_opts( + connection.clientHandle, + "admin", + cmd._bson, + readPref._readPreference, + opts?._bson, + replyPtr, + &error + ) } guard success else { diff --git a/Sources/MongoSwift/Operations/ListIndexesOperation.swift b/Sources/MongoSwift/Operations/ListIndexesOperation.swift index 741dbb51a..47cc71bf3 100644 --- a/Sources/MongoSwift/Operations/ListIndexesOperation.swift +++ b/Sources/MongoSwift/Operations/ListIndexesOperation.swift @@ -8,13 +8,17 @@ internal struct ListIndexesOperation: Operation { self.collection = collection } - internal func execute(using connection: Connection, - session: SyncClientSession?) throws -> SyncMongoCursor { + internal func execute( + using _: Connection, + session: SyncClientSession? + ) throws -> SyncMongoCursor { let opts = try encodeOptions(options: nil as Document?, session: session) - return try SyncMongoCursor(client: self.collection._client, - decoder: self.collection.decoder, - session: session) { conn in + return try SyncMongoCursor( + client: self.collection._client, + decoder: self.collection.decoder, + session: session + ) { conn in self.collection.withMongocCollection(from: conn) { collPtr in guard let indexes = mongoc_collection_find_indexes_with_opts(collPtr, opts?._bson) else { fatalError(failedToRetrieveCursorMessage) diff --git a/Sources/MongoSwift/Operations/NextOperation.swift b/Sources/MongoSwift/Operations/NextOperation.swift index 6c5c9f929..ac8b8aad6 100644 --- a/Sources/MongoSwift/Operations/NextOperation.swift +++ b/Sources/MongoSwift/Operations/NextOperation.swift @@ -20,7 +20,7 @@ internal struct NextOperation: Operation { } // swiftlint:disable:next cyclomatic_complexity - internal func execute(using connection: Connection, session: SyncClientSession?) throws -> T? { + internal func execute(using _: Connection, session: SyncClientSession?) throws -> T? { // NOTE: this method does not actually use the `connection` parameter passed in. for the moment, it is only // here so that `NextOperation` conforms to `Operation`. if we eventually rewrite our cursors to no longer // wrap a mongoc cursor then we will use the connection here. diff --git a/Sources/MongoSwift/Operations/Operation.swift b/Sources/MongoSwift/Operations/Operation.swift index 68e3dc010..5b14a5ec4 100644 --- a/Sources/MongoSwift/Operations/Operation.swift +++ b/Sources/MongoSwift/Operations/Operation.swift @@ -30,16 +30,20 @@ internal enum ConnectionStrategy { /// A protocol for types that can be used to execute `Operation`s synchronously. internal protocol SyncOperationExecutor { /// Executes an operation using the provided client and optionally provided session. - func execute(_ operation: T, - client: SyncMongoClient, - session: SyncClientSession?) throws -> T.OperationResult + func execute( + _ operation: T, + client: SyncMongoClient, + session: SyncClientSession? + ) throws -> T.OperationResult } /// Default executor type used by `SyncMongoClient`s. internal struct DefaultSyncOperationExecutor: SyncOperationExecutor { - internal func execute(_ operation: T, - client: SyncMongoClient, - session: SyncClientSession?) throws -> T.OperationResult { + internal func execute( + _ operation: T, + client: SyncMongoClient, + session: SyncClientSession? + ) throws -> T.OperationResult { switch operation.connectionStrategy { case let .bound(conn): // pass in the connection this operation is already bound to @@ -62,7 +66,7 @@ internal struct DefaultSyncOperationExecutor: SyncOperationExecutor { /// connection for the operation to use. After the connection is no longer in use, it should be returned by /// passing it to `returnConnection` along with the same client and session that were passed into this method. internal func resolveConnection(client: SyncMongoClient, session: SyncClientSession?) throws -> Connection { - return try session?.getConnection(forUseWith: client) ?? client.connectionPool.checkOut() + return try session?.getConnection(forUseWith: client) ?? client.connectionPool.checkOut() } /// Handles releasing a connection that was returned by `resolveConnection`. Must be called with the same client and diff --git a/Sources/MongoSwift/Operations/RunCommandOperation.swift b/Sources/MongoSwift/Operations/RunCommandOperation.swift index 44f22eaf2..df2d008af 100644 --- a/Sources/MongoSwift/Operations/RunCommandOperation.swift +++ b/Sources/MongoSwift/Operations/RunCommandOperation.swift @@ -15,9 +15,11 @@ public struct RunCommandOptions: Encodable { public var writeConcern: WriteConcern? /// Convenience initializer allowing any/all parameters to be omitted or optional. - public init(readConcern: ReadConcern? = nil, - readPreference: ReadPreference? = nil, - writeConcern: WriteConcern? = nil) { + public init( + readConcern: ReadConcern? = nil, + readPreference: ReadPreference? = nil, + writeConcern: WriteConcern? = nil + ) { self.readConcern = readConcern self.readPreference = readPreference self.writeConcern = writeConcern diff --git a/Sources/MongoSwift/Operations/WatchOperation.swift b/Sources/MongoSwift/Operations/WatchOperation.swift index e5c950ec2..00a73296a 100644 --- a/Sources/MongoSwift/Operations/WatchOperation.swift +++ b/Sources/MongoSwift/Operations/WatchOperation.swift @@ -19,18 +19,22 @@ internal struct WatchOperation, - pipeline: [Document], - options: ChangeStreamOptions?, - stealing connection: Connection) throws { + internal init( + target: ChangeStreamTarget, + pipeline: [Document], + options: ChangeStreamOptions?, + stealing connection: Connection + ) throws { self.target = target self.pipeline = .array(pipeline.map { .document($0) }) self.options = options self.connectionStrategy = .bound(to: connection) } - internal func execute(using connection: Connection, - session: SyncClientSession?) throws -> SyncChangeStream { + internal func execute( + using connection: Connection, + session: SyncClientSession? + ) throws -> SyncChangeStream { let pipeline: Document = ["pipeline": self.pipeline] let opts = try encodeOptions(options: self.options, session: session) @@ -57,11 +61,13 @@ internal struct WatchOperation(stealing: changeStream, - connection: connection, - client: client, - session: session, - decoder: decoder, - options: self.options) + return try SyncChangeStream( + stealing: changeStream, + connection: connection, + client: client, + session: session, + decoder: decoder, + options: self.options + ) } } diff --git a/Sources/MongoSwift/ReadConcern.swift b/Sources/MongoSwift/ReadConcern.swift index be4aa82b9..564d8f2da 100644 --- a/Sources/MongoSwift/ReadConcern.swift +++ b/Sources/MongoSwift/ReadConcern.swift @@ -31,7 +31,7 @@ public struct ReadConcern: Codable { return "linearizable" case .snapshot: return "snapshot" - case .other(let l): + case let .other(l): return l } } @@ -57,7 +57,7 @@ public struct ReadConcern: Codable { /// Indicates whether this `ReadConcern` is the server default. public var isDefault: Bool { - return level == nil + return self.level == nil } // Initializes a new `ReadConcern` with the same level as the provided `mongoc_read_concern_t`. diff --git a/Sources/MongoSwift/ReadPreference.swift b/Sources/MongoSwift/ReadPreference.swift index 8475ec5a6..e59cb8100 100644 --- a/Sources/MongoSwift/ReadPreference.swift +++ b/Sources/MongoSwift/ReadPreference.swift @@ -129,8 +129,10 @@ public final class ReadPreference { if let maxStalenessSeconds = maxStalenessSeconds { guard maxStalenessSeconds >= MONGOC_SMALLEST_MAX_STALENESS_SECONDS else { - throw UserError.invalidArgumentError(message: "Expected maxStalenessSeconds to be >= " + - " \(MONGOC_SMALLEST_MAX_STALENESS_SECONDS), \(maxStalenessSeconds) given") + throw UserError.invalidArgumentError( + message: "Expected maxStalenessSeconds to be >= " + + " \(MONGOC_SMALLEST_MAX_STALENESS_SECONDS), \(maxStalenessSeconds) given" + ) } mongoc_read_prefs_set_max_staleness_seconds(self._readPreference, maxStalenessSeconds) diff --git a/Sources/MongoSwift/SDAM.swift b/Sources/MongoSwift/SDAM.swift index c3c63fdcc..065d74c86 100644 --- a/Sources/MongoSwift/SDAM.swift +++ b/Sources/MongoSwift/SDAM.swift @@ -185,23 +185,23 @@ extension ServerDescription: Equatable { public static func == (lhs: ServerDescription, rhs: ServerDescription) -> Bool { // Compare everything except `error` it is always nil and `MongoError`s are not `Equatable` return lhs.connectionId == rhs.connectionId && - lhs.roundTripTime == rhs.roundTripTime && - lhs.lastWriteDate == rhs.lastWriteDate && - lhs.opTime == rhs.opTime && - lhs.type == rhs.type && - lhs.minWireVersion == rhs.minWireVersion && - lhs.maxWireVersion == rhs.maxWireVersion && - lhs.me == rhs.me && - lhs.hosts == rhs.hosts && - lhs.arbiters == rhs.arbiters && - lhs.passives == rhs.passives && - lhs.tags == rhs.tags && - lhs.setName == rhs.setName && - lhs.setVersion == rhs.setVersion && - lhs.electionId == rhs.electionId && - lhs.primary == rhs.primary && - lhs.lastUpdateTime == rhs.lastUpdateTime && - lhs.logicalSessionTimeoutMinutes == rhs.logicalSessionTimeoutMinutes + lhs.roundTripTime == rhs.roundTripTime && + lhs.lastWriteDate == rhs.lastWriteDate && + lhs.opTime == rhs.opTime && + lhs.type == rhs.type && + lhs.minWireVersion == rhs.minWireVersion && + lhs.maxWireVersion == rhs.maxWireVersion && + lhs.me == rhs.me && + lhs.hosts == rhs.hosts && + lhs.arbiters == rhs.arbiters && + lhs.passives == rhs.passives && + lhs.tags == rhs.tags && + lhs.setName == rhs.setName && + lhs.setVersion == rhs.setVersion && + lhs.electionId == rhs.electionId && + lhs.primary == rhs.primary && + lhs.lastUpdateTime == rhs.lastUpdateTime && + lhs.logicalSessionTimeoutMinutes == rhs.logicalSessionTimeoutMinutes } } @@ -305,10 +305,10 @@ extension TopologyDescription: Equatable { public static func == (lhs: TopologyDescription, rhs: TopologyDescription) -> Bool { // Compare everything except `error` it is always nil and `MongoError`s are not `Equatable` return lhs.type == rhs.type && - lhs.setName == rhs.setName && - lhs.maxSetVersion == rhs.maxSetVersion && - lhs.maxElectionId == rhs.maxElectionId && - lhs.servers == rhs.servers && - lhs.stale == rhs.stale + lhs.setName == rhs.setName && + lhs.maxSetVersion == rhs.maxSetVersion && + lhs.maxElectionId == rhs.maxElectionId && + lhs.servers == rhs.servers && + lhs.stale == rhs.stale } } diff --git a/Sources/MongoSwift/WriteConcern.swift b/Sources/MongoSwift/WriteConcern.swift index 850eb19c1..95a83af63 100644 --- a/Sources/MongoSwift/WriteConcern.swift +++ b/Sources/MongoSwift/WriteConcern.swift @@ -49,7 +49,7 @@ public struct WriteConcern: Codable { public var isAcknowledged: Bool { // An Unacknowledged WriteConcern is when (w equals 0) AND (journal is not set or is false). if let w = self.w, case let .number(wNumber) = w { - return !((journal == nil || journal == false ) && wNumber == 0) + return !((self.journal == nil || self.journal == false) && wNumber == 0) } return true } @@ -63,7 +63,7 @@ public struct WriteConcern: Codable { private var isValid: Bool { if let w = self.w, case let .number(wNumber) = w { // A WriteConcern is invalid if journal is set to true and w is equal to zero. - return journal == nil || journal == false || wNumber != 0 + return self.journal == nil || self.journal == false || wNumber != 0 } return true } @@ -84,7 +84,7 @@ public struct WriteConcern: Codable { if let wtimeoutMS = wtimeoutMS { if wtimeoutMS < 0 { throw UserError - .invalidArgumentError(message: "Invalid value: wtimeoutMS=\(wtimeoutMS) cannot be negative.") + .invalidArgumentError(message: "Invalid value: wtimeoutMS=\(wtimeoutMS) cannot be negative.") } } self.wtimeoutMS = wtimeoutMS @@ -100,8 +100,10 @@ public struct WriteConcern: Codable { let journalStr = String(describing: journal) let wStr = String(describing: w) let timeoutStr = String(describing: wtimeoutMS) - throw UserError.invalidArgumentError(message: - "Invalid combination of options: journal=\(journalStr), w=\(wStr), wtimeoutMS=\(timeoutStr)") + throw UserError.invalidArgumentError( + message: + "Invalid combination of options: journal=\(journalStr), w=\(wStr), wtimeoutMS=\(timeoutStr)" + ) } } diff --git a/Tests/MongoSwiftTests/AuthTests.swift b/Tests/MongoSwiftTests/AuthTests.swift index 007107fcc..fefb8689e 100644 --- a/Tests/MongoSwiftTests/AuthTests.swift +++ b/Tests/MongoSwiftTests/AuthTests.swift @@ -69,11 +69,13 @@ extension ConnectionString { /// Returns the credential configured on this URI. Will be empty if no options are set. fileprivate var credential: Credential { - return Credential(username: self.username, - password: self.password, - source: self.authSource, - mechanism: self.authMechanism, - mechanismProperties: self.authMechanismProperties) + return Credential( + username: self.username, + password: self.password, + source: self.authSource, + mechanism: self.authMechanism, + mechanismProperties: self.authMechanismProperties + ) } } @@ -124,7 +126,7 @@ struct Credential: Decodable, Equatable { case username, password, source, mechanism, mechanismProperties = "mechanism_properties" } - // TODO SWIFT-636: remove this initializer and the one below it. + // TODO: SWIFT-636: remove this initializer and the one below it. init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) self.username = try container.decodeIfPresent(String.self, forKey: .username) @@ -144,11 +146,13 @@ struct Credential: Decodable, Equatable { } } - init(username: String?, - password: String?, - source: String?, - mechanism: AuthMechanism?, - mechanismProperties: Document?) { + init( + username: String?, + password: String?, + source: String?, + mechanism: AuthMechanism?, + mechanismProperties: Document? + ) { self.mechanism = mechanism self.mechanismProperties = mechanismProperties self.password = password @@ -162,7 +166,7 @@ final class AuthTests: MongoSwiftTestCase { let testFiles = try retrieveSpecTestFiles(specName: "auth", asType: AuthTestFile.self) let invalidArgumentError = UserError.invalidArgumentError(message: "") - for (_, file) in testFiles { + for (_, file) in testFiles { for testCase in file.tests { guard testCase.valid else { expect(try ConnectionString(testCase.uri)) @@ -226,7 +230,7 @@ final class AuthTests: MongoSwiftTestCase { } } - // TODO SWIFT-640: spec says "Drivers that allow specifying auth parameters in code as well as via connection + // TODO: SWIFT-640: spec says "Drivers that allow specifying auth parameters in code as well as via connection // string should test both for the test cases described below". Once we support setting auth options via options // struct we should test that here too. func testAuthProseTests() throws { @@ -292,10 +296,10 @@ final class AuthTests: MongoSwiftTestCase { // As a URI, those have to be UTF-8 encoded and URL-escaped. let saslPrepConnectUsers = [ TestUser(username: "IX", password: "IX", mechanisms: [.scramSHA256]) - // TODO SWIFT-638 : unskip these tests. URIs cannot be parsed by libmongoc - see CDRIVER-3390. - //TestUser(username: "IX", password: "I%C2%ADX", mechanisms: [.scramSHA256]), - //TestUser(username: "%E2%85%A8", password: "IV", mechanisms: [.scramSHA256]), - //TestUser(username: "%E2%85%A8", password: "I%C2%ADV", mechanisms: [.scramSHA256]) + // TODO: SWIFT-638 : unskip these tests. URIs cannot be parsed by libmongoc - see CDRIVER-3390. + // TestUser(username: "IX", password: "I%C2%ADX", mechanisms: [.scramSHA256]), + // TestUser(username: "%E2%85%A8", password: "IV", mechanisms: [.scramSHA256]), + // TestUser(username: "%E2%85%A8", password: "I%C2%ADV", mechanisms: [.scramSHA256]) ] for user in saslPrepConnectUsers { @@ -304,7 +308,7 @@ final class AuthTests: MongoSwiftTestCase { expect(try client.db("admin").runCommand(["dbstats": 1])).toNot(throwError()) } - // TODO whenever auth is implemented in pure Swift - implement this test case: + // TODO: whenever auth is implemented in pure Swift - implement this test case: // For SCRAM-SHA-1 and SCRAM-SHA-256, test that the minimum iteration count is respected. This may be done via // unit testing of an underlying SCRAM library. } diff --git a/Tests/MongoSwiftTests/BSONValueTests.swift b/Tests/MongoSwiftTests/BSONValueTests.swift index e17d1f240..2326212a3 100644 --- a/Tests/MongoSwiftTests/BSONValueTests.swift +++ b/Tests/MongoSwiftTests/BSONValueTests.swift @@ -17,7 +17,7 @@ final class BSONValueTests: MongoSwiftTestCase { // UUIDs must have 16 bytes expect(try Binary(data: twoBytes, subtype: .uuidDeprecated)) - .to(throwError(UserError.invalidArgumentError(message: ""))) + .to(throwError(UserError.invalidArgumentError(message: ""))) expect(try Binary(data: twoBytes, subtype: .uuid)).to(throwError(UserError.invalidArgumentError(message: ""))) expect(try Binary(data: sixteenBytes, subtype: .uuidDeprecated)).toNot(throwError()) expect(try Binary(data: sixteenBytes, subtype: .uuid)).toNot(throwError()) @@ -30,29 +30,31 @@ final class BSONValueTests: MongoSwiftTestCase { func testBSONEquatable() throws { // Int - checkTrueAndFalse(val: 1, alternate: 2) + self.checkTrueAndFalse(val: 1, alternate: 2) // Int32 - checkTrueAndFalse(val: .int32(32), alternate: .int32(33)) + self.checkTrueAndFalse(val: .int32(32), alternate: .int32(33)) // Int64 - checkTrueAndFalse(val: .int64(64), alternate: .int64(65)) + self.checkTrueAndFalse(val: .int64(64), alternate: .int64(65)) // Double - checkTrueAndFalse(val: 1.618, alternate: 2.718) + self.checkTrueAndFalse(val: 1.618, alternate: 2.718) // Decimal128 - checkTrueAndFalse(val: .decimal128(Decimal128("1.618")!), alternate: .decimal128(Decimal128("2.718")!)) + self.checkTrueAndFalse(val: .decimal128(Decimal128("1.618")!), alternate: .decimal128(Decimal128("2.718")!)) // Bool - checkTrueAndFalse(val: true, alternate: false) + self.checkTrueAndFalse(val: true, alternate: false) // String - checkTrueAndFalse(val: "some", alternate: "not some") + self.checkTrueAndFalse(val: "some", alternate: "not some") // RegularExpression - checkTrueAndFalse( + self.checkTrueAndFalse( val: .regex(RegularExpression(pattern: ".*", options: "")), alternate: .regex(RegularExpression(pattern: ".+", options: "")) ) // Timestamp - checkTrueAndFalse(val: .timestamp(Timestamp(timestamp: 1, inc: 2)), - alternate: .timestamp(Timestamp(timestamp: 5, inc: 10))) + self.checkTrueAndFalse( + val: .timestamp(Timestamp(timestamp: 1, inc: 2)), + alternate: .timestamp(Timestamp(timestamp: 5, inc: 10)) + ) // Date - checkTrueAndFalse( + self.checkTrueAndFalse( val: .datetime(Date(timeIntervalSinceReferenceDate: 5000)), alternate: .datetime(Date(timeIntervalSinceReferenceDate: 5001)) ) @@ -60,28 +62,28 @@ final class BSONValueTests: MongoSwiftTestCase { expect(BSON.minKey).to(equal(.minKey)) expect(BSON.maxKey).to(equal(.maxKey)) // ObjectId - checkTrueAndFalse(val: .objectId(ObjectId()), alternate: .objectId(ObjectId())) + self.checkTrueAndFalse(val: .objectId(ObjectId()), alternate: .objectId(ObjectId())) // CodeWithScope - checkTrueAndFalse( + self.checkTrueAndFalse( val: .codeWithScope(CodeWithScope(code: "console.log('foo');", scope: [:])), alternate: .codeWithScope(CodeWithScope(code: "console.log(x);", scope: ["x": 2])) ) // Binary - checkTrueAndFalse( + self.checkTrueAndFalse( val: .binary(try Binary(data: Data(base64Encoded: "c//SZESzTGmQ6OfR38A11A==")!, subtype: .uuid)), alternate: .binary(try Binary(data: Data(base64Encoded: "c//88KLnfdfefOfR33ddFA==")!, subtype: .uuid)) ) // Document - checkTrueAndFalse( + self.checkTrueAndFalse( val: [ "foo": 1.414, "bar": "swift", - "nested": [ "a": 1, "b": "2" ] + "nested": ["a": 1, "b": "2"] ], alternate: [ "foo": 1.414, "bar": "swift", - "nested": [ "a": 1, "b": "different" ] + "nested": ["a": 1, "b": "different"] ] ) diff --git a/Tests/MongoSwiftTests/ChangeStreamTests.swift b/Tests/MongoSwiftTests/ChangeStreamTests.swift index 2937fc36c..0f0ce7f96 100644 --- a/Tests/MongoSwiftTests/ChangeStreamTests.swift +++ b/Tests/MongoSwiftTests/ChangeStreamTests.swift @@ -16,11 +16,13 @@ internal enum ChangeStreamTarget: String, Decodable { /// Open a change stream against this target. An error will be thrown if the necessary namespace information is not /// provided. - internal func watch(_ client: SyncMongoClient, - _ database: String?, - _ collection: String?, - _ pipeline: [Document], - _ options: ChangeStreamOptions) throws -> SyncChangeStream { + internal func watch( + _ client: SyncMongoClient, + _ database: String?, + _ collection: String?, + _ pipeline: [Document], + _ options: ChangeStreamOptions + ) throws -> SyncChangeStream { switch self { case .client: return try client.watch(pipeline, options: options, withEventType: Document.self) @@ -34,8 +36,8 @@ internal enum ChangeStreamTarget: String, Decodable { throw RuntimeError.internalError(message: "missing db or collection in watch") } return try client.db(database) - .collection(collection) - .watch(pipeline, options: options, withEventType: Document.self) + .collection(collection) + .watch(pipeline, options: options, withEventType: Document.self) } } } @@ -174,11 +176,13 @@ internal struct ChangeStreamTest: Decodable { defer { client.notificationCenter.removeObserver(observer) } do { - let changeStream = try self.target.watch(client, - database, - collection, - self.changeStreamPipeline, - self.changeStreamOptions) + let changeStream = try self.target.watch( + client, + database, + collection, + self.changeStreamPipeline, + self.changeStreamOptions + ) for operation in self.operations { _ = try operation.execute(using: globalClient) } @@ -191,7 +195,7 @@ internal struct ChangeStreamTest: Decodable { var seenEvents: [Document] = [] for _ in 0..= test.minServerVersion else { print("Skipping tests case \"\(test.description)\": minimum required server " + - "version \(test.minServerVersion) not met.") + "version \(test.minServerVersion) not met.") continue } @@ -288,9 +292,10 @@ final class ChangeStreamSpecTests: MongoSwiftTestCase, FailPointConfigured { } defer { self.disableActiveFailPoint() } - try test.run(globalClient: globalClient, - database: testFile.databaseName, - collection: testFile.collectionName + try test.run( + globalClient: globalClient, + database: testFile.databaseName, + collection: testFile.collectionName ) } } @@ -312,7 +317,7 @@ final class ChangeStreamTests: MongoSwiftTestCase { try withTestNamespace { _, _, coll in let changeStream = - try coll.watch(options: ChangeStreamOptions(maxAwaitTimeMS: ChangeStreamTests.MAX_AWAIT_TIME)) + try coll.watch(options: ChangeStreamOptions(maxAwaitTimeMS: ChangeStreamTests.MAX_AWAIT_TIME)) for x in 0..<5 { try coll.insertOne(["x": BSON(x)]) } @@ -350,10 +355,12 @@ final class ChangeStreamTests: MongoSwiftTestCase { } if try client.maxWireVersion() >= 8 { - let expectedError = ServerError.commandError(code: 280, - codeName: "ChangeStreamFatalError", - message: "", - errorLabels: ["NonResumableChangeStreamError"]) + let expectedError = ServerError.commandError( + code: 280, + codeName: "ChangeStreamFatalError", + message: "", + errorLabels: ["NonResumableChangeStreamError"] + ) expect(try changeStream.nextOrError()).to(throwError(expectedError)) } else { expect(try changeStream.nextOrError()).to(throwError(UserError.logicError(message: ""))) @@ -380,9 +387,11 @@ final class ChangeStreamTests: MongoSwiftTestCase { let events = try captureCommandEvents(eventTypes: [.commandStarted], commandNames: ["aggregate"]) { client in try withTestNamespace(client: client) { _, coll in - let options = ChangeStreamOptions(batchSize: 123, - fullDocument: .updateLookup, - maxAwaitTimeMS: ChangeStreamTests.MAX_AWAIT_TIME) + let options = ChangeStreamOptions( + batchSize: 123, + fullDocument: .updateLookup, + maxAwaitTimeMS: ChangeStreamTests.MAX_AWAIT_TIME + ) let changeStream = try coll.watch([["$match": ["fullDocument.x": 2]]], options: options) for x in 0..<5 { try coll.insertOne(["x": .int64(Int64(x))]) @@ -446,9 +455,11 @@ final class ChangeStreamTests: MongoSwiftTestCase { try failpoint.enable() defer { failpoint.disable() } - let aggAttempts = try captureCommandEvents(from: client, - eventTypes: [.commandStarted], - commandNames: ["aggregate"]) { + let aggAttempts = try captureCommandEvents( + from: client, + eventTypes: [.commandStarted], + commandNames: ["aggregate"] + ) { expect(try coll.watch()).to(throwError()) } expect(aggAttempts.count).to(equal(1)) @@ -456,15 +467,19 @@ final class ChangeStreamTests: MongoSwiftTestCase { // The above failpoint was configured to only run once, so this aggregate will succeed. let changeStream = try coll.watch() - let getMoreFailpoint = FailPoint.failCommand(failCommands: ["getMore", "aggregate"], - mode: .times(2), - errorCode: 10107) + let getMoreFailpoint = FailPoint.failCommand( + failCommands: ["getMore", "aggregate"], + mode: .times(2), + errorCode: 10107 + ) try getMoreFailpoint.enable() defer { getMoreFailpoint.disable() } - let aggAttempts1 = try captureCommandEvents(from: client, - eventTypes: [.commandStarted], - commandNames: ["aggregate"]) { + let aggAttempts1 = try captureCommandEvents( + from: client, + eventTypes: [.commandStarted], + commandNames: ["aggregate"] + ) { // getMore failure will trigger resume process, aggregate will fail and not retry again. expect(try changeStream.nextOrError()).to(throwError()) } @@ -523,7 +538,7 @@ final class ChangeStreamTests: MongoSwiftTestCase { try nonResumableLabel.enable() defer { nonResumableLabel.disable() } let labelAggs = try captureCommandEvents(eventTypes: [.commandStarted], commandNames: ["aggregate"]) { - expect(try $0.watch().nextOrError()).to(throwError()) + expect(try $0.watch().nextOrError()).to(throwError()) } expect(labelAggs.count).to(equal(1)) } @@ -545,7 +560,7 @@ final class ChangeStreamTests: MongoSwiftTestCase { let events = try captureCommandEvents(commandNames: ["killCursors"]) { client in try withTestNamespace(client: client) { _, coll in changeStream = - try coll.watch(options: ChangeStreamOptions(maxAwaitTimeMS: ChangeStreamTests.MAX_AWAIT_TIME)) + try coll.watch(options: ChangeStreamOptions(maxAwaitTimeMS: ChangeStreamTests.MAX_AWAIT_TIME)) _ = try changeStream!.nextOrError() } } @@ -574,9 +589,11 @@ final class ChangeStreamTests: MongoSwiftTestCase { } var changeStream: SyncChangeStream>? - let aggEvent = try captureCommandEvents(from: client, - eventTypes: [.commandSucceeded], - commandNames: ["aggregate"]) { + let aggEvent = try captureCommandEvents( + from: client, + eventTypes: [.commandSucceeded], + commandNames: ["aggregate"] + ) { let options = ChangeStreamOptions(batchSize: 1, maxAwaitTimeMS: ChangeStreamTests.MAX_AWAIT_TIME) changeStream = try collection.watch(options: options) } @@ -605,7 +622,7 @@ final class ChangeStreamTests: MongoSwiftTestCase { } } - // TODO SWIFT-567: Implement prose test 11 + // TODO: SWIFT-567: Implement prose test 11 /** * Prose test 12 of change stream spec. @@ -673,7 +690,7 @@ final class ChangeStreamTests: MongoSwiftTestCase { } let changeStream = - try coll.watch(options: ChangeStreamOptions(maxAwaitTimeMS: ChangeStreamTests.MAX_AWAIT_TIME)) + try coll.watch(options: ChangeStreamOptions(maxAwaitTimeMS: ChangeStreamTests.MAX_AWAIT_TIME)) for i in 0..<5 { try coll.insertOne(["x": BSON(i)]) } @@ -686,7 +703,7 @@ final class ChangeStreamTests: MongoSwiftTestCase { } } - // TODO SWIFT-576: Implement prose tests 14, 17, & 18 + // TODO: SWIFT-576: Implement prose tests 14, 17, & 18 func testChangeStreamOnAClient() throws { guard MongoSwiftTestCase.topologyType != .single else { @@ -715,7 +732,7 @@ final class ChangeStreamTests: MongoSwiftTestCase { expect(change1).toNot(beNil()) expect(change1?.operationType).to(equal(.insert)) expect(change1?.fullDocument).to(equal(doc1)) - //expect the resumeToken to be updated to the _id field of the most recently accessed document + // expect the resumeToken to be updated to the _id field of the most recently accessed document expect(changeStream.resumeToken).to(equal(change1?._id)) // test that a change exists for a different collection in the same database @@ -944,7 +961,7 @@ final class ChangeStreamTests: MongoSwiftTestCase { } func testChangeStreamWithFullDocumentType() throws { - guard MongoSwiftTestCase.topologyType != .single else { + guard MongoSwiftTestCase.topologyType != .single else { print(unsupportedTopologyMessage(testName: self.name)) return } diff --git a/Tests/MongoSwiftTests/ClientSessionTests.swift b/Tests/MongoSwiftTests/ClientSessionTests.swift index c7990ce8c..b454d0761 100644 --- a/Tests/MongoSwiftTests/ClientSessionTests.swift +++ b/Tests/MongoSwiftTests/ClientSessionTests.swift @@ -16,12 +16,18 @@ final class ClientSessionTests: MongoSwiftTestCase { super.tearDown() } - typealias CollectionSessionOp = (name: String, - body: (SyncMongoCollection, SyncClientSession?) throws -> Void) - typealias DatabaseSessionOp = (name: String, - body: (SyncMongoDatabase, SyncClientSession?) throws -> Void) - typealias ClientSessionOp = (name: String, - body: (SyncMongoClient, SyncClientSession?) throws -> Void) + typealias CollectionSessionOp = ( + name: String, + body: (SyncMongoCollection, SyncClientSession?) throws -> Void + ) + typealias DatabaseSessionOp = ( + name: String, + body: (SyncMongoDatabase, SyncClientSession?) throws -> Void + ) + typealias ClientSessionOp = ( + name: String, + body: (SyncMongoClient, SyncClientSession?) throws -> Void + ) typealias SessionOp = (name: String, body: (SyncClientSession?) throws -> Void) // list of read only operations on SyncMongoCollection that take in a session @@ -71,25 +77,27 @@ final class ClientSessionTests: MongoSwiftTestCase { (name: "listDatabaseNames", { _ = try $0.listDatabaseNames(session: $1) }) ] - // This function causes the compiler to crash on older versions of swift due to a bug in the compiler. - #if(swift(>=5.1)) +// This function causes the compiler to crash on older versions of swift due to a bug in the compiler. +#if swift(>=5.1) /// iterate over all the different session op types, passing in the provided client/db/collection as needed. - func forEachSessionOp(client: SyncMongoClient, - database: SyncMongoDatabase, - collection: SyncMongoCollection, - _ body: (SessionOp) throws -> Void) rethrows { - try (collectionSessionReadOps + collectionSessionWriteOps).forEach { op in + func forEachSessionOp( + client: SyncMongoClient, + database: SyncMongoDatabase, + collection: SyncMongoCollection, + _ body: (SessionOp) throws -> Void + ) rethrows { + try (self.collectionSessionReadOps + self.collectionSessionWriteOps).forEach { op in try body((name: op.name, body: { try op.body(collection, $0) })) } - try databaseSessionOps.forEach { op in + try self.databaseSessionOps.forEach { op in try body((name: op.name, body: { try op.body(database, $0) })) } - try clientSessionOps.forEach { op in + try self.clientSessionOps.forEach { op in try body((name: op.name, body: { try op.body(client, $0) })) } } - #endif +#endif /// Sessions spec test 1: Test that sessions are properly returned to the pool when ended. func testSessionCleanup() throws { @@ -174,26 +182,25 @@ final class ClientSessionTests: MongoSwiftTestCase { /// Sessions spec test 3: test that every function that takes a session parameter passes the sends implicit and /// explicit lsids to server. func testSessionArguments() throws { - // This test causes the compiler to crash on older versions of swift due to a bug in the compiler. - #if(swift(>=5.1)) - +// This test causes the compiler to crash on older versions of swift due to a bug in the compiler. +#if swift(>=5.1) let client1 = try SyncMongoClient.makeTestClient(options: ClientOptions(commandMonitoring: true)) let database = client1.db(type(of: self).testDatabase) let collection = try database.createCollection(self.getCollectionName()) let session = try client1.startSession() - try forEachSessionOp(client: client1, database: database, collection: collection) { op in + try self.forEachSessionOp(client: client1, database: database, collection: collection) { op in try runArgTest(session: session, op: op) } - #endif +#endif } /// Sessions spec test 4: test that a session can only be used with db's and collections that were derived from the /// same client. func testSessionClientValidation() throws { - // This test causes the compiler to crash on older versions of swift due to a bug in the compiler. - #if(swift(>=5.1)) +// This test causes the compiler to crash on older versions of swift due to a bug in the compiler. +#if swift(>=5.1) let client1 = try SyncMongoClient.makeTestClient() let client2 = try SyncMongoClient.makeTestClient() @@ -202,18 +209,18 @@ final class ClientSessionTests: MongoSwiftTestCase { let collection = try database.createCollection(self.getCollectionName()) let session = try client2.startSession() - try forEachSessionOp(client: client1, database: database, collection: collection) { op in + try self.forEachSessionOp(client: client1, database: database, collection: collection) { op in expect(try op.body(session)) - .to(throwError(UserError.invalidArgumentError(message: "")), description: op.name) + .to(throwError(UserError.invalidArgumentError(message: "")), description: op.name) } - #endif +#endif } /// Sessions spec test 5: Test that inactive sessions cannot be used. func testInactiveSession() throws { - // This test causes the compiler to crash on older versions of swift due to a bug in the compiler. - #if(swift(>=5.1)) +// This test causes the compiler to crash on older versions of swift due to a bug in the compiler. +#if swift(>=5.1) let client = try SyncMongoClient.makeTestClient() let db = client.db(type(of: self).testDatabase) @@ -223,7 +230,7 @@ final class ClientSessionTests: MongoSwiftTestCase { session1.end() expect(session1.active).to(beFalse()) - try forEachSessionOp(client: client, database: db, collection: collection) { op in + try self.forEachSessionOp(client: client, database: db, collection: collection) { op in expect(try op.body(session1)).to(throwError(SyncClientSession.SessionInactiveError), description: op.name) } @@ -238,7 +245,7 @@ final class ClientSessionTests: MongoSwiftTestCase { session2.end() expect(try cursor.nextOrError()).to(throwError(SyncClientSession.SessionInactiveError)) - #endif +#endif } /// Sessions spec test 10: Test cursors have the same lsid in the initial find command and in subsequent getMores. @@ -331,8 +338,8 @@ final class ClientSessionTests: MongoSwiftTestCase { /// Test that causal consistency guarantees are met on deployments that support cluster time. func testCausalConsistency() throws { - // This test causes the compiler to crash on older versions of swift due to a bug in the compiler. - #if(swift(>=5.1)) +// This test causes the compiler to crash on older versions of swift due to a bug in the compiler. +#if swift(>=5.1) guard MongoSwiftTestCase.topologyType != .single else { print(unsupportedTopologyMessage(testName: self.name)) @@ -384,7 +391,7 @@ final class ClientSessionTests: MongoSwiftTestCase { // // Causal consistency spec test 8: When using the default server ReadConcern the readConcern parameter in the // command sent to the server should not include a level field - try collectionSessionReadOps.forEach { op in + try self.collectionSessionReadOps.forEach { op in try client.withSession(options: ClientSessionOptions(causalConsistency: true)) { session in _ = try collection.find(session: session).next() let opTime = session.operationTime @@ -408,7 +415,7 @@ final class ClientSessionTests: MongoSwiftTestCase { // Causal consistency spec test 5: Any write operation followed by a find operation should include the // operationTime of the first operation in the afterClusterTime parameter of the second operation, including the // case where the first operation returned an error - try collectionSessionWriteOps.forEach { op in + try self.collectionSessionWriteOps.forEach { op in try client.withSession(options: ClientSessionOptions(causalConsistency: true)) { session in try? op.body(collection, session) let opTime = session.operationTime @@ -419,7 +426,7 @@ final class ClientSessionTests: MongoSwiftTestCase { return } expect(event.command["readConcern"]?.documentValue?["afterClusterTime"]?.timestampValue) - .to(equal(opTime), description: op.name) + .to(equal(opTime), description: op.name) seenCommand = true } defer { center.removeObserver(observer) } @@ -448,8 +455,10 @@ final class ClientSessionTests: MongoSwiftTestCase { // Causal consistency spec test 9: When using a custom ReadConcern the readConcern field in the command sent to // the server should be a merger of the ReadConcern value and the afterClusterTime field try client.withSession(options: ClientSessionOptions(causalConsistency: true)) { session in - let collection1 = db.collection(self.getCollectionName(), - options: CollectionOptions(readConcern: ReadConcern(.snapshot))) + let collection1 = db.collection( + self.getCollectionName(), + options: CollectionOptions(readConcern: ReadConcern(.snapshot)) + ) _ = try collection1.find(session: session).next() let opTime = session.operationTime @@ -484,7 +493,7 @@ final class ClientSessionTests: MongoSwiftTestCase { _ = try collection.find(session: session).next() expect(seenCommand).to(beTrue()) } - #endif +#endif } /// Test causal consistent behavior on a topology that doesn't support cluster time. @@ -570,8 +579,10 @@ final class ClientSessionTests: MongoSwiftTestCase { // Causal consistency spec test 10: When an unacknowledged write is executed in a causally consistent // ClientSession the operationTime property of the ClientSession is not updated try client.withSession(options: ClientSessionOptions(causalConsistency: true)) { session in - let collection1 = db.collection(self.getCollectionName(), - options: CollectionOptions(writeConcern: try WriteConcern(w: .number(0)))) + let collection1 = db.collection( + self.getCollectionName(), + options: CollectionOptions(writeConcern: try WriteConcern(w: .number(0))) + ) try collection1.insertOne(["x": 3]) expect(session.operationTime).to(beNil()) } diff --git a/Tests/MongoSwiftTests/CodecTests.swift b/Tests/MongoSwiftTests/CodecTests.swift index 215fbef9b..fa387e112 100644 --- a/Tests/MongoSwiftTests/CodecTests.swift +++ b/Tests/MongoSwiftTests/CodecTests.swift @@ -6,9 +6,9 @@ final class CodecTests: MongoSwiftTestCase { // generic decoding/encoding errors for error matching. Only the case is considered. static let typeMismatchErr = DecodingError._typeMismatch(at: [], expectation: Int.self, reality: 0) static let invalidValueErr = - EncodingError.invalidValue(0, EncodingError.Context(codingPath: [], debugDescription: "dummy error")) + EncodingError.invalidValue(0, EncodingError.Context(codingPath: [], debugDescription: "dummy error")) static let dataCorruptedErr = DecodingError.dataCorrupted( - DecodingError.Context(codingPath: [], debugDescription: "dummy error")) + DecodingError.Context(codingPath: [], debugDescription: "dummy error")) struct TestStruct: Encodable { let val1 = "a" @@ -123,14 +123,16 @@ final class CodecTests: MongoSwiftTestCase { static let keys = ["int8", "int16", "uint8", "uint16", "uint32", "uint64", "uint", "float"] - init(int8: Int8? = nil, - int16: Int16? = nil, - uint8: UInt8? = nil, - uint16: UInt16? = nil, - uint32: UInt32? = nil, - uint64: UInt64? = nil, - uint: UInt? = nil, - float: Float? = nil) { + init( + int8: Int8? = nil, + int16: Int16? = nil, + uint8: UInt8? = nil, + uint16: UInt16? = nil, + uint32: UInt32? = nil, + uint64: UInt64? = nil, + uint: UInt? = nil, + float: Float? = nil + ) { self.int8 = int8 self.int16 = int16 self.uint8 = uint8 @@ -159,23 +161,25 @@ final class CodecTests: MongoSwiftTestCase { expect(try encoder.encode(s1)).to(equal(doc1)) // check that a UInt32 too large for an Int32 gets converted to Int64 - expect(try encoder.encode(Numbers(uint32: 4294967295))).to(equal(["uint32": .int64(4294967295)])) + expect(try encoder.encode(Numbers(uint32: 4_294_967_295))).to(equal(["uint32": .int64(4_294_967_295)])) // check that UInt, UInt64 too large for an Int32 gets converted to Int64 - expect(try encoder.encode(Numbers(uint64: 4294967295))).to(equal(["uint64": .int64(4294967295)])) - expect(try encoder.encode(Numbers(uint: 4294967295))).to(equal(["uint": .int64(4294967295)])) + expect(try encoder.encode(Numbers(uint64: 4_294_967_295))).to(equal(["uint64": .int64(4_294_967_295)])) + expect(try encoder.encode(Numbers(uint: 4_294_967_295))).to(equal(["uint": .int64(4_294_967_295)])) // check that UInt, UInt64 too large for an Int64 gets converted to Double - expect(try encoder.encode(Numbers(uint64: UInt64(Int64.max) + 1))).to(equal(["uint64": 9223372036854775808.0])) + expect(try encoder.encode(Numbers(uint64: UInt64(Int64.max) + 1))) + .to(equal(["uint64": 9_223_372_036_854_775_808.0])) // on a 32-bit platform, Int64.max + 1 will not fit in a UInt. if !MongoSwiftTestCase.is32Bit { - expect(try encoder.encode(Numbers(uint: UInt(Int64.max) + 1))).to(equal(["uint": 9223372036854775808.0])) + expect(try encoder.encode(Numbers(uint: UInt(Int64.max) + 1))) + .to(equal(["uint": 9_223_372_036_854_775_808.0])) } // check that we fail gracefully with a UInt, UInt64 that can't fit in any type. expect(try encoder.encode(Numbers(uint64: UInt64.max))).to(throwError(CodecTests.invalidValueErr)) // on a 32-bit platform, UInt.max = UInt32.max, which fits in an Int64. if MongoSwiftTestCase.is32Bit { - expect(try encoder.encode(Numbers(uint: UInt.max))).to(equal(["uint": 4294967295])) + expect(try encoder.encode(Numbers(uint: UInt.max))).to(equal(["uint": 4_294_967_295])) } else { expect(try encoder.encode(Numbers(uint: UInt.max))).to(throwError(CodecTests.invalidValueErr)) } @@ -217,19 +221,19 @@ final class CodecTests: MongoSwiftTestCase { // test for each type that we fail gracefully when values cannot be represented because they are out of bounds expect(try decoder.decode(Numbers.self, from: ["int8": .int64(Int64(Int8.max) + 1)])) - .to(throwError(CodecTests.typeMismatchErr)) + .to(throwError(CodecTests.typeMismatchErr)) expect(try decoder.decode(Numbers.self, from: ["int16": .int64(Int64(Int16.max) + 1)])) - .to(throwError(CodecTests.typeMismatchErr)) + .to(throwError(CodecTests.typeMismatchErr)) expect(try decoder.decode(Numbers.self, from: ["uint8": -1])).to(throwError(CodecTests.typeMismatchErr)) - expect(try decoder.decode(Numbers.self, from: [ "uint16": -1])).to(throwError(CodecTests.typeMismatchErr)) + expect(try decoder.decode(Numbers.self, from: ["uint16": -1])).to(throwError(CodecTests.typeMismatchErr)) expect(try decoder.decode(Numbers.self, from: ["uint32": -1])).to(throwError(CodecTests.typeMismatchErr)) expect(try decoder.decode(Numbers.self, from: ["uint64": -1])).to(throwError(CodecTests.typeMismatchErr)) expect(try decoder.decode(Numbers.self, from: ["uint": -1])).to(throwError(CodecTests.typeMismatchErr)) expect(try decoder.decode(Numbers.self, from: ["float": .double(Double.greatestFiniteMagnitude)])) - .to(throwError(CodecTests.typeMismatchErr)) + .to(throwError(CodecTests.typeMismatchErr)) } - struct BSONNumbers: Codable, Equatable { + struct BSONNumbers: Codable, Equatable { let int: Int let int32: Int32 let int64: Int64 @@ -287,27 +291,28 @@ final class CodecTests: MongoSwiftTestCase { public static func factory() throws -> AllBSONTypes { return AllBSONTypes( - double: Double(2), - string: "hi", - doc: ["x": 1], - arr: [.int32(1), .int32(2)], - binary: try Binary(base64: "//8=", subtype: .generic), - oid: ObjectId("507f1f77bcf86cd799439011")!, - bool: true, - date: Date(timeIntervalSinceReferenceDate: 5000), - code: Code(code: "hi"), - codeWithScope: CodeWithScope(code: "hi", scope: ["x": .int64(1)]), - ts: Timestamp(timestamp: 1, inc: 2), - int32: 5, - int64: 6, - dec: Decimal128("1.2E+10")!, - minkey: MinKey(), - maxkey: MaxKey(), - regex: RegularExpression(pattern: "^abc", options: "imx"), - symbol: Symbol("i am a symbol"), - undefined: BSONUndefined(), - dbpointer: DBPointer(ref: "some.namespace", id: ObjectId("507f1f77bcf86cd799439011")!), - null: BSONNull()) + double: Double(2), + string: "hi", + doc: ["x": 1], + arr: [.int32(1), .int32(2)], + binary: try Binary(base64: "//8=", subtype: .generic), + oid: ObjectId("507f1f77bcf86cd799439011")!, + bool: true, + date: Date(timeIntervalSinceReferenceDate: 5000), + code: Code(code: "hi"), + codeWithScope: CodeWithScope(code: "hi", scope: ["x": .int64(1)]), + ts: Timestamp(timestamp: 1, inc: 2), + int32: 5, + int64: 6, + dec: Decimal128("1.2E+10")!, + minkey: MinKey(), + maxkey: MaxKey(), + regex: RegularExpression(pattern: "^abc", options: "imx"), + symbol: Symbol("i am a symbol"), + undefined: BSONUndefined(), + dbpointer: DBPointer(ref: "some.namespace", id: ObjectId("507f1f77bcf86cd799439011")!), + null: BSONNull() + ) } // Manually construct a document from this instance for comparision with encoder output. @@ -351,7 +356,7 @@ final class CodecTests: MongoSwiftTestCase { expect(try BSONEncoder().encode(expected)).to(equal(doc)) - //swiftlint:disable line_length + // swiftlint:disable line_length let base64 = "//8=" let extjson = """ { @@ -379,7 +384,7 @@ final class CodecTests: MongoSwiftTestCase { "null": null } """ - //swiftlint:enable line_length + // swiftlint:enable line_length let res2 = try decoder.decode(AllBSONTypes.self, from: extjson) expect(res2).to(equal(expected)) @@ -403,28 +408,40 @@ final class CodecTests: MongoSwiftTestCase { expect(try decoder.decode(Double.self, from: "42.42")).to(equal(42.42)) expect(try decoder.decode(Double.self, from: "{\"$numberDouble\": \"42.42\"}")).to(equal(42.42)) - expect(try decoder.decode(Decimal128.self, - from: "{\"$numberDecimal\": \"1.2E+10\"}")).to(equal(Decimal128("1.2E+10")!)) + expect(try decoder.decode( + Decimal128.self, + from: "{\"$numberDecimal\": \"1.2E+10\"}" + )).to(equal(Decimal128("1.2E+10")!)) let binary = try Binary(base64: "//8=", subtype: .generic) expect( - try decoder.decode(Binary.self, - from: "{\"$binary\" : {\"base64\": \"//8=\", \"subType\" : \"00\"}}") + try decoder.decode( + Binary.self, + from: "{\"$binary\" : {\"base64\": \"//8=\", \"subType\" : \"00\"}}" + ) ).to(equal(binary)) - expect(try decoder.decode(Code.self, - from: "{\"$code\": \"hi\" }")).to(equal(Code(code: "hi"))) + expect(try decoder.decode( + Code.self, + from: "{\"$code\": \"hi\" }" + )).to(equal(Code(code: "hi"))) let code = Code(code: "hi") - expect(try decoder.decode(Code.self, - from: "{\"$code\": \"hi\", \"$scope\": {\"x\" : { \"$numberLong\": \"1\" }} }") + expect(try decoder.decode( + Code.self, + from: "{\"$code\": \"hi\", \"$scope\": {\"x\" : { \"$numberLong\": \"1\" }} }" + ) ).to(throwError()) expect(try decoder.decode(Code.self, from: "{\"$code\": \"hi\" }")).to(equal(code)) - expect(try decoder.decode(CodeWithScope.self, - from: "{\"$code\": \"hi\" }")).to(throwError()) + expect(try decoder.decode( + CodeWithScope.self, + from: "{\"$code\": \"hi\" }" + )).to(throwError()) let cws = CodeWithScope(code: "hi", scope: ["x": 1]) - expect(try decoder.decode(CodeWithScope.self, - from: "{\"$code\": \"hi\", \"$scope\": {\"x\" : { \"$numberLong\": \"1\" }} }") + expect(try decoder.decode( + CodeWithScope.self, + from: "{\"$code\": \"hi\", \"$scope\": {\"x\" : { \"$numberLong\": \"1\" }} }" + ) ).to(equal(cws)) expect(try decoder.decode(Document.self, from: "{\"x\": 1}")).to(equal(["x": .int32(1)])) @@ -433,8 +450,10 @@ final class CodecTests: MongoSwiftTestCase { let regex = RegularExpression(pattern: "^abc", options: "imx") expect( - try decoder.decode(RegularExpression.self, - from: "{ \"$regularExpression\" : { \"pattern\" :\"^abc\", \"options\" : \"imx\" } }") + try decoder.decode( + RegularExpression.self, + from: "{ \"$regularExpression\" : { \"pattern\" :\"^abc\", \"options\" : \"imx\" } }" + ) ).to(equal(regex)) expect(try decoder.decode(MinKey.self, from: "{\"$minKey\": 1}")).to(equal(MinKey())) @@ -456,34 +475,34 @@ final class CodecTests: MongoSwiftTestCase { // to demonstrate that a Document can theoretically work with any encoder/decoder. return - // let encoder = JSONEncoder() - // let decoder = JSONDecoder() - - // let json = """ - // { - // "name": "Durian", - // "points": 600, - // "pointsDouble": 600.5, - // "description": "A fruit with a distinctive scent.", - // "array": ["a", "b", "c"], - // "doc": { "x" : 2.0 } - // } - // """ - - // let expected: Document = [ - // "name": "Durian", - // "points": 600, - // "pointsDouble": 600.5, - // "description": "A fruit with a distinctive scent.", - // "array": ["a", "b", "c"], - // "doc": ["x": 2] as Document - // ] - - // let decoded = try decoder.decode(Document.self, from: json.data(using: .utf8)!) - // expect(decoded).to(sortedEqual(expected)) - - // let encoded = try String(data: encoder.encode(expected), encoding: .utf8) - // expect(encoded).to(cleanEqual(json)) + // let encoder = JSONEncoder() + // let decoder = JSONDecoder() + + // let json = """ + // { + // "name": "Durian", + // "points": 600, + // "pointsDouble": 600.5, + // "description": "A fruit with a distinctive scent.", + // "array": ["a", "b", "c"], + // "doc": { "x" : 2.0 } + // } + // """ + + // let expected: Document = [ + // "name": "Durian", + // "points": 600, + // "pointsDouble": 600.5, + // "description": "A fruit with a distinctive scent.", + // "array": ["a", "b", "c"], + // "doc": ["x": 2] as Document + // ] + + // let decoded = try decoder.decode(Document.self, from: json.data(using: .utf8)!) + // expect(decoded).to(sortedEqual(expected)) + + // let encoded = try String(data: encoder.encode(expected), encoding: .utf8) + // expect(encoded).to(cleanEqual(json)) } func testEncodeArray() throws { @@ -520,8 +539,10 @@ final class CodecTests: MongoSwiftTestCase { let wrappedDoc: Document = ["x": bsonDoc] expect(try encoder.encode(AnyBSONStruct(bsonDoc))).to(equal(wrappedDoc)) expect(try decoder.decode(AnyBSONStruct.self, from: wrappedDoc).x).to(equal(bsonDoc)) - expect(try decoder.decode(AnyBSONStruct.self, - from: wrappedDoc.canonicalExtendedJSON).x).to(equal(bsonDoc)) + expect(try decoder.decode( + AnyBSONStruct.self, + from: wrappedDoc.canonicalExtendedJSON + ).x).to(equal(bsonDoc)) // values wrapped in an `AnyBSONStruct` let double: BSON = 42.0 @@ -545,8 +566,8 @@ final class CodecTests: MongoSwiftTestCase { let array: BSON = [1, 2, "hello"] let decodedArray = try decoder.decode( - BSON.self, - from: "[{\"$numberLong\": \"1\"}, {\"$numberLong\": \"2\"}, \"hello\"]" + BSON.self, + from: "[{\"$numberLong\": \"1\"}, {\"$numberLong\": \"2\"}, \"hello\"]" ).arrayValue expect(decodedArray).toNot(beNil()) expect(decodedArray?[0]).to(equal(1)) @@ -564,15 +585,19 @@ final class CodecTests: MongoSwiftTestCase { let binary = BSON.binary(try Binary(base64: "//8=", subtype: .generic)) expect( - try decoder.decode(BSON.self, - from: "{\"$binary\" : {\"base64\": \"//8=\", \"subType\" : \"00\"}}") + try decoder.decode( + BSON.self, + from: "{\"$binary\" : {\"base64\": \"//8=\", \"subType\" : \"00\"}}" + ) ).to(equal(binary)) let wrappedBinary: Document = ["x": binary] expect(try encoder.encode(AnyBSONStruct(binary))).to(equal(wrappedBinary)) expect(try decoder.decode(AnyBSONStruct.self, from: wrappedBinary).x).to(equal(binary)) - expect(try decoder.decode(AnyBSONStruct.self, - from: wrappedBinary.canonicalExtendedJSON).x).to(equal(binary)) + expect(try decoder.decode( + AnyBSONStruct.self, + from: wrappedBinary.canonicalExtendedJSON + ).x).to(equal(binary)) // objectid let oid = ObjectId() @@ -607,7 +632,7 @@ final class CodecTests: MongoSwiftTestCase { let dateEncoder = BSONEncoder() dateEncoder.dateEncodingStrategy = .millisecondsSince1970 - expect(try dateEncoder.encode(AnyBSONStruct(date))).to(equal(["x": 5000000])) + expect(try dateEncoder.encode(AnyBSONStruct(date))).to(equal(["x": 5_000_000])) let dateDecoder = BSONDecoder() dateDecoder.dateDecodingStrategy = .millisecondsSince1970 @@ -616,8 +641,10 @@ final class CodecTests: MongoSwiftTestCase { // regex let regex = BSON.regex(RegularExpression(pattern: "abc", options: "imx")) - expect(try decoder.decode(BSON.self, - from: "{ \"$regularExpression\" : { \"pattern\" : \"abc\", \"options\" : \"imx\" } }") + expect(try decoder.decode( + BSON.self, + from: "{ \"$regularExpression\" : { \"pattern\" : \"abc\", \"options\" : \"imx\" } }" + ) ).to(equal(regex)) let wrappedRegex: Document = ["x": regex] @@ -629,9 +656,11 @@ final class CodecTests: MongoSwiftTestCase { let code = BSON.codeWithScope(CodeWithScope(code: "console.log(x);", scope: ["x": 1])) expect( - try decoder.decode(BSON.self, - from: "{ \"$code\" : \"console.log(x);\", " - + "\"$scope\" : { \"x\" : { \"$numberLong\" : \"1\" } } }") + try decoder.decode( + BSON.self, + from: "{ \"$code\" : \"console.log(x);\", " + + "\"$scope\" : { \"x\" : { \"$numberLong\" : \"1\" } } }" + ) ).to(equal(code)) let wrappedCode: Document = ["x": code] @@ -709,7 +738,7 @@ final class CodecTests: MongoSwiftTestCase { let x: BSON // An empty encode here is incorrect. - func encode(to encoder: Encoder) throws {} + func encode(to _: Encoder) throws {} init(_ x: BSON) { self.x = x @@ -726,7 +755,7 @@ final class CodecTests: MongoSwiftTestCase { // An empty encode here is incorrect. func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) - try container.encode(x, forKey: .x) + try container.encode(self.x, forKey: .x) } init(_ x: BSON) { @@ -752,16 +781,17 @@ final class CodecTests: MongoSwiftTestCase { let rp = ReadPreference(.primary) let agg = AggregateOptions( - allowDiskUse: true, - batchSize: 5, - bypassDocumentValidation: false, - collation: Document(), - comment: "hello", - hint: .indexName("hint"), - maxTimeMS: 12, - readConcern: rc, - readPreference: rp, - writeConcern: wc) + allowDiskUse: true, + batchSize: 5, + bypassDocumentValidation: false, + collation: Document(), + comment: "hello", + hint: .indexName("hint"), + maxTimeMS: 12, + readConcern: rc, + readPreference: rp, + writeConcern: wc + ) expect(try encoder.encode(agg).keys.sorted()).to(equal([ "allowDiskUse", @@ -776,13 +806,13 @@ final class CodecTests: MongoSwiftTestCase { ])) let count = CountOptions( - collation: Document(), - hint: .indexName("hint"), - limit: 123, - maxTimeMS: 12, - readConcern: rc, - readPreference: rp, - skip: 123 + collation: Document(), + hint: .indexName("hint"), + limit: 123, + maxTimeMS: 12, + readConcern: rc, + readPreference: rp, + skip: 123 ) expect(try encoder.encode(count).keys.sorted()).to(equal([ "collation", @@ -794,10 +824,10 @@ final class CodecTests: MongoSwiftTestCase { ])) let distinct = DistinctOptions( - collation: Document(), - maxTimeMS: 123, - readConcern: rc, - readPreference: rp + collation: Document(), + maxTimeMS: 123, + readConcern: rc, + readPreference: rp ) expect(try encoder.encode(distinct).keys.sorted()).to(equal([ "collation", @@ -806,26 +836,27 @@ final class CodecTests: MongoSwiftTestCase { ].sorted())) let find = FindOptions( - allowPartialResults: false, - batchSize: 123, - collation: Document(), - comment: "asdf", - cursorType: .tailable, - hint: .indexName("sdf"), - limit: 123, - max: Document(), - maxAwaitTimeMS: 123, - maxScan: 23, - maxTimeMS: 123, - min: Document(), - noCursorTimeout: true, - projection: Document(), - readConcern: rc, - readPreference: rp, - returnKey: true, - showRecordId: false, - skip: 45, - sort: Document()) + allowPartialResults: false, + batchSize: 123, + collation: Document(), + comment: "asdf", + cursorType: .tailable, + hint: .indexName("sdf"), + limit: 123, + max: Document(), + maxAwaitTimeMS: 123, + maxScan: 23, + maxTimeMS: 123, + min: Document(), + noCursorTimeout: true, + projection: Document(), + readConcern: rc, + readPreference: rp, + returnKey: true, + showRecordId: false, + skip: 45, + sort: Document() + ) expect(try encoder.encode(find).keys.sorted()).to(equal([ "allowPartialResults", "awaitData", @@ -850,24 +881,25 @@ final class CodecTests: MongoSwiftTestCase { ])) let index = IndexOptions( - background: false, - bits: 32, - bucketSize: 333, - collation: Document(), - defaultLanguage: "english", - expireAfterSeconds: 123, - languageOverride: "asdf", - max: 5.5, - min: 4.4, - name: "sadf", - partialFilterExpression: Document(), - sparse: false, - sphereIndexVersion: 959, - storageEngine: ["a": 1], - textIndexVersion: 123, - unique: true, - version: 123, - weights: Document()) + background: false, + bits: 32, + bucketSize: 333, + collation: Document(), + defaultLanguage: "english", + expireAfterSeconds: 123, + languageOverride: "asdf", + max: 5.5, + min: 4.4, + name: "sadf", + partialFilterExpression: Document(), + sparse: false, + sphereIndexVersion: 959, + storageEngine: ["a": 1], + textIndexVersion: 123, + unique: true, + version: 123, + weights: Document() + ) expect(try encoder.encode(index).keys.sorted()).to(equal([ "background", "bits", @@ -890,9 +922,9 @@ final class CodecTests: MongoSwiftTestCase { ].sorted())) let runCommand = RunCommandOptions( - readConcern: rc, - readPreference: rp, - writeConcern: wc + readConcern: rc, + readPreference: rp, + writeConcern: wc ) expect(try encoder.encode(runCommand).keys.sorted()).to(equal([ diff --git a/Tests/MongoSwiftTests/CommandMonitoringTests.swift b/Tests/MongoSwiftTests/CommandMonitoringTests.swift index 26602de69..5476244c1 100644 --- a/Tests/MongoSwiftTests/CommandMonitoringTests.swift +++ b/Tests/MongoSwiftTests/CommandMonitoringTests.swift @@ -74,8 +74,10 @@ final class CommandMonitoringTests: MongoSwiftTestCase { func testAlternateNotificationCenters() throws { let customCenter = NotificationCenter() - let client = try SyncMongoClient.makeTestClient(options: ClientOptions(commandMonitoring: true, - notificationCenter: customCenter)) + let client = try SyncMongoClient.makeTestClient(options: ClientOptions( + commandMonitoring: true, + notificationCenter: customCenter + )) let db = client.db(type(of: self).testDatabase) let collection = try db.createCollection(self.getCollectionName()) var eventCount = 0 @@ -101,7 +103,7 @@ private struct CMTestFile: Decodable { enum CodingKeys: String, CodingKey { case data, collectionName = "collection_name", - databaseName = "database_name", tests, namespace + databaseName = "database_name", tests, namespace } } @@ -132,8 +134,8 @@ private struct CMTest: Decodable { enum CodingKeys: String, CodingKey { case description, op = "operation", expectationDocs = "expectations", - minServerVersion = "ignore_if_server_version_less_than", - maxServerVersion = "ignore_if_server_version_greater_than" + minServerVersion = "ignore_if_server_version_less_than", + maxServerVersion = "ignore_if_server_version_greater_than" } // Given a collection, perform the operation specified for this test on it. @@ -142,7 +144,7 @@ private struct CMTest: Decodable { // events won't match up. // swiftlint:disable cyclomatic_complexity func doOperation(withCollection collection: SyncMongoCollection) throws { - // TODO SWIFT-31: use readPreferences for commands if provided + // TODO: SWIFT-31: use readPreferences for commands if provided let filter: Document = self.op.args["filter"]?.documentValue ?? [:] switch self.op.name { @@ -159,17 +161,19 @@ private struct CMTest: Decodable { if let hintDoc = modifiers?["$hint"]?.documentValue { hint = .indexSpec(hintDoc) } - let options = FindOptions(batchSize: self.op.args["batchSize"]?.asInt32(), - comment: modifiers?["$comment"]?.stringValue, - hint: hint, - limit: self.op.args["limit"]?.asInt64(), - max: modifiers?["$max"]?.documentValue, - maxTimeMS: modifiers?["$maxTimeMS"]?.asInt64(), - min: modifiers?["$min"]?.documentValue, - returnKey: modifiers?["$returnKey"]?.boolValue, - showRecordId: modifiers?["$showDiskLoc"]?.boolValue, - skip: self.op.args["skip"]?.asInt64(), - sort: self.op.args["sort"]?.documentValue) + let options = FindOptions( + batchSize: self.op.args["batchSize"]?.asInt32(), + comment: modifiers?["$comment"]?.stringValue, + hint: hint, + limit: self.op.args["limit"]?.asInt64(), + max: modifiers?["$max"]?.documentValue, + maxTimeMS: modifiers?["$maxTimeMS"]?.asInt64(), + min: modifiers?["$min"]?.documentValue, + returnKey: modifiers?["$returnKey"]?.boolValue, + showRecordId: modifiers?["$showDiskLoc"]?.boolValue, + skip: self.op.args["skip"]?.asInt64(), + sort: self.op.args["sort"]?.documentValue + ) // we have to iterate the cursor to make the command execute for _ in try! collection.find(filter, options: options) {} @@ -196,6 +200,7 @@ private struct CMTest: Decodable { XCTFail("Unrecognized operation name \(self.op.name)") } } + // swiftlint:enable cyclomatic_complexity } @@ -234,8 +239,8 @@ private struct CommandStartedExpectation: ExpectationType, Decodable { enum CodingKeys: String, CodingKey { case command, - commandName = "command_name", - databaseName = "database_name" + commandName = "command_name", + databaseName = "database_name" } func compare(to notification: Notification, testContext: inout [String: Any]) { @@ -274,24 +279,24 @@ private func normalizeCommand(_ input: Document) -> Document { if ["upsert", "multi"].contains(k), let bV = v.boolValue { if bV { output[k] = true } else { continue } - // The tests don't explicitly store maxTimeMS as an Int64, so libmongoc - // parses it as an Int32 which we convert to Int. convert to Int64 here because we - // (as per the crud spec) use an Int64 for maxTimeMS and send that to - // the server in our actual commands. + // The tests don't explicitly store maxTimeMS as an Int64, so libmongoc + // parses it as an Int32 which we convert to Int. convert to Int64 here because we + // (as per the crud spec) use an Int64 for maxTimeMS and send that to + // the server in our actual commands. } else if k == "maxTimeMS", let iV = v.asInt64() { output[k] = .int64(iV) - // The expected batch sizes are always Int64s, however, find command - // events actually have Int32 batch sizes... (as the spec says...) - // but getMores have Int64s. so only convert if it's a find command... + // The expected batch sizes are always Int64s, however, find command + // events actually have Int32 batch sizes... (as the spec says...) + // but getMores have Int64s. so only convert if it's a find command... } else if k == "batchSize" && input["find"] != nil { output[k] = .int32(v.asInt32()!) - // recursively normalize if it's a document + // recursively normalize if it's a document } else if let docVal = v.documentValue { output[k] = .document(normalizeCommand(docVal)) - // recursively normalize each element if it's an array + // recursively normalize each element if it's an array } else if case let .array(arrVal) = v { output[k] = .array(arrVal.map { switch $0 { @@ -302,7 +307,7 @@ private func normalizeCommand(_ input: Document) -> Document { } }) - // just copy the value over as is + // just copy the value over as is } else { output[k] = v } @@ -317,7 +322,7 @@ private struct CommandFailedExpectation: ExpectationType, Decodable { case commandName = "command_name" } - func compare(to notification: Notification, testContext: inout [String: Any]) { + func compare(to notification: Notification, testContext _: inout [String: Any]) { guard let event = notification.userInfo?["event"] as? CommandFailedEvent else { XCTFail("Notification \(notification) did not contain a CommandFailedEvent") return @@ -367,7 +372,7 @@ private struct CommandSucceededExpectation: ExpectationType, Decodable { // if we aren't already storing a cursor ID for this test, add one if storedId == nil { testContext["cursorId"] = id - // otherwise, verify that this ID matches the stored one + // otherwise, verify that this ID matches the stored one } else { expect(storedId).to(equal(id)) } @@ -414,11 +419,11 @@ private func normalizeExpectedReply(_ input: Document) -> Document { // writeErrors and cursor separately. if ["writeErrors", "cursor"].contains(k) { continue - // The server sends back doubles, but the JSON test files - // contain integer statuses (see SPEC-1050.) + // The server sends back doubles, but the JSON test files + // contain integer statuses (see SPEC-1050.) } else if k == "ok", let dV = v.asDouble() { output[k] = .double(dV) - // just copy the value over as is + // just copy the value over as is } else { output[k] = v } diff --git a/Tests/MongoSwiftTests/CrudTests.swift b/Tests/MongoSwiftTests/CrudTests.swift index 1fc1697d6..4a29acbf8 100644 --- a/Tests/MongoSwiftTests/CrudTests.swift +++ b/Tests/MongoSwiftTests/CrudTests.swift @@ -51,12 +51,12 @@ final class CrudTests: MongoSwiftTestCase { // Run all the tests at the /read path func testReads() throws { - try doTests(forSubdirectory: "read") + try self.doTests(forSubdirectory: "read") } // Run all the tests at the /write path func testWrites() throws { - try doTests(forSubdirectory: "write") + try self.doTests(forSubdirectory: "write") } } @@ -64,7 +64,7 @@ final class CrudTests: MongoSwiftTestCase { private struct CrudTestFile: Decodable { let data: [Document] let testDocs: [Document] - var tests: [CrudTest] { return try! testDocs.map { try makeCrudTest($0) } } + var tests: [CrudTest] { return try! self.testDocs.map { try makeCrudTest($0) } } let minServerVersion: String? let maxServerVersion: String? @@ -125,6 +125,7 @@ private class CrudTest { } return nil } + var upsert: Bool? { return self.args["upsert"]?.boolValue } /// Initializes a new `CrudTest` from a `Document`. @@ -140,7 +141,7 @@ private class CrudTest { } // Subclasses should implement `execute` according to the particular operation(s) they are for. - func execute(usingCollection coll: SyncMongoCollection) throws { XCTFail("Unimplemented") } + func execute(usingCollection _: SyncMongoCollection) throws { XCTFail("Unimplemented") } // If the test has a `collection` field in its `outcome`, verify that the expected // data is present. If there is no `collection` field, do nothing. @@ -216,10 +217,10 @@ private class BulkWriteTest: CrudTest { do { if let result = try coll.bulkWrite(requests, options: options) { - verifyBulkWriteResult(result) + self.verifyBulkWriteResult(result) } expect(expectError).to(beFalse()) - } catch ServerError.bulkWriteError(_, _, _, let result, _) { + } catch let ServerError.bulkWriteError(_, _, _, result, _) { if let result = result { verifyBulkWriteResult(result) } @@ -315,11 +316,13 @@ private class DistinctTest: CrudTest { private class FindTest: CrudTest { override func execute(usingCollection coll: SyncMongoCollection) throws { let filter: Document = try self.args.get("filter") - let options = FindOptions(batchSize: self.batchSize, - collation: self.collation, - limit: self.limit, - skip: self.skip, - sort: self.sort) + let options = FindOptions( + batchSize: self.batchSize, + collation: self.collation, + limit: self.limit, + skip: self.skip, + sort: self.sort + ) let result = BSON.array(try coll.find(filter, options: options).map { .document($0) }) expect(result).to(equal(self.result)) } @@ -342,11 +345,13 @@ private class FindOneAndReplaceTest: CrudTest { let filter: Document = try self.args.get("filter") let replacement: Document = try self.args.get("replacement") - let opts = FindOneAndReplaceOptions(collation: self.collation, - projection: self.projection, - returnDocument: self.returnDoc, - sort: self.sort, - upsert: self.upsert) + let opts = FindOneAndReplaceOptions( + collation: self.collation, + projection: self.projection, + returnDocument: self.returnDoc, + sort: self.sort, + upsert: self.upsert + ) let result = try coll.findOneAndReplace(filter: filter, replacement: replacement, options: opts) self.verifyFindAndModifyResult(result) @@ -359,12 +364,14 @@ private class FindOneAndUpdateTest: CrudTest { let filter: Document = try self.args.get("filter") let update: Document = try self.args.get("update") - let opts = FindOneAndUpdateOptions(arrayFilters: self.arrayFilters, - collation: self.collation, - projection: self.projection, - returnDocument: self.returnDoc, - sort: self.sort, - upsert: self.upsert) + let opts = FindOneAndUpdateOptions( + arrayFilters: self.arrayFilters, + collation: self.collation, + projection: self.projection, + returnDocument: self.returnDoc, + sort: self.sort, + upsert: self.upsert + ) let result = try coll.findOneAndUpdate(filter: filter, update: update, options: opts) self.verifyFindAndModifyResult(result) @@ -383,7 +390,7 @@ private class InsertManyTest: CrudTest { verifyInsertManyResult(result) } expect(expectError).to(beFalse()) - } catch ServerError.bulkWriteError(_, _, _, let result, _) { + } catch let ServerError.bulkWriteError(_, _, _, result, _) { if let result = result { verifyInsertManyResult(InsertManyResult(from: result)!) } diff --git a/Tests/MongoSwiftTests/DNSSeedlistTests.swift b/Tests/MongoSwiftTests/DNSSeedlistTests.swift index 9bab69f4d..89bbe2641 100644 --- a/Tests/MongoSwiftTests/DNSSeedlistTests.swift +++ b/Tests/MongoSwiftTests/DNSSeedlistTests.swift @@ -47,10 +47,12 @@ final class DNSSeedlistTests: MongoSwiftTestCase { return } - let tests = try retrieveSpecTestFiles(specName: "initial-dns-seedlist-discovery", - asType: DNSSeedlistTestCase.self) + let tests = try retrieveSpecTestFiles( + specName: "initial-dns-seedlist-discovery", + asType: DNSSeedlistTestCase.self + ) for (filename, testCase) in tests { - // TODO SWIFT-593: run these tests + // TODO: SWIFT-593: run these tests guard !["encoded-userinfo-and-db.json", "uri-with-auth.json"].contains(filename) else { continue } @@ -70,11 +72,15 @@ final class DNSSeedlistTests: MongoSwiftTestCase { // Enclose all of the potentially throwing code in `doTest`. Sometimes the expected errors come when // parsing the URI, and other times they are not until we try to send a command. func doTest() throws { - let opts = TLSOptions(allowInvalidHostnames: true, - caFile: URL(string: MongoSwiftTestCase.sslCAFilePath ?? ""), - pemFile: URL(string: MongoSwiftTestCase.sslPEMKeyFilePath ?? "")) - let client = try SyncMongoClient(testCase.uri, - options: ClientOptions(serverMonitoring: true, tlsOptions: opts)) + let opts = TLSOptions( + allowInvalidHostnames: true, + caFile: URL(string: MongoSwiftTestCase.sslCAFilePath ?? ""), + pemFile: URL(string: MongoSwiftTestCase.sslPEMKeyFilePath ?? "") + ) + let client = try SyncMongoClient( + testCase.uri, + options: ClientOptions(serverMonitoring: true, tlsOptions: opts) + ) // mongoc connects lazily so we need to send a command. let db = client.db("test") @@ -95,7 +101,7 @@ final class DNSSeedlistTests: MongoSwiftTestCase { // "You MUST verify that each of the values of the Connection String Options under options match the // Client's parsed value for that option." - // TODO SWIFT-597: Implement these assertions. Not possible now. + // TODO: SWIFT-597: Implement these assertions. Not possible now. // Note: we also skip this assertion: "You SHOULD verify that the client's initial seed list matches the // list of seeds." mongoc doesn't make this assertion in their test runner either. diff --git a/Tests/MongoSwiftTests/Document+SequenceTests.swift b/Tests/MongoSwiftTests/Document+SequenceTests.swift index 18c772c5b..a45e2da8d 100644 --- a/Tests/MongoSwiftTests/Document+SequenceTests.swift +++ b/Tests/MongoSwiftTests/Document+SequenceTests.swift @@ -132,20 +132,21 @@ final class Document_SequenceTests: MongoSwiftTestCase { func is10(_ pair: Document.KeyValuePair) -> Bool { if let int = pair.value.asInt() { return int == 10 - } + } return false } - func isNot10(_ pair: Document.KeyValuePair) -> Bool { return !is10(pair) } + + func isNot10(_ pair: Document.KeyValuePair) -> Bool { return !self.is10(pair) } func testDropFirst() throws { expect(self.emptyDoc.dropFirst(0)).to(equal([:])) expect(self.emptyDoc.dropFirst(1)).to(equal([:])) - expect(self.smallDoc.dropFirst(0)).to(equal(smallDoc)) + expect(self.smallDoc.dropFirst(0)).to(equal(self.smallDoc)) expect(self.smallDoc.dropFirst()).to(equal([:])) expect(self.smallDoc.dropFirst(2)).to(equal([:])) - expect(self.doc.dropFirst(0)).to(equal(doc)) + expect(self.doc.dropFirst(0)).to(equal(self.doc)) expect(self.doc.dropFirst()).to(equal( [ "b": "hi", @@ -165,11 +166,11 @@ final class Document_SequenceTests: MongoSwiftTestCase { expect(self.emptyDoc.dropLast(0)).to(equal([:])) expect(self.emptyDoc.dropLast(1)).to(equal([:])) - expect(self.smallDoc.dropLast(0)).to(equal(smallDoc)) + expect(self.smallDoc.dropLast(0)).to(equal(self.smallDoc)) expect(self.smallDoc.dropLast()).to(equal([:])) expect(self.smallDoc.dropLast(2)).to(equal([:])) - expect(self.doc.dropLast(0)).to(equal(doc)) + expect(self.doc.dropLast(0)).to(equal(self.doc)) expect(self.doc.dropLast()).to(equal([ "a": 1, "b": "hi", @@ -204,8 +205,8 @@ final class Document_SequenceTests: MongoSwiftTestCase { expect(self.doc.drop(while: self.isNot10)).to(equal(["g": 10])) expect(self.emptyDoc.drop(while: self.is10)).to(equal([:])) - expect(self.smallDoc.drop(while: self.is10)).to(equal(smallDoc)) - expect(self.doc.drop(while: self.is10)).to(equal(doc)) + expect(self.smallDoc.drop(while: self.is10)).to(equal(self.smallDoc)) + expect(self.doc.drop(while: self.is10)).to(equal(self.doc)) } func testPrefixLength() throws { @@ -213,28 +214,28 @@ final class Document_SequenceTests: MongoSwiftTestCase { expect(self.emptyDoc.prefix(1)).to(equal([:])) expect(self.smallDoc.prefix(0)).to(equal([:])) - expect(self.smallDoc.prefix(1)).to(equal(smallDoc)) - expect(self.smallDoc.prefix(2)).to(equal(smallDoc)) + expect(self.smallDoc.prefix(1)).to(equal(self.smallDoc)) + expect(self.smallDoc.prefix(2)).to(equal(self.smallDoc)) expect(self.doc.prefix(0)).to(equal([:])) expect(self.doc.prefix(1)).to(equal(["a": 1])) expect(self.doc.prefix(2)).to(equal(["a": 1, "b": "hi"])) expect(self.doc.prefix(4)).to(equal(["a": 1, "b": "hi", "c": [1, 2], "d": false])) - expect(self.doc.prefix(7)).to(equal(doc)) - expect(self.doc.prefix(8)).to(equal(doc)) + expect(self.doc.prefix(7)).to(equal(self.doc)) + expect(self.doc.prefix(8)).to(equal(self.doc)) } func testPrefixPredicate() throws { expect(self.emptyDoc.prefix(while: self.isInt)).to(equal([:])) - expect(self.smallDoc.prefix(while: self.isInt)).to(equal(smallDoc)) + expect(self.smallDoc.prefix(while: self.isInt)).to(equal(self.smallDoc)) expect(self.doc.prefix(while: self.isInt)).to(equal(["a": 1])) expect(self.emptyDoc.prefix(while: self.isNotNil)).to(equal([:])) - expect(self.smallDoc.prefix(while: self.isNotNil)).to(equal(smallDoc)) + expect(self.smallDoc.prefix(while: self.isNotNil)).to(equal(self.smallDoc)) expect(self.doc.prefix(while: self.isNotNil)).to(equal(["a": 1, "b": "hi", "c": [1, 2], "d": false])) expect(self.emptyDoc.prefix(while: self.isNot10)).to(equal([:])) - expect(self.smallDoc.prefix(while: self.isNot10)).to(equal(smallDoc)) + expect(self.smallDoc.prefix(while: self.isNot10)).to(equal(self.smallDoc)) expect(self.doc.prefix(while: self.isNot10)).to(equal( [ "a": 1, @@ -257,16 +258,16 @@ final class Document_SequenceTests: MongoSwiftTestCase { expect(self.emptyDoc.suffix(5)).to(equal([:])) expect(self.smallDoc.suffix(0)).to(equal([:])) - expect(self.smallDoc.suffix(1)).to(equal(smallDoc)) - expect(self.smallDoc.suffix(2)).to(equal(smallDoc)) - expect(self.smallDoc.suffix(5)).to(equal(smallDoc)) + expect(self.smallDoc.suffix(1)).to(equal(self.smallDoc)) + expect(self.smallDoc.suffix(2)).to(equal(self.smallDoc)) + expect(self.smallDoc.suffix(5)).to(equal(self.smallDoc)) expect(self.doc.suffix(0)).to(equal([])) expect(self.doc.suffix(1)).to(equal(["g": 10])) expect(self.doc.suffix(2)).to(equal(["f": .minKey, "g": 10])) expect(self.doc.suffix(4)).to(equal(["d": false, "e": .null, "f": .minKey, "g": 10])) - expect(self.doc.suffix(7)).to(equal(doc)) - expect(self.doc.suffix(8)).to(equal(doc)) + expect(self.doc.suffix(7)).to(equal(self.doc)) + expect(self.doc.suffix(8)).to(equal(self.doc)) } func testSplit() throws { @@ -295,7 +296,7 @@ final class Document_SequenceTests: MongoSwiftTestCase { )) expect(self.doc.split(maxSplits: 1, omittingEmptySubsequences: false, whereSeparator: self.isInt)) - .to(equal([[:], ["b": "hi", "c": [1, 2], "d": false, "e": .null, "f": .minKey, "g": 10]])) + .to(equal([[:], ["b": "hi", "c": [1, 2], "d": false, "e": .null, "f": .minKey, "g": 10]])) } func testIsEmpty() throws { diff --git a/Tests/MongoSwiftTests/DocumentTests.swift b/Tests/MongoSwiftTests/DocumentTests.swift index f130b5e37..f3b2bc7b6 100644 --- a/Tests/MongoSwiftTests/DocumentTests.swift +++ b/Tests/MongoSwiftTests/DocumentTests.swift @@ -120,9 +120,9 @@ final class DocumentTests: MongoSwiftTestCase { // UUIDs must have 16 bytes expect(try Binary(data: testData, subtype: .uuidDeprecated)) - .to(throwError(UserError.invalidArgumentError(message: ""))) + .to(throwError(UserError.invalidArgumentError(message: ""))) expect(try Binary(data: testData, subtype: .uuid)) - .to(throwError(UserError.invalidArgumentError(message: ""))) + .to(throwError(UserError.invalidArgumentError(message: ""))) let expectedKeys = [ "string", "true", "false", "int", "int32", "int64", "double", "decimal128", @@ -211,8 +211,8 @@ final class DocumentTests: MongoSwiftTestCase { let regex = DocumentTests.testDoc.regex?.regexValue expect(regex).to(equal(RegularExpression(pattern: "^abc", options: "imx"))) expect(try NSRegularExpression(from: regex!)).to(equal(try NSRegularExpression( - pattern: "^abc", - options: NSRegularExpression.optionsFromString("imx") + pattern: "^abc", + options: NSRegularExpression.optionsFromString("imx") ))) let nestedArray = DocumentTests.testDoc.nestedarray?.arrayValue?.compactMap { @@ -244,25 +244,25 @@ final class DocumentTests: MongoSwiftTestCase { } func testDocumentFromArray() { - let doc1: Document = ["foo", .minKey, .null] + let doc1: Document = ["foo", .minKey, .null] - expect(doc1.keys).to(equal(["0", "1", "2"])) - expect(doc1["0"]).to(equal("foo")) - expect(doc1["1"]).to(equal(.minKey)) - expect(doc1["2"]).to(equal(.null)) + expect(doc1.keys).to(equal(["0", "1", "2"])) + expect(doc1["0"]).to(equal("foo")) + expect(doc1["1"]).to(equal(.minKey)) + expect(doc1["2"]).to(equal(.null)) - let elements: [BSON] = ["foo", .minKey, .null] - let doc2 = Document(elements) + let elements: [BSON] = ["foo", .minKey, .null] + let doc2 = Document(elements) - expect(doc2.keys).to(equal(["0", "1", "2"])) - expect(doc2["0"]).to(equal("foo")) - expect(doc2["1"]).to(equal(.minKey)) - expect(doc2["2"]).to(equal(.null)) + expect(doc2.keys).to(equal(["0", "1", "2"])) + expect(doc2["0"]).to(equal("foo")) + expect(doc2["1"]).to(equal(.minKey)) + expect(doc2["2"]).to(equal(.null)) } func testEquatable() { expect(["hi": true, "hello": "hi", "cat": 2] as Document) - .to(equal(["hi": true, "hello": "hi", "cat": 2] as Document)) + .to(equal(["hi": true, "hello": "hi", "cat": 2] as Document)) } func testRawBSON() throws { @@ -382,7 +382,7 @@ final class DocumentTests: MongoSwiftTestCase { // native_to_relaxed_extended_json( bson_to_native(cB) ) = rEJ (if rEJ exists) if let rEJ = validCase["relaxed_extjson"] as? String { - expect(try Document(fromBSON: cBData).extendedJSON).to(cleanEqual(rEJ)) + expect(try Document(fromBSON: cBData).extendedJSON).to(cleanEqual(rEJ)) } // for cEJ input: @@ -646,7 +646,7 @@ final class DocumentTests: MongoSwiftTestCase { } expect(nonOverwritableDoc).to( - equal(["string": .null, "nil": .null, "doc": .null, "arr": .null])) + equal(["string": .null, "nil": .null, "doc": .null, "arr": .null])) } // Test types where replacing them with an instance of their own type is a no-op @@ -835,7 +835,7 @@ final class DocumentTests: MongoSwiftTestCase { dateFormatter.timeStyle = .none let noSecondsDate = DateWrapper(date: dateFormatter.date(from: "1/2/19")!) - encoder.dateEncodingStrategy = .custom({d, e in + encoder.dateEncodingStrategy = .custom({ d, e in var container = e.unkeyedContainer() try dateFormatter.string(from: d).split(separator: "/").forEach { component in try container.encode(String(component)) @@ -852,7 +852,7 @@ final class DocumentTests: MongoSwiftTestCase { case month, day, year } - encoder.dateEncodingStrategy = .custom({d, e in + encoder.dateEncodingStrategy = .custom({ d, e in var container = e.container(keyedBy: DateKeys.self) let components = dateFormatter.string(from: d).split(separator: "/").map { String($0) } try container.encode(components[0], forKey: .month) @@ -920,7 +920,7 @@ final class DocumentTests: MongoSwiftTestCase { expect(isoStruct.date).to(equal(date)) expect(try decoder.decode(DateWrapper.self, from: formatted)).to(throwError(CodecTests.dataCorruptedErr)) expect(try decoder.decode(DateWrapper.self, from: badlyFormatted)) - .to(throwError(CodecTests.dataCorruptedErr)) + .to(throwError(CodecTests.dataCorruptedErr)) } decoder.dateDecodingStrategy = .custom({ decode in try Date(from: decode) }) @@ -975,13 +975,13 @@ final class DocumentTests: MongoSwiftTestCase { let roundTripBase64 = try decoder.decode(DataWrapper.self, from: base64Doc) expect(roundTripBase64.data).to(equal(data)) expect(try decoder.decode(DataWrapper.self, from: ["data": "this is not base64 encoded~"])) - .to(throwError(CodecTests.dataCorruptedErr)) + .to(throwError(CodecTests.dataCorruptedErr)) let customEncodedDoc: Document = [ "d": .string(data.base64EncodedString()), "hash": .int64(Int64(data.hashValue)) ] - encoder.dataEncodingStrategy = .custom({ d, encoder in + encoder.dataEncodingStrategy = .custom({ _, encoder in var container = encoder.singleValueContainer() try container.encode(customEncodedDoc) }) diff --git a/Tests/MongoSwiftTests/MongoClientTests.swift b/Tests/MongoSwiftTests/MongoClientTests.swift index ba3ecab1a..124e80e0d 100644 --- a/Tests/MongoSwiftTests/MongoClientTests.swift +++ b/Tests/MongoSwiftTests/MongoClientTests.swift @@ -68,8 +68,8 @@ final class MongoClientTests: MongoSwiftTestCase { let client = SyncMongoClient(stealing: client_t) let db = client.db(type(of: self).testDatabase) let coll = db.collection(self.getCollectionName()) - let insertResult = try coll.insertOne([ "test": 42 ]) - let findResult = try coll.find([ "_id": insertResult!.insertedId ]) + let insertResult = try coll.insertOne(["test": 42]) + let findResult = try coll.find(["_id": insertResult!.insertedId]) let docs = Array(findResult) expect(docs[0]["test"]).to(equal(42)) try db.drop() @@ -174,9 +174,9 @@ final class MongoClientTests: MongoSwiftTestCase { // Customize strategies on the client let custom = ClientOptions( - dataCodingStrategy: .base64, - dateCodingStrategy: .secondsSince1970, - uuidCodingStrategy: .deferredToUUID + dataCodingStrategy: .base64, + dateCodingStrategy: .secondsSince1970, + uuidCodingStrategy: .deferredToUUID ) let clientCustom = try SyncMongoClient.makeTestClient(options: custom) let collClient = clientCustom.db(defaultDb.name).collection(collDoc.name, withType: Wrapper.self) @@ -194,9 +194,9 @@ final class MongoClientTests: MongoSwiftTestCase { // Construct db with differing strategies from client let dbOpts = DatabaseOptions( - dataCodingStrategy: .binary, - dateCodingStrategy: .deferredToDate, - uuidCodingStrategy: .binary + dataCodingStrategy: .binary, + dateCodingStrategy: .deferredToDate, + uuidCodingStrategy: .binary ) let dbCustom = clientCustom.db(defaultDb.name, options: dbOpts) let collDb = dbCustom.collection(collClient.name, withType: Wrapper.self) @@ -214,9 +214,9 @@ final class MongoClientTests: MongoSwiftTestCase { // Construct collection with differing strategies from database let dbCollOpts = CollectionOptions( - dataCodingStrategy: .base64, - dateCodingStrategy: .millisecondsSince1970, - uuidCodingStrategy: .deferredToUUID + dataCodingStrategy: .base64, + dateCodingStrategy: .millisecondsSince1970, + uuidCodingStrategy: .deferredToUUID ) let collCustom = dbCustom.collection(collClient.name, withType: Wrapper.self, options: dbCollOpts) @@ -230,7 +230,7 @@ final class MongoClientTests: MongoSwiftTestCase { expect(doc?["data"]?.stringValue).to(equal(data.base64EncodedString())) expect(try collCustom.find(["_id": customDbCollId]).nextOrError()) - .to(equal(wrapper)) + .to(equal(wrapper)) try defaultDb.drop() } diff --git a/Tests/MongoSwiftTests/MongoCollection+BulkWriteTests.swift b/Tests/MongoSwiftTests/MongoCollection+BulkWriteTests.swift index 907ad9910..418d46dfb 100644 --- a/Tests/MongoSwiftTests/MongoCollection+BulkWriteTests.swift +++ b/Tests/MongoSwiftTests/MongoCollection+BulkWriteTests.swift @@ -10,7 +10,7 @@ final class MongoCollection_BulkWriteTests: MongoSwiftTestCase { override class func setUp() { super.setUp() do { - client = try SyncMongoClient.makeTestClient() + self.client = try SyncMongoClient.makeTestClient() } catch { print("Setup failed: \(error)") } @@ -25,13 +25,13 @@ final class MongoCollection_BulkWriteTests: MongoSwiftTestCase { return XCTFail("Client is not initialized") } - coll = client.db(type(of: self).testDatabase).collection(self.getCollectionName()) + self.coll = client.db(type(of: self).testDatabase).collection(self.getCollectionName()) } /// Teardown a single test - run after each testX function override func tearDown() { do { - try coll.drop() + try self.coll.drop() } catch let ServerError.commandError(code, _, _, _) where code == 26 { // ignore ns not found errors } catch { @@ -42,7 +42,7 @@ final class MongoCollection_BulkWriteTests: MongoSwiftTestCase { /// Teardown the entire suite - run after all tests complete override class func tearDown() { - client = nil + self.client = nil super.tearDown() } @@ -87,28 +87,31 @@ final class MongoCollection_BulkWriteTests: MongoSwiftTestCase { let requests: [WriteModel] = [ .insertOne(["_id": id2]), .insertOne(doc), - .updateOne(filter: ["_id": id3], - update: ["$set": ["asdfasdf": 1]], - options: UpdateModelOptions(upsert: true)) + .updateOne( + filter: ["_id": id3], + update: ["$set": ["asdfasdf": 1]], + options: UpdateModelOptions(upsert: true) + ) ] let expectedResult = BulkWriteResult( - deletedCount: 0, - insertedCount: 1, - insertedIds: [0: id2], - matchedCount: 0, - modifiedCount: 0, - upsertedCount: 1, - upsertedIds: [2: id3] + deletedCount: 0, + insertedCount: 1, + insertedIds: [0: id2], + matchedCount: 0, + modifiedCount: 0, + upsertedCount: 1, + upsertedIds: [2: id3] ) // Expect a duplicate key error (11000) let expectedError = ServerError.bulkWriteError( - writeErrors: [BulkWriteError(code: 11000, codeName: "DuplicateKey", message: "", index: 1)], - writeConcernError: nil, - otherError: nil, - result: expectedResult, - errorLabels: nil) + writeErrors: [BulkWriteError(code: 11000, codeName: "DuplicateKey", message: "", index: 1)], + writeConcernError: nil, + otherError: nil, + result: expectedResult, + errorLabels: nil + ) let options = BulkWriteOptions(ordered: false) @@ -116,17 +119,21 @@ final class MongoCollection_BulkWriteTests: MongoSwiftTestCase { } func testUpdates() throws { - try createFixtures(4) + try self.createFixtures(4) let requests: [WriteModel] = [ .updateOne(filter: ["_id": 2], update: ["$inc": ["x": 1]], options: nil), .updateMany(filter: ["_id": ["$gt": 2]], update: ["$inc": ["x": -1]], options: nil), - .updateOne(filter: ["_id": 5], - update: ["$set": ["x": 55]], - options: UpdateModelOptions(upsert: true)), - .updateOne(filter: ["x": 66], - update: ["$set": ["x": 66]], - options: UpdateModelOptions(upsert: true)), + .updateOne( + filter: ["_id": 5], + update: ["$set": ["x": 55]], + options: UpdateModelOptions(upsert: true) + ), + .updateOne( + filter: ["x": 66], + update: ["$set": ["x": 66]], + options: UpdateModelOptions(upsert: true) + ), .updateMany(filter: ["x": ["$gt": 50]], update: ["$inc": ["x": 1]], options: nil) ] @@ -149,7 +156,7 @@ final class MongoCollection_BulkWriteTests: MongoSwiftTestCase { } func testDeletes() throws { - try createFixtures(4) + try self.createFixtures(4) let requests: [WriteModel] = [ .deleteOne(["_id": 1], options: nil), @@ -166,18 +173,22 @@ final class MongoCollection_BulkWriteTests: MongoSwiftTestCase { } func testMixedOrderedOperations() throws { - try createFixtures(3) + try self.createFixtures(3) let requests: [WriteModel] = [ - .updateOne(filter: ["_id": ["$gt": 1]], - update: ["$inc": ["x": 1]], - options: nil), + .updateOne( + filter: ["_id": ["$gt": 1]], + update: ["$inc": ["x": 1]], + options: nil + ), .updateMany(filter: ["_id": ["$gt": 1]], update: ["$inc": ["x": 1]], options: nil), .insertOne(["_id": 4]), .deleteMany(["x": ["$nin": [24, 34]]], options: nil), - .replaceOne(filter: ["_id": 4], - replacement: ["_id": 4, "x": 44], - options: ReplaceOneModelOptions(upsert: true)) + .replaceOne( + filter: ["_id": 4], + replacement: ["_id": 4, "x": 44], + options: ReplaceOneModelOptions(upsert: true) + ) ] let result: BulkWriteResult! = try self.coll.bulkWrite(requests) diff --git a/Tests/MongoSwiftTests/MongoCollection+IndexTests.swift b/Tests/MongoSwiftTests/MongoCollection+IndexTests.swift index 7d6744ae1..6d8a0ea2d 100644 --- a/Tests/MongoSwiftTests/MongoCollection+IndexTests.swift +++ b/Tests/MongoSwiftTests/MongoCollection+IndexTests.swift @@ -31,8 +31,8 @@ final class MongoCollection_IndexTests: MongoSwiftTestCase { XCTFail("Invalid client") return } - coll = try client.db(type(of: self).testDatabase).createCollection(self.collName) - try coll.insertMany([doc1, doc2]) + self.coll = try client.db(type(of: self).testDatabase).createCollection(self.collName) + try self.coll.insertMany([doc1, doc2]) } catch { XCTFail("Setup failed: \(error)") } @@ -42,7 +42,7 @@ final class MongoCollection_IndexTests: MongoSwiftTestCase { override func tearDown() { super.tearDown() do { - if coll != nil { try coll.drop() } + if self.coll != nil { try self.coll.drop() } } catch { XCTFail("Dropping test collection \(type(of: self).testDatabase).\(self.collName) failed: \(error)") } @@ -72,7 +72,7 @@ final class MongoCollection_IndexTests: MongoSwiftTestCase { } func testIndexOptions() throws { - // TODO SWIFT-539: unskip + // TODO: SWIFT-539: unskip if MongoSwiftTestCase.ssl && MongoSwiftTestCase.isMacOS { print("Skipping test, fails with SSL, see CDRIVER-3318") return @@ -125,7 +125,7 @@ final class MongoCollection_IndexTests: MongoSwiftTestCase { func testCreateIndexesFromModels() throws { let model1 = IndexModel(keys: ["cat": 1]) let model2 = IndexModel(keys: ["cat": -1]) - expect( try self.coll.createIndexes([model1, model2]) ).to(equal(["cat_1", "cat_-1"])) + expect(try self.coll.createIndexes([model1, model2])).to(equal(["cat_1", "cat_-1"])) let indexes = try coll.listIndexes() expect(indexes.next()?.options?.name).to(equal("_id_")) expect(indexes.next()?.options?.name).to(equal("cat_1")) @@ -238,7 +238,7 @@ final class MongoCollection_IndexTests: MongoSwiftTestCase { let model = IndexModel(keys: ["cat": 1]) let wc = try WriteConcern(w: .number(1)) let createIndexOpts = CreateIndexOptions(maxTimeMS: maxTimeMS, writeConcern: wc) - expect( try collection.createIndex(model, options: createIndexOpts)).to(equal("cat_1")) + expect(try collection.createIndex(model, options: createIndexOpts)).to(equal("cat_1")) let dropIndexOpts = DropIndexOptions(maxTimeMS: maxTimeMS, writeConcern: wc) let res = try collection.dropIndex(model, options: dropIndexOpts) @@ -281,8 +281,8 @@ extension IndexOptions: Equatable { lhs.bucketSize == rhs.bucketSize && lhs.partialFilterExpression == rhs.partialFilterExpression && lhs.collation?["locale"] == rhs.collation?["locale"] - // ^ server adds a bunch of extra fields and a version number - // to collations. rather than deal with those, just verify the - // locale matches. + // ^ server adds a bunch of extra fields and a version number + // to collations. rather than deal with those, just verify the + // locale matches. } } diff --git a/Tests/MongoSwiftTests/MongoCollectionTests.swift b/Tests/MongoSwiftTests/MongoCollectionTests.swift index 57a5d9774..e735dc537 100644 --- a/Tests/MongoSwiftTests/MongoCollectionTests.swift +++ b/Tests/MongoSwiftTests/MongoCollectionTests.swift @@ -31,8 +31,8 @@ final class MongoCollectionTests: MongoSwiftTestCase { XCTFail("Invalid client") return } - coll = try client.db(type(of: self).testDatabase).createCollection(self.collName) - try coll.insertMany([doc1, doc2]) + self.coll = try client.db(type(of: self).testDatabase).createCollection(self.collName) + try self.coll.insertMany([doc1, doc2]) } catch { XCTFail("Setup failed: \(error)") } @@ -42,7 +42,7 @@ final class MongoCollectionTests: MongoSwiftTestCase { override func tearDown() { super.tearDown() do { - if coll != nil { try coll.drop() } + if self.coll != nil { try self.coll.drop() } } catch { XCTFail("Dropping test collection \(type(of: self).testDatabase).\(self.collName) failed: \(error)") } @@ -83,9 +83,9 @@ final class MongoCollectionTests: MongoSwiftTestCase { // error code 11000: DuplicateKey let expectedError = ServerError.writeError( - writeError: WriteError(code: 11000, codeName: "DuplicateKey", message: ""), - writeConcernError: nil, - errorLabels: nil + writeError: WriteError(code: 11000, codeName: "DuplicateKey", message: ""), + writeConcernError: nil, + errorLabels: nil ) expect(try self.coll.insertOne(["_id": 1])).to(throwError(expectedError)) @@ -99,9 +99,8 @@ final class MongoCollectionTests: MongoSwiftTestCase { } func testAggregate() throws { - expect( - Array(try self.coll.aggregate([["$project": ["_id": 0, "cat": 1]]]))) - .to(equal([["cat": "dog"], ["cat": "cat"]] as [Document])) + expect(Array(try self.coll.aggregate([["$project": ["_id": 0, "cat": 1]]]))) + .to(equal([["cat": "dog"], ["cat": "cat"]] as [Document])) } func testDrop() throws { @@ -126,7 +125,7 @@ final class MongoCollectionTests: MongoSwiftTestCase { expect(event.command["drop"]).toNot(beNil()) expect(event.command["writeConcern"]).toNot(beNil()) expect(event.command["writeConcern"]?.documentValue) - .to(sortedEqual(try? encoder.encode(expectedWriteConcern))) + .to(sortedEqual(try? encoder.encode(expectedWriteConcern))) } defer { center.removeObserver(observer) } @@ -171,11 +170,12 @@ final class MongoCollectionTests: MongoSwiftTestCase { ] let expectedErrorOrdered = ServerError.bulkWriteError( - writeErrors: expectedErrorsOrdered, - writeConcernError: nil, - otherError: nil, - result: expectedResultOrdered, - errorLabels: nil) + writeErrors: expectedErrorsOrdered, + writeConcernError: nil, + otherError: nil, + result: expectedResultOrdered, + errorLabels: nil + ) expect(try self.coll.insertMany([newDoc1, docId1, newDoc2, docId2])).to(throwError(expectedErrorOrdered)) @@ -185,14 +185,15 @@ final class MongoCollectionTests: MongoSwiftTestCase { ] let expectedResult = BulkWriteResult(insertedCount: 2, insertedIds: [0: newDoc3["_id"]!, 2: newDoc4["_id"]!]) let expectedError = ServerError.bulkWriteError( - writeErrors: expectedErrors, - writeConcernError: nil, - otherError: nil, - result: expectedResult, - errorLabels: nil) + writeErrors: expectedErrors, + writeConcernError: nil, + otherError: nil, + result: expectedResult, + errorLabels: nil + ) expect(try self.coll.insertMany([newDoc3, docId1, newDoc4, docId2], options: InsertManyOptions(ordered: false))) - .to(throwError(expectedError)) + .to(throwError(expectedError)) } func testInsertManyWithEmptyValues() { @@ -240,13 +241,15 @@ final class MongoCollectionTests: MongoSwiftTestCase { func testReplaceOneWithUnacknowledgedWriteConcern() throws { let options = ReplaceOptions(writeConcern: try WriteConcern(w: .number(0))) let replaceOneResult = try coll.replaceOne( - filter: ["_id": 1], replacement: ["apple": "banana"], options: options) + filter: ["_id": 1], replacement: ["apple": "banana"], options: options + ) expect(replaceOneResult).to(beNil()) } func testUpdateOne() throws { let updateOneResult = try coll.updateOne( - filter: ["_id": 2], update: ["$set": ["apple": "banana"]]) + filter: ["_id": 2], update: ["$set": ["apple": "banana"]] + ) expect(updateOneResult?.matchedCount).to(equal(1)) expect(updateOneResult?.modifiedCount).to(equal(1)) } @@ -254,13 +257,15 @@ final class MongoCollectionTests: MongoSwiftTestCase { func testUpdateOneWithUnacknowledgedWriteConcern() throws { let options = UpdateOptions(writeConcern: try WriteConcern(w: .number(0))) let updateOneResult = try coll.updateOne( - filter: ["_id": 2], update: ["$set": ["apple": "banana"]], options: options) + filter: ["_id": 2], update: ["$set": ["apple": "banana"]], options: options + ) expect(updateOneResult).to(beNil()) } func testUpdateMany() throws { let updateManyResult = try coll.updateMany( - filter: [:], update: ["$set": ["apple": "pear"]]) + filter: [:], update: ["$set": ["apple": "pear"]] + ) expect(updateManyResult?.matchedCount).to(equal(2)) expect(updateManyResult?.modifiedCount).to(equal(2)) } @@ -268,7 +273,8 @@ final class MongoCollectionTests: MongoSwiftTestCase { func testUpdateManyWithUnacknowledgedWriteConcern() throws { let options = UpdateOptions(writeConcern: try WriteConcern(w: .number(0))) let updateManyResult = try coll.updateMany( - filter: [:], update: ["$set": ["apple": "pear"]], options: options) + filter: [:], update: ["$set": ["apple": "pear"]], options: options + ) expect(updateManyResult).to(beNil()) } @@ -279,7 +285,7 @@ final class MongoCollectionTests: MongoSwiftTestCase { expect(try self.coll.distinct(fieldName: "abc", filter: [:])).to(beEmpty()) // test a null distinct value - try coll.insertOne(["cat": .null]) + try self.coll.insertOne(["cat": .null]) let distinct2 = try coll.distinct(fieldName: "cat", filter: [:]) expect(distinct2).to(haveCount(3)) // swiftlint:disable trailing_closure @@ -293,10 +299,10 @@ final class MongoCollectionTests: MongoSwiftTestCase { func testCursorIteration() throws { let findResult1 = try coll.find(["cat": "cat"]) - while let _ = try findResult1.nextOrError() { } + while let _ = try findResult1.nextOrError() {} let findResult2 = try coll.find(["cat": "cat"]) - for _ in findResult2 { } + for _ in findResult2 {} expect(findResult2.error).to(beNil()) } @@ -342,19 +348,19 @@ final class MongoCollectionTests: MongoSwiftTestCase { // test mutated cursorType nonTailable.cursorType = .tailable - expect(try encoder.encode(nonTailable)).to(equal(["awaitData": false, "tailable": true ])) + expect(try encoder.encode(nonTailable)).to(equal(["awaitData": false, "tailable": true])) var tailable = FindOptions(cursorType: .tailable) - expect(try encoder.encode(tailable)).to(equal(["awaitData": false, "tailable": true ])) + expect(try encoder.encode(tailable)).to(equal(["awaitData": false, "tailable": true])) tailable.cursorType = .nonTailable - expect(try encoder.encode(tailable)).to(equal(["awaitData": false, "tailable": false ])) + expect(try encoder.encode(tailable)).to(equal(["awaitData": false, "tailable": false])) var tailableAwait = FindOptions(cursorType: .tailableAwait) - expect(try encoder.encode(tailableAwait)).to(equal(["awaitData": true, "tailable": true ])) + expect(try encoder.encode(tailableAwait)).to(equal(["awaitData": true, "tailable": true])) tailableAwait.cursorType = .tailable - expect(try encoder.encode(tailableAwait)).to(equal(["awaitData": false, "tailable": true ])) + expect(try encoder.encode(tailableAwait)).to(equal(["awaitData": false, "tailable": true])) // test nill cursorType tailableAwait.cursorType = nil @@ -364,13 +370,13 @@ final class MongoCollectionTests: MongoSwiftTestCase { expect(try encoder.encode(nilTailable)).to(beNil()) nilTailable.cursorType = .tailable - expect(try encoder.encode(nilTailable)).to(equal(["awaitData": false, "tailable": true ])) + expect(try encoder.encode(nilTailable)).to(equal(["awaitData": false, "tailable": true])) nilTailable.cursorType = nil expect(try encoder.encode(nilTailable)).to(beNil()) nilTailable.cursorType = .tailableAwait - expect(try encoder.encode(nilTailable)).to(equal(["awaitData": true, "tailable": true ])) + expect(try encoder.encode(nilTailable)).to(equal(["awaitData": true, "tailable": true])) } func testEncodeHint() throws { @@ -400,33 +406,39 @@ final class MongoCollectionTests: MongoSwiftTestCase { let invalidOpts1 = FindOneAndDeleteOptions(maxTimeMS: 0) let invalidOpts2 = FindOneAndDeleteOptions(maxTimeMS: -1) expect(try self.coll.findOneAndDelete([:], options: invalidOpts1)) - .to(throwError(UserError.invalidArgumentError(message: ""))) + .to(throwError(UserError.invalidArgumentError(message: ""))) expect(try self.coll.findOneAndDelete([:], options: invalidOpts2)) - .to(throwError(UserError.invalidArgumentError(message: ""))) + .to(throwError(UserError.invalidArgumentError(message: ""))) } func testFindOneAndReplace() throws { // test using maxTimeMS let opts1 = FindOneAndReplaceOptions(maxTimeMS: 100) - let result1 = try self.coll.findOneAndReplace(filter: ["cat": "cat"], - replacement: ["cat": "blah"], - options: opts1) + let result1 = try self.coll.findOneAndReplace( + filter: ["cat": "cat"], + replacement: ["cat": "blah"], + options: opts1 + ) expect(result1).to(equal(self.doc2)) expect(try self.coll.count()).to(equal(2)) // test using bypassDocumentValidation let opts2 = FindOneAndReplaceOptions(bypassDocumentValidation: true) - let result2 = try self.coll.findOneAndReplace(filter: ["cat": "dog"], - replacement: ["cat": "hi"], - options: opts2) + let result2 = try self.coll.findOneAndReplace( + filter: ["cat": "dog"], + replacement: ["cat": "hi"], + options: opts2 + ) expect(result2).to(equal(self.doc1)) expect(try self.coll.count()).to(equal(2)) // test using a write concern let opts3 = FindOneAndReplaceOptions(writeConcern: try WriteConcern(w: .majority)) - let result3 = try self.coll.findOneAndReplace(filter: ["cat": "blah"], - replacement: ["cat": "cat"], - options: opts3) + let result3 = try self.coll.findOneAndReplace( + filter: ["cat": "blah"], + replacement: ["cat": "cat"], + options: opts3 + ) expect(result3).to(equal(["_id": 2, "cat": "blah"])) expect(try self.coll.count()).to(equal(2)) @@ -434,33 +446,39 @@ final class MongoCollectionTests: MongoSwiftTestCase { let invalidOpts1 = FindOneAndReplaceOptions(maxTimeMS: 0) let invalidOpts2 = FindOneAndReplaceOptions(maxTimeMS: -1) expect(try self.coll.findOneAndReplace(filter: [:], replacement: [:], options: invalidOpts1)) - .to(throwError(UserError.invalidArgumentError(message: ""))) + .to(throwError(UserError.invalidArgumentError(message: ""))) expect(try self.coll.findOneAndReplace(filter: [:], replacement: [:], options: invalidOpts2)) - .to(throwError(UserError.invalidArgumentError(message: ""))) + .to(throwError(UserError.invalidArgumentError(message: ""))) } func testFindOneAndUpdate() throws { // test using maxTimeMS let opts1 = FindOneAndUpdateOptions(maxTimeMS: 100) - let result1 = try self.coll.findOneAndUpdate(filter: ["cat": "cat"], - update: ["$set": ["cat": "blah"]], - options: opts1) + let result1 = try self.coll.findOneAndUpdate( + filter: ["cat": "cat"], + update: ["$set": ["cat": "blah"]], + options: opts1 + ) expect(result1).to(equal(self.doc2)) expect(try self.coll.count()).to(equal(2)) // test using bypassDocumentValidation let opts2 = FindOneAndUpdateOptions(bypassDocumentValidation: true) - let result2 = try self.coll.findOneAndUpdate(filter: ["cat": "dog"], - update: ["$set": ["cat": "hi"]], - options: opts2) + let result2 = try self.coll.findOneAndUpdate( + filter: ["cat": "dog"], + update: ["$set": ["cat": "hi"]], + options: opts2 + ) expect(result2).to(equal(self.doc1)) expect(try self.coll.count()).to(equal(2)) // test using a write concern let opts3 = FindOneAndUpdateOptions(writeConcern: try WriteConcern(w: .majority)) - let result3 = try self.coll.findOneAndUpdate(filter: ["cat": "blah"], - update: ["$set": ["cat": "cat"]], - options: opts3) + let result3 = try self.coll.findOneAndUpdate( + filter: ["cat": "blah"], + update: ["$set": ["cat": "cat"]], + options: opts3 + ) expect(result3).to(equal(["_id": 2, "cat": "blah"])) expect(try self.coll.count()).to(equal(2)) @@ -468,9 +486,9 @@ final class MongoCollectionTests: MongoSwiftTestCase { let invalidOpts1 = FindOneAndUpdateOptions(maxTimeMS: 0) let invalidOpts2 = FindOneAndUpdateOptions(maxTimeMS: -1) expect(try self.coll.findOneAndUpdate(filter: [:], update: [:], options: invalidOpts1)) - .to(throwError(UserError.invalidArgumentError(message: ""))) + .to(throwError(UserError.invalidArgumentError(message: ""))) expect(try self.coll.findOneAndUpdate(filter: [:], update: [:], options: invalidOpts2)) - .to(throwError(UserError.invalidArgumentError(message: ""))) + .to(throwError(UserError.invalidArgumentError(message: ""))) } func testNullIds() throws { diff --git a/Tests/MongoSwiftTests/MongoCursorTests.swift b/Tests/MongoSwiftTests/MongoCursorTests.swift index 38e115a0d..b59b9ffb7 100644 --- a/Tests/MongoSwiftTests/MongoCursorTests.swift +++ b/Tests/MongoSwiftTests/MongoCursorTests.swift @@ -45,10 +45,12 @@ final class MongoCursorTests: MongoSwiftTestCase { // run killCursors so next iteration fails on the server try db.runCommand(["killCursors": .string(coll.name), "cursors": [.int64(cursor.id!)]]) - let expectedError2 = ServerError.commandError(code: 43, - codeName: "CursorNotFound", - message: "", - errorLabels: nil) + let expectedError2 = ServerError.commandError( + code: 43, + codeName: "CursorNotFound", + message: "", + errorLabels: nil + ) expect(try cursor.nextOrError()).to(throwError(expectedError2)) // cursor should be closed now that it errored expect(cursor.isAlive).to(beFalse()) @@ -97,10 +99,12 @@ final class MongoCursorTests: MongoSwiftTestCase { try coll.insertOne(["_id": BSON(i), "x": BSON(i)]) } - let expectedError = ServerError.commandError(code: 136, - codeName: "CappedPositionLost", - message: "", - errorLabels: nil) + let expectedError = ServerError.commandError( + code: 136, + codeName: "CappedPositionLost", + message: "", + errorLabels: nil + ) expect(try cursor.nextOrError()).to(throwError(expectedError)) // cursor should be closed now that it errored expect(cursor.isAlive).to(beFalse()) diff --git a/Tests/MongoSwiftTests/MongoDatabaseTests.swift b/Tests/MongoSwiftTests/MongoDatabaseTests.swift index 7e70c1229..d3bd4df5d 100644 --- a/Tests/MongoSwiftTests/MongoDatabaseTests.swift +++ b/Tests/MongoSwiftTests/MongoDatabaseTests.swift @@ -36,10 +36,12 @@ final class MongoDatabaseTests: MongoSwiftTestCase { // error code 59: CommandNotFound expect(try db.runCommand(["asdfsadf": .objectId(ObjectId())])) - .to(throwError(ServerError.commandError(code: 59, - codeName: "CommandNotFound", - message: "", - errorLabels: nil))) + .to(throwError(ServerError.commandError( + code: 59, + codeName: "CommandNotFound", + message: "", + errorLabels: nil + ))) } func testDropDatabase() throws { @@ -53,9 +55,9 @@ final class MongoDatabaseTests: MongoSwiftTestCase { try collection.insertOne(["test": "blahblah"]) var expectedWriteConcerns: [WriteConcern] = [ - try WriteConcern(journal: true, w: .number(1)), - try WriteConcern(journal: true, w: .number(1), wtimeoutMS: 123) - ] + try WriteConcern(journal: true, w: .number(1)), + try WriteConcern(journal: true, w: .number(1), wtimeoutMS: 123) + ] var eventsSeen = 0 let observer = center.addObserver(forName: nil, object: nil, queue: nil) { notif in guard let event = notif.userInfo?["event"] as? CommandStartedEvent else { @@ -77,7 +79,7 @@ final class MongoDatabaseTests: MongoSwiftTestCase { } func testCreateCollection() throws { - // TODO SWIFT-539: unskip + // TODO: SWIFT-539: unskip if MongoSwiftTestCase.ssl && MongoSwiftTestCase.isMacOS { print("Skipping test, fails with SSL, see CDRIVER-3318") return @@ -120,19 +122,23 @@ final class MongoDatabaseTests: MongoSwiftTestCase { let fooInfo = CollectionSpecificationInfo(readOnly: false, uuid: UUID()) let fooIndex = IndexModel(keys: ["_id": 1] as Document, options: IndexOptions(name: "_id_")) - let expectedFoo = CollectionSpecification(name: "foo", - type: .collection, - options: fooOptions, - info: fooInfo, - idIndex: fooIndex) + let expectedFoo = CollectionSpecification( + name: "foo", + type: .collection, + options: fooOptions, + info: fooInfo, + idIndex: fooIndex + ) expect(collectionInfo[0]).to(equal(expectedFoo)) let viewInfo = CollectionSpecificationInfo(readOnly: true, uuid: nil) - let expectedView = CollectionSpecification(name: "fooView", - type: .view, - options: viewOptions, - info: viewInfo, - idIndex: nil) + let expectedView = CollectionSpecification( + name: "fooView", + type: .view, + options: viewOptions, + info: viewInfo, + idIndex: nil + ) expect(collectionInfo[1]).to(equal(expectedView)) expect(collectionInfo[2].name).to(equal("system.views")) @@ -151,9 +157,11 @@ final class MongoDatabaseTests: MongoSwiftTestCase { try db.collection("capped").insertOne(["a": 1]) try db.collection("uncapped").insertOne(["b": 2]) - let listNamesEvent = try captureCommandEvents(from: client, - eventTypes: [.commandStarted], - commandNames: ["listCollections"]) { + let listNamesEvent = try captureCommandEvents( + from: client, + eventTypes: [.commandStarted], + commandNames: ["listCollections"] + ) { var collectionNames = try db.listCollectionNames() collectionNames.sort { $0 < $1 } @@ -188,29 +196,29 @@ extension CreateCollectionOptions: Equatable { // and is not a property of the collection. public static func == (lhs: CreateCollectionOptions, rhs: CreateCollectionOptions) -> Bool { return rhs.capped == lhs.capped && - rhs.autoIndexId == lhs.autoIndexId && - lhs.size == rhs.size && - lhs.max == rhs.max && - lhs.storageEngine == rhs.storageEngine && - lhs.validator == rhs.validator && - lhs.validationLevel == rhs.validationLevel && - lhs.validationAction == rhs.validationAction && - lhs.indexOptionDefaults == rhs.indexOptionDefaults && - lhs.viewOn == rhs.viewOn && - lhs.pipeline == rhs.pipeline && - lhs.collation?["locale"] == rhs.collation?["locale"] - // ^ server adds a bunch of extra fields and a version number - // to collations. rather than deal with those, just verify the - // locale matches. + rhs.autoIndexId == lhs.autoIndexId && + lhs.size == rhs.size && + lhs.max == rhs.max && + lhs.storageEngine == rhs.storageEngine && + lhs.validator == rhs.validator && + lhs.validationLevel == rhs.validationLevel && + lhs.validationAction == rhs.validationAction && + lhs.indexOptionDefaults == rhs.indexOptionDefaults && + lhs.viewOn == rhs.viewOn && + lhs.pipeline == rhs.pipeline && + lhs.collation?["locale"] == rhs.collation?["locale"] + // ^ server adds a bunch of extra fields and a version number + // to collations. rather than deal with those, just verify the + // locale matches. } } extension CollectionSpecification: Equatable { public static func == (lhs: CollectionSpecification, rhs: CollectionSpecification) -> Bool { return lhs.name == rhs.name && - lhs.type == rhs.type && - lhs.options == rhs.options && - lhs.info.readOnly == rhs.info.readOnly && - lhs.idIndex?.options?.name == rhs.idIndex?.options?.name + lhs.type == rhs.type && + lhs.options == rhs.options && + lhs.info.readOnly == rhs.info.readOnly && + lhs.idIndex?.options?.name == rhs.idIndex?.options?.name } } diff --git a/Tests/MongoSwiftTests/MongoError+Equatable.swift b/Tests/MongoSwiftTests/MongoError+Equatable.swift index 0c4bc442d..461f542a2 100644 --- a/Tests/MongoSwiftTests/MongoError+Equatable.swift +++ b/Tests/MongoSwiftTests/MongoError+Equatable.swift @@ -8,8 +8,10 @@ extension RuntimeError: Equatable { (.authenticationError(message: _), .authenticationError(message: _)), (.compatibilityError(message: _), .compatibilityError(message: _)): return true - case let (.connectionError(message: _, errorLabels: lhsLabels), - .connectionError(message: _, errorLabels: rhsLabels)): + case let ( + .connectionError(message: _, errorLabels: lhsLabels), + .connectionError(message: _, errorLabels: rhsLabels) + ): return sortAndCompareOptionalArrays(lhs: lhsLabels, rhs: rhsLabels, cmp: { $0 < $1 }) default: return false @@ -20,32 +22,42 @@ extension RuntimeError: Equatable { extension ServerError: Equatable { public static func == (lhs: ServerError, rhs: ServerError) -> Bool { switch (lhs, rhs) { - case let (.commandError(code: lhsCode, codeName: _, message: _, errorLabels: lhsErrorLabels), - .commandError(code: rhsCode, codeName: _, message: _, errorLabels: rhsErrorLabels)): + case let ( + .commandError(code: lhsCode, codeName: _, message: _, errorLabels: lhsErrorLabels), + .commandError(code: rhsCode, codeName: _, message: _, errorLabels: rhsErrorLabels) + ): return lhsCode == rhsCode - && sortAndCompareOptionalArrays(lhs: lhsErrorLabels, rhs: rhsErrorLabels, cmp: { $0 < $1 }) - case let (.writeError(writeError: lhsWriteError, writeConcernError: lhsWCError, errorLabels: lhsErrorLabels), - .writeError(writeError: rhsWriteError, writeConcernError: rhsWCError, errorLabels: rhsErrorLabels)): + && sortAndCompareOptionalArrays(lhs: lhsErrorLabels, rhs: rhsErrorLabels, cmp: { $0 < $1 }) + case let ( + .writeError(writeError: lhsWriteError, writeConcernError: lhsWCError, errorLabels: lhsErrorLabels), + .writeError(writeError: rhsWriteError, writeConcernError: rhsWCError, errorLabels: rhsErrorLabels) + ): return lhsWriteError == rhsWriteError - && lhsWCError == rhsWCError - && sortAndCompareOptionalArrays(lhs: lhsErrorLabels, rhs: rhsErrorLabels, cmp: { $0 < $1 }) - case let (.bulkWriteError(writeErrors: lhsWriteErrors, - writeConcernError: lhsWCError, - otherError: lhsOther, - result: lhsResult, - errorLabels: lhsErrorLabels), - .bulkWriteError(writeErrors: rhsWriteErrors, - writeConcernError: rhsWCError, - otherError: rhsOther, - result: rhsResult, - errorLabels: rhsErrorLabels)): + && lhsWCError == rhsWCError + && sortAndCompareOptionalArrays(lhs: lhsErrorLabels, rhs: rhsErrorLabels, cmp: { $0 < $1 }) + case let ( + .bulkWriteError( + writeErrors: lhsWriteErrors, + writeConcernError: lhsWCError, + otherError: lhsOther, + result: lhsResult, + errorLabels: lhsErrorLabels + ), + .bulkWriteError( + writeErrors: rhsWriteErrors, + writeConcernError: rhsWCError, + otherError: rhsOther, + result: rhsResult, + errorLabels: rhsErrorLabels + ) + ): let cmp = { (l: BulkWriteError, r: BulkWriteError) in l.index < r.index } return sortAndCompareOptionalArrays(lhs: lhsWriteErrors, rhs: rhsWriteErrors, cmp: cmp) - && lhsWCError == rhsWCError - && sortAndCompareOptionalArrays(lhs: lhsErrorLabels, rhs: rhsErrorLabels, cmp: { $0 < $1 }) - && lhsResult == rhsResult - && lhsOther?.localizedDescription == rhsOther?.localizedDescription + && lhsWCError == rhsWCError + && sortAndCompareOptionalArrays(lhs: lhsErrorLabels, rhs: rhsErrorLabels, cmp: { $0 < $1 }) + && lhsResult == rhsResult + && lhsOther?.localizedDescription == rhsOther?.localizedDescription default: return false } @@ -55,11 +67,11 @@ extension ServerError: Equatable { extension BulkWriteResult: Equatable { public static func == (lhs: BulkWriteResult, rhs: BulkWriteResult) -> Bool { return lhs.insertedIds == rhs.insertedIds - && lhs.upsertedIds == rhs.upsertedIds - && lhs.upsertedCount == rhs.upsertedCount - && lhs.modifiedCount == rhs.modifiedCount - && lhs.matchedCount == rhs.matchedCount - && lhs.insertedCount == rhs.insertedCount + && lhs.upsertedIds == rhs.upsertedIds + && lhs.upsertedCount == rhs.upsertedCount + && lhs.modifiedCount == rhs.modifiedCount + && lhs.matchedCount == rhs.matchedCount + && lhs.insertedCount == rhs.insertedCount } } @@ -94,7 +106,7 @@ extension WriteConcernError: Equatable { } /// Private function for sorting, then comparing two optional arrays. -/// TODO: remove this function and just use optional chaining once we drop Swift 4.0 support (SWIFT-283) +// TODO: remove this function and just use optional chaining once we drop Swift 4.0 support (SWIFT-283) private func sortAndCompareOptionalArrays(lhs: [T]?, rhs: [T]?, cmp: (T, T) -> Bool) -> Bool { guard let lhsArr = lhs, let rhsArr = rhs else { return lhs == nil && rhs == nil diff --git a/Tests/MongoSwiftTests/OptionsTests.swift b/Tests/MongoSwiftTests/OptionsTests.swift index 0c8752a9b..906db2ea7 100644 --- a/Tests/MongoSwiftTests/OptionsTests.swift +++ b/Tests/MongoSwiftTests/OptionsTests.swift @@ -39,7 +39,7 @@ final class OptionsTests: MongoSwiftTestCase { // This will be useful with Swift 5.1 auto-generated initializers func testOptionsAlphabeticalOrder() throws { - for options in allOptionsStructs { + for options in self.allOptionsStructs { let mirror = Mirror(reflecting: options) let labels = mirror.children.map { $0.label! } expect(labels.sorted()).to(equal(labels), description: "\(type(of: options))") diff --git a/Tests/MongoSwiftTests/ReadPreferenceTests.swift b/Tests/MongoSwiftTests/ReadPreferenceTests.swift index 50f82b6d0..e96da94f9 100644 --- a/Tests/MongoSwiftTests/ReadPreferenceTests.swift +++ b/Tests/MongoSwiftTests/ReadPreferenceTests.swift @@ -39,7 +39,7 @@ final class ReadPreferenceTests: MongoSwiftTestCase { // Non-empty tag sets cannot be combined with primary mode expect(try ReadPreference(.primary, tagSets: [["dc": "east"], []])) - .to(throwError(UserError.invalidArgumentError(message: ""))) + .to(throwError(UserError.invalidArgumentError(message: ""))) expect(try ReadPreference(.primary, tagSets: [[]])).to(throwError(UserError.invalidArgumentError(message: ""))) } @@ -50,16 +50,16 @@ final class ReadPreferenceTests: MongoSwiftTestCase { let rpMinMaxStaleness = try ReadPreference(.nearest, maxStalenessSeconds: 90) expect(rpMinMaxStaleness.maxStalenessSeconds).to(equal(90)) - let rpLargeMaxStaleness = try ReadPreference(.nearest, maxStalenessSeconds: 2147483647) - expect(rpLargeMaxStaleness.maxStalenessSeconds).to(equal(2147483647)) + let rpLargeMaxStaleness = try ReadPreference(.nearest, maxStalenessSeconds: 2_147_483_647) + expect(rpLargeMaxStaleness.maxStalenessSeconds).to(equal(2_147_483_647)) // maxStalenessSeconds cannot be less than 90 expect(try ReadPreference(.nearest, maxStalenessSeconds: -1)) - .to(throwError(UserError.invalidArgumentError(message: ""))) + .to(throwError(UserError.invalidArgumentError(message: ""))) expect(try ReadPreference(.nearest, maxStalenessSeconds: 0)) - .to(throwError(UserError.invalidArgumentError(message: ""))) + .to(throwError(UserError.invalidArgumentError(message: ""))) expect(try ReadPreference(.nearest, maxStalenessSeconds: 89)) - .to(throwError(UserError.invalidArgumentError(message: ""))) + .to(throwError(UserError.invalidArgumentError(message: ""))) } func testInitFromPointer() { @@ -110,16 +110,20 @@ final class ReadPreferenceTests: MongoSwiftTestCase { // expect running other commands to not throw errors when passing in a valid read preference expect(try coll.find(options: FindOptions(readPreference: ReadPreference(.primary)))).toNot(throwError()) - expect(try coll.aggregate([["$project": ["a": 1]]], - options: AggregateOptions(readPreference: ReadPreference(.secondaryPreferred)))) - .toNot(throwError()) + expect(try coll.aggregate( + [["$project": ["a": 1]]], + options: AggregateOptions(readPreference: ReadPreference(.secondaryPreferred)) + )) + .toNot(throwError()) expect(try coll.count(options: CountOptions(readPreference: ReadPreference(.secondaryPreferred)))) - .toNot(throwError()) + .toNot(throwError()) - expect(try coll.distinct(fieldName: "a", - options: DistinctOptions(readPreference: ReadPreference(.secondaryPreferred)))) - .toNot(throwError()) + expect(try coll.distinct( + fieldName: "a", + options: DistinctOptions(readPreference: ReadPreference(.secondaryPreferred)) + )) + .toNot(throwError()) } func testClientReadPreference() throws { @@ -166,13 +170,15 @@ final class ReadPreferenceTests: MongoSwiftTestCase { let db = client.db(type(of: self).testDatabase) expect(db.readPreference).to(equal(ReadPreference(.primary))) - // expect that a collection inherits its database default read preference + // expect that a collection inherits its database default read preference let coll1 = db.collection(self.getCollectionName(suffix: "1")) expect(coll1.readPreference).to(equal(ReadPreference(.primary))) // expect that a collection can override its inherited read preference - let coll2 = db.collection(self.getCollectionName(suffix: "2"), - options: CollectionOptions(readPreference: secondary)) + let coll2 = db.collection( + self.getCollectionName(suffix: "2"), + options: CollectionOptions(readPreference: secondary) + ) expect(coll2.readPreference).to(equal(ReadPreference(.secondary))) } @@ -183,8 +189,10 @@ final class ReadPreferenceTests: MongoSwiftTestCase { expect(coll1.readPreference).to(equal(ReadPreference(.secondary))) // expect that a collection can override its database read preference - let coll2 = db.collection(self.getCollectionName(suffix: "2"), - options: CollectionOptions(readPreference: primary)) + let coll2 = db.collection( + self.getCollectionName(suffix: "2"), + options: CollectionOptions(readPreference: primary) + ) expect(coll2.readPreference).to(equal(ReadPreference(.primary))) } } diff --git a/Tests/MongoSwiftTests/ReadWriteConcernTests.swift b/Tests/MongoSwiftTests/ReadWriteConcernTests.swift index e53648866..e0a38019e 100644 --- a/Tests/MongoSwiftTests/ReadWriteConcernTests.swift +++ b/Tests/MongoSwiftTests/ReadWriteConcernTests.swift @@ -34,7 +34,7 @@ protocol ReadConcernable { /// corresponding mongoc type. protocol WriteConcernable { var writeConcern: WriteConcern? { get } - func getMongocWriteConcern() throws -> WriteConcern? + func getMongocWriteConcern() throws -> WriteConcern? } extension SyncMongoClient: ReadConcernable, WriteConcernable { @@ -43,6 +43,7 @@ extension SyncMongoClient: ReadConcernable, WriteConcernable { ReadConcern(from: mongoc_client_get_read_concern(conn.clientHandle)) } } + func getMongocWriteConcern() throws -> WriteConcern? { return try self.connectionPool.withConnection { conn in WriteConcern(from: mongoc_client_get_write_concern(conn.clientHandle)) @@ -51,13 +52,14 @@ extension SyncMongoClient: ReadConcernable, WriteConcernable { } extension SyncMongoDatabase: ReadConcernable, WriteConcernable { - func getMongocReadConcern() throws -> ReadConcern? { + func getMongocReadConcern() throws -> ReadConcern? { return try self._client.connectionPool.withConnection { conn in self.withMongocDatabase(from: conn) { dbPtr in ReadConcern(from: mongoc_database_get_read_concern(dbPtr)) } } } + func getMongocWriteConcern() throws -> WriteConcern? { return try self._client.connectionPool.withConnection { conn in self.withMongocDatabase(from: conn) { dbPtr in @@ -75,7 +77,8 @@ extension SyncMongoCollection: ReadConcernable, WriteConcernable { } } } - func getMongocWriteConcern() throws -> WriteConcern? { + + func getMongocWriteConcern() throws -> WriteConcern? { return try self._client.connectionPool.withConnection { conn in self.withMongocCollection(from: conn) { collPtr in WriteConcern(from: mongoc_collection_get_write_concern(collPtr)) @@ -123,19 +126,21 @@ final class ReadWriteConcernTests: MongoSwiftTestCase { // verify that this combination is considered invalid expect(try WriteConcern(journal: true, w: .number(0))) - .to(throwError(UserError.invalidArgumentError(message: ""))) + .to(throwError(UserError.invalidArgumentError(message: ""))) // verify that a negative value for w or for wtimeoutMS is considered invalid expect(try WriteConcern(w: .number(-1))) - .to(throwError(UserError.invalidArgumentError(message: ""))) + .to(throwError(UserError.invalidArgumentError(message: ""))) expect(try WriteConcern(wtimeoutMS: -1)) - .to(throwError(UserError.invalidArgumentError(message: ""))) + .to(throwError(UserError.invalidArgumentError(message: ""))) } /// Checks that a type T, as well as pointers to corresponding libmongoc instances, has the expected read concern. - func checkReadConcern(_ instance: T, - _ expected: ReadConcern, - _ description: String) throws { + func checkReadConcern( + _ instance: T, + _ expected: ReadConcern, + _ description: String + ) throws { if expected.isDefault { expect(instance.readConcern).to(beNil(), description: description) } else { @@ -146,9 +151,11 @@ final class ReadWriteConcernTests: MongoSwiftTestCase { } /// Checks that a type T, as well as pointers to corresponding libmongoc instances, has the expected write concern. - func checkWriteConcern(_ instance: T, - _ expected: WriteConcern, - _ description: String) throws { + func checkWriteConcern( + _ instance: T, + _ expected: WriteConcern, + _ description: String + ) throws { if expected.isDefault { expect(instance.writeConcern).to(beNil(), description: description) } else { @@ -173,11 +180,11 @@ final class ReadWriteConcernTests: MongoSwiftTestCase { // expect that a DB created from this client inherits its unset RC let db1 = client.db(type(of: self).testDatabase) - try checkReadConcern(db1, empty, "db created with no RC provided from \(clientDesc)") + try self.checkReadConcern(db1, empty, "db created with no RC provided from \(clientDesc)") // expect that a DB created from this client can override the client's unset RC let db2 = client.db(type(of: self).testDatabase, options: DatabaseOptions(readConcern: majority)) - try checkReadConcern(db2, majority, "db created with majority RC from \(clientDesc)") + try self.checkReadConcern(db2, majority, "db created with majority RC from \(clientDesc)") } // test behavior of a client initialized with local RC @@ -189,20 +196,20 @@ final class ReadWriteConcernTests: MongoSwiftTestCase { // expect that a DB created from this client inherits its local RC let db1 = client.db(type(of: self).testDatabase) - try checkReadConcern(db1, local, "db created with no RC provided from \(clientDesc)") + try self.checkReadConcern(db1, local, "db created with no RC provided from \(clientDesc)") // expect that a DB created from this client can override the client's local RC let db2 = client.db(type(of: self).testDatabase, options: DatabaseOptions(readConcern: majority)) - try checkReadConcern(db2, majority, "db created with majority RC from \(clientDesc)") + try self.checkReadConcern(db2, majority, "db created with majority RC from \(clientDesc)") // test with string init let db3 = client.db(type(of: self).testDatabase, options: DatabaseOptions(readConcern: majorityString)) - try checkReadConcern(db3, majority, "db created with majority string RC from \(clientDesc)") + try self.checkReadConcern(db3, majority, "db created with majority string RC from \(clientDesc)") // test with unknown level let unknown = ReadConcern("blah") let db4 = client.db(type(of: self).testDatabase, options: DatabaseOptions(readConcern: unknown)) - try checkReadConcern(db4, unknown, "db created with unknown RC from \(clientDesc)") + try self.checkReadConcern(db4, unknown, "db created with unknown RC from \(clientDesc)") } // test behavior of a client initialized with majority RC @@ -217,7 +224,7 @@ final class ReadWriteConcernTests: MongoSwiftTestCase { // expect that a DB created from this client can override the client's majority RC with an unset one let db = client.db(type(of: self).testDatabase, options: DatabaseOptions(readConcern: empty)) - try checkReadConcern(db, empty, "db created with empty RC from \(clientDesc) string") + try self.checkReadConcern(db, empty, "db created with empty RC from \(clientDesc) string") } } @@ -235,11 +242,11 @@ final class ReadWriteConcernTests: MongoSwiftTestCase { // expect that a DB created from this client inherits its default WC let db1 = client.db(type(of: self).testDatabase) - try checkWriteConcern(db1, empty, "db created with no WC provided from \(clientDesc)") + try self.checkWriteConcern(db1, empty, "db created with no WC provided from \(clientDesc)") // expect that a DB created from this client can override the client's default WC let db2 = client.db(type(of: self).testDatabase, options: DatabaseOptions(writeConcern: w2)) - try checkWriteConcern(db2, w2, "db created with w:2 from \(clientDesc)") + try self.checkWriteConcern(db2, w2, "db created with w:2 from \(clientDesc)") } // test behavior of a client with w: 1 @@ -251,11 +258,11 @@ final class ReadWriteConcernTests: MongoSwiftTestCase { // expect that a DB created from this client inherits its WC let db1 = client.db(type(of: self).testDatabase) - try checkWriteConcern(db1, w1, "db created with no WC provided from \(clientDesc)") + try self.checkWriteConcern(db1, w1, "db created with no WC provided from \(clientDesc)") // expect that a DB created from this client can override the client's WC let db2 = client.db(type(of: self).testDatabase, options: DatabaseOptions(writeConcern: w2)) - try checkWriteConcern(db2, w2, "db created with w:2 from \(clientDesc)") + try self.checkWriteConcern(db2, w2, "db created with w:2 from \(clientDesc)") } // test behavior of a client with w: 2 @@ -266,9 +273,10 @@ final class ReadWriteConcernTests: MongoSwiftTestCase { // expect that a DB created from this client can override the client's WC with an unset one let db = client.db( - type(of: self).testDatabase, - options: DatabaseOptions(writeConcern: empty)) - try checkWriteConcern(db, empty, "db created with empty WC from \(clientDesc)") + type(of: self).testDatabase, + options: DatabaseOptions(writeConcern: empty) + ) + try self.checkWriteConcern(db, empty, "db created with empty WC from \(clientDesc)") } } @@ -288,49 +296,50 @@ final class ReadWriteConcernTests: MongoSwiftTestCase { let coll1Name = self.getCollectionName(suffix: "1") // expect that a collection created from a DB with unset RC also has unset RC var coll1 = try db1.createCollection(coll1Name) - try checkReadConcern(coll1, empty, "collection created with no RC provided from \(dbDesc)") + try self.checkReadConcern(coll1, empty, "collection created with no RC provided from \(dbDesc)") // expect that a collection retrieved from a DB with unset RC also has unset RC coll1 = db1.collection(coll1Name) - try checkReadConcern(coll1, empty, "collection retrieved with no RC provided from \(dbDesc)") + try self.checkReadConcern(coll1, empty, "collection retrieved with no RC provided from \(dbDesc)") // expect that a collection retrieved from a DB with unset RC can override the DB's RC let coll2 = db1.collection(self.getCollectionName(suffix: "2"), options: CollectionOptions(readConcern: local)) - try checkReadConcern(coll2, local, "collection retrieved with local RC from \(dbDesc)") + try self.checkReadConcern(coll2, local, "collection retrieved with local RC from \(dbDesc)") // test with string init var coll3 = db1.collection( - self.getCollectionName(suffix: "3"), - options: CollectionOptions(readConcern: localString) + self.getCollectionName(suffix: "3"), + options: CollectionOptions(readConcern: localString) ) - try checkReadConcern(coll3, local, "collection created with local RC string from \(dbDesc)") + try self.checkReadConcern(coll3, local, "collection created with local RC string from \(dbDesc)") // test with unknown level coll3 = db1.collection(self.getCollectionName(suffix: "3"), options: CollectionOptions(readConcern: unknown)) - try checkReadConcern(coll3, unknown, "collection retrieved with unknown RC level from \(dbDesc)") + try self.checkReadConcern(coll3, unknown, "collection retrieved with unknown RC level from \(dbDesc)") try db1.drop() let db2 = client.db( - type(of: self).testDatabase, - options: DatabaseOptions(readConcern: local)) + type(of: self).testDatabase, + options: DatabaseOptions(readConcern: local) + ) defer { try? db2.drop() } let coll4Name = self.getCollectionName(suffix: "4") // expect that a collection created from a DB with local RC also has local RC var coll4 = try db2.createCollection(coll4Name) - try checkReadConcern(coll4, local, "collection created with no RC provided from \(dbDesc)") + try self.checkReadConcern(coll4, local, "collection created with no RC provided from \(dbDesc)") // expect that a collection retrieved from a DB with local RC also has local RC coll4 = db2.collection(coll4Name) - try checkReadConcern(coll4, local, "collection retrieved with no RC provided from \(dbDesc)") + try self.checkReadConcern(coll4, local, "collection retrieved with no RC provided from \(dbDesc)") // expect that a collection retrieved from a DB with local RC can override the DB's RC let coll5 = db2.collection( - self.getCollectionName(suffix: "5"), - options: CollectionOptions(readConcern: majority) + self.getCollectionName(suffix: "5"), + options: CollectionOptions(readConcern: majority) ) - try checkReadConcern(coll5, majority, "collection retrieved with majority RC from \(dbDesc)") + try self.checkReadConcern(coll5, majority, "collection retrieved with majority RC from \(dbDesc)") } func testDatabaseWriteConcern() throws { @@ -347,15 +356,15 @@ final class ReadWriteConcernTests: MongoSwiftTestCase { // expect that a collection created from a DB with default WC also has default WC var coll1 = try db1.createCollection(self.getCollectionName(suffix: "1")) - try checkWriteConcern(coll1, empty, "collection created with no WC provided from \(dbDesc)") + try self.checkWriteConcern(coll1, empty, "collection created with no WC provided from \(dbDesc)") // expect that a collection retrieved from a DB with default WC also has default WC coll1 = db1.collection(coll1.name) - try checkWriteConcern(coll1, empty, "collection retrieved with no WC provided from \(dbDesc)") + try self.checkWriteConcern(coll1, empty, "collection retrieved with no WC provided from \(dbDesc)") // expect that a collection retrieved from a DB with default WC can override the DB's WC var coll2 = db1.collection(self.getCollectionName(suffix: "2"), options: CollectionOptions(writeConcern: w1)) - try checkWriteConcern(coll2, w1, "collection retrieved with w:1 from \(dbDesc)") + try self.checkWriteConcern(coll2, w1, "collection retrieved with w:1 from \(dbDesc)") try db1.drop() @@ -365,15 +374,15 @@ final class ReadWriteConcernTests: MongoSwiftTestCase { // expect that a collection created from a DB with w:1 also has w:1 var coll3 = try db2.createCollection(self.getCollectionName(suffix: "3")) - try checkWriteConcern(coll3, w1, "collection created with no WC provided from \(dbDesc)") + try self.checkWriteConcern(coll3, w1, "collection created with no WC provided from \(dbDesc)") // expect that a collection retrieved from a DB with w:1 also has w:1 coll3 = db2.collection(coll3.name) - try checkWriteConcern(coll3, w1, "collection retrieved with no WC provided from \(dbDesc)") + try self.checkWriteConcern(coll3, w1, "collection retrieved with no WC provided from \(dbDesc)") // expect that a collection retrieved from a DB with w:1 can override the DB's WC let coll4 = db2.collection(self.getCollectionName(suffix: "4"), options: CollectionOptions(writeConcern: w2)) - try checkWriteConcern(coll4, w2, "collection retrieved with w:2 from \(dbDesc)") + try self.checkWriteConcern(coll4, w2, "collection retrieved with w:2 from \(dbDesc)") } func testOperationReadConcerns() throws { @@ -399,21 +408,27 @@ final class ReadWriteConcernTests: MongoSwiftTestCase { let options3 = RunCommandOptions(readConcern: ReadConcern("blah")) // error code 9: FailedToParse expect(try db.runCommand(command, options: options3)) - .to(throwError(ServerError.commandError(code: 9, - codeName: "FailedToParse", - message: "", - errorLabels: nil))) + .to(throwError(ServerError.commandError( + code: 9, + codeName: "FailedToParse", + message: "", + errorLabels: nil + ))) // try various command + read concern pairs to make sure they work expect(try coll.find(options: FindOptions(readConcern: ReadConcern(.local)))).toNot(throwError()) - expect(try coll.aggregate([["$project": ["a": 1]]], - options: AggregateOptions(readConcern: ReadConcern(.majority)))).toNot(throwError()) + expect(try coll.aggregate( + [["$project": ["a": 1]]], + options: AggregateOptions(readConcern: ReadConcern(.majority)) + )).toNot(throwError()) expect(try coll.count(options: CountOptions(readConcern: ReadConcern(.majority)))).toNot(throwError()) - expect(try coll.distinct(fieldName: "a", - options: DistinctOptions(readConcern: ReadConcern(.local)))).toNot(throwError()) + expect(try coll.distinct( + fieldName: "a", + options: DistinctOptions(readConcern: ReadConcern(.local)) + )).toNot(throwError()) } func testWriteConcernErrors() throws { @@ -427,15 +442,17 @@ final class ReadWriteConcernTests: MongoSwiftTestCase { let wc = try WriteConcern(w: .number(100)) let expectedWCError = - WriteConcernError(code: 100, codeName: "", details: nil, message: "") + WriteConcernError(code: 100, codeName: "", details: nil, message: "") let expectedWriteError = - ServerError.writeError(writeError: nil, writeConcernError: expectedWCError, errorLabels: nil) + ServerError.writeError(writeError: nil, writeConcernError: expectedWCError, errorLabels: nil) let expectedBulkResult = BulkWriteResult(insertedCount: 1, insertedIds: [0: 1]) - let expectedBulkError = ServerError.bulkWriteError(writeErrors: [], - writeConcernError: expectedWCError, - otherError: nil, - result: expectedBulkResult, - errorLabels: nil) + let expectedBulkError = ServerError.bulkWriteError( + writeErrors: [], + writeConcernError: expectedWCError, + otherError: nil, + result: expectedBulkResult, + errorLabels: nil + ) let client = try SyncMongoClient.makeTestClient() let database = client.db(type(of: self).testDatabase) @@ -443,10 +460,10 @@ final class ReadWriteConcernTests: MongoSwiftTestCase { defer { try? collection.drop() } expect(try collection.insertOne(["x": 1], options: InsertOneOptions(writeConcern: wc))) - .to(throwError(expectedWriteError)) + .to(throwError(expectedWriteError)) expect(try collection.bulkWrite([.insertOne(["_id": 1])], options: BulkWriteOptions(writeConcern: wc))) - .to(throwError(expectedBulkError)) + .to(throwError(expectedBulkError)) } func testOperationWriteConcerns() throws { @@ -480,36 +497,52 @@ final class ReadWriteConcernTests: MongoSwiftTestCase { expect(try coll.insertOne(nextDoc(), options: InsertOneOptions(writeConcern: wc1))).toNot(throwError()) expect(try coll.insertOne(nextDoc(), options: InsertOneOptions(writeConcern: wc3))).toNot(throwError()) - expect(try coll.insertMany([nextDoc(), nextDoc()], - options: InsertManyOptions(writeConcern: wc1))).toNot(throwError()) - expect(try coll.insertMany([nextDoc(), nextDoc()], - options: InsertManyOptions(writeConcern: wc3))).toNot(throwError()) - - expect(try coll.updateOne(filter: ["x": 1], - update: ["$set": .document(nextDoc())], - options: UpdateOptions(writeConcern: wc2))).toNot(throwError()) - expect(try coll.updateOne(filter: ["x": 2], - update: ["$set": .document(nextDoc())], - options: UpdateOptions(writeConcern: wc3))).toNot(throwError()) - - expect(try coll.updateMany(filter: ["x": 3], - update: ["$set": .document(nextDoc())], - options: UpdateOptions(writeConcern: wc2))).toNot(throwError()) - expect(try coll.updateMany(filter: ["x": 4], - update: ["$set": .document(nextDoc())], - options: UpdateOptions(writeConcern: wc3))).toNot(throwError()) + expect(try coll.insertMany( + [nextDoc(), nextDoc()], + options: InsertManyOptions(writeConcern: wc1) + )).toNot(throwError()) + expect(try coll.insertMany( + [nextDoc(), nextDoc()], + options: InsertManyOptions(writeConcern: wc3) + )).toNot(throwError()) + + expect(try coll.updateOne( + filter: ["x": 1], + update: ["$set": .document(nextDoc())], + options: UpdateOptions(writeConcern: wc2) + )).toNot(throwError()) + expect(try coll.updateOne( + filter: ["x": 2], + update: ["$set": .document(nextDoc())], + options: UpdateOptions(writeConcern: wc3) + )).toNot(throwError()) + + expect(try coll.updateMany( + filter: ["x": 3], + update: ["$set": .document(nextDoc())], + options: UpdateOptions(writeConcern: wc2) + )).toNot(throwError()) + expect(try coll.updateMany( + filter: ["x": 4], + update: ["$set": .document(nextDoc())], + options: UpdateOptions(writeConcern: wc3) + )).toNot(throwError()) let coll2 = try db.createCollection(self.getCollectionName(suffix: "2")) defer { try? coll2.drop() } let pipeline: [Document] = [["$out": .string("\(db.name).\(coll2.name)")]] expect(try coll.aggregate(pipeline, options: AggregateOptions(writeConcern: wc1))).toNot(throwError()) - expect(try coll.replaceOne(filter: ["x": 5], - replacement: nextDoc(), - options: ReplaceOptions(writeConcern: wc1))).toNot(throwError()) - expect(try coll.replaceOne(filter: ["x": 6], - replacement: nextDoc(), - options: ReplaceOptions(writeConcern: wc3))).toNot(throwError()) + expect(try coll.replaceOne( + filter: ["x": 5], + replacement: nextDoc(), + options: ReplaceOptions(writeConcern: wc1) + )).toNot(throwError()) + expect(try coll.replaceOne( + filter: ["x": 6], + replacement: nextDoc(), + options: ReplaceOptions(writeConcern: wc3) + )).toNot(throwError()) expect(try coll.deleteOne(["x": 7], options: DeleteOptions(writeConcern: wc1))).toNot(throwError()) expect(try coll.deleteOne(["x": 8], options: DeleteOptions(writeConcern: wc3))).toNot(throwError()) @@ -517,19 +550,25 @@ final class ReadWriteConcernTests: MongoSwiftTestCase { expect(try coll.deleteMany(["x": 9], options: DeleteOptions(writeConcern: wc1))).toNot(throwError()) expect(try coll.deleteMany(["x": 10], options: DeleteOptions(writeConcern: wc3))).toNot(throwError()) - expect(try coll.createIndex(["x": 1], - options: CreateIndexOptions(writeConcern: wc1))).toNot(throwError()) - expect(try coll.createIndexes([IndexModel(keys: ["x": -1])], - options: CreateIndexOptions(writeConcern: wc3))).toNot(throwError()) + expect(try coll.createIndex( + ["x": 1], + options: CreateIndexOptions(writeConcern: wc1) + )).toNot(throwError()) + expect(try coll.createIndexes( + [IndexModel(keys: ["x": -1])], + options: CreateIndexOptions(writeConcern: wc3) + )).toNot(throwError()) expect(try coll.dropIndex(["x": 1], options: DropIndexOptions(writeConcern: wc1))).toNot(throwError()) expect(try coll.dropIndexes(options: DropIndexOptions(writeConcern: wc3))).toNot(throwError()) } func testConnectionStrings() throws { - let testFiles = try retrieveSpecTestFiles(specName: "read-write-concern", - subdirectory: "connection-string", - asType: Document.self) + let testFiles = try retrieveSpecTestFiles( + specName: "read-write-concern", + subdirectory: "connection-string", + asType: Document.self + ) for (_, asDocument) in testFiles { let tests: [Document] = asDocument["tests"]!.arrayValue!.compactMap { $0.documentValue } for test in tests { @@ -564,9 +603,11 @@ final class ReadWriteConcernTests: MongoSwiftTestCase { func testDocuments() throws { let encoder = BSONEncoder() - let testFiles = try retrieveSpecTestFiles(specName: "read-write-concern", - subdirectory: "document", - asType: Document.self) + let testFiles = try retrieveSpecTestFiles( + specName: "read-write-concern", + subdirectory: "document", + asType: Document.self + ) for (_, asDocument) in testFiles { let tests = asDocument["tests"]!.arrayValue!.compactMap { $0.documentValue } diff --git a/Tests/MongoSwiftTests/SDAMMonitoringTests.swift b/Tests/MongoSwiftTests/SDAMMonitoringTests.swift index ca67be90b..8e89c668b 100644 --- a/Tests/MongoSwiftTests/SDAMMonitoringTests.swift +++ b/Tests/MongoSwiftTests/SDAMMonitoringTests.swift @@ -39,9 +39,9 @@ final class SDAMTests: MongoSwiftTestCase { let observer = center.addObserver(forName: nil, object: nil, queue: nil) { notif in guard [ - "serverDescriptionChanged", "serverOpening", "serverClosed", "topologyDescriptionChanged", - "topologyOpening", "topologyClosed" - ].contains(notif.name.rawValue) else { return } + "serverDescriptionChanged", "serverOpening", "serverClosed", "topologyDescriptionChanged", + "topologyOpening", "topologyClosed" + ].contains(notif.name.rawValue) else { return } guard let event = notif.userInfo?["event"] as? MongoEvent else { XCTFail("Notification \(notif) did not contain an event") @@ -92,13 +92,13 @@ final class SDAMTests: MongoSwiftTestCase { let event3 = receivedEvents[3] as! ServerDescriptionChangedEvent expect(event3.topologyId).to(equal(event2.topologyId)) let prevServer = event3.previousDescription - checkDefaultHostPort(prevServer, hostlist) - checkEmptyLists(prevServer) - checkUnknownServerType(prevServer) + self.checkDefaultHostPort(prevServer, hostlist) + self.checkEmptyLists(prevServer) + self.checkUnknownServerType(prevServer) let newServer = event3.newDescription - checkDefaultHostPort(newServer, hostlist) - checkEmptyLists(newServer) + self.checkDefaultHostPort(newServer, hostlist) + self.checkEmptyLists(newServer) expect(newServer.type).to(equal(ServerDescription.ServerType.standalone)) let event4 = receivedEvents[4] as! TopologyDescriptionChangedEvent @@ -109,8 +109,8 @@ final class SDAMTests: MongoSwiftTestCase { let newTopology = event4.newDescription expect(newTopology.type).to(equal(TopologyDescription.TopologyType.single)) - checkDefaultHostPort(newTopology.servers[0], hostlist) + self.checkDefaultHostPort(newTopology.servers[0], hostlist) expect(newTopology.servers[0].type).to(equal(ServerDescription.ServerType.standalone)) - checkEmptyLists(newTopology.servers[0]) + self.checkEmptyLists(newTopology.servers[0]) } } diff --git a/Tests/MongoSwiftTests/SpecTestRunner/Match.swift b/Tests/MongoSwiftTests/SpecTestRunner/Match.swift index 866b376b5..52bbf808e 100644 --- a/Tests/MongoSwiftTests/SpecTestRunner/Match.swift +++ b/Tests/MongoSwiftTests/SpecTestRunner/Match.swift @@ -15,6 +15,7 @@ internal protocol Matchable { /// Determines if this value is considered a wildcard for the purposes of the MATCHES function. func isPlaceholder() -> Bool } + // swiftlint:enable line_length extension Matchable { diff --git a/Tests/MongoSwiftTests/SpecTestRunner/SpecTest.swift b/Tests/MongoSwiftTests/SpecTestRunner/SpecTest.swift index ab9c28d0b..8ba73e7fe 100644 --- a/Tests/MongoSwiftTests/SpecTestRunner/SpecTest.swift +++ b/Tests/MongoSwiftTests/SpecTestRunner/SpecTest.swift @@ -35,13 +35,13 @@ internal struct TestCommandStartedEvent: Decodable, Matchable { internal func contentMatches(expected: TestCommandStartedEvent) -> Bool { return self.commandName.matches(expected: expected.commandName) - && self.databaseName.matches(expected: expected.databaseName) - && self.command.matches(expected: expected.command) + && self.databaseName.matches(expected: expected.databaseName) + && self.command.matches(expected: expected.command) } } /// Protocol that test cases which configure fail points during their execution conform to. -internal protocol FailPointConfigured: class { +internal protocol FailPointConfigured: AnyObject { /// The fail point currently set, if one exists. var activeFailPoint: FailPoint? { get set } } @@ -91,9 +91,9 @@ internal struct FailPoint: Decodable { // Need to convert error codes to int32's due to c driver bug (CDRIVER-3121) if k == "data", - var data = v.documentValue, - var wcErr = data["writeConcernError"]?.documentValue, - let code = wcErr["code"] { + var data = v.documentValue, + var wcErr = data["writeConcernError"]?.documentValue, + let code = wcErr["code"] { wcErr["code"] = .int32(code.asInt32()!) data["writeConcernError"] = .document(wcErr) commandDoc["data"] = .document(data) @@ -137,11 +137,13 @@ internal struct FailPoint: Decodable { /// Note: enabling a `failCommand` failpoint will override any other `failCommand` failpoint that is currently /// enabled. /// For more information, see the wiki: https://github.com/mongodb/mongo/wiki/The-%22failCommand%22-fail-point - public static func failCommand(failCommands: [String], - mode: Mode, - closeConnection: Bool? = nil, - errorCode: Int? = nil, - writeConcernError: Document? = nil) -> FailPoint { + public static func failCommand( + failCommands: [String], + mode: Mode, + closeConnection: Bool? = nil, + errorCode: Int? = nil, + writeConcernError: Document? = nil + ) -> FailPoint { var data: Document = [ "failCommands": .array(failCommands.map { .string($0) }) ] @@ -211,7 +213,7 @@ internal struct ServerVersion: Comparable, Decodable, CustomStringConvertible { } var description: String { - return "\(major).\(minor).\(patch)" + return "\(self.major).\(self.minor).\(self.patch)" } static func < (lhs: ServerVersion, rhs: ServerVersion) -> Bool { @@ -281,26 +283,31 @@ internal protocol SpecTest { var operation: AnyTestOperation { get } /// Runs the operation with the given context and performs assertions on the result based upon the expected outcome. - func run(client: SyncMongoClient, - db: SyncMongoDatabase, - collection: SyncMongoCollection, - session: SyncClientSession?) throws + func run( + client: SyncMongoClient, + db: SyncMongoDatabase, + collection: SyncMongoCollection, + session: SyncClientSession? + ) throws } /// Default implementation of a test execution. extension SpecTest { - internal func run(client: SyncMongoClient, - db: SyncMongoDatabase, - collection: SyncMongoCollection, - session: SyncClientSession?) throws { + internal func run( + client: SyncMongoClient, + db: SyncMongoDatabase, + collection: SyncMongoCollection, + session: SyncClientSession? + ) throws { var result: TestOperationResult? var seenError: Error? do { result = try self.operation.op.execute( - client: client, - database: db, - collection: collection, - session: session) + client: client, + database: db, + collection: collection, + session: session + ) } catch { if case let ServerError.bulkWriteError(_, _, _, bulkResult, _) = error { result = TestOperationResult(from: bulkResult) diff --git a/Tests/MongoSwiftTests/SpecTestRunner/SpecTestUtils.swift b/Tests/MongoSwiftTests/SpecTestRunner/SpecTestUtils.swift index 245017ac4..0e7512a8f 100644 --- a/Tests/MongoSwiftTests/SpecTestRunner/SpecTestUtils.swift +++ b/Tests/MongoSwiftTests/SpecTestRunner/SpecTestUtils.swift @@ -28,19 +28,21 @@ extension Document { /// Given a spec folder name (e.g. "crud") and optionally a subdirectory name for a folder (e.g. "read") retrieves an /// array of [(filename, file decoded to type T)]. -internal func retrieveSpecTestFiles(specName: String, - subdirectory: String? = nil, - asType: T.Type) throws -> [(String, T)] { +internal func retrieveSpecTestFiles( + specName: String, + subdirectory: String? = nil, + asType _: T.Type +) throws -> [(String, T)] { var path = "\(MongoSwiftTestCase.specsPath)/\(specName)/tests" if let sd = subdirectory { path += "/\(sd)" } return try FileManager.default - .contentsOfDirectory(atPath: path) - .filter { $0.hasSuffix(".json") } - .map { ($0, URL(fileURLWithPath: "\(path)/\($0)")) } - .map { ($0.0, try Document(fromJSONFile: $0.1)) } - .map { ($0.0, try BSONDecoder().decode(T.self, from: $0.1)) } + .contentsOfDirectory(atPath: path) + .filter { $0.hasSuffix(".json") } + .map { ($0, URL(fileURLWithPath: "\(path)/\($0)")) } + .map { ($0.0, try Document(fromJSONFile: $0.1)) } + .map { ($0.0, try BSONDecoder().decode(T.self, from: $0.1)) } } /// Given two documents, returns a copy of the input document with all keys that *don't* diff --git a/Tests/MongoSwiftTests/SpecTestRunner/TestOperation.swift b/Tests/MongoSwiftTests/SpecTestRunner/TestOperation.swift index fa67953a1..5c823cde4 100644 --- a/Tests/MongoSwiftTests/SpecTestRunner/TestOperation.swift +++ b/Tests/MongoSwiftTests/SpecTestRunner/TestOperation.swift @@ -3,10 +3,12 @@ /// Protocol describing the behavior of a spec test "operation" protocol TestOperation: Decodable { /// Execute the operation given the context. - func execute(client: SyncMongoClient, - database: SyncMongoDatabase, - collection: SyncMongoCollection, - session: SyncClientSession?) throws -> TestOperationResult? + func execute( + client: SyncMongoClient, + database: SyncMongoDatabase, + collection: SyncMongoCollection, + session: SyncClientSession? + ) throws -> TestOperationResult? } /// Wrapper around a `TestOperation.swift` allowing it to be decoded from a spec test. @@ -75,11 +77,14 @@ struct Aggregate: TestOperation { self.pipeline = try container.decode([Document].self, forKey: .pipeline) } - func execute(client: SyncMongoClient, - database: SyncMongoDatabase, - collection: SyncMongoCollection, - session: SyncClientSession? = nil) throws -> TestOperationResult? { - return TestOperationResult(from: try collection.aggregate(pipeline, options: self.options, session: session)) + func execute( + client _: SyncMongoClient, + database _: SyncMongoDatabase, + collection: SyncMongoCollection, + session: SyncClientSession? = nil + ) throws -> TestOperationResult? { + let cursor = try collection.aggregate(self.pipeline, options: self.options, session: session) + return TestOperationResult(from: cursor) } } @@ -95,11 +100,13 @@ struct Count: TestOperation { self.filter = try container.decode(Document.self, forKey: .filter) } - func execute(client: SyncMongoClient, - database: SyncMongoDatabase, - collection: SyncMongoCollection, - session: SyncClientSession? = nil) throws -> TestOperationResult? { - return .int(try collection.count(filter, options: self.options, session: session)) + func execute( + client _: SyncMongoClient, + database _: SyncMongoDatabase, + collection: SyncMongoCollection, + session: SyncClientSession? = nil + ) throws -> TestOperationResult? { + return .int(try collection.count(self.filter, options: self.options, session: session)) } } @@ -115,10 +122,12 @@ struct Distinct: TestOperation { self.fieldName = try container.decode(String.self, forKey: .fieldName) } - func execute(client: SyncMongoClient, - database: SyncMongoDatabase, - collection: SyncMongoCollection, - session: SyncClientSession? = nil) throws -> TestOperationResult? { + func execute( + client _: SyncMongoClient, + database _: SyncMongoDatabase, + collection: SyncMongoCollection, + session: SyncClientSession? = nil + ) throws -> TestOperationResult? { return .array(try collection.distinct(fieldName: self.fieldName, options: self.options, session: session)) } } @@ -135,10 +144,12 @@ struct Find: TestOperation { self.filter = try container.decode(Document.self, forKey: .filter) } - func execute(client: SyncMongoClient, - database: SyncMongoDatabase, - collection: SyncMongoCollection, - session: SyncClientSession? = nil) throws -> TestOperationResult? { + func execute( + client _: SyncMongoClient, + database _: SyncMongoDatabase, + collection: SyncMongoCollection, + session: SyncClientSession? = nil + ) throws -> TestOperationResult? { return TestOperationResult(from: try collection.find(self.filter, options: self.options, session: session)) } } @@ -157,14 +168,18 @@ struct UpdateOne: TestOperation { self.update = try container.decode(Document.self, forKey: .update) } - func execute(client: SyncMongoClient, - database: SyncMongoDatabase, - collection: SyncMongoCollection, - session: SyncClientSession? = nil) throws -> TestOperationResult? { - let result = try collection.updateOne(filter: self.filter, - update: self.update, - options: self.options, - session: session) + func execute( + client _: SyncMongoClient, + database _: SyncMongoDatabase, + collection: SyncMongoCollection, + session: SyncClientSession? = nil + ) throws -> TestOperationResult? { + let result = try collection.updateOne( + filter: self.filter, + update: self.update, + options: self.options, + session: session + ) return TestOperationResult(from: result) } } @@ -183,14 +198,18 @@ struct UpdateMany: TestOperation { self.update = try container.decode(Document.self, forKey: .update) } - func execute(client: SyncMongoClient, - database: SyncMongoDatabase, - collection: SyncMongoCollection, - session: SyncClientSession? = nil) throws -> TestOperationResult? { - let result = try collection.updateMany(filter: self.filter, - update: self.update, - options: self.options, - session: session) + func execute( + client _: SyncMongoClient, + database _: SyncMongoDatabase, + collection: SyncMongoCollection, + session: SyncClientSession? = nil + ) throws -> TestOperationResult? { + let result = try collection.updateMany( + filter: self.filter, + update: self.update, + options: self.options, + session: session + ) return TestOperationResult(from: result) } } @@ -207,10 +226,12 @@ struct DeleteMany: TestOperation { self.filter = try container.decode(Document.self, forKey: .filter) } - func execute(client: SyncMongoClient, - database: SyncMongoDatabase, - collection: SyncMongoCollection, - session: SyncClientSession? = nil) throws -> TestOperationResult? { + func execute( + client _: SyncMongoClient, + database _: SyncMongoDatabase, + collection: SyncMongoCollection, + session: SyncClientSession? = nil + ) throws -> TestOperationResult? { let result = try collection.deleteMany(self.filter, options: self.options, session: session) return TestOperationResult(from: result) } @@ -228,10 +249,12 @@ struct DeleteOne: TestOperation { self.filter = try container.decode(Document.self, forKey: .filter) } - func execute(client: SyncMongoClient, - database: SyncMongoDatabase, - collection: SyncMongoCollection, - session: SyncClientSession? = nil) throws -> TestOperationResult? { + func execute( + client _: SyncMongoClient, + database _: SyncMongoDatabase, + collection: SyncMongoCollection, + session: SyncClientSession? = nil + ) throws -> TestOperationResult? { let result = try collection.deleteOne(self.filter, options: self.options, session: session) return TestOperationResult(from: result) } @@ -240,10 +263,12 @@ struct DeleteOne: TestOperation { struct InsertOne: TestOperation { let document: Document - func execute(client: SyncMongoClient, - database: SyncMongoDatabase, - collection: SyncMongoCollection, - session: SyncClientSession? = nil) throws -> TestOperationResult? { + func execute( + client _: SyncMongoClient, + database _: SyncMongoDatabase, + collection: SyncMongoCollection, + session _: SyncClientSession? = nil + ) throws -> TestOperationResult? { return TestOperationResult(from: try collection.insertOne(self.document)) } } @@ -252,13 +277,17 @@ struct InsertMany: TestOperation { let documents: [Document] let options: InsertManyOptions - func execute(client: SyncMongoClient, - database: SyncMongoDatabase, - collection: SyncMongoCollection, - session: SyncClientSession? = nil) throws -> TestOperationResult? { - return TestOperationResult(from: try collection.insertMany(self.documents, - options: self.options, - session: session)) + func execute( + client _: SyncMongoClient, + database _: SyncMongoDatabase, + collection: SyncMongoCollection, + session: SyncClientSession? = nil + ) throws -> TestOperationResult? { + return TestOperationResult(from: try collection.insertMany( + self.documents, + options: self.options, + session: session + )) } } @@ -310,12 +339,16 @@ extension WriteModel: Decodable { let filter = try args.decode(Document.self, forKey: .filter) let update = try args.decode(Document.self, forKey: .update) self = name == "updateOne" ? - .updateOne(filter: filter, update: update, options: options) : - .updateMany(filter: filter, update: update, options: options) + .updateOne(filter: filter, update: update, options: options) : + .updateMany(filter: filter, update: update, options: options) default: - throw DecodingError.typeMismatch(WriteModel.self, - DecodingError.Context(codingPath: decoder.codingPath, - debugDescription: "Unknown write model: \(name)")) + throw DecodingError.typeMismatch( + WriteModel.self, + DecodingError.Context( + codingPath: decoder.codingPath, + debugDescription: "Unknown write model: \(name)" + ) + ) } } } @@ -324,10 +357,12 @@ struct BulkWrite: TestOperation { let requests: [WriteModel] let options: BulkWriteOptions - func execute(client: SyncMongoClient, - database: SyncMongoDatabase, - collection: SyncMongoCollection, - session: SyncClientSession? = nil) throws -> TestOperationResult? { + func execute( + client _: SyncMongoClient, + database _: SyncMongoDatabase, + collection: SyncMongoCollection, + session: SyncClientSession? = nil + ) throws -> TestOperationResult? { let result = try collection.bulkWrite(self.requests, options: self.options, session: session) return TestOperationResult(from: result) } @@ -347,14 +382,18 @@ struct FindOneAndUpdate: TestOperation { self.update = try container.decode(Document.self, forKey: .update) } - func execute(client: SyncMongoClient, - database: SyncMongoDatabase, - collection: SyncMongoCollection, - session: SyncClientSession? = nil) throws -> TestOperationResult? { - let doc = try collection.findOneAndUpdate(filter: self.filter, - update: self.update, - options: self.options, - session: session) + func execute( + client _: SyncMongoClient, + database _: SyncMongoDatabase, + collection: SyncMongoCollection, + session: SyncClientSession? = nil + ) throws -> TestOperationResult? { + let doc = try collection.findOneAndUpdate( + filter: self.filter, + update: self.update, + options: self.options, + session: session + ) return TestOperationResult(from: doc) } } @@ -371,10 +410,12 @@ struct FindOneAndDelete: TestOperation { self.filter = try container.decode(Document.self, forKey: .filter) } - func execute(client: SyncMongoClient, - database: SyncMongoDatabase, - collection: SyncMongoCollection, - session: SyncClientSession? = nil) throws -> TestOperationResult? { + func execute( + client _: SyncMongoClient, + database _: SyncMongoDatabase, + collection: SyncMongoCollection, + session: SyncClientSession? = nil + ) throws -> TestOperationResult? { let result = try collection.findOneAndDelete(self.filter, options: self.options, session: session) return TestOperationResult(from: result) } @@ -394,14 +435,18 @@ struct FindOneAndReplace: TestOperation { self.replacement = try container.decode(Document.self, forKey: .replacement) } - func execute(client: SyncMongoClient, - database: SyncMongoDatabase, - collection: SyncMongoCollection, - session: SyncClientSession? = nil) throws -> TestOperationResult? { - return TestOperationResult(from: try collection.findOneAndReplace(filter: self.filter, - replacement: self.replacement, - options: self.options, - session: session)) + func execute( + client _: SyncMongoClient, + database _: SyncMongoDatabase, + collection: SyncMongoCollection, + session: SyncClientSession? = nil + ) throws -> TestOperationResult? { + return TestOperationResult(from: try collection.findOneAndReplace( + filter: self.filter, + replacement: self.replacement, + options: self.options, + session: session + )) } } @@ -419,24 +464,30 @@ struct ReplaceOne: TestOperation { self.replacement = try container.decode(Document.self, forKey: .replacement) } - func execute(client: SyncMongoClient, - database: SyncMongoDatabase, - collection: SyncMongoCollection, - session: SyncClientSession? = nil) throws -> TestOperationResult? { - return TestOperationResult(from: try collection.replaceOne(filter: self.filter, - replacement: self.replacement, - options: self.options, - session: session)) + func execute( + client _: SyncMongoClient, + database _: SyncMongoDatabase, + collection: SyncMongoCollection, + session: SyncClientSession? = nil + ) throws -> TestOperationResult? { + return TestOperationResult(from: try collection.replaceOne( + filter: self.filter, + replacement: self.replacement, + options: self.options, + session: session + )) } } struct RenameCollection: TestOperation { let to: String - func execute(client: SyncMongoClient, - database: SyncMongoDatabase, - collection: SyncMongoCollection, - session: SyncClientSession? = nil) throws -> TestOperationResult? { + func execute( + client: SyncMongoClient, + database: SyncMongoDatabase, + collection: SyncMongoCollection, + session _: SyncClientSession? = nil + ) throws -> TestOperationResult? { let fromNamespace = database.name + "." + collection.name let toNamespace = database.name + "." + self.to let cmd: Document = ["renameCollection": .string(fromNamespace), "to": .string(toNamespace)] @@ -445,10 +496,12 @@ struct RenameCollection: TestOperation { } struct DropCollection: TestOperation { - func execute(client: SyncMongoClient, - database: SyncMongoDatabase, - collection: SyncMongoCollection, - session: SyncClientSession? = nil) throws -> TestOperationResult? { + func execute( + client _: SyncMongoClient, + database _: SyncMongoDatabase, + collection: SyncMongoCollection, + session _: SyncClientSession? = nil + ) throws -> TestOperationResult? { try collection.drop() return nil } diff --git a/Tests/MongoSwiftTests/SpecTestRunner/TestOperationResult.swift b/Tests/MongoSwiftTests/SpecTestRunner/TestOperationResult.swift index 7ab777aea..7445b6257 100644 --- a/Tests/MongoSwiftTests/SpecTestRunner/TestOperationResult.swift +++ b/Tests/MongoSwiftTests/SpecTestRunner/TestOperationResult.swift @@ -46,9 +46,12 @@ enum TestOperationResult: Decodable, Equatable { } else if let doc = try? Document(from: decoder) { self = .document(doc) } else { - throw DecodingError.valueNotFound(TestOperationResult.self, - DecodingError.Context(codingPath: decoder.codingPath, - debugDescription: "couldn't decode outcome") + throw DecodingError.valueNotFound( + TestOperationResult.self, + DecodingError.Context( + codingPath: decoder.codingPath, + debugDescription: "couldn't decode outcome" + ) ) } } @@ -61,7 +64,7 @@ enum TestOperationResult: Decodable, Equatable { return lhsInt == rhsInt case let (.array(lhsArray), .array(rhsArray)): return lhsArray == rhsArray - case let(.document(lhsDoc), .document(rhsDoc)): + case let (.document(lhsDoc), .document(rhsDoc)): return lhsDoc.sortedEquals(rhsDoc) default: return false @@ -98,10 +101,12 @@ extension UpdateResult: BulkWriteResultConvertible { upsertedIds = [0: upsertedId] } - return BulkWriteResult(matchedCount: self.matchedCount, - modifiedCount: self.modifiedCount, - upsertedCount: self.upsertedCount, - upsertedIds: upsertedIds) + return BulkWriteResult( + matchedCount: self.matchedCount, + modifiedCount: self.modifiedCount, + upsertedCount: self.upsertedCount, + upsertedIds: upsertedIds + ) } } diff --git a/Tests/MongoSwiftTests/TestUtils.swift b/Tests/MongoSwiftTests/TestUtils.swift index fa8fed45c..747aa16e9 100644 --- a/Tests/MongoSwiftTests/TestUtils.swift +++ b/Tests/MongoSwiftTests/TestUtils.swift @@ -95,15 +95,17 @@ class MongoSwiftTestCase: XCTestCase { /// executes, the collection associated with the namespace is dropped. /// /// Note: If a collection is not specified as part of the input namespace, this function will throw an error. - internal func withTestNamespace(ns: MongoNamespace? = nil, - clientOptions: ClientOptions? = nil, - collectionOptions: CreateCollectionOptions? = nil, - f: (SyncMongoClient, SyncMongoDatabase, SyncMongoCollection) - throws -> T) - throws -> T { + internal func withTestNamespace( + ns: MongoNamespace? = nil, + clientOptions: ClientOptions? = nil, + collectionOptions: CreateCollectionOptions? = nil, + f: (SyncMongoClient, SyncMongoDatabase, SyncMongoCollection) + throws -> T + ) + throws -> T { let client = try SyncMongoClient.makeTestClient(options: clientOptions) - return try withTestNamespace(client: client, ns: ns, options: collectionOptions) { db, coll in + return try self.withTestNamespace(client: client, ns: ns, options: collectionOptions) { db, coll in try f(client, db, coll) } } @@ -112,11 +114,13 @@ class MongoSwiftTestCase: XCTestCase { /// function. After the function executes, the collection associated with the namespace is dropped. /// /// Note: If a collection is not specified as part of the input namespace, this function will throw an error. - internal func withTestNamespace(client: SyncMongoClient, - ns: MongoNamespace? = nil, - options: CreateCollectionOptions? = nil, - _ f: (SyncMongoDatabase, SyncMongoCollection) throws -> T) - throws -> T { + internal func withTestNamespace( + client: SyncMongoClient, + ns: MongoNamespace? = nil, + options: CreateCollectionOptions? = nil, + _ f: (SyncMongoDatabase, SyncMongoCollection) throws -> T + ) + throws -> T { let ns = ns ?? self.getNamespace() guard let collName = ns.collection else { @@ -132,11 +136,14 @@ class MongoSwiftTestCase: XCTestCase { extension SyncMongoClient { internal func serverVersion() throws -> ServerVersion { - // TODO SWIFT-539: switch to always using buildInfo. fails on MacOS + SSL due to CDRIVER-3318 + // TODO: SWIFT-539: switch to always using buildInfo. fails on MacOS + SSL due to CDRIVER-3318 let cmd = MongoSwiftTestCase.ssl && MongoSwiftTestCase.isMacOS ? "serverStatus" : "buildInfo" - let reply = try self.db("admin").runCommand([cmd: 1], - options: RunCommandOptions( - readPreference: ReadPreference(.primary))) + let reply = try self.db("admin").runCommand( + [cmd: 1], + options: RunCommandOptions( + readPreference: ReadPreference(.primary) + ) + ) guard let versionString = reply["version"]?.stringValue else { throw TestError(message: " reply missing version string: \(reply)") } @@ -166,12 +173,16 @@ extension SyncMongoClient { return true } - static func makeTestClient(_ uri: String = MongoSwiftTestCase.connStr, - options: ClientOptions? = nil) throws -> SyncMongoClient { + static func makeTestClient( + _ uri: String = MongoSwiftTestCase.connStr, + options: ClientOptions? = nil + ) throws -> SyncMongoClient { var opts = options ?? ClientOptions() if MongoSwiftTestCase.ssl { - opts.tlsOptions = TLSOptions(caFile: URL(string: MongoSwiftTestCase.sslCAFilePath ?? ""), - pemFile: URL(string: MongoSwiftTestCase.sslPEMKeyFilePath ?? "")) + opts.tlsOptions = TLSOptions( + caFile: URL(string: MongoSwiftTestCase.sslCAFilePath ?? ""), + pemFile: URL(string: MongoSwiftTestCase.sslPEMKeyFilePath ?? "") + ) } return try SyncMongoClient(uri, options: opts) } @@ -258,10 +269,12 @@ internal func sortedEqual(_ expectedValue: Document?) -> Predicate { /// Captures any command monitoring events filtered by type and name that are emitted during the execution of the /// provided closure. Only events emitted by the provided client will be captured. -internal func captureCommandEvents(from client: SyncMongoClient, - eventTypes: [Notification.Name]? = nil, - commandNames: [String]? = nil, - f: () throws -> Void) rethrows -> [MongoCommandEvent] { +internal func captureCommandEvents( + from client: SyncMongoClient, + eventTypes: [Notification.Name]? = nil, + commandNames: [String]? = nil, + f: () throws -> Void +) rethrows -> [MongoCommandEvent] { let center = client.notificationCenter var events: [MongoCommandEvent] = [] @@ -291,18 +304,22 @@ internal func captureCommandEvents(from client: SyncMongoClient, /// Captures any command monitoring events filtered by type and name that are emitted during the execution of the /// provided closure. A client pre-configured for command monitoring is passed into the closure. -internal func captureCommandEvents(eventTypes: [Notification.Name]? = nil, - commandNames: [String]? = nil, - f: (SyncMongoClient) throws -> Void) throws -> [MongoCommandEvent] { +internal func captureCommandEvents( + eventTypes: [Notification.Name]? = nil, + commandNames: [String]? = nil, + f: (SyncMongoClient) throws -> Void +) throws -> [MongoCommandEvent] { let client = try SyncMongoClient.makeTestClient(options: ClientOptions(commandMonitoring: true)) return try captureCommandEvents(from: client, eventTypes: eventTypes, commandNames: commandNames) { try f(client) } } -internal func unsupportedTopologyMessage(testName: String, - topology: TopologyDescription.TopologyType = MongoSwiftTestCase.topologyType) - -> String { +internal func unsupportedTopologyMessage( + testName: String, + topology: TopologyDescription.TopologyType = MongoSwiftTestCase.topologyType +) + -> String { return "Skipping \(testName) due to unsupported topology type \(topology)" } From d94f17cd1a0ca70c9cc2b07e725432293a67d3ad Mon Sep 17 00:00:00 2001 From: Patrick Freed Date: Mon, 14 Oct 2019 15:23:59 -0400 Subject: [PATCH 3/4] update development guide --- Guides/Development.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Guides/Development.md b/Guides/Development.md index aa2f3d560..d8db1b0d4 100644 --- a/Guides/Development.md +++ b/Guides/Development.md @@ -78,6 +78,10 @@ To regenerate the files, run `make documentation` from the project's root direct ## Linting and Style We use [SwiftLint](https://github.com/realm/SwiftLint#using-homebrew) for linting. You can see our configuration in the `.swiftlint.yml` file in the project's root directory. Run `swiftlint` in the `/Sources` directory to lint all of our files. Running `swiftlint autocorrect` will correct some types of violations. +We use [SwiftFormat](https://github.com/nicklockwood/SwiftFormat) for formatting the code. You can see our configuration in the `.swiftformat` file in the project's root directory. Our linter config contains a superset of the rules that our formatter does, so some manual tweaking may be necessary to satisy both once the formatter is run (e.g. line length enforcement). Most of the time, the formatter should put the code into a format that passes the linter. + +To pass all the formatting stages of our testing matrix, both `swiftlint --strict` and `swiftformat --lint .` must finish successfully. + For style guidance, look at Swift's [API design guidelines](https://swift.org/documentation/api-design-guidelines/) and Google's [Swift Style Guide](https://google.github.io/swift/). ### Sublime Text Setup From ebf47417ad97799a1e7f2d9dce684d4eb6584302 Mon Sep 17 00:00:00 2001 From: Patrick Freed Date: Mon, 21 Oct 2019 14:01:40 -0400 Subject: [PATCH 4/4] cr comments --- .swiftlint.yml | 2 +- Guides/Development.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.swiftlint.yml b/.swiftlint.yml index b972c8b14..2a7e0dc81 100644 --- a/.swiftlint.yml +++ b/.swiftlint.yml @@ -53,7 +53,7 @@ excluded: - Package.swift - Examples/*/Package.swift - Tests/LinuxMain.swift - - SwiftFormat + - SwiftFormat # this is the path we download SwiftFormat to on travis trailing_whitespace: ignores_comments: false diff --git a/Guides/Development.md b/Guides/Development.md index d8db1b0d4..bab0b331d 100644 --- a/Guides/Development.md +++ b/Guides/Development.md @@ -78,7 +78,7 @@ To regenerate the files, run `make documentation` from the project's root direct ## Linting and Style We use [SwiftLint](https://github.com/realm/SwiftLint#using-homebrew) for linting. You can see our configuration in the `.swiftlint.yml` file in the project's root directory. Run `swiftlint` in the `/Sources` directory to lint all of our files. Running `swiftlint autocorrect` will correct some types of violations. -We use [SwiftFormat](https://github.com/nicklockwood/SwiftFormat) for formatting the code. You can see our configuration in the `.swiftformat` file in the project's root directory. Our linter config contains a superset of the rules that our formatter does, so some manual tweaking may be necessary to satisy both once the formatter is run (e.g. line length enforcement). Most of the time, the formatter should put the code into a format that passes the linter. +We use [SwiftFormat](https://github.com/nicklockwood/SwiftFormat) for formatting the code. You can see our configuration in the `.swiftformat` file in the project's root directory. Our linter config contains a superset of the rules that our formatter does, so some manual tweaking may be necessary to satisfy both once the formatter is run (e.g. line length enforcement). Most of the time, the formatter should put the code into a format that passes the linter. To pass all the formatting stages of our testing matrix, both `swiftlint --strict` and `swiftformat --lint .` must finish successfully.