123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162 |
- package broadcaster
- import (
- "bytes"
- "errors"
- "strings"
- "testing"
- )
- type dummyWriter struct {
- buffer bytes.Buffer
- failOnWrite bool
- }
- func (dw *dummyWriter) Write(p []byte) (n int, err error) {
- if dw.failOnWrite {
- return 0, errors.New("Fake fail")
- }
- return dw.buffer.Write(p)
- }
- func (dw *dummyWriter) String() string {
- return dw.buffer.String()
- }
- func (dw *dummyWriter) Close() error {
- return nil
- }
- func TestUnbuffered(t *testing.T) {
- writer := new(Unbuffered)
- // Test 1: Both bufferA and bufferB should contain "foo"
- bufferA := &dummyWriter{}
- writer.Add(bufferA)
- bufferB := &dummyWriter{}
- writer.Add(bufferB)
- writer.Write([]byte("foo"))
- if bufferA.String() != "foo" {
- t.Errorf("Buffer contains %v", bufferA.String())
- }
- if bufferB.String() != "foo" {
- t.Errorf("Buffer contains %v", bufferB.String())
- }
- // Test2: bufferA and bufferB should contain "foobar",
- // while bufferC should only contain "bar"
- bufferC := &dummyWriter{}
- writer.Add(bufferC)
- writer.Write([]byte("bar"))
- if bufferA.String() != "foobar" {
- t.Errorf("Buffer contains %v", bufferA.String())
- }
- if bufferB.String() != "foobar" {
- t.Errorf("Buffer contains %v", bufferB.String())
- }
- if bufferC.String() != "bar" {
- t.Errorf("Buffer contains %v", bufferC.String())
- }
- // Test3: Test eviction on failure
- bufferA.failOnWrite = true
- writer.Write([]byte("fail"))
- if bufferA.String() != "foobar" {
- t.Errorf("Buffer contains %v", bufferA.String())
- }
- if bufferC.String() != "barfail" {
- t.Errorf("Buffer contains %v", bufferC.String())
- }
- // Even though we reset the flag, no more writes should go in there
- bufferA.failOnWrite = false
- writer.Write([]byte("test"))
- if bufferA.String() != "foobar" {
- t.Errorf("Buffer contains %v", bufferA.String())
- }
- if bufferC.String() != "barfailtest" {
- t.Errorf("Buffer contains %v", bufferC.String())
- }
- // Test4: Test eviction on multiple simultaneous failures
- bufferB.failOnWrite = true
- bufferC.failOnWrite = true
- bufferD := &dummyWriter{}
- writer.Add(bufferD)
- writer.Write([]byte("yo"))
- writer.Write([]byte("ink"))
- if strings.Contains(bufferB.String(), "yoink") {
- t.Errorf("bufferB received write. contents: %q", bufferB)
- }
- if strings.Contains(bufferC.String(), "yoink") {
- t.Errorf("bufferC received write. contents: %q", bufferC)
- }
- if g, w := bufferD.String(), "yoink"; g != w {
- t.Errorf("bufferD = %q, want %q", g, w)
- }
- writer.Clean()
- }
- type devNullCloser int
- func (d devNullCloser) Close() error {
- return nil
- }
- func (d devNullCloser) Write(buf []byte) (int, error) {
- return len(buf), nil
- }
- // This test checks for races. It is only useful when run with the race detector.
- func TestRaceUnbuffered(t *testing.T) {
- writer := new(Unbuffered)
- c := make(chan bool)
- go func() {
- writer.Add(devNullCloser(0))
- c <- true
- }()
- writer.Write([]byte("hello"))
- <-c
- }
- func BenchmarkUnbuffered(b *testing.B) {
- writer := new(Unbuffered)
- setUpWriter := func() {
- for i := 0; i < 100; i++ {
- writer.Add(devNullCloser(0))
- writer.Add(devNullCloser(0))
- writer.Add(devNullCloser(0))
- }
- }
- testLine := "Line that thinks that it is log line from docker"
- var buf bytes.Buffer
- for i := 0; i < 100; i++ {
- buf.Write([]byte(testLine + "\n"))
- }
- // line without eol
- buf.Write([]byte(testLine))
- testText := buf.Bytes()
- b.SetBytes(int64(5 * len(testText)))
- b.ResetTimer()
- for i := 0; i < b.N; i++ {
- b.StopTimer()
- setUpWriter()
- b.StartTimer()
- for j := 0; j < 5; j++ {
- if _, err := writer.Write(testText); err != nil {
- b.Fatal(err)
- }
- }
- b.StopTimer()
- writer.Clean()
- b.StartTimer()
- }
- }
|