github.com/weiwenhao/getter@v1.30.1/decompress_testing.go (about)

     1  package getter
     2  
     3  import (
     4  	"crypto/md5"
     5  	"encoding/hex"
     6  	"io"
     7  	"io/ioutil"
     8  	"os"
     9  	"path/filepath"
    10  	"reflect"
    11  	"runtime"
    12  	"sort"
    13  	"strings"
    14  	"time"
    15  
    16  	"github.com/mitchellh/go-testing-interface"
    17  )
    18  
    19  // TestDecompressCase is a single test case for testing decompressors
    20  type TestDecompressCase struct {
    21  	Input   string     // Input is the complete path to the input file
    22  	Dir     bool       // Dir is whether or not we're testing directory mode
    23  	Err     bool       // Err is whether we expect an error or not
    24  	DirList []string   // DirList is the list of files for Dir mode
    25  	FileMD5 string     // FileMD5 is the expected MD5 for a single file
    26  	Mtime   *time.Time // Mtime is the optionally expected mtime for a single file (or all files if in Dir mode)
    27  }
    28  
    29  // TestDecompressor is a helper function for testing generic decompressors.
    30  func TestDecompressor(t testing.T, d Decompressor, cases []TestDecompressCase) {
    31  	t.Helper()
    32  
    33  	for _, tc := range cases {
    34  		t.Logf("Testing: %s", tc.Input)
    35  
    36  		// Temporary dir to store stuff
    37  		td, err := ioutil.TempDir("", "getter")
    38  		if err != nil {
    39  			t.Fatalf("err: %s", err)
    40  		}
    41  
    42  		// Destination is always joining result so that we have a new path
    43  		dst := filepath.Join(td, "subdir", "result")
    44  
    45  		// We use a function so defers work
    46  		func() {
    47  			defer os.RemoveAll(td)
    48  
    49  			// Decompress
    50  			err := d.Decompress(dst, tc.Input, tc.Dir, 0022)
    51  			if (err != nil) != tc.Err {
    52  				t.Fatalf("err %s: %s", tc.Input, err)
    53  			}
    54  			if tc.Err {
    55  				return
    56  			}
    57  
    58  			// If it isn't a directory, then check for a single file
    59  			if !tc.Dir {
    60  				fi, err := os.Stat(dst)
    61  				if err != nil {
    62  					t.Fatalf("err %s: %s", tc.Input, err)
    63  				}
    64  				if fi.IsDir() {
    65  					t.Fatalf("err %s: expected file, got directory", tc.Input)
    66  				}
    67  				if tc.FileMD5 != "" {
    68  					actual := testMD5(t, dst)
    69  					expected := tc.FileMD5
    70  					if actual != expected {
    71  						t.Fatalf("err %s: expected MD5 %s, got %s", tc.Input, expected, actual)
    72  					}
    73  				}
    74  
    75  				if tc.Mtime != nil {
    76  					actual := fi.ModTime()
    77  					if tc.Mtime.Unix() > 0 {
    78  						expected := *tc.Mtime
    79  						if actual != expected {
    80  							t.Fatalf("err %s: expected mtime '%s' for %s, got '%s'", tc.Input, expected.String(), dst, actual.String())
    81  						}
    82  					} else if actual.Unix() <= 0 {
    83  						t.Fatalf("err %s: expected mtime to be > 0, got '%s'", actual.String())
    84  					}
    85  				}
    86  
    87  				return
    88  			}
    89  
    90  			// Convert expected for windows
    91  			expected := tc.DirList
    92  			if runtime.GOOS == "windows" {
    93  				for i, v := range expected {
    94  					expected[i] = strings.Replace(v, "/", "\\", -1)
    95  				}
    96  			}
    97  
    98  			// Directory, check for the correct contents
    99  			actual := testListDir(t, dst)
   100  			if !reflect.DeepEqual(actual, expected) {
   101  				t.Fatalf("bad %s\n\n%#v\n\n%#v", tc.Input, actual, expected)
   102  			}
   103  			// Check for correct atime/mtime
   104  			for _, dir := range actual {
   105  				path := filepath.Join(dst, dir)
   106  				if tc.Mtime != nil {
   107  					fi, err := os.Stat(path)
   108  					if err != nil {
   109  						t.Fatalf("err: %s", err)
   110  					}
   111  					actual := fi.ModTime()
   112  					if tc.Mtime.Unix() > 0 {
   113  						expected := *tc.Mtime
   114  						if actual != expected {
   115  							t.Fatalf("err %s: expected mtime '%s' for %s, got '%s'", tc.Input, expected.String(), path, actual.String())
   116  						}
   117  					} else if actual.Unix() < 0 {
   118  						t.Fatalf("err %s: expected mtime to be > 0, got '%s'", actual.String())
   119  					}
   120  
   121  				}
   122  			}
   123  		}()
   124  	}
   125  }
   126  
   127  func testListDir(t testing.T, path string) []string {
   128  	var result []string
   129  	err := filepath.Walk(path, func(sub string, info os.FileInfo, err error) error {
   130  		if err != nil {
   131  			return err
   132  		}
   133  
   134  		sub = strings.TrimPrefix(sub, path)
   135  		if sub == "" {
   136  			return nil
   137  		}
   138  		sub = sub[1:] // Trim the leading path sep.
   139  
   140  		// If it is a dir, add trailing sep
   141  		if info.IsDir() {
   142  			sub += string(os.PathSeparator)
   143  		}
   144  
   145  		result = append(result, sub)
   146  		return nil
   147  	})
   148  	if err != nil {
   149  		t.Fatalf("err: %s", err)
   150  	}
   151  
   152  	sort.Strings(result)
   153  	return result
   154  }
   155  
   156  func testMD5(t testing.T, path string) string {
   157  	f, err := os.Open(path)
   158  	if err != nil {
   159  		t.Fatalf("err: %s", err)
   160  	}
   161  	defer f.Close()
   162  
   163  	h := md5.New()
   164  	_, err = io.Copy(h, f)
   165  	if err != nil {
   166  		t.Fatalf("err: %s", err)
   167  	}
   168  
   169  	result := h.Sum(nil)
   170  	return hex.EncodeToString(result)
   171  }