diff --git a/processor.go b/processor.go index eacefb7..8d2c0f1 100644 --- a/processor.go +++ b/processor.go @@ -93,16 +93,6 @@ func (p *Processor[AC, OC, JC]) init() error { return nil } - // validate the states - for _, s := range p.states { - if !s.Terminal && s.Exec == nil { - return fmt.Errorf("State %s is non-terminal but has no Exec function", s.TriggerState) - } - if !s.Terminal && p.ValidateExitStates && len(s.ExitStates) == 0 { - return fmt.Errorf("ValidateExitStates: invalid State machine, state %s is non-terminal but has no ExitStates", s.TriggerState) - } - } - if p.serializer == nil { p.serializer = &NilSerializer[OC, JC]{} } @@ -120,6 +110,26 @@ func (p *Processor[AC, OC, JC]) init() error { p.stateNames = append(p.stateNames, k) } + // validate the states + for _, s := range p.states { + if !s.Terminal && s.Exec == nil { + return fmt.Errorf("State %s is non-terminal but has no Exec function", s.TriggerState) + } + if p.ValidateExitStates { + if s.Terminal { + continue + } + if len(s.ExitStates) == 0 { + return fmt.Errorf("ValidateExitStates: invalid State machine, state %s is non-terminal but has no ExitStates", s.TriggerState) + } + for _, exit := range s.ExitStates { + if _, ok := p.stateMap[exit]; !ok { + return fmt.Errorf("invalid exit state [%s] for state %s", exit, s.TriggerState) + } + } + } + } + // For each state, we need a channel of jobs p.stateChan = map[string]chan Job[JC]{} diff --git a/processor_test.go b/processor_test.go index b997147..a52d3e1 100644 --- a/processor_test.go +++ b/processor_test.go @@ -741,6 +741,10 @@ func TestProcessor_NonTerminal_NoExitFunction(t *testing.T) { require.ErrorContains(t, err, fmt.Sprintf("State %s is non-terminal but has no Exec function", TRIGGER_STATE_NEW)) } +func TestProcessor_ValidExitStates_ContainingSelf_CantBeOnlyState(t *testing.T) { + t.Fatal("NYI") +} + func TestProcessor_ValidateExitStates_InvalidExit(t *testing.T) { t.Parallel() uknownState := "UNKNOWN_EXIT_STATE" @@ -751,11 +755,7 @@ func TestProcessor_ValidateExitStates_InvalidExit(t *testing.T) { return jc, uknownState, nil, nil }, Terminal: false, - ExitStates: []string{TRIGGER_STATE_NEW}, - }, - { - TriggerState: uknownState, - Terminal: true, + ExitStates: []string{uknownState}, }, } p := NewProcessor[MyAppContext, MyOverallContext, MyJobContext](MyAppContext{}, states, nil, nil)