Skip to content

Commit

Permalink
Disable tests that use @MainActor on Linux
Browse files Browse the repository at this point in the history
## Changes

- Disable tests that use `@MainActor` on Linux because of an issue
gathering tests:
https://github.com/apple/swift-corelibs-xctest/issues/424

- Remove Swift installation from SwiftPM Linux job, as Swift is already
included in `ubuntu-latest` (`ubuntu-20.04`):
https://github.com/actions/runner-images/blob/main/images/linux/Ubuntu2004-Readme.md#language-and-runtime
  • Loading branch information
p4checo committed Dec 13, 2022
1 parent a254af7 commit da54550
Show file tree
Hide file tree
Showing 14 changed files with 1,967 additions and 1,961 deletions.
12 changes: 0 additions & 12 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,19 +45,7 @@ jobs:
name: SwiftPM Linux
runs-on: ubuntu-latest
steps:
- name: Install Swift
run: |
eval "$(curl -sL https://swiftenv.fuller.li/install.sh)"
- name: Checkout
uses: actions/checkout@v2
- name: Pull dependencies
run: |
swift package resolve
- name: Swift version
run: swift --version
- name: Options
run: swift test --help
- name: List Tests
run: swift test --enable-test-discovery --list-tests
- name: Test via SwiftPM
run: swift test --enable-test-discovery
253 changes: 128 additions & 125 deletions Tests/ComposableArchitectureTests/ComposableArchitectureTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,154 +2,157 @@ import ComposableArchitecture
import ReactiveSwift
import XCTest

