github.com/creativeprojects/go-selfupdate@v1.2.0/decompress_test.go (about)

     1  package selfupdate
     2  
     3  import (
     4  	"bytes"
     5  	"io"
     6  	"os"
     7  	"path/filepath"
     8  	"runtime"
     9  	"strings"
    10  	"testing"
    11  
    12  	"github.com/stretchr/testify/assert"
    13  	"github.com/stretchr/testify/require"
    14  )
    15  
    16  func TestCompressionNotRequired(t *testing.T) {
    17  	buf := []byte{'a', 'b', 'c'}
    18  	want := bytes.NewReader(buf)
    19  	r, err := DecompressCommand(want, "https://github.com/foo/bar/releases/download/v1.2.3/foo", "foo", runtime.GOOS, runtime.GOOS)
    20  	require.NoError(t, err)
    21  
    22  	have, err := io.ReadAll(r)
    23  	require.NoError(t, err)
    24  	assert.Equal(t, buf, have)
    25  }
    26  
    27  func getArchiveFileExt(file string) string {
    28  	if strings.HasSuffix(file, ".tar.gz") {
    29  		return ".tar.gz"
    30  	}
    31  	if strings.HasSuffix(file, ".tar.xz") {
    32  		return ".tar.xz"
    33  	}
    34  	return filepath.Ext(file)
    35  }
    36  
    37  func TestDecompress(t *testing.T) {
    38  	for _, testCase := range []string{
    39  		"testdata/foo.zip",
    40  		"testdata/single-file.zip",
    41  		"testdata/single-file.gz",
    42  		"testdata/single-file.gzip",
    43  		"testdata/foo.tar.gz",
    44  		"testdata/foo.tgz",
    45  		"testdata/foo.tar.xz",
    46  		"testdata/single-file.xz",
    47  		"testdata/single-file.bz2",
    48  	} {
    49  		t.Run(testCase, func(t *testing.T) {
    50  			f, err := os.Open(testCase)
    51  			require.NoError(t, err)
    52  
    53  			ext := getArchiveFileExt(testCase)
    54  			url := "https://github.com/foo/bar/releases/download/v1.2.3/bar" + ext
    55  			r, err := DecompressCommand(f, url, "bar", runtime.GOOS, runtime.GOOS)
    56  			require.NoError(t, err)
    57  
    58  			content, err := io.ReadAll(r)
    59  			require.NoError(t, err)
    60  
    61  			assert.Equal(t, "this is test\n", string(content), "Decompressing zip failed into unexpected content")
    62  		})
    63  	}
    64  }
    65  
    66  func TestDecompressInvalidArchive(t *testing.T) {
    67  	for _, testCase := range []struct {
    68  		name string
    69  		msg  string
    70  	}{
    71  		{"testdata/invalid.zip", "failed to decompress zip file"},
    72  		{"testdata/invalid.gz", "failed to decompress gzip file"},
    73  		{"testdata/invalid-tar.tar.gz", "failed to decompress tar file"},
    74  		{"testdata/invalid-gzip.tar.gz", "failed to decompress tar.gz file"},
    75  		{"testdata/invalid.xz", "failed to decompress xzip file"},
    76  		{"testdata/invalid-tar.tar.xz", "failed to decompress tar file"},
    77  		{"testdata/invalid-xz.tar.xz", "failed to decompress tar.xz file"},
    78  	} {
    79  		f, err := os.Open(testCase.name)
    80  		require.NoError(t, err)
    81  
    82  		ext := getArchiveFileExt(testCase.name)
    83  		url := "https://github.com/foo/bar/releases/download/v1.2.3/bar" + ext
    84  		_, err = DecompressCommand(f, url, "bar", runtime.GOOS, runtime.GOOS)
    85  		assert.ErrorIs(t, err, ErrCannotDecompressFile)
    86  		if !strings.Contains(err.Error(), testCase.msg) {
    87  			t.Fatal("Unexpected error:", err)
    88  		}
    89  	}
    90  }
    91  
    92  func TestTargetNotFound(t *testing.T) {
    93  	for _, testCase := range []struct {
    94  		name string
    95  		msg  string
    96  	}{
    97  		{"testdata/empty.zip", "not found"},
    98  		{"testdata/bar-not-found.zip", "not found"},
    99  		{"testdata/bar-not-found.gzip", "not found"},
   100  		{"testdata/empty.tar.gz", "not found"},
   101  		{"testdata/bar-not-found.tar.gz", "not found"},
   102  	} {
   103  		t.Run(testCase.name, func(t *testing.T) {
   104  			f, err := os.Open(testCase.name)
   105  			require.NoError(t, err)
   106  
   107  			ext := getArchiveFileExt(testCase.name)
   108  			url := "https://github.com/foo/bar/releases/download/v1.2.3/bar" + ext
   109  			_, err = DecompressCommand(f, url, "bar", runtime.GOOS, runtime.GOOS)
   110  			assert.ErrorIs(t, err, ErrExecutableNotFoundInArchive)
   111  		})
   112  	}
   113  }
   114  
   115  func TestMatchExecutableName(t *testing.T) {
   116  	testData := []struct {
   117  		cmd    string
   118  		os     string
   119  		arch   string
   120  		target string
   121  		found  bool
   122  	}{
   123  		// valid
   124  		{"gostuff", "linux", "amd64", "gostuff", true},
   125  		{"gostuff", "linux", "amd64", "gostuff_0.16.0", true},
   126  		{"gostuff", "linux", "amd64", "gostuff-0.16.0", true},
   127  		{"gostuff", "linux", "amd64", "gostuff_linux_amd64", true},
   128  		{"gostuff", "linux", "amd64", "gostuff-linux-amd64", true},
   129  		{"gostuff", "linux", "amd64", "gostuff_0.16.0_linux_amd64", true},
   130  		{"gostuff", "linux", "amd64", "gostuff-0.16.0-linux-amd64", true},
   131  		// invalid
   132  		{"gostuff", "linux", "amd64", "gostuff_darwin_amd64", false},
   133  		{"gostuff", "linux", "amd64", "gostuff0.16.0", false},
   134  		{"gostuff", "linux", "amd64", "gostuff_0.16.0_amd64", false},
   135  		{"gostuff", "linux", "amd64", "gostuff_0.16.0_linux", false},
   136  		// windows valid
   137  		{"gostuff", "windows", "amd64", "gostuff.exe", true},
   138  		{"gostuff", "windows", "amd64", "gostuff_0.16.0.exe", true},
   139  		{"gostuff", "windows", "amd64", "gostuff-0.16.0.exe", true},
   140  		{"gostuff", "windows", "amd64", "gostuff_windows_amd64.exe", true},
   141  		{"gostuff", "windows", "amd64", "gostuff-windows-amd64.exe", true},
   142  		{"gostuff", "windows", "amd64", "gostuff_0.16.0_windows_amd64.exe", true},
   143  		{"gostuff", "windows", "amd64", "gostuff-0.16.0-windows-amd64.exe", true},
   144  		// windows invalid
   145  		{"gostuff", "windows", "amd64", "gostuff_darwin_amd64.exe", false},
   146  		{"gostuff", "windows", "amd64", "gostuff0.16.0.exe", false},
   147  		{"gostuff", "windows", "amd64", "gostuff_0.16.0_amd64.exe", false},
   148  		{"gostuff", "windows", "amd64", "gostuff_0.16.0_windows.exe", false},
   149  	}
   150  
   151  	for _, testItem := range testData {
   152  		t.Run(testItem.target, func(t *testing.T) {
   153  			assert.Equal(t, testItem.found, matchExecutableName(testItem.cmd, testItem.os, testItem.arch, testItem.target))
   154  		})
   155  		// also try with .exe already in cmd for windows
   156  		if testItem.os == "windows" {
   157  			t.Run(testItem.target, func(t *testing.T) {
   158  				assert.Equal(t, testItem.found, matchExecutableName(testItem.cmd+".exe", testItem.os, testItem.arch, testItem.target))
   159  			})
   160  		}
   161  	}
   162  }
   163  
   164  func TestErrorFromReader(t *testing.T) {
   165  	extensions := []string{
   166  		"zip",
   167  		"tar.gz",
   168  		"tgz",
   169  		"gzip",
   170  		"gz",
   171  		"tar.xz",
   172  		"xz",
   173  		"bz2",
   174  	}
   175  
   176  	for _, extension := range extensions {
   177  		t.Run(extension, func(t *testing.T) {
   178  			reader, err := DecompressCommand(&bogusReader{}, "foo."+extension, "foo."+extension, runtime.GOOS, runtime.GOARCH)
   179  			if err != nil {
   180  				t.Log(err)
   181  				assert.ErrorIs(t, err, ErrCannotDecompressFile)
   182  			} else {
   183  				// bz2 does not return an error straight away: it only fails when you start reading from the output reader
   184  				_, err = io.ReadAll(reader)
   185  				t.Log(err)
   186  				assert.Error(t, err)
   187  			}
   188  		})
   189  	}
   190  }