Skip to content
This repository was archived by the owner on Dec 1, 2021. It is now read-only.

Commit 162fea7

Browse files
fabstudavecheney
authored andcommitted
tests: added recursively trying out combinations of calls for %+v.
1 parent 542b81d commit 162fea7

File tree

1 file changed

+125
-17
lines changed

1 file changed

+125
-17
lines changed

format_test.go

Lines changed: 125 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,7 @@ func TestFormatWithStack(t *testing.T) {
224224
}}
225225

226226
for i, tt := range tests {
227-
testFormatCompleteCompare(t, i, tt.error, tt.format, tt.want)
227+
testFormatCompleteCompare(t, i, tt.error, tt.format, tt.want, true)
228228
}
229229
}
230230

@@ -304,7 +304,60 @@ func TestFormatWithMessage(t *testing.T) {
304304
}}
305305

306306
for i, tt := range tests {
307-
testFormatCompleteCompare(t, i, tt.error, tt.format, tt.want)
307+
testFormatCompleteCompare(t, i, tt.error, tt.format, tt.want, true)
308+
}
309+
}
310+
311+
func TestFormatGeneric(t *testing.T) {
312+
starts := []struct {
313+
err error
314+
want []string
315+
}{
316+
{New("new-error"), []string{
317+
"new-error",
318+
"github.com/pkg/errors.TestFormatGeneric\n" +
319+
"\t.+/github.com/pkg/errors/format_test.go:311"},
320+
}, {Errorf("errorf-error"), []string{
321+
"errorf-error",
322+
"github.com/pkg/errors.TestFormatGeneric\n" +
323+
"\t.+/github.com/pkg/errors/format_test.go:315"},
324+
}, {errors.New("errors-new-error"), []string{
325+
"errors-new-error"},
326+
},
327+
}
328+
329+
wrappers := []wrapper{
330+
{
331+
func(err error) error { return WithMessage(err, "with-message") },
332+
[]string{"with-message"},
333+
}, {
334+
func(err error) error { return WithStack(err) },
335+
[]string{
336+
"github.com/pkg/errors.TestFormatGeneric.func2\n\t" +
337+
".+/github.com/pkg/errors/format_test.go:329",
338+
},
339+
}, {
340+
func(err error) error { return Wrap(err, "wrap-error") },
341+
[]string{
342+
"wrap-error",
343+
"github.com/pkg/errors.TestFormatGeneric.func3\n\t" +
344+
".+/github.com/pkg/errors/format_test.go:335",
345+
},
346+
}, {
347+
func(err error) error { return Wrapf(err, "wrapf-error%d", 1) },
348+
[]string{
349+
"wrapf-error1",
350+
"github.com/pkg/errors.TestFormatGeneric.func4\n\t" +
351+
".+/github.com/pkg/errors/format_test.go:342",
352+
},
353+
},
354+
}
355+
356+
for s := range starts {
357+
err := starts[s].err
358+
want := starts[s].want
359+
testFormatCompleteCompare(t, s, err, "%+v", want, false)
360+
testGenericRecursive(t, err, want, wrappers, 3)
308361
}
309362
}
310363

