2015-10-11 23:27:43 +00:00
|
|
|
package parser
|
|
|
|
|
2015-10-15 21:57:57 +00:00
|
|
|
import (
|
|
|
|
"fmt"
|
2015-10-15 23:00:02 +00:00
|
|
|
"path/filepath"
|
|
|
|
"reflect"
|
|
|
|
"runtime"
|
2015-10-15 21:57:57 +00:00
|
|
|
"testing"
|
2015-10-15 23:00:02 +00:00
|
|
|
|
2015-10-16 20:12:26 +00:00
|
|
|
"github.com/fatih/hcl/ast"
|
|
|
|
"github.com/fatih/hcl/token"
|
2015-10-15 21:57:57 +00:00
|
|
|
)
|
2015-10-11 23:27:43 +00:00
|
|
|
|
2015-10-16 23:16:33 +00:00
|
|
|
func TestType(t *testing.T) {
|
|
|
|
var literals = []struct {
|
|
|
|
typ token.Type
|
|
|
|
src string
|
|
|
|
}{
|
|
|
|
{token.STRING, `foo = "foo"`},
|
|
|
|
{token.NUMBER, `foo = 123`},
|
|
|
|
{token.FLOAT, `foo = 123.12`},
|
|
|
|
{token.BOOL, `foo = true`},
|
|
|
|
}
|
2015-10-16 22:14:40 +00:00
|
|
|
|
2015-10-16 23:16:33 +00:00
|
|
|
for _, l := range literals {
|
|
|
|
p := New([]byte(l.src))
|
|
|
|
item, err := p.parseObjectItem()
|
|
|
|
if err != nil {
|
|
|
|
t.Error(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
lit, ok := item.Val.(*ast.LiteralType)
|
|
|
|
if !ok {
|
|
|
|
t.Errorf("node should be of type LiteralType, got: %+v", item.Val)
|
|
|
|
}
|
2015-10-16 19:57:56 +00:00
|
|
|
|
2015-10-16 23:16:33 +00:00
|
|
|
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},
|
|
|
|
},
|
2015-10-16 19:57:56 +00:00
|
|
|
}
|
|
|
|
|
2015-10-16 23:16:33 +00:00
|
|
|
for _, l := range literals {
|
|
|
|
p := New([]byte(l.src))
|
|
|
|
item, err := p.parseObjectItem()
|
|
|
|
if err != nil {
|
|
|
|
t.Error(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
list, ok := item.Val.(*ast.ListType)
|
|
|
|
if !ok {
|
|
|
|
t.Errorf("node should be of type LiteralType, got: %+v", item.Val)
|
|
|
|
}
|
|
|
|
|
2015-10-18 19:51:10 +00:00
|
|
|
tokens := []token.Type{}
|
2015-10-16 23:16:33 +00:00
|
|
|
for _, li := range list.List {
|
|
|
|
if tp, ok := li.(*ast.LiteralType); ok {
|
|
|
|
tokens = append(tokens, tp.Token.Type)
|
2015-10-16 21:00:05 +00:00
|
|
|
}
|
|
|
|
}
|
2015-10-16 23:16:33 +00:00
|
|
|
|
|
|
|
equals(t, l.tokens, tokens)
|
|
|
|
|
|
|
|
}
|
2015-10-16 19:57:56 +00:00
|
|
|
}
|
|
|
|
|
2015-10-16 23:16:33 +00:00
|
|
|
func TestObjectType(t *testing.T) {
|
|
|
|
}
|
|
|
|
|
|
|
|
// func TestParseType(t *testing.T) {
|
|
|
|
// src := `foo {
|
|
|
|
// fatih = "true"
|
|
|
|
// }`
|
|
|
|
//
|
|
|
|
// p := New([]byte(src))
|
|
|
|
// p.enableTrace = true
|
|
|
|
//
|
|
|
|
// node, err := p.Parse()
|
|
|
|
// if err != nil {
|
|
|
|
// t.Fatal(err)
|
|
|
|
// }
|
|
|
|
//
|
|
|
|
// ast.Walk(node, func(n ast.Node) bool {
|
|
|
|
// if list, ok := n.(*ast.ObjectList); ok {
|
|
|
|
// for _, l := range list.Items {
|
|
|
|
// fmt.Printf("l = %+v\n", l)
|
|
|
|
// for _, k := range l.Keys {
|
|
|
|
// fmt.Printf("key = %+v\n", k)
|
|
|
|
// }
|
|
|
|
// fmt.Printf("val = %+v\n", l.Val)
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
// return true
|
|
|
|
// })
|
|
|
|
// }
|
|
|
|
|
2015-10-15 23:00:02 +00:00
|
|
|
func TestObjectKey(t *testing.T) {
|
|
|
|
keys := []struct {
|
2015-10-16 20:23:23 +00:00
|
|
|
exp []token.Type
|
2015-10-15 23:00:02 +00:00
|
|
|
src string
|
|
|
|
}{
|
2015-10-16 20:23:23 +00:00
|
|
|
{[]token.Type{token.IDENT}, `foo {}`},
|
|
|
|
{[]token.Type{token.IDENT}, `foo = {}`},
|
|
|
|
{[]token.Type{token.IDENT}, `foo = bar`},
|
|
|
|
{[]token.Type{token.IDENT}, `foo = 123`},
|
|
|
|
{[]token.Type{token.IDENT}, `foo = "${var.bar}`},
|
|
|
|
{[]token.Type{token.STRING}, `"foo" {}`},
|
|
|
|
{[]token.Type{token.STRING}, `"foo" = {}`},
|
|
|
|
{[]token.Type{token.STRING}, `"foo" = "${var.bar}`},
|
|
|
|
{[]token.Type{token.IDENT, token.IDENT}, `foo bar {}`},
|
|
|
|
{[]token.Type{token.IDENT, token.STRING}, `foo "bar" {}`},
|
|
|
|
{[]token.Type{token.STRING, token.IDENT}, `"foo" bar {}`},
|
|
|
|
{[]token.Type{token.IDENT, token.IDENT, token.IDENT}, `foo bar baz {}`},
|
2015-10-15 23:00:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
for _, k := range keys {
|
|
|
|
p := New([]byte(k.src))
|
|
|
|
keys, err := p.parseObjectKey()
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
2015-10-16 20:23:23 +00:00
|
|
|
tokens := []token.Type{}
|
2015-10-15 23:00:02 +00:00
|
|
|
for _, o := range keys {
|
2015-10-16 20:12:26 +00:00
|
|
|
tokens = append(tokens, o.Token.Type)
|
2015-10-15 23:00:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
equals(t, k.exp, tokens)
|
2015-10-12 07:37:37 +00:00
|
|
|
}
|
2015-10-11 23:27:43 +00:00
|
|
|
|
2015-10-15 23:00:02 +00:00
|
|
|
errKeys := []struct {
|
|
|
|
src string
|
|
|
|
}{
|
|
|
|
{`foo 12 {}`},
|
|
|
|
{`foo bar = {}`},
|
|
|
|
{`foo []`},
|
|
|
|
{`12 {}`},
|
2015-10-11 23:49:07 +00:00
|
|
|
}
|
2015-10-15 21:57:57 +00:00
|
|
|
|
2015-10-15 23:00:02 +00:00
|
|
|
for _, k := range errKeys {
|
|
|
|
p := New([]byte(k.src))
|
|
|
|
_, err := p.parseObjectKey()
|
|
|
|
if err == nil {
|
|
|
|
t.Errorf("case '%s' should give an error", k.src)
|
|
|
|
}
|
2015-10-15 21:57:57 +00:00
|
|
|
}
|
2015-10-15 23:00:02 +00:00
|
|
|
}
|
2015-10-15 21:57:57 +00:00
|
|
|
|
2015-10-15 23:00:02 +00:00
|
|
|
// equals fails the test if exp is not equal to act.
|
|
|
|
func equals(tb testing.TB, exp, act interface{}) {
|
|
|
|
if !reflect.DeepEqual(exp, act) {
|
|
|
|
_, file, line, _ := runtime.Caller(1)
|
|
|
|
fmt.Printf("\033[31m%s:%d:\n\n\texp: %#v\n\n\tgot: %#v\033[39m\n\n", filepath.Base(file), line, exp, act)
|
|
|
|
tb.FailNow()
|
2015-10-15 21:57:57 +00:00
|
|
|
}
|
2015-10-11 23:27:43 +00:00
|
|
|
}
|