deps: Update GoDeps to reflect hashicorp/hil

This commit is contained in:
James Nugent 2016-02-03 13:26:12 -05:00
parent 4576eaa966
commit 0340ea7235
15 changed files with 5 additions and 1611 deletions

6
Godeps/Godeps.json generated
View File

@ -75,8 +75,6 @@
"github.com/hashicorp/terraform/communicator/ssh",
"github.com/hashicorp/terraform/communicator/winrm",
"github.com/hashicorp/terraform/config",
"github.com/hashicorp/terraform/config/lang",
"github.com/hashicorp/terraform/config/lang/ast",
"github.com/hashicorp/terraform/config/module",
"github.com/hashicorp/terraform/dag",
"github.com/hashicorp/terraform/digraph",
@ -499,6 +497,10 @@
"ImportPath": "github.com/hashicorp/hcl",
"Rev": "578dd9746824a54637686b51a41bad457a56bcef"
},
{
"ImportPath": "github.com/hashicorp/hil",
"Rev": "075475a7408f16568f5cf79656dbcb053ac6196b"
},
{
"ImportPath": "github.com/hashicorp/logutils",
"Rev": "0dc08b1671f34c4250ce212759ebd880f743d883"

1
vendor/github.com/hashicorp/hil/.gitignore generated vendored Normal file
View File

@ -0,0 +1 @@
.DS_Store

View File

@ -1,36 +0,0 @@
package ast
import (
"testing"
)
func TestCallType(t *testing.T) {
c := &Call{Func: "foo"}
scope := &BasicScope{
FuncMap: map[string]Function{
"foo": Function{ReturnType: TypeString},
},
}
actual, err := c.Type(scope)
if err != nil {
t.Fatalf("err: %s", err)
}
if actual != TypeString {
t.Fatalf("bad: %s", actual)
}
}
func TestCallType_invalid(t *testing.T) {
c := &Call{Func: "bar"}
scope := &BasicScope{
FuncMap: map[string]Function{
"foo": Function{ReturnType: TypeString},
},
}
_, err := c.Type(scope)
if err == nil {
t.Fatal("should error")
}
}

View File

@ -1,16 +0,0 @@
package ast
import (
"testing"
)
func TestConcatType(t *testing.T) {
c := &Concat{}
actual, err := c.Type(nil)
if err != nil {
t.Fatalf("err: %s", err)
}
if actual != TypeString {
t.Fatalf("bad: %s", actual)
}
}

View File

@ -1,16 +0,0 @@
package ast
import (
"testing"
)
func TestLiteralNodeType(t *testing.T) {
c := &LiteralNode{Typex: TypeString}
actual, err := c.Type(nil)
if err != nil {
t.Fatalf("err: %s", err)
}
if actual != TypeString {
t.Fatalf("bad: %s", actual)
}
}

View File

@ -1,39 +0,0 @@
package ast
import (
"testing"
)
func TestBasicScope_impl(t *testing.T) {
var _ Scope = new(BasicScope)
}
func TestBasicScopeLookupFunc(t *testing.T) {
scope := &BasicScope{
FuncMap: map[string]Function{
"foo": Function{},
},
}
if _, ok := scope.LookupFunc("bar"); ok {
t.Fatal("should not find bar")
}
if _, ok := scope.LookupFunc("foo"); !ok {
t.Fatal("should find foo")
}
}
func TestBasicScopeLookupVar(t *testing.T) {
scope := &BasicScope{
VarMap: map[string]Variable{
"foo": Variable{},
},
}
if _, ok := scope.LookupVar("bar"); ok {
t.Fatal("should not find bar")
}
if _, ok := scope.LookupVar("foo"); !ok {
t.Fatal("should find foo")
}
}

View File

@ -1,46 +0,0 @@
package ast
import (
"reflect"
"testing"
)
func TestStack(t *testing.T) {
var s Stack
if s.Len() != 0 {
t.Fatalf("bad: %d", s.Len())
}
n := &LiteralNode{Value: 42}
s.Push(n)
if s.Len() != 1 {
t.Fatalf("bad: %d", s.Len())
}
actual := s.Pop()
if !reflect.DeepEqual(actual, n) {
t.Fatalf("bad: %#v", actual)
}
if s.Len() != 0 {
t.Fatalf("bad: %d", s.Len())
}
}
func TestStack_reset(t *testing.T) {
var s Stack
n := &LiteralNode{Value: 42}
s.Push(n)
if s.Len() != 1 {
t.Fatalf("bad: %d", s.Len())
}
s.Reset()
if s.Len() != 0 {
t.Fatalf("bad: %d", s.Len())
}
}

View File

@ -1,36 +0,0 @@
package ast
import (
"testing"
)
func TestVariableAccessType(t *testing.T) {
c := &VariableAccess{Name: "foo"}
scope := &BasicScope{
VarMap: map[string]Variable{
"foo": Variable{Type: TypeString},
},
}
actual, err := c.Type(scope)
if err != nil {
t.Fatalf("err: %s", err)
}
if actual != TypeString {
t.Fatalf("bad: %s", actual)
}
}
func TestVariableAccessType_invalid(t *testing.T) {
c := &VariableAccess{Name: "bar"}
scope := &BasicScope{
VarMap: map[string]Variable{
"foo": Variable{Type: TypeString},
},
}
_, err := c.Type(scope)
if err == nil {
t.Fatal("should error")
}
}

View File

@ -1,141 +0,0 @@
package hil
import (
"testing"
"github.com/hashicorp/hil/ast"
)
func TestIdentifierCheck(t *testing.T) {
cases := []struct {
Input string
Scope ast.Scope
Error bool
}{
{
"foo",
&ast.BasicScope{},
false,
},
{
"foo ${bar} success",
&ast.BasicScope{
VarMap: map[string]ast.Variable{
"bar": ast.Variable{
Value: "baz",
Type: ast.TypeString,
},
},
},
false,
},
{
"foo ${bar}",
&ast.BasicScope{},
true,
},
{
"foo ${rand()} success",
&ast.BasicScope{
FuncMap: map[string]ast.Function{
"rand": ast.Function{
ReturnType: ast.TypeString,
Callback: func([]interface{}) (interface{}, error) {
return "42", nil
},
},
},
},
false,
},
{
"foo ${rand()}",
&ast.BasicScope{},
true,
},
{
"foo ${rand(42)} ",
&ast.BasicScope{
FuncMap: map[string]ast.Function{
"rand": ast.Function{
ReturnType: ast.TypeString,
Callback: func([]interface{}) (interface{}, error) {
return "42", nil
},
},
},
},
true,
},
{
"foo ${rand()} ",
&ast.BasicScope{
FuncMap: map[string]ast.Function{
"rand": ast.Function{
ReturnType: ast.TypeString,
Variadic: true,
VariadicType: ast.TypeInt,
Callback: func([]interface{}) (interface{}, error) {
return "42", nil
},
},
},
},
false,
},
{
"foo ${rand(42)} ",
&ast.BasicScope{
FuncMap: map[string]ast.Function{
"rand": ast.Function{
ReturnType: ast.TypeString,
Variadic: true,
VariadicType: ast.TypeInt,
Callback: func([]interface{}) (interface{}, error) {
return "42", nil
},
},
},
},
false,
},
{
"foo ${rand(\"foo\", 42)} ",
&ast.BasicScope{
FuncMap: map[string]ast.Function{
"rand": ast.Function{
ArgTypes: []ast.Type{ast.TypeString},
ReturnType: ast.TypeString,
Variadic: true,
VariadicType: ast.TypeInt,
Callback: func([]interface{}) (interface{}, error) {
return "42", nil
},
},
},
},
false,
},
}
for _, tc := range cases {
node, err := Parse(tc.Input)
if err != nil {
t.Fatalf("Error: %s\n\nInput: %s", err, tc.Input)
}
visitor := &IdentifierCheck{Scope: tc.Scope}
err = visitor.Visit(node)
if err != nil != tc.Error {
t.Fatalf("Error: %s\n\nInput: %s", err, tc.Input)
}
}
}

View File

@ -1,265 +0,0 @@
package hil
import (
"testing"
"github.com/hashicorp/hil/ast"
)
func TestTypeCheck(t *testing.T) {
cases := []struct {
Input string
Scope ast.Scope
Error bool
}{
{
"foo",
&ast.BasicScope{},
false,
},
{
"foo ${bar}",
&ast.BasicScope{
VarMap: map[string]ast.Variable{
"bar": ast.Variable{
Value: "baz",
Type: ast.TypeString,
},
},
},
false,
},
{
"foo ${rand()}",
&ast.BasicScope{
FuncMap: map[string]ast.Function{
"rand": ast.Function{
ReturnType: ast.TypeString,
Callback: func([]interface{}) (interface{}, error) {
return "42", nil
},
},
},
},
false,
},
{
`foo ${rand("42")}`,
&ast.BasicScope{
FuncMap: map[string]ast.Function{
"rand": ast.Function{
ArgTypes: []ast.Type{ast.TypeString},
ReturnType: ast.TypeString,
Callback: func([]interface{}) (interface{}, error) {
return "42", nil
},
},
},
},
false,
},
{
`foo ${rand(42)}`,
&ast.BasicScope{
FuncMap: map[string]ast.Function{
"rand": ast.Function{
ArgTypes: []ast.Type{ast.TypeString},
ReturnType: ast.TypeString,
Callback: func([]interface{}) (interface{}, error) {
return "42", nil
},
},
},
},
true,
},
{
`foo ${rand()}`,
&ast.BasicScope{
FuncMap: map[string]ast.Function{
"rand": ast.Function{
ArgTypes: nil,
ReturnType: ast.TypeString,
Variadic: true,
VariadicType: ast.TypeString,
Callback: func([]interface{}) (interface{}, error) {
return "42", nil
},
},
},
},
false,
},
{
`foo ${rand("42")}`,
&ast.BasicScope{
FuncMap: map[string]ast.Function{
"rand": ast.Function{
ArgTypes: nil,
ReturnType: ast.TypeString,
Variadic: true,
VariadicType: ast.TypeString,
Callback: func([]interface{}) (interface{}, error) {
return "42", nil
},
},
},
},
false,
},
{
`foo ${rand("42", 42)}`,
&ast.BasicScope{
FuncMap: map[string]ast.Function{
"rand": ast.Function{
ArgTypes: nil,
ReturnType: ast.TypeString,
Variadic: true,
VariadicType: ast.TypeString,
Callback: func([]interface{}) (interface{}, error) {
return "42", nil
},
},
},
},
true,
},
{
"foo ${bar}",
&ast.BasicScope{
VarMap: map[string]ast.Variable{
"bar": ast.Variable{
Value: 42,
Type: ast.TypeInt,
},
},
},
true,
},
{
"foo ${rand()}",
&ast.BasicScope{
FuncMap: map[string]ast.Function{
"rand": ast.Function{
ReturnType: ast.TypeInt,
Callback: func([]interface{}) (interface{}, error) {
return 42, nil
},
},
},
},
true,
},
}
for _, tc := range cases {
node, err := Parse(tc.Input)
if err != nil {
t.Fatalf("Error: %s\n\nInput: %s", err, tc.Input)
}
visitor := &TypeCheck{Scope: tc.Scope}
err = visitor.Visit(node)
if err != nil != tc.Error {
t.Fatalf("Error: %s\n\nInput: %s", err, tc.Input)
}
}
}
func TestTypeCheck_implicit(t *testing.T) {
implicitMap := map[ast.Type]map[ast.Type]string{
ast.TypeInt: {
ast.TypeString: "intToString",
},
}
cases := []struct {
Input string
Scope *ast.BasicScope
Error bool
}{
{
"foo ${bar}",
&ast.BasicScope{
VarMap: map[string]ast.Variable{
"bar": ast.Variable{
Value: 42,
Type: ast.TypeInt,
},
},
},
false,
},
{
"foo ${foo(42)}",
&ast.BasicScope{
FuncMap: map[string]ast.Function{
"foo": ast.Function{
ArgTypes: []ast.Type{ast.TypeString},
ReturnType: ast.TypeString,
},
},
},
false,
},
{
`foo ${foo("42", 42)}`,
&ast.BasicScope{
FuncMap: map[string]ast.Function{
"foo": ast.Function{
ArgTypes: []ast.Type{ast.TypeString},
Variadic: true,
VariadicType: ast.TypeString,
ReturnType: ast.TypeString,
},
},
},
false,
},
}
for _, tc := range cases {
node, err := Parse(tc.Input)
if err != nil {
t.Fatalf("Error: %s\n\nInput: %s", err, tc.Input)
}
// Modify the scope to add our conversion functions.
if tc.Scope.FuncMap == nil {
tc.Scope.FuncMap = make(map[string]ast.Function)
}
tc.Scope.FuncMap["intToString"] = ast.Function{
ArgTypes: []ast.Type{ast.TypeInt},
ReturnType: ast.TypeString,
}
// Do the first pass...
visitor := &TypeCheck{Scope: tc.Scope, Implicit: implicitMap}
err = visitor.Visit(node)
if err != nil != tc.Error {
t.Fatalf("Error: %s\n\nInput: %s", err, tc.Input)
}
if err != nil {
continue
}
// If we didn't error, then the next type check should not fail
// WITHOUT implicits.
visitor = &TypeCheck{Scope: tc.Scope}
err = visitor.Visit(node)
if err != nil {
t.Fatalf("Error: %s\n\nInput: %s", err, tc.Input)
}
}
}

View File

@ -1,273 +0,0 @@
package hil
import (
"reflect"
"strconv"
"testing"
"github.com/hashicorp/hil/ast"
)
func TestEval(t *testing.T) {
cases := []struct {
Input string
Scope *ast.BasicScope
Error bool
Result interface{}
ResultType ast.Type
}{
{
"foo",
nil,
false,
"foo",
ast.TypeString,
},
{
"foo ${bar}",
&ast.BasicScope{
VarMap: map[string]ast.Variable{
"bar": ast.Variable{
Value: "baz",
Type: ast.TypeString,
},
},
},
false,
"foo baz",
ast.TypeString,
},
{
"foo ${42+1}",
nil,
false,
"foo 43",
ast.TypeString,
},
{
"foo ${42-1}",
nil,
false,
"foo 41",
ast.TypeString,
},
{
"foo ${42*2}",
nil,
false,
"foo 84",
ast.TypeString,
},
{
"foo ${42/2}",
nil,
false,
"foo 21",
ast.TypeString,
},
{
"foo ${42%4}",
nil,
false,
"foo 2",
ast.TypeString,
},
{
"foo ${42.0+1.0}",
nil,
false,
"foo 43",
ast.TypeString,
},
{
"foo ${42.0+1}",
nil,
false,
"foo 43",
ast.TypeString,
},
{
"foo ${42+1.0}",
nil,
false,
"foo 43",
ast.TypeString,
},
{
"foo ${42+2*2}",
nil,
false,
"foo 88",
ast.TypeString,
},
{
"foo ${42+(2*2)}",
nil,
false,
"foo 46",
ast.TypeString,
},
{
"foo ${bar+1}",
&ast.BasicScope{
VarMap: map[string]ast.Variable{
"bar": ast.Variable{
Value: 41,
Type: ast.TypeInt,
},
},
},
false,
"foo 42",
ast.TypeString,
},
{
"foo ${bar+1}",
&ast.BasicScope{
VarMap: map[string]ast.Variable{
"bar": ast.Variable{
Value: "41",
Type: ast.TypeString,
},
},
},
false,
"foo 42",
ast.TypeString,
},
{
"foo ${bar+baz}",
&ast.BasicScope{
VarMap: map[string]ast.Variable{
"bar": ast.Variable{
Value: "41",
Type: ast.TypeString,
},
"baz": ast.Variable{
Value: "1",
Type: ast.TypeString,
},
},
},
false,
"foo 42",
ast.TypeString,
},
{
"foo ${rand()}",
&ast.BasicScope{
FuncMap: map[string]ast.Function{
"rand": ast.Function{
ReturnType: ast.TypeString,
Callback: func([]interface{}) (interface{}, error) {
return "42", nil
},
},
},
},
false,
"foo 42",
ast.TypeString,
},
{
`foo ${rand("foo", "bar")}`,
&ast.BasicScope{
FuncMap: map[string]ast.Function{
"rand": ast.Function{
ReturnType: ast.TypeString,
Variadic: true,
VariadicType: ast.TypeString,
Callback: func(args []interface{}) (interface{}, error) {
var result string
for _, a := range args {
result += a.(string)
}
return result, nil
},
},
},
},
false,
"foo foobar",
ast.TypeString,
},
// Testing implicit type conversions
{
"foo ${bar}",
&ast.BasicScope{
VarMap: map[string]ast.Variable{
"bar": ast.Variable{
Value: 42,
Type: ast.TypeInt,
},
},
},
false,
"foo 42",
ast.TypeString,
},
{
`foo ${foo("42")}`,
&ast.BasicScope{
FuncMap: map[string]ast.Function{
"foo": ast.Function{
ArgTypes: []ast.Type{ast.TypeInt},
ReturnType: ast.TypeString,
Callback: func(args []interface{}) (interface{}, error) {
return strconv.FormatInt(int64(args[0].(int)), 10), nil
},
},
},
},
false,
"foo 42",
ast.TypeString,
},
// Multiline
{
"foo ${42+\n1.0}",
nil,
false,
"foo 43",
ast.TypeString,
},
}
for _, tc := range cases {
node, err := Parse(tc.Input)
if err != nil {
t.Fatalf("Error: %s\n\nInput: %s", err, tc.Input)
}
out, outType, err := Eval(node, &EvalConfig{GlobalScope: tc.Scope})
if err != nil != tc.Error {
t.Fatalf("Error: %s\n\nInput: %s", err, tc.Input)
}
if outType != tc.ResultType {
t.Fatalf("Bad: %s\n\nInput: %s", outType, tc.Input)
}
if !reflect.DeepEqual(out, tc.Result) {
t.Fatalf("Bad: %#v\n\nInput: %s", out, tc.Input)
}
}
}

View File

@ -1,140 +0,0 @@
package hil
import (
"reflect"
"testing"
)
func TestLex(t *testing.T) {
cases := []struct {
Input string
Output []int
}{
{
"foo",
[]int{STRING, lexEOF},
},
{
"foo$bar",
[]int{STRING, lexEOF},
},
{
"foo ${bar}",
[]int{STRING, PROGRAM_BRACKET_LEFT, IDENTIFIER, PROGRAM_BRACKET_RIGHT, lexEOF},
},
{
"foo $${bar}",
[]int{STRING, lexEOF},
},
{
"foo $$$${bar}",
[]int{STRING, lexEOF},
},
{
"foo ${\"bar\"}",
[]int{STRING, PROGRAM_BRACKET_LEFT, STRING, PROGRAM_BRACKET_RIGHT, lexEOF},
},
{
"${bar(baz)}",
[]int{PROGRAM_BRACKET_LEFT,
IDENTIFIER, PAREN_LEFT, IDENTIFIER, PAREN_RIGHT,
PROGRAM_BRACKET_RIGHT, lexEOF},
},
{
"${bar(baz, foo)}",
[]int{PROGRAM_BRACKET_LEFT,
IDENTIFIER, PAREN_LEFT,
IDENTIFIER, COMMA, IDENTIFIER,
PAREN_RIGHT,
PROGRAM_BRACKET_RIGHT, lexEOF},
},
{
"${bar(42)}",
[]int{PROGRAM_BRACKET_LEFT,
IDENTIFIER, PAREN_LEFT, INTEGER, PAREN_RIGHT,
PROGRAM_BRACKET_RIGHT, lexEOF},
},
{
"${bar(42+1)}",
[]int{PROGRAM_BRACKET_LEFT,
IDENTIFIER, PAREN_LEFT,
INTEGER, ARITH_OP, INTEGER,
PAREN_RIGHT,
PROGRAM_BRACKET_RIGHT, lexEOF},
},
{
"${bar(3.14159)}",
[]int{PROGRAM_BRACKET_LEFT,
IDENTIFIER, PAREN_LEFT, FLOAT, PAREN_RIGHT,
PROGRAM_BRACKET_RIGHT, lexEOF},
},
{
"${bar(inner(baz))}",
[]int{PROGRAM_BRACKET_LEFT,
IDENTIFIER, PAREN_LEFT,
IDENTIFIER, PAREN_LEFT,
IDENTIFIER,
PAREN_RIGHT, PAREN_RIGHT,
PROGRAM_BRACKET_RIGHT, lexEOF},
},
{
"foo ${foo.bar.baz}",
[]int{STRING, PROGRAM_BRACKET_LEFT, IDENTIFIER, PROGRAM_BRACKET_RIGHT, lexEOF},
},
{
"foo ${foo.bar.*.baz}",
[]int{STRING, PROGRAM_BRACKET_LEFT, IDENTIFIER, PROGRAM_BRACKET_RIGHT, lexEOF},
},
{
"foo ${foo(\"baz\")}",
[]int{STRING, PROGRAM_BRACKET_LEFT,
IDENTIFIER, PAREN_LEFT, STRING, PAREN_RIGHT,
PROGRAM_BRACKET_RIGHT, lexEOF},
},
{
`foo ${"${var.foo}"}`,
[]int{STRING, PROGRAM_BRACKET_LEFT,
PROGRAM_BRACKET_LEFT, IDENTIFIER, PROGRAM_BRACKET_RIGHT,
PROGRAM_BRACKET_RIGHT, lexEOF},
},
}
for _, tc := range cases {
l := &parserLex{Input: tc.Input}
var actual []int
for {
token := l.Lex(new(parserSymType))
actual = append(actual, token)
if token == lexEOF {
break
}
// Be careful against what are probably infinite loops
if len(actual) > 100 {
t.Fatalf("Input:%s\n\nExausted.", tc.Input)
}
}
if !reflect.DeepEqual(actual, tc.Output) {
t.Fatalf(
"Input: %s\n\nBad: %#v\n\nExpected: %#v",
tc.Input, actual, tc.Output)
}
}
}

View File

@ -1,363 +0,0 @@
package hil
import (
"reflect"
"testing"
"github.com/hashicorp/hil/ast"
)
func TestParse(t *testing.T) {
cases := []struct {
Input string
Error bool
Result ast.Node
}{
{
"",
false,
&ast.LiteralNode{
Value: "",
Typex: ast.TypeString,
Posx: ast.Pos{Column: 1, Line: 1},
},
},
{
"foo",
false,
&ast.LiteralNode{
Value: "foo",
Typex: ast.TypeString,
Posx: ast.Pos{Column: 1, Line: 1},
},
},
{
"$${var.foo}",
false,
&ast.LiteralNode{
Value: "${var.foo}",
Typex: ast.TypeString,
Posx: ast.Pos{Column: 1, Line: 1},
},
},
{
"foo ${var.bar}",
false,
&ast.Concat{
Posx: ast.Pos{Column: 1, Line: 1},
Exprs: []ast.Node{
&ast.LiteralNode{
Value: "foo ",
Typex: ast.TypeString,
Posx: ast.Pos{Column: 1, Line: 1},
},
&ast.VariableAccess{
Name: "var.bar",
Posx: ast.Pos{Column: 7, Line: 1},
},
},
},
},
{
"foo ${var.bar} baz",
false,
&ast.Concat{
Posx: ast.Pos{Column: 1, Line: 1},
Exprs: []ast.Node{
&ast.LiteralNode{
Value: "foo ",
Typex: ast.TypeString,
Posx: ast.Pos{Column: 1, Line: 1},
},
&ast.VariableAccess{
Name: "var.bar",
Posx: ast.Pos{Column: 7, Line: 1},
},
&ast.LiteralNode{
Value: " baz",
Typex: ast.TypeString,
Posx: ast.Pos{Column: 15, Line: 1},
},
},
},
},
{
"foo ${\"bar\"}",
false,
&ast.Concat{
Posx: ast.Pos{Column: 1, Line: 1},
Exprs: []ast.Node{
&ast.LiteralNode{
Value: "foo ",
Typex: ast.TypeString,
Posx: ast.Pos{Column: 1, Line: 1},
},
&ast.LiteralNode{
Value: "bar",
Typex: ast.TypeString,
Posx: ast.Pos{Column: 7, Line: 1},
},
},
},
},
{
`foo ${func('baz')}`,
true,
nil,
},
{
"foo ${42}",
false,
&ast.Concat{
Posx: ast.Pos{Column: 1, Line: 1},
Exprs: []ast.Node{
&ast.LiteralNode{
Value: "foo ",
Typex: ast.TypeString,
Posx: ast.Pos{Column: 1, Line: 1},
},
&ast.LiteralNode{
Value: 42,
Typex: ast.TypeInt,
Posx: ast.Pos{Column: 7, Line: 1},
},
},
},
},
{
"foo ${3.14159}",
false,
&ast.Concat{
Posx: ast.Pos{Column: 1, Line: 1},
Exprs: []ast.Node{
&ast.LiteralNode{
Value: "foo ",
Typex: ast.TypeString,
Posx: ast.Pos{Column: 1, Line: 1},
},
&ast.LiteralNode{
Value: 3.14159,
Typex: ast.TypeFloat,
Posx: ast.Pos{Column: 7, Line: 1},
},
},
},
},
{
"foo ${42+1}",
false,
&ast.Concat{
Posx: ast.Pos{Column: 1, Line: 1},
Exprs: []ast.Node{
&ast.LiteralNode{
Value: "foo ",
Typex: ast.TypeString,
Posx: ast.Pos{Column: 1, Line: 1},
},
&ast.Arithmetic{
Op: ast.ArithmeticOpAdd,
Exprs: []ast.Node{
&ast.LiteralNode{
Value: 42,
Typex: ast.TypeInt,
Posx: ast.Pos{Column: 7, Line: 1},
},
&ast.LiteralNode{
Value: 1,
Typex: ast.TypeInt,
Posx: ast.Pos{Column: 10, Line: 1},
},
},
Posx: ast.Pos{Column: 7, Line: 1},
},
},
},
},
{
"foo ${var.bar*1} baz",
false,
&ast.Concat{
Posx: ast.Pos{Column: 1, Line: 1},
Exprs: []ast.Node{
&ast.LiteralNode{
Value: "foo ",
Typex: ast.TypeString,
Posx: ast.Pos{Column: 1, Line: 1},
},
&ast.Arithmetic{
Op: ast.ArithmeticOpMul,
Exprs: []ast.Node{
&ast.VariableAccess{
Name: "var.bar",
Posx: ast.Pos{Column: 7, Line: 1},
},
&ast.LiteralNode{
Value: 1,
Typex: ast.TypeInt,
Posx: ast.Pos{Column: 15, Line: 1},
},
},
Posx: ast.Pos{Column: 7, Line: 1},
},
&ast.LiteralNode{
Value: " baz",
Typex: ast.TypeString,
Posx: ast.Pos{Column: 17, Line: 1},
},
},
},
},
{
"${foo()}",
false,
&ast.Concat{
Posx: ast.Pos{Column: 3, Line: 1},
Exprs: []ast.Node{
&ast.Call{
Func: "foo",
Args: nil,
Posx: ast.Pos{Column: 3, Line: 1},
},
},
},
},
{
"${foo(bar)}",
false,
&ast.Concat{
Posx: ast.Pos{Column: 3, Line: 1},
Exprs: []ast.Node{
&ast.Call{
Func: "foo",
Posx: ast.Pos{Column: 3, Line: 1},
Args: []ast.Node{
&ast.VariableAccess{
Name: "bar",
Posx: ast.Pos{Column: 7, Line: 1},
},
},
},
},
},
},
{
"${foo(bar, baz)}",
false,
&ast.Concat{
Posx: ast.Pos{Column: 3, Line: 1},
Exprs: []ast.Node{
&ast.Call{
Func: "foo",
Posx: ast.Pos{Column: 3, Line: 1},
Args: []ast.Node{
&ast.VariableAccess{
Name: "bar",
Posx: ast.Pos{Column: 7, Line: 1},
},
&ast.VariableAccess{
Name: "baz",
Posx: ast.Pos{Column: 11, Line: 1},
},
},
},
},
},
},
{
"${foo(bar(baz))}",
false,
&ast.Concat{
Posx: ast.Pos{Column: 3, Line: 1},
Exprs: []ast.Node{
&ast.Call{
Func: "foo",
Posx: ast.Pos{Column: 3, Line: 1},
Args: []ast.Node{
&ast.Call{
Func: "bar",
Posx: ast.Pos{Column: 7, Line: 1},
Args: []ast.Node{
&ast.VariableAccess{
Name: "baz",
Posx: ast.Pos{Column: 11, Line: 1},
},
},
},
},
},
},
},
},
{
`foo ${"bar ${baz}"}`,
false,
&ast.Concat{
Posx: ast.Pos{Column: 1, Line: 1},
Exprs: []ast.Node{
&ast.LiteralNode{
Value: "foo ",
Typex: ast.TypeString,
Posx: ast.Pos{Column: 1, Line: 1},
},
&ast.Concat{
Posx: ast.Pos{Column: 7, Line: 1},
Exprs: []ast.Node{
&ast.LiteralNode{
Value: "bar ",
Typex: ast.TypeString,
Posx: ast.Pos{Column: 7, Line: 1},
},
&ast.VariableAccess{
Name: "baz",
Posx: ast.Pos{Column: 14, Line: 1},
},
},
},
},
},
},
{
`foo ${bar ${baz}}`,
true,
nil,
},
{
`foo ${${baz}}`,
true,
nil,
},
{
"${var",
true,
nil,
},
}
for _, tc := range cases {
actual, err := Parse(tc.Input)
if err != nil != tc.Error {
t.Fatalf("Error: %s\n\nInput: %s", err, tc.Input)
}
if !reflect.DeepEqual(actual, tc.Result) {
t.Fatalf("Bad: %#v\n\nInput: %s", actual, tc.Input)
}
}
}

View File

@ -1,48 +0,0 @@
package hil
import (
"reflect"
"testing"
"github.com/hashicorp/hil/ast"
)
func TestFixedValueTransform(t *testing.T) {
cases := []struct {
Input ast.Node
Output ast.Node
}{
{
&ast.LiteralNode{Value: 42},
&ast.LiteralNode{Value: 42},
},
{
&ast.VariableAccess{Name: "bar"},
&ast.LiteralNode{Value: "foo"},
},
{
&ast.Concat{
Exprs: []ast.Node{
&ast.VariableAccess{Name: "bar"},
&ast.LiteralNode{Value: 42},
},
},
&ast.Concat{
Exprs: []ast.Node{
&ast.LiteralNode{Value: "foo"},
&ast.LiteralNode{Value: 42},
},
},
},
}
value := &ast.LiteralNode{Value: "foo"}
for _, tc := range cases {
actual := FixedValueTransform(tc.Input, value)
if !reflect.DeepEqual(actual, tc.Output) {
t.Fatalf("bad: %#v\n\nInput: %#v", actual, tc.Input)
}
}
}

View File

@ -1,190 +0,0 @@
package hil
import (
"fmt"
"reflect"
"testing"
)
func TestInterpolationWalker_detect(t *testing.T) {
cases := []struct {
Input interface{}
Result []string
}{
{
Input: map[string]interface{}{
"foo": "$${var.foo}",
},
Result: []string{
"Literal(TypeString, ${var.foo})",
},
},
{
Input: map[string]interface{}{
"foo": "${var.foo}",
},
Result: []string{
"Variable(var.foo)",
},
},
{
Input: map[string]interface{}{
"foo": "${aws_instance.foo.*.num}",
},
Result: []string{
"Variable(aws_instance.foo.*.num)",
},
},
{
Input: map[string]interface{}{
"foo": "${lookup(var.foo)}",
},
Result: []string{
"Call(lookup, Variable(var.foo))",
},
},
{
Input: map[string]interface{}{
"foo": `${file("test.txt")}`,
},
Result: []string{
"Call(file, Literal(TypeString, test.txt))",
},
},
{
Input: map[string]interface{}{
"foo": `${file("foo/bar.txt")}`,
},
Result: []string{
"Call(file, Literal(TypeString, foo/bar.txt))",
},
},
{
Input: map[string]interface{}{
"foo": `${join(",", foo.bar.*.id)}`,
},
Result: []string{
"Call(join, Literal(TypeString, ,), Variable(foo.bar.*.id))",
},
},
{
Input: map[string]interface{}{
"foo": `${concat("localhost", ":8080")}`,
},
Result: []string{
"Call(concat, Literal(TypeString, localhost), Literal(TypeString, :8080))",
},
},
}
for i, tc := range cases {
var actual []string
detectFn := func(data *WalkData) error {
actual = append(actual, fmt.Sprintf("%s", data.Root))
return nil
}
if err := Walk(tc.Input, detectFn); err != nil {
t.Fatalf("err: %s", err)
}
if !reflect.DeepEqual(actual, tc.Result) {
t.Fatalf("%d: bad:\n\n%#v", i, actual)
}
}
}
func TestInterpolationWalker_replace(t *testing.T) {
cases := []struct {
Input interface{}
Output interface{}
Value string
}{
{
Input: map[string]interface{}{
"foo": "$${var.foo}",
},
Output: map[string]interface{}{
"foo": "bar",
},
Value: "bar",
},
{
Input: map[string]interface{}{
"foo": "hi, ${var.foo}",
},
Output: map[string]interface{}{
"foo": "bar",
},
Value: "bar",
},
{
Input: map[string]interface{}{
"foo": map[string]interface{}{
"${var.foo}": "bar",
},
},
Output: map[string]interface{}{
"foo": map[string]interface{}{
"bar": "bar",
},
},
Value: "bar",
},
/*
{
Input: map[string]interface{}{
"foo": []interface{}{
"${var.foo}",
"bing",
},
},
Output: map[string]interface{}{
"foo": []interface{}{
"bar",
"baz",
"bing",
},
},
Value: NewStringList([]string{"bar", "baz"}).String(),
},
{
Input: map[string]interface{}{
"foo": []interface{}{
"${var.foo}",
"bing",
},
},
Output: map[string]interface{}{},
Value: NewStringList([]string{UnknownVariableValue, "baz"}).String(),
},
*/
}
for i, tc := range cases {
fn := func(data *WalkData) error {
data.Replace = true
data.ReplaceValue = tc.Value
return nil
}
if err := Walk(tc.Input, fn); err != nil {
t.Fatalf("err: %s", err)
}
if !reflect.DeepEqual(tc.Input, tc.Output) {
t.Fatalf("%d: bad:\n\nexpected:%#v\ngot:%#v", i, tc.Output, tc.Input)
}
}
}