Skip to content

Commit

Permalink
Remove all go 1.20 features from test usage
Browse files Browse the repository at this point in the history
This commit removes all test code that references:
- go 1.20 `errors.Join` function.
- go 1.20 multi-cause `fmt.Errorf` that contain multiple `%w`
formatting directives.

This commit also reverts go.mod to use 1.17 to match the state of the
codebase from before the go 1.20 upgrade.

This allows older codebases to upgrade to a version of this library
that can encode/decode multi-cause errors from newer versions without
completely discarding the child cause error info.
  • Loading branch information
dhartunian committed Aug 24, 2023
1 parent ca59e56 commit 29c8643
Show file tree
Hide file tree
Showing 20 changed files with 1,638 additions and 3,032 deletions.
8 changes: 5 additions & 3 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ name: Go

on:
push:
branches: [ master ]
branches: [ master, go-1.17-compat ]
pull_request:
branches: [ master ]
branches: [ master, go-1.17-compat ]

jobs:

Expand All @@ -13,8 +13,10 @@ jobs:
strategy:
matrix:
go:
- "1.17"
- "1.18"
- "1.19"
- "1.20"
- "1.21"
steps:
- uses: actions/checkout@v2

Expand Down
25 changes: 0 additions & 25 deletions errbase/adapters_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,31 +68,6 @@ func TestAdaptGoSingleWrapErr(t *testing.T) {
tt.CheckContains(newErr.Error(), "hello")
}

func TestAdaptBaseGoJoinErr(t *testing.T) {
origErr := goErr.Join(goErr.New("hello"), goErr.New("world"))
t.Logf("start err: %# v", pretty.Formatter(origErr))

newErr := network(t, origErr)

tt := testutils.T{T: t}
// The library preserves the error message.
tt.CheckEqual(newErr.Error(), origErr.Error())

}

func TestAdaptGoMultiWrapErr(t *testing.T) {
origErr := fmt.Errorf("an error %w and also %w", goErr.New("hello"), goErr.New("world"))
t.Logf("start err: %# v", pretty.Formatter(origErr))

newErr := network(t, origErr)

tt := testutils.T{T: t}
// The library preserves the causes. It's not possible to preserve the fmt string.
tt.CheckEqual(newErr.Error(), origErr.Error())
tt.CheckContains(newErr.Error(), "hello")
tt.CheckContains(newErr.Error(), "world")
}

