@@ -7,17 +7,18 @@ import (
7
7
"fmt"
8
8
"io/fs"
9
9
"io/ioutil"
10
- "net"
11
10
"net/http"
12
11
"os"
13
12
"path/filepath"
14
13
"runtime"
15
14
"strings"
16
15
"testing"
17
16
17
+ "cdr.dev/coder-cli/pkg/clog"
18
18
"cdr.dev/slog/sloggers/slogtest/assert"
19
19
"github.com/manifoldco/promptui"
20
20
"github.com/spf13/afero"
21
+ "golang.org/x/xerrors"
21
22
)
22
23
23
24
const (
@@ -34,7 +35,9 @@ const (
34
35
35
36
var (
36
37
apiPrivateVersionURL = fakeCoderURL + "/api/private/version"
38
+ fakeError = xerrors .New ("fake error for testing" )
37
39
fakeNewVersionJSON = fmt .Sprintf (`{"version":%q}` , fakeNewVersion )
40
+ fakeOldVersionJSON = fmt .Sprintf (`{"version":%q}` , fakeOldVersion )
38
41
)
39
42
40
43
func Test_updater_run (t * testing.T ) {
@@ -169,22 +172,22 @@ func Test_updater_run(t *testing.T) {
169
172
u := fromParams (p )
170
173
assertFileContent (t , p .Fakefs , fakeExePathLinux , fakeOldVersion )
171
174
err := u .Run (p .Ctx , false , fakeCoderURL )
172
- assert . ErrorContains (t , "update coder - user cancelled" , err , "failed to confirm update" )
175
+ assertCLIError (t , "update coder - user cancelled" , err , "failed to confirm update" , " " )
173
176
assertFileContent (t , p .Fakefs , fakeExePathLinux , fakeOldVersion )
174
177
})
175
178
176
179
run (t , "update coder - cannot stat" , func (t * testing.T , p * params ) {
177
180
u := fromParams (p )
178
181
err := u .Run (p .Ctx , false , fakeCoderURL )
179
- assert . ErrorContains (t , "update coder - cannot stat" , err , "cannot stat current binary" )
182
+ assertCLIError (t , "update coder - cannot stat" , err , "cannot stat current binary" , os . ErrNotExist . Error () )
180
183
})
181
184
182
185
run (t , "update coder - no permission" , func (t * testing.T , p * params ) {
183
186
fakeFile (t , p .Fakefs , fakeExePathLinux , 0400 , fakeOldVersion )
184
187
u := fromParams (p )
185
188
assertFileContent (t , p .Fakefs , fakeExePathLinux , fakeOldVersion )
186
189
err := u .Run (p .Ctx , false , fakeCoderURL )
187
- assert . ErrorContains (t , "update coder - no permission" , err , "missing write permission" )
190
+ assertCLIError (t , "update coder - no permission" , err , "missing write permission" , " " )
188
191
assertFileContent (t , p .Fakefs , fakeExePathLinux , fakeOldVersion )
189
192
})
190
193
@@ -194,31 +197,31 @@ func Test_updater_run(t *testing.T) {
194
197
u := fromParams (p )
195
198
assertFileContent (t , p .Fakefs , fakeExePathLinux , fakeOldVersion )
196
199
err := u .Run (p .Ctx , false , "h$$p://invalid.url" )
197
- assert . ErrorContains (t , "update coder - invalid url" , err , "invalid coder URL" )
200
+ assertCLIError (t , "update coder - invalid url" , err , "invalid coder URL" , "first path segment in URL cannot contain colon " )
198
201
assertFileContent (t , p .Fakefs , fakeExePathLinux , fakeOldVersion )
199
202
})
200
203
201
204
run (t , "update coder - fetch api version failure" , func (t * testing.T , p * params ) {
202
205
fakeFile (t , p .Fakefs , fakeExePathLinux , 0755 , fakeOldVersion )
203
- p .HTTPClient .M [apiPrivateVersionURL ] = newFakeGetterResponse ([]byte {}, 401 , variadicS (), net . ErrClosed )
206
+ p .HTTPClient .M [apiPrivateVersionURL ] = newFakeGetterResponse ([]byte {}, 401 , variadicS (), fakeError )
204
207
p .VersionF = func () string { return fakeOldVersion }
205
208
u := fromParams (p )
206
209
assertFileContent (t , p .Fakefs , fakeExePathLinux , fakeOldVersion )
207
210
err := u .Run (p .Ctx , false , fakeCoderURL )
208
- assert . ErrorContains (t , "update coder - fetch api version failure" , err , "fetch api version" )
211
+ assertCLIError (t , "update coder - fetch api version failure" , err , "fetch api version" , fakeError . Error () )
209
212
assertFileContent (t , p .Fakefs , fakeExePathLinux , fakeOldVersion )
210
213
})
211
214
212
215
run (t , "update coder - failed to fetch URL" , func (t * testing.T , p * params ) {
213
216
fakeFile (t , p .Fakefs , fakeExePathLinux , 0755 , fakeOldVersion )
214
217
p .HTTPClient .M [apiPrivateVersionURL ] = newFakeGetterResponse ([]byte (fakeNewVersionJSON ), 200 , variadicS (), nil )
215
- p .HTTPClient .M [fakeReleaseURLLinux ] = newFakeGetterResponse ([]byte {}, 0 , variadicS (), net . ErrClosed )
218
+ p .HTTPClient .M [fakeReleaseURLLinux ] = newFakeGetterResponse ([]byte {}, 0 , variadicS (), fakeError )
216
219
p .VersionF = func () string { return fakeOldVersion }
217
220
p .ConfirmF = fakeConfirmYes
218
221
u := fromParams (p )
219
222
assertFileContent (t , p .Fakefs , fakeExePathLinux , fakeOldVersion )
220
223
err := u .Run (p .Ctx , false , fakeCoderURL )
221
- assert . ErrorContains (t , "update coder - release URL 404 " , err , "failed to fetch URL" )
224
+ assertCLIError (t , "update coder - failed to fetch URL " , err , "failed to fetch URL" , fakeError . Error () )
222
225
assertFileContent (t , p .Fakefs , fakeExePathLinux , fakeOldVersion )
223
226
})
224
227
@@ -231,7 +234,7 @@ func Test_updater_run(t *testing.T) {
231
234
u := fromParams (p )
232
235
assertFileContent (t , p .Fakefs , fakeExePathLinux , fakeOldVersion )
233
236
err := u .Run (p .Ctx , false , fakeCoderURL )
234
- assert . ErrorContains (t , "update coder - release URL 404" , err , "failed to fetch release" )
237
+ assertCLIError (t , "update coder - release URL 404" , err , "failed to fetch release" , "status code 404 " )
235
238
assertFileContent (t , p .Fakefs , fakeExePathLinux , fakeOldVersion )
236
239
})
237
240
@@ -244,7 +247,7 @@ func Test_updater_run(t *testing.T) {
244
247
u := fromParams (p )
245
248
assertFileContent (t , p .Fakefs , fakeExePathLinux , fakeOldVersion )
246
249
err := u .Run (p .Ctx , false , fakeCoderURL )
247
- assert . ErrorContains (t , "update coder - invalid archive" , err , "failed to extract coder binary from archive" )
250
+ assertCLIError (t , "update coder - invalid tgz archive" , err , "failed to extract coder binary from archive" , "unknown archive type " )
248
251
assertFileContent (t , p .Fakefs , fakeExePathLinux , fakeOldVersion )
249
252
})
250
253
@@ -259,7 +262,7 @@ func Test_updater_run(t *testing.T) {
259
262
u := fromParams (p )
260
263
assertFileContent (t , p .Fakefs , p .ExecutablePath , fakeOldVersion )
261
264
err := u .Run (p .Ctx , false , fakeCoderURL )
262
- assert . ErrorContains (t , "update coder - invalid archive" , err , "failed to extract coder binary from archive" )
265
+ assertCLIError (t , "update coder - invalid zip archive" , err , "failed to extract coder binary from archive" , "unknown archive type " )
263
266
assertFileContent (t , p .Fakefs , p .ExecutablePath , fakeOldVersion )
264
267
})
265
268
@@ -274,7 +277,7 @@ func Test_updater_run(t *testing.T) {
274
277
u := fromParams (p )
275
278
assertFileContent (t , p .Fakefs , fakeExePathLinux , fakeOldVersion )
276
279
err := u .Run (p .Ctx , false , fakeCoderURL )
277
- assert . ErrorContains (t , "update coder - read-only fs" , err , "failed to create file" )
280
+ assertCLIError (t , "update coder - read-only fs" , err , "failed to create file" , " " )
278
281
assertFileContent (t , p .Fakefs , fakeExePathLinux , fakeOldVersion )
279
282
})
280
283
@@ -283,35 +286,35 @@ func Test_updater_run(t *testing.T) {
283
286
p .ExecutablePath = `C:\Windows\system32\coder.exe`
284
287
u := fromParams (p )
285
288
err := u .Run (p .Ctx , false , fakeCoderURL )
286
- assert . ErrorContains (t , "update coder - path blocklist - windows" , err , "cowardly refusing to update coder binary" )
289
+ assertCLIError (t , "update coder - path blocklist - windows" , err , "cowardly refusing to update coder binary" , "blocklisted prefix " )
287
290
})
288
291
} else {
289
292
run (t , "update coder - path blocklist - coder assets dir" , func (t * testing.T , p * params ) {
290
293
p .ExecutablePath = `/var/tmp/coder/coder`
291
294
u := fromParams (p )
292
295
err := u .Run (p .Ctx , false , fakeCoderURL )
293
- assert . ErrorContains (t , "update coder - path blocklist - windows" , err , "cowardly refusing to update coder binary" )
296
+ assertCLIError (t , "update coder - path blocklist - windows" , err , "cowardly refusing to update coder binary" , "blocklisted prefix " )
294
297
})
295
298
run (t , "update coder - path blocklist - old homebrew prefix" , func (t * testing.T , p * params ) {
296
299
p .Execer .M ["brew --prefix" ] = fakeExecerResult {[]byte ("/usr/local" ), nil }
297
300
p .ExecutablePath = `/usr/local/bin/coder`
298
301
u := fromParams (p )
299
302
err := u .Run (p .Ctx , false , fakeCoderURL )
300
- assert . ErrorContains (t , "update coder - path blocklist - old homebrew prefix" , err , "cowardly refusing to update coder binary" )
303
+ assertCLIError (t , "update coder - path blocklist - old homebrew prefix" , err , "cowardly refusing to update coder binary" , "blocklisted prefix " )
301
304
})
302
305
run (t , "update coder - path blocklist - new homebrew prefix" , func (t * testing.T , p * params ) {
303
306
p .Execer .M ["brew --prefix" ] = fakeExecerResult {[]byte ("/opt/homebrew" ), nil }
304
307
p .ExecutablePath = `/opt/homebrew/bin/coder`
305
308
u := fromParams (p )
306
309
err := u .Run (p .Ctx , false , fakeCoderURL )
307
- assert . ErrorContains (t , "update coder - path blocklist - new homebrew prefix" , err , "cowardly refusing to update coder binary" )
310
+ assertCLIError (t , "update coder - path blocklist - new homebrew prefix" , err , "cowardly refusing to update coder binary" , "blocklisted prefix " )
308
311
})
309
312
run (t , "update coder - path blocklist - linuxbrew" , func (t * testing.T , p * params ) {
310
313
p .Execer .M ["brew --prefix" ] = fakeExecerResult {[]byte ("/home/user/.linuxbrew" ), nil }
311
314
p .ExecutablePath = `/home/user/.linuxbrew/bin/coder`
312
315
u := fromParams (p )
313
316
err := u .Run (p .Ctx , false , fakeCoderURL )
314
- assert . ErrorContains (t , "update coder - path blocklist - linuxbrew" , err , "cowardly refusing to update coder binary" )
317
+ assertCLIError (t , "update coder - path blocklist - linuxbrew" , err , "cowardly refusing to update coder binary" , "blocklisted prefix " )
315
318
})
316
319
}
317
320
}
@@ -408,6 +411,27 @@ func assertFileContent(t *testing.T, fs afero.Fs, name string, content string) {
408
411
assert .Equal (t , "assert content equal" , content , string (b ))
409
412
}
410
413
414
+ func assertCLIError (t * testing.T , name string , err error , expectedHeader , expectedLines string ) {
415
+ t .Helper ()
416
+ cliError , ok := err .(clog.CLIError )
417
+ if ! ok {
418
+ t .Errorf ("%s: assert cli error: %+v is not a cli error" , name , err )
419
+ }
420
+
421
+ if ! strings .Contains (err .Error (), expectedHeader ) {
422
+ t .Errorf ("%s: assert cli error: expected header %q to contain %q" , name , err .Error (), expectedHeader )
423
+ }
424
+
425
+ if expectedLines == "" {
426
+ return
427
+ }
428
+
429
+ fullLines := strings .Join (cliError .Lines , "\n " )
430
+ if ! strings .Contains (fullLines , expectedLines ) {
431
+ t .Errorf ("%s: assert cli error: expected %q to contain %q" , name , fullLines , expectedLines )
432
+ }
433
+ }
434
+
411
435
// this is a valid tgz archive containing a single file named 'coder' with permissions 0751
412
436
// containing the string "1.23.4-rc.5+678-gabcdef-12345678".
413
437
var fakeValidTgzBytes , _ = base64 .StdEncoding .DecodeString (`H4sIAAAAAAAAA+3QsQ4CIRCEYR6F3oC7wIqvc3KnpQnq+3tGCwsTK3LN/zWTTDWZuG/XeeluJFlV
0 commit comments