...
1 package cmp
2
3 import (
4 "bytes"
5 "fmt"
6 "go/ast"
7 "reflect"
8 "text/template"
9
10 "gotest.tools/v3/internal/source"
11 )
12
13
14 type Result interface {
15 Success() bool
16 }
17
18
19
20
21 type StringResult struct {
22 success bool
23 message string
24 }
25
26
27 func (r StringResult) Success() bool {
28 return r.success
29 }
30
31
32
33 func (r StringResult) FailureMessage() string {
34 return r.message
35 }
36
37
38
39 var ResultSuccess = StringResult{success: true}
40
41
42 func ResultFailure(message string) StringResult {
43 return StringResult{message: message}
44 }
45
46
47
48 func ResultFromError(err error) Result {
49 if err == nil {
50 return ResultSuccess
51 }
52 return ResultFailure(err.Error())
53 }
54
55 type templatedResult struct {
56 template string
57 data map[string]interface{}
58 }
59
60 func (r templatedResult) Success() bool {
61 return false
62 }
63
64 func (r templatedResult) FailureMessage(args []ast.Expr) string {
65 msg, err := renderMessage(r, args)
66 if err != nil {
67 return fmt.Sprintf("failed to render failure message: %s", err)
68 }
69 return msg
70 }
71
72 func (r templatedResult) UpdatedExpected(stackIndex int) error {
73
74 return source.UpdateExpectedValue(stackIndex+1, r.data["x"], r.data["y"])
75 }
76
77
78
79
80
81 func ResultFailureTemplate(template string, data map[string]interface{}) Result {
82 return templatedResult{template: template, data: data}
83 }
84
85 func renderMessage(result templatedResult, args []ast.Expr) (string, error) {
86 tmpl := template.New("failure").Funcs(template.FuncMap{
87 "formatNode": source.FormatNode,
88 "callArg": func(index int) ast.Expr {
89 if index >= len(args) {
90 return nil
91 }
92 return args[index]
93 },
94
95 "notStdlibErrorType": func(typ interface{}) bool {
96 r := reflect.TypeOf(typ)
97 return r != stdlibFmtErrorType && r != stdlibErrorNewType
98 },
99 })
100 var err error
101 tmpl, err = tmpl.Parse(result.template)
102 if err != nil {
103 return "", err
104 }
105 buf := new(bytes.Buffer)
106 err = tmpl.Execute(buf, map[string]interface{}{
107 "Data": result.data,
108 })
109 return buf.String(), err
110 }
111
View as plain text