aboutsummaryrefslogtreecommitdiffstats
path: root/vendor/gotest.tools/assert/cmp/result.go
blob: 7c3c37dd721a7e88ae0e088afb17f2af7671665c (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
package cmp

import (
	"bytes"
	"fmt"
	"go/ast"
	"text/template"

	"gotest.tools/internal/source"
)

// Result of a Comparison.
type Result interface {
	Success() bool
}

type result struct {
	success bool
	message string
}

func (r result) Success() bool {
	return r.success
}

func (r result) FailureMessage() string {
	return r.message
}

// ResultSuccess is a constant which is returned by a ComparisonWithResult to
// indicate success.
var ResultSuccess = result{success: true}

// ResultFailure returns a failed Result with a failure message.
func ResultFailure(message string) Result {
	return result{message: message}
}

// ResultFromError returns ResultSuccess if err is nil. Otherwise ResultFailure
// is returned with the error message as the failure message.
func ResultFromError(err error) Result {
	if err == nil {
		return ResultSuccess
	}
	return ResultFailure(err.Error())
}

type templatedResult struct {
	success  bool
	template string
	data     map[string]interface{}
}

func (r templatedResult) Success() bool {
	return r.success
}

func (r templatedResult) FailureMessage(args []ast.Expr) string {
	msg, err := renderMessage(r, args)
	if err != nil {
		return fmt.Sprintf("failed to render failure message: %s", err)
	}
	return msg
}

// ResultFailureTemplate returns a Result with a template string and data which
// can be used to format a failure message. The template may access data from .Data,
// the comparison args with the callArg function, and the formatNode function may
// be used to format the call args.
func ResultFailureTemplate(template string, data map[string]interface{}) Result {
	return templatedResult{template: template, data: data}
}

func renderMessage(result templatedResult, args []ast.Expr) (string, error) {
	tmpl := template.New("failure").Funcs(template.FuncMap{
		"formatNode": source.FormatNode,
		"callArg": func(index int) ast.Expr {
			if index >= len(args) {
				return nil
			}
			return args[index]
		},
	})
	var err error
	tmpl, err = tmpl.Parse(result.template)
	if err != nil {
		return "", err
	}
	buf := new(bytes.Buffer)
	err = tmpl.Execute(buf, map[string]interface{}{
		"Data": result.data,
	})
	return buf.String(), err
}