1package executor
2
3import (
4 "context"
5 "os"
6 "path/filepath"
7 "testing"
8
9 "github.com/bnema/archup/internal/domain/ports/mocks"
10 "go.uber.org/mock/gomock"
11)
12
13func TestScriptExecutor_NewScriptExecutor(t *testing.T) {
14 ctrl := gomock.NewController(t)
15 defer ctrl.Finish()
16 mockFS := mocks.NewMockFileSystem(ctrl)
17 mockCmdExec := mocks.NewMockCommandExecutor(ctrl)
18
19 executor := NewScriptExecutor(mockFS, mockCmdExec, "/test/scripts")
20 if executor == nil {
21 t.Fatal("expected non-nil executor")
22 }
23}
24
25func TestScriptExecutor_ExecuteScript_Success(t *testing.T) {
26 ctrl := gomock.NewController(t)
27 defer ctrl.Finish()
28 mockFS := mocks.NewMockFileSystem(ctrl)
29 mockCmdExec := mocks.NewMockCommandExecutor(ctrl)
30
31 executor := NewScriptExecutor(mockFS, mockCmdExec, "/test/scripts")
32 tmpDir := t.TempDir()
33
34 // Create a simple test script
35 scriptPath := filepath.Join(tmpDir, "test.sh")
36 scriptContent := "#!/bin/bash\nexit 0"
37 if err := os.WriteFile(scriptPath, []byte(scriptContent), 0755); err != nil {
38 t.Fatalf("failed to create test script: %v", err)
39 }
40
41 ctx := context.Background()
42 err := executor.ExecuteScript(ctx, scriptPath, nil)
43 if err != nil {
44 t.Fatalf("expected no error, got %v", err)
45 }
46}
47
48func TestScriptExecutor_ExecuteScript_NotFound(t *testing.T) {
49 ctrl := gomock.NewController(t)
50 defer ctrl.Finish()
51 mockFS := mocks.NewMockFileSystem(ctrl)
52 mockCmdExec := mocks.NewMockCommandExecutor(ctrl)
53
54 executor := NewScriptExecutor(mockFS, mockCmdExec, "/test/scripts")
55 ctx := context.Background()
56
57 err := executor.ExecuteScript(ctx, "/nonexistent/script.sh", nil)
58 if err == nil {
59 t.Fatal("expected error for nonexistent script")
60 }
61}
62
63func TestScriptExecutor_ExecuteScript_Failure(t *testing.T) {
64 ctrl := gomock.NewController(t)
65 defer ctrl.Finish()
66 mockFS := mocks.NewMockFileSystem(ctrl)
67 mockCmdExec := mocks.NewMockCommandExecutor(ctrl)
68
69 executor := NewScriptExecutor(mockFS, mockCmdExec, "/test/scripts")
70 tmpDir := t.TempDir()
71
72 // Create a script that fails
73 scriptPath := filepath.Join(tmpDir, "fail.sh")
74 scriptContent := "#!/bin/bash\nexit 1"
75 if err := os.WriteFile(scriptPath, []byte(scriptContent), 0755); err != nil {
76 t.Fatalf("failed to create test script: %v", err)
77 }
78
79 ctx := context.Background()
80 err := executor.ExecuteScript(ctx, scriptPath, nil)
81 if err == nil {
82 t.Fatal("expected error for failed script")
83 }
84}
85
86func TestScriptExecutor_ExecuteScript_WithEnv(t *testing.T) {
87 ctrl := gomock.NewController(t)
88 defer ctrl.Finish()
89 mockFS := mocks.NewMockFileSystem(ctrl)
90 mockCmdExec := mocks.NewMockCommandExecutor(ctrl)
91
92 executor := NewScriptExecutor(mockFS, mockCmdExec, "/test/scripts")
93 tmpDir := t.TempDir()
94
95 // Create a script that uses environment variables
96 scriptPath := filepath.Join(tmpDir, "env.sh")
97 scriptContent := "#!/bin/bash\ntest \"$TEST_VAR\" = \"test_value\" || exit 1"
98 if err := os.WriteFile(scriptPath, []byte(scriptContent), 0755); err != nil {
99 t.Fatalf("failed to create test script: %v", err)
100 }
101
102 ctx := context.Background()
103 env := map[string]string{
104 "TEST_VAR": "test_value",
105 }
106
107 err := executor.ExecuteScript(ctx, scriptPath, env)
108 if err != nil {
109 t.Fatalf("expected no error, got %v", err)
110 }
111}
112
113func TestScriptExecutor_ExecuteScript_WithMultipleEnv(t *testing.T) {
114 ctrl := gomock.NewController(t)
115 defer ctrl.Finish()
116 mockFS := mocks.NewMockFileSystem(ctrl)
117 mockCmdExec := mocks.NewMockCommandExecutor(ctrl)
118
119 executor := NewScriptExecutor(mockFS, mockCmdExec, "/test/scripts")
120 tmpDir := t.TempDir()
121
122 // Create a script that checks multiple environment variables
123 scriptPath := filepath.Join(tmpDir, "multienv.sh")
124 scriptContent := "#!/bin/bash\ntest \"$VAR1\" = \"value1\" && test \"$VAR2\" = \"value2\" || exit 1"
125 if err := os.WriteFile(scriptPath, []byte(scriptContent), 0755); err != nil {
126 t.Fatalf("failed to create test script: %v", err)
127 }
128
129 ctx := context.Background()
130 env := map[string]string{
131 "VAR1": "value1",
132 "VAR2": "value2",
133 }
134
135 err := executor.ExecuteScript(ctx, scriptPath, env)
136 if err != nil {
137 t.Fatalf("expected no error, got %v", err)
138 }
139}
140
141func TestScriptExecutor_ExecuteScript_Stderr(t *testing.T) {
142 ctrl := gomock.NewController(t)
143 defer ctrl.Finish()
144 mockFS := mocks.NewMockFileSystem(ctrl)
145 mockCmdExec := mocks.NewMockCommandExecutor(ctrl)
146
147 executor := NewScriptExecutor(mockFS, mockCmdExec, "/test/scripts")
148 tmpDir := t.TempDir()
149
150 // Create a script that writes to stderr
151 scriptPath := filepath.Join(tmpDir, "stderr.sh")
152 scriptContent := "#!/bin/bash\necho error >&2\nexit 1"
153 if err := os.WriteFile(scriptPath, []byte(scriptContent), 0755); err != nil {
154 t.Fatalf("failed to create test script: %v", err)
155 }
156
157 ctx := context.Background()
158 err := executor.ExecuteScript(ctx, scriptPath, nil)
159 if err == nil {
160 t.Fatal("expected error")
161 }
162
163 // Verify stderr is captured in error message
164 if err != nil && err.Error() == "" {
165 t.Error("expected error message to contain stderr")
166 }
167}
168
169func TestScriptExecutor_ExecuteScript_ContextCancellation(t *testing.T) {
170 ctrl := gomock.NewController(t)
171 defer ctrl.Finish()
172 mockFS := mocks.NewMockFileSystem(ctrl)
173 mockCmdExec := mocks.NewMockCommandExecutor(ctrl)
174
175 executor := NewScriptExecutor(mockFS, mockCmdExec, "/test/scripts")
176 tmpDir := t.TempDir()
177
178 // Create a script that sleeps
179 scriptPath := filepath.Join(tmpDir, "sleep.sh")
180 scriptContent := "#!/bin/bash\nsleep 10"
181 if err := os.WriteFile(scriptPath, []byte(scriptContent), 0755); err != nil {
182 t.Fatalf("failed to create test script: %v", err)
183 }
184
185 ctx, cancel := context.WithCancel(context.Background())
186 cancel() // Cancel immediately
187
188 err := executor.ExecuteScript(ctx, scriptPath, nil)
189 if err == nil {
190 t.Fatal("expected error due to context cancellation")
191 }
192}