github.com/titanous/docker@v1.4.1/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  }