320 lines
7.6 KiB
Go
320 lines
7.6 KiB
Go
package json
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/hashicorp/hcl/v2"
|
|
"github.com/zclconf/go-cty/cty"
|
|
)
|
|
|
|
func TestParse_nonObject(t *testing.T) {
|
|
src := `true`
|
|
file, diags := Parse([]byte(src), "")
|
|
if len(diags) != 1 {
|
|
t.Errorf("got %d diagnostics; want 1", len(diags))
|
|
}
|
|
if file == nil {
|
|
t.Errorf("got nil File; want actual file")
|
|
}
|
|
if file.Body == nil {
|
|
t.Fatalf("got nil Body; want actual body")
|
|
}
|
|
if file.Body.(*body).val == nil {
|
|
t.Errorf("got nil Body object; want placeholder object")
|
|
}
|
|
}
|
|
|
|
func TestParseTemplate(t *testing.T) {
|
|
src := `{"greeting": "hello ${\"world\"}"}`
|
|
file, diags := Parse([]byte(src), "")
|
|
if len(diags) != 0 {
|
|
t.Errorf("got %d diagnostics on parse; want 0", len(diags))
|
|
for _, diag := range diags {
|
|
t.Logf("- %s", diag.Error())
|
|
}
|
|
}
|
|
if file == nil {
|
|
t.Errorf("got nil File; want actual file")
|
|
}
|
|
if file.Body == nil {
|
|
t.Fatalf("got nil Body; want actual body")
|
|
}
|
|
attrs, diags := file.Body.JustAttributes()
|
|
if len(diags) != 0 {
|
|
t.Errorf("got %d diagnostics on decode; want 0", len(diags))
|
|
for _, diag := range diags {
|
|
t.Logf("- %s", diag.Error())
|
|
}
|
|
}
|
|
|
|
val, diags := attrs["greeting"].Expr.Value(&hcl.EvalContext{})
|
|
if len(diags) != 0 {
|
|
t.Errorf("got %d diagnostics on eval; want 0", len(diags))
|
|
for _, diag := range diags {
|
|
t.Logf("- %s", diag.Error())
|
|
}
|
|
}
|
|
|
|
if !val.RawEquals(cty.StringVal("hello world")) {
|
|
t.Errorf("wrong result %#v; want %#v", val, cty.StringVal("hello world"))
|
|
}
|
|
}
|
|
|
|
func TestParseTemplateUnwrap(t *testing.T) {
|
|
src := `{"greeting": "${true}"}`
|
|
file, diags := Parse([]byte(src), "")
|
|
if len(diags) != 0 {
|
|
t.Errorf("got %d diagnostics on parse; want 0", len(diags))
|
|
for _, diag := range diags {
|
|
t.Logf("- %s", diag.Error())
|
|
}
|
|
}
|
|
if file == nil {
|
|
t.Errorf("got nil File; want actual file")
|
|
}
|
|
if file.Body == nil {
|
|
t.Fatalf("got nil Body; want actual body")
|
|
}
|
|
attrs, diags := file.Body.JustAttributes()
|
|
if len(diags) != 0 {
|
|
t.Errorf("got %d diagnostics on decode; want 0", len(diags))
|
|
for _, diag := range diags {
|
|
t.Logf("- %s", diag.Error())
|
|
}
|
|
}
|
|
|
|
val, diags := attrs["greeting"].Expr.Value(&hcl.EvalContext{})
|
|
if len(diags) != 0 {
|
|
t.Errorf("got %d diagnostics on eval; want 0", len(diags))
|
|
for _, diag := range diags {
|
|
t.Logf("- %s", diag.Error())
|
|
}
|
|
}
|
|
|
|
if !val.RawEquals(cty.True) {
|
|
t.Errorf("wrong result %#v; want %#v", val, cty.True)
|
|
}
|
|
}
|
|
|
|
func TestParse_malformed(t *testing.T) {
|
|
src := `{
|
|
"http_proxy_url: "http://xxxxxx",
|
|
}`
|
|
file, diags := Parse([]byte(src), "")
|
|
if got, want := len(diags), 2; got != want {
|
|
t.Errorf("got %d diagnostics; want %d", got, want)
|
|
}
|
|
if err, want := diags.Error(), `Missing property value colon`; !strings.Contains(err, want) {
|
|
t.Errorf("diags are %q, but should contain %q", err, want)
|
|
}
|
|
if file == nil {
|
|
t.Errorf("got nil File; want actual file")
|
|
}
|
|
}
|
|
|
|
func TestParseWithStartPos(t *testing.T) {
|
|
src := `{
|
|
"foo": {
|
|
"bar": "baz"
|
|
}
|
|
}`
|
|
part := `{
|
|
"bar": "baz"
|
|
}`
|
|
|
|
file, diags := Parse([]byte(src), "")
|
|
partFile, partDiags := ParseWithStartPos([]byte(part), "", hcl.Pos{Byte: 0, Line: 2, Column: 10})
|
|
if len(diags) != 0 {
|
|
t.Errorf("got %d diagnostics on parse src; want 0", len(diags))
|
|
for _, diag := range diags {
|
|
t.Logf("- %s", diag.Error())
|
|
}
|
|
}
|
|
if len(partDiags) != 0 {
|
|
t.Errorf("got %d diagnostics on parse part src; want 0", len(partDiags))
|
|
for _, diag := range partDiags {
|
|
t.Logf("- %s", diag.Error())
|
|
}
|
|
}
|
|
|
|
if file == nil {
|
|
t.Errorf("got nil File; want actual file")
|
|
}
|
|
if file.Body == nil {
|
|
t.Fatalf("got nil Body; want actual body")
|
|
}
|
|
if partFile == nil {
|
|
t.Errorf("got nil part File; want actual file")
|
|
}
|
|
if partFile.Body == nil {
|
|
t.Fatalf("got nil part Body; want actual body")
|
|
}
|
|
|
|
content, diags := file.Body.Content(&hcl.BodySchema{
|
|
Blocks: []hcl.BlockHeaderSchema{{Type: "foo"}},
|
|
})
|
|
if len(diags) != 0 {
|
|
t.Errorf("got %d diagnostics on decode; want 0", len(diags))
|
|
for _, diag := range diags {
|
|
t.Logf("- %s", diag.Error())
|
|
}
|
|
}
|
|
attrs, diags := content.Blocks[0].Body.JustAttributes()
|
|
if len(diags) != 0 {
|
|
t.Errorf("got %d diagnostics on decode; want 0", len(diags))
|
|
for _, diag := range diags {
|
|
t.Logf("- %s", diag.Error())
|
|
}
|
|
}
|
|
srcRange := attrs["bar"].Expr.Range()
|
|
|
|
partAttrs, diags := partFile.Body.JustAttributes()
|
|
if len(diags) != 0 {
|
|
t.Errorf("got %d diagnostics on decode; want 0", len(diags))
|
|
for _, diag := range diags {
|
|
t.Logf("- %s", diag.Error())
|
|
}
|
|
}
|
|
partRange := partAttrs["bar"].Expr.Range()
|
|
|
|
if srcRange.String() != partRange.String() {
|
|
t.Errorf("The two ranges did not match: src=%s, part=%s", srcRange, partRange)
|
|
}
|
|
}
|
|
|
|
func TestParseExpression(t *testing.T) {
|
|
tests := []struct {
|
|
Input string
|
|
Want string
|
|
}{
|
|
{
|
|
`"hello"`,
|
|
`cty.StringVal("hello")`,
|
|
},
|
|
{
|
|
`"hello ${noun}"`,
|
|
`cty.StringVal("hello world")`,
|
|
},
|
|
{
|
|
"true",
|
|
"cty.True",
|
|
},
|
|
{
|
|
"false",
|
|
"cty.False",
|
|
},
|
|
{
|
|
"1",
|
|
"cty.NumberIntVal(1)",
|
|
},
|
|
{
|
|
"{}",
|
|
"cty.EmptyObjectVal",
|
|
},
|
|
{
|
|
`{"foo":"bar","baz":1}`,
|
|
`cty.ObjectVal(map[string]cty.Value{"baz":cty.NumberIntVal(1), "foo":cty.StringVal("bar")})`,
|
|
},
|
|
{
|
|
"[]",
|
|
"cty.EmptyTupleVal",
|
|
},
|
|
{
|
|
`["1",2,3]`,
|
|
`cty.TupleVal([]cty.Value{cty.StringVal("1"), cty.NumberIntVal(2), cty.NumberIntVal(3)})`,
|
|
},
|
|
}
|
|
|
|
for _, test := range tests {
|
|
t.Run(test.Input, func(t *testing.T) {
|
|
expr, diags := ParseExpression([]byte(test.Input), "")
|
|
if diags.HasErrors() {
|
|
t.Errorf("got %d diagnostics; want 0", len(diags))
|
|
for _, d := range diags {
|
|
t.Logf(" - %s", d.Error())
|
|
}
|
|
}
|
|
|
|
value, diags := expr.Value(&hcl.EvalContext{
|
|
Variables: map[string]cty.Value{
|
|
"noun": cty.StringVal("world"),
|
|
},
|
|
})
|
|
if diags.HasErrors() {
|
|
t.Errorf("got %d diagnostics on decode value; want 0", len(diags))
|
|
for _, d := range diags {
|
|
t.Logf(" - %s", d.Error())
|
|
}
|
|
}
|
|
got := fmt.Sprintf("%#v", value)
|
|
|
|
if got != test.Want {
|
|
t.Errorf("got %s, but want %s", got, test.Want)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestParseExpression_malformed(t *testing.T) {
|
|
src := `invalid`
|
|
expr, diags := ParseExpression([]byte(src), "")
|
|
if got, want := len(diags), 1; got != want {
|
|
t.Errorf("got %d diagnostics; want %d", got, want)
|
|
}
|
|
if err, want := diags.Error(), `Invalid JSON keyword`; !strings.Contains(err, want) {
|
|
t.Errorf("diags are %q, but should contain %q", err, want)
|
|
}
|
|
if expr == nil {
|
|
t.Errorf("got nil Expression; want actual expression")
|
|
}
|
|
}
|
|
|
|
func TestParseExpressionWithStartPos(t *testing.T) {
|
|
src := `{
|
|
"foo": "bar"
|
|
}`
|
|
part := `"bar"`
|
|
|
|
file, diags := Parse([]byte(src), "")
|
|
partExpr, partDiags := ParseExpressionWithStartPos([]byte(part), "", hcl.Pos{Byte: 0, Line: 2, Column: 10})
|
|
if len(diags) != 0 {
|
|
t.Errorf("got %d diagnostics on parse src; want 0", len(diags))
|
|
for _, diag := range diags {
|
|
t.Logf("- %s", diag.Error())
|
|
}
|
|
}
|
|
if len(partDiags) != 0 {
|
|
t.Errorf("got %d diagnostics on parse part src; want 0", len(partDiags))
|
|
for _, diag := range partDiags {
|
|
t.Logf("- %s", diag.Error())
|
|
}
|
|
}
|
|
|
|
if file == nil {
|
|
t.Errorf("got nil File; want actual file")
|
|
}
|
|
if file.Body == nil {
|
|
t.Errorf("got nil Body: want actual body")
|
|
}
|
|
if partExpr == nil {
|
|
t.Errorf("got nil Expression; want actual expression")
|
|
}
|
|
|
|
content, diags := file.Body.Content(&hcl.BodySchema{
|
|
Attributes: []hcl.AttributeSchema{{Name: "foo"}},
|
|
})
|
|
if len(diags) != 0 {
|
|
t.Errorf("got %d diagnostics on decode; want 0", len(diags))
|
|
for _, diag := range diags {
|
|
t.Logf("- %s", diag.Error())
|
|
}
|
|
}
|
|
expr := content.Attributes["foo"].Expr
|
|
|
|
if expr.Range().String() != partExpr.Range().String() {
|
|
t.Errorf("The two ranges did not match: src=%s, part=%s", expr.Range(), partExpr.Range())
|
|
}
|
|
}
|