Skip to content

Commit

Permalink
Throw error when recursion is detected in transition (#47)
Browse files Browse the repository at this point in the history
* Use Xcode 12.5.1

* Throw error when recursion is detected in transition

* Add test for recursion detected error
  • Loading branch information
tinder-cfuller authored Nov 19, 2021
1 parent 6a493bf commit 0f79642
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 0 deletions.
11 changes: 11 additions & 0 deletions Swift/Sources/StateMachine/StateMachine.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@ open class StateMachine<State: StateMachineHashable, Event: StateMachineHashable
public struct Invalid: Error, Equatable {}
}

public enum StateMachineError: Error {

case recursionDetected
}

private struct Observer {

weak var object: AnyObject?
Expand All @@ -51,6 +56,8 @@ open class StateMachine<State: StateMachineHashable, Event: StateMachineHashable
private let states: States
private var observers: [Observer] = []

private var isNotifying: Bool = false

public init(@DefinitionBuilder build: () -> Definition) {
let definition: Definition = build()
state = definition.initialState.state
Expand Down Expand Up @@ -86,6 +93,8 @@ open class StateMachine<State: StateMachineHashable, Event: StateMachineHashable

@discardableResult
public func transition(_ event: Event) throws -> Transition.Valid {
guard !isNotifying
else { throw StateMachineError.recursionDetected }
let result: Transition.Result
defer { notify(result) }
do {
Expand All @@ -111,6 +120,8 @@ open class StateMachine<State: StateMachineHashable, Event: StateMachineHashable
}

private func notify(_ result: Transition.Result) {
isNotifying = true
defer { isNotifying = false }
var observers: [Observer] = []
for observer in self.observers {
guard observer.object != nil
Expand Down
22 changes: 22 additions & 0 deletions Swift/Tests/StateMachineTests/StateMachineTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,28 @@ final class StateMachineTests: XCTestCase, StateMachineBuilder {
// Then
expect(transitionCount).to(equal(2))
}

func testRecursionDetectedError() throws {

var error: TestStateMachine.StateMachineError? = nil

// Given
let stateMachine: TestStateMachine = givenState(is: .stateOne)

stateMachine.startObserving(self) { [unowned stateMachine] _ in
do {
try stateMachine.transition(.eventOne)
} catch let e as TestStateMachine.StateMachineError {
error = e
} catch {}
}

// When
try stateMachine.transition(.eventOne)

// Then
expect(error).to(equal(.recursionDetected))
}
}

final class Logger {
Expand Down

0 comments on commit 0f79642

Please sign in to comment.