From 678ad627b2cb09bbc498a9a3bddc44b41018fdc6 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Tue, 4 Jul 2023 05:15:03 +0530 Subject: [PATCH] Improve testing infra for rsync roundtrip --- tools/rsync/api.go | 2 +- tools/rsync/api_test.go | 69 +++++++++++++++++++++++++---------------- 2 files changed, 44 insertions(+), 27 deletions(-) diff --git a/tools/rsync/api.go b/tools/rsync/api.go index 30e20853d..6b7e96eed 100644 --- a/tools/rsync/api.go +++ b/tools/rsync/api.go @@ -192,7 +192,7 @@ func (self *Differ) CreateDelta(src io.Reader, output_callback func([]byte) erro if err = self.finish_signature_data(); err != nil { return } - if len(self.signature) == 0 { + if self.signature == nil { return fmt.Errorf("Cannot call CreateDelta() before loading a signature") } self.rsync.CreateDelta(src, self.signature, func(op Operation) error { diff --git a/tools/rsync/api_test.go b/tools/rsync/api_test.go index 00e4645ed..7772615c0 100644 --- a/tools/rsync/api_test.go +++ b/tools/rsync/api_test.go @@ -16,22 +16,13 @@ import ( var _ = fmt.Print var _ = cmp.Diff -func TestRsyncRoundtrip(t *testing.T) { - src_data := make([]byte, 4*1024*1024) - random.Bytes(src_data) - total_patch_size := 0 - num_of_patches := 8 - - random_patch := func(data []byte) (size int) { - if offset := random.Int(len(data)); offset < len(data) { - max_size := utils.Min(257, len(data)-offset) - if size = random.Int(max_size); size > 0 { - total_patch_size += size - random.Bytes(data[offset : offset+size]) - } - } - return +func run_roundtrip_test(t *testing.T, src_data, changed []byte, num_of_patches, total_patch_size int) { + using_serialization := false + prefix_msg := func() string { + q := utils.IfElse(using_serialization, "with", "without") + return fmt.Sprintf("Running %s serialization: src size: %d changed size: %d difference: %d\n", q, len(src_data), len(changed), len(changed)-len(src_data)) } + test_equal := func(src_data, output []byte) { if !bytes.Equal(src_data, output) { first_diff := utils.Min(len(src_data), len(output)) @@ -41,15 +32,10 @@ func TestRsyncRoundtrip(t *testing.T) { break } } - t.Fatalf("Patching failed: %d extra_bytes first different byte at: %d", len(output)-len(src_data), first_diff) + t.Fatalf("%sPatching failed: %d extra_bytes first different byte at: %d", prefix_msg(), len(output)-len(src_data), first_diff) } } - changed := slices.Clone(src_data) - for i := 0; i < num_of_patches; i++ { - random_patch(changed) - } - // first try just the engine without serialization p := NewPatcher(int64(len(src_data))) signature := make([]BlockHash, 0, 128) @@ -74,14 +60,14 @@ func TestRsyncRoundtrip(t *testing.T) { } return outputbuf.Bytes() } - test_equal(src_data, apply_delta(nil)) test_equal(src_data, apply_delta(signature)) limit := 2 * (p.rsync.BlockSize * num_of_patches) - if total_data_in_delta > limit { - t.Fatalf("Unexpectedly poor delta performance: total_patch_size: %d total_delta_size: %d limit: %d", total_patch_size, total_data_in_delta, limit) + if limit > -1 && total_data_in_delta > limit { + t.Fatalf("%sUnexpectedly poor delta performance: total_patch_size: %d total_delta_size: %d limit: %d", prefix_msg(), total_patch_size, total_data_in_delta, limit) } // Now try with serialization + using_serialization = true p = NewPatcher(int64(len(src_data))) sigbuf := bytes.Buffer{} if err := p.CreateSignature(bytes.NewReader(changed), func(p []byte) error { _, err := sigbuf.Write(p); return err }); err != nil { @@ -112,8 +98,39 @@ func TestRsyncRoundtrip(t *testing.T) { } test_equal(src_data, outputbuf.Bytes()) - if p.total_data_in_delta > limit { - t.Fatalf("Unexpectedly poor delta performance: total_patch_size: %d total_delta_size: %d limit: %d", total_patch_size, p.total_data_in_delta, limit) + if limit > -1 && p.total_data_in_delta > limit { + t.Fatalf("%sUnexpectedly poor delta performance: total_patch_size: %d total_delta_size: %d limit: %d", prefix_msg(), total_patch_size, p.total_data_in_delta, limit) } } + +func TestRsyncRoundtrip(t *testing.T) { + src_data := make([]byte, 4*1024*1024) + random.Bytes(src_data) + total_patch_size := 0 + num_of_patches := 8 + + random_patch := func(data []byte) (size int) { + if offset := random.Int(len(data)); offset < len(data) { + max_size := utils.Min(257, len(data)-offset) + if size = random.Int(max_size); size > 0 { + total_patch_size += size + random.Bytes(data[offset : offset+size]) + } + } + return + } + changed := slices.Clone(src_data) + for i := 0; i < num_of_patches; i++ { + random_patch(changed) + } + + run_roundtrip_test(t, src_data, changed, num_of_patches, total_patch_size) + run_roundtrip_test(t, src_data, []byte{}, -1, 0) + run_roundtrip_test(t, src_data, src_data, 0, 0) + + // p := NewPatcher(int64(len(src_data))) + // block_size := p.rsync.BlockSize + // run_roundtrip_test(t, src_data, src_data[block_size:], 0, 0) + +}