@MainActor
final class ComposableArchitectureTests: XCTestCase {
func testScheduling() async {
enum CounterAction: Equatable {
case incrAndSquareLater
case incrNow
case squareNow
}
// `@MainActor` introduces issues gathering tests on Linux
#if !os(Linux)
@MainActor
final class ComposableArchitectureTests: XCTestCase {
func testScheduling() async {
enum CounterAction: Equatable {
case incrAndSquareLater
case incrNow
case squareNow
}

let counterReducer = Reducer<Int, CounterAction, DateScheduler> {
state, action, scheduler in
switch action {
case .incrAndSquareLater:
return .merge(
Effect(value: .incrNow).deferred(for: 2, scheduler: scheduler),
Effect(value: .squareNow).deferred(for: 1, scheduler: scheduler),
Effect(value: .squareNow).deferred(for: 2, scheduler: scheduler)
)
case .incrNow:
state += 1
return .none
case .squareNow:
state *= state
return .none
let counterReducer = Reducer<Int, CounterAction, DateScheduler> {
state, action, scheduler in
switch action {
case .incrAndSquareLater:
return .merge(
Effect(value: .incrNow).deferred(for: 2, scheduler: scheduler),
Effect(value: .squareNow).deferred(for: 1, scheduler: scheduler),
Effect(value: .squareNow).deferred(for: 2, scheduler: scheduler)
)
case .incrNow:
state += 1
return .none
case .squareNow:
state *= state
return .none
}
}

let mainQueue = TestScheduler()

let store = TestStore(
initialState: 2,
reducer: counterReducer,
environment: mainQueue
)

await store.send(.incrAndSquareLater)
await mainQueue.advance(by: 1)
await store.receive(.squareNow) { $0 = 4 }
await mainQueue.advance(by: 1)
await store.receive(.incrNow) { $0 = 5 }
await store.receive(.squareNow) { $0 = 25 }

await store.send(.incrAndSquareLater)
await mainQueue.advance(by: 2)
await store.receive(.squareNow) { $0 = 625 }
await store.receive(.incrNow) { $0 = 626 }
await store.receive(.squareNow) { $0 = 391876 }
}

let mainQueue = TestScheduler()

let store = TestStore(
initialState: 2,
reducer: counterReducer,
environment: mainQueue
)

await store.send(.incrAndSquareLater)
await mainQueue.advance(by: 1)
await store.receive(.squareNow) { $0 = 4 }
await mainQueue.advance(by: 1)
await store.receive(.incrNow) { $0 = 5 }
await store.receive(.squareNow) { $0 = 25 }

await store.send(.incrAndSquareLater)
await mainQueue.advance(by: 2)
await store.receive(.squareNow) { $0 = 625 }
await store.receive(.incrNow) { $0 = 626 }
await store.receive(.squareNow) { $0 = 391876 }
}
func testSimultaneousWorkOrdering() {
let testScheduler = TestScheduler()

func testSimultaneousWorkOrdering() {
let testScheduler = TestScheduler()
var values: [Int] = []
testScheduler.schedule(after: .seconds(0), interval: .seconds(1)) { values.append(1) }
testScheduler.schedule(after: .seconds(0), interval: .seconds(2)) { values.append(42) }

var values: [Int] = []
testScheduler.schedule(after: .seconds(0), interval: .seconds(1)) { values.append(1) }
testScheduler.schedule(after: .seconds(0), interval: .seconds(2)) { values.append(42) }
XCTAssertNoDifference(values, [])
testScheduler.advance()
XCTAssertNoDifference(values, [1, 42])
testScheduler.advance(by: 2)
XCTAssertNoDifference(values, [1, 42, 1, 42, 1])
}

XCTAssertNoDifference(values, [])
testScheduler.advance()
XCTAssertNoDifference(values, [1, 42])
testScheduler.advance(by: 2)
XCTAssertNoDifference(values, [1, 42, 1, 42, 1])
}
func testLongLivingEffects() async {
typealias Environment = (
startEffect: Effect<Void, Never>,
stopEffect: Effect<Never, Never>
)

func testLongLivingEffects() async {
typealias Environment = (
startEffect: Effect<Void, Never>,
stopEffect: Effect<Never, Never>
)

enum Action { case end, incr, start }

let reducer = Reducer<Int, Action, Environment> { state, action, environment in
switch action {
case .end:
return environment.stopEffect.fireAndForget()
case .incr:
state += 1
return .none
case .start:
return environment.startEffect.map { Action.incr }
enum Action { case end, incr, start }

let reducer = Reducer<Int, Action, Environment> { state, action, environment in
switch action {
case .end:
return environment.stopEffect.fireAndForget()
case .incr:
state += 1
return .none
case .start:
return environment.startEffect.map { Action.incr }
}
}
}

let subject = Signal<Void, Never>.pipe()
let subject = Signal<Void, Never>.pipe()

let store = TestStore(
initialState: 0,
reducer: reducer,
environment: (
startEffect: subject.output.producer.eraseToEffect(),
stopEffect: .fireAndForget { subject.input.sendCompleted() }
let store = TestStore(
initialState: 0,
reducer: reducer,
environment: (
startEffect: subject.output.producer.eraseToEffect(),
stopEffect: .fireAndForget { subject.input.sendCompleted() }
)
)
)

await store.send(.start)
await store.send(.incr) { $0 = 1 }
subject.input.send(value: ())
await store.receive(.incr) { $0 = 2 }
await store.send(.end)
}
await store.send(.start)
await store.send(.incr) { $0 = 1 }
subject.input.send(value: ())
await store.receive(.incr) { $0 = 2 }
await store.send(.end)
}

func testCancellation() async {
let mainQueue = TestScheduler()
func testCancellation() async {
let mainQueue = TestScheduler()

enum Action: Equatable {
case cancel
case incr
case response(Int)
}
enum Action: Equatable {
case cancel
case incr
case response(Int)
}

struct Environment {
let fetch: (Int) async -> Int
}
struct Environment {
let fetch: (Int) async -> Int
}

let reducer = Reducer<Int, Action, Environment> { state, action, environment in
enum CancelID {}
let reducer = Reducer<Int, Action, Environment> { state, action, environment in
enum CancelID {}

switch action {
case .cancel:
return .cancel(id: CancelID.self)
switch action {
case .cancel:
return .cancel(id: CancelID.self)

case .incr:
state += 1
return .task { [state] in
try await mainQueue.sleep(for: .seconds(1))
return .response(await environment.fetch(state))
}
.cancellable(id: CancelID.self)
case .incr:
state += 1
return .task { [state] in
try await mainQueue.sleep(for: .seconds(1))
return .response(await environment.fetch(state))
}
.cancellable(id: CancelID.self)

case let .response(value):
state = value
return .none
case let .response(value):
state = value
return .none
}
}
}

let store = TestStore(
initialState: 0,
reducer: reducer,
environment: Environment(
fetch: { value in value * value }
let store = TestStore(
initialState: 0,
reducer: reducer,
environment: Environment(
fetch: { value in value * value }
)
)
)

await store.send(.incr) { $0 = 1 }
await mainQueue.advance(by: .seconds(1))
await store.receive(.response(1))
await store.send(.incr) { $0 = 1 }
await mainQueue.advance(by: .seconds(1))
await store.receive(.response(1))

await store.send(.incr) { $0 = 2 }
await store.send(.cancel)
await store.send(.incr) { $0 = 2 }
await store.send(.cancel)
}
}
}
#endif
Loading

0 comments on commit da54550

Please sign in to comment.