| 24 | ) |
| 25 | |
| 26 | func TestAs(t *testing.T) { |
| 27 | tt := testutils.T{t} |
| 28 | |
| 29 | refErr := &myType{msg: "woo"} |
| 30 | |
| 31 | // Check we can fish the leaf back. |
| 32 | var mySlot *myType |
| 33 | tt.Check(errors.As(refErr, &mySlot)) |
| 34 | tt.Check(errors.Is(mySlot, refErr)) |
| 35 | |
| 36 | // Check we can fish it even if behind something else. |
| 37 | // Note: this would fail with xerrors.As() because |
| 38 | // Wrap() uses github.com/pkg/errors which implements |
| 39 | // Cause() but not Unwrap(). |
| 40 | // This may change with https://github.com/pkg/errors/pull/206. |
| 41 | wErr := errors.Wrap(refErr, "hidden") |
| 42 | mySlot = nil |
| 43 | tt.Check(errors.As(wErr, &mySlot)) |
| 44 | tt.Check(errors.Is(mySlot, refErr)) |
| 45 | |
| 46 | // Check we can fish the wrapper back. |
| 47 | refwErr := &myWrapper{cause: errors.New("world"), msg: "hello"} |
| 48 | var mywSlot *myWrapper |
| 49 | tt.Check(errors.As(refwErr, &mywSlot)) |
| 50 | tt.Check(errors.Is(mywSlot, refwErr)) |
| 51 | |
| 52 | // Check that it works even if behind something else. |
| 53 | wwErr := errors.Wrap(refwErr, "hidden") |
| 54 | mywSlot = nil |
| 55 | tt.Check(errors.As(wwErr, &mywSlot)) |
| 56 | tt.Check(errors.Is(mywSlot, refwErr)) |
| 57 | |
| 58 | // Check that it works even if hidden in wrapError |
| 59 | multiWrapErr := fmt.Errorf("test %w test", errors.Wrap(refwErr, "hidden")) |
| 60 | mywSlot = nil |
| 61 | tt.Check(errors.As(multiWrapErr, &mywSlot)) |
| 62 | tt.Check(errors.Is(mywSlot, refwErr)) |
| 63 | |
| 64 | // Check that it works even if hidden in multi-cause wrapErrors |
| 65 | multiWrapErr = fmt.Errorf("error: %w and %w", errors.Wrap(refwErr, "hidden"), errors.New("world")) |
| 66 | mywSlot = nil |
| 67 | tt.Check(errors.As(multiWrapErr, &mywSlot)) |
| 68 | tt.Check(errors.Is(mywSlot, refwErr)) |
| 69 | |
| 70 | // Check that it works even if hidden in custom multi-error |
| 71 | multiWrapErr = &myMultiWrapper{ |
| 72 | causes: []error{errors.Wrap(refwErr, "hidden"), errors.New("world")}, |
| 73 | msg: "errors", |
| 74 | } |
| 75 | mywSlot = nil |
| 76 | tt.Check(errors.As(multiWrapErr, &mywSlot)) |
| 77 | tt.Check(errors.Is(mywSlot, refwErr)) |
| 78 | |
| 79 | // Check that it works even if hidden in a multi-level multi-cause chain |
| 80 | multiWrapErr = fmt.Errorf("error: %w and %w", |
| 81 | &myMultiWrapper{ |
| 82 | causes: []error{errors.New("ignoreme"), errors.New("also ignore")}, |
| 83 | msg: "red herring", |