209 lines
3.7 KiB
Go
209 lines
3.7 KiB
Go
package cli
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"io/ioutil"
|
|
"os"
|
|
"path"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
type customFlag bool
|
|
|
|
func (c customFlag) String() string {
|
|
if c == true {
|
|
return "on"
|
|
}
|
|
return "off"
|
|
}
|
|
|
|
func (c *customFlag) Set(s string) error {
|
|
if s == "on" {
|
|
*c = true
|
|
} else {
|
|
*c = false
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (c *customFlag) Type() string {
|
|
return "fancy-bool"
|
|
}
|
|
|
|
func ExampleNewCommand() {
|
|
var monitorHost string
|
|
var number int
|
|
var sleep bool
|
|
var duration time.Duration
|
|
var stringSlice []string
|
|
var fancyBool customFlag
|
|
cmd := NewCommand(&Program{
|
|
Run: func() error {
|
|
fmt.Println(monitorHost)
|
|
for i := 0; i < number; i++ {
|
|
fmt.Printf("%d\n", i)
|
|
}
|
|
fmt.Println(sleep)
|
|
fmt.Println(duration)
|
|
fmt.Println(stringSlice)
|
|
fmt.Println(fancyBool)
|
|
return nil
|
|
},
|
|
Name: "myprogram",
|
|
Opts: []Opt{
|
|
{
|
|
DestP: &monitorHost,
|
|
Flag: "monitor-host",
|
|
Default: "http://localhost:8086",
|
|
Desc: "host to send influxdb metrics",
|
|
},
|
|
{
|
|
DestP: &number,
|
|
Flag: "number",
|
|
Default: 2,
|
|
Desc: "number of times to loop",
|
|
},
|
|
{
|
|
DestP: &sleep,
|
|
Flag: "sleep",
|
|
Default: true,
|
|
Desc: "whether to sleep",
|
|
},
|
|
{
|
|
DestP: &duration,
|
|
Flag: "duration",
|
|
Default: time.Minute,
|
|
Desc: "how long to sleep",
|
|
},
|
|
{
|
|
DestP: &stringSlice,
|
|
Flag: "string-slice",
|
|
Default: []string{"foo", "bar"},
|
|
Desc: "things come in lists",
|
|
},
|
|
{
|
|
DestP: &fancyBool,
|
|
Flag: "fancy-bool",
|
|
Default: "on",
|
|
Desc: "things that implement pflag.Value",
|
|
},
|
|
},
|
|
})
|
|
|
|
if err := cmd.Execute(); err != nil {
|
|
fmt.Fprintln(os.Stderr, err)
|
|
}
|
|
// Output:
|
|
// http://localhost:8086
|
|
// 0
|
|
// 1
|
|
// true
|
|
// 1m0s
|
|
// [foo bar]
|
|
// on
|
|
}
|
|
|
|
func Test_NewProgram(t *testing.T) {
|
|
testFilePath, cleanup := newConfigFile(t, map[string]string{
|
|
// config values should be same as flags
|
|
"foo": "bar",
|
|
"shoe-fly": "yadon",
|
|
})
|
|
defer cleanup()
|
|
defer setEnvVar("TEST_CONFIG_PATH", testFilePath)()
|
|
|
|
tests := []struct {
|
|
name string
|
|
envVarVal string
|
|
args []string
|
|
expected string
|
|
}{
|
|
{
|
|
name: "no vals reads from config",
|
|
expected: "bar",
|
|
},
|
|
{
|
|
name: "reads from env var",
|
|
envVarVal: "foobar",
|
|
expected: "foobar",
|
|
},
|
|
{
|
|
name: "reads from flag",
|
|
args: []string{"--foo=baz"},
|
|
expected: "baz",
|
|
},
|
|
{
|
|
name: "flag has highest precedence",
|
|
envVarVal: "foobar",
|
|
args: []string{"--foo=baz"},
|
|
expected: "baz",
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
fn := func(t *testing.T) {
|
|
if tt.envVarVal != "" {
|
|
defer setEnvVar("TEST_FOO", tt.envVarVal)()
|
|
}
|
|
|
|
var testVar string
|
|
var testFly string
|
|
program := &Program{
|
|
Name: "test",
|
|
Opts: []Opt{
|
|
{
|
|
DestP: &testVar,
|
|
Flag: "foo",
|
|
Required: true,
|
|
},
|
|
{
|
|
DestP: &testFly,
|
|
Flag: "shoe-fly",
|
|
},
|
|
},
|
|
Run: func() error { return nil },
|
|
}
|
|
|
|
cmd := NewCommand(program)
|
|
cmd.SetArgs(append([]string{}, tt.args...))
|
|
require.NoError(t, cmd.Execute())
|
|
|
|
require.Equal(t, tt.expected, testVar)
|
|
assert.Equal(t, "yadon", testFly)
|
|
}
|
|
|
|
t.Run(tt.name, fn)
|
|
}
|
|
}
|
|
|
|
func setEnvVar(key, val string) func() {
|
|
old := os.Getenv(key)
|
|
os.Setenv(key, val)
|
|
return func() {
|
|
os.Setenv(key, old)
|
|
}
|
|
}
|
|
|
|
func newConfigFile(t *testing.T, config interface{}) (string, func()) {
|
|
t.Helper()
|
|
|
|
testDir, err := ioutil.TempDir("", "")
|
|
require.NoError(t, err)
|
|
|
|
b, err := json.Marshal(config)
|
|
require.NoError(t, err)
|
|
|
|
testFile := path.Join(testDir, "config.json")
|
|
require.NoError(t, ioutil.WriteFile(testFile, b, os.ModePerm))
|
|
|
|
return testFile, func() {
|
|
os.RemoveAll(testDir)
|
|
}
|
|
}
|