github.com/olljanat/moby@v1.13.1/pkg/broadcaster/unbuffered_test.go (about)

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