Skip to content

Commit afd6207

Browse files
authored
Merge pull request #18 from ncode/juliano/updates
(feat): Improve a bit coverage
2 parents fe8f7cb + 1734d39 commit afd6207

File tree

4 files changed

+522
-0
lines changed

4 files changed

+522
-0
lines changed

cmd/cleanup_test.go

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
package cmd
2+
3+
import (
4+
"bytes"
5+
"testing"
6+
7+
"github.com/spf13/cobra"
8+
"github.com/stretchr/testify/assert"
9+
)
10+
11+
func TestCleanupCmd(t *testing.T) {
12+
tests := []struct {
13+
name string
14+
args []string
15+
expectError bool
16+
errorContains string
17+
}{
18+
{
19+
name: "Missing required service-id",
20+
args: []string{"cleanup"},
21+
expectError: true,
22+
errorContains: "required flag(s)",
23+
},
24+
{
25+
name: "Missing required script (even though not used for cleanup)",
26+
args: []string{"cleanup", "--service-id=test-service"},
27+
expectError: true,
28+
errorContains: "required flag(s) \"script\" not set",
29+
},
30+
}
31+
32+
for _, tt := range tests {
33+
t.Run(tt.name, func(t *testing.T) {
34+
// Create a new root command for each test
35+
cmd := &cobra.Command{Use: "tagit"}
36+
cmd.PersistentFlags().StringP("consul-addr", "c", "127.0.0.1:8500", "consul address")
37+
cmd.PersistentFlags().StringP("service-id", "s", "", "consul service id")
38+
cmd.MarkPersistentFlagRequired("service-id")
39+
cmd.PersistentFlags().StringP("script", "x", "", "path to script used to generate tags")
40+
cmd.MarkPersistentFlagRequired("script")
41+
cmd.PersistentFlags().StringP("tag-prefix", "p", "tagged", "prefix to be added to tags")
42+
cmd.PersistentFlags().StringP("interval", "i", "60s", "interval to run the script")
43+
cmd.PersistentFlags().StringP("token", "t", "", "consul token")
44+
45+
// Add the cleanup command
46+
testCleanupCmd := &cobra.Command{
47+
Use: "cleanup",
48+
Short: "cleanup removes all services with the tag prefix",
49+
Run: cleanupCmd.Run,
50+
}
51+
cmd.AddCommand(testCleanupCmd)
52+
53+
// Capture stderr
54+
var buf bytes.Buffer
55+
cmd.SetErr(&buf)
56+
cmd.SetArgs(tt.args)
57+
58+
err := cmd.Execute()
59+
60+
if tt.expectError {
61+
assert.Error(t, err)
62+
if tt.errorContains != "" {
63+
output := buf.String()
64+
assert.Contains(t, output, tt.errorContains)
65+
}
66+
} else {
67+
assert.NoError(t, err)
68+
}
69+
})
70+
}
71+
}
72+
73+
func TestCleanupCmdFlagParsing(t *testing.T) {
74+
var capturedFlags map[string]string
75+
76+
cmd := &cobra.Command{Use: "tagit"}
77+
cmd.PersistentFlags().StringP("consul-addr", "c", "127.0.0.1:8500", "consul address")
78+
cmd.PersistentFlags().StringP("service-id", "s", "", "consul service id")
79+
cmd.PersistentFlags().StringP("script", "x", "", "path to script used to generate tags")
80+
cmd.PersistentFlags().StringP("tag-prefix", "p", "tagged", "prefix to be added to tags")
81+
cmd.PersistentFlags().StringP("token", "t", "", "consul token")
82+
83+
testCleanupCmd := &cobra.Command{
84+
Use: "cleanup",
85+
Short: "cleanup removes all services with the tag prefix",
86+
Run: func(cmd *cobra.Command, args []string) {
87+
// Capture flag values during execution
88+
capturedFlags = make(map[string]string)
89+
capturedFlags["service-id"], _ = cmd.InheritedFlags().GetString("service-id")
90+
capturedFlags["tag-prefix"], _ = cmd.InheritedFlags().GetString("tag-prefix")
91+
capturedFlags["consul-addr"], _ = cmd.InheritedFlags().GetString("consul-addr")
92+
capturedFlags["token"], _ = cmd.InheritedFlags().GetString("token")
93+
},
94+
}
95+
cmd.AddCommand(testCleanupCmd)
96+
97+
cmd.SetArgs([]string{
98+
"cleanup",
99+
"--service-id=test-service",
100+
"--script=/tmp/test.sh", // Required by root command
101+
"--tag-prefix=test",
102+
"--consul-addr=localhost:8500",
103+
"--token=test-token",
104+
})
105+
106+
err := cmd.Execute()
107+
assert.NoError(t, err)
108+
109+
// Verify flags were parsed correctly
110+
assert.Equal(t, "test-service", capturedFlags["service-id"])
111+
assert.Equal(t, "test", capturedFlags["tag-prefix"])
112+
assert.Equal(t, "localhost:8500", capturedFlags["consul-addr"])
113+
assert.Equal(t, "test-token", capturedFlags["token"])
114+
}
115+
116+
func TestCleanupCmdHelp(t *testing.T) {
117+
cmd := &cobra.Command{Use: "tagit"}
118+
cmd.PersistentFlags().StringP("consul-addr", "c", "127.0.0.1:8500", "consul address")
119+
cmd.PersistentFlags().StringP("service-id", "s", "", "consul service id")
120+
cmd.PersistentFlags().StringP("script", "x", "", "path to script used to generate tags")
121+
cmd.PersistentFlags().StringP("tag-prefix", "p", "tagged", "prefix to be added to tags")
122+
cmd.PersistentFlags().StringP("token", "t", "", "consul token")
123+
124+
testCleanupCmd := &cobra.Command{
125+
Use: "cleanup",
126+
Short: "cleanup removes all services with the tag prefix from a given consul service",
127+
Run: cleanupCmd.Run,
128+
}
129+
cmd.AddCommand(testCleanupCmd)
130+
131+
buf := new(bytes.Buffer)
132+
cmd.SetOut(buf)
133+
cmd.SetArgs([]string{"cleanup", "--help"})
134+
135+
err := cmd.Execute()
136+
assert.NoError(t, err)
137+
138+
output := buf.String()
139+
assert.Contains(t, output, "cleanup removes all services with the tag prefix")
140+
assert.Contains(t, output, "Usage:")
141+
}

