...

Source file src/github.com/aws/smithy-go/transport/http/internal/io/safe_test.go

Documentation: github.com/aws/smithy-go/transport/http/internal/io

     1  package io
     2  
     3  import (
     4  	"bytes"
     5  	"errors"
     6  	"fmt"
     7  	"io"
     8  	"testing"
     9  )
    10  
    11  type mockReadCloser struct {
    12  	ReadFn  func([]byte) (int, error)
    13  	CloseFn func() error
    14  }
    15  
    16  func (m *mockReadCloser) Read(p []byte) (n int, err error) {
    17  	if m.ReadFn == nil {
    18  		return len(p), nil
    19  	}
    20  	return m.ReadFn(p)
    21  }
    22  
    23  func (m *mockReadCloser) Close() error {
    24  	if m.CloseFn == nil {
    25  		return nil
    26  	}
    27  	return m.CloseFn()
    28  }
    29  
    30  type mockWriteTo struct {
    31  	mockReadCloser
    32  	WriteToFn func(io.Writer) (int64, error)
    33  }
    34  
    35  func (m *mockWriteTo) WriteTo(w io.Writer) (int64, error) {
    36  	if m.WriteToFn == nil {
    37  		return 0, nil
    38  	}
    39  	return m.WriteToFn(w)
    40  }
    41  
    42  func TestNewSafeReadCloser(t *testing.T) {
    43  	cases := map[string]struct {
    44  		ReadCloser io.ReadCloser
    45  		ReadTest   func(*testing.T, *safeReadCloser)
    46  		CloseTest  func(*testing.T, *safeReadCloser)
    47  	}{
    48  		"success read and close": {
    49  			ReadCloser: &mockReadCloser{
    50  				ReadFn: func(bytes []byte) (int, error) {
    51  					bytes[0], bytes[1], bytes[2] = 'f', 'o', 'o'
    52  					return 3, nil
    53  				},
    54  			},
    55  			ReadTest: func(t *testing.T, closer *safeReadCloser) {
    56  				t.Helper()
    57  				bs := make([]byte, 3)
    58  				read, err := closer.Read(bs)
    59  				if err != nil {
    60  					t.Errorf("expect no error, got %v", err)
    61  				}
    62  				if e, a := "foo", string(bs[:read]); e != a {
    63  					t.Errorf("expect %v, got %v", e, a)
    64  				}
    65  			},
    66  			CloseTest: func(t *testing.T, closer *safeReadCloser) {
    67  				t.Helper()
    68  				if err := closer.Close(); err != nil {
    69  					t.Errorf("expect no error, got %v", err)
    70  				}
    71  			},
    72  		},
    73  		"error read": {
    74  			ReadCloser: &mockReadCloser{
    75  				ReadFn: func(bytes []byte) (int, error) {
    76  					return 0, io.ErrUnexpectedEOF
    77  				},
    78  			},
    79  			ReadTest: func(t *testing.T, closer *safeReadCloser) {
    80  				t.Helper()
    81  				_, err := closer.Read([]byte{})
    82  				if err == nil {
    83  					t.Errorf("expect error, got nil")
    84  				}
    85  				if !errors.Is(err, io.ErrUnexpectedEOF) {
    86  					t.Errorf("expect error to be type %T, got %T", io.ErrUnexpectedEOF, err)
    87  				}
    88  			},
    89  		},
    90  		"error close": {
    91  			ReadCloser: &mockReadCloser{
    92  				CloseFn: func() error {
    93  					return fmt.Errorf("foobar error")
    94  				},
    95  			},
    96  			CloseTest: func(t *testing.T, closer *safeReadCloser) {
    97  				t.Helper()
    98  				if err := closer.Close(); err == nil {
    99  					t.Error("expect close error, got nil")
   100  				} else if e, a := "foobar error", err.Error(); e != a {
   101  					t.Errorf("expect %v, got %v", e, a)
   102  				}
   103  			},
   104  		},
   105  	}
   106  
   107  	for name, tt := range cases {
   108  		t.Run(name, func(t *testing.T) {
   109  			sr := NewSafeReadCloser(tt.ReadCloser).(*safeReadCloser)
   110  			if e, a := false, sr.closed; e != a {
   111  				t.Errorf("expect %v, got %v", e, a)
   112  			}
   113  			if tt.ReadTest != nil {
   114  				tt.ReadTest(t, sr)
   115  			}
   116  			if tt.CloseTest != nil {
   117  				tt.CloseTest(t, sr)
   118  			} else {
   119  				sr.Close()
   120  			}
   121  			if e, a := true, sr.closed; e != a {
   122  				t.Errorf("expect %v, got %v", e, a)
   123  			}
   124  			if sr.readCloser != nil {
   125  				t.Errorf("expect reader to be nil after Close")
   126  			}
   127  			if err := sr.Close(); err != nil {
   128  				t.Errorf("expect subsequent Close returns to be nil, got %v", err)
   129  			}
   130  		})
   131  	}
   132  }
   133  
   134  func TestNewSafeReadCloser_WriteTo(t *testing.T) {
   135  	{
   136  		rc := &mockWriteTo{}
   137  		writeToReadCloser := NewSafeReadCloser(rc).(*safeWriteToReadCloser)
   138  		_, err := writeToReadCloser.WriteTo(nil)
   139  		if err != nil {
   140  			t.Errorf("expect no error, got %v", err)
   141  		}
   142  
   143  		err = writeToReadCloser.Close()
   144  		if err != nil {
   145  			t.Errorf("expect no error, got %v", err)
   146  		}
   147  
   148  		_, err = writeToReadCloser.WriteTo(nil)
   149  		if err != io.EOF {
   150  			t.Errorf("expect %T, got %T", io.EOF, err)
   151  		}
   152  	}
   153  	{
   154  		rc := &mockWriteTo{
   155  			WriteToFn: func(writer io.Writer) (int64, error) {
   156  				write, err := writer.Write([]byte("foo"))
   157  				return int64(write), err
   158  			},
   159  		}
   160  		writeToReadCloser := NewSafeReadCloser(rc).(*safeWriteToReadCloser)
   161  		var buf bytes.Buffer
   162  		_, err := writeToReadCloser.WriteTo(&buf)
   163  		if err != nil {
   164  			t.Errorf("expect no error, got %v", err)
   165  		}
   166  		if e, a := "foo", buf.String(); e != a {
   167  			t.Errorf("expect %v, got %v", e, a)
   168  		}
   169  	}
   170  }
   171  

View as plain text