github.com/vieux/docker@v0.6.3-0.20161004191708-e097c2a938c7/daemon/logger/copier_test.go (about) 1 package logger 2 3 import ( 4 "bytes" 5 "encoding/json" 6 "fmt" 7 "io" 8 "os" 9 "sync" 10 "testing" 11 "time" 12 ) 13 14 type TestLoggerJSON struct { 15 *json.Encoder 16 mu sync.Mutex 17 delay time.Duration 18 } 19 20 func (l *TestLoggerJSON) Log(m *Message) error { 21 if l.delay > 0 { 22 time.Sleep(l.delay) 23 } 24 l.mu.Lock() 25 defer l.mu.Unlock() 26 return l.Encode(m) 27 } 28 29 func (l *TestLoggerJSON) Close() error { return nil } 30 31 func (l *TestLoggerJSON) Name() string { return "json" } 32 33 func TestCopier(t *testing.T) { 34 stdoutLine := "Line that thinks that it is log line from docker stdout" 35 stderrLine := "Line that thinks that it is log line from docker stderr" 36 var stdout bytes.Buffer 37 var stderr bytes.Buffer 38 for i := 0; i < 30; i++ { 39 if _, err := stdout.WriteString(stdoutLine + "\n"); err != nil { 40 t.Fatal(err) 41 } 42 if _, err := stderr.WriteString(stderrLine + "\n"); err != nil { 43 t.Fatal(err) 44 } 45 } 46 47 var jsonBuf bytes.Buffer 48 49 jsonLog := &TestLoggerJSON{Encoder: json.NewEncoder(&jsonBuf)} 50 51 c := NewCopier( 52 map[string]io.Reader{ 53 "stdout": &stdout, 54 "stderr": &stderr, 55 }, 56 jsonLog) 57 c.Run() 58 wait := make(chan struct{}) 59 go func() { 60 c.Wait() 61 close(wait) 62 }() 63 select { 64 case <-time.After(1 * time.Second): 65 t.Fatal("Copier failed to do its work in 1 second") 66 case <-wait: 67 } 68 dec := json.NewDecoder(&jsonBuf) 69 for { 70 var msg Message 71 if err := dec.Decode(&msg); err != nil { 72 if err == io.EOF { 73 break 74 } 75 t.Fatal(err) 76 } 77 if msg.Source != "stdout" && msg.Source != "stderr" { 78 t.Fatalf("Wrong Source: %q, should be %q or %q", msg.Source, "stdout", "stderr") 79 } 80 if msg.Source == "stdout" { 81 if string(msg.Line) != stdoutLine { 82 t.Fatalf("Wrong Line: %q, expected %q", msg.Line, stdoutLine) 83 } 84 } 85 if msg.Source == "stderr" { 86 if string(msg.Line) != stderrLine { 87 t.Fatalf("Wrong Line: %q, expected %q", msg.Line, stderrLine) 88 } 89 } 90 } 91 } 92 93 func TestCopierSlow(t *testing.T) { 94 stdoutLine := "Line that thinks that it is log line from docker stdout" 95 var stdout bytes.Buffer 96 for i := 0; i < 30; i++ { 97 if _, err := stdout.WriteString(stdoutLine + "\n"); err != nil { 98 t.Fatal(err) 99 } 100 } 101 102 var jsonBuf bytes.Buffer 103 //encoder := &encodeCloser{Encoder: json.NewEncoder(&jsonBuf)} 104 jsonLog := &TestLoggerJSON{Encoder: json.NewEncoder(&jsonBuf), delay: 100 * time.Millisecond} 105 106 c := NewCopier(map[string]io.Reader{"stdout": &stdout}, jsonLog) 107 c.Run() 108 wait := make(chan struct{}) 109 go func() { 110 c.Wait() 111 close(wait) 112 }() 113 <-time.After(150 * time.Millisecond) 114 c.Close() 115 select { 116 case <-time.After(200 * time.Millisecond): 117 t.Fatalf("failed to exit in time after the copier is closed") 118 case <-wait: 119 } 120 } 121 122 type BenchmarkLoggerDummy struct { 123 } 124 125 func (l *BenchmarkLoggerDummy) Log(m *Message) error { return nil } 126 127 func (l *BenchmarkLoggerDummy) Close() error { return nil } 128 129 func (l *BenchmarkLoggerDummy) Name() string { return "dummy" } 130 131 func BenchmarkCopier64(b *testing.B) { 132 benchmarkCopier(b, 1<<6) 133 } 134 func BenchmarkCopier128(b *testing.B) { 135 benchmarkCopier(b, 1<<7) 136 } 137 func BenchmarkCopier256(b *testing.B) { 138 benchmarkCopier(b, 1<<8) 139 } 140 func BenchmarkCopier512(b *testing.B) { 141 benchmarkCopier(b, 1<<9) 142 } 143 func BenchmarkCopier1K(b *testing.B) { 144 benchmarkCopier(b, 1<<10) 145 } 146 func BenchmarkCopier2K(b *testing.B) { 147 benchmarkCopier(b, 1<<11) 148 } 149 func BenchmarkCopier4K(b *testing.B) { 150 benchmarkCopier(b, 1<<12) 151 } 152 func BenchmarkCopier8K(b *testing.B) { 153 benchmarkCopier(b, 1<<13) 154 } 155 func BenchmarkCopier16K(b *testing.B) { 156 benchmarkCopier(b, 1<<14) 157 } 158 func BenchmarkCopier32K(b *testing.B) { 159 benchmarkCopier(b, 1<<15) 160 } 161 func BenchmarkCopier64K(b *testing.B) { 162 benchmarkCopier(b, 1<<16) 163 } 164 func BenchmarkCopier128K(b *testing.B) { 165 benchmarkCopier(b, 1<<17) 166 } 167 func BenchmarkCopier256K(b *testing.B) { 168 benchmarkCopier(b, 1<<18) 169 } 170 171 func piped(b *testing.B, iterations int, delay time.Duration, buf []byte) io.Reader { 172 r, w, err := os.Pipe() 173 if err != nil { 174 b.Fatal(err) 175 return nil 176 } 177 go func() { 178 for i := 0; i < iterations; i++ { 179 time.Sleep(delay) 180 if n, err := w.Write(buf); err != nil || n != len(buf) { 181 if err != nil { 182 b.Fatal(err) 183 } 184 b.Fatal(fmt.Errorf("short write")) 185 } 186 } 187 w.Close() 188 }() 189 return r 190 } 191 192 func benchmarkCopier(b *testing.B, length int) { 193 b.StopTimer() 194 buf := []byte{'A'} 195 for len(buf) < length { 196 buf = append(buf, buf...) 197 } 198 buf = append(buf[:length-1], []byte{'\n'}...) 199 b.StartTimer() 200 for i := 0; i < b.N; i++ { 201 c := NewCopier( 202 map[string]io.Reader{ 203 "buffer": piped(b, 10, time.Nanosecond, buf), 204 }, 205 &BenchmarkLoggerDummy{}) 206 c.Run() 207 c.Wait() 208 c.Close() 209 } 210 }