Skip to content

Commit d8ffe5a

Browse files
committed
test: uninstall flow tests
1 parent 1889d72 commit d8ffe5a

File tree

9 files changed

+200
-7
lines changed

9 files changed

+200
-7
lines changed

cmd/agent_smith/config_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ func newConfigTestFS() *mockFileSystem {
3030
readFileFunc: func(string) ([]byte, error) { return []byte("binary"), nil },
3131
writeFileFunc: func(string, []byte, os.FileMode) error { return nil },
3232
mkdirAllFunc: func(string) error { return nil },
33+
removeAllFunc: func(string) error { return nil },
3334
}
3435
}
3536

cmd/agent_smith/main.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ func main() {
4242
fs := utils.NewFileSystem()
4343
svcMgr := service.NewServiceManager()
4444

45-
uninstallContext, err := newUninstallContext(os.Args[1:], svcMgr)
45+
uninstallContext, err := newUninstallContext(os.Args[1:], svcMgr, fs)
4646
if err == nil {
4747
// Run uninstall routine
4848
runUninstall(uninstallContext)

cmd/agent_smith/main_test.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ type mockFileSystem struct {
7272
readFileFunc func(name string) ([]byte, error)
7373
writeFileFunc func(name string, data []byte, perm os.FileMode) error
7474
mkdirAllFunc func(path string) error
75+
removeAllFunc func(path string) error
7576
}
7677

7778
func (m *mockFileSystem) Executable() (string, error) {
@@ -90,6 +91,10 @@ func (m *mockFileSystem) MkdirAll(path string) error {
9091
return m.mkdirAllFunc(path)
9192
}
9293

94+
func (m *mockFileSystem) RemoveAll(path string) error {
95+
return m.removeAllFunc(path)
96+
}
97+
9398
type mockService struct {
9499
isActive bool
95100
stopErr error

cmd/agent_smith/uninstall.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ func runUninstall(params *uninstallContext) {
5252

5353
// Delete data directory
5454
dataDir := agent.GetDataDirectory(params.OrgId)
55-
err = os.RemoveAll(dataDir)
55+
err = params.FS.RemoveAll(dataDir)
5656
if err != nil {
5757
logger.Error("Failed to delete directory", "directory", dataDir, "error", err)
5858
return
@@ -61,7 +61,7 @@ func runUninstall(params *uninstallContext) {
6161

6262
// Delete program directory
6363
programDir := agent.GetProgramDirectory(params.OrgId)
64-
err = os.RemoveAll(programDir)
64+
err = params.FS.RemoveAll(programDir)
6565
if err != nil {
6666
logger.Error("Failed to delete directory", "directory", programDir, "error", err)
6767
return
@@ -70,7 +70,7 @@ func runUninstall(params *uninstallContext) {
7070

7171
// Delete scripts directory
7272
scriptsDir := agent.GetScriptsDirectory(params.OrgId)
73-
err = os.RemoveAll(scriptsDir)
73+
err = params.FS.RemoveAll(scriptsDir)
7474
if err != nil {
7575
logger.Error("Failed to delete directory", "directory", scriptsDir, "error", err)
7676
return

cmd/agent_smith/uninstall_context.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,18 @@ import (
66
"fmt"
77

88
"github.com/RewstApp/agent-smith-go/internal/service"
9+
"github.com/RewstApp/agent-smith-go/internal/utils"
910
)
1011

1112
type uninstallContext struct {
1213
OrgId string
1314
Uninstall bool
1415

1516
ServiceManager service.ServiceManager
17+
FS utils.FileSystem
1618
}
1719

18-
func newUninstallContext(args []string, svcMgr service.ServiceManager) (*uninstallContext, error) {
20+
func newUninstallContext(args []string, svcMgr service.ServiceManager, fsys utils.FileSystem) (*uninstallContext, error) {
1921
var params uninstallContext
2022

2123
fs := flag.NewFlagSet("uninstall", flag.ContinueOnError)
@@ -37,6 +39,7 @@ func newUninstallContext(args []string, svcMgr service.ServiceManager) (*uninsta
3739
}
3840

3941
params.ServiceManager = svcMgr
42+
params.FS = fsys
4043

4144
return &params, nil
4245
}

cmd/agent_smith/uninstall_context_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import (
77

88
func TestNewUninstallContext(t *testing.T) {
99
orgId := "test123"
10-
result, _ := newUninstallContext([]string{"--org-id", orgId, "--uninstall"}, nil)
10+
result, _ := newUninstallContext([]string{"--org-id", orgId, "--uninstall"}, nil, nil)
1111

1212
if result.OrgId != orgId {
1313
t.Errorf("expected %v, got %v", orgId, result.OrgId)
@@ -27,7 +27,7 @@ func TestNewUninstallContext(t *testing.T) {
2727
}
2828

2929
for _, errorTest := range errorTests {
30-
_, err := newUninstallContext(errorTest.args, nil)
30+
_, err := newUninstallContext(errorTest.args, nil, nil)
3131

3232
if err == nil || !strings.Contains(err.Error(), errorTest.message) {
3333
t.Errorf("expected error %s, got %v", errorTest.message, err.Error())

cmd/agent_smith/uninstall_test.go

Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
package main
2+
3+
import (
4+
"errors"
5+
"testing"
6+
)
7+
8+
func newUninstallTestFS() *mockFileSystem {
9+
return &mockFileSystem{
10+
removeAllFunc: func(string) error { return nil },
11+
}
12+
}
13+
14+
// ── early-exit tests (no sleep) ───────────────────────────────────────────────
15+
16+
func TestRunUninstall_OpenFails(t *testing.T) {
17+
params := &uninstallContext{
18+
OrgId: "test-org",
19+
ServiceManager: &mockServiceManager{
20+
openErr: errors.New("service not found"),
21+
},
22+
FS: newUninstallTestFS(),
23+
}
24+
25+
runUninstall(params)
26+
}
27+
28+
func TestRunUninstall_StopFails(t *testing.T) {
29+
params := &uninstallContext{
30+
OrgId: "test-org",
31+
ServiceManager: &mockServiceManager{
32+
openService: &mockService{isActive: true, stopErr: errors.New("stop failed")},
33+
},
34+
FS: newUninstallTestFS(),
35+
}
36+
37+
runUninstall(params)
38+
}
39+
40+
func TestRunUninstall_ActiveService_DeleteFails(t *testing.T) {
41+
params := &uninstallContext{
42+
OrgId: "test-org",
43+
ServiceManager: &mockServiceManager{
44+
openService: &mockService{isActive: true, deleteErr: errors.New("delete failed")},
45+
},
46+
FS: newUninstallTestFS(),
47+
}
48+
49+
runUninstall(params)
50+
}
51+
52+
func TestRunUninstall_InactiveService_DeleteFails(t *testing.T) {
53+
params := &uninstallContext{
54+
OrgId: "test-org",
55+
ServiceManager: &mockServiceManager{
56+
openService: &mockService{isActive: false, deleteErr: errors.New("delete failed")},
57+
},
58+
FS: newUninstallTestFS(),
59+
}
60+
61+
runUninstall(params)
62+
}
63+
64+
// ── post-delete tests (run in parallel to share the serviceExecutableTimeout delay) ──
65+
66+
func TestRunUninstall_RemoveAllDataDirFails(t *testing.T) {
67+
t.Parallel()
68+
69+
params := &uninstallContext{
70+
OrgId: "test-org",
71+
ServiceManager: &mockServiceManager{
72+
openService: &mockService{isActive: false},
73+
},
74+
FS: &mockFileSystem{
75+
removeAllFunc: func(string) error { return errors.New("remove failed") },
76+
},
77+
}
78+
79+
runUninstall(params)
80+
}
81+
82+
func TestRunUninstall_RemoveAllProgramDirFails(t *testing.T) {
83+
t.Parallel()
84+
85+
call := 0
86+
params := &uninstallContext{
87+
OrgId: "test-org",
88+
ServiceManager: &mockServiceManager{
89+
openService: &mockService{isActive: false},
90+
},
91+
FS: &mockFileSystem{
92+
removeAllFunc: func(string) error {
93+
call++
94+
if call == 2 {
95+
return errors.New("remove failed")
96+
}
97+
return nil
98+
},
99+
},
100+
}
101+
102+
runUninstall(params)
103+
}
104+
105+
func TestRunUninstall_RemoveAllScriptsDirFails(t *testing.T) {
106+
t.Parallel()
107+
108+
call := 0
109+
params := &uninstallContext{
110+
OrgId: "test-org",
111+
ServiceManager: &mockServiceManager{
112+
openService: &mockService{isActive: false},
113+
},
114+
FS: &mockFileSystem{
115+
removeAllFunc: func(string) error {
116+
call++
117+
if call == 3 {
118+
return errors.New("remove failed")
119+
}
120+
return nil
121+
},
122+
},
123+
}
124+
125+
runUninstall(params)
126+
}
127+
128+
func TestRunUninstall_Success(t *testing.T) {
129+
t.Parallel()
130+
131+
params := &uninstallContext{
132+
OrgId: "test-org",
133+
ServiceManager: &mockServiceManager{
134+
openService: &mockService{isActive: false},
135+
},
136+
FS: newUninstallTestFS(),
137+
}
138+
139+
runUninstall(params)
140+
}
141+
142+
func TestRunUninstall_ActiveService_Success(t *testing.T) {
143+
t.Parallel()
144+
145+
params := &uninstallContext{
146+
OrgId: "test-org",
147+
ServiceManager: &mockServiceManager{
148+
openService: &mockService{isActive: true},
149+
},
150+
FS: newUninstallTestFS(),
151+
}
152+
153+
runUninstall(params)
154+
}

internal/utils/filesystem.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ type FileSystem interface {
1313
ReadFile(name string) ([]byte, error)
1414
WriteFile(name string, data []byte, perm os.FileMode) error
1515
MkdirAll(path string) error
16+
RemoveAll(path string) error
1617
}
1718

1819
type defaultFileSystem struct{}
@@ -33,6 +34,10 @@ func (*defaultFileSystem) MkdirAll(path string) error {
3334
return os.MkdirAll(path, DefaultDirMod)
3435
}
3536

37+
func (*defaultFileSystem) RemoveAll(path string) error {
38+
return os.RemoveAll(path)
39+
}
40+
3641
func NewFileSystem() FileSystem {
3742
return &defaultFileSystem{}
3843
}

internal/utils/filesystem_test.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,31 @@ func TestDefaultFileSystem_ReadFile(t *testing.T) {
8888
}
8989
}
9090

91+
func TestDefaultFileSystem_RemoveAll(t *testing.T) {
92+
fs := NewFileSystem()
93+
dir := filepath.Join(t.TempDir(), "to_remove")
94+
95+
if err := os.MkdirAll(dir, 0755); err != nil {
96+
t.Fatal(err)
97+
}
98+
99+
err := fs.RemoveAll(dir)
100+
101+
if err != nil {
102+
t.Fatalf("expected no error, got %v", err)
103+
}
104+
if _, statErr := os.Stat(dir); !os.IsNotExist(statErr) {
105+
t.Errorf("expected directory %s to be removed", dir)
106+
}
107+
108+
// Calling RemoveAll on a non-existent path must also succeed.
109+
err = fs.RemoveAll(dir)
110+
111+
if err != nil {
112+
t.Fatalf("expected no error on non-existent path, got %v", err)
113+
}
114+
}
115+
91116
func TestDefaultFileSystem_ReadFile_NotFound(t *testing.T) {
92117
fs := NewFileSystem()
93118

0 commit comments

Comments
 (0)