hcl/hcl/diagnostic_text_test.go
Martin Atkins f45c1cdace hcl: Include variable values in rendered diagnostics messages
If a diagnostic has an associated Expression and EvalContext then we can
look up the values of any variables referenced in the expression and show
them in the diagnostics message as additional context.

This is particularly useful when dealing with situations where a given
expression is evaluated multiple times with different variables, such as
in a 'for' expression, since each evaluation may produce a different set
of diagnostics.
2018-07-28 14:42:53 -07:00

236 lines
4.3 KiB
Go

package hcl
import (
"bytes"
"fmt"
"testing"
"github.com/zclconf/go-cty/cty"
)
func TestDiagnosticTextWriter(t *testing.T) {
tests := []struct {
Input *Diagnostic
Want string
}{
{
&Diagnostic{
Severity: DiagError,
Summary: "Splines not reticulated",
Detail: "All splines must be pre-reticulated.",
Subject: &Range{
Start: Pos{
Byte: 0,
Column: 1,
Line: 1,
},
End: Pos{
Byte: 3,
Column: 4,
Line: 1,
},
},
},
`Error: Splines not reticulated
on line 1, in hardcoded-context:
1: foo = 1
All splines must be pre-reticulated.
`,
},
{
&Diagnostic{
Severity: DiagError,
Summary: "Unsupported attribute",
Detail: `"baz" is not a supported top-level attribute. Did you mean "bam"?`,
Subject: &Range{
Start: Pos{
Byte: 16,
Column: 1,
Line: 3,
},
End: Pos{
Byte: 19,
Column: 4,
Line: 3,
},
},
},
`Error: Unsupported attribute
on line 3, in hardcoded-context:
3: baz = 3
"baz" is not a supported top-level
attribute. Did you mean "bam"?
`,
},
{
&Diagnostic{
Severity: DiagError,
Summary: "Unsupported attribute",
Detail: `"pizza" is not a supported attribute. Did you mean "pizzetta"?`,
Subject: &Range{
Start: Pos{
Byte: 42,
Column: 3,
Line: 5,
},
End: Pos{
Byte: 47,
Column: 8,
Line: 5,
},
},
// This is actually not a great example of a context, but is here to test
// whether we're able to show a multi-line context when needed.
Context: &Range{
Start: Pos{
Byte: 24,
Column: 1,
Line: 4,
},
End: Pos{
Byte: 60,
Column: 2,
Line: 6,
},
},
},
`Error: Unsupported attribute
on line 5, in hardcoded-context:
4: block "party" {
5: pizza = "cheese"
6: }
"pizza" is not a supported attribute.
Did you mean "pizzetta"?
`,
},
{
&Diagnostic{
Severity: DiagError,
Summary: "Test of including relevant variable values",
Detail: `This diagnostic includes an expression and an evalcontext.`,
Subject: &Range{
Start: Pos{
Byte: 42,
Column: 3,
Line: 5,
},
End: Pos{
Byte: 47,
Column: 8,
Line: 5,
},
},
Expression: &diagnosticTestExpr{
vars: []Traversal{
{
TraverseRoot{
Name: "foo",
},
},
{
TraverseRoot{
Name: "bar",
},
TraverseAttr{
Name: "baz",
},
},
{
TraverseRoot{
Name: "missing",
},
},
{
TraverseRoot{
Name: "boz",
},
},
},
},
EvalContext: &EvalContext{
parent: &EvalContext{
Variables: map[string]cty.Value{
"foo": cty.StringVal("foo value"),
},
},
Variables: map[string]cty.Value{
"bar": cty.ObjectVal(map[string]cty.Value{
"baz": cty.ListValEmpty(cty.String),
}),
"boz": cty.NumberIntVal(5),
"unused": cty.True,
},
},
},
`Error: Test of including relevant variable values
on line 5, in hardcoded-context:
5: pizza = "cheese"
with bar.baz as empty list of string,
boz as 5,
foo as "foo value".
This diagnostic includes an expression
and an evalcontext.
`,
},
}
files := map[string]*File{
"": &File{
Bytes: []byte(testDiagnosticTextWriterSource),
Nav: &diagnosticTestNav{},
},
}
for i, test := range tests {
t.Run(fmt.Sprintf("%02d", i), func(t *testing.T) {
bwr := &bytes.Buffer{}
dwr := NewDiagnosticTextWriter(bwr, files, 40, false)
err := dwr.WriteDiagnostic(test.Input)
if err != nil {
t.Fatalf("unexpected error: %s", err)
}
got := bwr.String()
if got != test.Want {
t.Errorf("wrong result\n\ngot:\n%swant:\n%s", got, test.Want)
}
})
}
}
const testDiagnosticTextWriterSource = `foo = 1
bar = 2
baz = 3
block "party" {
pizza = "cheese"
}
`
type diagnosticTestNav struct {
}
func (tn *diagnosticTestNav) ContextString(offset int) string {
return "hardcoded-context"
}
type diagnosticTestExpr struct {
vars []Traversal
staticExpr
}
func (e *diagnosticTestExpr) Variables() []Traversal {
return e.vars
}