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