func TestCopy(t *testing.T) { srcb, dstb := new(bytes.Buffer), new(bytes.Buffer) for tname, tt := range copyTests() { // Reset buffers between tests srcb.Reset() dstb.Reset() // Last file name (needed for gzip.NewReader) var fname string // Seed the src srcw := writer(t, tname, srcb, tt.srcType) for _, f := range tt.in { srcw.NextFile(f.name, iotest.FileInfo(t, f.contents)) mustCopy(t, tname, srcw, bytes.NewReader(f.contents)) fname = f.name } mustClose(t, tname, srcw) // Perform the copy srcr := reader(t, tname, srcb, tt.srcType, fname) dstw := writer(t, tname, dstb, tt.dstType) if err := archive.Copy(dstw, srcr); err != nil { t.Fatalf("%s: %v", tname, err) } srcr.Close() // Read-only mustClose(t, tname, dstw) // Read back dst to confirm our expectations dstr := reader(t, tname, dstb, tt.dstType, fname) for _, want := range tt.in { buf := new(bytes.Buffer) name, err := dstr.NextFile() if err != nil { t.Fatalf("%s: %v", tname, err) } mustCopy(t, tname, buf, dstr) got := file{ name: name, contents: buf.Bytes(), } switch { case got.name != want.name: t.Errorf("%s: got file %q but want file %q", tname, got.name, want.name) case !bytes.Equal(got.contents, want.contents): t.Errorf("%s: mismatched contents in %q: got %q but want %q", tname, got.name, got.contents, want.contents) } } dstr.Close() } }
func (rw *rollingFileWriter) archiveUnexplodedLogs(compressionType compressionType, rollsToDelete int, history []string) (err error) { closeWithError := func(c io.Closer) { if cerr := c.Close(); cerr != nil && err == nil { err = cerr } } // Buffer to a temporary file on the same partition // Note: archivePath is a path to a file when handling unexploded logs dst, err := rw.tempArchiveFile(filepath.Dir(rw.archivePath)) if err != nil { return err } defer func() { closeWithError(dst) if err != nil { os.Remove(dst.Name()) // Can't do anything when we fail to remove temp file return } // Finalize archive by moving the buffered archive into place err = os.Rename(dst.Name(), rw.archivePath) }() w := compressionType.archiver(dst, false) defer closeWithError(w) src, err := os.Open(rw.archivePath) switch { // Archive exists case err == nil: defer src.Close() // Read-only r, err := compressionType.unarchiver(src) if err != nil { return err } defer r.Close() // Read-only if err := archive.Copy(w, r); err != nil { return err } // Failed to stat case !os.IsNotExist(err): return err } // Add new files to the archive for i := 0; i < rollsToDelete; i++ { rollPath := filepath.Join(rw.currentDirPath, history[i]) src, err := os.Open(rollPath) if err != nil { return err } defer src.Close() // Read-only fi, err := src.Stat() if err != nil { return err } if err := w.NextFile(src.Name(), fi); err != nil { return err } if _, err := io.Copy(w, src); err != nil { return err } } return nil }