11 "github.com/hashicorp/hcl/hcl/ast"
12 "github.com/hashicorp/hcl/hcl/token"
15 func TestType(t *testing.T) {
16 var literals = []struct {
20 {token.STRING, `"foo": "bar"`},
21 {token.NUMBER, `"foo": 123`},
22 {token.FLOAT, `"foo": 123.12`},
23 {token.FLOAT, `"foo": -123.12`},
24 {token.BOOL, `"foo": true`},
25 {token.STRING, `"foo": null`},
28 for _, l := range literals {
29 t.Logf("Testing: %s", l.src)
31 p := newParser([]byte(l.src))
32 item, err := p.objectItem()
37 lit, ok := item.Val.(*ast.LiteralType)
39 t.Errorf("node should be of type LiteralType, got: %T", item.Val)
42 if lit.Token.Type != l.typ {
43 t.Errorf("want: %s, got: %s", l.typ, lit.Token.Type)
48 func TestListType(t *testing.T) {
49 var literals = []struct {
54 `"foo": ["123", 123]`,
55 []token.Type{token.STRING, token.NUMBER},
58 `"foo": [123, "123",]`,
59 []token.Type{token.NUMBER, token.STRING},
66 `"foo": ["123", 123]`,
67 []token.Type{token.STRING, token.NUMBER},
71 []token.Type{token.STRING, token.LBRACE},
75 for _, l := range literals {
76 t.Logf("Testing: %s", l.src)
78 p := newParser([]byte(l.src))
79 item, err := p.objectItem()
84 list, ok := item.Val.(*ast.ListType)
86 t.Errorf("node should be of type LiteralType, got: %T", item.Val)
89 tokens := []token.Type{}
90 for _, li := range list.List {
91 switch v := li.(type) {
92 case *ast.LiteralType:
93 tokens = append(tokens, v.Token.Type)
95 tokens = append(tokens, token.LBRACE)
99 equals(t, l.tokens, tokens)
103 func TestObjectType(t *testing.T) {
104 var literals = []struct {
118 []ast.Node{&ast.LiteralType{}},
154 for _, l := range literals {
155 t.Logf("Testing:\n%s\n", l.src)
157 p := newParser([]byte(l.src))
158 // p.enableTrace = true
159 item, err := p.objectItem()
164 // we know that the ObjectKey name is foo for all cases, what matters
166 obj, ok := item.Val.(*ast.ObjectType)
168 t.Errorf("node should be of type LiteralType, got: %T", item.Val)
171 // check if the total length of items are correct
172 equals(t, l.itemLen, len(obj.List.Items))
174 // check if the types are correct
175 for i, item := range obj.List.Items {
176 equals(t, reflect.TypeOf(l.nodeType[i]), reflect.TypeOf(item.Val))
181 func TestFlattenObjects(t *testing.T) {
182 var literals = []struct {
234 for _, l := range literals {
235 t.Logf("Testing:\n%s\n", l.src)
237 f, err := Parse([]byte(l.src))
242 // the first object is always an ObjectList so just assert that one
243 // so we can use it as such
244 obj, ok := f.Node.(*ast.ObjectList)
246 t.Errorf("node should be *ast.ObjectList, got: %T", f.Node)
249 // check if the types are correct
251 for _, item := range obj.Items {
252 equals(t, reflect.TypeOf(l.nodeType[i]), reflect.TypeOf(item.Val))
255 if obj, ok := item.Val.(*ast.ObjectType); ok {
256 for _, item := range obj.List.Items {
257 equals(t, reflect.TypeOf(l.nodeType[i]), reflect.TypeOf(item.Val))
263 // check if the number of items is correct
264 equals(t, l.itemLen, i)
269 func TestObjectKey(t *testing.T) {
274 {[]token.Type{token.STRING}, `"foo": {}`},
277 for _, k := range keys {
278 p := newParser([]byte(k.src))
279 keys, err := p.objectKey()
284 tokens := []token.Type{}
285 for _, o := range keys {
286 tokens = append(tokens, o.Token.Type)
289 equals(t, k.exp, tokens)
292 errKeys := []struct {
301 for _, k := range errKeys {
302 p := newParser([]byte(k.src))
303 _, err := p.objectKey()
305 t.Errorf("case '%s' should give an error", k.src)
310 // Official HCL tests
311 func TestParse(t *testing.T) {
333 "bad_input_128.json",
337 "bad_input_tf_8110.json",
341 "good_input_tf_8110.json",
346 const fixtureDir = "./test-fixtures"
348 for _, tc := range cases {
349 d, err := ioutil.ReadFile(filepath.Join(fixtureDir, tc.Name))
351 t.Fatalf("err: %s", err)
355 if (err != nil) != tc.Err {
356 t.Fatalf("Input: %s\n\nError: %s", tc.Name, err)
361 func TestParse_inline(t *testing.T) {
369 for _, tc := range cases {
370 _, err := Parse([]byte(tc.Value))
371 if (err != nil) != tc.Err {
372 t.Fatalf("Input: %q\n\nError: %s", tc.Value, err)
377 // equals fails the test if exp is not equal to act.
378 func equals(tb testing.TB, exp, act interface{}) {
379 if !reflect.DeepEqual(exp, act) {
380 _, file, line, _ := runtime.Caller(1)
381 fmt.Printf("\033[31m%s:%d:\n\n\texp: %s\n\n\tgot: %s\033[39m\n\n", filepath.Base(file), line, exp, act)