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 }