From 9623a8f64dd882aeef0cc14f3495a60e7a4717f1 Mon Sep 17 00:00:00 2001 From: VaibhavMalik4187 Date: Wed, 24 Jan 2024 18:15:18 +0530 Subject: [PATCH] Added unit tests for `go/cmd/rulesctl/` package This commit increases the code coverage of the `cmd/rulesctl/common` package to 71% and that of `cmd/rulesctl/cmd` package to >90% Partially Fixes: https://github.com/vitessio/vitess/issues/14931 Signed-off-by: VaibhavMalik4187 --- go/cmd/rulesctl/cmd/add_test.go | 78 +++++++++++++++++ go/cmd/rulesctl/cmd/explain_test.go | 68 +++++++++++++++ go/cmd/rulesctl/cmd/list_test.go | 87 +++++++++++++++++++ go/cmd/rulesctl/cmd/main_test.go | 51 +++++++++++ go/cmd/rulesctl/cmd/remove_test.go | 99 ++++++++++++++++++++++ go/cmd/rulesctl/cmd/testdata/rules.json | 6 ++ go/cmd/rulesctl/common/common_test.go | 63 ++++++++++++++ go/cmd/rulesctl/common/testdata/rules.json | 6 ++ 8 files changed, 458 insertions(+) create mode 100644 go/cmd/rulesctl/cmd/add_test.go create mode 100644 go/cmd/rulesctl/cmd/explain_test.go create mode 100644 go/cmd/rulesctl/cmd/list_test.go create mode 100644 go/cmd/rulesctl/cmd/main_test.go create mode 100644 go/cmd/rulesctl/cmd/remove_test.go create mode 100644 go/cmd/rulesctl/cmd/testdata/rules.json create mode 100644 go/cmd/rulesctl/common/common_test.go create mode 100644 go/cmd/rulesctl/common/testdata/rules.json diff --git a/go/cmd/rulesctl/cmd/add_test.go b/go/cmd/rulesctl/cmd/add_test.go new file mode 100644 index 00000000000..baf4c2db6d6 --- /dev/null +++ b/go/cmd/rulesctl/cmd/add_test.go @@ -0,0 +1,78 @@ +/* +Copyright 2024 The Vitess Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package cmd + +import ( + "io" + "os" + "testing" + + "github.com/spf13/cobra" + "github.com/stretchr/testify/require" +) + +func TestAdd(t *testing.T) { + cmd := Add() + require.NotNil(t, cmd) + require.Equal(t, "add-rule", cmd.Name()) + configFile = "./testdata/rules.json" + + tests := []struct { + name string + args []string + expectedOutput string + }{ + { + name: "Action fail", + args: []string{"--dry-run=true", "--name=Rule", `--description="New rules that will be added to the file"`, "--action=fail", "--plan=Select"}, + expectedOutput: "[\n {\n \"Description\": \"Some value\",\n \"Name\": \"Name\",\n \"Action\": \"FAIL\"\n },\n {\n \"Description\": \"\\\"New rules that will be added to the file\\\"\",\n \"Name\": \"Rule\",\n \"Plans\": [\n \"Select\"\n ],\n \"Action\": \"FAIL\"\n }\n]\n", + }, + { + name: "Action fail_retry", + args: []string{"--dry-run=true", "--name=Rule", `--description="New rules that will be added to the file"`, "--action=fail_retry", "--plan=Select"}, + expectedOutput: "[\n {\n \"Description\": \"Some value\",\n \"Name\": \"Name\",\n \"Action\": \"FAIL\"\n },\n {\n \"Description\": \"\\\"New rules that will be added to the file\\\"\",\n \"Name\": \"Rule\",\n \"Plans\": [\n \"Select\",\n \"Select\"\n ],\n \"Action\": \"FAIL_RETRY\"\n }\n]\n", + }, + { + name: "Action continue with query", + args: []string{"--dry-run=true", "--name=Rule", `--description="New rules that will be added to the file"`, "--action=continue", "--plan=Select", "--query=secret", "--leading-comment=None", "--trailing-comment=Yoho", "--table=Temp"}, + expectedOutput: "[\n {\n \"Description\": \"Some value\",\n \"Name\": \"Name\",\n \"Action\": \"FAIL\"\n },\n {\n \"Description\": \"\\\"New rules that will be added to the file\\\"\",\n \"Name\": \"Rule\",\n \"Query\": \"secret\",\n \"LeadingComment\": \"None\",\n \"TrailingComment\": \"Yoho\",\n \"Plans\": [\n \"Select\",\n \"Select\",\n \"Select\"\n ],\n \"TableNames\": [\n \"Temp\"\n ]\n }\n]\n", + }, + } + for _, tt := range tests { + tt := tt + t.Run(tt.name, func(t *testing.T) { + if tt.args != nil { + cmd.SetArgs(tt.args) + err := cmd.Execute() + require.NoError(t, err) + } + + // Redirect stdout to a buffer + rescueStdout := os.Stdout + r, w, _ := os.Pipe() + os.Stdout = w + + cmd.Run(&cobra.Command{}, []string{}) + + w.Close() + got, _ := io.ReadAll(r) + os.Stdout = rescueStdout + + require.Contains(t, string(got), tt.expectedOutput) + }) + } +} diff --git a/go/cmd/rulesctl/cmd/explain_test.go b/go/cmd/rulesctl/cmd/explain_test.go new file mode 100644 index 00000000000..588715d96d6 --- /dev/null +++ b/go/cmd/rulesctl/cmd/explain_test.go @@ -0,0 +1,68 @@ +/* +Copyright 2024 The Vitess Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package cmd + +import ( + "io" + "os" + "testing" + + "github.com/spf13/cobra" + "github.com/stretchr/testify/require" +) + +func TestExplainWithQueryPlanArguement(t *testing.T) { + explainCmd := Explain() + + require.NotNil(t, explainCmd) + require.Equal(t, "explain", explainCmd.Name()) + + // Redirect stdout to a buffer + rescueStdout := os.Stdout + r, w, _ := os.Pipe() + os.Stdout = w + + explainCmd.Run(&cobra.Command{}, []string{"query-plans"}) + + w.Close() + got, _ := io.ReadAll(r) + os.Stdout = rescueStdout + + expected := "Query Plans!" + require.Contains(t, string(got), expected) +} + +func TestExplainWithRandomArguement(t *testing.T) { + explainCmd := Explain() + + require.NotNil(t, explainCmd) + require.Equal(t, "explain", explainCmd.Name()) + + // Redirect stdout to a buffer + rescueStdout := os.Stdout + r, w, _ := os.Pipe() + os.Stdout = w + + explainCmd.Run(&cobra.Command{}, []string{"random"}) + + w.Close() + got, _ := io.ReadAll(r) + os.Stdout = rescueStdout + + expected := "I don't know anything about" + require.Contains(t, string(got), expected) +} diff --git a/go/cmd/rulesctl/cmd/list_test.go b/go/cmd/rulesctl/cmd/list_test.go new file mode 100644 index 00000000000..71e9331703a --- /dev/null +++ b/go/cmd/rulesctl/cmd/list_test.go @@ -0,0 +1,87 @@ +/* +Copyright 2024 The Vitess Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package cmd + +import ( + "io" + "os" + "testing" + + "github.com/spf13/cobra" + "github.com/stretchr/testify/require" +) + +func TestList(t *testing.T) { + cmd := List() + require.NotNil(t, cmd) + require.Equal(t, "list", cmd.Name()) + configFile = "./testdata/rules.json" + + tests := []struct { + name string + args []string + expectedOutput string + }{ + { + name: "No args", + expectedOutput: "[\n {\n \"Description\": \"Some value\",\n \"Name\": \"Name\",\n \"Action\": \"FAIL\"\n }\n]\n", + }, + { + name: "Name only", + args: []string{"--names-only=true"}, + expectedOutput: "[\n \"Name\"\n]\n", + }, + { + name: "Name flag set", + args: []string{"--name=Name"}, + expectedOutput: "\"Name\"\n", + }, + { + name: "Random name in name flag", + args: []string{"--name=Random"}, + expectedOutput: "\"\"\n", + }, + { + name: "Random name in name flag and names-only false", + args: []string{"--name=Random", "--names-only=false"}, + expectedOutput: "null\n", + }, + } + for _, tt := range tests { + tt := tt + t.Run(tt.name, func(t *testing.T) { + if tt.args != nil { + cmd.SetArgs(tt.args) + err := cmd.Execute() + require.NoError(t, err) + } + + // Redirect stdout to a buffer + rescueStdout := os.Stdout + r, w, _ := os.Pipe() + os.Stdout = w + + cmd.Run(&cobra.Command{}, []string{}) + + w.Close() + got, _ := io.ReadAll(r) + os.Stdout = rescueStdout + + require.Contains(t, string(got), tt.expectedOutput) + }) + } +} diff --git a/go/cmd/rulesctl/cmd/main_test.go b/go/cmd/rulesctl/cmd/main_test.go new file mode 100644 index 00000000000..6cd48a153e7 --- /dev/null +++ b/go/cmd/rulesctl/cmd/main_test.go @@ -0,0 +1,51 @@ +/* +Copyright 2024 The Vitess Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package cmd + +import ( + "io" + "os" + "testing" + + "github.com/stretchr/testify/require" +) + +func TestMain(t *testing.T) { + rootCmd := Main() + require.NotNil(t, rootCmd) + require.Equal(t, "rulesctl", rootCmd.Name()) + + // Redirect stdout to a buffer + rescueStdout := os.Stdout + t.Cleanup(func() { + os.Stdout = rescueStdout + }) + r, w, _ := os.Pipe() + os.Stdout = w + + args := os.Args + t.Cleanup(func() { os.Args = args }) + os.Args = []string{"rulesctl", "-f=testdata/rules.json", "list"} + err := rootCmd.Execute() + require.NoError(t, err) + + w.Close() + got, _ := io.ReadAll(r) + + expected := "[\n {\n \"Description\": \"Some value\",\n \"Name\": \"Name\",\n \"Action\": \"FAIL\"\n }\n]\n" + require.Equal(t, string(got), expected) +} diff --git a/go/cmd/rulesctl/cmd/remove_test.go b/go/cmd/rulesctl/cmd/remove_test.go new file mode 100644 index 00000000000..d330f75c791 --- /dev/null +++ b/go/cmd/rulesctl/cmd/remove_test.go @@ -0,0 +1,99 @@ +/* +Copyright 2024 The Vitess Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package cmd + +import ( + "io" + "os" + "testing" + + "github.com/spf13/cobra" + "github.com/stretchr/testify/require" +) + +func TestRemoveOld(t *testing.T) { + removeCmd := Remove() + + require.NotNil(t, removeCmd) + require.Equal(t, "remove-rule", removeCmd.Name()) + + // Redirect stdout to a buffer + rescueStdout := os.Stdout + r, w, _ := os.Pipe() + os.Stdout = w + + configFile = "../common/testdata/rules.json" + removeCmd.Run(&cobra.Command{}, []string{""}) + + w.Close() + got, _ := io.ReadAll(r) + os.Stdout = rescueStdout + + expected := "No rule found:" + require.Contains(t, string(got), expected) +} + +func TestRemove(t *testing.T) { + cmd := Remove() + require.NotNil(t, cmd) + require.Equal(t, "remove-rule", cmd.Name()) + configFile = "./testdata/rules.json" + + tests := []struct { + name string + args []string + expectedOutput string + }{ + { + name: "No args", + expectedOutput: "No rule found: ''", + }, + { + name: "Dry run and name both set", + args: []string{"--dry-run=true", "--name=Name"}, + expectedOutput: "[]\n", + }, + { + name: "Dry run not set name set", + args: []string{"--dry-run=false", "--name=Name"}, + expectedOutput: "No rule found: 'Name'", + }, + } + for _, tt := range tests { + tt := tt + t.Run(tt.name, func(t *testing.T) { + if tt.args != nil { + cmd.SetArgs(tt.args) + err := cmd.Execute() + require.NoError(t, err) + } + + // Redirect stdout to a buffer + rescueStdout := os.Stdout + r, w, _ := os.Pipe() + os.Stdout = w + + cmd.Run(&cobra.Command{}, []string{}) + + w.Close() + got, _ := io.ReadAll(r) + os.Stdout = rescueStdout + + require.Contains(t, string(got), tt.expectedOutput) + }) + } +} diff --git a/go/cmd/rulesctl/cmd/testdata/rules.json b/go/cmd/rulesctl/cmd/testdata/rules.json new file mode 100644 index 00000000000..12f0bfa0b5a --- /dev/null +++ b/go/cmd/rulesctl/cmd/testdata/rules.json @@ -0,0 +1,6 @@ +[ + { + "Description": "Some value", + "Name": "Name" + } +] diff --git a/go/cmd/rulesctl/common/common_test.go b/go/cmd/rulesctl/common/common_test.go new file mode 100644 index 00000000000..65542e7f9a7 --- /dev/null +++ b/go/cmd/rulesctl/common/common_test.go @@ -0,0 +1,63 @@ +/* +Copyright 2024 The Vitess Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package common + +import ( + "io" + "os" + "testing" + + "github.com/stretchr/testify/require" +) + +func TestGetRules(t *testing.T) { + rules := GetRules("testdata/rules.json") + require.NotEmpty(t, rules) +} + +func TestMustPrintJSON(t *testing.T) { + jsonFile, err := os.ReadFile("testdata/rules.json") + require.NoError(t, err) + + // Redirect stdout to a buffer + rescueStdout := os.Stdout + r, w, _ := os.Pipe() + os.Stdout = w + + MustPrintJSON(jsonFile) + + w.Close() + got, _ := io.ReadAll(r) + os.Stdout = rescueStdout + + want := `"WwogICAgewogICAgICAgICJEZXNjcmlwdGlvbiI6ICJTb21lIHZhbHVlIiwKICAgICAgICAiTmFtZSI6ICJOYW1lIgogICAgfQpdCg=="` + "\n" + require.Equal(t, want, string(got)) +} + +func TestMustWriteJSON(t *testing.T) { + jsonFile, err := os.ReadFile("testdata/rules.json") + require.NoError(t, err) + + tmpFile := "testdata/temp.json" + MustWriteJSON(jsonFile, tmpFile) + + _, err = os.ReadFile(tmpFile) + require.NoError(t, err) + + err = os.Remove(tmpFile) + require.NoError(t, err) +} diff --git a/go/cmd/rulesctl/common/testdata/rules.json b/go/cmd/rulesctl/common/testdata/rules.json new file mode 100644 index 00000000000..12f0bfa0b5a --- /dev/null +++ b/go/cmd/rulesctl/common/testdata/rules.json @@ -0,0 +1,6 @@ +[ + { + "Description": "Some value", + "Name": "Name" + } +]