Skip to content

Commit 2454dd8

Browse files
committed
Add lock to guard access to calls in multithreaded tests
1 parent 1a1a266 commit 2454dd8

File tree

2 files changed

+25
-10
lines changed

2 files changed

+25
-10
lines changed

Sources/MockingKit/Mock.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,4 +24,5 @@ open class Mock: Mockable, @unchecked Sendable {
2424

2525
var registeredCalls: [UUID: [AnyCall]] = [:]
2626
var registeredResults: [UUID: Function] = [:]
27+
let registeredCallsLock = NSLock()
2728
}

Sources/MockingKit/Mockable.swift

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -38,41 +38,55 @@ extension Mockable {
3838
_ call: MockCall<Arguments, Result>,
3939
for ref: MockReference<Arguments, Result>
4040
) {
41-
let calls = mock.registeredCalls[ref.id] ?? []
42-
mock.registeredCalls[ref.id] = calls + [call]
41+
mock.registeredCallsLock.withLock {
42+
let calls = mock.registeredCalls[ref.id] ?? []
43+
mock.registeredCalls[ref.id] = calls + [call]
44+
}
4345
}
4446

4547
func registerCall<Arguments, Result>(
4648
_ call: MockCall<Arguments, Result>,
4749
for ref: AsyncMockReference<Arguments, Result>
4850
) {
49-
let calls = mock.registeredCalls[ref.id] ?? []
50-
mock.registeredCalls[ref.id] = calls + [call]
51+
mock.registeredCallsLock.withLock {
52+
let calls = mock.registeredCalls[ref.id] ?? []
53+
mock.registeredCalls[ref.id] = calls + [call]
54+
}
5155
}
5256

5357
func registeredCalls<Arguments, Result>(
5458
for ref: MockReference<Arguments, Result>
5559
) -> [MockCall<Arguments, Result>] {
56-
let calls = mock.registeredCalls[ref.id]
57-
return (calls as? [MockCall<Arguments, Result>]) ?? []
60+
mock.registeredCallsLock.withLock {
61+
let calls = mock.registeredCalls[ref.id]
62+
return (calls as? [MockCall<Arguments, Result>]) ?? []
63+
}
5864
}
5965

6066
func registeredCalls<Arguments, Result>(
6167
for ref: AsyncMockReference<Arguments, Result>
6268
) -> [MockCall<Arguments, Result>] {
63-
let calls = mock.registeredCalls[ref.id]
64-
return (calls as? [MockCall<Arguments, Result>]) ?? []
69+
mock.registeredCallsLock.withLock {
70+
let calls = mock.registeredCalls[ref.id]
71+
return (calls as? [MockCall<Arguments, Result>]) ?? []
72+
}
6573
}
6674

6775
func registeredResult<Arguments, Result>(
6876
for ref: MockReference<Arguments, Result>
6977
) -> ((Arguments) throws -> Result)? {
70-
mock.registeredResults[ref.id] as? (Arguments) throws -> Result
78+
mock.registeredCallsLock.withLock {
79+
let result = mock.registeredResults[ref.id] as? (Arguments) throws -> Result
80+
return result
81+
}
7182
}
7283

7384
func registeredResult<Arguments, Result>(
7485
for ref: AsyncMockReference<Arguments, Result>
7586
) -> ((Arguments) async throws -> Result)? {
76-
mock.registeredResults[ref.id] as? (Arguments) async throws -> Result
87+
mock.registeredCallsLock.withLock {
88+
let result = mock.registeredResults[ref.id] as? (Arguments) async throws -> Result
89+
return result
90+
}
7791
}
7892
}

0 commit comments

Comments
 (0)