69 lines
2.3 KiB
Swift
69 lines
2.3 KiB
Swift
import Testing
|
|
import Foundation
|
|
@testable import ThreadSafe
|
|
|
|
class ThreadSafetyTest: @unchecked Sendable {
|
|
|
|
class Obj {
|
|
let id = UUID().uuidString
|
|
}
|
|
|
|
// If @ThreadSafe is removed, the test would crash instantly
|
|
@ThreadSafe var obj = Obj()
|
|
|
|
@Test func testThreadSafe() async throws {
|
|
let coreCount = ProcessInfo.processInfo.activeProcessorCount
|
|
|
|
for _ in 0 ..< coreCount / 2 {
|
|
Thread { // write thread
|
|
while true {
|
|
self.obj = .init()
|
|
}
|
|
}.start()
|
|
}
|
|
|
|
for _ in 0 ..< coreCount / 2{
|
|
Thread { // read thread
|
|
while self.obj.id.count != 0 {}
|
|
}.start()
|
|
}
|
|
|
|
// If it doesn't crash after 10s, consider it passed.
|
|
// I think it's good enough as the possibility for a false positive is microscopic.
|
|
// Can't think of a way to definitively prove it's thread safe
|
|
try? await Task.sleep(for: .seconds(10))
|
|
}
|
|
}
|
|
|
|
@Test func TestCopyBehaviour() async throws {
|
|
struct Example {
|
|
// valueTypeCopyOnWrite enabled by default
|
|
@ThreadSafe var string: String = "Hello"
|
|
// valueTypeCopyOnWrite disabled
|
|
@ThreadSafe(valueTypeCopyOnWrite: false) var anotherString: String = "Hello"
|
|
// won't do anything as NSMutableString is a class
|
|
@ThreadSafe(valueTypeCopyOnWrite: true) var nsString: NSMutableString = "Hello"
|
|
// same as above
|
|
@ThreadSafe(valueTypeCopyOnWrite: false) var anotherNSString: NSMutableString = "Hello"
|
|
}
|
|
|
|
let original = Example()
|
|
var copy = original
|
|
|
|
copy.string.append(", World!")
|
|
#expect(original.string == "Hello") // copy on write triggered, original not affected
|
|
#expect(copy.string == "Hello, World!")
|
|
|
|
copy.anotherString.append(", World!")
|
|
#expect(original.anotherString == "Hello, World!") // valueTypeCopyOnWrite == false, underlying box not copied
|
|
#expect(copy.anotherString == "Hello, World!")
|
|
|
|
copy.nsString.append(", World!")
|
|
#expect(original.nsString == "Hello, World!")
|
|
#expect(copy.nsString == "Hello, World!")
|
|
|
|
copy.anotherNSString.append(", World!")
|
|
#expect(original.anotherNSString == "Hello, World!")
|
|
#expect(copy.anotherNSString == "Hello, World!")
|
|
}
|