github.com/qxnw/lib4go@v0.0.0-20180426074627-c80c7e84b925/archiver/archiver_test.go (about)

     1  package archiver
     2  
     3  import (
     4  	"bytes"
     5  	"io/ioutil"
     6  	"os"
     7  	"path/filepath"
     8  	"testing"
     9  )
    10  
    11  func TestArchiver(t *testing.T) {
    12  	for name, ar := range SupportedFormats {
    13  		name, ar := name, ar
    14  		t.Run(name, func(t *testing.T) {
    15  			t.Parallel()
    16  			// skip RAR for now
    17  			if _, ok := ar.(rarFormat); ok {
    18  				t.Skip("not supported")
    19  			}
    20  			testWriteRead(t, name, ar)
    21  			testMakeOpen(t, name, ar)
    22  		})
    23  	}
    24  }
    25  
    26  // testWriteRead performs a symmetric test by using ar.Write to generate an archive
    27  // from the test corpus, then using ar.Read to extract the archive and comparing
    28  // the contents to ensure they are equal.
    29  func testWriteRead(t *testing.T, name string, ar Archiver) {
    30  	buf := new(bytes.Buffer)
    31  	tmp, err := ioutil.TempDir("", "archiver")
    32  	if err != nil {
    33  		t.Fatalf("[%s] %v", name, err)
    34  	}
    35  	defer os.RemoveAll(tmp)
    36  
    37  	// Test creating archive
    38  	err = ar.Write(buf, []string{"testdata"})
    39  	if err != nil {
    40  		t.Fatalf("[%s] writing archive: didn't expect an error, but got: %v", name, err)
    41  	}
    42  
    43  	// Test extracting archive
    44  	err = ar.Read(buf, tmp)
    45  	if err != nil {
    46  		t.Fatalf("[%s] reading archive: didn't expect an error, but got: %v", name, err)
    47  	}
    48  
    49  	// Check that what was extracted is what was compressed
    50  	symmetricTest(t, name, tmp)
    51  }
    52  
    53  // testMakeOpen performs a symmetric test by using ar.Make to make an archive
    54  // from the test corpus, then using ar.Open to open the archive and comparing
    55  // the contents to ensure they are equal.
    56  func testMakeOpen(t *testing.T, name string, ar Archiver) {
    57  	tmp, err := ioutil.TempDir("", "archiver")
    58  	if err != nil {
    59  		t.Fatalf("[%s] %v", name, err)
    60  	}
    61  	defer os.RemoveAll(tmp)
    62  
    63  	// Test creating archive
    64  	outfile := filepath.Join(tmp, "test-"+name)
    65  	err = ar.Make(outfile, []string{"testdata"})
    66  	if err != nil {
    67  		t.Fatalf("[%s] making archive: didn't expect an error, but got: %v", name, err)
    68  	}
    69  
    70  	if !ar.Match(outfile) {
    71  		t.Fatalf("[%s] identifying format should be 'true', but got 'false'", name)
    72  	}
    73  
    74  	// Test extracting archive
    75  	dest := filepath.Join(tmp, "extraction_test")
    76  	os.Mkdir(dest, 0755)
    77  	err = ar.Open(outfile, dest)
    78  	if err != nil {
    79  		t.Fatalf("[%s] extracting archive [%s -> %s]: didn't expect an error, but got: %v", name, outfile, dest, err)
    80  	}
    81  
    82  	// Check that what was extracted is what was compressed
    83  	symmetricTest(t, name, dest)
    84  }
    85  
    86  // symmetricTest compares the contents of a destination directory to the contents
    87  // of the test corpus and tests that they are equal.
    88  func symmetricTest(t *testing.T, name, dest string) {
    89  	var expectedFileCount int
    90  	filepath.Walk("testdata", func(fpath string, info os.FileInfo, err error) error {
    91  		expectedFileCount++
    92  		return nil
    93  	})
    94  
    95  	// If outputs equals inputs, we're good; traverse output files
    96  	// and compare file names, file contents, and file count.
    97  	var actualFileCount int
    98  	filepath.Walk(dest, func(fpath string, info os.FileInfo, err error) error {
    99  		if fpath == dest {
   100  			return nil
   101  		}
   102  		actualFileCount++
   103  
   104  		origPath, err := filepath.Rel(dest, fpath)
   105  		if err != nil {
   106  			t.Fatalf("[%s] %s: Error inducing original file path: %v", name, fpath, err)
   107  		}
   108  
   109  		if info.IsDir() {
   110  			// stat dir instead of read file
   111  			_, err = os.Stat(origPath)
   112  			if err != nil {
   113  				t.Fatalf("[%s] %s: Couldn't stat original directory (%s): %v", name,
   114  					fpath, origPath, err)
   115  			}
   116  			return nil
   117  		}
   118  
   119  		expectedFileInfo, err := os.Stat(origPath)
   120  		if err != nil {
   121  			t.Fatalf("[%s] %s: Error obtaining original file info: %v", name, fpath, err)
   122  		}
   123  		expected, err := ioutil.ReadFile(origPath)
   124  		if err != nil {
   125  			t.Fatalf("[%s] %s: Couldn't open original file (%s) from disk: %v", name,
   126  				fpath, origPath, err)
   127  		}
   128  
   129  		actualFileInfo, err := os.Stat(fpath)
   130  		if err != nil {
   131  			t.Fatalf("[%s] %s: Error obtaining actual file info: %v", name, fpath, err)
   132  		}
   133  		actual, err := ioutil.ReadFile(fpath)
   134  		if err != nil {
   135  			t.Fatalf("[%s] %s: Couldn't open new file from disk: %v", name, fpath, err)
   136  		}
   137  
   138  		if actualFileInfo.Mode() != expectedFileInfo.Mode() {
   139  			t.Fatalf("[%s] %s: File mode differed between on disk and compressed", name,
   140  				expectedFileInfo.Mode().String()+" : "+actualFileInfo.Mode().String())
   141  		}
   142  		if !bytes.Equal(expected, actual) {
   143  			t.Fatalf("[%s] %s: File contents differed between on disk and compressed", name, origPath)
   144  		}
   145  
   146  		return nil
   147  	})
   148  
   149  	if got, want := actualFileCount, expectedFileCount; got != want {
   150  		t.Fatalf("[%s] Expected %d resulting files, got %d", name, want, got)
   151  	}
   152  }
   153  
   154  func BenchmarkMake(b *testing.B) {
   155  	tmp, err := ioutil.TempDir("", "archiver")
   156  	if err != nil {
   157  		b.Fatal(err)
   158  	}
   159  	defer os.RemoveAll(tmp)
   160  
   161  	for name, ar := range SupportedFormats {
   162  		name, ar := name, ar
   163  		b.Run(name, func(b *testing.B) {
   164  			// skip RAR for now
   165  			if _, ok := ar.(rarFormat); ok {
   166  				b.Skip("not supported")
   167  			}
   168  			outfile := filepath.Join(tmp, "benchMake-"+name)
   169  			for i := 0; i < b.N; i++ {
   170  				err = ar.Make(outfile, []string{"testdata"})
   171  				if err != nil {
   172  					b.Fatalf("making archive: didn't expect an error, but got: %v", err)
   173  				}
   174  			}
   175  		})
   176  	}
   177  }
   178  
   179  func BenchmarkOpen(b *testing.B) {
   180  	tmp, err := ioutil.TempDir("", "archiver")
   181  	if err != nil {
   182  		b.Fatal(err)
   183  	}
   184  	defer os.RemoveAll(tmp)
   185  
   186  	for name, ar := range SupportedFormats {
   187  		name, ar := name, ar
   188  		b.Run(name, func(b *testing.B) {
   189  			// skip RAR for now
   190  			if _, ok := ar.(rarFormat); ok {
   191  				b.Skip("not supported")
   192  			}
   193  			// prepare a archive
   194  			outfile := filepath.Join(tmp, "benchMake-"+name)
   195  			err = ar.Make(outfile, []string{"testdata"})
   196  			if err != nil {
   197  				b.Fatalf("open archive: didn't expect an error, but got: %v", err)
   198  			}
   199  			// prepare extraction destination
   200  			dest := filepath.Join(tmp, "extraction_test")
   201  			os.Mkdir(dest, 0755)
   202  
   203  			// let's go
   204  			b.ResetTimer()
   205  			for i := 0; i < b.N; i++ {
   206  				err = ar.Open(outfile, dest)
   207  				if err != nil {
   208  					b.Fatalf("open archive: didn't expect an error, but got: %v", err)
   209  				}
   210  			}
   211  		})
   212  	}
   213  }