1
1
package reexec
2
2
3
3
import (
4
+ "context"
5
+ "errors"
4
6
"fmt"
5
7
"os"
6
8
"os/exec"
7
9
"path/filepath"
8
10
"reflect"
9
11
"strings"
10
12
"testing"
13
+ "time"
11
14
)
12
15
13
16
const (
14
17
testReExec = "test-reexec"
15
18
testReExec2 = "test-reexec2"
19
+ testReExec3 = "test-reexec3"
16
20
)
17
21
18
22
func init () {
@@ -27,6 +31,11 @@ func init() {
27
31
fmt .Println ("Hello" , testReExec2 , args )
28
32
os .Exit (0 )
29
33
})
34
+ Register (testReExec3 , func () {
35
+ fmt .Println ("Hello " + testReExec3 )
36
+ time .Sleep (1 * time .Second )
37
+ os .Exit (0 )
38
+ })
30
39
Init ()
31
40
}
32
41
@@ -112,6 +121,86 @@ func TestCommand(t *testing.T) {
112
121
}
113
122
}
114
123
124
+ func TestCommandContext (t * testing.T ) {
125
+ tests := []struct {
126
+ doc string
127
+ cmdAndArgs []string
128
+ cancel bool
129
+ expOut string
130
+ expError string
131
+ }{
132
+ {
133
+ doc : "basename" ,
134
+ cmdAndArgs : []string {testReExec2 },
135
+ expOut : "Hello test-reexec2" ,
136
+ },
137
+ {
138
+ doc : "full path" ,
139
+ cmdAndArgs : []string {filepath .Join ("something" , testReExec2 )},
140
+ expOut : "Hello test-reexec2" ,
141
+ },
142
+ {
143
+ doc : "command with args" ,
144
+ cmdAndArgs : []string {testReExec2 , "--some-flag" , "some-value" , "arg1" , "arg2" },
145
+ expOut : `Hello test-reexec2 (args: []string{"--some-flag", "some-value", "arg1", "arg2"})` ,
146
+ },
147
+ {
148
+ doc : "context canceled" ,
149
+ cancel : true ,
150
+ cmdAndArgs : []string {testReExec2 },
151
+ expError : context .Canceled .Error (),
152
+ },
153
+ {
154
+ doc : "context timeout" ,
155
+ cmdAndArgs : []string {testReExec3 },
156
+ expOut : "Hello test-reexec3" ,
157
+ expError : "signal: killed" ,
158
+ },
159
+ }
160
+
161
+ for _ , tc := range tests {
162
+ t .Run (tc .doc , func (t * testing.T ) {
163
+ ctx , cancel := context .WithTimeout (context .Background (), 100 * time .Millisecond )
164
+ defer cancel ()
165
+
166
+ cmd := CommandContext (ctx , tc .cmdAndArgs ... )
167
+ if ! reflect .DeepEqual (cmd .Args , tc .cmdAndArgs ) {
168
+ t .Fatalf ("got %+v, want %+v" , cmd .Args , tc .cmdAndArgs )
169
+ }
170
+
171
+ w , err := cmd .StdinPipe ()
172
+ if err != nil {
173
+ t .Fatalf ("Error on pipe creation: %v" , err )
174
+ }
175
+ defer func () { _ = w .Close () }()
176
+ if tc .cancel {
177
+ cancel ()
178
+ }
179
+ out , err := cmd .CombinedOutput ()
180
+ if tc .cancel {
181
+ if ! errors .Is (err , context .Canceled ) {
182
+ t .Errorf ("got %[1]v (%[1]T), want %v" , err , context .Canceled )
183
+ }
184
+ }
185
+ if tc .expError != "" {
186
+ if err == nil {
187
+ t .Errorf ("expected error, got nil" )
188
+ }
189
+ if err .Error () != tc .expError {
190
+ t .Errorf ("got %q, want %q" , err .Error (), tc .expError )
191
+ }
192
+ } else if err != nil {
193
+ t .Errorf ("error on re-exec cmd: %v, out: %v" , err , string (out ))
194
+ }
195
+
196
+ actual := strings .TrimSpace (string (out ))
197
+ if actual != tc .expOut {
198
+ t .Errorf ("got %v, want %v" , actual , tc .expOut )
199
+ }
200
+ })
201
+ }
202
+ }
203
+
115
204
func TestNaiveSelf (t * testing.T ) {
116
205
if os .Getenv ("TEST_CHECK" ) == "1" {
117
206
os .Exit (2 )
0 commit comments