unbuffered_test.go 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. package broadcaster
  2. import (
  3. "bytes"
  4. "errors"
  5. "strings"
  6. "testing"
  7. )
  8. type dummyWriter struct {
  9. buffer bytes.Buffer
  10. failOnWrite bool
  11. }
  12. func (dw *dummyWriter) Write(p []byte) (n int, err error) {
  13. if dw.failOnWrite {
  14. return 0, errors.New("Fake fail")
  15. }
  16. return dw.buffer.Write(p)
  17. }
  18. func (dw *dummyWriter) String() string {
  19. return dw.buffer.String()
  20. }
  21. func (dw *dummyWriter) Close() error {
  22. return nil
  23. }
  24. func TestUnbuffered(t *testing.T) {
  25. writer := new(Unbuffered)
  26. // Test 1: Both bufferA and bufferB should contain "foo"
  27. bufferA := &dummyWriter{}
  28. writer.Add(bufferA)
  29. bufferB := &dummyWriter{}
  30. writer.Add(bufferB)
  31. writer.Write([]byte("foo"))
  32. if bufferA.String() != "foo" {
  33. t.Errorf("Buffer contains %v", bufferA.String())
  34. }
  35. if bufferB.String() != "foo" {
  36. t.Errorf("Buffer contains %v", bufferB.String())
  37. }
  38. // Test2: bufferA and bufferB should contain "foobar",
  39. // while bufferC should only contain "bar"
  40. bufferC := &dummyWriter{}
  41. writer.Add(bufferC)
  42. writer.Write([]byte("bar"))
  43. if bufferA.String() != "foobar" {
  44. t.Errorf("Buffer contains %v", bufferA.String())
  45. }
  46. if bufferB.String() != "foobar" {
  47. t.Errorf("Buffer contains %v", bufferB.String())
  48. }
  49. if bufferC.String() != "bar" {
  50. t.Errorf("Buffer contains %v", bufferC.String())
  51. }
  52. // Test3: Test eviction on failure
  53. bufferA.failOnWrite = true
  54. writer.Write([]byte("fail"))
  55. if bufferA.String() != "foobar" {
  56. t.Errorf("Buffer contains %v", bufferA.String())
  57. }
  58. if bufferC.String() != "barfail" {
  59. t.Errorf("Buffer contains %v", bufferC.String())
  60. }
  61. // Even though we reset the flag, no more writes should go in there
  62. bufferA.failOnWrite = false
  63. writer.Write([]byte("test"))
  64. if bufferA.String() != "foobar" {
  65. t.Errorf("Buffer contains %v", bufferA.String())
  66. }
  67. if bufferC.String() != "barfailtest" {
  68. t.Errorf("Buffer contains %v", bufferC.String())
  69. }
  70. // Test4: Test eviction on multiple simultaneous failures
  71. bufferB.failOnWrite = true
  72. bufferC.failOnWrite = true
  73. bufferD := &dummyWriter{}
  74. writer.Add(bufferD)
  75. writer.Write([]byte("yo"))
  76. writer.Write([]byte("ink"))
  77. if strings.Contains(bufferB.String(), "yoink") {
  78. t.Errorf("bufferB received write. contents: %q", bufferB)
  79. }
  80. if strings.Contains(bufferC.String(), "yoink") {
  81. t.Errorf("bufferC received write. contents: %q", bufferC)
  82. }
  83. if g, w := bufferD.String(), "yoink"; g != w {
  84. t.Errorf("bufferD = %q, want %q", g, w)
  85. }
  86. writer.Clean()
  87. }
  88. type devNullCloser int
  89. func (d devNullCloser) Close() error {
  90. return nil
  91. }
  92. func (d devNullCloser) Write(buf []byte) (int, error) {
  93. return len(buf), nil
  94. }
  95. // This test checks for races. It is only useful when run with the race detector.
  96. func TestRaceUnbuffered(t *testing.T) {
  97. writer := new(Unbuffered)
  98. c := make(chan bool)
  99. go func() {
  100. writer.Add(devNullCloser(0))
  101. c <- true
  102. }()
  103. writer.Write([]byte("hello"))
  104. <-c
  105. }
  106. func BenchmarkUnbuffered(b *testing.B) {
  107. writer := new(Unbuffered)
  108. setUpWriter := func() {
  109. for i := 0; i < 100; i++ {
  110. writer.Add(devNullCloser(0))
  111. writer.Add(devNullCloser(0))
  112. writer.Add(devNullCloser(0))
  113. }
  114. }
  115. testLine := "Line that thinks that it is log line from docker"
  116. var buf bytes.Buffer
  117. for i := 0; i < 100; i++ {
  118. buf.Write([]byte(testLine + "\n"))
  119. }
  120. // line without eol
  121. buf.Write([]byte(testLine))
  122. testText := buf.Bytes()
  123. b.SetBytes(int64(5 * len(testText)))
  124. b.ResetTimer()
  125. for i := 0; i < b.N; i++ {
  126. b.StopTimer()
  127. setUpWriter()
  128. b.StartTimer()
  129. for j := 0; j < 5; j++ {
  130. if _, err := writer.Write(testText); err != nil {
  131. b.Fatal(err)
  132. }
  133. }
  134. b.StopTimer()
  135. writer.Clean()
  136. b.StartTimer()
  137. }
  138. }