github.com/Jeffail/benthos/v3@v3.65.0/lib/input/reader/async_bundle_unacks_test.go (about) 1 package reader 2 3 import ( 4 "context" 5 "errors" 6 "reflect" 7 "sync" 8 "testing" 9 "time" 10 11 "github.com/Jeffail/benthos/v3/lib/message" 12 "github.com/Jeffail/benthos/v3/lib/response" 13 "github.com/Jeffail/benthos/v3/lib/types" 14 ) 15 16 //------------------------------------------------------------------------------ 17 18 func TestAsyncBundleUnacksClose(t *testing.T) { 19 t.Parallel() 20 21 ctx, cancel := context.WithTimeout(context.Background(), time.Second*2) 22 defer cancel() 23 24 readerImpl := newMockAsyncReader() 25 pres := NewAsyncBundleUnacks(readerImpl) 26 27 exp := errors.New("foo error") 28 29 wg := sync.WaitGroup{} 30 wg.Add(1) 31 32 go func() { 33 if err := pres.ConnectWithContext(ctx); err != nil { 34 t.Error(err) 35 } 36 pres.CloseAsync() 37 if act := pres.WaitForClose(time.Second); act != exp { 38 t.Errorf("Wrong error returned: %v != %v", act, exp) 39 } 40 wg.Done() 41 }() 42 43 select { 44 case readerImpl.connChan <- nil: 45 case <-time.After(time.Second): 46 t.Error("Timed out") 47 } 48 49 select { 50 case readerImpl.closeAsyncChan <- struct{}{}: 51 case <-time.After(time.Second): 52 t.Error("Timed out") 53 } 54 55 select { 56 case readerImpl.waitForCloseChan <- exp: 57 case <-time.After(time.Second): 58 t.Error("Timed out") 59 } 60 61 wg.Wait() 62 } 63 64 func TestAsyncBundleUnacksBasic(t *testing.T) { 65 t.Parallel() 66 67 ctx, cancel := context.WithTimeout(context.Background(), time.Second*2) 68 defer cancel() 69 70 readerImpl := newMockAsyncReader() 71 pres := NewAsyncBundleUnacks(readerImpl) 72 73 expMsgs := [][]byte{ 74 []byte("foo"), 75 []byte("bar"), 76 } 77 78 go func() { 79 select { 80 case readerImpl.connChan <- nil: 81 case <-time.After(time.Second): 82 t.Error("Timed out") 83 } 84 for _, p := range expMsgs { 85 readerImpl.msgsToSnd = []types.Message{message.New([][]byte{p})} 86 select { 87 case readerImpl.readChan <- nil: 88 case <-time.After(time.Second): 89 t.Error("Timed out") 90 } 91 select { 92 case readerImpl.ackChan <- nil: 93 case <-time.After(time.Second): 94 t.Error("Timed out") 95 } 96 } 97 }() 98 99 if err := pres.ConnectWithContext(ctx); err != nil { 100 t.Error(err) 101 } 102 103 msg, ackFn, err := pres.ReadWithContext(ctx) 104 if err != nil { 105 t.Fatal(err) 106 } 107 if act, exp := msg.Get(0).Get(), expMsgs[0]; !reflect.DeepEqual(act, exp) { 108 t.Errorf("Wrong message returned: %s != %s", act, exp) 109 } 110 if err := ackFn(ctx, response.NewAck()); err != nil { 111 t.Error(err) 112 } 113 114 msg, ackFn, err = pres.ReadWithContext(ctx) 115 if err != nil { 116 t.Fatal(err) 117 } 118 if act, exp := msg.Get(0).Get(), expMsgs[1]; !reflect.DeepEqual(act, exp) { 119 t.Errorf("Wrong message returned: %s != %s", act, exp) 120 } 121 if err := ackFn(ctx, response.NewAck()); err != nil { 122 t.Error(err) 123 } 124 125 if exp, act := []error{nil, nil}, readerImpl.ackRcvd; !reflect.DeepEqual(exp, act) { 126 t.Errorf("Wrong acks returned: %v != %v", act, exp) 127 } 128 } 129 130 func TestAsyncBundleUnacksHappy(t *testing.T) { 131 t.Parallel() 132 133 ctx, cancel := context.WithTimeout(context.Background(), time.Second*2) 134 defer cancel() 135 136 readerImpl := newMockAsyncReader() 137 pres := NewAsyncBundleUnacks(readerImpl) 138 139 expMsgs := [][]byte{ 140 []byte("foo"), 141 []byte("bar"), 142 } 143 for _, p := range expMsgs { 144 readerImpl.msgsToSnd = append(readerImpl.msgsToSnd, message.New([][]byte{p})) 145 } 146 147 go func() { 148 select { 149 case readerImpl.connChan <- nil: 150 case <-time.After(time.Second): 151 t.Error("Timed out") 152 } 153 for range expMsgs { 154 select { 155 case readerImpl.readChan <- nil: 156 case <-time.After(time.Second): 157 t.Error("Timed out") 158 } 159 } 160 for range expMsgs { 161 select { 162 case readerImpl.ackChan <- nil: 163 case <-time.After(time.Second): 164 t.Error("Timed out") 165 } 166 } 167 }() 168 169 if err := pres.ConnectWithContext(ctx); err != nil { 170 t.Error(err) 171 } 172 173 msg, ackFn, err := pres.ReadWithContext(ctx) 174 if err != nil { 175 t.Fatal(err) 176 } 177 if act, exp := msg.Get(0).Get(), expMsgs[0]; !reflect.DeepEqual(act, exp) { 178 t.Errorf("Wrong message returned: %s != %s", act, exp) 179 } 180 if err := ackFn(ctx, response.NewUnack()); err != nil { 181 t.Error(err) 182 } 183 184 msg, ackFn, err = pres.ReadWithContext(ctx) 185 if err != nil { 186 t.Fatal(err) 187 } 188 if act, exp := msg.Get(0).Get(), expMsgs[1]; !reflect.DeepEqual(act, exp) { 189 t.Errorf("Wrong message returned: %s != %s", act, exp) 190 } 191 if err := ackFn(ctx, response.NewAck()); err != nil { 192 t.Error(err) 193 } 194 195 if exp, act := []error{nil, nil}, readerImpl.ackRcvd; !reflect.DeepEqual(exp, act) { 196 t.Errorf("Wrong acks returned: %v != %v", act, exp) 197 } 198 } 199 200 func TestAsyncBundleUnacksSad(t *testing.T) { 201 t.Parallel() 202 203 ctx, cancel := context.WithTimeout(context.Background(), time.Second*2) 204 defer cancel() 205 206 readerImpl := newMockAsyncReader() 207 pres := NewAsyncBundleUnacks(readerImpl) 208 209 expMsgs := [][]byte{ 210 []byte("foo"), 211 []byte("bar"), 212 } 213 for _, p := range expMsgs { 214 readerImpl.msgsToSnd = append(readerImpl.msgsToSnd, message.New([][]byte{p})) 215 } 216 217 go func() { 218 select { 219 case readerImpl.connChan <- nil: 220 case <-time.After(time.Second): 221 t.Error("Timed out") 222 } 223 for range expMsgs { 224 select { 225 case readerImpl.readChan <- nil: 226 case <-time.After(time.Second): 227 t.Error("Timed out") 228 } 229 } 230 for range expMsgs { 231 select { 232 case readerImpl.ackChan <- nil: 233 case <-time.After(time.Second): 234 t.Error("Timed out") 235 } 236 } 237 }() 238 239 if err := pres.ConnectWithContext(ctx); err != nil { 240 t.Error(err) 241 } 242 243 msg, ackFn, err := pres.ReadWithContext(ctx) 244 if err != nil { 245 t.Fatal(err) 246 } 247 if act, exp := msg.Get(0).Get(), expMsgs[0]; !reflect.DeepEqual(act, exp) { 248 t.Errorf("Wrong message returned: %s != %s", act, exp) 249 } 250 if err := ackFn(ctx, response.NewUnack()); err != nil { 251 t.Error(err) 252 } 253 254 errTest := errors.New("test error") 255 256 msg, ackFn, err = pres.ReadWithContext(ctx) 257 if err != nil { 258 t.Fatal(err) 259 } 260 if act, exp := msg.Get(0).Get(), expMsgs[1]; !reflect.DeepEqual(act, exp) { 261 t.Errorf("Wrong message returned: %s != %s", act, exp) 262 } 263 if err := ackFn(ctx, response.NewError(errTest)); err != nil { 264 t.Error(err) 265 } 266 267 if exp, act := []error{errTest, errTest}, readerImpl.ackRcvd; !reflect.DeepEqual(exp, act) { 268 t.Errorf("Wrong acks returned: %v != %v", act, exp) 269 } 270 } 271 272 func TestAsyncBundleUnacksSadTwo(t *testing.T) { 273 t.Parallel() 274 275 ctx, cancel := context.WithTimeout(context.Background(), time.Second*2) 276 defer cancel() 277 278 readerImpl := newMockAsyncReader() 279 pres := NewAsyncBundleUnacks(readerImpl) 280 281 expMsgs := [][]byte{ 282 []byte("foo"), 283 []byte("bar"), 284 } 285 for _, p := range expMsgs { 286 readerImpl.msgsToSnd = append(readerImpl.msgsToSnd, message.New([][]byte{p})) 287 } 288 289 errFirstAck := errors.New("error returned by first ack") 290 errSecondAck := errors.New("error returned by second ack") 291 292 go func() { 293 select { 294 case readerImpl.connChan <- nil: 295 case <-time.After(time.Second): 296 t.Error("Timed out") 297 } 298 for range expMsgs { 299 select { 300 case readerImpl.readChan <- nil: 301 case <-time.After(time.Second): 302 t.Error("Timed out") 303 } 304 } 305 select { 306 case readerImpl.ackChan <- errFirstAck: 307 case <-time.After(time.Second): 308 t.Error("Timed out") 309 } 310 select { 311 case readerImpl.ackChan <- errSecondAck: 312 case <-time.After(time.Second): 313 t.Error("Timed out") 314 } 315 }() 316 317 if err := pres.ConnectWithContext(ctx); err != nil { 318 t.Error(err) 319 } 320 321 msg, ackFn, err := pres.ReadWithContext(ctx) 322 if err != nil { 323 t.Fatal(err) 324 } 325 if act, exp := msg.Get(0).Get(), expMsgs[0]; !reflect.DeepEqual(act, exp) { 326 t.Errorf("Wrong message returned: %s != %s", act, exp) 327 } 328 if err := ackFn(ctx, response.NewUnack()); err != nil { 329 t.Error(err) 330 } 331 332 errTest := errors.New("test error") 333 334 msg, ackFn, err = pres.ReadWithContext(ctx) 335 if err != nil { 336 t.Fatal(err) 337 } 338 if act, exp := msg.Get(0).Get(), expMsgs[1]; !reflect.DeepEqual(act, exp) { 339 t.Errorf("Wrong message returned: %s != %s", act, exp) 340 } 341 if act, exp := ackFn(ctx, response.NewError(errTest)).Error(), "failed to send grouped acknowledgements: [error returned by first ack error returned by second ack]"; act != exp { 342 t.Errorf("Wrong error returned: %v != %v", act, exp) 343 } 344 345 if exp, act := []error{errTest, errTest}, readerImpl.ackRcvd; !reflect.DeepEqual(exp, act) { 346 t.Errorf("Wrong acks returned: %v != %v", act, exp) 347 } 348 } 349 350 func TestAsyncBundleUnacksSadThree(t *testing.T) { 351 t.Parallel() 352 353 ctx, cancel := context.WithTimeout(context.Background(), time.Second*2) 354 defer cancel() 355 356 readerImpl := newMockAsyncReader() 357 pres := NewAsyncBundleUnacks(readerImpl) 358 359 expMsgs := [][]byte{ 360 []byte("foo"), 361 []byte("bar"), 362 } 363 for _, p := range expMsgs { 364 readerImpl.msgsToSnd = append(readerImpl.msgsToSnd, message.New([][]byte{p})) 365 } 366 367 errFirstAck := errors.New("error returned by first ack") 368 369 go func() { 370 select { 371 case readerImpl.connChan <- nil: 372 case <-time.After(time.Second): 373 t.Error("Timed out") 374 } 375 for range expMsgs { 376 select { 377 case readerImpl.readChan <- nil: 378 case <-time.After(time.Second): 379 t.Error("Timed out") 380 } 381 } 382 select { 383 case readerImpl.ackChan <- nil: 384 case <-time.After(time.Second): 385 t.Error("Timed out") 386 } 387 select { 388 case readerImpl.ackChan <- errFirstAck: 389 case <-time.After(time.Second): 390 t.Error("Timed out") 391 } 392 }() 393 394 if err := pres.ConnectWithContext(ctx); err != nil { 395 t.Error(err) 396 } 397 398 msg, ackFn, err := pres.ReadWithContext(ctx) 399 if err != nil { 400 t.Fatal(err) 401 } 402 if act, exp := msg.Get(0).Get(), expMsgs[0]; !reflect.DeepEqual(act, exp) { 403 t.Errorf("Wrong message returned: %s != %s", act, exp) 404 } 405 if err := ackFn(ctx, response.NewUnack()); err != nil { 406 t.Error(err) 407 } 408 409 errTest := errors.New("test error") 410 411 msg, ackFn, err = pres.ReadWithContext(ctx) 412 if err != nil { 413 t.Fatal(err) 414 } 415 if act, exp := msg.Get(0).Get(), expMsgs[1]; !reflect.DeepEqual(act, exp) { 416 t.Errorf("Wrong message returned: %s != %s", act, exp) 417 } 418 if act, exp := ackFn(ctx, response.NewError(errTest)).Error(), "error returned by first ack"; act != exp { 419 t.Errorf("Wrong error returned: %v != %v", act, exp) 420 } 421 422 if exp, act := []error{errTest, errTest}, readerImpl.ackRcvd; !reflect.DeepEqual(exp, act) { 423 t.Errorf("Wrong acks returned: %v != %v", act, exp) 424 } 425 } 426 427 //------------------------------------------------------------------------------