summaryrefslogtreecommitdiffstats
path: root/client/go/cmd/command_tester_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'client/go/cmd/command_tester_test.go')
-rw-r--r--client/go/cmd/command_tester_test.go124
1 files changed, 124 insertions, 0 deletions
diff --git a/client/go/cmd/command_tester_test.go b/client/go/cmd/command_tester_test.go
new file mode 100644
index 00000000000..d71cdde0e8f
--- /dev/null
+++ b/client/go/cmd/command_tester_test.go
@@ -0,0 +1,124 @@
+// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+// A helper for testing commands
+// Author: bratseth
+
+package cmd
+
+import (
+ "bytes"
+ "io"
+ "os"
+ "path/filepath"
+ "testing"
+
+ "github.com/spf13/pflag"
+ "github.com/spf13/viper"
+ "github.com/stretchr/testify/require"
+ "github.com/vespa-engine/vespa/client/go/mock"
+ "github.com/vespa-engine/vespa/client/go/util"
+)
+
+type command struct {
+ homeDir string
+ cacheDir string
+ stdin io.ReadWriter
+ args []string
+ moreArgs []string
+ env map[string]string
+ failTestOnError bool
+}
+
+func resetFlag(f *pflag.Flag) {
+ switch v := f.Value.(type) {
+ case pflag.SliceValue:
+ _ = v.Replace([]string{})
+ default:
+ switch v.Type() {
+ case "bool", "string", "int":
+ _ = v.Set(f.DefValue)
+ }
+ }
+}
+
+func setEnv(env map[string]string) map[string]string {
+ originalEnv := map[string]string{}
+ for k, v := range env {
+ value, ok := os.LookupEnv(k)
+ if ok {
+ originalEnv[k] = value
+ }
+ os.Setenv(k, v)
+ }
+ return originalEnv
+}
+
+func resetEnv(env map[string]string, original map[string]string) {
+ for k, _ := range env {
+ if v, ok := original[k]; ok {
+ os.Setenv(k, v)
+ } else {
+ os.Unsetenv(k)
+ }
+ }
+}
+
+func execute(cmd command, t *testing.T, client *mock.HTTPClient) (string, string) {
+ if client != nil {
+ util.ActiveHttpClient = client
+ }
+
+ // Set Vespa CLI directories. Use a separate one per test if none is specified
+ if cmd.homeDir == "" {
+ cmd.homeDir = filepath.Join(t.TempDir(), ".vespa")
+ viper.Reset()
+ }
+ if cmd.cacheDir == "" {
+ cmd.cacheDir = filepath.Join(t.TempDir(), ".cache", "vespa")
+ }
+
+ env := map[string]string{}
+ for k, v := range cmd.env {
+ env[k] = v
+ }
+ env["VESPA_CLI_HOME"] = cmd.homeDir
+ env["VESPA_CLI_CACHE_DIR"] = cmd.cacheDir
+ originalEnv := setEnv(env)
+ defer resetEnv(env, originalEnv)
+
+ // Reset viper at end of test to ensure vespa config set does not leak between tests
+ t.Cleanup(viper.Reset)
+
+ // Reset flags to their default value - persistent flags in Cobra persists over tests
+ // TODO: Due to the bad design of viper, the only proper fix is to get rid of global state by moving each command to
+ // their own sub-package
+ rootCmd.Flags().VisitAll(resetFlag)
+ queryCmd.Flags().VisitAll(resetFlag)
+ documentCmd.Flags().VisitAll(resetFlag)
+ logCmd.Flags().VisitAll(resetFlag)
+ certCmd.Flags().VisitAll(resetFlag)
+ certAddCmd.Flags().VisitAll(resetFlag)
+
+ // Capture stdout and execute command
+ var capturedOut bytes.Buffer
+ var capturedErr bytes.Buffer
+ stdout = &capturedOut
+ stderr = &capturedErr
+ if cmd.stdin != nil {
+ stdin = cmd.stdin
+ } else {
+ stdin = os.Stdin
+ }
+
+ // Execute command and return output
+ rootCmd.SetArgs(append(cmd.args, cmd.moreArgs...))
+ err := Execute()
+ if cmd.failTestOnError {
+ require.Nil(t, err)
+ }
+ return capturedOut.String(), capturedErr.String()
+}
+
+func executeCommand(t *testing.T, client *mock.HTTPClient, args []string, moreArgs []string) string {
+ out, _ := execute(command{args: args, moreArgs: moreArgs}, t, client)
+ return out
+}