basic implementation and unit tests
This commit is contained in:
68
Tests/ThreadSafeTests/ThreadSafeTests.swift
Normal file
68
Tests/ThreadSafeTests/ThreadSafeTests.swift
Normal file
@@ -0,0 +1,68 @@
|
||||
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!")
|
||||
}
|
||||
Reference in New Issue
Block a user