github.com/demonoid81/moby@v0.0.0-20200517203328-62dd8e17c460/pkg/broadcaster/unbuffered_test.go (about)

     1  package broadcaster // import "github.com/demonoid81/moby/pkg/broadcaster"
     2  
     3  import (
     4  	"bytes"
     5  	"errors"
     6  	"strings"
     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 TestUnbuffered(t *testing.T) {
    31  	writer := new(Unbuffered)
    32  
    33  	// Test 1: Both bufferA and bufferB should contain "foo"
    34  	bufferA := &dummyWriter{}
    35  	writer.Add(bufferA)
    36  	bufferB := &dummyWriter{}
    37  	writer.Add(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.Add(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  	// Test4: Test eviction on multiple simultaneous failures
    86  	bufferB.failOnWrite = true
    87  	bufferC.failOnWrite = true
    88  	bufferD := &dummyWriter{}
    89  	writer.Add(bufferD)
    90  	writer.Write([]byte("yo"))
    91  	writer.Write([]byte("ink"))
    92  	if strings.Contains(bufferB.String(), "yoink") {
    93  		t.Errorf("bufferB received write. contents: %q", bufferB)
    94  	}
    95  	if strings.Contains(bufferC.String(), "yoink") {
    96  		t.Errorf("bufferC received write. contents: %q", bufferC)
    97  	}
    98  	if g, w := bufferD.String(), "yoink"; g != w {
    99  		t.Errorf("bufferD = %q, want %q", g, w)
   100  	}
   101  
   102  	writer.Clean()
   103  }
   104  
   105  type devNullCloser int
   106  
   107  func (d devNullCloser) Close() error {
   108  	return nil
   109  }
   110  
   111  func (d devNullCloser) Write(buf []byte) (int, error) {
   112  	return len(buf), nil
   113  }
   114  
   115  // This test checks for races. It is only useful when run with the race detector.
   116  func TestRaceUnbuffered(t *testing.T) {
   117  	writer := new(Unbuffered)
   118  	c := make(chan bool)
   119  	go func() {
   120  		writer.Add(devNullCloser(0))
   121  		c <- true
   122  	}()
   123  	writer.Write([]byte("hello"))
   124  	<-c
   125  }
   126  
   127  func BenchmarkUnbuffered(b *testing.B) {
   128  	writer := new(Unbuffered)
   129  	setUpWriter := func() {
   130  		for i := 0; i < 100; i++ {
   131  			writer.Add(devNullCloser(0))
   132  			writer.Add(devNullCloser(0))
   133  			writer.Add(devNullCloser(0))
   134  		}
   135  	}
   136  	testLine := "Line that thinks that it is log line from docker"
   137  	var buf bytes.Buffer
   138  	for i := 0; i < 100; i++ {
   139  		buf.Write([]byte(testLine + "\n"))
   140  	}
   141  	// line without eol
   142  	buf.Write([]byte(testLine))
   143  	testText := buf.Bytes()
   144  	b.SetBytes(int64(5 * len(testText)))
   145  	b.ResetTimer()
   146  	for i := 0; i < b.N; i++ {
   147  		b.StopTimer()
   148  		setUpWriter()
   149  		b.StartTimer()
   150  
   151  		for j := 0; j < 5; j++ {
   152  			if _, err := writer.Write(testText); err != nil {
   153  				b.Fatal(err)
   154  			}
   155  		}
   156  
   157  		b.StopTimer()
   158  		writer.Clean()
   159  		b.StartTimer()
   160  	}
   161  }