1package archive_test 2 3import ( 4 "bytes" 5 "fmt" 6 "io" 7 "testing" 8 9 "github.com/cihub/seelog/archive" 10 "github.com/cihub/seelog/archive/gzip" 11 "github.com/cihub/seelog/archive/tar" 12 "github.com/cihub/seelog/archive/zip" 13 "github.com/cihub/seelog/io/iotest" 14) 15 16const ( 17 gzipType = "gzip" 18 tarType = "tar" 19 zipType = "zip" 20) 21 22var types = []string{gzipType, tarType, zipType} 23 24type file struct { 25 name string 26 contents []byte 27} 28 29var ( 30 oneFile = []file{ 31 { 32 name: "file1", 33 contents: []byte("This is a single log."), 34 }, 35 } 36 twoFiles = []file{ 37 { 38 name: "file1", 39 contents: []byte("This is a log."), 40 }, 41 { 42 name: "file2", 43 contents: []byte("This is another log."), 44 }, 45 } 46) 47 48type testCase struct { 49 srcType, dstType string 50 in []file 51} 52 53func copyTests() map[string]testCase { 54 // types X types X files 55 tests := make(map[string]testCase, len(types)*len(types)*2) 56 for _, srct := range types { 57 for _, dstt := range types { 58 tests[fmt.Sprintf("%s to %s: one file", srct, dstt)] = testCase{ 59 srcType: srct, 60 dstType: dstt, 61 in: oneFile, 62 } 63 // gzip does not handle more than one file 64 if srct != gzipType && dstt != gzipType { 65 tests[fmt.Sprintf("%s to %s: two files", srct, dstt)] = testCase{ 66 srcType: srct, 67 dstType: dstt, 68 in: twoFiles, 69 } 70 } 71 } 72 } 73 return tests 74} 75 76func TestCopy(t *testing.T) { 77 srcb, dstb := new(bytes.Buffer), new(bytes.Buffer) 78 for tname, tt := range copyTests() { 79 // Reset buffers between tests 80 srcb.Reset() 81 dstb.Reset() 82 83 // Last file name (needed for gzip.NewReader) 84 var fname string 85 86 // Seed the src 87 srcw := writer(t, tname, srcb, tt.srcType) 88 for _, f := range tt.in { 89 srcw.NextFile(f.name, iotest.FileInfo(t, f.contents)) 90 mustCopy(t, tname, srcw, bytes.NewReader(f.contents)) 91 fname = f.name 92 } 93 mustClose(t, tname, srcw) 94 95 // Perform the copy 96 srcr := reader(t, tname, srcb, tt.srcType, fname) 97 dstw := writer(t, tname, dstb, tt.dstType) 98 if err := archive.Copy(dstw, srcr); err != nil { 99 t.Fatalf("%s: %v", tname, err) 100 } 101 srcr.Close() // Read-only 102 mustClose(t, tname, dstw) 103 104 // Read back dst to confirm our expectations 105 dstr := reader(t, tname, dstb, tt.dstType, fname) 106 for _, want := range tt.in { 107 buf := new(bytes.Buffer) 108 name, err := dstr.NextFile() 109 if err != nil { 110 t.Fatalf("%s: %v", tname, err) 111 } 112 mustCopy(t, tname, buf, dstr) 113 got := file{ 114 name: name, 115 contents: buf.Bytes(), 116 } 117 118 switch { 119 case got.name != want.name: 120 t.Errorf("%s: got file %q but want file %q", 121 tname, got.name, want.name) 122 123 case !bytes.Equal(got.contents, want.contents): 124 t.Errorf("%s: mismatched contents in %q: got %q but want %q", 125 tname, got.name, got.contents, want.contents) 126 } 127 } 128 dstr.Close() 129 } 130} 131 132func writer(t *testing.T, tname string, w io.Writer, atype string) archive.WriteCloser { 133 switch atype { 134 case gzipType: 135 return gzip.NewWriter(w) 136 case tarType: 137 return tar.NewWriter(w) 138 case zipType: 139 return zip.NewWriter(w) 140 } 141 t.Fatalf("%s: unrecognized archive type: %s", tname, atype) 142 panic("execution continued after (*testing.T).Fatalf") 143} 144 145func reader(t *testing.T, tname string, buf *bytes.Buffer, atype string, fname string) archive.ReadCloser { 146 switch atype { 147 case gzipType: 148 gr, err := gzip.NewReader(buf, fname) 149 if err != nil { 150 t.Fatalf("%s: %v", tname, err) 151 } 152 return gr 153 case tarType: 154 return archive.NopCloser(tar.NewReader(buf)) 155 case zipType: 156 zr, err := zip.NewReader( 157 bytes.NewReader(buf.Bytes()), 158 int64(buf.Len())) 159 if err != nil { 160 t.Fatalf("%s: new zip reader: %v", tname, err) 161 } 162 return archive.NopCloser(zr) 163 } 164 t.Fatalf("%s: unrecognized archive type: %s", tname, atype) 165 panic("execution continued after (*testing.T).Fatalf") 166} 167 168func mustCopy(t *testing.T, tname string, dst io.Writer, src io.Reader) { 169 if _, err := io.Copy(dst, src); err != nil { 170 t.Fatalf("%s: copy: %v", tname, err) 171 } 172} 173 174func mustClose(t *testing.T, tname string, c io.Closer) { 175 if err := c.Close(); err != nil { 176 t.Fatalf("%s: close: %v", tname, err) 177 } 178} 179