github.com/Heebron/moby@v0.0.0-20221111184709-6eab4f55faf7/pkg/stdcopy/stdcopy_test.go (about)

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