From 81b86afe2085c0b97b7ba202e7c4a4ca55bfa3fb Mon Sep 17 00:00:00 2001 From: Kevin Malek Date: Fri, 22 Nov 2024 11:38:46 -0800 Subject: [PATCH] Fixes an issue where asking a mock for values in a concurrent way causes a crash in the VerifyContainer --- .../SwiftMock/Verify/VerifyContainer.swift | 15 +++++++----- .../SwiftMockTests/Macro/MockMacroTests.swift | 22 ++++++++--------- .../SwiftMockTests/MethodStubbingTests.swift | 24 ++++++++++++++++++- 3 files changed, 43 insertions(+), 18 deletions(-) diff --git a/Sources/SwiftMock/Verify/VerifyContainer.swift b/Sources/SwiftMock/Verify/VerifyContainer.swift index 07df6af..64ef110 100644 --- a/Sources/SwiftMock/Verify/VerifyContainer.swift +++ b/Sources/SwiftMock/Verify/VerifyContainer.swift @@ -11,15 +11,18 @@ public class VerifyContainer: CallContainer { var calls: [Any] = [] var functions: [String] = [] var isVerified: [Bool] = [] - + private let queue = DispatchQueue(label: "VerifyContainerQueue") + public init() { } public func append(mock: AnyObject, call: MethodCall, function: String) { - calls.append(call) - functions.append(function) - isVerified.append(false) - - InOrderContainer.append(mock: mock, call: call, function: function) + queue.sync { [weak self] in + self?.calls.append(call) + self?.functions.append(function) + self?.isVerified.append(false) + + InOrderContainer.append(mock: mock, call: call, function: function) + } } public func verify( diff --git a/Tests/SwiftMockTests/Macro/MockMacroTests.swift b/Tests/SwiftMockTests/Macro/MockMacroTests.swift index fce70f1..99885f6 100644 --- a/Tests/SwiftMockTests/Macro/MockMacroTests.swift +++ b/Tests/SwiftMockTests/Macro/MockMacroTests.swift @@ -11,7 +11,7 @@ private let testMacros: [String: Macro.Type] = [ #endif final class MockMacroTests: XCTestCase { - func testEmptyProtocol() { + func testEmptyProtocol() throws { #if canImport(SwiftMockMacros) assertMacroExpansion( """ @@ -46,7 +46,7 @@ final class MockMacroTests: XCTestCase { #endif } - func testInternalProtocol() { + func testInternalProtocol() throws { #if canImport(SwiftMockMacros) assertMacroExpansion( """ @@ -79,7 +79,7 @@ final class MockMacroTests: XCTestCase { #endif } - func testFunctionWithoutArgumentsAndReturnType() { + func testFunctionWithoutArgumentsAndReturnType() throws { #if canImport(SwiftMockMacros) assertMacroExpansion( """ @@ -136,7 +136,7 @@ final class MockMacroTests: XCTestCase { #endif } - func testGetProperty() { + func testGetProperty() throws { #if canImport(SwiftMockMacros) assertMacroExpansion( """ @@ -192,7 +192,7 @@ final class MockMacroTests: XCTestCase { #endif } - func testGetSetProperty() { + func testGetSetProperty() throws { #if canImport(SwiftMockMacros) assertMacroExpansion( """ @@ -432,7 +432,7 @@ final class MockMacroTests: XCTestCase { #endif } - func testFunctionWithoutArguments() { + func testFunctionWithoutArguments() throws { #if canImport(SwiftMockMacros) assertMacroExpansion( """ @@ -489,7 +489,7 @@ final class MockMacroTests: XCTestCase { #endif } - func testFunctionWitOneArgument() { + func testFunctionWitOneArgument() throws { #if canImport(SwiftMockMacros) assertMacroExpansion( """ @@ -546,7 +546,7 @@ final class MockMacroTests: XCTestCase { #endif } - func testFunctionWithTwoArgument() { + func testFunctionWithTwoArgument() throws { #if canImport(SwiftMockMacros) assertMacroExpansion( """ @@ -605,7 +605,7 @@ final class MockMacroTests: XCTestCase { #endif } - func testFunctionThatThrows() { + func testFunctionThatThrows() throws { #if canImport(SwiftMockMacros) assertMacroExpansion( """ @@ -664,7 +664,7 @@ final class MockMacroTests: XCTestCase { #endif } - func testAsyncFunction() { + func testAsyncFunction() throws { #if canImport(SwiftMockMacros) assertMacroExpansion( """ @@ -723,7 +723,7 @@ final class MockMacroTests: XCTestCase { #endif } - func testAsyncThrowsFunction() { + func testAsyncThrowsFunction() throws { #if canImport(SwiftMockMacros) assertMacroExpansion( """ diff --git a/Tests/SwiftMockTests/MethodStubbingTests.swift b/Tests/SwiftMockTests/MethodStubbingTests.swift index 6ee4008..430bab4 100644 --- a/Tests/SwiftMockTests/MethodStubbingTests.swift +++ b/Tests/SwiftMockTests/MethodStubbingTests.swift @@ -177,7 +177,29 @@ final class MethodStubbingTests: XCTestCase { } XCTAssertNil(catchedError) } - + + func testConcurrentMockAccess() throws { + let mock = SimpleProtocolMock() + let expectation = -1 + when(mock.$call()).thenReturn(expectation) + + let xcTestExpectation = XCTestExpectation() + xcTestExpectation.expectedFulfillmentCount = 400 + DispatchQueue.concurrentPerform(iterations: 200) { number in + let actual = mock.call() + XCTAssertEqual(expectation, actual) + xcTestExpectation.fulfill() + } + + DispatchQueue.concurrentPerform(iterations: 200) { number in + let actual = mock.call() + XCTAssertEqual(expectation, actual) + xcTestExpectation.fulfill() + } + + wait(for: [xcTestExpectation]) + } + func testGenericWithOneParameter() { let mock = GenericMethodProtocolMock()