blob: c4c32f053037edea7fcfd33b13388f073d020302 [file] [log] [blame] [edit]
// Copyright 2014 Canonical Ltd.
// Licensed under the LGPLv3, see LICENCE file for details.
package errors_test
import (
"fmt"
"runtime"
gc "gopkg.in/check.v1"
"github.com/juju/errors"
)
type errorsSuite struct{}
var _ = gc.Suite(&errorsSuite{})
var someErr = errors.New("some error") //err varSomeErr
func (*errorsSuite) TestErrorString(c *gc.C) {
for i, test := range []struct {
message string
generator func() error
expected string
}{
{
message: "uncomparable errors",
generator: func() error {
err := errors.Annotatef(newNonComparableError("uncomparable"), "annotation")
return errors.Annotatef(err, "another")
},
expected: "another: annotation: uncomparable",
}, {
message: "Errorf",
generator: func() error {
return errors.Errorf("first error")
},
expected: "first error",
}, {
message: "annotated error",
generator: func() error {
err := errors.Errorf("first error")
return errors.Annotatef(err, "annotation")
},
expected: "annotation: first error",
}, {
message: "test annotation format",
generator: func() error {
err := errors.Errorf("first %s", "error")
return errors.Annotatef(err, "%s", "annotation")
},
expected: "annotation: first error",
}, {
message: "wrapped error",
generator: func() error {
err := newError("first error")
return errors.Wrap(err, newError("detailed error"))
},
expected: "detailed error",
}, {
message: "wrapped annotated error",
generator: func() error {
err := errors.Errorf("first error")
err = errors.Annotatef(err, "annotated")
return errors.Wrap(err, fmt.Errorf("detailed error"))
},
expected: "detailed error",
}, {
message: "annotated wrapped error",
generator: func() error {
err := errors.Errorf("first error")
err = errors.Wrap(err, fmt.Errorf("detailed error"))
return errors.Annotatef(err, "annotated")
},
expected: "annotated: detailed error",
}, {
message: "traced, and annotated",
generator: func() error {
err := errors.New("first error")
err = errors.Trace(err)
err = errors.Annotate(err, "some context")
err = errors.Trace(err)
err = errors.Annotate(err, "more context")
return errors.Trace(err)
},
expected: "more context: some context: first error",
}, {
message: "traced, and annotated, masked and annotated",
generator: func() error {
err := errors.New("first error")
err = errors.Trace(err)
err = errors.Annotate(err, "some context")
err = errors.Maskf(err, "masked")
err = errors.Annotate(err, "more context")
return errors.Trace(err)
},
expected: "more context: masked: some context: first error",
}, {
message: "error traced then unwrapped",
generator: func() error {
err := errors.New("inner error")
err = errors.Trace(err)
return errors.Unwrap(err)
},
expected: "inner error",
}, {
message: "error annotated then unwrapped",
generator: func() error {
err := errors.New("inner error")
err = errors.Annotate(err, "annotation")
return errors.Unwrap(err)
},
expected: "inner error",
}, {
message: "error wrapped then unwrapped",
generator: func() error {
err := errors.New("inner error")
err = errors.Wrap(err, errors.New("cause"))
return errors.Unwrap(err)
},
expected: "inner error",
}, {
message: "error masked then unwrapped",
generator: func() error {
err := errors.New("inner error")
err = errors.Mask(err)
return errors.Unwrap(err)
},
expected: "inner error",
},
} {
c.Logf("%v: %s", i, test.message)
err := test.generator()
ok := c.Check(err.Error(), gc.Equals, test.expected)
if !ok {
c.Logf("%#v", test.generator())
}
}
}
func (*errorsSuite) TestNewErr(c *gc.C) {
if runtime.Compiler == "gccgo" {
c.Skip("gccgo can't determine the location")
}
err := errors.NewErr("testing %d", 42)
err.SetLocation(0)
locLine := errorLocationValue(c)
c.Assert(err.Error(), gc.Equals, "testing 42")
c.Assert(errors.Cause(&err), gc.Equals, &err)
c.Assert(errors.Details(&err), Contains, locLine)
}
func (*errorsSuite) TestNewErrWithCause(c *gc.C) {
if runtime.Compiler == "gccgo" {
c.Skip("gccgo can't determine the location")
}
causeErr := fmt.Errorf("external error")
err := errors.NewErrWithCause(causeErr, "testing %d", 43)
err.SetLocation(0)
locLine := errorLocationValue(c)
c.Assert(err.Error(), gc.Equals, "testing 43: external error")
c.Assert(errors.Cause(&err), gc.Equals, causeErr)
c.Assert(errors.Details(&err), Contains, locLine)
}
func (*errorsSuite) TestUnwrapNewErrGivesNil(c *gc.C) {
err := errors.New("test error")
c.Assert(errors.Unwrap(err), gc.IsNil)
}
// This is an uncomparable error type, as it is a struct that supports the
// error interface (as opposed to a pointer type).
type error_ struct {
info string
slice []string
}
// Create a non-comparable error
func newNonComparableError(message string) error {
return error_{info: message}
}
func (e error_) Error() string {
return e.info
}
func newError(message string) error {
return testError{message}
}
// The testError is a value type error for ease of seeing results
// when the test fails.
type testError struct {
message string
}
func (e testError) Error() string {
return e.message
}