func TestAdaptPkgWithMessage(t *testing.T) {
// Simple message wrappers from github.com/pkg/errors are preserved
// completely.
Expand Down
97 changes: 0 additions & 97 deletions errbase/format_error_internal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,18 +130,6 @@ func TestFormatErrorInternal(t *testing.T) {
Wraps: (2) ab
Wraps: (3) b
Error types: (1) *fmt.wrapError (2) *fmt.wrapError (3) *errors.errorString`,
},
{
name: "simple multi-wrapper",
err: goErr.Join(goErr.New("a"), goErr.New("b")),
expectedSimple: "a\nb",
// TODO(davidh): verbose test case should have line break
// between `a` and `b` on second line.
expectedVerbose: `a
(1) ab
Wraps: (2) b
Wraps: (3) a
Error types: (1) *errors.joinError (2) *errors.errorString (3) *errors.errorString`,
},
{
name: "multi-wrapper with custom formatter and partial elide",
Expand Down Expand Up @@ -190,91 +178,6 @@ Error types: (1) *errbase.wrapNoElideCauses (2) *errbase.wrapNoElideCauses (3) *
| c
| d
Error types: (1) *errors.errorString`,
},
{
name: "two-level multi-wrapper",
err: goErr.Join(
goErr.Join(goErr.New("a"), goErr.New("b")),
goErr.Join(goErr.New("c"), goErr.New("d")),
),
expectedSimple: "a\nb\nc\nd",
// TODO(davidh): verbose output should preserve line breaks after (1)
// and also after (2) and (5) in `c\nd` and `a\nb`.
expectedVerbose: `a
(1) ab
|
| c
| d
Wraps: (2) cd
└─ Wraps: (3) d
└─ Wraps: (4) c
Wraps: (5) ab
└─ Wraps: (6) b
└─ Wraps: (7) a
Error types: (1) *errors.joinError (2) *errors.joinError (3) *errors.errorString (4) *errors.errorString (5) *errors.joinError (6) *errors.errorString (7) *errors.errorString`,
},
{
name: "simple multi-wrapper with single-cause chains inside",
err: goErr.Join(
fmt.Errorf("a%w", goErr.New("b")),
fmt.Errorf("c%w", goErr.New("d")),
),
expectedSimple: "ab\ncd",
expectedVerbose: `ab
(1) ab
| cd
Wraps: (2) cd
└─ Wraps: (3) d
Wraps: (4) ab
└─ Wraps: (5) b
Error types: (1) *errors.joinError (2) *fmt.wrapError (3) *errors.errorString (4) *fmt.wrapError (5) *errors.errorString`,
},
{
name: "multi-cause wrapper with single-cause chains inside",
err: goErr.Join(
fmt.Errorf("a%w", fmt.Errorf("b%w", fmt.Errorf("c%w", goErr.New("d")))),
fmt.Errorf("e%w", fmt.Errorf("f%w", fmt.Errorf("g%w", goErr.New("h")))),
),
expectedSimple: `abcd
efgh`,
expectedVerbose: `abcd
(1) abcd
| efgh
Wraps: (2) efgh
└─ Wraps: (3) fgh
└─ Wraps: (4) gh
└─ Wraps: (5) h
Wraps: (6) abcd
└─ Wraps: (7) bcd
└─ Wraps: (8) cd
└─ Wraps: (9) d
Error types: (1) *errors.joinError (2) *fmt.wrapError (3) *fmt.wrapError (4) *fmt.wrapError (5) *errors.errorString (6) *fmt.wrapError (7) *fmt.wrapError (8) *fmt.wrapError (9) *errors.errorString`},
{
name: "single cause chain with multi-cause wrapper inside with single-cause chains inside",
err: fmt.Errorf(
"prefix1: %w",
fmt.Errorf(
"prefix2: %w",
goErr.Join(
fmt.Errorf("a%w", fmt.Errorf("b%w", fmt.Errorf("c%w", goErr.New("d")))),
fmt.Errorf("e%w", fmt.Errorf("f%w", fmt.Errorf("g%w", goErr.New("h")))),
))),
expectedSimple: `prefix1: prefix2: abcd
efgh`,
expectedVerbose: `prefix1: prefix2: abcd
(1) prefix1
Wraps: (2) prefix2
Wraps: (3) abcd
| efgh
└─ Wraps: (4) efgh
└─ Wraps: (5) fgh
└─ Wraps: (6) gh
└─ Wraps: (7) h
└─ Wraps: (8) abcd
└─ Wraps: (9) bcd
└─ Wraps: (10) cd
└─ Wraps: (11) d
Error types: (1) *fmt.wrapError (2) *fmt.wrapError (3) *errors.joinError (4) *fmt.wrapError (5) *fmt.wrapError (6) *fmt.wrapError (7) *errors.errorString (8) *fmt.wrapError (9) *fmt.wrapError (10) *fmt.wrapError (11) *errors.errorString`,
},
{
name: "test wrapMini elides cause error string",
Expand Down
13 changes: 0 additions & 13 deletions errbase/unwrap_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ package errbase_test

import (
"errors"
"fmt"
"testing"

"github.com/cockroachdb/errors/errbase"
Expand Down Expand Up @@ -59,18 +58,6 @@ func TestMixedErrorWrapping(t *testing.T) {
tt.CheckEqual(errbase.UnwrapAll(err3), err)
}

func TestMultiErrorUnwrap(t *testing.T) {
tt := testutils.T{T: t}

err := errors.New("hello")
err2 := pkgErr.WithMessage(err, "woo")
err3 := fmt.Errorf("%w %w", err, err2)

tt.CheckEqual(errbase.UnwrapOnce(err3), nil)
tt.CheckEqual(errbase.UnwrapAll(err3), err3)
tt.CheckDeepEqual(errbase.UnwrapMulti(err3), []error{err, err2})
}

type myWrapper struct{ cause error }

func (w *myWrapper) Error() string { return w.cause.Error() }
Expand Down
24 changes: 3 additions & 21 deletions errutil/as_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
package errutil_test

import (
goErr "errors"
"fmt"
"testing"

Expand Down Expand Up @@ -61,12 +60,6 @@ func TestAs(t *testing.T) {
tt.Check(errors.As(multiWrapErr, &mywSlot))
tt.Check(errors.Is(mywSlot, refwErr))

// Check that it works even if hidden in multi-cause wrapErrors
multiWrapErr = fmt.Errorf("error: %w and %w", errors.Wrap(refwErr, "hidden"), errors.New("world"))
mywSlot = nil
tt.Check(errors.As(multiWrapErr, &mywSlot))
tt.Check(errors.Is(mywSlot, refwErr))

// Check that it works even if hidden in custom multi-error
multiWrapErr = &myMultiWrapper{
causes: []error{errors.Wrap(refwErr, "hidden"), errors.New("world")},
Expand All @@ -75,19 +68,6 @@ func TestAs(t *testing.T) {
mywSlot = nil
tt.Check(errors.As(multiWrapErr, &mywSlot))
tt.Check(errors.Is(mywSlot, refwErr))

// Check that it works even if hidden in a multi-level multi-cause chain
multiWrapErr = fmt.Errorf("error: %w and %w",
&myMultiWrapper{
causes: []error{errors.New("ignoreme"), errors.New("also ignore")},
msg: "red herring",
}, &myMultiWrapper{
causes: []error{errors.Wrap(refwErr, "hidden"), errors.New("world")},
msg: "errors",
})
mywSlot = nil
tt.Check(errors.As(multiWrapErr, &mywSlot))
tt.Check(errors.Is(mywSlot, refwErr))
}

type myType struct{ msg string }
Expand All @@ -106,7 +86,9 @@ type myMultiWrapper struct {
msg string
}

func (m *myMultiWrapper) Error() string { return fmt.Sprintf("%s: %v", m.msg, goErr.Join(m.causes...)) }
func (m *myMultiWrapper) Error() string {
return fmt.Sprintf("%s: %v", m.msg, errors.Join(m.causes...))
}

func (m *myMultiWrapper) Unwrap() []error {
return m.causes
Expand Down
11 changes: 0 additions & 11 deletions errutil_api_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,8 @@ import (
"testing"

"github.com/cockroachdb/errors"
"github.com/cockroachdb/errors/testutils"
)

func TestUnwrap(t *testing.T) {
tt := testutils.T{t}

e := fmt.Errorf("foo %w %w", fmt.Errorf("bar"), fmt.Errorf("baz"))

// Compatibility with go 1.20: Unwrap() on a multierror returns nil
// (per API documentation)
tt.Check(errors.Unwrap(e) == nil)
}

// More detailed testing of Join is in datadriven_test.go. Here we make
// sure that the public API includes the stacktrace wrapper.
func TestJoin(t *testing.T) {
Expand Down
3 changes: 0 additions & 3 deletions fmttests/datadriven_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -158,9 +158,6 @@ var wrapCommands = map[string]commandFn{
"go-errorf-suffix": func(e error, args []arg) error {
return fmt.Errorf("%w - %s", e, strfy(args))
},
"go-errorf-multi": func(err error, args []arg) error {
return fmt.Errorf("%s - %w %w", strfy(args), err, pkgErr.New("sibling error in wrapper"))
},
"opaque": func(err error, _ []arg) error {
return errbase.DecodeError(context.Background(),
errbase.EncodeError(context.Background(), err))
Expand Down
Loading

0 comments on commit 29c8643

Please sign in to comment.