tomb_test.go 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. package tomb_test
  2. import (
  3. "errors"
  4. "gopkg.in/tomb.v1"
  5. "reflect"
  6. "testing"
  7. )
  8. func TestNewTomb(t *testing.T) {
  9. tb := &tomb.Tomb{}
  10. testState(t, tb, false, false, tomb.ErrStillAlive)
  11. tb.Done()
  12. testState(t, tb, true, true, nil)
  13. }
  14. func TestKill(t *testing.T) {
  15. // a nil reason flags the goroutine as dying
  16. tb := &tomb.Tomb{}
  17. tb.Kill(nil)
  18. testState(t, tb, true, false, nil)
  19. // a non-nil reason now will override Kill
  20. err := errors.New("some error")
  21. tb.Kill(err)
  22. testState(t, tb, true, false, err)
  23. // another non-nil reason won't replace the first one
  24. tb.Kill(errors.New("ignore me"))
  25. testState(t, tb, true, false, err)
  26. tb.Done()
  27. testState(t, tb, true, true, err)
  28. }
  29. func TestKillf(t *testing.T) {
  30. tb := &tomb.Tomb{}
  31. err := tb.Killf("BO%s", "OM")
  32. if s := err.Error(); s != "BOOM" {
  33. t.Fatalf(`Killf("BO%s", "OM"): want "BOOM", got %q`, s)
  34. }
  35. testState(t, tb, true, false, err)
  36. // another non-nil reason won't replace the first one
  37. tb.Killf("ignore me")
  38. testState(t, tb, true, false, err)
  39. tb.Done()
  40. testState(t, tb, true, true, err)
  41. }
  42. func TestErrDying(t *testing.T) {
  43. // ErrDying being used properly, after a clean death.
  44. tb := &tomb.Tomb{}
  45. tb.Kill(nil)
  46. tb.Kill(tomb.ErrDying)
  47. testState(t, tb, true, false, nil)
  48. // ErrDying being used properly, after an errorful death.
  49. err := errors.New("some error")
  50. tb.Kill(err)
  51. tb.Kill(tomb.ErrDying)
  52. testState(t, tb, true, false, err)
  53. // ErrDying being used badly, with an alive tomb.
  54. tb = &tomb.Tomb{}
  55. defer func() {
  56. err := recover()
  57. if err != "tomb: Kill with ErrDying while still alive" {
  58. t.Fatalf("Wrong panic on Kill(ErrDying): %v", err)
  59. }
  60. testState(t, tb, false, false, tomb.ErrStillAlive)
  61. }()
  62. tb.Kill(tomb.ErrDying)
  63. }
  64. func testState(t *testing.T, tb *tomb.Tomb, wantDying, wantDead bool, wantErr error) {
  65. select {
  66. case <-tb.Dying():
  67. if !wantDying {
  68. t.Error("<-Dying: should block")
  69. }
  70. default:
  71. if wantDying {
  72. t.Error("<-Dying: should not block")
  73. }
  74. }
  75. seemsDead := false
  76. select {
  77. case <-tb.Dead():
  78. if !wantDead {
  79. t.Error("<-Dead: should block")
  80. }
  81. seemsDead = true
  82. default:
  83. if wantDead {
  84. t.Error("<-Dead: should not block")
  85. }
  86. }
  87. if err := tb.Err(); err != wantErr {
  88. t.Errorf("Err: want %#v, got %#v", wantErr, err)
  89. }
  90. if wantDead && seemsDead {
  91. waitErr := tb.Wait()
  92. switch {
  93. case waitErr == tomb.ErrStillAlive:
  94. t.Errorf("Wait should not return ErrStillAlive")
  95. case !reflect.DeepEqual(waitErr, wantErr):
  96. t.Errorf("Wait: want %#v, got %#v", wantErr, waitErr)
  97. }
  98. }
  99. }