@@ -195,14 +195,11 @@ type file struct {
195
195
body []byte
196
196
}
197
197
198
- func createVsix (manifest * storage.VSIXManifest ) ([]byte , error ) {
199
- manifestBytes , err := xml .Marshal (manifest )
200
- if err != nil {
201
- return nil , err
202
- }
203
-
198
+ // createVSIX returns the bytes for a VSIX file containing the provided manifest
199
+ // and an icon.
200
+ func createVSIX (manifestBytes []byte ) ([]byte , error ) {
204
201
files := []file {{"icon.png" , []byte ("fake icon" )}}
205
- if manifest != nil {
202
+ if manifestBytes != nil {
206
203
files = append (files , file {"extension.vsixmanifest" , manifestBytes })
207
204
}
208
205
@@ -223,6 +220,8 @@ func createVsix(manifest *storage.VSIXManifest) ([]byte, error) {
223
220
return buf .Bytes (), nil
224
221
}
225
222
223
+ // requireExtension verifies an extension exists in the extension directory and
224
+ // that the received output matches the expected path.
226
225
func requireExtension (t * testing.T , ext testutil.Extension , extdir string , got string ) {
227
226
expected := filepath .Join (extdir , ext .Publisher , ext .Name , ext .LatestVersion )
228
227
require .Equal (t , expected , got )
@@ -238,85 +237,192 @@ func requireExtension(t *testing.T, ext testutil.Extension, extdir string, got s
238
237
func TestAddExtension (t * testing.T ) {
239
238
t .Parallel ()
240
239
241
- t .Run ("HTTPOK" , func (t * testing.T ) {
242
- t .Parallel ()
243
-
244
- ext := testutil .Extensions [0 ]
245
- vsix , err := createVsix (testutil .ConvertExtensionToManifest (ext , ext .LatestVersion ))
246
- require .NoError (t , err )
247
-
248
- server := httptest .NewServer (http .HandlerFunc (func (rw http.ResponseWriter , r * http.Request ) {
249
- _ , err := rw .Write (vsix )
250
- require .NoError (t , err )
251
- }))
252
- defer server .Close ()
240
+ ext := testutil .Extensions [0 ]
241
+ manifestBytes , err := xml .Marshal (testutil .ConvertExtensionToManifest (ext , ext .LatestVersion ))
242
+ require .NoError (t , err )
243
+ vsix , err := createVSIX (manifestBytes )
244
+ require .NoError (t , err )
253
245
254
- extdir := t . TempDir ()
255
- s := & storage. Local { ExtDir : extdir }
246
+ t . Run ( "HTTP" , func ( t * testing. T ) {
247
+ t . Parallel ()
256
248
257
- got , err := s .AddExtension (context .Background (), server .URL )
258
- require .NoError (t , err )
259
- requireExtension (t , ext , extdir , got )
260
- })
249
+ tests := []struct {
250
+ error string
251
+ name string
252
+ handler http.HandlerFunc
253
+ setup func (extdir string ) (string , error )
254
+ }{
255
+ {
256
+ name : "OK" ,
257
+ },
258
+ {
259
+ name : "InternalError" ,
260
+ error : strconv .Itoa (http .StatusInternalServerError ),
261
+ handler : func (rw http.ResponseWriter , r * http.Request ) {
262
+ http .Error (rw , "something went wrong" , http .StatusInternalServerError )
263
+ },
264
+ },
265
+ {
266
+ name : "ReadError" ,
267
+ error : "unexpected EOF" ,
268
+ handler : func (rw http.ResponseWriter , r * http.Request ) {
269
+ rw .Header ().Set ("Content-Length" , "1" )
270
+ },
271
+ },
272
+ {
273
+ name : "InvalidZip" ,
274
+ error : "zip: not a valid zip file" ,
275
+ handler : func (rw http.ResponseWriter , r * http.Request ) {
276
+ _ , err := rw .Write ([]byte {})
277
+ require .NoError (t , err )
278
+ },
279
+ },
280
+ {
281
+ name : "ExtensionDirPerms" ,
282
+ error : "permission denied" ,
283
+ setup : func (extdir string ) (string , error ) {
284
+ // Disallow writing to the extension directory.
285
+ extdir = filepath .Join (extdir , "no-write" )
286
+ return extdir , os .MkdirAll (extdir , 0o444 )
287
+ },
288
+ },
289
+ {
290
+ name : "CopyOverDirectory" ,
291
+ error : "is a directory" ,
292
+ setup : func (extdir string ) (string , error ) {
293
+ // Put a directory in the way of the vsix.
294
+ vsixName := fmt .Sprintf ("%s.%s-%s.vsix" , ext .Publisher , ext .Name , ext .LatestVersion )
295
+ vsixPath := filepath .Join (extdir , ext .Publisher , ext .Name , ext .LatestVersion , vsixName )
296
+ return extdir , os .MkdirAll (vsixPath , 0o755 )
297
+ },
298
+ },
299
+ }
261
300
262
- t .Run ("HTTPError" , func (t * testing.T ) {
263
- t .Parallel ()
301
+ for _ , test := range tests {
302
+ test := test
303
+ t .Run (test .name , func (t * testing.T ) {
304
+ t .Parallel ()
264
305
265
- server := httptest .NewServer (http .HandlerFunc (func (rw http.ResponseWriter , r * http.Request ) {
266
- http .Error (rw , "something went wrong" , http .StatusInternalServerError )
267
- }))
268
- defer server .Close ()
306
+ handler := test .handler
307
+ if handler == nil {
308
+ handler = func (rw http.ResponseWriter , r * http.Request ) {
309
+ _ , err := rw .Write (vsix )
310
+ require .NoError (t , err )
311
+ }
312
+ }
269
313
270
- s := & storage.Local {ExtDir : t .TempDir ()}
314
+ server := httptest .NewServer (http .HandlerFunc (handler ))
315
+ defer server .Close ()
271
316
272
- _ , err := s .AddExtension (context .Background (), server .URL )
273
- require .Error (t , err )
317
+ extdir := t .TempDir ()
318
+ if test .setup != nil {
319
+ extdir , err = test .setup (extdir )
320
+ require .NoError (t , err )
321
+ }
322
+ s := & storage.Local {ExtDir : extdir }
274
323
275
- // The error should mention the status code.
276
- require .Contains (t , err .Error (), strconv .Itoa (http .StatusInternalServerError ))
324
+ got , err := s .AddExtension (context .Background (), server .URL )
325
+ if test .error != "" {
326
+ require .Error (t , err )
327
+ require .Regexp (t , test .error , err .Error ())
328
+ } else {
329
+ requireExtension (t , ext , extdir , got )
330
+ }
331
+ })
332
+ }
277
333
})
278
334
279
- t .Run ("FileOK " , func (t * testing.T ) {
335
+ t .Run ("File " , func (t * testing.T ) {
280
336
t .Parallel ()
281
337
282
- ext := testutil .Extensions [0 ]
283
- vsix , err := createVsix (testutil .ConvertExtensionToManifest (ext , ext .LatestVersion ))
284
- require .NoError (t , err )
285
-
286
- extdir := t .TempDir ()
287
- vsixPath := filepath .Join (extdir , "extension.vsix" )
288
- err = os .WriteFile (vsixPath , vsix , 0o644 )
289
- require .NoError (t , err )
338
+ tests := []struct {
339
+ error string
340
+ name string
341
+ source func (extdir string ) (string , error )
342
+ }{
343
+ {
344
+ name : "OK" ,
345
+ source : func (extdir string ) (string , error ) {
346
+ vsixPath := filepath .Join (extdir , "extension.vsix" )
347
+ return vsixPath , os .WriteFile (vsixPath , vsix , 0o644 )
348
+ },
349
+ },
350
+ {
351
+ name : "NotFound" ,
352
+ error : "foo\\ .vsix.+no such file" ,
353
+ source : func (extdir string ) (string , error ) {
354
+ return filepath .Join (extdir , "foo.vsix" ), nil
355
+ },
356
+ },
357
+ {
358
+ name : "EmptyFile" ,
359
+ error : "zip: not a valid zip file" ,
360
+ source : func (extdir string ) (string , error ) {
361
+ vsixPath := filepath .Join (extdir , "foo.vsix" )
362
+ return vsixPath , os .WriteFile (vsixPath , []byte {}, 0o644 )
363
+ },
364
+ },
365
+ {
366
+ name : "Unreadable" ,
367
+ error : "permission denied" ,
368
+ source : func (extdir string ) (string , error ) {
369
+ vsixPath := filepath .Join (extdir , "extension.vsix" )
370
+ return vsixPath , os .WriteFile (vsixPath , []byte {}, 0o222 )
371
+ },
372
+ },
373
+ }
290
374
291
- s := & storage.Local {ExtDir : extdir }
375
+ for _ , test := range tests {
376
+ test := test
377
+ t .Run (test .name , func (t * testing.T ) {
378
+ t .Parallel ()
292
379
293
- got , err := s .AddExtension (context .Background (), vsixPath )
294
- require .NoError (t , err )
295
- requireExtension (t , ext , extdir , got )
296
- })
380
+ extdir := t .TempDir ()
381
+ s := & storage.Local {ExtDir : extdir }
297
382
298
- t . Run ( "FileError" , func ( t * testing. T ) {
299
- t . Parallel ( )
383
+ source , err := test . source ( extdir )
384
+ require . NoError ( t , err )
300
385
301
- extdir := t .TempDir ()
302
- s := & storage.Local {ExtDir : extdir }
303
- _ , err := s .AddExtension (context .Background (), filepath .Join (extdir , "foo.vsix" ))
304
- require .Error (t , err )
386
+ got , err := s .AddExtension (context .Background (), source )
387
+ if test .error != "" {
388
+ require .Error (t , err )
389
+ require .Regexp (t , test .error , err .Error ())
390
+ } else {
391
+ requireExtension (t , ext , extdir , got )
392
+ }
393
+ })
394
+ }
305
395
})
306
396
307
- t .Run ("InvalidManifest " , func (t * testing.T ) {
397
+ t .Run ("ValidateManifest " , func (t * testing.T ) {
308
398
t .Parallel ()
309
399
310
400
tests := []struct {
311
- error string
312
- manifest * storage.VSIXManifest
313
- name string
401
+ error string
402
+ manifest * storage.VSIXManifest
403
+ manifestBytes []byte
404
+ name string
314
405
}{
315
406
{
316
407
error : "not found" ,
317
408
name : "Missing" ,
318
409
manifest : nil ,
319
410
},
411
+ {
412
+ error : "EOF" ,
413
+ name : "Empty" ,
414
+ manifestBytes : []byte ("" ),
415
+ },
416
+ {
417
+ error : "EOF" ,
418
+ name : "TextFile" ,
419
+ manifestBytes : []byte ("just some random text" ),
420
+ },
421
+ {
422
+ error : "XML syntax error" ,
423
+ name : "SyntaxError" ,
424
+ manifestBytes : []byte ("<PackageManifest/PackageManifest>" ),
425
+ },
320
426
{
321
427
error : "publisher" ,
322
428
name : "MissingPublisher" ,
@@ -352,7 +458,12 @@ func TestAddExtension(t *testing.T) {
352
458
t .Run (test .name , func (t * testing.T ) {
353
459
t .Parallel ()
354
460
355
- vsix , err := createVsix (test .manifest )
461
+ manifestBytes := test .manifestBytes
462
+ if manifestBytes == nil {
463
+ manifestBytes , err = xml .Marshal (test .manifest )
464
+ require .NoError (t , err )
465
+ }
466
+ vsix , err := createVSIX (manifestBytes )
356
467
require .NoError (t , err )
357
468
358
469
extdir := t .TempDir ()
@@ -364,9 +475,7 @@ func TestAddExtension(t *testing.T) {
364
475
365
476
_ , err = s .AddExtension (context .Background (), vsixPath )
366
477
require .Error (t , err )
367
-
368
- // The error should mention what is wrong.
369
- require .Contains (t , err .Error (), test .error )
478
+ require .Regexp (t , test .error , err .Error ())
370
479
})
371
480
}
372
481
})
0 commit comments