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

     1  package stdcopy // import "github.com/demonoid81/moby/pkg/stdcopy"
     2  
     3  import (
     4  	"bytes"
     5  	"errors"
     6  	"io"
     7  	"io/ioutil"
     8  	"strings"
     9  	"testing"
    10  )
    11  
    12  func TestNewStdWriter(t *testing.T) {
    13  	writer := NewStdWriter(ioutil.Discard, Stdout)
    14  	if writer == nil {
    15  		t.Fatalf("NewStdWriter with an invalid StdType should not return nil.")
    16  	}
    17  }
    18  
    19  func TestWriteWithUninitializedStdWriter(t *testing.T) {
    20  	writer := stdWriter{
    21  		Writer: nil,
    22  		prefix: byte(Stdout),
    23  	}
    24  	n, err := writer.Write([]byte("Something here"))
    25  	if n != 0 || err == nil {
    26  		t.Fatalf("Should fail when given an incomplete or uninitialized StdWriter")
    27  	}
    28  }
    29  
    30  func TestWriteWithNilBytes(t *testing.T) {
    31  	writer := NewStdWriter(ioutil.Discard, Stdout)
    32  	n, err := writer.Write(nil)
    33  	if err != nil {
    34  		t.Fatalf("Shouldn't have fail when given no data")
    35  	}
    36  	if n > 0 {
    37  		t.Fatalf("Write should have written 0 byte, but has written %d", n)
    38  	}
    39  }
    40  
    41  func TestWrite(t *testing.T) {
    42  	writer := NewStdWriter(ioutil.Discard, Stdout)
    43  	data := []byte("Test StdWrite.Write")
    44  	n, err := writer.Write(data)
    45  	if err != nil {
    46  		t.Fatalf("Error while writing with StdWrite")
    47  	}
    48  	if n != len(data) {
    49  		t.Fatalf("Write should have written %d byte but wrote %d.", len(data), n)
    50  	}
    51  }
    52  
    53  type errWriter struct {
    54  	n   int
    55  	err error
    56  }
    57  
    58  func (f *errWriter) Write(buf []byte) (int, error) {
    59  	return f.n, f.err
    60  }
    61  
    62  func TestWriteWithWriterError(t *testing.T) {
    63  	expectedError := errors.New("expected")
    64  	expectedReturnedBytes := 10
    65  	writer := NewStdWriter(&errWriter{
    66  		n:   stdWriterPrefixLen + expectedReturnedBytes,
    67  		err: expectedError}, Stdout)
    68  	data := []byte("This won't get written, sigh")
    69  	n, err := writer.Write(data)
    70  	if err != expectedError {
    71  		t.Fatalf("Didn't get expected error.")
    72  	}
    73  	if n != expectedReturnedBytes {
    74  		t.Fatalf("Didn't get expected written bytes %d, got %d.",
    75  			expectedReturnedBytes, n)
    76  	}
    77  }
    78  
    79  func TestWriteDoesNotReturnNegativeWrittenBytes(t *testing.T) {
    80  	writer := NewStdWriter(&errWriter{n: -1}, Stdout)
    81  	data := []byte("This won't get written, sigh")
    82  	actual, _ := writer.Write(data)
    83  	if actual != 0 {
    84  		t.Fatalf("Expected returned written bytes equal to 0, got %d", actual)
    85  	}
    86  }
    87  
    88  func getSrcBuffer(stdOutBytes, stdErrBytes []byte) (buffer *bytes.Buffer, err error) {
    89  	buffer = new(bytes.Buffer)
    90  	dstOut := NewStdWriter(buffer, Stdout)
    91  	_, err = dstOut.Write(stdOutBytes)
    92  	if err != nil {
    93  		return
    94  	}
    95  	dstErr := NewStdWriter(buffer, Stderr)
    96  	_, err = dstErr.Write(stdErrBytes)
    97  	return
    98  }
    99  
   100  func TestStdCopyWriteAndRead(t *testing.T) {
   101  	stdOutBytes := []byte(strings.Repeat("o", startingBufLen))
   102  	stdErrBytes := []byte(strings.Repeat("e", startingBufLen))
   103  	buffer, err := getSrcBuffer(stdOutBytes, stdErrBytes)
   104  	if err != nil {
   105  		t.Fatal(err)
   106  	}
   107  	written, err := StdCopy(ioutil.Discard, ioutil.Discard, buffer)
   108  	if err != nil {
   109  		t.Fatal(err)
   110  	}
   111  	expectedTotalWritten := len(stdOutBytes) + len(stdErrBytes)
   112  	if written != int64(expectedTotalWritten) {
   113  		t.Fatalf("Expected to have total of %d bytes written, got %d", expectedTotalWritten, written)
   114  	}
   115  }
   116  
   117  type customReader struct {
   118  	n            int
   119  	err          error
   120  	totalCalls   int
   121  	correctCalls int
   122  	src          *bytes.Buffer
   123  }
   124  
   125  func (f *customReader) Read(buf []byte) (int, error) {
   126  	f.totalCalls++
   127  	if f.totalCalls <= f.correctCalls {
   128  		return f.src.Read(buf)
   129  	}
   130  	return f.n, f.err
   131  }
   132  
   133  func TestStdCopyReturnsErrorReadingHeader(t *testing.T) {
   134  	expectedError := errors.New("error")
   135  	reader := &customReader{
   136  		err: expectedError}
   137  	written, err := StdCopy(ioutil.Discard, ioutil.Discard, reader)
   138  	if written != 0 {
   139  		t.Fatalf("Expected 0 bytes read, got %d", written)
   140  	}
   141  	if err != expectedError {
   142  		t.Fatalf("Didn't get expected error")
   143  	}
   144  }
   145  
   146  func TestStdCopyReturnsErrorReadingFrame(t *testing.T) {
   147  	expectedError := errors.New("error")
   148  	stdOutBytes := []byte(strings.Repeat("o", startingBufLen))
   149  	stdErrBytes := []byte(strings.Repeat("e", startingBufLen))
   150  	buffer, err := getSrcBuffer(stdOutBytes, stdErrBytes)
   151  	if err != nil {
   152  		t.Fatal(err)
   153  	}
   154  	reader := &customReader{
   155  		correctCalls: 1,
   156  		n:            stdWriterPrefixLen + 1,
   157  		err:          expectedError,
   158  		src:          buffer}
   159  	written, err := StdCopy(ioutil.Discard, ioutil.Discard, reader)
   160  	if written != 0 {
   161  		t.Fatalf("Expected 0 bytes read, got %d", written)
   162  	}
   163  	if err != expectedError {
   164  		t.Fatalf("Didn't get expected error")
   165  	}
   166  }
   167  
   168  func TestStdCopyDetectsCorruptedFrame(t *testing.T) {
   169  	stdOutBytes := []byte(strings.Repeat("o", startingBufLen))
   170  	stdErrBytes := []byte(strings.Repeat("e", startingBufLen))
   171  	buffer, err := getSrcBuffer(stdOutBytes, stdErrBytes)
   172  	if err != nil {
   173  		t.Fatal(err)
   174  	}
   175  	reader := &customReader{
   176  		correctCalls: 1,
   177  		n:            stdWriterPrefixLen + 1,
   178  		err:          io.EOF,
   179  		src:          buffer}
   180  	written, err := StdCopy(ioutil.Discard, ioutil.Discard, reader)
   181  	if written != startingBufLen {
   182  		t.Fatalf("Expected %d bytes read, got %d", startingBufLen, written)
   183  	}
   184  	if err != nil {
   185  		t.Fatal("Didn't get nil error")
   186  	}
   187  }
   188  
   189  func TestStdCopyWithInvalidInputHeader(t *testing.T) {
   190  	dstOut := NewStdWriter(ioutil.Discard, Stdout)
   191  	dstErr := NewStdWriter(ioutil.Discard, Stderr)
   192  	src := strings.NewReader("Invalid input")
   193  	_, err := StdCopy(dstOut, dstErr, src)
   194  	if err == nil {
   195  		t.Fatal("StdCopy with invalid input header should fail.")
   196  	}
   197  }
   198  
   199  func TestStdCopyWithCorruptedPrefix(t *testing.T) {
   200  	data := []byte{0x01, 0x02, 0x03}
   201  	src := bytes.NewReader(data)
   202  	written, err := StdCopy(nil, nil, src)
   203  	if err != nil {
   204  		t.Fatalf("StdCopy should not return an error with corrupted prefix.")
   205  	}
   206  	if written != 0 {
   207  		t.Fatalf("StdCopy should have written 0, but has written %d", written)
   208  	}
   209  }
   210  
   211  func TestStdCopyReturnsWriteErrors(t *testing.T) {
   212  	stdOutBytes := []byte(strings.Repeat("o", startingBufLen))
   213  	stdErrBytes := []byte(strings.Repeat("e", startingBufLen))
   214  	buffer, err := getSrcBuffer(stdOutBytes, stdErrBytes)
   215  	if err != nil {
   216  		t.Fatal(err)
   217  	}
   218  	expectedError := errors.New("expected")
   219  
   220  	dstOut := &errWriter{err: expectedError}
   221  
   222  	written, err := StdCopy(dstOut, ioutil.Discard, buffer)
   223  	if written != 0 {
   224  		t.Fatalf("StdCopy should have written 0, but has written %d", written)
   225  	}
   226  	if err != expectedError {
   227  		t.Fatalf("Didn't get expected error, got %v", err)
   228  	}
   229  }
   230  
   231  func TestStdCopyDetectsNotFullyWrittenFrames(t *testing.T) {
   232  	stdOutBytes := []byte(strings.Repeat("o", startingBufLen))
   233  	stdErrBytes := []byte(strings.Repeat("e", startingBufLen))
   234  	buffer, err := getSrcBuffer(stdOutBytes, stdErrBytes)
   235  	if err != nil {
   236  		t.Fatal(err)
   237  	}
   238  	dstOut := &errWriter{n: startingBufLen - 10}
   239  
   240  	written, err := StdCopy(dstOut, ioutil.Discard, buffer)
   241  	if written != 0 {
   242  		t.Fatalf("StdCopy should have return 0 written bytes, but returned %d", written)
   243  	}
   244  	if err != io.ErrShortWrite {
   245  		t.Fatalf("Didn't get expected io.ErrShortWrite error")
   246  	}
   247  }
   248  
   249  // TestStdCopyReturnsErrorFromSystem tests that StdCopy correctly returns an
   250  // error, when that error is muxed into the Systemerr stream.
   251  func TestStdCopyReturnsErrorFromSystem(t *testing.T) {
   252  	// write in the basic messages, just so there's some fluff in there
   253  	stdOutBytes := []byte(strings.Repeat("o", startingBufLen))
   254  	stdErrBytes := []byte(strings.Repeat("e", startingBufLen))
   255  	buffer, err := getSrcBuffer(stdOutBytes, stdErrBytes)
   256  	if err != nil {
   257  		t.Fatal(err)
   258  	}
   259  	// add in an error message on the Systemerr stream
   260  	systemErrBytes := []byte(strings.Repeat("S", startingBufLen))
   261  	systemWriter := NewStdWriter(buffer, Systemerr)
   262  	_, err = systemWriter.Write(systemErrBytes)
   263  	if err != nil {
   264  		t.Fatal(err)
   265  	}
   266  
   267  	// now copy and demux. we should expect an error containing the string we
   268  	// wrote out
   269  	_, err = StdCopy(ioutil.Discard, ioutil.Discard, buffer)
   270  	if err == nil {
   271  		t.Fatal("expected error, got none")
   272  	}
   273  	if !strings.Contains(err.Error(), string(systemErrBytes)) {
   274  		t.Fatal("expected error to contain message")
   275  	}
   276  }
   277  
   278  func BenchmarkWrite(b *testing.B) {
   279  	w := NewStdWriter(ioutil.Discard, Stdout)
   280  	data := []byte("Test line for testing stdwriter performance\n")
   281  	data = bytes.Repeat(data, 100)
   282  	b.SetBytes(int64(len(data)))
   283  	b.ResetTimer()
   284  	for i := 0; i < b.N; i++ {
   285  		if _, err := w.Write(data); err != nil {
   286  			b.Fatal(err)
   287  		}
   288  	}
   289  }