github.com/mailgun/holster/v4@v4.20.0/errors/with_context_test.go (about)

     1  package errors_test
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"io"
     7  	"strings"
     8  	"testing"
     9  
    10  	linq "github.com/ahmetb/go-linq"
    11  	"github.com/mailgun/holster/v4/callstack"
    12  	"github.com/mailgun/holster/v4/errors"
    13  	"github.com/stretchr/testify/assert"
    14  
    15  	stderrors "errors"
    16  )
    17  
    18  type TestError struct {
    19  	Msg string
    20  }
    21  
    22  func (err *TestError) Error() string {
    23  	return err.Msg
    24  }
    25  
    26  func TestContext(t *testing.T) {
    27  	// Wrap an error with context
    28  	err := &TestError{Msg: "query error"}
    29  	wrap := errors.WithContext{"key1": "value1"}.Wrap(err, "message")
    30  	assert.NotNil(t, wrap)
    31  
    32  	// Extract as normal map
    33  	errMap := errors.ToMap(wrap)
    34  	assert.NotNil(t, errMap)
    35  	assert.Equal(t, "value1", errMap["key1"])
    36  
    37  	// Also implements the causer interface
    38  	err = errors.Cause(wrap).(*TestError)
    39  	assert.Equal(t, "query error", err.Msg)
    40  
    41  	out := wrap.Error()
    42  	assert.Equal(t, "message: query error", out)
    43  
    44  	// Should output the message, fields and trace
    45  	out = fmt.Sprintf("%+v", wrap)
    46  	assert.True(t, strings.Contains(out, `message: query error (`))
    47  	assert.True(t, strings.Contains(out, `key1=value1`))
    48  }
    49  
    50  func TestWithStack(t *testing.T) {
    51  	err := errors.WithStack(io.EOF)
    52  
    53  	var files []string
    54  	var funcs []string
    55  	if cast, ok := err.(callstack.HasStackTrace); ok {
    56  		for _, frame := range cast.StackTrace() {
    57  			files = append(files, fmt.Sprintf("%s", frame))
    58  			funcs = append(funcs, fmt.Sprintf("%n", frame))
    59  		}
    60  	}
    61  	assert.True(t, linq.From(files).Contains("with_context_test.go"))
    62  	assert.True(t, linq.From(funcs).Contains("TestWithStack"), funcs)
    63  }
    64  
    65  func TestWrapfNil(t *testing.T) {
    66  	got := errors.WithContext{"some": "context"}.Wrapf(nil, "no error")
    67  	assert.Nil(t, got)
    68  }
    69  
    70  func TestWrapNil(t *testing.T) {
    71  	got := errors.WithContext{"some": "context"}.Wrap(nil, "no error")
    72  	assert.Nil(t, got)
    73  }
    74  
    75  func TestUnwrap(t *testing.T) {
    76  	holsterWrappedErr := errors.WithContext{"some": "context"}.Wrap(context.Canceled, "external timeout")
    77  	assert.True(t, stderrors.Is(holsterWrappedErr, context.Canceled))
    78  
    79  	stdWrappedErr := fmt.Errorf("%w external timeout", context.Canceled)
    80  	assert.True(t, stderrors.Is(stdWrappedErr, context.Canceled))
    81  }