github.com/xmidt-org/webpa-common@v1.11.9/xerrors/xerrors_test.go (about)

     1  package xerrors
     2  
     3  import (
     4  	"context"
     5  	"errors"
     6  	"fmt"
     7  	"github.com/stretchr/testify/assert"
     8  	"net/http"
     9  	"net/http/httptest"
    10  	"net/url"
    11  	"testing"
    12  	"time"
    13  )
    14  
    15  type subError struct {
    16  	err error
    17  	str string
    18  }
    19  
    20  func (err subError) Error() string {
    21  	return fmt.Sprintf("%s(%s)", err.str, err.err.Error())
    22  }
    23  
    24  type subErrorPtr struct {
    25  	err *error
    26  	str string
    27  }
    28  
    29  func (err subErrorPtr) Error() string {
    30  	return fmt.Sprintf("%s(%s)", err.str, (*err.err).Error())
    31  }
    32  
    33  func TestGetErrorInt(t *testing.T) {
    34  	assert := assert.New(t)
    35  
    36  	assert.Equal(nil, getError(5))
    37  
    38  }
    39  func TestGetErrorString(t *testing.T) {
    40  	assert := assert.New(t)
    41  
    42  	assert.Equal(nil, getError("hi"))
    43  }
    44  func TestGetErrorNil(t *testing.T) {
    45  	assert := assert.New(t)
    46  
    47  	assert.Equal(nil, getError(nil))
    48  }
    49  
    50  func TestGetErrorError(t *testing.T) {
    51  	assert := assert.New(t)
    52  
    53  	expected := errors.New("hi")
    54  	assert.Equal(expected, getError(expected))
    55  }
    56  func TestGetErrorErrorPTR(t *testing.T) {
    57  	assert := assert.New(t)
    58  
    59  	expected := errors.New("hi")
    60  	assert.Equal(expected, getError(&expected))
    61  }
    62  
    63  func TestGetErrorErrorComplex(t *testing.T) {
    64  	assert := assert.New(t)
    65  	type testA struct {
    66  		error
    67  		str string
    68  	}
    69  	expected := testA{errors.New("hi"), "bye"}
    70  	assert.Equal(expected, getError(expected))
    71  }
    72  
    73  func TestGetErrorErrorComplexWithPointer(t *testing.T) {
    74  	assert := assert.New(t)
    75  	type testA struct {
    76  		error
    77  		str string
    78  	}
    79  	expected := testA{errors.New("hi"), "bye"}
    80  	assert.Equal(expected, getError(&expected))
    81  }
    82  
    83  func TestGetErrorNoError(t *testing.T) {
    84  	assert := assert.New(t)
    85  	type testA struct {
    86  		str string
    87  	}
    88  	expected := testA{"bye"}
    89  	assert.Nil(getError(&expected))
    90  }
    91  
    92  func TestFirstCauseCustomSubError(t *testing.T) {
    93  	assert := assert.New(t)
    94  	type testA struct {
    95  		error
    96  		str string
    97  	}
    98  	exectedErr := errors.New("testA")
    99  	test := testA{exectedErr, "cool"}
   100  	assert.Equal(exectedErr, FirstCause(subError{test, "neat"}))
   101  }
   102  
   103  func TestFirstCauseNil(t *testing.T) {
   104  	assert := assert.New(t)
   105  
   106  	assert.Nil(FirstCause(nil))
   107  }
   108  
   109  func TestFirstCauseChainSubError(t *testing.T) {
   110  	assert := assert.New(t)
   111  
   112  	exectedErr := errors.New("expected error")
   113  	test := subError{
   114  		subError{
   115  			subError{
   116  				subErrorPtr{&exectedErr, "cool"},
   117  				"c",
   118  			},
   119  			"b",
   120  		},
   121  		"a",
   122  	}
   123  	assert.Equal(exectedErr, FirstCause(subError{test, "root"}))
   124  }
   125  
   126  func TestGetErrorSubError(t *testing.T) {
   127  	assert := assert.New(t)
   128  
   129  	expected := subError{errors.New("hi"), "bye"}
   130  	assert.Equal(expected, getError(&expected))
   131  }
   132  
   133  func TestFirstCauseBasic(t *testing.T) {
   134  	assert := assert.New(t)
   135  
   136  	err := errors.New("my bad")
   137  	assert.Equal(err, FirstCause(err))
   138  }
   139  
   140  func testFirstCauseHTTPHandler(t *testing.T, serverSleep time.Duration, contextDeadline time.Duration, timeout time.Duration, useDefer bool) {
   141  	assert := assert.New(t)
   142  
   143  	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   144  		time.Sleep(serverSleep)
   145  		fmt.Fprintln(w, "Hello, client")
   146  	}))
   147  	defer ts.Close()
   148  
   149  	client := http.Client{Timeout: timeout}
   150  	req, err := http.NewRequest(http.MethodGet, ts.URL, nil)
   151  	assert.NoError(err)
   152  
   153  	ctx, cancel := context.WithTimeout(context.Background(), contextDeadline)
   154  	if useDefer {
   155  		defer cancel()
   156  	} else {
   157  		cancel() // cancel() is a hook to cancel the deadline
   158  	}
   159  
   160  	reqWithDeadline := req.WithContext(ctx)
   161  
   162  	_, clientErr := client.Do(reqWithDeadline)
   163  
   164  	if !assert.Error(clientErr) {
   165  		assert.FailNow("clientErr can not be nil to continue")
   166  	}
   167  
   168  	xerr := FirstCause(clientErr)
   169  	assert.Equal(clientErr.(*url.Error).Err, xerr)
   170  }
   171  
   172  func TestFirstCauseHTTP(t *testing.T) {
   173  
   174  	testData := []struct {
   175  		name            string
   176  		serverSleep     time.Duration
   177  		contextDeadline time.Duration
   178  		timeout         time.Duration
   179  		useDefer        bool
   180  	}{
   181  		{"client-timeout", time.Second, 500 * time.Millisecond, time.Millisecond, true},
   182  		{"context-cancel", time.Nanosecond, 500 * time.Millisecond, time.Millisecond, false},
   183  		{"context-timeout", time.Second, time.Millisecond, 500 * time.Millisecond, true},
   184  	}
   185  
   186  	for _, record := range testData {
   187  		t.Run(fmt.Sprintf("handle/%s", record.name), func(t *testing.T) {
   188  			testFirstCauseHTTPHandler(t, record.serverSleep, record.contextDeadline, record.timeout, record.useDefer)
   189  		})
   190  	}
   191  }