@@ -53,13 +53,23 @@ func TestRepoFromTarballLink(t *testing.T) {
5353
5454func TestRepoFromTarballLinkErrors (t * testing.T ) {
5555 for _ , test := range []struct {
56+ name string
5657 tarballLink string
5758 }{
58- {tarballLink : "too-short" },
59+ {
60+ name : "URL path does not match prefix" ,
61+ tarballLink : "too-short" ,
62+ },
63+ {
64+ name : "URL path has only one component after prefix removal" ,
65+ tarballLink : testGitHubDn + "/org" ,
66+ },
5967 } {
60- if got , err := RepoFromTarballLink (testGitHubDn , test .tarballLink ); err == nil {
61- t .Errorf ("expected an error, got=%v" , got )
62- }
68+ t .Run (test .name , func (t * testing.T ) {
69+ if got , err := RepoFromTarballLink (testGitHubDn , test .tarballLink ); err == nil {
70+ t .Errorf ("expected an error, got=%v" , got )
71+ }
72+ })
6373 }
6474}
6575
@@ -380,3 +390,180 @@ func createTestTarball(t *testing.T, topLevelDir string, files map[string]string
380390 }
381391 return buf .Bytes ()
382392}
393+
394+ func TestExtractTarballErrors (t * testing.T ) {
395+ for _ , test := range []struct {
396+ name string
397+ tarballPath func (t * testing.T ) string // Function to create the test file
398+ dest func (t * testing.T ) string
399+ wantErr bool
400+ }{
401+ {
402+ name : "tarball does not exist" ,
403+ tarballPath : func (t * testing.T ) string {
404+ return "non-existent-file.tar.gz"
405+ },
406+ dest : func (t * testing.T ) string {
407+ return t .TempDir ()
408+ },
409+ wantErr : true ,
410+ },
411+ {
412+ name : "not a gzip file" ,
413+ tarballPath : func (t * testing.T ) string {
414+ p := path .Join (t .TempDir (), "file.txt" )
415+ if err := os .WriteFile (p , []byte ("not a tarball" ), 0644 ); err != nil {
416+ t .Fatal (err )
417+ }
418+ return p
419+ },
420+ dest : func (t * testing.T ) string {
421+ return t .TempDir ()
422+ },
423+ wantErr : true ,
424+ },
425+ {
426+ name : "gzipped but not a tar file" ,
427+ tarballPath : func (t * testing.T ) string {
428+ var buf bytes.Buffer
429+ gw := gzip .NewWriter (& buf )
430+ if _ , err := gw .Write ([]byte ("not a tar file" )); err != nil {
431+ t .Fatal (err )
432+ }
433+ if err := gw .Close (); err != nil {
434+ t .Fatal (err )
435+ }
436+ p := path .Join (t .TempDir (), "file.gz" )
437+ if err := os .WriteFile (p , buf .Bytes (), 0644 ); err != nil {
438+ t .Fatal (err )
439+ }
440+ return p
441+ },
442+ dest : func (t * testing.T ) string {
443+ return t .TempDir ()
444+ },
445+ wantErr : true ,
446+ },
447+ {
448+ name : "destination is a file" ,
449+ tarballPath : func (t * testing.T ) string {
450+ tarballData := createTestTarball (t , "repo-abc123" , map [string ]string {"file.txt" : "content" })
451+ p := path .Join (t .TempDir (), "test.tar.gz" )
452+ if err := os .WriteFile (p , tarballData , 0644 ); err != nil {
453+ t .Fatal (err )
454+ }
455+ return p
456+ },
457+ dest : func (t * testing.T ) string {
458+ p := path .Join (t .TempDir (), "destfile" )
459+ if err := os .WriteFile (p , []byte ("i am a file" ), 0644 ); err != nil {
460+ t .Fatal (err )
461+ }
462+ return p
463+ },
464+ wantErr : true ,
465+ },
466+ } {
467+ t .Run (test .name , func (t * testing.T ) {
468+ err := ExtractTarball (test .tarballPath (t ), test .dest (t ))
469+ if (err != nil ) != test .wantErr {
470+ t .Errorf ("ExtractTarball() error = %v, wantErr %v" , err , test .wantErr )
471+ }
472+ })
473+ }
474+ }
475+
476+ func TestDownloadTarballErrors (t * testing.T ) {
477+ for _ , test := range []struct {
478+ name string
479+ target func (t * testing.T ) string
480+ url func (t * testing.T ) string
481+ sha string
482+ wantErr bool
483+ }{
484+ {
485+ name : "http fails after 3 retries" ,
486+ target : func (t * testing.T ) string {
487+ return path .Join (t .TempDir (), "target" )
488+ },
489+ url : func (t * testing.T ) string {
490+ server := httptest .NewServer (http .HandlerFunc (func (w http.ResponseWriter , r * http.Request ) {
491+ w .WriteHeader (http .StatusInternalServerError )
492+ }))
493+ t .Cleanup (server .Close )
494+ return server .URL
495+ },
496+ sha : "any-sha" ,
497+ wantErr : true ,
498+ }, {
499+ name : "cannot create parent directory" ,
500+ target : func (t * testing.T ) string {
501+ // Create a read-only directory to trigger a permission error.
502+ readOnlyDir := path .Join (t .TempDir (), "read-only" )
503+ if err := os .Mkdir (readOnlyDir , 0555 ); err != nil { // Read and execute only
504+ t .Fatal (err )
505+ }
506+ t .Cleanup (func () {
507+ // Restore permissions so the temp dir can be cleaned up.
508+ os .Chmod (readOnlyDir , 0755 )
509+ })
510+ return path .Join (readOnlyDir , "subdir" , "target" )
511+ },
512+ url : func (t * testing.T ) string {
513+ return "https://any-url"
514+ },
515+ sha : "any-sha" ,
516+ wantErr : true ,
517+ },
518+ } {
519+ t .Run (test .name , func (t * testing.T ) {
520+ defaultBackoff = time .Millisecond
521+ t .Cleanup (func () {
522+ defaultBackoff = 10 * time .Second
523+ })
524+ err := DownloadTarball (context .Background (), test .target (t ), test .url (t ), test .sha )
525+ if (err != nil ) != test .wantErr {
526+ t .Errorf ("DownloadTarball() error = %v, wantErr %v" , err , test .wantErr )
527+ }
528+ })
529+ }
530+ }
531+
532+ func TestDownloadTarballRetry (t * testing.T ) {
533+ t .Run ("succeeds after a few retries" , func (t * testing.T ) {
534+ // Set a short backoff for this test to speed up retries.
535+ defaultBackoff = time .Millisecond
536+ t .Cleanup (func () {
537+ defaultBackoff = 10 * time .Second
538+ })
539+ testDir := t .TempDir ()
540+ tarball := makeTestContents (t )
541+ var requestCount int
542+ server := httptest .NewServer (http .HandlerFunc (func (w http.ResponseWriter , r * http.Request ) {
543+ requestCount ++
544+ if requestCount < 3 {
545+ w .WriteHeader (http .StatusInternalServerError )
546+ return
547+ }
548+ w .WriteHeader (http .StatusOK )
549+ w .Write (tarball .Contents )
550+ }))
551+ defer server .Close ()
552+
553+ target := path .Join (testDir , "target-file" )
554+ if err := DownloadTarball (t .Context (), target , server .URL + "/test.tar.gz" , tarball .Sha256 ); err != nil {
555+ t .Fatal (err )
556+ }
557+
558+ if requestCount != 3 {
559+ t .Errorf ("expected 3 requests, got %d" , requestCount )
560+ }
561+ got , err := os .ReadFile (target )
562+ if err != nil {
563+ t .Fatal (err )
564+ }
565+ if diff := cmp .Diff (tarball .Contents , got ); diff != "" {
566+ t .Errorf ("mismatch (-want +got):\n %s" , diff )
567+ }
568+ })
569+ }
0 commit comments