pulumi/pkg/compiler/binder_test.go
joeduffy e02921dc35 Finish dependency and type binding
This change completes the implementation of dependency and type binding.
The top-level change here is that, during the first semantic analysis AST walk,
we gather up all unknown dependencies.  Then the compiler resolves them, caching
the lookups to ensure that we don't load the same stack twice.  Finally, during
the second and final semantic analysis AST walk, we populate the bound nodes
by looking up what the compiler resolved for us.
2016-11-23 07:26:45 -08:00

162 lines
6.1 KiB
Go

// Copyright 2016 Marapongo, Inc. All rights reserved.
package compiler
import (
"fmt"
"testing"
"github.com/stretchr/testify/assert"
"github.com/marapongo/mu/pkg/diag"
"github.com/marapongo/mu/pkg/errors"
)
func TestBadMissingStackName(t *testing.T) {
sink := buildNoCodegen("testdata", "binder", "bad__missing_stack_name")
// Check that the compiler complained about a missing Stack name.
d := errors.ErrorMissingStackName
assert.Equal(t, 1, sink.Errors(), "expected a single error")
assert.Equal(t,
fmt.Sprintf("%v: %v%v: %v: %v\n",
diag.DefaultSinkErrorPrefix, diag.DefaultSinkIDPrefix, d.ID, "Mu.yaml", d.Message),
sink.ErrorMsgs()[0])
}
func TestBadStackSemVer1(t *testing.T) {
sink := buildNoCodegen("testdata", "binder", "bad__stack_semver__1")
// Check that the compiler complained about an illegal semantic version.
d := errors.ErrorIllegalStackVersion
assert.Equal(t, 1, sink.Errors(), "expected a single error")
assert.Equal(t,
fmt.Sprintf("%v: %v%v: %v: %v\n",
diag.DefaultSinkErrorPrefix, diag.DefaultSinkIDPrefix, d.ID, "Mu.yaml",
fmt.Sprintf(d.Message, "badbadbad", "No Major.Minor.Patch elements found")),
sink.ErrorMsgs()[0])
}
func TestBadStackSemVer2(t *testing.T) {
sink := buildNoCodegen("testdata", "binder", "bad__stack_semver__2")
// Check that the compiler complained about an illegal semantic version.
d := errors.ErrorIllegalStackVersion
assert.Equal(t, 1, sink.Errors(), "expected a single error")
assert.Equal(t,
fmt.Sprintf("%v: %v%v: %v: %v\n",
diag.DefaultSinkErrorPrefix, diag.DefaultSinkIDPrefix, d.ID, "Mu.yaml",
fmt.Sprintf(d.Message, ">1.0.0",
"Invalid character(s) found in major number \">1\"")),
sink.ErrorMsgs()[0])
}
func TestBadDepSemVer1(t *testing.T) {
sink := buildNoCodegen("testdata", "binder", "bad__dep_semver__1")
// Check that the compiler complained about an illegal semantic version.
d := errors.ErrorMalformedStackReference
assert.Equal(t, 1, sink.Errors(), "expected a single error")
assert.Equal(t,
fmt.Sprintf("%v: %v%v: %v: %v\n",
diag.DefaultSinkErrorPrefix, diag.DefaultSinkIDPrefix, d.ID, "Mu.yaml",
fmt.Sprintf(d.Message, "dep1@badbadbad",
"Illegal version spec: Could not get version from string: \"badbadbad\"")),
sink.ErrorMsgs()[0])
}
func TestBadDepSemVer2(t *testing.T) {
sink := buildNoCodegen("testdata", "binder", "bad__dep_semver__2")
// Check that the compiler complained about an illegal semantic version.
d := errors.ErrorMalformedStackReference
assert.Equal(t, 1, sink.Errors(), "expected a single error")
assert.Equal(t,
fmt.Sprintf("%v: %v%v: %v: %v\n",
diag.DefaultSinkErrorPrefix, diag.DefaultSinkIDPrefix, d.ID, "Mu.yaml",
fmt.Sprintf(d.Message, "dep3@badbadbad",
"Illegal version spec: Could not get version from string: \"badbadbad\"")),
sink.ErrorMsgs()[0])
}
func TestBadDepSemVer3(t *testing.T) {
sink := buildNoCodegen("testdata", "binder", "bad__dep_semver__3")
// Check that the compiler complained about an illegal semantic version.
d := errors.ErrorMalformedStackReference
assert.Equal(t, 4, sink.Errors(), "expected an error for each bad semver")
assert.Equal(t,
fmt.Sprintf("%v: %v%v: %v: %v\n",
diag.DefaultSinkErrorPrefix, diag.DefaultSinkIDPrefix, d.ID, "Mu.yaml",
fmt.Sprintf(d.Message, "dep1@bad1",
"Illegal version spec: Could not parse Range \"bad1\": "+
"Could not parse comparator \"bad\" in \"bad1\"")),
sink.ErrorMsgs()[0])
assert.Equal(t,
fmt.Sprintf("%v: %v%v: %v: %v\n",
diag.DefaultSinkErrorPrefix, diag.DefaultSinkIDPrefix, d.ID, "Mu.yaml",
fmt.Sprintf(d.Message, "dep2@0.0",
"Illegal version spec: Could not parse Range \"0.0\": "+
"Could not parse version \"0.0\" in \"0.0\": No Major.Minor.Patch elements found")),
sink.ErrorMsgs()[1])
assert.Equal(t,
fmt.Sprintf("%v: %v%v: %v: %v\n",
diag.DefaultSinkErrorPrefix, diag.DefaultSinkIDPrefix, d.ID, "Mu.yaml",
fmt.Sprintf(d.Message, "dep3@bad3",
"Illegal version spec: Could not parse Range \"bad3\": "+
"Could not parse comparator \"bad\" in \"bad3\"")),
sink.ErrorMsgs()[2])
assert.Equal(t,
fmt.Sprintf("%v: %v%v: %v: %v\n",
diag.DefaultSinkErrorPrefix, diag.DefaultSinkIDPrefix, d.ID, "Mu.yaml",
fmt.Sprintf(d.Message, "dep4@0.6.bad.ness.1",
"Illegal version spec: Could not parse Range \"0.6.bad.ness.1\": "+
"Could not parse version \"0.6.bad.ness.1\" in \"0.6.bad.ness.1\": "+
"Invalid character(s) found in patch number \"bad.ness.1\"")),
sink.ErrorMsgs()[3])
}
func TestSymbolAlreadyExists(t *testing.T) {
sink := buildNoCodegen("testdata", "binder", "bad__symbol_already_exists")
// Check that the compiler complained about a duplicate symbol.
d := errors.ErrorSymbolAlreadyExists
assert.Equal(t, 1, sink.Errors(), "expected a single error")
assert.Equal(t,
fmt.Sprintf("%v: %v%v: %v: %v\n",
diag.DefaultSinkErrorPrefix, diag.DefaultSinkIDPrefix, d.ID, "Mu.yaml",
fmt.Sprintf(d.Message, "foo")),
sink.ErrorMsgs()[0])
}
func TestTypeNotFound1(t *testing.T) {
sink := buildNoCodegen("testdata", "binder", "bad__type_not_found__1")
// Check that the compiler complained about the type missisng.
d := errors.ErrorStackTypeNotFound
assert.Equal(t, 1, sink.Errors(), "expected a single error")
assert.Equal(t,
fmt.Sprintf("%v: %v%v: %v: %v\n",
diag.DefaultSinkErrorPrefix, diag.DefaultSinkIDPrefix, d.ID, "Mu.yaml",
fmt.Sprintf(d.Message, "something/non/existent")),
sink.ErrorMsgs()[0])
}
func TestTypeNotFound2(t *testing.T) {
sink := buildNoCodegen("testdata", "binder", "bad__type_not_found__2")
// Check that the compiler complained about the type missisng.
d := errors.ErrorStackTypeNotFound
assert.Equal(t, 1, sink.Errors(), "expected a single error")
assert.Equal(t,
fmt.Sprintf("%v: %v%v: %v: %v\n",
diag.DefaultSinkErrorPrefix, diag.DefaultSinkIDPrefix, d.ID, "Mu.yaml",
fmt.Sprintf(d.Message, "something/non/existent")),
sink.ErrorMsgs()[0])
}
func TestGoodPredefTypes(t *testing.T) {
sink := buildNoCodegen("testdata", "binder", "good__predef_types")
// Check that no errors are found when using predefined stack types.
assert.Equal(t, 0, sink.Errors(), "expected no errors when binding to predef types")
}