mirror of
https://github.com/getsops/sops.git
synced 2026-02-05 21:45:26 +01:00
It's been around 9 months since our last vendor update. This is also needed for some new features being worked on for sops workspace. Additionally, this PR regenerates the kms mocks.
561 lines
13 KiB
Go
561 lines
13 KiB
Go
package errors
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"io"
|
|
"regexp"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func TestFormatNew(t *testing.T) {
|
|
tests := []struct {
|
|
error
|
|
format string
|
|
want string
|
|
}{{
|
|
New("error"),
|
|
"%s",
|
|
"error",
|
|
}, {
|
|
New("error"),
|
|
"%v",
|
|
"error",
|
|
}, {
|
|
New("error"),
|
|
"%+v",
|
|
"error\n" +
|
|
"github.com/pkg/errors.TestFormatNew\n" +
|
|
"\t.+/github.com/pkg/errors/format_test.go:26",
|
|
}, {
|
|
New("error"),
|
|
"%q",
|
|
`"error"`,
|
|
}}
|
|
|
|
for i, tt := range tests {
|
|
testFormatRegexp(t, i, tt.error, tt.format, tt.want)
|
|
}
|
|
}
|
|
|
|
func TestFormatErrorf(t *testing.T) {
|
|
tests := []struct {
|
|
error
|
|
format string
|
|
want string
|
|
}{{
|
|
Errorf("%s", "error"),
|
|
"%s",
|
|
"error",
|
|
}, {
|
|
Errorf("%s", "error"),
|
|
"%v",
|
|
"error",
|
|
}, {
|
|
Errorf("%s", "error"),
|
|
"%+v",
|
|
"error\n" +
|
|
"github.com/pkg/errors.TestFormatErrorf\n" +
|
|
"\t.+/github.com/pkg/errors/format_test.go:56",
|
|
}}
|
|
|
|
for i, tt := range tests {
|
|
testFormatRegexp(t, i, tt.error, tt.format, tt.want)
|
|
}
|
|
}
|
|
|
|
func TestFormatWrap(t *testing.T) {
|
|
tests := []struct {
|
|
error
|
|
format string
|
|
want string
|
|
}{{
|
|
Wrap(New("error"), "error2"),
|
|
"%s",
|
|
"error2: error",
|
|
}, {
|
|
Wrap(New("error"), "error2"),
|
|
"%v",
|
|
"error2: error",
|
|
}, {
|
|
Wrap(New("error"), "error2"),
|
|
"%+v",
|
|
"error\n" +
|
|
"github.com/pkg/errors.TestFormatWrap\n" +
|
|
"\t.+/github.com/pkg/errors/format_test.go:82",
|
|
}, {
|
|
Wrap(io.EOF, "error"),
|
|
"%s",
|
|
"error: EOF",
|
|
}, {
|
|
Wrap(io.EOF, "error"),
|
|
"%v",
|
|
"error: EOF",
|
|
}, {
|
|
Wrap(io.EOF, "error"),
|
|
"%+v",
|
|
"EOF\n" +
|
|
"error\n" +
|
|
"github.com/pkg/errors.TestFormatWrap\n" +
|
|
"\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:103\n",
|
|
}, {
|
|
Wrap(New("error with space"), "context"),
|
|
"%q",
|
|
`"context: error with space"`,
|
|
}}
|
|
|
|
for i, tt := range tests {
|
|
testFormatRegexp(t, i, tt.error, tt.format, tt.want)
|
|
}
|
|
}
|
|
|
|
func TestFormatWrapf(t *testing.T) {
|
|
tests := []struct {
|
|
error
|
|
format string
|
|
want string
|
|
}{{
|
|
Wrapf(io.EOF, "error%d", 2),
|
|
"%s",
|
|
"error2: EOF",
|
|
}, {
|
|
Wrapf(io.EOF, "error%d", 2),
|
|
"%v",
|
|
"error2: EOF",
|
|
}, {
|
|
Wrapf(io.EOF, "error%d", 2),
|
|
"%+v",
|
|
"EOF\n" +
|
|
"error2\n" +
|
|
"github.com/pkg/errors.TestFormatWrapf\n" +
|
|
"\t.+/github.com/pkg/errors/format_test.go:134",
|
|
}, {
|
|
Wrapf(New("error"), "error%d", 2),
|
|
"%s",
|
|
"error2: error",
|
|
}, {
|
|
Wrapf(New("error"), "error%d", 2),
|
|
"%v",
|
|
"error2: error",
|
|
}, {
|
|
Wrapf(New("error"), "error%d", 2),
|
|
"%+v",
|
|
"error\n" +
|
|
"github.com/pkg/errors.TestFormatWrapf\n" +
|
|
"\t.+/github.com/pkg/errors/format_test.go:149",
|
|
}}
|
|
|
|
for i, tt := range tests {
|
|
testFormatRegexp(t, i, tt.error, tt.format, tt.want)
|
|
}
|
|
}
|
|
|
|
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 wrappedNew(message string) error { // This function will be mid-stack inlined in go 1.12+
|
|
return New(message)
|
|
}
|
|
|
|
func TestFormatWrappedNew(t *testing.T) {
|
|
tests := []struct {
|
|
error
|
|
format string
|
|
want string
|
|
}{{
|
|
wrappedNew("error"),
|
|
"%+v",
|
|
"error\n" +
|
|
"github.com/pkg/errors.wrappedNew\n" +
|
|
"\t.+/github.com/pkg/errors/format_test.go:364\n" +
|
|
"github.com/pkg/errors.TestFormatWrappedNew\n" +
|
|
"\t.+/github.com/pkg/errors/format_test.go:373",
|
|
}}
|
|
|
|
for i, tt := range tests {
|
|
testFormatRegexp(t, i, tt.error, tt.format, tt.want)
|
|
}
|
|
}
|
|
|
|
func testFormatRegexp(t *testing.T, n int, arg interface{}, format, want string) {
|
|
t.Helper()
|
|
got := fmt.Sprintf(format, arg)
|
|
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):\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) 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)
|
|
}
|
|
}
|
|
}
|