| 771 | } |
| 772 | |
| 773 | func TestContextInCallbacks(t *testing.T) { |
| 774 | var fsm *FSM |
| 775 | var enterEndAsyncWorkDone = make(chan struct{}) |
| 776 | fsm = NewFSM( |
| 777 | "start", |
| 778 | Events{ |
| 779 | {Name: "run", Src: []string{"start"}, Dst: "end"}, |
| 780 | {Name: "finish", Src: []string{"end"}, Dst: "finished"}, |
| 781 | {Name: "reset", Src: []string{"end", "finished"}, Dst: "start"}, |
| 782 | }, |
| 783 | Callbacks{ |
| 784 | "enter_end": func(ctx context.Context, e *Event) { |
| 785 | go func() { |
| 786 | <-ctx.Done() |
| 787 | close(enterEndAsyncWorkDone) |
| 788 | }() |
| 789 | |
| 790 | <-ctx.Done() |
| 791 | if err := e.FSM.Event(ctx, "finish"); err != nil { |
| 792 | e.Err = fmt.Errorf("transitioning to the finished state failed: %w", err) |
| 793 | } |
| 794 | }, |
| 795 | }, |
| 796 | ) |
| 797 | |
| 798 | ctx, cancel := context.WithCancel(context.Background()) |
| 799 | go func() { |
| 800 | cancel() |
| 801 | }() |
| 802 | err := fsm.Event(ctx, "run") |
| 803 | if !errors.Is(err, context.Canceled) { |
| 804 | t.Errorf("expected 'context canceled' error, got %v", err) |
| 805 | } |
| 806 | <-enterEndAsyncWorkDone |
| 807 | |
| 808 | currentState := fsm.Current() |
| 809 | if currentState != "end" { |
| 810 | t.Errorf("expected state to be 'end', was '%s'", currentState) |
| 811 | } |
| 812 | } |
| 813 | |
| 814 | func TestNoTransition(t *testing.T) { |
| 815 | fsm := NewFSM( |