Example #1
0
func TestMultiErrorString(t *testing.T) {
	t.Parallel()

	h := newHarness(t)
	defer h.Stop()

	err := errgroup.MultiError(
		[]error{
			stackerr.New("error"),
			stackerr.Wrap(&parse.Error{Message: "message", Code: 1}),
		},
	)

	h.env.ErrorStack = false
	errStr := errorString(h.env, err)

	ensure.DeepEqual(t, errStr, "multiple errors: error | message")

	h.env.ErrorStack = true
	errStr = errorString(h.env, err)

	ensure.StringContains(t, errStr, "multiple errors")
	ensure.StringContains(t, errStr, `parse: api error with code=1 and message="message"`)
	ensure.StringContains(t, errStr, ".go")
}
Example #2
0
// errorString returns the error string with our without the stack trace
// depending on the environment variable. this exists because we want plain
// messages for end users, but when we're working on the CLI we want the stack
// trace for debugging.
func errorString(e *env, err error) string {
	type hasUnderlying interface {
		HasUnderlying() error
	}

	parseErr := func(err error) error {
		if apiErr, ok := err.(*parse.Error); ok {
			return errors.New(apiErr.Message)
		}
		return err
	}

	lastErr := func(err error) error {
		if serr, ok := err.(*stackerr.Error); ok {
			if errs := stackerr.Underlying(serr); len(errs) != 0 {
				err = errs[len(errs)-1]
			}
		} else {
			if eu, ok := err.(hasUnderlying); ok {
				err = eu.HasUnderlying()
			}
		}

		return parseErr(err)
	}

	if !e.ErrorStack {
		if merr, ok := err.(errgroup.MultiError); ok {
			var multiError []error
			for _, ierr := range []error(merr) {
				multiError = append(multiError, lastErr(ierr))
			}
			err = errgroup.MultiError(multiError)
		} else {
			err = lastErr(err)
		}
		return parseErr(err).Error()
	}

	return err.Error()
}