func TestParse(t *testing.T) {
	cases := []struct {
		Name string
		Err  bool
	}{
		{
			"array.json",
			false,
		},
		{
			"basic.json",
			false,
		},
		{
			"object.json",
			false,
		},
		{
			"types.json",
			false,
		},
		{
			"bad_input_128.json",
			true,
		},
		{
			"bad_input_tf_8110.json",
			true,
		},
		{
			"good_input_tf_8110.json",
			false,
		},
	}
	const fixtureDir = "./test-fixtures"
	for _, tc := range cases {
		d, err := ioutil.ReadFile(filepath.Join(fixtureDir, tc.Name))
		if err != nil {
			t.Fatalf("err: %s", err)
		}
		_, err = Parse(d)
		if (err != nil) != tc.Err {
			t.Fatalf("Input: %s\n\nError: %s", tc.Name, err)
		}
	}
}
Official HCL tests
package parser
import (
	"fmt"
	"io/ioutil"
	"path/filepath"
	"reflect"
	"runtime"
	"testing"
	"github.com/hashicorp/hcl/hcl/ast"
	"github.com/hashicorp/hcl/hcl/token"
)
func TestType(t *testing.T) {
	var literals = []struct {
		typ token.Type
		src string
	}{
		{token.STRING, `"foo": "bar"`},
		{token.NUMBER, `"foo": 123`},
		{token.FLOAT, `"foo": 123.12`},
		{token.FLOAT, `"foo": -123.12`},
		{token.BOOL, `"foo": true`},
		{token.STRING, `"foo": null`},
	}
	for _, l := range literals {
		t.Logf("Testing: %s", l.src)
		p := newParser([]byte(l.src))
		item, err := p.objectItem()
		if err != nil {
			t.Error(err)
		}
		lit, ok := item.Val.(*ast.LiteralType)
		if !ok {
			t.Errorf("node should be of type LiteralType, got: %T", item.Val)
		}
		if lit.Token.Type != l.typ {
			t.Errorf("want: %s, got: %s", l.typ, lit.Token.Type)
		}
	}
}
func TestListType(t *testing.T) {
	var literals = []struct {
		src    string
		tokens []token.Type
	}{
		{
			`"foo": ["123", 123]`,
			[]token.Type{token.STRING, token.NUMBER},
		},
		{
			`"foo": [123, "123",]`,
			[]token.Type{token.NUMBER, token.STRING},
		},
		{
			`"foo": []`,
			[]token.Type{},
		},
		{
			`"foo": ["123", 123]`,
			[]token.Type{token.STRING, token.NUMBER},
		},
		{
			`"foo": ["123", {}]`,
			[]token.Type{token.STRING, token.LBRACE},
		},
	}
	for _, l := range literals {
		t.Logf("Testing: %s", l.src)
		p := newParser([]byte(l.src))
		item, err := p.objectItem()
		if err != nil {
			t.Error(err)
		}
		list, ok := item.Val.(*ast.ListType)
		if !ok {
			t.Errorf("node should be of type LiteralType, got: %T", item.Val)
		}
		tokens := []token.Type{}
		for _, li := range list.List {
			switch v := li.(type) {
			case *ast.LiteralType:
				tokens = append(tokens, v.Token.Type)
			case *ast.ObjectType:
				tokens = append(tokens, token.LBRACE)
			}
		}
		equals(t, l.tokens, tokens)
	}
}
func TestObjectType(t *testing.T) {
	var literals = []struct {
		src      string
		nodeType []ast.Node
		itemLen  int
	}{
		{
			`"foo": {}`,
			nil,
			0,
		},
		{
			`"foo": {
				"bar": "fatih"
			 }`,
			[]ast.Node{&ast.LiteralType{}},
			1,
		},
		{
			`"foo": {
				"bar": "fatih",
				"baz": ["arslan"]
			 }`,
			[]ast.Node{
				&ast.LiteralType{},
				&ast.ListType{},
			},
			2,
		},
		{
			`"foo": {
				"bar": {}
			 }`,
			[]ast.Node{
				&ast.ObjectType{},
			},
			1,
		},
		{
			`"foo": {
				"bar": {},
				"foo": true
			 }`,
			[]ast.Node{
				&ast.ObjectType{},
				&ast.LiteralType{},
			},
			2,
		},
	}
	for _, l := range literals {
		t.Logf("Testing:\n%s\n", l.src)
		p := newParser([]byte(l.src))
		item, err := p.objectItem()
		if err != nil {
			t.Error(err)
		}
		obj, ok := item.Val.(*ast.ObjectType)
		if !ok {
			t.Errorf("node should be of type LiteralType, got: %T", item.Val)
		}
		equals(t, l.itemLen, len(obj.List.Items))
		for i, item := range obj.List.Items {
			equals(t, reflect.TypeOf(l.nodeType[i]), reflect.TypeOf(item.Val))
		}
	}
}
func TestFlattenObjects(t *testing.T) {
	var literals = []struct {
		src      string
		nodeType []ast.Node
		itemLen  int
	}{
		{
			`{
					"foo": [
						{
							"foo": "svh",
							"bar": "fatih"
						}
					]
				}`,
			[]ast.Node{
				&ast.ObjectType{},
				&ast.LiteralType{},
				&ast.LiteralType{},
			},
			3,
		},
		{
			`{
					"variable": {
						"foo": {}
					}
				}`,
			[]ast.Node{
				&ast.ObjectType{},
			},
			1,
		},
		{
			`{
				"empty": []
			}`,
			[]ast.Node{
				&ast.ListType{},
			},
			1,
		},
		{
			`{
				"basic": [1, 2, 3]
			}`,
			[]ast.Node{
				&ast.ListType{},
			},
			1,
		},
	}
	for _, l := range literals {
		t.Logf("Testing:\n%s\n", l.src)
		f, err := Parse([]byte(l.src))
		if err != nil {
			t.Error(err)
		}
		obj, ok := f.Node.(*ast.ObjectList)
		if !ok {
			t.Errorf("node should be *ast.ObjectList, got: %T", f.Node)
		}
		var i int
		for _, item := range obj.Items {
			equals(t, reflect.TypeOf(l.nodeType[i]), reflect.TypeOf(item.Val))
			i++
			if obj, ok := item.Val.(*ast.ObjectType); ok {
				for _, item := range obj.List.Items {
					equals(t, reflect.TypeOf(l.nodeType[i]), reflect.TypeOf(item.Val))
					i++
				}
			}
		}
		equals(t, l.itemLen, i)
	}
}
func TestObjectKey(t *testing.T) {
	keys := []struct {
		exp []token.Type
		src string
	}{
		{[]token.Type{token.STRING}, `"foo": {}`},
	}
	for _, k := range keys {
		p := newParser([]byte(k.src))
		keys, err := p.objectKey()
		if err != nil {
			t.Fatal(err)
		}
		tokens := []token.Type{}
		for _, o := range keys {
			tokens = append(tokens, o.Token.Type)
		}
		equals(t, k.exp, tokens)
	}
	errKeys := []struct {
		src string
	}{
		{`foo 12 {}`},
		{`foo bar = {}`},
		{`foo []`},
		{`12 {}`},
	}
	for _, k := range errKeys {
		p := newParser([]byte(k.src))
		_, err := p.objectKey()
		if err == nil {
			t.Errorf("case '%s' should give an error", k.src)
		}
	}
}