diff options
| author | Andrej Mihajlov <and@mullvad.net> | 2022-06-08 12:23:57 +0200 |
|---|---|---|
| committer | Andrej Mihajlov <and@mullvad.net> | 2022-06-08 12:31:16 +0200 |
| commit | 24d1318b92113ef92703d504e90587b052959b31 (patch) | |
| tree | 6a1879bdfe92f7fbe16a69a35911e3bf813e56d8 | |
| parent | a003d0c2a63042e339456f2566c7d0e2b9ae95b1 (diff) | |
| download | mullvadvpn-24d1318b92113ef92703d504e90587b052959b31.tar.xz mullvadvpn-24d1318b92113ef92703d504e90587b052959b31.zip | |
Add tests
| -rw-r--r-- | ios/MullvadVPN.xcodeproj/project.pbxproj | 40 | ||||
| -rw-r--r-- | ios/MullvadVPNTests/OperationConditionTests.swift | 144 | ||||
| -rw-r--r-- | ios/MullvadVPNTests/OperationObserverTests.swift | 68 |
3 files changed, 244 insertions, 8 deletions
diff --git a/ios/MullvadVPN.xcodeproj/project.pbxproj b/ios/MullvadVPN.xcodeproj/project.pbxproj index 3f4b6b5e80..6d6c7ff27b 100644 --- a/ios/MullvadVPN.xcodeproj/project.pbxproj +++ b/ios/MullvadVPN.xcodeproj/project.pbxproj @@ -21,6 +21,7 @@ 58095C552760F02500890776 /* UpdateAddressCacheOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58095C542760F02500890776 /* UpdateAddressCacheOperation.swift */; }; 58095C572760F47900890776 /* api-ip-address.json in Resources */ = {isa = PBXBuildFile; fileRef = 58095C562760F47900890776 /* api-ip-address.json */; }; 58095C592762155700890776 /* RESTRetryStrategy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58095C582762155700890776 /* RESTRetryStrategy.swift */; }; + 580CBFB82848D503007878F0 /* OperationConditionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 580CBFB72848D503007878F0 /* OperationConditionTests.swift */; }; 580EE22424B3243100F9D8A1 /* AsyncBlockOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 580EE22324B3243100F9D8A1 /* AsyncBlockOperation.swift */; }; 580F8B8328197881002E0998 /* TunnelSettingsV2.swift in Sources */ = {isa = PBXBuildFile; fileRef = 580F8B8228197881002E0998 /* TunnelSettingsV2.swift */; }; 580F8B8428197884002E0998 /* TunnelSettingsV2.swift in Sources */ = {isa = PBXBuildFile; fileRef = 580F8B8228197881002E0998 /* TunnelSettingsV2.swift */; }; @@ -71,6 +72,16 @@ 5838318B27C40A3900000571 /* Pinger.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5838318A27C40A3900000571 /* Pinger.swift */; }; 583DA21425FA4B5C00318683 /* LocationDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 583DA21325FA4B5C00318683 /* LocationDataSource.swift */; }; 583E1E1B2848DE1C004838B3 /* ResultOperation+Fallible.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58059DE128468255002B1049 /* ResultOperation+Fallible.swift */; }; + 583E1E1C2848DE1C004838B3 /* AsyncOperationQueue.swift in Sources */ = {isa = PBXBuildFile; fileRef = 589D28782846250500F9A7B3 /* AsyncOperationQueue.swift */; }; + 583E1E1E2848DE1C004838B3 /* OperationCondition.swift in Sources */ = {isa = PBXBuildFile; fileRef = 589D28772846250500F9A7B3 /* OperationCondition.swift */; }; + 583E1E202848DE1C004838B3 /* OperationObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = 589D28792846250500F9A7B3 /* OperationObserver.swift */; }; + 583E1E222848DE1C004838B3 /* GroupOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 589D28812846306C00F9A7B3 /* GroupOperation.swift */; }; + 583E1E232848DE1C004838B3 /* OperationCompletion.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5840BE34279EDB16002836BA /* OperationCompletion.swift */; }; + 583E1E252848DE1C004838B3 /* ResultOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58F7D26427EB50A300E4D821 /* ResultOperation.swift */; }; + 583E1E262848DE1C004838B3 /* ResultBlockOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5842102D282D3FC200F24E46 /* ResultBlockOperation.swift */; }; + 583E1E282848DE1C004838B3 /* BackgroundObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = 589D287F28462CB000F9A7B3 /* BackgroundObserver.swift */; }; + 583E1E2A2848DF67004838B3 /* OperationObserverTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 583E1E292848DF67004838B3 /* OperationObserverTests.swift */; }; + 583E1E2C2848E1A1004838B3 /* WireGuardKitTypes in Frameworks */ = {isa = PBXBuildFile; productRef = 583E1E2B2848E1A1004838B3 /* WireGuardKitTypes */; }; 5840250122B1124600E4CFEC /* IPAddress+Codable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5840250022B1124600E4CFEC /* IPAddress+Codable.swift */; }; 5840250222B1124600E4CFEC /* IPAddress+Codable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5840250022B1124600E4CFEC /* IPAddress+Codable.swift */; }; 5840250422B11AB700E4CFEC /* MullvadEndpoint.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5840250322B11AB700E4CFEC /* MullvadEndpoint.swift */; }; @@ -177,7 +188,6 @@ 5883A09E266A5AF7003EFFCB /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 587B7543266922BF00DEF7E9 /* Localizable.strings */; }; 588527B2276B3F0700BAA373 /* LoadTunnelConfigurationOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 588527B1276B3F0700BAA373 /* LoadTunnelConfigurationOperation.swift */; }; 588527B4276B4F2F00BAA373 /* SetAccountOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 588527B3276B4F2F00BAA373 /* SetAccountOperation.swift */; }; - 58871D1E25D535A3002297FA /* WireGuardKit in Frameworks */ = {isa = PBXBuildFile; productRef = 58871D1D25D535A3002297FA /* WireGuardKit */; }; 58871D2325D535D2002297FA /* IPAddressRange+Codable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5850366725A47AC700A43E93 /* IPAddressRange+Codable.swift */; }; 5888AD83227B11080051EB06 /* SelectLocationCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5888AD82227B11080051EB06 /* SelectLocationCell.swift */; }; 5888AD87227B17950051EB06 /* SelectLocationViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5888AD86227B17950051EB06 /* SelectLocationViewController.swift */; }; @@ -345,6 +355,7 @@ 58095C542760F02500890776 /* UpdateAddressCacheOperation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UpdateAddressCacheOperation.swift; sourceTree = "<group>"; }; 58095C562760F47900890776 /* api-ip-address.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "api-ip-address.json"; sourceTree = "<group>"; }; 58095C582762155700890776 /* RESTRetryStrategy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RESTRetryStrategy.swift; sourceTree = "<group>"; }; + 580CBFB72848D503007878F0 /* OperationConditionTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OperationConditionTests.swift; sourceTree = "<group>"; }; 580EE22324B3243100F9D8A1 /* AsyncBlockOperation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AsyncBlockOperation.swift; sourceTree = "<group>"; }; 580F8B8228197881002E0998 /* TunnelSettingsV2.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TunnelSettingsV2.swift; sourceTree = "<group>"; }; 580F8B8528197958002E0998 /* DNSSettings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DNSSettings.swift; sourceTree = "<group>"; }; @@ -378,6 +389,7 @@ 5835B7CB233B76CB0096D79F /* TunnelManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TunnelManager.swift; sourceTree = "<group>"; }; 5838318A27C40A3900000571 /* Pinger.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Pinger.swift; sourceTree = "<group>"; }; 583DA21325FA4B5C00318683 /* LocationDataSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocationDataSource.swift; sourceTree = "<group>"; }; + 583E1E292848DF67004838B3 /* OperationObserverTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OperationObserverTests.swift; sourceTree = "<group>"; }; 5840250022B1124600E4CFEC /* IPAddress+Codable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "IPAddress+Codable.swift"; sourceTree = "<group>"; }; 5840250322B11AB700E4CFEC /* MullvadEndpoint.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MullvadEndpoint.swift; sourceTree = "<group>"; }; 5840BE34279EDB16002836BA /* OperationCompletion.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OperationCompletion.swift; sourceTree = "<group>"; }; @@ -560,8 +572,8 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 583E1E2C2848E1A1004838B3 /* WireGuardKitTypes in Frameworks */, 584789EC2652A1A2000E45FB /* Logging in Frameworks */, - 58871D1E25D535A3002297FA /* WireGuardKit in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -778,6 +790,8 @@ 58B0A2A1238EE67E00BC001D /* MullvadVPNTests */ = { isa = PBXGroup; children = ( + 583E1E292848DF67004838B3 /* OperationObserverTests.swift */, + 580CBFB72848D503007878F0 /* OperationConditionTests.swift */, 582AE3112440CA0D00E6733A /* AccountTokenInputTests.swift */, 5896AE85246D6AD8005B36CB /* CustomDateComponentsFormattingTests.swift */, 58B0A2A4238EE67E00BC001D /* Info.plist */, @@ -1017,8 +1031,8 @@ ); name = MullvadVPNTests; packageProductDependencies = ( - 58871D1D25D535A3002297FA /* WireGuardKit */, 584789EB2652A1A2000E45FB /* Logging */, + 583E1E2B2848E1A1004838B3 /* WireGuardKitTypes */, ); productName = MullvadVPNTests; productReference = 58B0A2A0238EE67E00BC001D /* MullvadVPNTests.xctest */; @@ -1202,6 +1216,8 @@ files = ( 582AE3132440CA2700E6733A /* AccountTokenInput.swift in Sources */, 58CAF4EF26025954007C5886 /* SimulatorTunnelProvider.swift in Sources */, + 583E1E232848DE1C004838B3 /* OperationCompletion.swift in Sources */, + 583E1E222848DE1C004838B3 /* GroupOperation.swift in Sources */, 58B0A2AA238EE6A900BC001D /* RelaySelector.swift in Sources */, 5896AE86246D6AD8005B36CB /* CustomDateComponentsFormattingTests.swift in Sources */, 5807E2C3243203E700F5FF30 /* String+Split.swift in Sources */, @@ -1213,20 +1229,28 @@ 58B0A2AC238EE6D500BC001D /* IPAddress+Codable.swift in Sources */, 58B0A2AD238EE6EC00BC001D /* MullvadEndpoint.swift in Sources */, 58FAEDF4245088B300CB0F5B /* KeychainError.swift in Sources */, + 583E1E252848DE1C004838B3 /* ResultOperation.swift in Sources */, + 583E1E262848DE1C004838B3 /* ResultBlockOperation.swift in Sources */, + 583E1E2A2848DF67004838B3 /* OperationObserverTests.swift in Sources */, 5896AE88246D7FAF005B36CB /* CustomDateComponentsFormatting.swift in Sources */, 5857F23824C8446700CF6F47 /* AsyncBlockOperation.swift in Sources */, 582AE3122440CA0D00E6733A /* AccountTokenInputTests.swift in Sources */, 585DA8A526B14EE000B8C587 /* PacketTunnelStatus.swift in Sources */, 58B0A2A9238EE6A100BC001D /* RelayConstraints.swift in Sources */, + 583E1E282848DE1C004838B3 /* BackgroundObserver.swift in Sources */, 5807E2C2243203D000F5FF30 /* StringTests.swift in Sources */, 5819C2142726CC8D00D6EC38 /* DataSourceSnapshotTests.swift in Sources */, 585DA8A326B14E0D00B8C587 /* ServerRelaysResponse.swift in Sources */, + 583E1E1E2848DE1C004838B3 /* OperationCondition.swift in Sources */, + 583E1E1C2848DE1C004838B3 /* AsyncOperationQueue.swift in Sources */, 5820676226E75D8500655B05 /* REST.swift in Sources */, 58A8055E2716EA6700681642 /* AnyIPAddress.swift in Sources */, 583E1E1B2848DE1C004838B3 /* ResultOperation+Fallible.swift in Sources */, 5857F23024C843ED00CF6F47 /* ChainedError.swift in Sources */, 58A8BE81239FBE62006B74AC /* IPEndpoint.swift in Sources */, 58871D2325D535D2002297FA /* IPAddressRange+Codable.swift in Sources */, + 580CBFB82848D503007878F0 /* OperationConditionTests.swift in Sources */, + 583E1E202848DE1C004838B3 /* OperationObserver.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1907,6 +1931,11 @@ package = 58BA79192578F092006FAEA0 /* XCRemoteSwiftPackageReference "wireguard-apple" */; productName = WireGuardKitTypes; }; + 583E1E2B2848E1A1004838B3 /* WireGuardKitTypes */ = { + isa = XCSwiftPackageProductDependency; + package = 58BA79192578F092006FAEA0 /* XCRemoteSwiftPackageReference "wireguard-apple" */; + productName = WireGuardKitTypes; + }; 584789EB2652A1A2000E45FB /* Logging */ = { isa = XCSwiftPackageProductDependency; package = 585834F624D2BC1F00A8AF56 /* XCRemoteSwiftPackageReference "swift-log" */; @@ -1922,11 +1951,6 @@ package = 585834F624D2BC1F00A8AF56 /* XCRemoteSwiftPackageReference "swift-log" */; productName = Logging; }; - 58871D1D25D535A3002297FA /* WireGuardKit */ = { - isa = XCSwiftPackageProductDependency; - package = 58BA79192578F092006FAEA0 /* XCRemoteSwiftPackageReference "wireguard-apple" */; - productName = WireGuardKit; - }; 58BA791A2578F092006FAEA0 /* WireGuardKit */ = { isa = XCSwiftPackageProductDependency; package = 58BA79192578F092006FAEA0 /* XCRemoteSwiftPackageReference "wireguard-apple" */; diff --git a/ios/MullvadVPNTests/OperationConditionTests.swift b/ios/MullvadVPNTests/OperationConditionTests.swift new file mode 100644 index 0000000000..297b8128ee --- /dev/null +++ b/ios/MullvadVPNTests/OperationConditionTests.swift @@ -0,0 +1,144 @@ +// +// OperationConditionTests.swift +// MullvadVPNTests +// +// Created by pronebird on 02/06/2022. +// Copyright © 2022 Mullvad VPN AB. All rights reserved. +// + +import XCTest + +class OperationConditionTests: XCTestCase { + func testTrueCondition() { + let expectConditionEvaluation = expectation(description: "Expect condition evaluation") + let expectOperationToExecute = expectation(description: "Expect operation to execute") + + let operation = AsyncBlockOperation { + expectOperationToExecute.fulfill() + } + + let blockCondition = BlockCondition { op, completion in + expectConditionEvaluation.fulfill() + completion(true) + } + + operation.addCondition(blockCondition) + + let operationQueue = AsyncOperationQueue() + operationQueue.addOperation(operation) + + waitForExpectations(timeout: 1) + } + + func testFalseCondition() { + let expectConditionEvaluation = expectation(description: "Expect condition evaluation") + let expectOperationToNeverExecute = expectation( + description: "Expect operation to never execute" + ) + expectOperationToNeverExecute.isInverted = true + + let operation = AsyncBlockOperation { + expectOperationToNeverExecute.fulfill() + } + + let blockCondition = BlockCondition { op, completion in + expectConditionEvaluation.fulfill() + completion(false) + } + + operation.addCondition(blockCondition) + + let operationQueue = AsyncOperationQueue() + operationQueue.addOperation(operation) + + waitForExpectations(timeout: 1) + } + + func testNoCancelledDependenciesCondition() { + let expectToNeverExecute = expectation(description: "Expect child to never execute.") + expectToNeverExecute.isInverted = true + + let parent = BlockOperation() + parent.cancel() + + let child = AsyncBlockOperation { + expectToNeverExecute.fulfill() + } + child.addDependency(parent) + child.addCondition(NoCancelledDependenciesCondition()) + + let operationQueue = AsyncOperationQueue() + operationQueue.addOperations([parent, child], waitUntilFinished: false) + + waitForExpectations(timeout: 1) + } + + func testNoFailedDependenciesCondition() { + let expectToNeverExecute = expectation(description: "Expect child to never execute.") + expectToNeverExecute.isInverted = true + + let parent = ResultBlockOperation<(), URLError> { + throw URLError(.badURL) + } + + let child = AsyncBlockOperation { + expectToNeverExecute.fulfill() + } + child.addDependency(parent) + child.addCondition(NoFailedDependenciesCondition(ignoreCancellations: false)) + + let operationQueue = AsyncOperationQueue() + operationQueue.addOperations([parent, child], waitUntilFinished: false) + + waitForExpectations(timeout: 1) + } + + func testNoFailedDependenciesIgnoringCancellationsCondition() { + let expectToExecute = expectation(description: "Expect child to execute.") + + let parent = BlockOperation() + parent.cancel() + + let child = AsyncBlockOperation { + expectToExecute.fulfill() + } + child.addDependency(parent) + child.addCondition(NoFailedDependenciesCondition(ignoreCancellations: true)) + + let operationQueue = AsyncOperationQueue() + operationQueue.addOperations([parent, child], waitUntilFinished: false) + + waitForExpectations(timeout: 1) + } + + func testMutuallyExclusiveCondition() { + let expectFirstOperationExecution = expectation( + description: "Expect first operation to execute first" + ) + let expectSecondOperationExecution = expectation( + description: "Expect second operation to execute last" + ) + + let exclusiveCategory = "exclusiveOperations" + let operationQueue = AsyncOperationQueue() + + let firstOperation = AsyncBlockOperation { op in + DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(1)) { + expectFirstOperationExecution.fulfill() + op.finish() + } + } + firstOperation.addCondition(MutuallyExclusive(category: exclusiveCategory)) + + let secondOperation = AsyncBlockOperation { + expectSecondOperationExecution.fulfill() + } + secondOperation.addCondition(MutuallyExclusive(category: exclusiveCategory)) + + operationQueue.addOperations([firstOperation, secondOperation], waitUntilFinished: false) + + let expectations = [expectFirstOperationExecution, expectSecondOperationExecution] + wait(for: expectations, timeout: 2, enforceOrder: true) + } + +} diff --git a/ios/MullvadVPNTests/OperationObserverTests.swift b/ios/MullvadVPNTests/OperationObserverTests.swift new file mode 100644 index 0000000000..ab4c29f6e3 --- /dev/null +++ b/ios/MullvadVPNTests/OperationObserverTests.swift @@ -0,0 +1,68 @@ +// +// OperationObserverTests.swift +// MullvadVPNTests +// +// Created by pronebird on 02/06/2022. +// Copyright © 2022 Mullvad VPN AB. All rights reserved. +// + +import XCTest + +class OperationObserverTests: XCTestCase { + + func testBlockObserver() throws { + let expectDidAttach = expectation(description: "didAttach handler") + let expectDidStart = expectation(description: "didStart handler") + let expectDidCancel = expectation(description: "didCancel handler") + expectDidCancel.isInverted = true + let expectDidFinish = expectation(description: "didAttach handler") + + let operation = AsyncBlockOperation() + operation.addBlockObserver(OperationBlockObserver( + didAttach: { op in + expectDidAttach.fulfill() + }, didStart: { op in + expectDidStart.fulfill() + }, didCancel: { op in + expectDidCancel.fulfill() + }, didFinish: { op in + expectDidFinish.fulfill() + } + )) + + let operationQueue = AsyncOperationQueue() + operationQueue.addOperation(operation) + + let expectations = [expectDidCancel, expectDidAttach, expectDidStart, expectDidFinish] + wait(for: expectations, timeout: 1, enforceOrder: true) + } + + func testBlockObserverWithCancelledOperation() { + let expectDidAttach = expectation(description: "didAttach handler") + let expectDidStart = expectation(description: "didStart handler") + expectDidStart.isInverted = true + let expectDidCancel = expectation(description: "didCancel handler") + let expectDidFinish = expectation(description: "didAttach handler") + + let operation = AsyncBlockOperation() + operation.addBlockObserver(OperationBlockObserver( + didAttach: { op in + expectDidAttach.fulfill() + }, didStart: { op in + expectDidStart.fulfill() + }, didCancel: { op in + expectDidCancel.fulfill() + }, didFinish: { op in + expectDidFinish.fulfill() + } + )) + operation.cancel() + + let operationQueue = AsyncOperationQueue() + operationQueue.addOperation(operation) + + let expectations = [expectDidAttach, expectDidCancel, expectDidStart, expectDidFinish] + wait(for: expectations, timeout: 1, enforceOrder: true) + } + +} |
