1
1
package cliplugins
2
2
3
3
import (
4
- "bytes "
4
+ "errors "
5
5
"io"
6
6
"os/exec"
7
7
"strings"
@@ -11,6 +11,7 @@ import (
11
11
12
12
"github.com/creack/pty"
13
13
"gotest.tools/v3/assert"
14
+ is "gotest.tools/v3/assert/cmp"
14
15
)
15
16
16
17
// TestPluginSocketBackwardsCompatible executes a plugin binary
@@ -37,15 +38,15 @@ func TestPluginSocketBackwardsCompatible(t *testing.T) {
37
38
err := syscall .Kill (- command .Process .Pid , syscall .SIGINT )
38
39
assert .NilError (t , err , "failed to signal process group" )
39
40
}()
40
- bytes , err := io .ReadAll (ptmx )
41
+ out , err := io .ReadAll (ptmx )
41
42
if err != nil && ! strings .Contains (err .Error (), "input/output error" ) {
42
43
t .Fatal ("failed to get command output" )
43
44
}
44
45
45
46
// the plugin is attached to the TTY, so the parent process
46
47
// ignores the received signal, and the plugin receives a SIGINT
47
48
// as well
48
- assert .Equal (t , string (bytes ), "received SIGINT\r \n exit after 3 seconds\r \n " )
49
+ assert .Equal (t , string (out ), "received SIGINT\r \n exit after 3 seconds\r \n " )
49
50
})
50
51
51
52
// ensure that we don't break plugins that attempt to read from the TTY
@@ -95,13 +96,13 @@ func TestPluginSocketBackwardsCompatible(t *testing.T) {
95
96
err := syscall .Kill (command .Process .Pid , syscall .SIGINT )
96
97
assert .NilError (t , err , "failed to signal process group" )
97
98
}()
98
- bytes , err := command .CombinedOutput ()
99
- t .Log ("command output: " + string (bytes ))
99
+ out , err := command .CombinedOutput ()
100
+ t .Log ("command output: " + string (out ))
100
101
assert .NilError (t , err , "failed to run command" )
101
102
102
103
// the plugin process does not receive a SIGINT
103
104
// so it exits after 3 seconds and prints this message
104
- assert .Equal (t , string (bytes ), "exit after 3 seconds\n " )
105
+ assert .Equal (t , string (out ), "exit after 3 seconds\n " )
105
106
})
106
107
107
108
t .Run ("the main CLI exits after 3 signals" , func (t * testing.T ) {
@@ -130,13 +131,18 @@ func TestPluginSocketBackwardsCompatible(t *testing.T) {
130
131
err = syscall .Kill (command .Process .Pid , syscall .SIGINT )
131
132
assert .NilError (t , err , "failed to signal process group" )
132
133
}()
133
- bytes , err := command .CombinedOutput ()
134
- assert .ErrorContains (t , err , "exit status 1" )
134
+ out , err := command .CombinedOutput ()
135
+
136
+ var exitError * exec.ExitError
137
+ assert .Assert (t , errors .As (err , & exitError ))
138
+ assert .Check (t , exitError .Exited ())
139
+ assert .Check (t , is .Equal (exitError .ExitCode (), 1 ))
140
+ assert .Check (t , is .ErrorContains (err , "exit status 1" ))
135
141
136
142
// the plugin process does not receive a SIGINT and does
137
143
// the CLI cannot cancel it over the socket, so it kills
138
144
// the plugin process and forcefully exits
139
- assert .Equal (t , string (bytes ), "got 3 SIGTERM/SIGINTs, forcefully exiting\n " )
145
+ assert .Equal (t , string (out ), "got 3 SIGTERM/SIGINTs, forcefully exiting\n " )
140
146
})
141
147
})
142
148
}
@@ -161,25 +167,22 @@ func TestPluginSocketCommunication(t *testing.T) {
161
167
err := syscall .Kill (- command .Process .Pid , syscall .SIGINT )
162
168
assert .NilError (t , err , "failed to signal process group" )
163
169
}()
164
- bytes , err := io .ReadAll (ptmx )
170
+ out , err := io .ReadAll (ptmx )
165
171
if err != nil && ! strings .Contains (err .Error (), "input/output error" ) {
166
172
t .Fatal ("failed to get command output" )
167
173
}
168
174
169
175
// the plugin is attached to the TTY, so the parent process
170
176
// ignores the received signal, and the plugin receives a SIGINT
171
177
// as well
172
- assert .Equal (t , string (bytes ), "received SIGINT\r \n exit after 3 seconds\r \n " )
178
+ assert .Equal (t , string (out ), "received SIGINT\r \n exit after 3 seconds\r \n " )
173
179
})
174
180
})
175
181
176
182
t .Run ("detached" , func (t * testing.T ) {
177
183
t .Run ("the plugin does not get signalled" , func (t * testing.T ) {
178
184
cmd := run ("presocket" , "test-socket" )
179
185
command := exec .Command (cmd .Command [0 ], cmd .Command [1 :]... )
180
- outB := bytes.Buffer {}
181
- command .Stdout = & outB
182
- command .Stderr = & outB
183
186
command .SysProcAttr = & syscall.SysProcAttr {
184
187
Setpgid : true ,
185
188
}
@@ -190,13 +193,19 @@ func TestPluginSocketCommunication(t *testing.T) {
190
193
err := syscall .Kill (command .Process .Pid , syscall .SIGINT )
191
194
assert .NilError (t , err , "failed to signal CLI process" )
192
195
}()
193
- err := command .Run ()
194
- t .Log (outB .String ())
195
- assert .ErrorContains (t , err , "exit status 2" )
196
-
197
- // the plugin does not get signalled, but it does get it's
198
- // context cancelled by the CLI through the socket
199
- assert .Equal (t , outB .String (), "context cancelled\n " )
196
+ out , err := command .CombinedOutput ()
197
+
198
+ var exitError * exec.ExitError
199
+ assert .Assert (t , errors .As (err , & exitError ))
200
+ assert .Check (t , exitError .Exited ())
201
+ assert .Check (t , is .Equal (exitError .ExitCode (), 2 ))
202
+ assert .Check (t , is .ErrorContains (err , "exit status 2" ))
203
+
204
+ // the plugin does not get signalled, but it does get its
205
+ // context canceled by the CLI through the socket
206
+ const expected = "test-socket: exiting after context was done\n exit status 2"
207
+ actual := strings .TrimSpace (string (out ))
208
+ assert .Check (t , is .Equal (actual , expected ))
200
209
})
201
210
202
211
t .Run ("the main CLI exits after 3 signals" , func (t * testing.T ) {
@@ -223,13 +232,18 @@ func TestPluginSocketCommunication(t *testing.T) {
223
232
err = syscall .Kill (command .Process .Pid , syscall .SIGINT )
224
233
assert .NilError (t , err , "failed to signal CLI process§" )
225
234
}()
226
- bytes , err := command .CombinedOutput ()
227
- assert .ErrorContains (t , err , "exit status 1" )
235
+ out , err := command .CombinedOutput ()
236
+
237
+ var exitError * exec.ExitError
238
+ assert .Assert (t , errors .As (err , & exitError ))
239
+ assert .Check (t , exitError .Exited ())
240
+ assert .Check (t , is .Equal (exitError .ExitCode (), 1 ))
241
+ assert .Check (t , is .ErrorContains (err , "exit status 1" ))
228
242
229
243
// the plugin process does not receive a SIGINT and does
230
- // not exit after having it's context cancelled , so the CLI
244
+ // not exit after having it's context canceled , so the CLI
231
245
// kills the plugin process and forcefully exits
232
- assert .Equal (t , string (bytes ), "got 3 SIGTERM/SIGINTs, forcefully exiting\n " )
246
+ assert .Equal (t , string (out ), "got 3 SIGTERM/SIGINTs, forcefully exiting\n " )
233
247
})
234
248
})
235
249
}
0 commit comments