@@ -335,6 +388,9 @@ var stackLineR = regexp.MustCompile(`\.`)
335388
// - incase entry contains a newline, its a stacktrace
336389
// - incase entry contains no newline, its a solo line.
337390
//
391+
// Detecting stack boundaries only works incase the WithStack-calls are
392+
// to be found on the same line, thats why it is optionally here.
393+
//
338394
// Example use:
339395
//
340396
// for _, e := range blocks {
@@ -344,7 +400,8 @@ var stackLineR = regexp.MustCompile(`\.`)
344400
// // Match as line
345401
// }
346402
// }
347-
func parseBlocks(input string) ([]string, error) {
403+
//
404+
func parseBlocks(input string, detectStackboundaries bool) ([]string, error) {
348405
var blocks []string
349406

350407
stack := ""
@@ -363,15 +420,17 @@ func parseBlocks(input string) ([]string, error) {
363420
if wasStack {
364421
// Detecting two stacks after another, possible cause lines match in
365422
// our tests due to WithStack(WithStack(io.EOF)) on same line.
366-
if lines[l] {
367-
if len(stack) == 0 {
368-
return nil, errors.New("len of block must not be zero here")
369-
}
423+
if detectStackboundaries {
424+
if lines[l] {
425+
if len(stack) == 0 {
426+
return nil, errors.New("len of block must not be zero here")
427+
}
370428

371-
blocks = append(blocks, stack)
372-
stack = l
373-
lines = map[string]bool{l: true}
374-
continue
429+
blocks = append(blocks, stack)
430+
stack = l
431+
lines = map[string]bool{l: true}
432+
continue
433+
}
375434
}
376435

377436
stack = stack + "\n" + l
@@ -395,17 +454,17 @@ func parseBlocks(input string) ([]string, error) {
395454
return blocks, nil
396455
}
397456

398-
func testFormatCompleteCompare(t *testing.T, n int, arg interface{}, format string, want []string) {
457+
func testFormatCompleteCompare(t *testing.T, n int, arg interface{}, format string, want []string, detectStackBoundaries bool) {
399458
gotStr := fmt.Sprintf(format, arg)
400459

401-
got, err := parseBlocks(gotStr)
460+
got, err := parseBlocks(gotStr, detectStackBoundaries)
402461
if err != nil {
403462
t.Fatal(err)
404463
}
405464

406465
if len(got) != len(want) {
407-
t.Fatalf("test %d: fmt.Sprintf(%s, err) -> wrong number of blocks: got(%d) want(%d)\n got: %q\nwant: %q\ngotStr: %q",
408-
n+1, format, len(got), len(want), got, want, gotStr)
466+
t.Fatalf("test %d: fmt.Sprintf(%s, err) -> wrong number of blocks: got(%d) want(%d)\n got: %s\nwant: %s\ngotStr: %q",
467+
n+1, format, len(got), len(want), prettyBlocks(got), prettyBlocks(want), gotStr)
409468
}
410469

411470
for i := range got {
@@ -416,13 +475,62 @@ func testFormatCompleteCompare(t *testing.T, n int, arg interface{}, format stri
416475
t.Fatal(err)
417476
}
418477
if !match {
419-
t.Errorf("test %d: block %d: fmt.Sprintf(%q, err):\n got: %q\nwant: %q", n+1, i+1, format, got[i], want[i])
478+
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",
479+
n+1, i+1, format, got[i], want[i], prettyBlocks(got), prettyBlocks(want))
420480
}
421481
} else {
422482
// Match as message
423483
if got[i] != want[i] {
424-
t.Errorf("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])
484+
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])
425485
}
426486
}
427487
}
428488
}
489+
490+
type wrapper struct {
491+
wrap func(err error) error
492+
want []string
493+
}
494+
495+
func prettyBlocks(blocks []string, prefix ...string) string {
496+
var out []string
497+
498+
for _, b := range blocks {
499+
out = append(out, fmt.Sprintf("%v", b))
500+
}
501+
502+
return " " + strings.Join(out, "\n ")
503+
}
504+
505+
func testGenericRecursive(t *testing.T, beforeErr error, beforeWant []string, list []wrapper, maxDepth int) {
506+
if len(beforeWant) == 0 {
507+
panic("beforeWant must not be empty")
508+
}
509+
for _, w := range list {
510+
if len(w.want) == 0 {
511+
panic("want must not be empty")
512+
}
513+
514+
err := w.wrap(beforeErr)
515+
516+
// Copy required cause append(beforeWant, ..) modified beforeWant subtly.
517+
beforeCopy := make([]string, len(beforeWant))
518+
copy(beforeCopy, beforeWant)
519+
520+
beforeWant := beforeCopy
521+
last := len(beforeWant) - 1
522+
var want []string
523+
524+
// Merge two stacks behind each other.
525+
if strings.ContainsAny(beforeWant[last], "\n") && strings.ContainsAny(w.want[0], "\n") {
526+
want = append(beforeWant[:last], append([]string{beforeWant[last] + "((?s).*)" + w.want[0]}, w.want[1:]...)...)
527+
} else {
528+
want = append(beforeWant, w.want...)
529+
}
530+
531+
testFormatCompleteCompare(t, maxDepth, err, "%+v", want, false)
532+
if maxDepth > 0 {
533+
testGenericRecursive(t, err, want, list, maxDepth-1)
534+
}
535+
}
536+
}

0 commit comments

Comments
 (0)