Skip to content

Add Swift 6.0 to Linux test matrix #303

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 13 commits into from
Feb 25, 2025
Merged
1 change: 1 addition & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ jobs:
matrix:
swift:
- '5.10'
- '6.0'
name: Ubuntu (Swift ${{ matrix.swift }})
runs-on: ubuntu-latest
container: swift:${{ matrix.swift }}
Expand Down
43 changes: 26 additions & 17 deletions Package.resolved

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

18 changes: 13 additions & 5 deletions Sources/Dependencies/DependencyValues.swift
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ public struct DependencyValues: Sendable {
.takeUnretainedValue()
else { return }
let testCaseWillStartBlock: @convention(block) (AnyObject) -> Void = { _ in
DependencyValues._current.cachedValues.cached = [:]
DependencyValues._current.cachedValues.resetCache()
}
let testCaseWillStartImp = imp_implementationWithBlock(testCaseWillStartBlock)
class_addMethod(
Expand All @@ -167,7 +167,7 @@ public struct DependencyValues: Sendable {
if isTesting {
XCTestObservationCenter.shared.addTestObserver(
TestObserver {
DependencyValues._current.cachedValues.cached = [:]
DependencyValues._current.cachedValues.resetCache()
}
)
}
Expand All @@ -191,7 +191,7 @@ public struct DependencyValues: Sendable {
}
#endif
pRegisterTestObserver?({
DependencyValues._current.cachedValues.cached = [:]
DependencyValues._current.cachedValues.resetCache()
})
#endif
}
Expand Down Expand Up @@ -286,6 +286,8 @@ public struct DependencyValues: Sendable {
reportIssue("Ignoring dependencies prepared in preview app entry point")
return
}
cachedValues.lock.lock()
defer { cachedValues.lock.unlock() }
let cacheKey = CachedValues.CacheKey(id: TypeIdentifier(key), context: context)
guard !cachedValues.cached.keys.contains(cacheKey) else {
if cachedValues.cached[cacheKey]?.preparationID != DependencyValues.preparationID {
Expand Down Expand Up @@ -405,7 +407,7 @@ public struct DependencyValues: Sendable {
message: "'resetCache' is no longer necessary for most (unparameterized) '@Test' cases"
)
public func resetCache() {
cachedValues.cached = [:]
cachedValues.resetCache()
}
}

Expand Down Expand Up @@ -478,9 +480,15 @@ public final class CachedValues: @unchecked Sendable {
let preparationID: UUID?
}

private let lock = NSRecursiveLock()
public let lock = NSRecursiveLock()
public var cached = [CacheKey: CachedValue]()

public func resetCache() {
lock.lock()
defer { lock.unlock() }
cached = [:]
}

func value<Key: TestDependencyKey>(
for key: Key.Type,
context: DependencyContext,
Expand Down
2 changes: 1 addition & 1 deletion Tests/DependenciesTests/CacheTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ final class CachedValueTests: XCTestCase {
override func tearDown() {
super.tearDown()
CacheLocals.$skipFailure.withValue(true) {
DependencyValues._current.cachedValues.cached = [:]
DependencyValues._current.cachedValues.resetCache()
}
}

Expand Down
41 changes: 22 additions & 19 deletions Tests/DependenciesTests/DependencyValuesTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -437,30 +437,33 @@ final class DependencyValuesTests: XCTestCase {
self.wait(for: [expectation], timeout: 1)
}

@MainActor
func testEscapingInFeatureModel_InstanceVariablePropagated() async {
let expectation = self.expectation(description: "escape")

// TODO: Remove this condition when Linux CI is updated to a more recent Swift 6.
#if !os(Linux) || compiler(<6)
@MainActor
class FeatureModel /*: ObservableObject*/ {
@Dependency(\.fullDependency) var fullDependency
func doSomething(expectation: XCTestExpectation) {
DispatchQueue.main.async {
XCTAssertEqual(self.fullDependency.value, 42)
expectation.fulfill()
func testEscapingInFeatureModel_InstanceVariablePropagated() async {
let expectation = self.expectation(description: "escape")

@MainActor
class FeatureModel /*: ObservableObject*/ {
@Dependency(\.fullDependency) var fullDependency
func doSomething(expectation: XCTestExpectation) {
DispatchQueue.main.async {
XCTAssertEqual(self.fullDependency.value, 42)
expectation.fulfill()
}
}
}
}

let model = withDependencies {
$0.fullDependency.value = 42
} operation: {
FeatureModel()
}
let model = withDependencies {
$0.fullDependency.value = 42
} operation: {
FeatureModel()
}

model.doSomething(expectation: expectation)
await fulfillment(of: [expectation], timeout: 1)
}
model.doSomething(expectation: expectation)
await fulfillment(of: [expectation], timeout: 1)
}
#endif

func testEscapingInFeatureModel_NotPropagated() async {
let expectation = self.expectation(description: "escape")
Expand Down