package v2 import ( "fmt" "testing" "time" "github.com/stretchr/testify/assert" ) type eventA struct { priorityNormal } var errDone = fmt.Errorf("done") func simpleHandler(event Event) (Event, error) { if _, ok := event.(eventA); ok { return noOp, errDone } return noOp, nil } func TestRoutineFinal(t *testing.T) { var ( bufferSize = 10 routine = newRoutine("simpleRoutine", simpleHandler, bufferSize) ) assert.False(t, routine.isRunning(), "expected an initialized routine to not be running") go routine.start() <-routine.ready() assert.True(t, routine.isRunning(), "expected an started routine") assert.True(t, routine.send(eventA{}), "expected sending to a ready routine to succeed") assert.Equal(t, errDone, <-routine.final(), "expected the final event to be done") assert.False(t, routine.isRunning(), "expected an completed routine to no longer be running") } func TestRoutineStop(t *testing.T) { var ( bufferSize = 10 routine = newRoutine("simpleRoutine", simpleHandler, bufferSize) ) assert.False(t, routine.send(eventA{}), "expected sending to an unstarted routine to fail") go routine.start() <-routine.ready() assert.True(t, routine.send(eventA{}), "expected sending to a running routine to succeed") routine.stop() assert.False(t, routine.send(eventA{}), "expected sending to a stopped routine to fail") } type finalCount struct { count int } func (f finalCount) Error() string { return "end" } func genStatefulHandler(maxCount int) handleFunc { counter := 0 return func(event Event) (Event, error) { if _, ok := event.(eventA); ok { counter++ if counter >= maxCount { return noOp, finalCount{counter} } return eventA{}, nil } return noOp, nil } } func feedback(r *Routine) { for event := range r.next() { r.send(event) } } func TestStatefulRoutine(t *testing.T) { var ( count = 10 handler = genStatefulHandler(count) bufferSize = 20 routine = newRoutine("statefulRoutine", handler, bufferSize) ) go routine.start() go feedback(routine) <-routine.ready() assert.True(t, routine.send(eventA{}), "expected sending to a started routine to succeed") final := <-routine.final() if fnl, ok := final.(finalCount); ok { assert.Equal(t, count, fnl.count, "expected the routine to count to 10") } else { t.Fail() } } type lowPriorityEvent struct { priorityLow } type highPriorityEvent struct { priorityHigh } func handleWithPriority(event Event) (Event, error) { switch event.(type) { case lowPriorityEvent: return noOp, nil case highPriorityEvent: return noOp, errDone } return noOp, nil } func TestPriority(t *testing.T) { var ( bufferSize = 20 routine = newRoutine("priorityRoutine", handleWithPriority, bufferSize) ) go routine.start() <-routine.ready() go func() { for { routine.send(lowPriorityEvent{}) time.Sleep(1 * time.Millisecond) } }() time.Sleep(10 * time.Millisecond) assert.True(t, routine.isRunning(), "expected an started routine") assert.True(t, routine.send(highPriorityEvent{}), "expected send to succeed even when saturated") assert.Equal(t, errDone, <-routine.final()) assert.False(t, routine.isRunning(), "expected an started routine") }