github.com/cmd-stream/base-go@v0.0.0-20230813145615-dd6ac24c16f5/client/client_test.go (about) 1 package client 2 3 import ( 4 "errors" 5 "fmt" 6 "net" 7 "sync" 8 "testing" 9 "time" 10 11 "github.com/cmd-stream/base-go" 12 "github.com/cmd-stream/base-go/testdata/mock" 13 "github.com/ymz-ncnk/mok" 14 ) 15 16 const Delta = 100 * time.Millisecond 17 18 func TestClient(t *testing.T) { 19 20 t.Run("We should be able to send cmd and receive several results", 21 func(t *testing.T) { 22 var ( 23 wantSeq base.Seq = 1 24 wantCmd = mock.NewCmd() 25 wantResult1 = mock.NewResult().RegisterLastOne( 26 func() (lastOne bool) { return false }, 27 ) 28 wantResult2 = mock.NewResult().RegisterLastOne( 29 func() (lastOne bool) { return true }, 30 ) 31 delegate = func() (delegate mock.ClientDelegate) { 32 receive := make(chan struct{}) 33 delegate = mock.NewClientDelegate().RegisterSend( 34 func(seq base.Seq, cmd base.Cmd[any]) (err error) { 35 defer close(receive) 36 if seq != wantSeq { 37 return fmt.Errorf("unexpected seq, want '%v' actual '%v'", 38 wantSeq, 39 seq) 40 } 41 if cmd != wantCmd { 42 return fmt.Errorf("unexpected cmd, want '%v' actual '%v'", 43 wantCmd, 44 cmd) 45 } 46 return 47 }, 48 ).RegisterFlush(func() (err error) { 49 return nil 50 }).RegisterReceive( 51 func() (seq base.Seq, result base.Result, err error) { 52 <-receive 53 return wantSeq, wantResult1, nil 54 }, 55 ).RegisterReceive( 56 func() (seq base.Seq, result base.Result, err error) { 57 return wantSeq, wantResult2, nil 58 }, 59 ).RegisterReceive( 60 func() (seq base.Seq, result base.Result, err error) { 61 err = errors.New("done error") 62 return 63 }, 64 ).RegisterClose( 65 func() (err error) { return nil }, 66 ) 67 return 68 }() 69 mocks = []*mok.Mock{wantCmd.Mock, wantResult1.Mock, wantResult2.Mock, 70 delegate.Mock} 71 client = New[any](delegate, nil) 72 results = make(chan base.AsyncResult, 2) 73 ) 74 seq, err := client.Send(wantCmd, results) 75 if err != nil { 76 t.Errorf("unexpected error, watn '%v' actual %v", nil, err) 77 } 78 if seq != wantSeq { 79 t.Errorf("unexpected seq, want '%v' actual '%v'", wantSeq, seq) 80 } 81 if !client.Has(seq) { 82 t.Error("cmd was not memorized") 83 } 84 result1 := <-results 85 if result1.Result != wantResult1 { 86 t.Errorf("unexpected result, want '%v' actual '%v'", wantResult1, 87 result1) 88 } 89 result2 := <-results 90 if result2.Result != wantResult2 { 91 t.Errorf("unexpected result, want '%v' actual '%v'", wantResult2, 92 result2.Result) 93 } 94 if infomap := mok.CheckCalls(mocks); len(infomap) > 0 { 95 t.Error(infomap) 96 } 97 }) 98 99 t.Run("When the client receives the last one result it should forget cmd", 100 func(t *testing.T) { 101 var ( 102 done = make(chan struct{}) 103 wantCmd = mock.NewCmd() 104 wantResult1 = mock.NewResult().RegisterLastOne( 105 func() (lastOne bool) { return true }, 106 ) 107 wantResult2 = mock.NewResult().RegisterLastOne( 108 func() (lastOne bool) { return true }, 109 ) 110 delegate = func() (delegate mock.ClientDelegate) { 111 receive := make(chan struct{}) 112 delegate = mock.NewClientDelegate().RegisterSend( 113 func(seq base.Seq, cmd base.Cmd[any]) (err error) { 114 defer close(receive) 115 return 116 }, 117 ).RegisterFlush( 118 func() (err error) { return nil }, 119 ).RegisterReceive( 120 func() (seq base.Seq, result base.Result, err error) { 121 <-receive 122 return 1, wantResult1, nil 123 }, 124 ).RegisterReceive( 125 func() (seq base.Seq, result base.Result, err error) { 126 return 1, wantResult2, nil 127 }, 128 ).RegisterReceive( 129 func() (seq base.Seq, result base.Result, err error) { 130 err = errors.New("done error") 131 return 132 }, 133 ).RegisterClose( 134 func() (err error) { return nil }, 135 ) 136 return 137 }() 138 mocks = []*mok.Mock{wantCmd.Mock, wantResult1.Mock, wantResult2.Mock, 139 delegate.Mock} 140 callback = func(seq base.Seq, result base.Result) { 141 if result != wantResult2 { 142 t.Errorf("unexpected result, want '%v' actual '%v'", wantResult2, 143 result) 144 } 145 close(done) 146 } 147 client = New[any](delegate, callback) 148 results = make(chan base.AsyncResult, 1) 149 ) 150 client.Send(wantCmd, results) 151 waitDone(done, t) 152 if infomap := mok.CheckCalls(mocks); len(infomap) > 0 { 153 t.Error(infomap) 154 } 155 }) 156 157 t.Run("Send should increment seq", func(t *testing.T) { 158 var ( 159 done = make(chan struct{}) 160 wantSeq1 base.Seq = 1 161 wantSeq2 base.Seq = 2 162 wantCmd1 = mock.NewCmd() 163 wantCmd2 = mock.NewCmd() 164 delegate = func() (delegate mock.ClientDelegate) { 165 receive := make(chan struct{}) 166 delegate = mock.NewClientDelegate().RegisterSend( 167 func(seq base.Seq, cmd base.Cmd[any]) (err error) { 168 if seq != wantSeq1 { 169 t.Errorf("unexpected seq, want '%v' actual '%v'", wantSeq1, seq) 170 } 171 if cmd != wantCmd1 { 172 t.Errorf("unexpected cmd, want '%v' actual '%v'", wantCmd1, cmd) 173 } 174 return 175 }, 176 ).RegisterFlush( 177 func() (err error) { return nil }, 178 ).RegisterSend( 179 func(seq base.Seq, cmd base.Cmd[any]) (err error) { 180 defer close(receive) 181 if seq != wantSeq2 { 182 t.Errorf("unexpected seq, want '%v' actual '%v'", wantSeq1, seq) 183 } 184 if cmd != wantCmd2 { 185 t.Errorf("unexpected cmd, want '%v' actual '%v'", wantCmd2, cmd) 186 } 187 return 188 }, 189 ).RegisterReceive( 190 func() (seq base.Seq, result base.Result, err error) { 191 defer close(done) 192 <-receive 193 err = errors.New("done error") 194 return 195 }, 196 ).RegisterFlush( 197 func() (err error) { return nil }, 198 ).RegisterClose( 199 func() (err error) { return nil }, 200 ) 201 return 202 }() 203 mocks = []*mok.Mock{wantCmd1.Mock, wantCmd2.Mock, delegate.Mock} 204 client = New[any](delegate, nil) 205 ) 206 seq, _ := client.Send(wantCmd1, nil) 207 if seq != wantSeq1 { 208 t.Errorf("unexpected seq, want '%v' actual '%v'", wantSeq1, seq) 209 } 210 seq, _ = client.Send(wantCmd2, nil) 211 if seq != wantSeq2 { 212 t.Errorf("unexpected seq, want '%v' actual '%v'", wantSeq2, seq) 213 } 214 waitDone(done, t) 215 if infomap := mok.CheckCalls(mocks); len(infomap) > 0 { 216 t.Error(infomap) 217 } 218 }) 219 220 t.Run("Send should memorize cmd", func(t *testing.T) { 221 var ( 222 done = make(chan struct{}) 223 delegate = mock.NewClientDelegate().RegisterSend( 224 func(seq base.Seq, cmd base.Cmd[any]) (err error) { 225 return nil 226 }, 227 ).RegisterFlush( 228 func() (err error) { return nil }, 229 ).RegisterReceive( 230 func() (seq base.Seq, result base.Result, err error) { 231 defer close(done) 232 err = errors.New("Delegate.Receive error") 233 return 234 }, 235 ).RegisterClose( 236 func() (err error) { return nil }, 237 ) 238 mocks = []*mok.Mock{delegate.Mock} 239 client = New[any](delegate, nil) 240 ) 241 seq, _ := client.Send(nil, nil) 242 if !client.Has(seq) { 243 t.Error("cmd was not memorized") 244 } 245 waitDone(done, t) 246 if infomap := mok.CheckCalls(mocks); len(infomap) > 0 { 247 t.Error(infomap) 248 } 249 }) 250 251 t.Run("Seq should be incremented even if Send fails", func(t *testing.T) { 252 var ( 253 done = make(chan struct{}) 254 wantSeq base.Seq = 1 255 wantErr = errors.New("Delegate.Send error") 256 delegate = mock.NewClientDelegate().RegisterSend( 257 func(seq base.Seq, cmd base.Cmd[any]) (err error) { 258 return wantErr 259 }, 260 ).RegisterReceive( 261 func() (seq base.Seq, result base.Result, err error) { 262 defer close(done) 263 err = errors.New("Delegate.Receive error") 264 return 265 }, 266 ).RegisterClose( 267 func() (err error) { return nil }, 268 ) 269 mocks = []*mok.Mock{delegate.Mock} 270 client = New[any](delegate, nil) 271 ) 272 seq, err := client.Send(nil, nil) 273 if err != wantErr { 274 t.Errorf("unexpected err, want '%v' actual '%v'", wantErr, err) 275 } 276 if seq != wantSeq { 277 t.Errorf("unexpected seq, want '%v' actual '%v'", wantSeq, seq) 278 } 279 waitDone(done, t) 280 if infomap := mok.CheckCalls(mocks); len(infomap) > 0 { 281 t.Error(infomap) 282 } 283 }) 284 285 t.Run("If Send fails cmd should be forgotten", func(t *testing.T) { 286 var ( 287 done = make(chan struct{}) 288 delegate = mock.NewClientDelegate().RegisterSend( 289 func(seq base.Seq, cmd base.Cmd[any]) (err error) { 290 return errors.New("Delegate.Send error") 291 }, 292 ).RegisterReceive( 293 func() (seq base.Seq, result base.Result, err error) { 294 defer close(done) 295 err = errors.New("Delegate.Receive error") 296 return 297 }, 298 ).RegisterClose( 299 func() (err error) { return nil }, 300 ) 301 mocks = []*mok.Mock{delegate.Mock} 302 client = New[any](delegate, nil) 303 ) 304 seq, _ := client.Send(nil, nil) 305 if client.Has(seq) { 306 t.Error("cmd was not forgotten") 307 } 308 waitDone(done, t) 309 if infomap := mok.CheckCalls(mocks); len(infomap) > 0 { 310 t.Error(infomap) 311 } 312 }) 313 314 t.Run("We should be able to send cmd by SendWithDeadline", func(t *testing.T) { 315 var ( 316 done = make(chan struct{}) 317 wantSeq base.Seq = 1 318 wantDeadline = time.Now() 319 wantCmd = mock.NewCmd() 320 delegate = func() (delegate mock.ClientDelegate) { 321 receive := make(chan struct{}) 322 delegate = mock.NewClientDelegate().RegisterSetSendDeadline( 323 func(deadline time.Time) (err error) { 324 if !SameTime(deadline, wantDeadline) { 325 return fmt.Errorf("unexpected deadline, want '%v' actual '%v'", 326 wantDeadline, 327 deadline) 328 } 329 return nil 330 }, 331 ).RegisterSend( 332 func(seq base.Seq, cmd base.Cmd[any]) (err error) { 333 defer close(receive) 334 if seq != wantSeq { 335 t.Errorf("unexpected seq, want '%v' actual '%v'", wantSeq, seq) 336 } 337 if cmd != wantCmd { 338 t.Errorf("unexpected cmd, want '%v' actual '%v'", wantCmd, cmd) 339 } 340 return 341 }, 342 ).RegisterFlush( 343 func() (err error) { return nil }, 344 ).RegisterReceive( 345 func() (seq base.Seq, result base.Result, err error) { 346 defer close(done) 347 <-receive 348 err = errors.New("done error") 349 return 350 }, 351 ).RegisterClose( 352 func() (err error) { return nil }, 353 ) 354 return 355 }() 356 mocks = []*mok.Mock{wantCmd.Mock, delegate.Mock} 357 client = New[any](delegate, nil) 358 ) 359 seq, err := client.SendWithDeadline(wantDeadline, wantCmd, nil) 360 if err != nil { 361 t.Errorf("unexpected error, want '%v' actual '%v'", nil, err) 362 } 363 if seq != wantSeq { 364 t.Errorf("unexpected seq, want '%v' actual '%v'", wantSeq, seq) 365 } 366 if !client.Has(seq) { 367 t.Error("cmd was not memorized") 368 } 369 waitDone(done, t) 370 if infomap := mok.CheckCalls(mocks); len(infomap) > 0 { 371 t.Error(infomap) 372 } 373 }) 374 375 t.Run("Seq should be incremented even if SendWithDeadline fails", 376 func(t *testing.T) { 377 var ( 378 done = make(chan struct{}) 379 wantSeq base.Seq = 1 380 wantErr = errors.New("Delegate.Send error") 381 delegate = mock.NewClientDelegate().RegisterSetSendDeadline( 382 func(deadline time.Time) (err error) { 383 return wantErr 384 }, 385 ).RegisterReceive( 386 func() (seq base.Seq, result base.Result, err error) { 387 defer close(done) 388 err = errors.New("Delegate.Receive error") 389 return 390 }, 391 ).RegisterClose( 392 func() (err error) { return nil }, 393 ) 394 mocks = []*mok.Mock{delegate.Mock} 395 client = New[any](delegate, nil) 396 ) 397 seq, err := client.SendWithDeadline(time.Time{}, nil, nil) 398 if err != wantErr { 399 t.Errorf("unexpected err, want '%v' actual '%v'", wantErr, err) 400 } 401 if seq != wantSeq { 402 t.Errorf("unexpected seq, want '%v' actual '%v'", wantSeq, seq) 403 } 404 waitDone(done, t) 405 if infomap := mok.CheckCalls(mocks); len(infomap) > 0 { 406 t.Error(infomap) 407 } 408 }) 409 410 t.Run("If Delegate.SetSendDeadline fails with an error, SendWithDeadline should return it", 411 func(t *testing.T) { 412 var ( 413 done = make(chan struct{}) 414 wantErr = errors.New("Delegate.SetSendDeadline error") 415 delegate = mock.NewClientDelegate().RegisterSetSendDeadline( 416 func(deadline time.Time) (err error) { 417 return wantErr 418 }, 419 ).RegisterReceive( 420 func() (seq base.Seq, result base.Result, err error) { 421 defer close(done) 422 err = errors.New("Delegate.Receive error") 423 return 424 }, 425 ).RegisterClose( 426 func() (err error) { return nil }, 427 ) 428 mocks = []*mok.Mock{delegate.Mock} 429 client = New[any](delegate, nil) 430 ) 431 _, err := client.SendWithDeadline(time.Time{}, nil, nil) 432 if err != wantErr { 433 t.Errorf("unexpected error, want '%v' actual '%v'", nil, err) 434 } 435 waitDone(done, t) 436 if infomap := mok.CheckCalls(mocks); len(infomap) > 0 { 437 t.Error(infomap) 438 } 439 }) 440 441 t.Run("If Delegate.Send fails with an error, SendWithDeadline should return it", 442 func(t *testing.T) { 443 var ( 444 done = make(chan struct{}) 445 wantErr = errors.New("Delegate.Send error") 446 delegate = mock.NewClientDelegate().RegisterSetSendDeadline( 447 func(deadline time.Time) (err error) { 448 return nil 449 }, 450 ).RegisterSend( 451 func(seq base.Seq, cmd base.Cmd[any]) (err error) { 452 return wantErr 453 }, 454 ).RegisterReceive( 455 func() (seq base.Seq, result base.Result, err error) { 456 defer close(done) 457 err = errors.New("Delegate.Receive error") 458 return 459 }, 460 ).RegisterClose( 461 func() (err error) { return nil }, 462 ) 463 mocks = []*mok.Mock{delegate.Mock} 464 client = New[any](delegate, nil) 465 ) 466 _, err := client.SendWithDeadline(time.Time{}, nil, nil) 467 if err != wantErr { 468 t.Errorf("unexpected error, want '%v' actual '%v'", nil, err) 469 } 470 waitDone(done, t) 471 if infomap := mok.CheckCalls(mocks); len(infomap) > 0 { 472 t.Error(infomap) 473 } 474 }) 475 476 t.Run("Client should forget cmd, if SendWithDeadline failed, because of Delegate.SetSendDeadline", 477 func(t *testing.T) { 478 var ( 479 done = make(chan struct{}) 480 delegate = mock.NewClientDelegate().RegisterSetSendDeadline( 481 func(deadline time.Time) (err error) { 482 return errors.New("Delegate.SetSendDeadline error") 483 }, 484 ).RegisterReceive( 485 func() (seq base.Seq, result base.Result, err error) { 486 defer close(done) 487 err = errors.New("Delegate.Receive error") 488 return 489 }, 490 ).RegisterClose( 491 func() (err error) { return nil }, 492 ) 493 mocks = []*mok.Mock{delegate.Mock} 494 client = New[any](delegate, nil) 495 ) 496 seq, _ := client.SendWithDeadline(time.Time{}, nil, nil) 497 if client.Has(seq) { 498 t.Error("cmd was not forgotten") 499 } 500 waitDone(done, t) 501 if infomap := mok.CheckCalls(mocks); len(infomap) > 0 { 502 t.Error(infomap) 503 } 504 }) 505 506 t.Run("Client should forget cmd, if SendWithDeadline failed, because of Delegate.Send", 507 func(t *testing.T) { 508 var ( 509 done = make(chan struct{}) 510 delegate = mock.NewClientDelegate().RegisterSetSendDeadline( 511 func(deadline time.Time) (err error) { 512 return nil 513 }, 514 ).RegisterSend( 515 func(seq base.Seq, cmd base.Cmd[any]) (err error) { 516 return errors.New("Delegate.Send error") 517 }, 518 ).RegisterReceive( 519 func() (seq base.Seq, result base.Result, err error) { 520 defer close(done) 521 err = errors.New("Delegate.Receive error") 522 return 523 }, 524 ).RegisterClose( 525 func() (err error) { return nil }, 526 ) 527 mocks = []*mok.Mock{delegate.Mock} 528 client = New[any](delegate, nil) 529 ) 530 seq, _ := client.SendWithDeadline(time.Time{}, nil, nil) 531 if client.Has(seq) { 532 t.Error("cmd was not forgotten") 533 } 534 waitDone(done, t) 535 if infomap := mok.CheckCalls(mocks); len(infomap) > 0 { 536 t.Error(infomap) 537 } 538 }) 539 540 t.Run("We should be able to forget cmd", func(t *testing.T) { 541 var ( 542 done = make(chan struct{}) 543 cmd = mock.NewCmd() 544 delegate = mock.NewClientDelegate().RegisterSend( 545 func(seq base.Seq, cmd base.Cmd[any]) (err error) { 546 return nil 547 }, 548 ).RegisterFlush( 549 func() (err error) { return nil }, 550 ).RegisterReceive( 551 func() (seq base.Seq, result base.Result, err error) { 552 defer close(done) 553 err = errors.New("Delegate.Receive error") 554 return 555 }, 556 ).RegisterClose( 557 func() (err error) { return nil }, 558 ) 559 mocks = []*mok.Mock{cmd.Mock, delegate.Mock} 560 client = New[any](delegate, nil) 561 ) 562 seq, _ := client.Send(cmd, nil) 563 client.Forget(seq) 564 if client.Has(seq) { 565 t.Error("cmd was not forgotten") 566 } 567 waitDone(done, t) 568 if infomap := mok.CheckCalls(mocks); len(infomap) > 0 { 569 t.Error(infomap) 570 } 571 }) 572 573 t.Run("If the client was closed or failed to receive a next result, Done channel should be closed and Err method should return the cause", 574 func(t *testing.T) { 575 var ( 576 done = make(chan struct{}) 577 wantErr = errors.New("Delegate.Receive error") 578 delegate = mock.NewClientDelegate().RegisterReceive( 579 func() (seq base.Seq, result base.Result, err error) { 580 err = wantErr 581 return 582 }, 583 ).RegisterClose( 584 func() (err error) { return nil }, 585 ) 586 mocks = []*mok.Mock{delegate.Mock} 587 client = New[any](delegate, nil) 588 ) 589 <-client.Done() 590 go func() { 591 defer close(done) 592 err := client.Err() 593 if err != wantErr { 594 t.Errorf("unexpected error, want '%v' actual '%v'", nil, err) 595 } 596 }() 597 waitDone(done, t) 598 if infomap := mok.CheckCalls(mocks); len(infomap) > 0 { 599 t.Error(infomap) 600 } 601 }) 602 603 t.Run("We should be able to close the client while it queues a result", 604 func(t *testing.T) { 605 var ( 606 done = make(chan struct{}) 607 wantCmd = mock.NewCmd() 608 wantResult = mock.NewResult().RegisterLastOne( 609 func() (lastOne bool) { return true }, 610 ) 611 results = make(chan base.AsyncResult) 612 delegate = mock.NewClientDelegate().RegisterSend( 613 func(seq base.Seq, cmd base.Cmd[any]) (err error) { 614 return errors.New("Delegate.Send error") 615 }, 616 ).RegisterReceive( 617 func() (seq base.Seq, result base.Result, err error) { 618 return 1, wantResult, nil 619 }, 620 ).RegisterClose( 621 func() (err error) { 622 defer close(done) 623 return nil 624 }, 625 ) 626 mocks = []*mok.Mock{wantCmd.Mock, wantResult.Mock, delegate.Mock} 627 client = New[any](delegate, nil) 628 ) 629 client.Send(wantCmd, results) 630 time.Sleep(100 * time.Millisecond) 631 client.Close() 632 <-client.Done() 633 err := client.Err() 634 if err != ErrClosed { 635 t.Errorf("unexpected error, want '%v' actual '%v'", ErrClosed, err) 636 } 637 waitDone(done, t) 638 if infomap := mok.CheckCalls(mocks); len(infomap) > 0 { 639 t.Error(infomap) 640 } 641 }) 642 643 t.Run("If Delegate.Close fails with an error, Close should return it", 644 func(t *testing.T) { 645 var ( 646 done = make(chan struct{}) 647 receiveDone = make(chan struct{}) 648 wantErr = errors.New("Delegate.Close error") 649 delegate = mock.NewClientDelegate().RegisterReceive( 650 func() (seq base.Seq, result base.Result, err error) { 651 <-receiveDone 652 err = errors.New("Delegate.Receive error") 653 return 654 }, 655 ).RegisterClose( 656 func() (err error) { 657 defer close(receiveDone) 658 return wantErr 659 }, 660 ).RegisterClose( 661 func() (err error) { defer close(done); return nil }, 662 ) 663 mocks = []*mok.Mock{delegate.Mock} 664 client = New[any](delegate, nil) 665 ) 666 time.Sleep(100 * time.Millisecond) 667 err := client.Close() 668 if err != wantErr { 669 t.Errorf("unexpected error, want '%v' actual '%v'", nil, err) 670 } 671 waitDone(done, t) 672 if infomap := mok.CheckCalls(mocks); len(infomap) > 0 { 673 t.Error(infomap) 674 } 675 }) 676 677 t.Run("If Delegate.Flush fails with an error, Send of all involved commands should return error", 678 func(t *testing.T) { 679 var ( 680 wantErr = errors.New("flush error") 681 done = make(chan struct{}) 682 cmd1 = mock.NewCmd() 683 cmd2 = mock.NewCmd() 684 cmd3 = mock.NewCmd() 685 delegate = mock.NewClientDelegate().RegisterNSend(3, 686 func(seq base.Seq, cmd base.Cmd[any]) (err error) { 687 return nil 688 }, 689 ).RegisterNFlush(3, 690 func() (err error) { return wantErr }, 691 ).RegisterReceive( 692 func() (seq base.Seq, result base.Result, err error) { 693 <-done 694 err = errors.New("receive error") 695 return 696 }, 697 ).RegisterClose( 698 func() (err error) { return nil }, 699 ) 700 wg = &sync.WaitGroup{} 701 // mocks = []*mok.Mock{delegate.Mock} 702 client = New[any](delegate, nil) 703 ) 704 wg.Add(1) 705 go func() { 706 defer wg.Done() 707 _, err := client.Send(cmd1, nil) 708 if err != wantErr { 709 t.Errorf("unexpected error, want '%v' actual '%v'", wantErr, err) 710 } 711 }() 712 wg.Add(1) 713 go func() { 714 defer wg.Done() 715 _, err := client.Send(cmd2, nil) 716 if err != wantErr { 717 t.Errorf("unexpected error, want '%v' actual '%v'", wantErr, err) 718 } 719 }() 720 wg.Add(1) 721 go func() { 722 defer wg.Done() 723 _, err := client.Send(cmd3, nil) 724 if err != wantErr { 725 t.Errorf("unexpected error, want '%v' actual '%v'", wantErr, err) 726 } 727 }() 728 wg.Wait() 729 close(done) 730 // Commented out, because we do not know the actual count of the 731 // Delegate.Flush() method calls. 732 // 733 // If we want the flush method to be called only once, we should put 734 // time.Sleep(200*time.Milisecond) before the flush method acquires a 735 // lock. 736 // 737 // if infomap := mok.CheckCalls(mocks); len(infomap) > 0 { 738 // t.Error(infomap) 739 // } 740 }) 741 742 t.Run("If the client has lost a connection it should try to reconnect", 743 func(t *testing.T) { 744 var ( 745 reconected = make(chan struct{}) 746 delegate = func() (delegate mock.ReconnectClientDelegate) { 747 done := make(chan struct{}) 748 delegate = mock.NewReconnectClientDelegate().RegisterReceive( 749 func() (seq base.Seq, result base.Result, err error) { 750 err = net.ErrClosed 751 return 752 }, 753 ).RegisterReconnect( 754 func() error { close(reconected); return nil }, 755 ).RegisterReceive( 756 func() (seq base.Seq, result base.Result, err error) { 757 <-done 758 err = errors.New("closed") 759 return 760 }, 761 ).RegisterClose( 762 func() (err error) { close(done); return nil }, 763 ) 764 return 765 }() 766 mocks = []*mok.Mock{delegate.Mock} 767 client = New[any](delegate, nil) 768 ) 769 <-reconected 770 if err := client.Close(); err != nil { 771 t.Errorf("unexpected error, want '%v' actual '%v'", nil, err) 772 } 773 <-client.Done() 774 if infomap := mok.CheckCalls(mocks); len(infomap) > 0 { 775 t.Error(infomap) 776 } 777 }) 778 779 t.Run("If the client is closed it should not reconnect", func(t *testing.T) { 780 var ( 781 delegate = func() (delegate mock.ReconnectClientDelegate) { 782 done := make(chan struct{}) 783 delegate = mock.NewReconnectClientDelegate().RegisterReceive( 784 func() (seq base.Seq, result base.Result, err error) { 785 <-done 786 err = errors.New("receive error") 787 return 788 }, 789 ).RegisterClose( 790 func() (err error) { close(done); return nil }, 791 ) 792 return 793 }() 794 mocks = []*mok.Mock{delegate.Mock} 795 client = New[any](delegate, nil) 796 ) 797 if err := client.Close(); err != nil { 798 t.Errorf("unexpected error, want '%v' actual '%v'", nil, err) 799 } 800 <-client.Done() 801 if infomap := mok.CheckCalls(mocks); len(infomap) > 0 { 802 t.Error(infomap) 803 } 804 }) 805 806 t.Run("If reconnection fails with an error, it should became the client error", 807 func(t *testing.T) { 808 var ( 809 wantErr = errors.New("reconnection error") 810 delegate = func() (delegate mock.ReconnectClientDelegate) { 811 delegate = mock.NewReconnectClientDelegate().RegisterReceive( 812 func() (seq base.Seq, result base.Result, err error) { 813 err = net.ErrClosed 814 return 815 }, 816 ).RegisterReconnect( 817 func() error { return wantErr }, 818 ).RegisterClose( 819 func() (err error) { return nil }, 820 ) 821 return 822 }() 823 mocks = []*mok.Mock{delegate.Mock} 824 client = New[any](delegate, nil) 825 ) 826 <-client.Done() 827 err := client.Err() 828 if err != wantErr { 829 t.Errorf("unexpected error, want '%v' actual '%v'", wantErr, err) 830 } 831 if infomap := mok.CheckCalls(mocks); len(infomap) > 0 { 832 t.Error(infomap) 833 } 834 }) 835 836 } 837 838 func SameTime(t1, t2 time.Time) bool { 839 return !(t1.Before(t2.Truncate(Delta)) || t1.After(t2.Add(Delta))) 840 } 841 842 func waitDone(done chan struct{}, t *testing.T) { 843 select { 844 case <-done: 845 case <-time.NewTimer(time.Second).C: 846 t.Fatal("test lasts too long") 847 } 848 }