forked from TrueCloudLab/restic
Update pkg/errors to v0.8.0
This commit is contained in:
parent
1794bdc663
commit
3bbcf89105
6 changed files with 545 additions and 31 deletions
4
vendor/manifest
vendored
4
vendor/manifest
vendored
|
@ -34,8 +34,8 @@
|
|||
{
|
||||
"importpath": "github.com/pkg/errors",
|
||||
"repository": "https://github.com/pkg/errors",
|
||||
"revision": "17b591df37844cde689f4d5813e5cea0927d8dd2",
|
||||
"branch": "master"
|
||||
"revision": "645ef00459ed84a119197bfb8d8205042c6df63d",
|
||||
"branch": "HEAD"
|
||||
},
|
||||
{
|
||||
"importpath": "github.com/pkg/profile",
|
||||
|
|
37
vendor/src/github.com/pkg/errors/errors.go
vendored
37
vendor/src/github.com/pkg/errors/errors.go
vendored
|
@ -14,13 +14,18 @@
|
|||
// Adding context to an error
|
||||
//
|
||||
// The errors.Wrap function returns a new error that adds context to the
|
||||
// original error. For example
|
||||
// original error by recording a stack trace at the point Wrap is called,
|
||||
// and the supplied message. For example
|
||||
//
|
||||
// _, err := ioutil.ReadAll(r)
|
||||
// if err != nil {
|
||||
// return errors.Wrap(err, "read failed")
|
||||
// }
|
||||
//
|
||||
// If additional control is required the errors.WithStack and errors.WithMessage
|
||||
// functions destructure errors.Wrap into its component operations of annotating
|
||||
// an error with a stack trace and an a message, respectively.
|
||||
//
|
||||
// Retrieving the cause of an error
|
||||
//
|
||||
// Using errors.Wrap constructs a stack of errors, adding context to the
|
||||
|
@ -134,6 +139,18 @@ func (f *fundamental) Format(s fmt.State, verb rune) {
|
|||
}
|
||||
}
|
||||
|
||||
// WithStack annotates err with a stack trace at the point WithStack was called.
|
||||
// If err is nil, WithStack returns nil.
|
||||
func WithStack(err error) error {
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
return &withStack{
|
||||
err,
|
||||
callers(),
|
||||
}
|
||||
}
|
||||
|
||||
type withStack struct {
|
||||
error
|
||||
*stack
|
||||
|
@ -157,7 +174,8 @@ func (w *withStack) Format(s fmt.State, verb rune) {
|
|||
}
|
||||
}
|
||||
|
||||
// Wrap returns an error annotating err with message.
|
||||
// Wrap returns an error annotating err with a stack trace
|
||||
// at the point Wrap is called, and the supplied message.
|
||||
// If err is nil, Wrap returns nil.
|
||||
func Wrap(err error, message string) error {
|
||||
if err == nil {
|
||||
|
@ -173,7 +191,8 @@ func Wrap(err error, message string) error {
|
|||
}
|
||||
}
|
||||
|
||||
// Wrapf returns an error annotating err with the format specifier.
|
||||
// Wrapf returns an error annotating err with a stack trace
|
||||
// at the point Wrapf is call, and the format specifier.
|
||||
// If err is nil, Wrapf returns nil.
|
||||
func Wrapf(err error, format string, args ...interface{}) error {
|
||||
if err == nil {
|
||||
|
@ -189,6 +208,18 @@ func Wrapf(err error, format string, args ...interface{}) error {
|
|||
}
|
||||
}
|
||||
|
||||
// WithMessage annotates err with a new message.
|
||||
// If err is nil, WithMessage returns nil.
|
||||
func WithMessage(err error, message string) error {
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
return &withMessage{
|
||||
cause: err,
|
||||
msg: message,
|
||||
}
|
||||
}
|
||||
|
||||
type withMessage struct {
|
||||
cause error
|
||||
msg string
|
||||
|
|
91
vendor/src/github.com/pkg/errors/errors_test.go
vendored
91
vendor/src/github.com/pkg/errors/errors_test.go
vendored
|
@ -84,6 +84,18 @@ func TestCause(t *testing.T) {
|
|||
}, {
|
||||
err: x, // return from errors.New
|
||||
want: x,
|
||||
}, {
|
||||
WithMessage(nil, "whoops"),
|
||||
nil,
|
||||
}, {
|
||||
WithMessage(io.EOF, "whoops"),
|
||||
io.EOF,
|
||||
}, {
|
||||
WithStack(nil),
|
||||
nil,
|
||||
}, {
|
||||
WithStack(io.EOF),
|
||||
io.EOF,
|
||||
}}
|
||||
|
||||
for i, tt := range tests {
|
||||
|
@ -137,23 +149,78 @@ func TestErrorf(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestWithStackNil(t *testing.T) {
|
||||
got := WithStack(nil)
|
||||
if got != nil {
|
||||
t.Errorf("WithStack(nil): got %#v, expected nil", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestWithStack(t *testing.T) {
|
||||
tests := []struct {
|
||||
err error
|
||||
want string
|
||||
}{
|
||||
{io.EOF, "EOF"},
|
||||
{WithStack(io.EOF), "EOF"},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
got := WithStack(tt.err).Error()
|
||||
if got != tt.want {
|
||||
t.Errorf("WithStack(%v): got: %v, want %v", tt.err, got, tt.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestWithMessageNil(t *testing.T) {
|
||||
got := WithMessage(nil, "no error")
|
||||
if got != nil {
|
||||
t.Errorf("WithMessage(nil, \"no error\"): got %#v, expected nil", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestWithMessage(t *testing.T) {
|
||||
tests := []struct {
|
||||
err error
|
||||
message string
|
||||
want string
|
||||
}{
|
||||
{io.EOF, "read error", "read error: EOF"},
|
||||
{WithMessage(io.EOF, "read error"), "client error", "client error: read error: EOF"},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
got := WithMessage(tt.err, tt.message).Error()
|
||||
if got != tt.want {
|
||||
t.Errorf("WithMessage(%v, %q): got: %q, want %q", tt.err, tt.message, got, tt.want)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// errors.New, etc values are not expected to be compared by value
|
||||
// but the change in errors#27 made them incomparable. Assert that
|
||||
// various kinds of errors have a functional equality operator, even
|
||||
// if the result of that equality is always false.
|
||||
func TestErrorEquality(t *testing.T) {
|
||||
tests := []struct {
|
||||
err1, err2 error
|
||||
}{
|
||||
{io.EOF, io.EOF},
|
||||
{io.EOF, nil},
|
||||
{io.EOF, errors.New("EOF")},
|
||||
{io.EOF, New("EOF")},
|
||||
{New("EOF"), New("EOF")},
|
||||
{New("EOF"), Errorf("EOF")},
|
||||
{New("EOF"), Wrap(io.EOF, "EOF")},
|
||||
vals := []error{
|
||||
nil,
|
||||
io.EOF,
|
||||
errors.New("EOF"),
|
||||
New("EOF"),
|
||||
Errorf("EOF"),
|
||||
Wrap(io.EOF, "EOF"),
|
||||
Wrapf(io.EOF, "EOF%d", 2),
|
||||
WithMessage(nil, "whoops"),
|
||||
WithMessage(io.EOF, "whoops"),
|
||||
WithStack(io.EOF),
|
||||
WithStack(nil),
|
||||
}
|
||||
for _, tt := range tests {
|
||||
_ = tt.err1 == tt.err2 // mustn't panic
|
||||
|
||||
for i := range vals {
|
||||
for j := range vals {
|
||||
_ = vals[i] == vals[j] // mustn't panic
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
53
vendor/src/github.com/pkg/errors/example_test.go
vendored
53
vendor/src/github.com/pkg/errors/example_test.go
vendored
|
@ -35,6 +35,59 @@ func ExampleNew_printf() {
|
|||
// /home/dfc/go/src/runtime/asm_amd64.s:2059
|
||||
}
|
||||
|
||||
func ExampleWithMessage() {
|
||||
cause := errors.New("whoops")
|
||||
err := errors.WithMessage(cause, "oh noes")
|
||||
fmt.Println(err)
|
||||
|
||||
// Output: oh noes: whoops
|
||||
}
|
||||
|
||||
func ExampleWithStack() {
|
||||
cause := errors.New("whoops")
|
||||
err := errors.WithStack(cause)
|
||||
fmt.Println(err)
|
||||
|
||||
// Output: whoops
|
||||
}
|
||||
|
||||
func ExampleWithStack_printf() {
|
||||
cause := errors.New("whoops")
|
||||
err := errors.WithStack(cause)
|
||||
fmt.Printf("%+v", err)
|
||||
|
||||
// Example Output:
|
||||
// whoops
|
||||
// github.com/pkg/errors_test.ExampleWithStack_printf
|
||||
// /home/fabstu/go/src/github.com/pkg/errors/example_test.go:55
|
||||
// testing.runExample
|
||||
// /usr/lib/go/src/testing/example.go:114
|
||||
// testing.RunExamples
|
||||
// /usr/lib/go/src/testing/example.go:38
|
||||
// testing.(*M).Run
|
||||
// /usr/lib/go/src/testing/testing.go:744
|
||||
// main.main
|
||||
// github.com/pkg/errors/_test/_testmain.go:106
|
||||
// runtime.main
|
||||
// /usr/lib/go/src/runtime/proc.go:183
|
||||
// runtime.goexit
|
||||
// /usr/lib/go/src/runtime/asm_amd64.s:2086
|
||||
// github.com/pkg/errors_test.ExampleWithStack_printf
|
||||
// /home/fabstu/go/src/github.com/pkg/errors/example_test.go:56
|
||||
// testing.runExample
|
||||
// /usr/lib/go/src/testing/example.go:114
|
||||
// testing.RunExamples
|
||||
// /usr/lib/go/src/testing/example.go:38
|
||||
// testing.(*M).Run
|
||||
// /usr/lib/go/src/testing/testing.go:744
|
||||
// main.main
|
||||
// github.com/pkg/errors/_test/_testmain.go:106
|
||||
// runtime.main
|
||||
// /usr/lib/go/src/runtime/proc.go:183
|
||||
// runtime.goexit
|
||||
// /usr/lib/go/src/runtime/asm_amd64.s:2086
|
||||
}
|
||||
|
||||
func ExampleWrap() {
|
||||
cause := errors.New("whoops")
|
||||
err := errors.Wrap(cause, "oh noes")
|
||||
|
|
385
vendor/src/github.com/pkg/errors/format_test.go
vendored
385
vendor/src/github.com/pkg/errors/format_test.go
vendored
|
@ -1,6 +1,7 @@
|
|||
package errors
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"regexp"
|
||||
|
@ -26,7 +27,7 @@ func TestFormatNew(t *testing.T) {
|
|||
"%+v",
|
||||
"error\n" +
|
||||
"github.com/pkg/errors.TestFormatNew\n" +
|
||||
"\t.+/github.com/pkg/errors/format_test.go:25",
|
||||
"\t.+/github.com/pkg/errors/format_test.go:26",
|
||||
}, {
|
||||
New("error"),
|
||||
"%q",
|
||||
|
@ -56,7 +57,7 @@ func TestFormatErrorf(t *testing.T) {
|
|||
"%+v",
|
||||
"error\n" +
|
||||
"github.com/pkg/errors.TestFormatErrorf\n" +
|
||||
"\t.+/github.com/pkg/errors/format_test.go:55",
|
||||
"\t.+/github.com/pkg/errors/format_test.go:56",
|
||||
}}
|
||||
|
||||
for i, tt := range tests {
|
||||
|
@ -82,7 +83,7 @@ func TestFormatWrap(t *testing.T) {
|
|||
"%+v",
|
||||
"error\n" +
|
||||
"github.com/pkg/errors.TestFormatWrap\n" +
|
||||
"\t.+/github.com/pkg/errors/format_test.go:81",
|
||||
"\t.+/github.com/pkg/errors/format_test.go:82",
|
||||
}, {
|
||||
Wrap(io.EOF, "error"),
|
||||
"%s",
|
||||
|
@ -97,14 +98,14 @@ func TestFormatWrap(t *testing.T) {
|
|||
"EOF\n" +
|
||||
"error\n" +
|
||||
"github.com/pkg/errors.TestFormatWrap\n" +
|
||||
"\t.+/github.com/pkg/errors/format_test.go:95",
|
||||
"\t.+/github.com/pkg/errors/format_test.go:96",
|
||||
}, {
|
||||
Wrap(Wrap(io.EOF, "error1"), "error2"),
|
||||
"%+v",
|
||||
"EOF\n" +
|
||||
"error1\n" +
|
||||
"github.com/pkg/errors.TestFormatWrap\n" +
|
||||
"\t.+/github.com/pkg/errors/format_test.go:102\n",
|
||||
"\t.+/github.com/pkg/errors/format_test.go:103\n",
|
||||
}, {
|
||||
Wrap(New("error with space"), "context"),
|
||||
"%q",
|
||||
|
@ -135,7 +136,7 @@ func TestFormatWrapf(t *testing.T) {
|
|||
"EOF\n" +
|
||||
"error2\n" +
|
||||
"github.com/pkg/errors.TestFormatWrapf\n" +
|
||||
"\t.+/github.com/pkg/errors/format_test.go:133",
|
||||
"\t.+/github.com/pkg/errors/format_test.go:134",
|
||||
}, {
|
||||
Wrapf(New("error"), "error%d", 2),
|
||||
"%s",
|
||||
|
@ -149,7 +150,7 @@ func TestFormatWrapf(t *testing.T) {
|
|||
"%+v",
|
||||
"error\n" +
|
||||
"github.com/pkg/errors.TestFormatWrapf\n" +
|
||||
"\t.+/github.com/pkg/errors/format_test.go:148",
|
||||
"\t.+/github.com/pkg/errors/format_test.go:149",
|
||||
}}
|
||||
|
||||
for i, tt := range tests {
|
||||
|
@ -157,16 +158,378 @@ func TestFormatWrapf(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestFormatWithStack(t *testing.T) {
|
||||
tests := []struct {
|
||||
error
|
||||
format string
|
||||
want []string
|
||||
}{{
|
||||
WithStack(io.EOF),
|
||||
"%s",
|
||||
[]string{"EOF"},
|
||||
}, {
|
||||
WithStack(io.EOF),
|
||||
"%v",
|
||||
[]string{"EOF"},
|
||||
}, {
|
||||
WithStack(io.EOF),
|
||||
"%+v",
|
||||
[]string{"EOF",
|
||||
"github.com/pkg/errors.TestFormatWithStack\n" +
|
||||
"\t.+/github.com/pkg/errors/format_test.go:175"},
|
||||
}, {
|
||||
WithStack(New("error")),
|
||||
"%s",
|
||||
[]string{"error"},
|
||||
}, {
|
||||
WithStack(New("error")),
|
||||
"%v",
|
||||
[]string{"error"},
|
||||
}, {
|
||||
WithStack(New("error")),
|
||||
"%+v",
|
||||
[]string{"error",
|
||||
"github.com/pkg/errors.TestFormatWithStack\n" +
|
||||
"\t.+/github.com/pkg/errors/format_test.go:189",
|
||||
"github.com/pkg/errors.TestFormatWithStack\n" +
|
||||
"\t.+/github.com/pkg/errors/format_test.go:189"},
|
||||
}, {
|
||||
WithStack(WithStack(io.EOF)),
|
||||
"%+v",
|
||||
[]string{"EOF",
|
||||
"github.com/pkg/errors.TestFormatWithStack\n" +
|
||||
"\t.+/github.com/pkg/errors/format_test.go:197",
|
||||
"github.com/pkg/errors.TestFormatWithStack\n" +
|
||||
"\t.+/github.com/pkg/errors/format_test.go:197"},
|
||||
}, {
|
||||
WithStack(WithStack(Wrapf(io.EOF, "message"))),
|
||||
"%+v",
|
||||
[]string{"EOF",
|
||||
"message",
|
||||
"github.com/pkg/errors.TestFormatWithStack\n" +
|
||||
"\t.+/github.com/pkg/errors/format_test.go:205",
|
||||
"github.com/pkg/errors.TestFormatWithStack\n" +
|
||||
"\t.+/github.com/pkg/errors/format_test.go:205",
|
||||
"github.com/pkg/errors.TestFormatWithStack\n" +
|
||||
"\t.+/github.com/pkg/errors/format_test.go:205"},
|
||||
}, {
|
||||
WithStack(Errorf("error%d", 1)),
|
||||
"%+v",
|
||||
[]string{"error1",
|
||||
"github.com/pkg/errors.TestFormatWithStack\n" +
|
||||
"\t.+/github.com/pkg/errors/format_test.go:216",
|
||||
"github.com/pkg/errors.TestFormatWithStack\n" +
|
||||
"\t.+/github.com/pkg/errors/format_test.go:216"},
|
||||
}}
|
||||
|
||||
for i, tt := range tests {
|
||||
testFormatCompleteCompare(t, i, tt.error, tt.format, tt.want, true)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFormatWithMessage(t *testing.T) {
|
||||
tests := []struct {
|
||||
error
|
||||
format string
|
||||
want []string
|
||||
}{{
|
||||
WithMessage(New("error"), "error2"),
|
||||
"%s",
|
||||
[]string{"error2: error"},
|
||||
}, {
|
||||
WithMessage(New("error"), "error2"),
|
||||
"%v",
|
||||
[]string{"error2: error"},
|
||||
}, {
|
||||
WithMessage(New("error"), "error2"),
|
||||
"%+v",
|
||||
[]string{
|
||||
"error",
|
||||
"github.com/pkg/errors.TestFormatWithMessage\n" +
|
||||
"\t.+/github.com/pkg/errors/format_test.go:244",
|
||||
"error2"},
|
||||
}, {
|
||||
WithMessage(io.EOF, "addition1"),
|
||||
"%s",
|
||||
[]string{"addition1: EOF"},
|
||||
}, {
|
||||
WithMessage(io.EOF, "addition1"),
|
||||
"%v",
|
||||
[]string{"addition1: EOF"},
|
||||
}, {
|
||||
WithMessage(io.EOF, "addition1"),
|
||||
"%+v",
|
||||
[]string{"EOF", "addition1"},
|
||||
}, {
|
||||
WithMessage(WithMessage(io.EOF, "addition1"), "addition2"),
|
||||
"%v",
|
||||
[]string{"addition2: addition1: EOF"},
|
||||
}, {
|
||||
WithMessage(WithMessage(io.EOF, "addition1"), "addition2"),
|
||||
"%+v",
|
||||
[]string{"EOF", "addition1", "addition2"},
|
||||
}, {
|
||||
Wrap(WithMessage(io.EOF, "error1"), "error2"),
|
||||
"%+v",
|
||||
[]string{"EOF", "error1", "error2",
|
||||
"github.com/pkg/errors.TestFormatWithMessage\n" +
|
||||
"\t.+/github.com/pkg/errors/format_test.go:272"},
|
||||
}, {
|
||||
WithMessage(Errorf("error%d", 1), "error2"),
|
||||
"%+v",
|
||||
[]string{"error1",
|
||||
"github.com/pkg/errors.TestFormatWithMessage\n" +
|
||||
"\t.+/github.com/pkg/errors/format_test.go:278",
|
||||
"error2"},
|
||||
}, {
|
||||
WithMessage(WithStack(io.EOF), "error"),
|
||||
"%+v",
|
||||
[]string{
|
||||
"EOF",
|
||||
"github.com/pkg/errors.TestFormatWithMessage\n" +
|
||||
"\t.+/github.com/pkg/errors/format_test.go:285",
|
||||
"error"},
|
||||
}, {
|
||||
WithMessage(Wrap(WithStack(io.EOF), "inside-error"), "outside-error"),
|
||||
"%+v",
|
||||
[]string{
|
||||
"EOF",
|
||||
"github.com/pkg/errors.TestFormatWithMessage\n" +
|
||||
"\t.+/github.com/pkg/errors/format_test.go:293",
|
||||
"inside-error",
|
||||
"github.com/pkg/errors.TestFormatWithMessage\n" +
|
||||
"\t.+/github.com/pkg/errors/format_test.go:293",
|
||||
"outside-error"},
|
||||
}}
|
||||
|
||||
for i, tt := range tests {
|
||||
testFormatCompleteCompare(t, i, tt.error, tt.format, tt.want, true)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFormatGeneric(t *testing.T) {
|
||||
starts := []struct {
|
||||
err error
|
||||
want []string
|
||||
}{
|
||||
{New("new-error"), []string{
|
||||
"new-error",
|
||||
"github.com/pkg/errors.TestFormatGeneric\n" +
|
||||
"\t.+/github.com/pkg/errors/format_test.go:315"},
|
||||
}, {Errorf("errorf-error"), []string{
|
||||
"errorf-error",
|
||||
"github.com/pkg/errors.TestFormatGeneric\n" +
|
||||
"\t.+/github.com/pkg/errors/format_test.go:319"},
|
||||
}, {errors.New("errors-new-error"), []string{
|
||||
"errors-new-error"},
|
||||
},
|
||||
}
|
||||
|
||||
wrappers := []wrapper{
|
||||
{
|
||||
func(err error) error { return WithMessage(err, "with-message") },
|
||||
[]string{"with-message"},
|
||||
}, {
|
||||
func(err error) error { return WithStack(err) },
|
||||
[]string{
|
||||
"github.com/pkg/errors.(func·002|TestFormatGeneric.func2)\n\t" +
|
||||
".+/github.com/pkg/errors/format_test.go:333",
|
||||
},
|
||||
}, {
|
||||
func(err error) error { return Wrap(err, "wrap-error") },
|
||||
[]string{
|
||||
"wrap-error",
|
||||
"github.com/pkg/errors.(func·003|TestFormatGeneric.func3)\n\t" +
|
||||
".+/github.com/pkg/errors/format_test.go:339",
|
||||
},
|
||||
}, {
|
||||
func(err error) error { return Wrapf(err, "wrapf-error%d", 1) },
|
||||
[]string{
|
||||
"wrapf-error1",
|
||||
"github.com/pkg/errors.(func·004|TestFormatGeneric.func4)\n\t" +
|
||||
".+/github.com/pkg/errors/format_test.go:346",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for s := range starts {
|
||||
err := starts[s].err
|
||||
want := starts[s].want
|
||||
testFormatCompleteCompare(t, s, err, "%+v", want, false)
|
||||
testGenericRecursive(t, err, want, wrappers, 3)
|
||||
}
|
||||
}
|
||||
|
||||
func testFormatRegexp(t *testing.T, n int, arg interface{}, format, want string) {
|
||||
got := fmt.Sprintf(format, arg)
|
||||
lines := strings.SplitN(got, "\n", -1)
|
||||
for i, w := range strings.SplitN(want, "\n", -1) {
|
||||
match, err := regexp.MatchString(w, lines[i])
|
||||
gotLines := strings.SplitN(got, "\n", -1)
|
||||
wantLines := strings.SplitN(want, "\n", -1)
|
||||
|
||||
if len(wantLines) > len(gotLines) {
|
||||
t.Errorf("test %d: wantLines(%d) > gotLines(%d):\n got: %q\nwant: %q", n+1, len(wantLines), len(gotLines), got, want)
|
||||
return
|
||||
}
|
||||
|
||||
for i, w := range wantLines {
|
||||
match, err := regexp.MatchString(w, gotLines[i])
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !match {
|
||||
t.Errorf("test %d: line %d: fmt.Sprintf(%q, err): got: %q, want: %q", n+1, i+1, format, got, want)
|
||||
t.Errorf("test %d: line %d: fmt.Sprintf(%q, err):\n got: %q\nwant: %q", n+1, i+1, format, got, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var stackLineR = regexp.MustCompile(`\.`)
|
||||
|
||||
// parseBlocks parses input into a slice, where:
|
||||
// - incase entry contains a newline, its a stacktrace
|
||||
// - incase entry contains no newline, its a solo line.
|
||||
//
|
||||
// Detecting stack boundaries only works incase the WithStack-calls are
|
||||
// to be found on the same line, thats why it is optionally here.
|
||||
//
|
||||
// Example use:
|
||||
//
|
||||
// for _, e := range blocks {
|
||||
// if strings.ContainsAny(e, "\n") {
|
||||
// // Match as stack
|
||||
// } else {
|
||||
// // Match as line
|
||||
// }
|
||||
// }
|
||||
//
|
||||
func parseBlocks(input string, detectStackboundaries bool) ([]string, error) {
|
||||
var blocks []string
|
||||
|
||||
stack := ""
|
||||
wasStack := false
|
||||
lines := map[string]bool{} // already found lines
|
||||
|
||||
for _, l := range strings.Split(input, "\n") {
|
||||
isStackLine := stackLineR.MatchString(l)
|
||||
|
||||
switch {
|
||||
case !isStackLine && wasStack:
|
||||
blocks = append(blocks, stack, l)
|
||||
stack = ""
|
||||
lines = map[string]bool{}
|
||||
case isStackLine:
|
||||
if wasStack {
|
||||
// Detecting two stacks after another, possible cause lines match in
|
||||
// our tests due to WithStack(WithStack(io.EOF)) on same line.
|
||||
if detectStackboundaries {
|
||||
if lines[l] {
|
||||
if len(stack) == 0 {
|
||||
return nil, errors.New("len of block must not be zero here")
|
||||
}
|
||||
|
||||
blocks = append(blocks, stack)
|
||||
stack = l
|
||||
lines = map[string]bool{l: true}
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
stack = stack + "\n" + l
|
||||
} else {
|
||||
stack = l
|
||||
}
|
||||
lines[l] = true
|
||||
case !isStackLine && !wasStack:
|
||||
blocks = append(blocks, l)
|
||||
default:
|
||||
return nil, errors.New("must not happen")
|
||||
}
|
||||
|
||||
wasStack = isStackLine
|
||||
}
|
||||
|
||||
// Use up stack
|
||||
if stack != "" {
|
||||
blocks = append(blocks, stack)
|
||||
}
|
||||
return blocks, nil
|
||||
}
|
||||
|
||||
func testFormatCompleteCompare(t *testing.T, n int, arg interface{}, format string, want []string, detectStackBoundaries bool) {
|
||||
gotStr := fmt.Sprintf(format, arg)
|
||||
|
||||
got, err := parseBlocks(gotStr, detectStackBoundaries)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if len(got) != len(want) {
|
||||
t.Fatalf("test %d: fmt.Sprintf(%s, err) -> wrong number of blocks: got(%d) want(%d)\n got: %s\nwant: %s\ngotStr: %q",
|
||||
n+1, format, len(got), len(want), prettyBlocks(got), prettyBlocks(want), gotStr)
|
||||
}
|
||||
|
||||
for i := range got {
|
||||
if strings.ContainsAny(want[i], "\n") {
|
||||
// Match as stack
|
||||
match, err := regexp.MatchString(want[i], got[i])
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !match {
|
||||
t.Fatalf("test %d: block %d: fmt.Sprintf(%q, err):\ngot:\n%q\nwant:\n%q\nall-got:\n%s\nall-want:\n%s\n",
|
||||
n+1, i+1, format, got[i], want[i], prettyBlocks(got), prettyBlocks(want))
|
||||
}
|
||||
} else {
|
||||
// Match as message
|
||||
if got[i] != want[i] {
|
||||
t.Fatalf("test %d: fmt.Sprintf(%s, err) at block %d got != want:\n got: %q\nwant: %q", n+1, format, i+1, got[i], want[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type wrapper struct {
|
||||
wrap func(err error) error
|
||||
want []string
|
||||
}
|
||||
|
||||
func prettyBlocks(blocks []string, prefix ...string) string {
|
||||
var out []string
|
||||
|
||||
for _, b := range blocks {
|
||||
out = append(out, fmt.Sprintf("%v", b))
|
||||
}
|
||||
|
||||
return " " + strings.Join(out, "\n ")
|
||||
}
|
||||
|
||||
func testGenericRecursive(t *testing.T, beforeErr error, beforeWant []string, list []wrapper, maxDepth int) {
|
||||
if len(beforeWant) == 0 {
|
||||
panic("beforeWant must not be empty")
|
||||
}
|
||||
for _, w := range list {
|
||||
if len(w.want) == 0 {
|
||||
panic("want must not be empty")
|
||||
}
|
||||
|
||||
err := w.wrap(beforeErr)
|
||||
|
||||
// Copy required cause append(beforeWant, ..) modified beforeWant subtly.
|
||||
beforeCopy := make([]string, len(beforeWant))
|
||||
copy(beforeCopy, beforeWant)
|
||||
|
||||
beforeWant := beforeCopy
|
||||
last := len(beforeWant) - 1
|
||||
var want []string
|
||||
|
||||
// Merge two stacks behind each other.
|
||||
if strings.ContainsAny(beforeWant[last], "\n") && strings.ContainsAny(w.want[0], "\n") {
|
||||
want = append(beforeWant[:last], append([]string{beforeWant[last] + "((?s).*)" + w.want[0]}, w.want[1:]...)...)
|
||||
} else {
|
||||
want = append(beforeWant, w.want...)
|
||||
}
|
||||
|
||||
testFormatCompleteCompare(t, maxDepth, err, "%+v", want, false)
|
||||
if maxDepth > 0 {
|
||||
testGenericRecursive(t, err, want, list, maxDepth-1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -185,7 +185,7 @@ func TestStackTrace(t *testing.T) {
|
|||
},
|
||||
}, {
|
||||
func() error { return New("ooh") }(), []string{
|
||||
`github.com/pkg/errors.(func·005|TestStackTrace.func1)` +
|
||||
`github.com/pkg/errors.(func·009|TestStackTrace.func1)` +
|
||||
"\n\t.+/github.com/pkg/errors/stack_test.go:187", // this is the stack of New
|
||||
"github.com/pkg/errors.TestStackTrace\n" +
|
||||
"\t.+/github.com/pkg/errors/stack_test.go:187", // this is the stack of New's caller
|
||||
|
@ -196,9 +196,9 @@ func TestStackTrace(t *testing.T) {
|
|||
return Errorf("hello %s", fmt.Sprintf("world"))
|
||||
}()
|
||||
}()), []string{
|
||||
`github.com/pkg/errors.(func·006|TestStackTrace.func2.1)` +
|
||||
`github.com/pkg/errors.(func·010|TestStackTrace.func2.1)` +
|
||||
"\n\t.+/github.com/pkg/errors/stack_test.go:196", // this is the stack of Errorf
|
||||
`github.com/pkg/errors.(func·007|TestStackTrace.func2)` +
|
||||
`github.com/pkg/errors.(func·011|TestStackTrace.func2)` +
|
||||
"\n\t.+/github.com/pkg/errors/stack_test.go:197", // this is the stack of Errorf's caller
|
||||
"github.com/pkg/errors.TestStackTrace\n" +
|
||||
"\t.+/github.com/pkg/errors/stack_test.go:198", // this is the stack of Errorf's caller's caller
|
||||
|
|
Loading…
Reference in a new issue