282 lines
7.1 KiB
Go
282 lines
7.1 KiB
Go
package config
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"github.com/Masterminds/semver"
|
|
"github.com/spf13/afero"
|
|
"os"
|
|
filepath2 "path/filepath"
|
|
"strconv"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/cucumber/godog"
|
|
"github.com/cucumber/godog/colors"
|
|
|
|
"github.com/spf13/pflag"
|
|
|
|
a "github.com/stretchr/testify/assert"
|
|
)
|
|
|
|
var (
|
|
SupportedDataTypes = [4]string{"string", "integer", "float", "boolean"}
|
|
assertTest *a.Assertions
|
|
assertError = fmt.Errorf("assert error")
|
|
opts = godog.Options{
|
|
Output: colors.Colored(os.Stdout),
|
|
Format: "pretty",
|
|
Paths: []string{"features"},
|
|
}
|
|
originalCommandLine = os.Args
|
|
)
|
|
|
|
const (
|
|
StringDefaultValue = "default value"
|
|
StringConfigValue = "config file value"
|
|
StringEnvironmentValue = "environment variable value"
|
|
StringFlagValue = "command line value"
|
|
|
|
IntegerDefaultValue = 123
|
|
IntegerConfigValue = 234
|
|
IntegerEnvironmentValue = "345"
|
|
IntegerFlagValue = 456
|
|
|
|
FloatDefaultValue = 1.99
|
|
FloatConfigValue = 2.99
|
|
FloatEnvironmentValue = "3.99"
|
|
FloatFlagValue = 4.99
|
|
|
|
BoolDefaultValue = false
|
|
BoolConfigValue = true
|
|
BoolEnvironmentValue = "false"
|
|
BoolFlagValue = true
|
|
)
|
|
|
|
func init() {
|
|
godog.BindCommandLineFlags("godog.", &opts)
|
|
configFS = afero.NewMemMapFs()
|
|
}
|
|
|
|
func TestCucumber(t *testing.T) {
|
|
pflag.Parse()
|
|
assertTest = a.New(t)
|
|
|
|
opts.Paths = pflag.Args()
|
|
opts.TestingT = t
|
|
|
|
suite := godog.TestSuite{
|
|
Name: "pretty",
|
|
ScenarioInitializer: InitializeScenario,
|
|
TestSuiteInitializer: InitializeTestSuite,
|
|
Options: &opts,
|
|
}
|
|
|
|
if suite.Run() != 0 {
|
|
t.Fatal("cucumber tests failed")
|
|
}
|
|
}
|
|
|
|
func InitializeTestSuite(ctx *godog.TestSuiteContext) {
|
|
ctx.BeforeSuite(func() {
|
|
os.Args = []string{originalCommandLine[0]}
|
|
})
|
|
|
|
ctx.AfterSuite(func() {
|
|
os.Args = originalCommandLine
|
|
})
|
|
}
|
|
|
|
func InitializeScenario(ctx *godog.ScenarioContext) {
|
|
ctx.Given(`^an application with a name of "([^"]*)" and a prefix of "([^"]*)"$`, setAppNameAndPrefix)
|
|
ctx.Given(`^a version of "([^"]*)"$`, setAppVersion)
|
|
ctx.Given(`^a "([^"]*)" configuration item defines as$`, setupConfigItem)
|
|
|
|
ctx.When(`^I call GetConfig$`, callGetConfig)
|
|
|
|
ctx.Then(`^the "([^"]*)" result should return "([^"]*)"$`, checkConfigValue)
|
|
ctx.Then(`^the app name should return "([^"]*)"$`, theAppNameShouldReturn)
|
|
ctx.Then(`^the app prefix should return "([^"]*)"$`, theAppPrefixShouldReturn)
|
|
ctx.Then(`^the app version should pass the following constraint: "([^"]*)"$`, theAppVersionShouldPassTheFollowingConstraint)
|
|
}
|
|
|
|
// Given Callbacks
|
|
func setAppNameAndPrefix(ctx context.Context, name, prefix string) context.Context {
|
|
SetAppName(name, prefix)
|
|
return context.WithValue(ctx, "appPrefix", prefix)
|
|
}
|
|
|
|
func setAppVersion(_ context.Context, versionString string) {
|
|
SetAppVersion(versionString)
|
|
}
|
|
|
|
func setupConfigItem(ctx context.Context, itemType string, itemDefinition *godog.Table) (context.Context, error) {
|
|
if assertTest.Containsf(SupportedDataTypes, itemType, "config items of type '%s' are not yet supported", itemType) {
|
|
var (
|
|
data = make(map[string]string)
|
|
name string
|
|
shortFlag = ""
|
|
helpText = ""
|
|
|
|
fileContents = ""
|
|
|
|
defVal any
|
|
configVal any
|
|
envVal string
|
|
flagVal any
|
|
)
|
|
|
|
for idx, key := range itemDefinition.Rows[0].Cells {
|
|
data[key.Value] = itemDefinition.Rows[1].Cells[idx].Value
|
|
}
|
|
|
|
ctx = context.WithValue(ctx, "data", data)
|
|
|
|
name = data["name"]
|
|
switch itemType {
|
|
case "string":
|
|
defVal = StringDefaultValue
|
|
configVal = StringConfigValue
|
|
envVal = StringEnvironmentValue
|
|
flagVal = StringFlagValue
|
|
helpText = "String Config Item Test"
|
|
case "integer":
|
|
defVal = IntegerDefaultValue
|
|
configVal = IntegerConfigValue
|
|
envVal = IntegerEnvironmentValue
|
|
flagVal = IntegerFlagValue
|
|
helpText = "Integer Config Item Test"
|
|
case "float":
|
|
defVal = FloatDefaultValue
|
|
configVal = FloatConfigValue
|
|
envVal = FloatEnvironmentValue
|
|
flagVal = FloatFlagValue
|
|
helpText = "Float Config Item Test"
|
|
case "boolean":
|
|
defVal = BoolDefaultValue
|
|
configVal = BoolConfigValue
|
|
envVal = BoolEnvironmentValue
|
|
flagVal = BoolFlagValue
|
|
helpText = "Bool Config Item Test"
|
|
}
|
|
|
|
if data["has_file_entry"] == "true" {
|
|
var dirPath = filepath2.Join("/", "etc", Config.GetString("app.prefix"))
|
|
var filename = filepath2.Join(dirPath, "config.yaml")
|
|
|
|
fileContents = fmt.Sprintf("---\n%s: %v\n", name, configVal)
|
|
|
|
err := configFS.MkdirAll(dirPath, 0755)
|
|
if !assertTest.NoError(err, "unable to create test config folder") {
|
|
if !assertTest.DirExists(dirPath, "unable to create test config folder") {
|
|
return ctx, assertError
|
|
}
|
|
}
|
|
|
|
err = afero.WriteFile(configFS, filename, []byte(fileContents), 0755)
|
|
if !assertTest.NoError(err, "unable to write file contents") {
|
|
return ctx, fmt.Errorf(err.Error())
|
|
}
|
|
}
|
|
|
|
if data["has_env_var"] == "true" {
|
|
if data["has_env_var"] == "true" {
|
|
key := strings.ToUpper(
|
|
strings.ReplaceAll(
|
|
strings.ReplaceAll(
|
|
fmt.Sprintf("test_%s", name),
|
|
"-",
|
|
"_",
|
|
),
|
|
".",
|
|
"_",
|
|
),
|
|
)
|
|
_ = os.Setenv(key, envVal)
|
|
}
|
|
}
|
|
|
|
if data["commandline_flag"] != "" {
|
|
os.Args = append(os.Args, fmt.Sprintf("%s=%v", data["commandline_flag"], flagVal))
|
|
tagName := strings.Trim(data["commandline_flag"], "-")
|
|
if len(tagName) == 1 {
|
|
shortFlag = tagName
|
|
}
|
|
}
|
|
|
|
DefineConfigItem(name, shortFlag, defVal, helpText)
|
|
|
|
return ctx, nil
|
|
} else {
|
|
return ctx, assertError
|
|
}
|
|
}
|
|
|
|
// When Callbacks
|
|
func callGetConfig(_ context.Context) {
|
|
GetConfigs()
|
|
}
|
|
|
|
// Then Callbacks
|
|
func checkConfigValue(ctx context.Context, itemType, expectedString string) error {
|
|
var (
|
|
// key = ctx.Value("itemName").(string)
|
|
data = ctx.Value("data").(map[string]string)
|
|
key = data["name"]
|
|
err error
|
|
)
|
|
|
|
if assertTest.Containsf(SupportedDataTypes, itemType, "config items of type '%s' are not yet supported", itemType) {
|
|
var actual, expected interface{}
|
|
switch itemType {
|
|
case "string":
|
|
actual = strings.Trim(Config.GetString(key), "\"")
|
|
expected = expectedString
|
|
case "integer":
|
|
actual = Config.GetInt64(key)
|
|
expected, _ = strconv.ParseInt(expectedString, 10, 64)
|
|
case "float":
|
|
actual = Config.GetFloat64(key)
|
|
expected, _ = strconv.ParseFloat(expectedString, 64)
|
|
case "boolean":
|
|
actual = Config.GetBool(key)
|
|
expected, _ = strconv.ParseBool(expectedString)
|
|
}
|
|
|
|
if !assertTest.Equal(expected, actual, "config item should equal expected", os.Args, data) {
|
|
err = assertError
|
|
}
|
|
} else {
|
|
err = assertError
|
|
}
|
|
|
|
return err
|
|
}
|
|
|
|
func theAppNameShouldReturn(expected string) error {
|
|
if !assertTest.Equal(expected, Config.GetString("app.name")) {
|
|
return assertError
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func theAppPrefixShouldReturn(expected string) error {
|
|
if !assertTest.Equal(expected, Config.GetString("app.prefix")) {
|
|
return assertError
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func theAppVersionShouldPassTheFollowingConstraint(constraintString string) error {
|
|
var (
|
|
constraint, _ = semver.NewConstraint(constraintString)
|
|
actual = Config.Get("app.version").(*semver.Version)
|
|
)
|
|
|
|
if !assertTest.True(constraint.Check(actual), "version does not pass check") {
|
|
return assertError
|
|
}
|
|
|
|
return nil
|
|
}
|