diff --git a/.golangci.yaml b/.golangci.yaml index 3fd336f2..1995214e 100644 --- a/.golangci.yaml +++ b/.golangci.yaml @@ -73,6 +73,7 @@ linters-settings: - "github.com/prometheus/client_model/go" - "github.com/prometheus/common/expfmt" - "github.com/panjf2000/gnet/v2" + - "github.com/spf13/cobra" tagalign: align: false sort: false diff --git a/cmd/cmd_helpers_test.go b/cmd/cmd_helpers_test.go new file mode 100644 index 00000000..e8ed00bc --- /dev/null +++ b/cmd/cmd_helpers_test.go @@ -0,0 +1,20 @@ +package cmd + +import ( + "bytes" + + "github.com/spf13/cobra" +) + +// executeCommandC executes a cobra command and returns the command, output, and error. +// Taken from https://github.com/spf13/cobra/blob/0c72800b8dba637092b57a955ecee75949e79a73/command_test.go#L48. +func executeCommandC(root *cobra.Command, args ...string) (string, error) { + buf := new(bytes.Buffer) + root.SetOut(buf) + root.SetErr(buf) + root.SetArgs(args) + + _, err := root.ExecuteC() + + return buf.String(), err +} diff --git a/cmd/config_init_test.go b/cmd/config_init_test.go new file mode 100644 index 00000000..1c737590 --- /dev/null +++ b/cmd/config_init_test.go @@ -0,0 +1,36 @@ +package cmd + +import ( + "fmt" + "os" + "testing" + + "github.com/stretchr/testify/assert" +) + +func Test_configInitCmd(t *testing.T) { + // Reset globalConfigFile to avoid conflicts with other tests. + globalConfigFile = "./test_config.yaml" + + // Test configInitCmd. + output, err := executeCommandC(rootCmd, "config", "init", "-c", globalConfigFile) + assert.NoError(t, err, "configInitCmd should not return an error") + assert.Equal(t, + fmt.Sprintf("Config file '%s' was created successfully.", globalConfigFile), + output, + "configInitCmd should print the correct output") + // Check that the config file was created. + assert.FileExists(t, globalConfigFile, "configInitCmd should create a config file") + + // Test configInitCmd with the --force flag to overwrite the config file. + output, err = executeCommandC(rootCmd, "config", "init", "--force") + assert.NoError(t, err, "configInitCmd should not return an error") + assert.Equal(t, + fmt.Sprintf("Config file '%s' was overwritten successfully.", globalConfigFile), + output, + "configInitCmd should print the correct output") + + // Clean up. + err = os.Remove(globalConfigFile) + assert.NoError(t, err) +} diff --git a/cmd/config_lint_test.go b/cmd/config_lint_test.go new file mode 100644 index 00000000..c046925e --- /dev/null +++ b/cmd/config_lint_test.go @@ -0,0 +1,36 @@ +package cmd + +import ( + "fmt" + "os" + "testing" + + "github.com/stretchr/testify/assert" +) + +func Test_configLintCmd(t *testing.T) { + // Reset globalConfigFile to avoid conflicts with other tests. + globalConfigFile = "./test_config.yaml" + + // Test configInitCmd. + output, err := executeCommandC(rootCmd, "config", "init", "-c", globalConfigFile) + assert.NoError(t, err, "configInitCmd should not return an error") + assert.Equal(t, + fmt.Sprintf("Config file '%s' was created successfully.", globalConfigFile), + output, + "configInitCmd should print the correct output") + // Check that the config file was created. + assert.FileExists(t, globalConfigFile, "configInitCmd should create a config file") + + // Test configLintCmd. + output, err = executeCommandC(rootCmd, "config", "lint", "-c", globalConfigFile) + assert.NoError(t, err, "configLintCmd should not return an error") + assert.Equal(t, + "global config is valid\n", + output, + "configLintCmd should print the correct output") + + // Clean up. + err = os.Remove(globalConfigFile) + assert.NoError(t, err) +} diff --git a/cmd/config_test.go b/cmd/config_test.go new file mode 100644 index 00000000..62870b55 --- /dev/null +++ b/cmd/config_test.go @@ -0,0 +1,31 @@ +package cmd + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func Test_configCmd(t *testing.T) { + // Test configCmd with no arguments. + output, err := executeCommandC(rootCmd, "config") + assert.NoError(t, err, "configCmd should not return an error") + assert.Equal(t, + `Manage GatewayD global configuration + +Usage: + gatewayd config [flags] + gatewayd config [command] + +Available Commands: + init Create or overwrite the GatewayD global config + lint Lint the GatewayD global config + +Flags: + -h, --help help for config + +Use "gatewayd config [command] --help" for more information about a command. +`, + output, + "configCmd should print the correct output") +} diff --git a/cmd/plugin_init_test.go b/cmd/plugin_init_test.go new file mode 100644 index 00000000..b05a077e --- /dev/null +++ b/cmd/plugin_init_test.go @@ -0,0 +1,25 @@ +package cmd + +import ( + "fmt" + "os" + "testing" + + "github.com/stretchr/testify/assert" +) + +func Test_pluginInitCmd(t *testing.T) { + // Test plugin init command. + pluginConfigFile := "./test.yaml" + output, err := executeCommandC(rootCmd, "plugin", "init", "-p", pluginConfigFile) + assert.NoError(t, err, "plugin init command should not have returned an error") + assert.Equal(t, + fmt.Sprintf("Config file '%s' was created successfully.", pluginConfigFile), + output, + "plugin init command should have returned the correct output") + assert.FileExists(t, pluginConfigFile, "plugin init command should have created a config file") + + // Clean up. + err = os.Remove(pluginConfigFile) + assert.NoError(t, err) +} diff --git a/cmd/plugin_lint_test.go b/cmd/plugin_lint_test.go new file mode 100644 index 00000000..88574b23 --- /dev/null +++ b/cmd/plugin_lint_test.go @@ -0,0 +1,18 @@ +package cmd + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func Test_pluginLintCmd(t *testing.T) { + // Test plugin lint command. + pluginConfigFile := "../gatewayd_plugins.yaml" + output, err := executeCommandC(rootCmd, "plugin", "lint", "-p", pluginConfigFile) + assert.NoError(t, err, "plugin lint command should not have returned an error") + assert.Equal(t, + "plugins config is valid\n", + output, + "plugin lint command should have returned the correct output") +} diff --git a/cmd/plugin_list_test.go b/cmd/plugin_list_test.go new file mode 100644 index 00000000..ea85318d --- /dev/null +++ b/cmd/plugin_list_test.go @@ -0,0 +1,64 @@ +package cmd + +import ( + "fmt" + "os" + "testing" + + "github.com/stretchr/testify/assert" +) + +func Test_pluginListCmd(t *testing.T) { + // Test plugin list command. + pluginConfigFile := "./test.yaml" + output, err := executeCommandC(rootCmd, "plugin", "init", "-p", pluginConfigFile) + assert.NoError(t, err, "plugin init command should not have returned an error") + assert.Equal(t, + fmt.Sprintf("Config file '%s' was created successfully.", pluginConfigFile), + output, + "plugin init command should have returned the correct output") + assert.FileExists(t, pluginConfigFile, "plugin init command should have created a config file") + + output, err = executeCommandC(rootCmd, "plugin", "list", "-p", pluginConfigFile) + assert.NoError(t, err, "plugin list command should not have returned an error") + assert.Equal(t, + "No plugins found\n", + output, + "plugin list command should have returned empty output") + + // Clean up. + err = os.Remove(pluginConfigFile) + assert.NoError(t, err) +} + +func Test_pluginListCmdWithPlugins(t *testing.T) { + // Test plugin list command. + // Read the plugin config file from the root directory. + pluginConfigFile := "../gatewayd_plugins.yaml" + output, err := executeCommandC(rootCmd, "plugin", "list", "-p", pluginConfigFile) + assert.NoError(t, err, "plugin list command should not have returned an error") + assert.Equal(t, `Total plugins: 1 +Plugins: + Name: gatewayd-plugin-cache + Enabled: true + Path: ../gatewayd-plugin-cache/gatewayd-plugin-cache + Args: --log-level debug + Env: + MAGIC_COOKIE_KEY=GATEWAYD_PLUGIN + MAGIC_COOKIE_VALUE=5712b87aa5d7e9f9e9ab643e6603181c5b796015cb1c09d6f5ada882bf2a1872 + REDIS_URL=redis://localhost:6379/0 + EXPIRY=1h + METRICS_ENABLED=True + METRICS_UNIX_DOMAIN_SOCKET=/tmp/gatewayd-plugin-cache.sock + METRICS_PATH=/metrics + PERIODIC_INVALIDATOR_ENABLED=True + PERIODIC_INVALIDATOR_INTERVAL=1m + PERIODIC_INVALIDATOR_START_DELAY=1m + API_ADDRESS=localhost:18080 + EXIT_ON_STARTUP_ERROR=False + SENTRY_DSN=https://70eb1abcd32e41acbdfc17bc3407a543@o4504550475038720.ingest.sentry.io/4505342961123328 + Checksum: 054e7dba9c1e3e3910f4928a000d35c8a6199719fad505c66527f3e9b1993833 +`, + output, + "plugin list command should have returned the correct output") +} diff --git a/cmd/plugin_test.go b/cmd/plugin_test.go new file mode 100644 index 00000000..4f8233a3 --- /dev/null +++ b/cmd/plugin_test.go @@ -0,0 +1,32 @@ +package cmd + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func Test_pluginCmd(t *testing.T) { + // Test pluginCmd with no arguments. + output, err := executeCommandC(rootCmd, "plugin") + assert.NoError(t, err, "pluginCmd should not return an error") + assert.Equal(t, `Manage plugins and their configuration + +Usage: + gatewayd plugin [flags] + gatewayd plugin [command] + +Available Commands: + init Create or overwrite the GatewayD plugins config + install Install a plugin from a local archive or a GitHub repository + lint Lint the GatewayD plugins config + list List the GatewayD plugins + +Flags: + -h, --help help for plugin + +Use "gatewayd plugin [command] --help" for more information about a command. +`, + output, + "pluginCmd should print the correct output") +} diff --git a/cmd/root_test.go b/cmd/root_test.go new file mode 100644 index 00000000..ea2ee268 --- /dev/null +++ b/cmd/root_test.go @@ -0,0 +1,34 @@ +package cmd + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func Test_rootCmd(t *testing.T) { + output, err := executeCommandC(rootCmd) + assert.NoError(t, err, "rootCmd should not return an error") + //nolint:lll + assert.Equal(t, + `GatewayD is a cloud-native database gateway and framework for building data-driven applications. It sits between your database servers and clients and proxies all their communication. + +Usage: + gatewayd [command] + +Available Commands: + completion Generate the autocompletion script for the specified shell + config Manage GatewayD global configuration + help Help about any command + plugin Manage plugins and their configuration + run Run a GatewayD instance + version Show version information + +Flags: + -h, --help help for gatewayd + +Use "gatewayd [command] --help" for more information about a command. +`, + output, + "rootCmd should print the correct output") +} diff --git a/cmd/version.go b/cmd/version.go index 524725de..94c44cba 100644 --- a/cmd/version.go +++ b/cmd/version.go @@ -10,7 +10,7 @@ var versionCmd = &cobra.Command{ Use: "version", Short: "Show version information", Run: func(cmd *cobra.Command, _ []string) { - cmd.Println(config.VersionInfo()) //nolint:forbidigo + cmd.Println(config.VersionInfo()) }, } diff --git a/cmd/version_test.go b/cmd/version_test.go new file mode 100644 index 00000000..c648cad2 --- /dev/null +++ b/cmd/version_test.go @@ -0,0 +1,23 @@ +package cmd + +import ( + "regexp" + "testing" + + "github.com/gatewayd-io/gatewayd/config" + "github.com/stretchr/testify/assert" +) + +func Test_versionCmd(t *testing.T) { + // Test versionCmd with no arguments. + config.Version = "SEMVER" + config.VersionDetails = "COMMIT-HASH" + output, err := executeCommandC(rootCmd, "version") + assert.NoError(t, err, "versionCmd should not return an error") + assert.Regexp(t, + // The regexp matches something like the following output: + // GatewayD v0.7.7 (2023-09-16T19:27:38+0000/038f75b, go1.21.0, linux/amd64) + regexp.MustCompile(`^GatewayD SEMVER \(COMMIT-HASH, go\d+\.\d+\.\d+, \w+/\w+\)\n$`), + output, + "versionCmd should print the correct output") +}