func testCompressDecompress(t *testing.T, size int64, algo AlgorithmType, useReadFrom, useWriteTo bool) { // Fake data file is written to disk, // as compression reader has to be a ReadSeeker. testutil.Remover(t, ZipFilePath) data := testutil.CreateDummyBuf(size) zipFileDest := openDest(t, ZipFilePath) defer testutil.Remover(t, ZipFilePath) // Compress. w, err := NewWriter(zipFileDest, algo) if err != nil { t.Errorf("Writer init failed %v", err) return } if _, err := testutil.DumbCopy(w, bytes.NewReader(data), useReadFrom, useWriteTo); err != nil { t.Errorf("Compress failed %v", err) return } if err := w.Close(); err != nil { t.Errorf("Compression writer close failed: %v", err) return } if err := zipFileDest.Close(); err != nil { t.Errorf("close(zipFileDest) failed: %v", err) return } // Read compressed file into buffer. dataUncomp := bytes.NewBuffer(nil) dataFromZip := openSrc(t, ZipFilePath) // Uncompress. r := NewReader(dataFromZip) if _, err := testutil.DumbCopy(dataUncomp, r, useReadFrom, useWriteTo); err != nil { t.Errorf("Decompression failed: %v", err) return } if err := dataFromZip.Close(); err != nil { t.Errorf("Zip close failed: %v", err) return } // Compare. got, want := dataUncomp.Bytes(), data if !bytes.Equal(got, want) { t.Error("Uncompressed data and input data does not match.") t.Errorf("\tGOT: %v", util.OmitBytes(got, 10)) t.Errorf("\tWANT: %v", util.OmitBytes(want, 10)) return } }
func testSeek(t *testing.T, N int64, readFrom, writeTo bool) { sourceData := testutil.CreateDummyBuf(N) source := bytes.NewBuffer(sourceData) shared := &bytes.Buffer{} t.Logf("Testing seek for size %d", N) enc, err := NewWriter(shared, TestKey) if err != nil { t.Errorf("Creating an encrypted writer failed: %v", err) return } // Encrypt: if _, err = testutil.DumbCopy(enc, source, readFrom, writeTo); err != nil { t.Errorf("copy(enc, source) failed %v", err) return } // This needs to be here, since close writes // left over data to the write stream if err = enc.Close(); err != nil { t.Errorf("close(enc): %v", err) return } sharedReader := bytes.NewReader(shared.Bytes()) decLayer, err := NewReader(sharedReader, TestKey) if err != nil { t.Errorf("creating new reader failed: %v", err) return } lastJump := int64(0) for _, test := range SeekTests { realOffset := int64(math.Floor(.5 + test.Offset*float64(N))) whence := map[int]string{ 0: "SEEK_SET", 1: "SEEK_CUR", 2: "SEEK_END", }[test.Whence] exptOffset := int64(0) switch test.Whence { case os.SEEK_SET: exptOffset = realOffset case os.SEEK_CUR: exptOffset = lastJump + realOffset case os.SEEK_END: exptOffset = N + realOffset default: panic("Bad whence") } t.Logf( " => Seek(%v, %v) -> %v (size: %v)", realOffset, whence, exptOffset, N, ) jumpedTo, err := decLayer.Seek(realOffset, test.Whence) if err != test.Error { if err != io.EOF && N != 0 { t.Errorf( "Seek(%v, %v) produced an error: %v (should be %v)", realOffset, whence, err, test.Error, ) } return } if test.Error != nil { continue } if jumpedTo != exptOffset { t.Errorf( "Seek(%v, %v) jumped badly. Should be %v, was %v", realOffset, whence, exptOffset, jumpedTo, ) return } lastJump = jumpedTo // Decrypt and check if the contents are okay: dest := bytes.NewBuffer(nil) copiedBytes, err := testutil.DumbCopy(dest, decLayer, readFrom, writeTo) if err != nil { t.Errorf("Decrypt failed: %v", err) return } if copiedBytes != N-jumpedTo { t.Errorf("Copied different amount of decrypted data than expected.") t.Errorf("Should be %v, was %v bytes.", N-jumpedTo, copiedBytes) } // Check the data actually matches the source data. if !bytes.Equal(sourceData[jumpedTo:], dest.Bytes()) { t.Errorf("Seeked data does not match expectations.") t.Errorf("\tEXPECTED: %v", util.OmitBytes(sourceData[jumpedTo:], 10)) t.Errorf("\tGOT: %v", util.OmitBytes(dest.Bytes(), 10)) return } // Jump back, so the other tests continue to work: jumpedAgain, err := decLayer.Seek(jumpedTo, os.SEEK_SET) if err != nil { t.Errorf("Seeking not possible after reading: %v", err) return } if jumpedTo != jumpedAgain { t.Errorf("Jumping back to original pos failed.") t.Errorf("Should be %v, was %v.", jumpedTo, jumpedAgain) return } } }
func testSeek(t *testing.T, size, offset int64, algo AlgorithmType, useReadFrom, useWriteTo bool) { // Fake data file is written to disk, // as compression reader has to be a ReadSeeker. testutil.Remover(t, ZipFilePath) data := testutil.CreateDummyBuf(size) zipFileDest := openDest(t, ZipFilePath) // Compress. w, err := NewWriter(zipFileDest, algo) if err != nil { t.Errorf("Writer init failed %v", err) return } if _, err := testutil.DumbCopy(w, bytes.NewReader(data), useReadFrom, useWriteTo); err != nil { t.Errorf("Compress failed %v", err) return } defer testutil.Remover(t, ZipFilePath) if err := w.Close(); err != nil { t.Errorf("Compression writer close failed: %v", err) return } if err := zipFileDest.Close(); err != nil { t.Errorf("close(zipFileDest) failed: %v", err) return } // Read compressed file into buffer. dataUncomp := bytes.NewBuffer(nil) dataFromZip := openSrc(t, ZipFilePath) zr := NewReader(dataFromZip) // Set specific offset before read. _, err = zr.Seek(offset, os.SEEK_SET) if err == io.EOF && offset < size && offset > -1 { t.Errorf("Seek failed even with EOF: %d <= %d", offset, size) return } if err != io.EOF && err != nil { t.Errorf("Seek failed: %v", err) return } // Read starting at a specific offset. if _, err := testutil.DumbCopy(dataUncomp, zr, useReadFrom, useWriteTo); err != nil { t.Errorf("Decompression failed: %v", err) return } if err := dataFromZip.Close(); err != nil { t.Errorf("Zip close failed: %v", err) return } // Compare. maxOffset := offset if offset > size { maxOffset = size } if offset < 0 { maxOffset = 0 } got, want := dataUncomp.Bytes(), data[maxOffset:] if !bytes.Equal(got, want) { t.Error("Uncompressed data and input data does not match.") t.Errorf("\tGOT: %v", util.OmitBytes(got, 10)) t.Errorf("\tWANT: %v", util.OmitBytes(want, 10)) return } }
func stageFile(fs *FS, repoPath string, newHash *Hash, key []byte, size uint64, author id.ID) (*File, error) { var oldHash *Hash file, err := fs.LookupFile(repoPath) if err != nil && !IsNoSuchFileError(err) { return nil, err } needRemove := false if file != nil { // We know this file already. log.WithFields(log.Fields{"file": repoPath}).Info("File exists; modifying.") oldHash = file.Hash().Clone() needRemove = true } else { par, err := mkdirParents(fs, repoPath) if err != nil { return nil, err } // Create a new file at specified path: file, err = newEmptyFile(fs, par, path.Base(repoPath)) if err != nil { return nil, err } } log.Infof( "store-add: %s (hash: %s, key: %x)", repoPath, newHash.B58String(), util.OmitBytes(file.Key(), 10), ) if file.Hash().Equal(newHash) { log.Debugf("Hash was not modified. Refusing update.") return nil, ErrNoChange } parNode, err := file.Parent() if err != nil { return nil, err } if parNode == nil { return nil, fmt.Errorf("%s has no parent yet (BUG)", repoPath) } parDir, ok := parNode.(*Directory) if !ok { return nil, ErrBadNode } if needRemove { // Remove the child before changing the hash: if err := parDir.RemoveChild(file); err != nil { return nil, err } } file.SetSize(size) file.SetModTime(time.Now()) file.SetKey(key) file.SetHash(newHash) // Add it again when the hash was changed. if err := parDir.Add(file); err != nil { return nil, err } // Create a checkpoint in the version history. if err := makeCheckpoint(fs, author, file.ID(), oldHash, newHash, repoPath, repoPath); err != nil { return nil, err } if err := fs.StageNode(file); err != nil { return nil, err } return file, err }