314 lines
6.1 KiB
Go
314 lines
6.1 KiB
Go
package mcfg
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/json"
|
|
"strconv"
|
|
. "testing"
|
|
|
|
"github.com/mediocregopher/mediocre-go-lib/mtest"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
// * dimension
|
|
// - dimension value
|
|
//
|
|
// * Cfg path
|
|
// - New()
|
|
// - New.Child("a")
|
|
// - New.Child("a-b")
|
|
// - New.Child("a=b")
|
|
// * Param name
|
|
// - normal
|
|
// - w/ "-"
|
|
// - w/ "=" ?
|
|
// * Param type
|
|
// - bool
|
|
// - non-bool
|
|
// * non-bool type
|
|
// - int
|
|
// - string
|
|
// * Str value
|
|
// - empty
|
|
// - normal
|
|
// - w/ -
|
|
// - w/ =
|
|
// * Value format
|
|
// - w/ =
|
|
// - w/o =
|
|
|
|
func combinate(slices ...[]string) [][]string {
|
|
out := [][]string{{}}
|
|
for _, slice := range slices {
|
|
if len(slice) == 0 {
|
|
continue
|
|
}
|
|
prev := out
|
|
out = make([][]string, 0, len(prev)*len(slice))
|
|
for _, prevSet := range prev {
|
|
for _, sliceElem := range slice {
|
|
prevSetCp := make([]string, len(prevSet), len(prevSet)+1)
|
|
copy(prevSetCp, prevSet)
|
|
prevSetCp = append(prevSetCp, sliceElem)
|
|
out = append(out, prevSetCp)
|
|
}
|
|
}
|
|
}
|
|
return out
|
|
}
|
|
|
|
func TestCombinate(t *T) {
|
|
type combTest struct {
|
|
args [][]string
|
|
exp [][]string
|
|
}
|
|
|
|
tests := []combTest{
|
|
{
|
|
args: [][]string{},
|
|
exp: [][]string{{}},
|
|
},
|
|
{
|
|
args: [][]string{{"a"}},
|
|
exp: [][]string{{"a"}},
|
|
},
|
|
{
|
|
args: [][]string{{"a"}, {"b"}},
|
|
exp: [][]string{{"a", "b"}},
|
|
},
|
|
{
|
|
args: [][]string{{"a", "aa"}, {"b"}},
|
|
exp: [][]string{
|
|
{"a", "b"},
|
|
{"aa", "b"},
|
|
},
|
|
},
|
|
{
|
|
args: [][]string{{"a"}, {"b", "bb"}},
|
|
exp: [][]string{
|
|
{"a", "b"},
|
|
{"a", "bb"},
|
|
},
|
|
},
|
|
{
|
|
args: [][]string{{"a", "aa"}, {"b", "bb"}},
|
|
exp: [][]string{
|
|
{"a", "b"},
|
|
{"aa", "b"},
|
|
{"a", "bb"},
|
|
{"aa", "bb"},
|
|
},
|
|
},
|
|
}
|
|
|
|
for i, test := range tests {
|
|
msgAndArgs := []interface{}{"test:%d args:%v", i, test.args}
|
|
got := combinate(test.args...)
|
|
assert.Len(t, got, len(test.exp), msgAndArgs...)
|
|
for _, expHas := range test.exp {
|
|
assert.Contains(t, got, expHas, msgAndArgs...)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestSourceCLI(t *T) {
|
|
var (
|
|
paths = []string{
|
|
"root",
|
|
"child",
|
|
"childDash",
|
|
"childEq",
|
|
}
|
|
|
|
paramNames = []string{
|
|
"normal",
|
|
"wDash",
|
|
"wEq",
|
|
}
|
|
|
|
isBool = []string{
|
|
"isBool",
|
|
"isNotBool",
|
|
}
|
|
|
|
nonBoolTypes = []string{
|
|
"int",
|
|
"str",
|
|
}
|
|
|
|
nonBoolFmts = []string{
|
|
"wEq",
|
|
"woEq",
|
|
}
|
|
|
|
nonBoolStrValues = []string{
|
|
"empty",
|
|
"normal",
|
|
"wDash",
|
|
"wEq",
|
|
}
|
|
)
|
|
|
|
type cliTest struct {
|
|
path string
|
|
name string
|
|
isBool bool
|
|
nonBoolType string
|
|
nonBoolStrValue string
|
|
nonBoolFmt string
|
|
|
|
// it's kinda hacky to make this a pointer, but it makes the code a lot
|
|
// easier to read later
|
|
exp *ParamValue
|
|
}
|
|
|
|
var tests []cliTest
|
|
for _, comb := range combinate(paths, paramNames, isBool) {
|
|
var test cliTest
|
|
test.path = comb[0]
|
|
test.name = comb[1]
|
|
test.isBool = comb[2] == "isBool"
|
|
if test.isBool {
|
|
tests = append(tests, test)
|
|
continue
|
|
}
|
|
|
|
for _, nonBoolComb := range combinate(nonBoolTypes, nonBoolFmts) {
|
|
test.nonBoolType = nonBoolComb[0]
|
|
test.nonBoolFmt = nonBoolComb[1]
|
|
if test.nonBoolType != "str" {
|
|
tests = append(tests, test)
|
|
continue
|
|
}
|
|
for _, nonBoolStrValue := range nonBoolStrValues {
|
|
test.nonBoolStrValue = nonBoolStrValue
|
|
tests = append(tests, test)
|
|
}
|
|
}
|
|
}
|
|
|
|
childName := mtest.RandHex(8)
|
|
childDashName := mtest.RandHex(4) + "-" + mtest.RandHex(4)
|
|
childEqName := mtest.RandHex(4) + "=" + mtest.RandHex(4)
|
|
|
|
var args []string
|
|
rootCfg := New()
|
|
childCfg := rootCfg.Child(childName)
|
|
childDashCfg := rootCfg.Child(childDashName)
|
|
childEqCfg := rootCfg.Child(childEqName)
|
|
|
|
for i := range tests {
|
|
var pv ParamValue
|
|
tests[i].exp = &pv
|
|
|
|
switch tests[i].name {
|
|
case "normal":
|
|
pv.Name = mtest.RandHex(8)
|
|
case "wDash":
|
|
pv.Name = mtest.RandHex(4) + "-" + mtest.RandHex(4)
|
|
case "wEq":
|
|
pv.Name = mtest.RandHex(4) + "=" + mtest.RandHex(4)
|
|
}
|
|
|
|
pv.IsBool = tests[i].isBool
|
|
pv.IsString = !tests[i].isBool && tests[i].nonBoolType == "str"
|
|
|
|
var arg string
|
|
switch tests[i].path {
|
|
case "root":
|
|
rootCfg.ParamAdd(pv.Param)
|
|
arg = "--" + pv.Name
|
|
case "child":
|
|
childCfg.ParamAdd(pv.Param)
|
|
pv.Path = append(pv.Path, childName)
|
|
arg = "--" + childName + "-" + pv.Name
|
|
case "childDash":
|
|
childDashCfg.ParamAdd(pv.Param)
|
|
pv.Path = append(pv.Path, childDashName)
|
|
arg = "--" + childDashName + "-" + pv.Name
|
|
case "childEq":
|
|
childEqCfg.ParamAdd(pv.Param)
|
|
pv.Path = append(pv.Path, childEqName)
|
|
arg = "--" + childEqName + "-" + pv.Name
|
|
}
|
|
|
|
if pv.IsBool {
|
|
pv.Value = json.RawMessage("true")
|
|
args = append(args, arg)
|
|
continue
|
|
}
|
|
|
|
var val string
|
|
switch tests[i].nonBoolType {
|
|
case "int":
|
|
val = strconv.Itoa(mtest.Rand.Int())
|
|
pv.Value = json.RawMessage(val)
|
|
case "str":
|
|
switch tests[i].nonBoolStrValue {
|
|
case "empty":
|
|
// ez
|
|
case "normal":
|
|
val = mtest.RandHex(8)
|
|
case "wDash":
|
|
val = mtest.RandHex(4) + "-" + mtest.RandHex(4)
|
|
case "wEq":
|
|
val = mtest.RandHex(4) + "=" + mtest.RandHex(4)
|
|
}
|
|
pv.Value = json.RawMessage(`"` + val + `"`)
|
|
}
|
|
|
|
switch tests[i].nonBoolFmt {
|
|
case "wEq":
|
|
arg += "=" + val
|
|
args = append(args, arg)
|
|
case "woEq":
|
|
args = append(args, arg, val)
|
|
}
|
|
}
|
|
|
|
src := SourceCLI{Args: args}
|
|
pvals, err := src.Parse(rootCfg)
|
|
require.NoError(t, err)
|
|
assert.Len(t, pvals, len(tests))
|
|
|
|
for _, test := range tests {
|
|
assert.Contains(t, pvals, *test.exp)
|
|
}
|
|
|
|
// an extra bogus param or value should generate an error
|
|
src = SourceCLI{Args: append(args, "foo")}
|
|
_, err = src.Parse(rootCfg)
|
|
require.Error(t, err)
|
|
|
|
}
|
|
|
|
func TestSourceCLIHelp(t *T) {
|
|
cfg := New()
|
|
cfg.ParamInt("foo", 5, "Test int param")
|
|
cfg.ParamBool("bar", "Test bool param")
|
|
cfg.ParamString("baz", "baz", "Test string param")
|
|
cfg.ParamString("baz2", "", "")
|
|
src := SourceCLI{}
|
|
|
|
buf := new(bytes.Buffer)
|
|
pvM, err := src.cliParamVals(cfg)
|
|
require.NoError(t, err)
|
|
SourceCLI{}.printHelp(buf, pvM)
|
|
|
|
exp := `
|
|
--bar (Flag)
|
|
Test bool param
|
|
|
|
--baz (Default: "baz")
|
|
Test string param
|
|
|
|
--baz2
|
|
|
|
--foo (Default: 5)
|
|
Test int param
|
|
|
|
`
|
|
assert.Equal(t, exp, buf.String())
|
|
}
|