Example #1
0
func TestPatchingStart(t *testing.T) {
	LOCAL := bytes.NewReader([]byte("48 brown fox jumped over the lazy dog"))
	out := bytes.NewBuffer(nil)

	missing := []patcher.MissingBlockSpan{
		{
			BlockSize:    BLOCKSIZE,
			StartBlock:   0,
			EndBlock:     2,
			Hasher:       md5.New(),
			ExpectedSums: REFERENCE_HASHES[0:3],
		},
	}

	matched := []patcher.FoundBlockSpan{
		{
			BlockSize:   BLOCKSIZE,
			StartBlock:  3,
			EndBlock:    11,
			MatchOffset: 5,
		},
	}

	err := SequentialPatcher(
		LOCAL,
		blocksources.NewReadSeekerBlockSource(
			stringToReadSeeker(REFERENCE_STRING),
			blocksources.MakeNullFixedSizeResolver(BLOCKSIZE),
		),
		missing,
		matched,
		1024,
		out,
	)

	if err != nil {
		t.Fatal(err)
	}

	if result, err := ioutil.ReadAll(out); err == nil {
		t.Logf("String split is: \"%v\"", strings.Join(REFERENCE_BLOCKS, "\", \""))
		if bytes.Compare(result, []byte(REFERENCE_STRING)) != 0 {
			t.Errorf("Result does not equal reference: \"%s\" vs \"%v\"", result, REFERENCE_STRING)
		}
	} else {
		t.Fatal(err)
	}
	//
}
Example #2
0
func TestPatchingEntirelyMissing(t *testing.T) {
	LOCAL := bytes.NewReader([]byte(""))
	out := bytes.NewBuffer(nil)

	missing := []patcher.MissingBlockSpan{
		{
			BlockSize:    BLOCKSIZE,
			StartBlock:   0,
			EndBlock:     10,
			Hasher:       md5.New(),
			ExpectedSums: REFERENCE_HASHES[0:10],
		},
	}

	matched := []patcher.FoundBlockSpan{}

	err := SequentialPatcher(
		LOCAL,
		blocksources.NewReadSeekerBlockSource(
			stringToReadSeeker(REFERENCE_STRING),
			blocksources.MakeNullFixedSizeResolver(BLOCKSIZE),
		),
		missing,
		matched,
		1024,
		out,
	)

	if err != nil {
		t.Fatal(err)
	}

	if result, err := ioutil.ReadAll(out); err == nil {
		if bytes.Compare(result, []byte(REFERENCE_STRING)) != 0 {
			t.Errorf("Result does not equal reference: \"%s\" vs \"%v\"", result, REFERENCE_STRING)
		}
	} else {
		t.Fatal(err)
	}
}
Example #3
0
func Example() {
	// due to short example strings, use a very small block size
	// using one this small in practice would increase your file transfer!
	const blockSize = 4

	// This is the "file" as described by the authoritive version
	const reference = "The quick brown fox jumped over the lazy dog"

	// This is what we have locally. Not too far off, but not correct.
	const localVersion = "The qwik brown fox jumped 0v3r the lazy"

	generator := filechecksum.NewFileChecksumGenerator(blockSize)
	_, referenceFileIndex, _, err := indexbuilder.BuildIndexFromString(
		generator,
		reference,
	)

	if err != nil {
		return
	}

	referenceAsBytes := []byte(reference)
	localVersionAsBytes := []byte(localVersion)

	blockCount := len(referenceAsBytes) / blockSize
	if len(referenceAsBytes)%blockSize != 0 {
		blockCount++
	}

	inputFile := bytes.NewReader(localVersionAsBytes)
	patchedFile := bytes.NewBuffer(nil)

	// This is more complicated than usual, because we're using in-memory
	// "files" and sources. Normally you would use MakeRSync
	summary := &BasicSummary{
		ChecksumIndex:  referenceFileIndex,
		ChecksumLookup: nil,
		BlockCount:     uint(blockCount),
		BlockSize:      blockSize,
		FileSize:       int64(len(referenceAsBytes)),
	}

	rsync := &RSync{
		Input:  inputFile,
		Output: patchedFile,
		Source: blocksources.NewReadSeekerBlockSource(
			bytes.NewReader(referenceAsBytes),
			blocksources.MakeNullFixedSizeResolver(uint64(blockSize)),
		),
		Summary: summary,
		OnClose: nil,
	}

	if err := rsync.Patch(); err != nil {
		fmt.Printf("Error: %v", err)
		return
	}

	fmt.Printf("Patched result: \"%s\"\n", patchedFile.Bytes())
	// Output:
	// Patched result: "The quick brown fox jumped over the lazy dog"
}