From 6c3211ffed33b88b3bffd600ca1cad44f334772f Mon Sep 17 00:00:00 2001 From: Lawrence Forooghian Date: Wed, 4 May 2022 15:09:21 -0300 Subject: [PATCH] Add locking to MockDeviceStorage As promised in 3f78a12. Together with de281bd and 214795f, I believe this closes #1322 (various crashes in PushTests.test__008__LocalDevice__has_a_device_method_that_returns_a_LocalDevice, which seemed to be related to threading). Test case: https://test-observability.herokuapp.com/repos/ably/ably-cocoa/test_cases/4f837671-6233-41f1-94e8-01174d1da7b8 --- Spec/Test Utilities/MockDeviceStorage.swift | 50 +++++++++++++-------- 1 file changed, 32 insertions(+), 18 deletions(-) diff --git a/Spec/Test Utilities/MockDeviceStorage.swift b/Spec/Test Utilities/MockDeviceStorage.swift index 39237517a..1bbb4a751 100644 --- a/Spec/Test Utilities/MockDeviceStorage.swift +++ b/Spec/Test Utilities/MockDeviceStorage.swift @@ -1,6 +1,8 @@ import Ably class MockDeviceStorage: NSObject, ARTDeviceStorage { + + private let accessQueue = DispatchQueue(label: "io.ably.MockDeviceStorage") var keysRead: [String] = [] var keysWritten: [String: Any?] = [:] @@ -16,41 +18,53 @@ class MockDeviceStorage: NSObject, ARTDeviceStorage { } func object(forKey key: String) -> Any? { - keysRead.append(key) - if let data = simulateData[key] { - defer { simulateData.removeValue(forKey: key) } - return data + return accessQueue.sync { + keysRead.append(key) + if let data = simulateData[key] { + defer { simulateData.removeValue(forKey: key) } + return data + } + if let string = simulateString[key] { + defer { simulateString.removeValue(forKey: key) } + return string + } + return nil } - if let string = simulateString[key] { - defer { simulateString.removeValue(forKey: key) } - return string - } - return nil } func setObject(_ value: Any?, forKey key: String) { - keysWritten.updateValue(value, forKey: key) + accessQueue.sync { + _ = keysWritten.updateValue(value, forKey: key) + } } func secret(forDevice deviceId: ARTDeviceId) -> String? { - keysRead.append(ARTDeviceSecretKey) - if let value = simulateString[ARTDeviceSecretKey] { - defer { simulateString.removeValue(forKey: ARTDeviceSecretKey) } - return value + return accessQueue.sync { + keysRead.append(ARTDeviceSecretKey) + if let value = simulateString[ARTDeviceSecretKey] { + defer { simulateString.removeValue(forKey: ARTDeviceSecretKey) } + return value + } + return nil } - return nil } func setSecret(_ value: String?, forDevice deviceId: ARTDeviceId) { - keysWritten.updateValue(value, forKey: ARTDeviceSecretKey) + accessQueue.sync { + _ = keysWritten.updateValue(value, forKey: ARTDeviceSecretKey) + } } func simulateOnNextRead(data value: Data, `for` key: String) { - simulateData[key] = value + accessQueue.sync { + simulateData[key] = value + } } func simulateOnNextRead(string value: String, `for` key: String) { - simulateString[key] = value + accessQueue.sync { + simulateString[key] = value + } } }