github.com/Jeffail/benthos/v3@v3.65.0/lib/buffer/parallel_wrapper_test.go (about) 1 package buffer 2 3 import ( 4 "testing" 5 "time" 6 7 "github.com/Jeffail/benthos/v3/lib/buffer/parallel" 8 "github.com/Jeffail/benthos/v3/lib/log" 9 "github.com/Jeffail/benthos/v3/lib/message" 10 "github.com/Jeffail/benthos/v3/lib/metrics" 11 "github.com/Jeffail/benthos/v3/lib/response" 12 "github.com/Jeffail/benthos/v3/lib/types" 13 ) 14 15 //------------------------------------------------------------------------------ 16 17 func TestParallelMemoryBuffer(t *testing.T) { 18 var incr, total uint8 = 100, 50 19 20 tChan := make(chan types.Transaction) 21 resChan := make(chan types.Response) 22 23 conf := NewConfig() 24 b := NewParallelWrapper( 25 conf, parallel.NewMemory(int(incr)*int(total)), 26 log.Noop(), metrics.Noop(), 27 ) 28 if err := b.Consume(tChan); err != nil { 29 t.Fatal(err) 30 } 31 32 var i uint8 33 34 // Check correct flow no blocking 35 for ; i < total; i++ { 36 msgBytes := make([][]byte, 1) 37 msgBytes[0] = make([]byte, int(incr)) 38 msgBytes[0][0] = i 39 40 select { 41 // Send to buffer 42 case tChan <- types.NewTransaction(message.New(msgBytes), resChan): 43 case <-time.After(time.Second): 44 t.Errorf("Timed out waiting for unbuffered message %v send", i) 45 return 46 } 47 48 // Instant response from buffer 49 select { 50 case res := <-resChan: 51 if res.Error() != nil { 52 t.Error(res.Error()) 53 } 54 case <-time.After(time.Second): 55 t.Errorf("Timed out waiting for unbuffered message %v response", i) 56 return 57 } 58 59 // Receive on output 60 var outTr types.Transaction 61 select { 62 case outTr = <-b.TransactionChan(): 63 if actual := outTr.Payload.Get(0).Get()[0]; actual != i { 64 t.Errorf("Wrong order receipt of unbuffered message receive: %v != %v", actual, i) 65 } 66 case <-time.After(time.Second): 67 t.Errorf("Timed out waiting for unbuffered message %v read", i) 68 return 69 } 70 71 // Response from output 72 select { 73 case outTr.ResponseChan <- response.NewAck(): 74 case <-time.After(time.Second): 75 t.Errorf("Timed out waiting for unbuffered response send back %v", i) 76 return 77 } 78 } 79 80 for i = 0; i < total; i++ { 81 msgBytes := make([][]byte, 1) 82 msgBytes[0] = make([]byte, int(incr)) 83 msgBytes[0][0] = i 84 85 select { 86 case tChan <- types.NewTransaction(message.New(msgBytes), resChan): 87 case <-time.After(time.Second): 88 t.Errorf("Timed out waiting for buffered message %v send", i) 89 return 90 } 91 select { 92 case res := <-resChan: 93 if res.Error() != nil { 94 t.Error(res.Error()) 95 } 96 case <-time.After(time.Second): 97 t.Errorf("Timed out waiting for buffered message %v response", i) 98 return 99 } 100 } 101 102 // Should have reached limit here 103 msgBytes := make([][]byte, 1) 104 msgBytes[0] = make([]byte, int(incr)) 105 106 select { 107 case tChan <- types.NewTransaction(message.New(msgBytes), resChan): 108 case <-time.After(time.Second): 109 t.Errorf("Timed out waiting for final buffered message send") 110 return 111 } 112 113 // Response should block until buffer is relieved 114 select { 115 case res := <-resChan: 116 if res.Error() != nil { 117 t.Error(res.Error()) 118 } else { 119 t.Errorf("Overflowed response returned before timeout") 120 } 121 return 122 case <-time.After(100 * time.Millisecond): 123 } 124 125 var outTr types.Transaction 126 127 // Extract last message 128 select { 129 case outTr = <-b.TransactionChan(): 130 if actual := outTr.Payload.Get(0).Get()[0]; actual != 0 { 131 t.Errorf("Wrong order receipt of buffered message receive: %v != %v", actual, 0) 132 } 133 outTr.ResponseChan <- response.NewAck() 134 case <-time.After(time.Second): 135 t.Errorf("Timed out waiting for final buffered message read") 136 return 137 } 138 139 // Response from the last attempt should no longer be blocking 140 select { 141 case res := <-resChan: 142 if res.Error() != nil { 143 t.Error(res.Error()) 144 } 145 case <-time.After(100 * time.Millisecond): 146 t.Errorf("Final buffered response blocked") 147 } 148 149 // Extract all other messages 150 for i = 1; i < total; i++ { 151 select { 152 case outTr = <-b.TransactionChan(): 153 if actual := outTr.Payload.Get(0).Get()[0]; actual != i { 154 t.Errorf("Wrong order receipt of buffered message: %v != %v", actual, i) 155 } 156 case <-time.After(time.Second): 157 t.Errorf("Timed out waiting for buffered message %v read", i) 158 return 159 } 160 161 select { 162 case outTr.ResponseChan <- response.NewAck(): 163 case <-time.After(time.Second): 164 t.Errorf("Timed out waiting for buffered response send back %v", i) 165 return 166 } 167 } 168 169 // Get final message 170 select { 171 case outTr = <-b.TransactionChan(): 172 case <-time.After(time.Second): 173 t.Errorf("Timed out waiting for buffered message %v read", i) 174 return 175 } 176 177 select { 178 case outTr.ResponseChan <- response.NewAck(): 179 case <-time.After(time.Second): 180 t.Errorf("Timed out waiting for buffered response send back %v", i) 181 return 182 } 183 184 b.CloseAsync() 185 b.WaitForClose(time.Second) 186 187 close(resChan) 188 close(tChan) 189 } 190 191 func TestParallelBufferClosing(t *testing.T) { 192 var incr, total uint8 = 100, 5 193 194 tChan := make(chan types.Transaction) 195 resChan := make(chan types.Response) 196 197 conf := NewConfig() 198 b := NewParallelWrapper( 199 conf, parallel.NewMemory(int(incr)*int(total)), 200 log.Noop(), metrics.Noop(), 201 ) 202 if err := b.Consume(tChan); err != nil { 203 t.Fatal(err) 204 } 205 206 var i uint8 207 208 // Populate buffer with some messages 209 for i = 0; i < total; i++ { 210 msgBytes := make([][]byte, 1) 211 msgBytes[0] = make([]byte, int(incr)) 212 msgBytes[0][0] = i 213 214 select { 215 case tChan <- types.NewTransaction(message.New(msgBytes), resChan): 216 case <-time.After(time.Second): 217 t.Errorf("Timed out waiting for buffered message %v send", i) 218 return 219 } 220 select { 221 case res := <-resChan: 222 if res.Error() != nil { 223 t.Error(res.Error()) 224 } 225 case <-time.After(time.Second): 226 t.Errorf("Timed out waiting for buffered message %v response", i) 227 return 228 } 229 } 230 231 // Close input, this should prompt the stack buffer to CloseOnceEmpty(). 232 close(tChan) 233 234 // Receive all of those messages from the buffer 235 for i = 0; i < total; i++ { 236 select { 237 case val := <-b.TransactionChan(): 238 if actual := val.Payload.Get(0).Get()[0]; actual != i { 239 t.Errorf("Wrong order receipt of buffered message receive: %v != %v", actual, i) 240 } 241 val.ResponseChan <- response.NewAck() 242 case <-time.After(time.Second): 243 t.Errorf("Timed out waiting for final buffered message read") 244 return 245 } 246 } 247 248 // The buffer should now be closed, therefore so should our read channel. 249 select { 250 case _, open := <-b.TransactionChan(): 251 if open { 252 t.Error("Reader channel still open after clearing buffer") 253 } 254 case <-time.After(time.Second): 255 t.Errorf("Timed out waiting for final buffered message read") 256 return 257 } 258 259 // Should already be shut down. 260 b.WaitForClose(time.Second) 261 } 262 263 func BenchmarkParallelMem(b *testing.B) { 264 tChan := make(chan types.Transaction) 265 resChan := make(chan types.Response) 266 267 conf := NewConfig() 268 buffer := NewParallelWrapper( 269 conf, parallel.NewMemory(50000000), 270 log.Noop(), metrics.Noop(), 271 ) 272 if err := buffer.Consume(tChan); err != nil { 273 b.Fatal(err) 274 } 275 276 contents := [][]byte{ 277 make([]byte, 1024*1024*1), 278 } 279 280 b.ReportAllocs() 281 b.ResetTimer() 282 for i := 0; i < b.N; i++ { 283 select { 284 case tChan <- types.NewTransaction(message.New(contents), resChan): 285 case <-time.After(time.Second): 286 b.Errorf("Timed out waiting for buffered message %v send", i) 287 return 288 } 289 select { 290 case res := <-resChan: 291 if res.Error() != nil { 292 b.Error(res.Error()) 293 } 294 case <-time.After(time.Second): 295 b.Errorf("Timed out waiting for buffered message %v response", i) 296 return 297 } 298 299 select { 300 case val := <-buffer.TransactionChan(): 301 val.ResponseChan <- response.NewAck() 302 case <-time.After(time.Second): 303 b.Errorf("Timed out waiting for final buffered message read") 304 return 305 } 306 } 307 b.StopTimer() 308 309 buffer.CloseAsync() 310 buffer.WaitForClose(time.Second) 311 } 312 313 //------------------------------------------------------------------------------