github.com/voedger/voedger@v0.0.0-20240520144910-273e84102129/pkg/pipeline/async_test.go (about) 1 // Copyright (c) 2021-present Voedger Authors. 2 // This source code is licensed under the MIT license found in the 3 // LICENSE file in the root directory of this source tree. 4 5 package pipeline 6 7 import ( 8 "context" 9 "errors" 10 "sync" 11 "testing" 12 "time" 13 14 "github.com/stretchr/testify/require" 15 ) 16 17 func Test_p_release(t *testing.T) { 18 t.Run("Should release workpiece", func(t *testing.T) { 19 release := false 20 21 p_release(testWorkpiece{func() { 22 release = true 23 }}) 24 25 require.True(t, release) 26 }) 27 t.Run("Should not release workpiece because workpiece is nil", func(t *testing.T) { 28 release := false 29 30 p_release(nil) 31 32 require.False(t, release) 33 }) 34 } 35 36 func Test_p_flush(t *testing.T) { 37 testErr := errors.New("error occurred") 38 t.Run("Should flush", func(t *testing.T) { 39 operator := WireAsyncOperator("operator", mockAsyncOp(). 40 flush(func(callback OpFuncFlush) (err error) { 41 callback(testWorkpiece{}) 42 return nil 43 }).create()) 44 operator.ctx = context.Background() 45 46 p_flush(operator, "test") 47 48 require.Len(t, operator.Stdout, 1) 49 require.Equal(t, testWorkpiece{}, <-operator.Stdout) 50 }) 51 t.Run("Should no flush by error reason", func(t *testing.T) { 52 operator := WireAsyncOperator("operator", mockAsyncOp(). 53 flush(func(callback OpFuncFlush) (err error) { 54 return testErr 55 }).create()) 56 operator.ctx = context.Background() 57 58 p_flush(operator, "test") 59 60 require.Len(t, operator.Stdout, 1) 61 err := <-operator.Stdout 62 require.ErrorIs(t, err.(*errPipeline), testErr) 63 }) 64 t.Run("Should no flush by error in ctx reason", func(t *testing.T) { 65 operator := WireAsyncOperator("operator", mockAsyncOp(). 66 flush(func(callback OpFuncFlush) (err error) { 67 callback(testWorkpiece{}) 68 return nil 69 }).create()) 70 operator.ctx = testContext{err: testErr} 71 72 p_flush(operator, "test") 73 74 require.Empty(t, operator.Stdout) 75 }) 76 } 77 78 func Test_flushTimer_stop(t *testing.T) { 79 flushTimer := flushTimer{ 80 active: true, 81 timer: time.NewTimer(time.Millisecond), 82 } 83 time.Sleep(time.Duration(2) * time.Millisecond) 84 85 require.NotPanics(t, func() { 86 flushTimer.stop() 87 }) 88 } 89 90 func Test_puller_async(t *testing.T) { 91 t.Run("Should release workpiece and continue when wired operator isn not active", func(t *testing.T) { 92 release := false 93 doAsync := false 94 wg := new(sync.WaitGroup) 95 wg.Add(1) 96 work := testWorkpiece{func() { 97 release = true 98 wg.Done() 99 }} 100 operator := &WiredOperator{ 101 Operator: mockAsyncOp().doAsync(func(ctx context.Context, work IWorkpiece) (outWork IWorkpiece, err error) { 102 doAsync = true 103 return nil, err 104 }).create(), 105 Stdin: make(chan interface{}, 1), 106 Stdout: make(chan interface{}, 1), 107 ctx: context.Background(), 108 err: errPipeline{}, 109 } 110 go puller_async(operator) 111 operator.Stdin <- work 112 wg.Wait() 113 close(operator.Stdout) 114 115 require.True(t, release) 116 require.False(t, doAsync) 117 }) 118 t.Run("Should forward error and continue", func(t *testing.T) { 119 doAsync := false 120 operator := &WiredOperator{ 121 Operator: mockAsyncOp().doAsync(func(ctx context.Context, work IWorkpiece) (outWork IWorkpiece, err error) { 122 doAsync = true 123 return nil, err 124 }).create(), 125 Stdin: make(chan interface{}, 1), 126 Stdout: make(chan interface{}, 1), 127 ctx: context.Background(), 128 } 129 go puller_async(operator) 130 operator.Stdin <- errPipeline{} 131 err := <-operator.Stdout 132 close(operator.Stdout) 133 134 require.Equal(t, errPipeline{}, err) 135 require.False(t, doAsync) 136 }) 137 t.Run("Should send error when error occurred at doAsync method", func(t *testing.T) { 138 doAsync := false 139 operator := &WiredOperator{ 140 Operator: mockAsyncOp(). 141 doAsync(func(ctx context.Context, work IWorkpiece) (outWork IWorkpiece, err error) { 142 doAsync = true 143 return nil, errors.New("boom") 144 }).create(), 145 Stdin: make(chan interface{}, 1), 146 Stdout: make(chan interface{}, 1), 147 ctx: context.Background(), 148 } 149 go puller_async(operator) 150 operator.Stdin <- testWorkpiece{} 151 err := <-operator.Stdout 152 close(operator.Stdout) 153 154 require.IsType(t, new(errPipeline), err) 155 require.True(t, doAsync) 156 }) 157 }