2016-12-20 16:26:49 -05:00
|
|
|
package template
|
|
|
|
|
|
|
|
import (
|
2018-06-25 11:15:26 -04:00
|
|
|
"fmt"
|
2017-12-21 16:27:57 -05:00
|
|
|
"reflect"
|
2016-12-20 16:26:49 -05:00
|
|
|
"testing"
|
|
|
|
|
2018-06-08 12:24:26 -04:00
|
|
|
"gotest.tools/assert"
|
|
|
|
is "gotest.tools/assert/cmp"
|
2016-12-20 16:26:49 -05:00
|
|
|
)
|
|
|
|
|
|
|
|
var defaults = map[string]string{
|
|
|
|
"FOO": "first",
|
|
|
|
"BAR": "",
|
|
|
|
}
|
|
|
|
|
|
|
|
func defaultMapping(name string) (string, bool) {
|
|
|
|
val, ok := defaults[name]
|
|
|
|
return val, ok
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestEscaped(t *testing.T) {
|
|
|
|
result, err := Substitute("$${foo}", defaultMapping)
|
2018-03-06 14:44:13 -05:00
|
|
|
assert.NilError(t, err)
|
2018-03-05 18:53:52 -05:00
|
|
|
assert.Check(t, is.Equal("${foo}", result))
|
2016-12-20 16:26:49 -05:00
|
|
|
}
|
|
|
|
|
2018-02-21 15:16:12 -05:00
|
|
|
func TestSubstituteNoMatch(t *testing.T) {
|
|
|
|
result, err := Substitute("foo", defaultMapping)
|
2018-03-05 18:53:52 -05:00
|
|
|
assert.NilError(t, err)
|
|
|
|
assert.Equal(t, "foo", result)
|
2018-02-21 15:16:12 -05:00
|
|
|
}
|
|
|
|
|
2016-12-20 16:26:49 -05:00
|
|
|
func TestInvalid(t *testing.T) {
|
|
|
|
invalidTemplates := []string{
|
|
|
|
"${",
|
|
|
|
"$}",
|
|
|
|
"${}",
|
|
|
|
"${ }",
|
|
|
|
"${ foo}",
|
|
|
|
"${foo }",
|
|
|
|
"${foo!}",
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, template := range invalidTemplates {
|
|
|
|
_, err := Substitute(template, defaultMapping)
|
2017-12-21 16:27:57 -05:00
|
|
|
assert.ErrorContains(t, err, "Invalid template")
|
2016-12-20 16:26:49 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestNoValueNoDefault(t *testing.T) {
|
|
|
|
for _, template := range []string{"This ${missing} var", "This ${BAR} var"} {
|
|
|
|
result, err := Substitute(template, defaultMapping)
|
2018-03-06 14:44:13 -05:00
|
|
|
assert.NilError(t, err)
|
2018-03-05 18:53:52 -05:00
|
|
|
assert.Check(t, is.Equal("This var", result))
|
2016-12-20 16:26:49 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestValueNoDefault(t *testing.T) {
|
|
|
|
for _, template := range []string{"This $FOO var", "This ${FOO} var"} {
|
|
|
|
result, err := Substitute(template, defaultMapping)
|
2018-03-06 14:44:13 -05:00
|
|
|
assert.NilError(t, err)
|
2018-03-05 18:53:52 -05:00
|
|
|
assert.Check(t, is.Equal("This first var", result))
|
2016-12-20 16:26:49 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestNoValueWithDefault(t *testing.T) {
|
|
|
|
for _, template := range []string{"ok ${missing:-def}", "ok ${missing-def}"} {
|
|
|
|
result, err := Substitute(template, defaultMapping)
|
2018-03-06 14:44:13 -05:00
|
|
|
assert.NilError(t, err)
|
2018-03-05 18:53:52 -05:00
|
|
|
assert.Check(t, is.Equal("ok def", result))
|
2016-12-20 16:26:49 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestEmptyValueWithSoftDefault(t *testing.T) {
|
|
|
|
result, err := Substitute("ok ${BAR:-def}", defaultMapping)
|
2018-03-06 14:44:13 -05:00
|
|
|
assert.NilError(t, err)
|
2018-03-05 18:53:52 -05:00
|
|
|
assert.Check(t, is.Equal("ok def", result))
|
2016-12-20 16:26:49 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestEmptyValueWithHardDefault(t *testing.T) {
|
|
|
|
result, err := Substitute("ok ${BAR-def}", defaultMapping)
|
2018-03-06 14:44:13 -05:00
|
|
|
assert.NilError(t, err)
|
2018-03-05 18:53:52 -05:00
|
|
|
assert.Check(t, is.Equal("ok ", result))
|
2016-12-20 16:26:49 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestNonAlphanumericDefault(t *testing.T) {
|
|
|
|
result, err := Substitute("ok ${BAR:-/non:-alphanumeric}", defaultMapping)
|
2018-03-06 14:44:13 -05:00
|
|
|
assert.NilError(t, err)
|
2018-03-05 18:53:52 -05:00
|
|
|
assert.Check(t, is.Equal("ok /non:-alphanumeric", result))
|
2016-12-20 16:26:49 -05:00
|
|
|
}
|
2018-02-21 06:29:08 -05:00
|
|
|
|
|
|
|
func TestMandatoryVariableErrors(t *testing.T) {
|
|
|
|
testCases := []struct {
|
|
|
|
template string
|
|
|
|
expectedError string
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
template: "not ok ${UNSET_VAR:?Mandatory Variable Unset}",
|
2018-02-26 15:23:52 -05:00
|
|
|
expectedError: "required variable UNSET_VAR is missing a value: Mandatory Variable Unset",
|
2018-02-21 06:29:08 -05:00
|
|
|
},
|
|
|
|
{
|
|
|
|
template: "not ok ${BAR:?Mandatory Variable Empty}",
|
2018-02-26 15:23:52 -05:00
|
|
|
expectedError: "required variable BAR is missing a value: Mandatory Variable Empty",
|
2018-02-21 06:29:08 -05:00
|
|
|
},
|
|
|
|
{
|
|
|
|
template: "not ok ${UNSET_VAR:?}",
|
2018-02-26 15:23:52 -05:00
|
|
|
expectedError: "required variable UNSET_VAR is missing a value",
|
2018-02-21 06:29:08 -05:00
|
|
|
},
|
|
|
|
{
|
2018-02-26 15:23:52 -05:00
|
|
|
template: "not ok ${UNSET_VAR?Mandatory Variable Unset}",
|
|
|
|
expectedError: "required variable UNSET_VAR is missing a value: Mandatory Variable Unset",
|
2018-02-21 06:29:08 -05:00
|
|
|
},
|
|
|
|
{
|
|
|
|
template: "not ok ${UNSET_VAR?}",
|
2018-02-26 15:23:52 -05:00
|
|
|
expectedError: "required variable UNSET_VAR is missing a value",
|
2018-02-21 06:29:08 -05:00
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, tc := range testCases {
|
|
|
|
_, err := Substitute(tc.template, defaultMapping)
|
2017-12-21 16:27:57 -05:00
|
|
|
assert.ErrorContains(t, err, tc.expectedError)
|
|
|
|
assert.ErrorType(t, err, reflect.TypeOf(&InvalidTemplateError{}))
|
2018-02-21 06:29:08 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestDefaultsForMandatoryVariables(t *testing.T) {
|
|
|
|
testCases := []struct {
|
|
|
|
template string
|
|
|
|
expected string
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
template: "ok ${FOO:?err}",
|
|
|
|
expected: "ok first",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
template: "ok ${FOO?err}",
|
|
|
|
expected: "ok first",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
template: "ok ${BAR?err}",
|
|
|
|
expected: "ok ",
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, tc := range testCases {
|
|
|
|
result, err := Substitute(tc.template, defaultMapping)
|
2018-03-06 14:44:13 -05:00
|
|
|
assert.NilError(t, err)
|
2018-03-05 18:53:52 -05:00
|
|
|
assert.Check(t, is.Equal(tc.expected, result))
|
2018-02-21 06:29:08 -05:00
|
|
|
}
|
|
|
|
}
|
2018-06-25 11:15:26 -04:00
|
|
|
|
|
|
|
func TestSubstituteWithCustomFunc(t *testing.T) {
|
|
|
|
errIsMissing := func(substitution string, mapping Mapping) (string, bool, error) {
|
|
|
|
value, found := mapping(substitution)
|
|
|
|
if !found {
|
|
|
|
return "", true, &InvalidTemplateError{
|
|
|
|
Template: fmt.Sprintf("required variable %s is missing a value", substitution),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return value, true, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
result, err := SubstituteWith("ok ${FOO}", defaultMapping, pattern, errIsMissing)
|
|
|
|
assert.NilError(t, err)
|
|
|
|
assert.Check(t, is.Equal("ok first", result))
|
|
|
|
|
|
|
|
result, err = SubstituteWith("ok ${BAR}", defaultMapping, pattern, errIsMissing)
|
|
|
|
assert.NilError(t, err)
|
|
|
|
assert.Check(t, is.Equal("ok ", result))
|
|
|
|
|
|
|
|
_, err = SubstituteWith("ok ${NOTHERE}", defaultMapping, pattern, errIsMissing)
|
|
|
|
assert.Check(t, is.ErrorContains(err, "required variable"))
|
|
|
|
}
|