pulumi/pkg/codegen/go/gen_program_expression_test.go
Ian Wahbe 9f6589ed8c
iwahbe/7802/compile program generator test output (#8036)
* Move program tests into folders

* update package schema

* Enabled tests pass

* Fix lints and begin to update test cases

* Re-enable tests

* Update aws version to v4

* Refactor language specific parts

* Hook up dotnet and nodejs

* Update tests from master

* SSOT for schema/version

* Name blocking errors. Leave tests in valid state

* Give each language its own folder

* Remove SkipCompile for azure-sa (bug was fixed)

* Fix nits + changes asserts to require

* Remove unused import

* One last assert => require
2021-09-29 11:33:57 -07:00

216 lines
5.5 KiB
Go

package gen
import (
"bytes"
"io"
"path/filepath"
"testing"
"github.com/hashicorp/hcl/v2"
"github.com/pulumi/pulumi/pkg/v3/codegen/hcl2/model"
"github.com/pulumi/pulumi/pkg/v3/codegen/hcl2/syntax"
"github.com/stretchr/testify/assert"
)
type exprTestCase struct {
hcl2Expr string
goCode string
}
type environment map[string]interface{}
func (e environment) scope() *model.Scope {
s := model.NewRootScope(syntax.None)
for name, typeOrFunction := range e {
switch typeOrFunction := typeOrFunction.(type) {
case *model.Function:
s.DefineFunction(name, typeOrFunction)
case model.Type:
s.Define(name, &model.Variable{Name: name, VariableType: typeOrFunction})
}
}
return s
}
func TestLiteralExpression(t *testing.T) {
cases := []exprTestCase{
{hcl2Expr: "false", goCode: "false"},
{hcl2Expr: "true", goCode: "true"},
{hcl2Expr: "0", goCode: "0"},
{hcl2Expr: "3.14", goCode: "3.14"},
{hcl2Expr: "\"foo\"", goCode: "\"foo\""},
}
for _, c := range cases {
testGenerateExpression(t, c.hcl2Expr, c.goCode, nil, nil)
}
}
func TestBinaryOpExpression(t *testing.T) {
env := environment(map[string]interface{}{
"a": model.BoolType,
"b": model.BoolType,
"c": model.NumberType,
"d": model.NumberType,
})
scope := env.scope()
cases := []exprTestCase{
{hcl2Expr: "0 == 0", goCode: "0 == 0"},
{hcl2Expr: "0 != 0", goCode: "0 != 0"},
{hcl2Expr: "0 < 0", goCode: "0 < 0"},
{hcl2Expr: "0 > 0", goCode: "0 > 0"},
{hcl2Expr: "0 <= 0", goCode: "0 <= 0"},
{hcl2Expr: "0 >= 0", goCode: "0 >= 0"},
{hcl2Expr: "0 + 0", goCode: "0 + 0"},
{hcl2Expr: "0 * 0", goCode: "0 * 0"},
{hcl2Expr: "0 / 0", goCode: "0 / 0"},
{hcl2Expr: "0 % 0", goCode: "0 % 0"},
{hcl2Expr: "false && false", goCode: "false && false"},
{hcl2Expr: "false || false", goCode: "false || false"},
{hcl2Expr: "a == true", goCode: "a == true"},
{hcl2Expr: "b == true", goCode: "b == true"},
{hcl2Expr: "c + 0", goCode: "c + 0"},
{hcl2Expr: "d + 0", goCode: "d + 0"},
{hcl2Expr: "a && true", goCode: "a && true"},
{hcl2Expr: "b && true", goCode: "b && true"},
}
for _, c := range cases {
testGenerateExpression(t, c.hcl2Expr, c.goCode, scope, nil)
}
}
func TestUnaryOpExrepssion(t *testing.T) {
env := environment(map[string]interface{}{
"a": model.NumberType,
"b": model.BoolType,
})
scope := env.scope()
cases := []exprTestCase{
{hcl2Expr: "-1", goCode: "-1"},
{hcl2Expr: "!true", goCode: "!true"},
{hcl2Expr: "-a", goCode: "-a"},
{hcl2Expr: "!b", goCode: "!b"},
}
for _, c := range cases {
testGenerateExpression(t, c.hcl2Expr, c.goCode, scope, nil)
}
}
// nolint: lll
func TestConditionalExpression(t *testing.T) {
cases := []exprTestCase{
{
hcl2Expr: "true ? 1 : 0",
goCode: "var tmp0 float64\nif true {\ntmp0 = 1\n} else {\ntmp0 = 0\n}\ntmp0",
},
{
hcl2Expr: "true ? 1 : true ? 0 : -1",
goCode: "var tmp0 float64\nif true {\ntmp0 = 0\n} else {\ntmp0 = -1\n}\nvar tmp1 float64\nif true {\ntmp1 = 1\n} else {\ntmp1 = tmp0\n}\ntmp1",
},
{
hcl2Expr: "true ? true ? 0 : -1 : 0",
goCode: "var tmp0 float64\nif true {\ntmp0 = 0\n} else {\ntmp0 = -1\n}\nvar tmp1 float64\nif true {\ntmp1 = tmp0\n} else {\ntmp1 = 0\n}\ntmp1",
},
{
hcl2Expr: "{foo = true ? 2 : 0}",
goCode: "var tmp0 float64\nif true {\ntmp0 = 2\n} else {\ntmp0 = 0\n}\nmap[string]interface{}{\n\"foo\": tmp0,\n}",
},
}
genFunc := func(w io.Writer, g *generator, e model.Expression) {
e, temps := g.lowerExpression(e, e.Type())
g.genTemps(w, temps)
g.Fgenf(w, "%v", e)
}
for _, c := range cases {
testGenerateExpression(t, c.hcl2Expr, c.goCode, nil, genFunc)
}
}
func TestObjectConsExpression(t *testing.T) {
env := environment(map[string]interface{}{
"a": model.StringType,
})
scope := env.scope()
cases := []exprTestCase{
{
// TODO probably a bug in the binder. Single value objects should just be maps
hcl2Expr: "{foo = 1}",
goCode: "map[string]interface{}{\n\"foo\": 1,\n}",
},
{
hcl2Expr: "{\"foo\" = 1}",
goCode: "map[string]interface{}{\n\"foo\": 1,\n}",
},
{
hcl2Expr: "{1 = 1}",
goCode: "map[string]interface{}{\n\"1\": 1,\n}",
},
{
hcl2Expr: "{(a) = 1}",
goCode: "map[string]float64{\na: 1,\n}",
},
{
hcl2Expr: "{(a+a) = 1}",
goCode: "map[string]float64{\na + a: 1,\n}",
},
}
for _, c := range cases {
testGenerateExpression(t, c.hcl2Expr, c.goCode, scope, nil)
}
}
func TestTupleConsExpression(t *testing.T) {
env := environment(map[string]interface{}{
"a": model.StringType,
})
scope := env.scope()
cases := []exprTestCase{
{
hcl2Expr: "[\"foo\"]",
goCode: "[]string{\n\"foo\",\n}",
},
{
hcl2Expr: "[\"foo\", \"bar\", \"baz\"]",
goCode: "[]string{\n\"foo\",\n\"bar\",\n\"baz\",\n}",
},
{
hcl2Expr: "[1]",
goCode: "[]float64{\n1,\n}",
},
{
hcl2Expr: "[1,2,3]",
goCode: "[]float64{\n1,\n2,\n3,\n}",
},
{
hcl2Expr: "[1,\"foo\"]",
goCode: "[]interface{}{\n1,\n\"foo\",\n}",
},
}
for _, c := range cases {
testGenerateExpression(t, c.hcl2Expr, c.goCode, scope, nil)
}
}
func testGenerateExpression(
t *testing.T,
hcl2Expr, goCode string,
scope *model.Scope,
gen func(w io.Writer, g *generator, e model.Expression),
) {
t.Run(hcl2Expr, func(t *testing.T) {
// test program is only for schema info
g := newTestGenerator(t, filepath.Join("aws-s3-logging-pp", "aws-s3-logging.pp"))
var index bytes.Buffer
expr, _ := model.BindExpressionText(hcl2Expr, scope, hcl.Pos{})
if gen != nil {
gen(&index, g, expr)
} else {
g.Fgenf(&index, "%v", expr)
}
assert.Equal(t, goCode, index.String())
})
}