2018-08-12 16:31:28 +00:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"reflect"
|
|
|
|
|
2019-09-09 23:08:19 +00:00
|
|
|
"github.com/hashicorp/hcl/v2"
|
2018-08-12 16:31:28 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
func findTraversalSpec(got hcl.Traversal, candidates []*TestFileExpectTraversal) *TestFileExpectTraversal {
|
|
|
|
for _, candidate := range candidates {
|
|
|
|
if traversalsAreEquivalent(candidate.Traversal, got) {
|
|
|
|
return candidate
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func findTraversalForSpec(want *TestFileExpectTraversal, have []hcl.Traversal) hcl.Traversal {
|
|
|
|
for _, candidate := range have {
|
|
|
|
if traversalsAreEquivalent(candidate, want.Traversal) {
|
|
|
|
return candidate
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func traversalsAreEquivalent(a, b hcl.Traversal) bool {
|
|
|
|
if len(a) != len(b) {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
for i := range a {
|
|
|
|
aStep := a[i]
|
|
|
|
bStep := b[i]
|
|
|
|
|
|
|
|
if reflect.TypeOf(aStep) != reflect.TypeOf(bStep) {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
// We can now assume that both are of the same type.
|
|
|
|
switch ts := aStep.(type) {
|
|
|
|
|
|
|
|
case hcl.TraverseRoot:
|
|
|
|
if bStep.(hcl.TraverseRoot).Name != ts.Name {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
case hcl.TraverseAttr:
|
|
|
|
if bStep.(hcl.TraverseAttr).Name != ts.Name {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
case hcl.TraverseIndex:
|
|
|
|
if !bStep.(hcl.TraverseIndex).Key.RawEquals(ts.Key) {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
default:
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
// checkTraversalsMatch determines if a given traversal matches the given
|
|
|
|
// expectation, which must've been produced by an earlier call to
|
|
|
|
// findTraversalSpec for the same traversal.
|
|
|
|
func checkTraversalsMatch(got hcl.Traversal, filename string, match *TestFileExpectTraversal) hcl.Diagnostics {
|
|
|
|
var diags hcl.Diagnostics
|
|
|
|
|
|
|
|
gotRng := got.SourceRange()
|
|
|
|
wantRng := match.Range
|
|
|
|
|
|
|
|
if got, want := gotRng.Filename, filename; got != want {
|
|
|
|
diags = append(diags, &hcl.Diagnostic{
|
|
|
|
Severity: hcl.DiagError,
|
|
|
|
Summary: "Incorrect filename in detected traversal",
|
|
|
|
Detail: fmt.Sprintf(
|
|
|
|
"Filename was reported as %q, but was expecting %q.",
|
|
|
|
got, want,
|
|
|
|
),
|
|
|
|
Subject: match.Traversal.SourceRange().Ptr(),
|
|
|
|
})
|
|
|
|
return diags
|
|
|
|
}
|
|
|
|
|
|
|
|
// If we have the expected filename then we'll use that to construct the
|
|
|
|
// full "want range" here so that we can use it to point to the appropriate
|
|
|
|
// location in the remaining diagnostics.
|
|
|
|
wantRng.Filename = filename
|
|
|
|
|
|
|
|
if got, want := gotRng.Start, wantRng.Start; got != want {
|
|
|
|
diags = append(diags, &hcl.Diagnostic{
|
|
|
|
Severity: hcl.DiagError,
|
|
|
|
Summary: "Incorrect start position in detected traversal",
|
|
|
|
Detail: fmt.Sprintf(
|
|
|
|
"Start position was reported as line %d column %d byte %d, but was expecting line %d column %d byte %d.",
|
|
|
|
got.Line, got.Column, got.Byte,
|
|
|
|
want.Line, want.Column, want.Byte,
|
|
|
|
),
|
|
|
|
Subject: &wantRng,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
if got, want := gotRng.End, wantRng.End; got != want {
|
|
|
|
diags = append(diags, &hcl.Diagnostic{
|
|
|
|
Severity: hcl.DiagError,
|
|
|
|
Summary: "Incorrect end position in detected traversal",
|
|
|
|
Detail: fmt.Sprintf(
|
|
|
|
"End position was reported as line %d column %d byte %d, but was expecting line %d column %d byte %d.",
|
|
|
|
got.Line, got.Column, got.Byte,
|
|
|
|
want.Line, want.Column, want.Byte,
|
|
|
|
),
|
|
|
|
Subject: &wantRng,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
return diags
|
|
|
|
}
|