cmd/root_test.go

Lines changed: 206 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,206 @@
1+
package cmd
2+
3+
import (
4+
"bytes"
5+
"os"
6+
"path/filepath"
7+
"testing"
8+
9+
"github.com/spf13/cobra"
10+
"github.com/spf13/viper"
11+
"github.com/stretchr/testify/assert"
12+
)
13+
14+
func TestExecute(t *testing.T) {
15+
// Save original args
16+
originalArgs := os.Args
17+
defer func() { os.Args = originalArgs }()
18+
19+
tests := []struct {
20+
name string
21+
args []string
22+
expectError bool
23+
}{
24+
{
25+
name: "Help command",
26+
args: []string{"--help"},
27+
expectError: false,
28+
},
29+
{
30+
name: "Unknown subcommand",
31+
args: []string{"invalid-command"},
32+
expectError: false, // Unknown subcommands just show help, don't error
33+
},
34+
}
35+
36+
for _, tt := range tests {
37+
t.Run(tt.name, func(t *testing.T) {
38+
// Create a test version of the root command to avoid affecting global state
39+
testRootCmd := &cobra.Command{
40+
Use: "tagit",
41+
Short: "Update consul services with dynamic tags coming from a script",
42+
}
43+
testRootCmd.PersistentFlags().StringP("consul-addr", "c", "127.0.0.1:8500", "consul address")
44+
testRootCmd.PersistentFlags().StringP("service-id", "s", "", "consul service id")
45+
testRootCmd.PersistentFlags().StringP("script", "x", "", "path to script used to generate tags")
46+
testRootCmd.PersistentFlags().StringP("tag-prefix", "p", "tagged", "prefix to be added to tags")
47+
testRootCmd.PersistentFlags().StringP("interval", "i", "60s", "interval to run the script")
48+
testRootCmd.PersistentFlags().StringP("token", "t", "", "consul token")
49+
50+
var buf bytes.Buffer
51+
testRootCmd.SetOut(&buf)
52+
testRootCmd.SetErr(&buf)
53+
testRootCmd.SetArgs(tt.args)
54+
55+
err := testRootCmd.Execute()
56+
57+
if tt.expectError {
58+
assert.Error(t, err)
59+
} else {
60+
assert.NoError(t, err)
61+
}
62+
})
63+
}
64+
}
65+
66+
func TestInitConfig(t *testing.T) {
67+
// Save original environment
68+
originalHome := os.Getenv("HOME")
69+
defer func() {
70+
if originalHome != "" {
71+
os.Setenv("HOME", originalHome)
72+
} else {
73+
os.Unsetenv("HOME")
74+
}
75+
}()
76+
77+
tests := []struct {
78+
name string
79+
setupConfig func() (string, func()) // Returns config file path and cleanup function
80+
expectError bool
81+
expectedVals map[string]string
82+
}{
83+
{
84+
name: "No config file",
85+
setupConfig: func() (string, func()) {
86+
// Create a temporary home directory
87+
tempDir, err := os.MkdirTemp("", "tagit-test-home")
88+
if err != nil {
89+
t.Fatalf("Failed to create temp dir: %v", err)
90+
}
91+
os.Setenv("HOME", tempDir)
92+
return "", func() { os.RemoveAll(tempDir) }
93+
},
94+
expectError: false,
95+
},
96+
{
97+
name: "Valid config file",
98+
setupConfig: func() (string, func()) {
99+
// Create a temporary home directory
100+
tempDir, err := os.MkdirTemp("", "tagit-test-home")
101+
if err != nil {
102+
t.Fatalf("Failed to create temp dir: %v", err)
103+
}
104+
os.Setenv("HOME", tempDir)
105+
106+
// Create a config file
107+
configPath := filepath.Join(tempDir, ".tagit.yaml")
108+
configContent := `consul-addr: "localhost:8500"
109+
service-id: "test-service"
110+
script: "/tmp/test.sh"
111+
tag-prefix: "test"
112+
interval: "30s"
113+
token: "test-token"
114+
`
115+
err = os.WriteFile(configPath, []byte(configContent), 0644)
116+
if err != nil {
117+
t.Fatalf("Failed to create config file: %v", err)
118+
}
119+
120+
return configPath, func() { os.RemoveAll(tempDir) }
121+
},
122+
expectError: false,
123+
expectedVals: map[string]string{
124+
"consul-addr": "localhost:8500",
125+
"service-id": "test-service",
126+
"script": "/tmp/test.sh",
127+
"tag-prefix": "test",
128+
"interval": "30s",
129+
"token": "test-token",
130+
},
131+
},
132+
}
133+
134+
for _, tt := range tests {
135+
t.Run(tt.name, func(t *testing.T) {
136+
// Reset viper for each test
137+
viper.Reset()
138+
139+
configPath, cleanup := tt.setupConfig()
140+
defer cleanup()
141+
142+
// Set config file if provided
143+
if configPath != "" {
144+
viper.SetConfigFile(configPath)
145+
}
146+
147+
// Call initConfig
148+
initConfig()
149+
150+
// Verify expected values
151+
for key, expectedVal := range tt.expectedVals {
152+
actualVal := viper.GetString(key)
153+
assert.Equal(t, expectedVal, actualVal, "Config value for %q should be %q but got %q", key, expectedVal, actualVal)
154+
}
155+
})
156+
}
157+
}
158+
159+
func TestRootCmdFlags(t *testing.T) {
160+
// Test that all expected flags are defined
161+
expectedFlags := []struct {
162+
name string
163+
shorthand string
164+
defaultValue string
165+
required bool
166+
}{
167+
{"consul-addr", "c", "127.0.0.1:8500", false},
168+
{"service-id", "s", "", true},
169+
{"script", "x", "", true},
170+
{"tag-prefix", "p", "tagged", false},
171+
{"interval", "i", "60s", false},
172+
{"token", "t", "", false},
173+
}
174+
175+
for _, flag := range expectedFlags {
176+
t.Run(flag.name, func(t *testing.T) {
177+
f := rootCmd.PersistentFlags().Lookup(flag.name)
178+
assert.NotNil(t, f, "Flag %q should be defined", flag.name)
179+
180+
if f != nil {
181+
assert.Equal(t, flag.shorthand, f.Shorthand, "Flag %q shorthand should be %q", flag.name, flag.shorthand)
182+
assert.Equal(t, flag.defaultValue, f.DefValue, "Flag %q default value should be %q", flag.name, flag.defaultValue)
183+
}
184+
})
185+
}
186+
}
187+
188+
func TestRootCmdHelp(t *testing.T) {
189+
var buf bytes.Buffer
190+
rootCmd.SetOut(&buf)
191+
rootCmd.SetArgs([]string{"--help"})
192+
193+
err := rootCmd.Execute()
194+
assert.NoError(t, err)
195+
196+
output := buf.String()
197+
assert.Contains(t, output, "Update consul services with dynamic tags")
198+
assert.Contains(t, output, "Usage:")
199+
assert.Contains(t, output, "Available Commands:")
200+
assert.Contains(t, output, "Flags:")
201+
202+
// Check that our subcommands are listed
203+
assert.Contains(t, output, "cleanup")
204+
assert.Contains(t, output, "run")
205+
assert.Contains(t, output, "systemd")
206+
}

0 commit comments

Comments
 (0)