github.com/LazyboyChen7/engine@v17.12.1-ce-rc2+incompatible/daemon/logger/ring_test.go (about) 1 package logger 2 3 import ( 4 "context" 5 "strconv" 6 "testing" 7 "time" 8 ) 9 10 type mockLogger struct{ c chan *Message } 11 12 func (l *mockLogger) Log(msg *Message) error { 13 l.c <- msg 14 return nil 15 } 16 17 func (l *mockLogger) Name() string { 18 return "mock" 19 } 20 21 func (l *mockLogger) Close() error { 22 return nil 23 } 24 25 func TestRingLogger(t *testing.T) { 26 mockLog := &mockLogger{make(chan *Message)} // no buffer on this channel 27 ring := newRingLogger(mockLog, Info{}, 1) 28 defer ring.setClosed() 29 30 // this should never block 31 ring.Log(&Message{Line: []byte("1")}) 32 ring.Log(&Message{Line: []byte("2")}) 33 ring.Log(&Message{Line: []byte("3")}) 34 35 select { 36 case msg := <-mockLog.c: 37 if string(msg.Line) != "1" { 38 t.Fatalf("got unexpected msg: %q", string(msg.Line)) 39 } 40 case <-time.After(100 * time.Millisecond): 41 t.Fatal("timeout reading log message") 42 } 43 44 select { 45 case msg := <-mockLog.c: 46 t.Fatalf("expected no more messages in the queue, got: %q", string(msg.Line)) 47 default: 48 } 49 } 50 51 func TestRingCap(t *testing.T) { 52 r := newRing(5) 53 for i := 0; i < 10; i++ { 54 // queue messages with "0" to "10" 55 // the "5" to "10" messages should be dropped since we only allow 5 bytes in the buffer 56 if err := r.Enqueue(&Message{Line: []byte(strconv.Itoa(i))}); err != nil { 57 t.Fatal(err) 58 } 59 } 60 61 // should have messages in the queue for "5" to "10" 62 for i := 0; i < 5; i++ { 63 m, err := r.Dequeue() 64 if err != nil { 65 t.Fatal(err) 66 } 67 if string(m.Line) != strconv.Itoa(i) { 68 t.Fatalf("got unexpected message for iter %d: %s", i, string(m.Line)) 69 } 70 } 71 72 // queue a message that's bigger than the buffer cap 73 if err := r.Enqueue(&Message{Line: []byte("hello world")}); err != nil { 74 t.Fatal(err) 75 } 76 77 // queue another message that's bigger than the buffer cap 78 if err := r.Enqueue(&Message{Line: []byte("eat a banana")}); err != nil { 79 t.Fatal(err) 80 } 81 82 m, err := r.Dequeue() 83 if err != nil { 84 t.Fatal(err) 85 } 86 if string(m.Line) != "hello world" { 87 t.Fatalf("got unexpected message: %s", string(m.Line)) 88 } 89 if len(r.queue) != 0 { 90 t.Fatalf("expected queue to be empty, got: %d", len(r.queue)) 91 } 92 } 93 94 func TestRingClose(t *testing.T) { 95 r := newRing(1) 96 if err := r.Enqueue(&Message{Line: []byte("hello")}); err != nil { 97 t.Fatal(err) 98 } 99 r.Close() 100 if err := r.Enqueue(&Message{}); err != errClosed { 101 t.Fatalf("expected errClosed, got: %v", err) 102 } 103 if len(r.queue) != 1 { 104 t.Fatal("expected empty queue") 105 } 106 if m, err := r.Dequeue(); err == nil || m != nil { 107 t.Fatal("expected err on Dequeue after close") 108 } 109 110 ls := r.Drain() 111 if len(ls) != 1 { 112 t.Fatalf("expected one message: %v", ls) 113 } 114 if string(ls[0].Line) != "hello" { 115 t.Fatalf("got unexpected message: %s", string(ls[0].Line)) 116 } 117 } 118 119 func TestRingDrain(t *testing.T) { 120 r := newRing(5) 121 for i := 0; i < 5; i++ { 122 if err := r.Enqueue(&Message{Line: []byte(strconv.Itoa(i))}); err != nil { 123 t.Fatal(err) 124 } 125 } 126 127 ls := r.Drain() 128 if len(ls) != 5 { 129 t.Fatal("got unexpected length after drain") 130 } 131 132 for i := 0; i < 5; i++ { 133 if string(ls[i].Line) != strconv.Itoa(i) { 134 t.Fatalf("got unexpected message at position %d: %s", i, string(ls[i].Line)) 135 } 136 } 137 if r.sizeBytes != 0 { 138 t.Fatalf("expected buffer size to be 0 after drain, got: %d", r.sizeBytes) 139 } 140 141 ls = r.Drain() 142 if len(ls) != 0 { 143 t.Fatalf("expected 0 messages on 2nd drain: %v", ls) 144 } 145 146 } 147 148 type nopLogger struct{} 149 150 func (nopLogger) Name() string { return "nopLogger" } 151 func (nopLogger) Close() error { return nil } 152 func (nopLogger) Log(*Message) error { return nil } 153 154 func BenchmarkRingLoggerThroughputNoReceiver(b *testing.B) { 155 mockLog := &mockLogger{make(chan *Message)} 156 defer mockLog.Close() 157 l := NewRingLogger(mockLog, Info{}, -1) 158 msg := &Message{Line: []byte("hello humans and everyone else!")} 159 b.SetBytes(int64(len(msg.Line))) 160 161 for i := 0; i < b.N; i++ { 162 if err := l.Log(msg); err != nil { 163 b.Fatal(err) 164 } 165 } 166 } 167 168 func BenchmarkRingLoggerThroughputWithReceiverDelay0(b *testing.B) { 169 l := NewRingLogger(nopLogger{}, Info{}, -1) 170 msg := &Message{Line: []byte("hello humans and everyone else!")} 171 b.SetBytes(int64(len(msg.Line))) 172 173 for i := 0; i < b.N; i++ { 174 if err := l.Log(msg); err != nil { 175 b.Fatal(err) 176 } 177 } 178 } 179 180 func consumeWithDelay(delay time.Duration, c <-chan *Message) (cancel func()) { 181 started := make(chan struct{}) 182 ctx, cancel := context.WithCancel(context.Background()) 183 go func() { 184 close(started) 185 ticker := time.NewTicker(delay) 186 for range ticker.C { 187 select { 188 case <-ctx.Done(): 189 ticker.Stop() 190 return 191 case <-c: 192 } 193 } 194 }() 195 <-started 196 return cancel 197 } 198 199 func BenchmarkRingLoggerThroughputConsumeDelay1(b *testing.B) { 200 mockLog := &mockLogger{make(chan *Message)} 201 defer mockLog.Close() 202 l := NewRingLogger(mockLog, Info{}, -1) 203 msg := &Message{Line: []byte("hello humans and everyone else!")} 204 b.SetBytes(int64(len(msg.Line))) 205 206 cancel := consumeWithDelay(1*time.Millisecond, mockLog.c) 207 defer cancel() 208 209 for i := 0; i < b.N; i++ { 210 if err := l.Log(msg); err != nil { 211 b.Fatal(err) 212 } 213 } 214 } 215 216 func BenchmarkRingLoggerThroughputConsumeDelay10(b *testing.B) { 217 mockLog := &mockLogger{make(chan *Message)} 218 defer mockLog.Close() 219 l := NewRingLogger(mockLog, Info{}, -1) 220 msg := &Message{Line: []byte("hello humans and everyone else!")} 221 b.SetBytes(int64(len(msg.Line))) 222 223 cancel := consumeWithDelay(10*time.Millisecond, mockLog.c) 224 defer cancel() 225 226 for i := 0; i < b.N; i++ { 227 if err := l.Log(msg); err != nil { 228 b.Fatal(err) 229 } 230 } 231 } 232 233 func BenchmarkRingLoggerThroughputConsumeDelay50(b *testing.B) { 234 mockLog := &mockLogger{make(chan *Message)} 235 defer mockLog.Close() 236 l := NewRingLogger(mockLog, Info{}, -1) 237 msg := &Message{Line: []byte("hello humans and everyone else!")} 238 b.SetBytes(int64(len(msg.Line))) 239 240 cancel := consumeWithDelay(50*time.Millisecond, mockLog.c) 241 defer cancel() 242 243 for i := 0; i < b.N; i++ { 244 if err := l.Log(msg); err != nil { 245 b.Fatal(err) 246 } 247 } 248 } 249 250 func BenchmarkRingLoggerThroughputConsumeDelay100(b *testing.B) { 251 mockLog := &mockLogger{make(chan *Message)} 252 defer mockLog.Close() 253 l := NewRingLogger(mockLog, Info{}, -1) 254 msg := &Message{Line: []byte("hello humans and everyone else!")} 255 b.SetBytes(int64(len(msg.Line))) 256 257 cancel := consumeWithDelay(100*time.Millisecond, mockLog.c) 258 defer cancel() 259 260 for i := 0; i < b.N; i++ { 261 if err := l.Log(msg); err != nil { 262 b.Fatal(err) 263 } 264 } 265 } 266 267 func BenchmarkRingLoggerThroughputConsumeDelay300(b *testing.B) { 268 mockLog := &mockLogger{make(chan *Message)} 269 defer mockLog.Close() 270 l := NewRingLogger(mockLog, Info{}, -1) 271 msg := &Message{Line: []byte("hello humans and everyone else!")} 272 b.SetBytes(int64(len(msg.Line))) 273 274 cancel := consumeWithDelay(300*time.Millisecond, mockLog.c) 275 defer cancel() 276 277 for i := 0; i < b.N; i++ { 278 if err := l.Log(msg); err != nil { 279 b.Fatal(err) 280 } 281 } 282 } 283 284 func BenchmarkRingLoggerThroughputConsumeDelay500(b *testing.B) { 285 mockLog := &mockLogger{make(chan *Message)} 286 defer mockLog.Close() 287 l := NewRingLogger(mockLog, Info{}, -1) 288 msg := &Message{Line: []byte("hello humans and everyone else!")} 289 b.SetBytes(int64(len(msg.Line))) 290 291 cancel := consumeWithDelay(500*time.Millisecond, mockLog.c) 292 defer cancel() 293 294 for i := 0; i < b.N; i++ { 295 if err := l.Log(msg); err != nil { 296 b.Fatal(err) 297 } 298 } 299 }