From 9623a8f64dd882aeef0cc14f3495a60e7a4717f1 Mon Sep 17 00:00:00 2001 From: VaibhavMalik4187 Date: Wed, 24 Jan 2024 18:15:18 +0530 Subject: [PATCH 1/3] 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" + } +] From 8c26fe18c63022f76557d16e596187c4e3fd7ab4 Mon Sep 17 00:00:00 2001 From: Manan Gupta Date: Tue, 5 Mar 2024 13:56:16 +0530 Subject: [PATCH 2/3] test: address review comments Signed-off-by: Manan Gupta --- go/cmd/rulesctl/cmd/add_test.go | 87 +++++++++++++++++++++++------ go/cmd/rulesctl/cmd/explain_test.go | 25 ++++++--- go/cmd/rulesctl/cmd/list_test.go | 56 ++++++++++++------- go/cmd/rulesctl/cmd/main_test.go | 27 ++++++--- go/cmd/rulesctl/cmd/remove_test.go | 34 ++++++++--- 5 files changed, 167 insertions(+), 62 deletions(-) diff --git a/go/cmd/rulesctl/cmd/add_test.go b/go/cmd/rulesctl/cmd/add_test.go index baf4c2db6d6..54c6623dab8 100644 --- a/go/cmd/rulesctl/cmd/add_test.go +++ b/go/cmd/rulesctl/cmd/add_test.go @@ -37,23 +37,75 @@ func TestAdd(t *testing.T) { 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", + args: []string{"--dry-run=true", "--name=Rule", `--description="New rules that will be added to the file"`, "--action=fail", "--plan=Select"}, + expectedOutput: `[ + { + "Description": "Some value", + "Name": "Name", + "Action": "FAIL" + }, + { + "Description": "\"New rules that will be added to the file\"", + "Name": "Rule", + "Plans": [ + "Select" + ], + "Action": "FAIL" + } +] +`, }, { - 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 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: `[ + { + "Description": "Some value", + "Name": "Name", + "Action": "FAIL" + }, + { + "Description": "\"New rules that will be added to the file\"", + "Name": "Rule", + "Plans": [ + "Select", + "Select" + ], + "Action": "FAIL_RETRY" + } +] +`, }, { - 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", + 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: `[ + { + "Description": "Some value", + "Name": "Name", + "Action": "FAIL" + }, + { + "Description": "\"New rules that will be added to the file\"", + "Name": "Rule", + "Query": "secret", + "LeadingComment": "None", + "TrailingComment": "Yoho", + "Plans": [ + "Select", + "Select", + "Select" + ], + "TableNames": [ + "Temp" + ] + } +] +`, }, } for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { if tt.args != nil { cmd.SetArgs(tt.args) @@ -61,18 +113,21 @@ func TestAdd(t *testing.T) { require.NoError(t, err) } + originalStdOut := os.Stdout + defer func() { + os.Stdout = originalStdOut + }() // 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) + err := w.Close() + require.NoError(t, err) + got, err := io.ReadAll(r) + require.NoError(t, err) + require.EqualValues(t, tt.expectedOutput, string(got)) }) } } diff --git a/go/cmd/rulesctl/cmd/explain_test.go b/go/cmd/rulesctl/cmd/explain_test.go index 588715d96d6..cc515a1eb3d 100644 --- a/go/cmd/rulesctl/cmd/explain_test.go +++ b/go/cmd/rulesctl/cmd/explain_test.go @@ -31,16 +31,20 @@ func TestExplainWithQueryPlanArguement(t *testing.T) { require.NotNil(t, explainCmd) require.Equal(t, "explain", explainCmd.Name()) + originalStdOut := os.Stdout + defer func() { + os.Stdout = originalStdOut + }() // 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 + err := w.Close() + require.NoError(t, err) + got, err := io.ReadAll(r) + require.NoError(t, err) expected := "Query Plans!" require.Contains(t, string(got), expected) @@ -53,15 +57,20 @@ func TestExplainWithRandomArguement(t *testing.T) { require.Equal(t, "explain", explainCmd.Name()) // Redirect stdout to a buffer - rescueStdout := os.Stdout + originalStdOut := os.Stdout + defer func() { + os.Stdout = originalStdOut + }() + // Redirect stdout to a buffer r, w, _ := os.Pipe() os.Stdout = w explainCmd.Run(&cobra.Command{}, []string{"random"}) - w.Close() - got, _ := io.ReadAll(r) - os.Stdout = rescueStdout + err := w.Close() + require.NoError(t, err) + got, err := io.ReadAll(r) + require.NoError(t, err) 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 index 71e9331703a..d787481165e 100644 --- a/go/cmd/rulesctl/cmd/list_test.go +++ b/go/cmd/rulesctl/cmd/list_test.go @@ -37,32 +37,44 @@ func TestList(t *testing.T) { expectedOutput string }{ { - name: "No args", - expectedOutput: "[\n {\n \"Description\": \"Some value\",\n \"Name\": \"Name\",\n \"Action\": \"FAIL\"\n }\n]\n", + name: "No args", + expectedOutput: `[ + { + "Description": "Some value", + "Name": "Name", + "Action": "FAIL" + } +] +`, }, { - name: "Name only", - args: []string{"--names-only=true"}, - expectedOutput: "[\n \"Name\"\n]\n", + name: "Name only", + args: []string{"--names-only=true"}, + expectedOutput: `[ + "Name" +] +`, }, { - name: "Name flag set", - args: []string{"--name=Name"}, - expectedOutput: "\"Name\"\n", + name: "Name flag set", + args: []string{"--name=Name"}, + expectedOutput: `"Name" +`, }, { - name: "Random name in name flag", - args: []string{"--name=Random"}, - expectedOutput: "\"\"\n", + name: "Random name in name flag", + args: []string{"--name=Random"}, + expectedOutput: `"" +`, }, { - name: "Random name in name flag and names-only false", - args: []string{"--name=Random", "--names-only=false"}, - expectedOutput: "null\n", + name: "Random name in name flag and names-only false", + args: []string{"--name=Random", "--names-only=false"}, + expectedOutput: `null +`, }, } for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { if tt.args != nil { cmd.SetArgs(tt.args) @@ -70,18 +82,22 @@ func TestList(t *testing.T) { require.NoError(t, err) } + originalStdOut := os.Stdout + defer func() { + os.Stdout = originalStdOut + }() // 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 + err := w.Close() + require.NoError(t, err) + got, err := io.ReadAll(r) + require.NoError(t, err) - require.Contains(t, string(got), tt.expectedOutput) + require.EqualValues(t, tt.expectedOutput, string(got)) }) } } diff --git a/go/cmd/rulesctl/cmd/main_test.go b/go/cmd/rulesctl/cmd/main_test.go index 6cd48a153e7..cbdba6c00e6 100644 --- a/go/cmd/rulesctl/cmd/main_test.go +++ b/go/cmd/rulesctl/cmd/main_test.go @@ -24,16 +24,16 @@ import ( "github.com/stretchr/testify/require" ) -func TestMain(t *testing.T) { +func TestMainFunction(t *testing.T) { rootCmd := Main() require.NotNil(t, rootCmd) require.Equal(t, "rulesctl", rootCmd.Name()) + originalStdOut := os.Stdout + defer func() { + os.Stdout = originalStdOut + }() // Redirect stdout to a buffer - rescueStdout := os.Stdout - t.Cleanup(func() { - os.Stdout = rescueStdout - }) r, w, _ := os.Pipe() os.Stdout = w @@ -43,9 +43,18 @@ func TestMain(t *testing.T) { err := rootCmd.Execute() require.NoError(t, err) - w.Close() - got, _ := io.ReadAll(r) + err = w.Close() + require.NoError(t, err) + got, err := io.ReadAll(r) + require.NoError(t, err) - expected := "[\n {\n \"Description\": \"Some value\",\n \"Name\": \"Name\",\n \"Action\": \"FAIL\"\n }\n]\n" - require.Equal(t, string(got), expected) + expected := `[ + { + "Description": "Some value", + "Name": "Name", + "Action": "FAIL" + } +] +` + require.EqualValues(t, expected, string(got)) } diff --git a/go/cmd/rulesctl/cmd/remove_test.go b/go/cmd/rulesctl/cmd/remove_test.go index d330f75c791..c3899b38463 100644 --- a/go/cmd/rulesctl/cmd/remove_test.go +++ b/go/cmd/rulesctl/cmd/remove_test.go @@ -31,17 +31,21 @@ func TestRemoveOld(t *testing.T) { require.NotNil(t, removeCmd) require.Equal(t, "remove-rule", removeCmd.Name()) + originalStdOut := os.Stdout + defer func() { + os.Stdout = originalStdOut + }() // 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 + err := w.Close() + require.NoError(t, err) + got, err := io.ReadAll(r) + require.NoError(t, err) expected := "No rule found:" require.Contains(t, string(got), expected) @@ -52,6 +56,15 @@ func TestRemove(t *testing.T) { require.NotNil(t, cmd) require.Equal(t, "remove-rule", cmd.Name()) configFile = "./testdata/rules.json" + defer func() { + _ = os.WriteFile(configFile, []byte(`[ + { + "Description": "Some value", + "Name": "Name" + } +] +`), 0777) + }() tests := []struct { name string @@ -74,7 +87,6 @@ func TestRemove(t *testing.T) { }, } for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { if tt.args != nil { cmd.SetArgs(tt.args) @@ -82,16 +94,20 @@ func TestRemove(t *testing.T) { require.NoError(t, err) } + originalStdOut := os.Stdout + defer func() { + os.Stdout = originalStdOut + }() // 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 + err := w.Close() + require.NoError(t, err) + got, err := io.ReadAll(r) + require.NoError(t, err) require.Contains(t, string(got), tt.expectedOutput) }) From f9560ac477b25bd9cdced81351f4ace01a644577 Mon Sep 17 00:00:00 2001 From: Manan Gupta Date: Tue, 5 Mar 2024 15:10:58 +0530 Subject: [PATCH 3/3] test: fix few more things Signed-off-by: Manan Gupta --- go/cmd/rulesctl/cmd/remove_test.go | 11 +++-- go/cmd/rulesctl/common/common_test.go | 59 ++++++++++++++++++--------- 2 files changed, 45 insertions(+), 25 deletions(-) diff --git a/go/cmd/rulesctl/cmd/remove_test.go b/go/cmd/rulesctl/cmd/remove_test.go index c3899b38463..d0ee9f9880e 100644 --- a/go/cmd/rulesctl/cmd/remove_test.go +++ b/go/cmd/rulesctl/cmd/remove_test.go @@ -88,12 +88,6 @@ func TestRemove(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if tt.args != nil { - cmd.SetArgs(tt.args) - err := cmd.Execute() - require.NoError(t, err) - } - originalStdOut := os.Stdout defer func() { os.Stdout = originalStdOut @@ -102,6 +96,11 @@ func TestRemove(t *testing.T) { r, w, _ := os.Pipe() os.Stdout = w + if tt.args != nil { + cmd.SetArgs(tt.args) + err := cmd.Execute() + require.NoError(t, err) + } cmd.Run(&cobra.Command{}, []string{}) err := w.Close() diff --git a/go/cmd/rulesctl/common/common_test.go b/go/cmd/rulesctl/common/common_test.go index 65542e7f9a7..aff7f012c20 100644 --- a/go/cmd/rulesctl/common/common_test.go +++ b/go/cmd/rulesctl/common/common_test.go @@ -19,6 +19,7 @@ package common import ( "io" "os" + "path" "testing" "github.com/stretchr/testify/require" @@ -29,35 +30,55 @@ func TestGetRules(t *testing.T) { require.NotEmpty(t, rules) } +type testStruct struct { + StringField string `yaml:"stringfield"` + IntField int `yaml:"intfield"` + BoolField bool `yaml:"boolfield"` + Float64Field float64 `yaml:"float64field"` +} + +var testData = testStruct{ + "tricky text to test text", + 32, + true, + 3.141, +} + func TestMustPrintJSON(t *testing.T) { - jsonFile, err := os.ReadFile("testdata/rules.json") - require.NoError(t, err) + originalStdOut := os.Stdout + defer func() { + os.Stdout = originalStdOut + }() // Redirect stdout to a buffer - rescueStdout := os.Stdout r, w, _ := os.Pipe() os.Stdout = w + MustPrintJSON(testData) - MustPrintJSON(jsonFile) - - w.Close() - got, _ := io.ReadAll(r) - os.Stdout = rescueStdout - - want := `"WwogICAgewogICAgICAgICJEZXNjcmlwdGlvbiI6ICJTb21lIHZhbHVlIiwKICAgICAgICAiTmFtZSI6ICJOYW1lIgogICAgfQpdCg=="` + "\n" - require.Equal(t, want, string(got)) + err := w.Close() + require.NoError(t, err) + got, err := io.ReadAll(r) + require.NoError(t, err) + require.Equal(t, `{ + "StringField": "tricky text to test text", + "IntField": 32, + "BoolField": true, + "Float64Field": 3.141 +} +`, 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) + tmpFile := path.Join(t.TempDir(), "temp.json") + MustWriteJSON(testData, tmpFile) - _, err = os.ReadFile(tmpFile) + res, err := os.ReadFile(tmpFile) require.NoError(t, err) - err = os.Remove(tmpFile) - require.NoError(t, err) + require.EqualValues(t, `{ + "StringField": "tricky text to test text", + "IntField": 32, + "BoolField": true, + "Float64Field": 3.141 +}`, string(res)) }