summaryrefslogtreecommitdiff
path: root/xdelta3/testing/regtest.cc
diff options
context:
space:
mode:
authorJoshua MacDonald <josh.macdonald@gmail.com>2015-11-17 22:52:01 -0800
committerJoshua MacDonald <josh.macdonald@gmail.com>2015-11-17 22:52:01 -0800
commitdc410accc1e1dcef1100d4c047fadb3c6545d172 (patch)
tree5df6805271e4a6d79b385a25df6f487010593d78 /xdelta3/testing/regtest.cc
parent97a6543f64e84821b638a60c88c814c2bdcdfc60 (diff)
Simplifies xd3_srcwin_move_point; reads the full max_winsize before starting to compress (see notes in the corresponding comments); eliminates xd3_stream::frontier_pos; changes as a result, and improvements in testing/regtest.cc; tested on osx-darwin
Diffstat (limited to 'xdelta3/testing/regtest.cc')
-rw-r--r--xdelta3/testing/regtest.cc177
1 files changed, 84 insertions, 93 deletions
diff --git a/xdelta3/testing/regtest.cc b/xdelta3/testing/regtest.cc
index eeb0e4b..23c985e 100644
--- a/xdelta3/testing/regtest.cc
+++ b/xdelta3/testing/regtest.cc
@@ -790,32 +790,34 @@ void TestSmallStride() {
790 usize_t size = Constants::BLOCK_SIZE * 4; 790 usize_t size = Constants::BLOCK_SIZE * 4;
791 spec0.GenerateFixedSize(size); 791 spec0.GenerateFixedSize(size);
792 792
793 /* TODO Need to study the actual causes of missed adds for tests 793 // Note: Not very good performance due to hash collisions, note 3x
794 * less than 30 bytes. */ 794 // multiplier below.
795 const int s = 30; 795 for (int s = 15; s < 101; s++) {
796 usize_t adds = 0; 796 usize_t changes = 0;
797 ChangeList cl; 797 ChangeList cl;
798 for (usize_t j = s; j < size; j += s, ++adds) 798 for (usize_t j = s; j < size; j += s, ++changes)
799 { 799 {
800 cl.push_back(Change(Change::MODIFY, 1, j)); 800 cl.push_back(Change(Change::MODIFY, 1, j));
801 } 801 }
802 802
803 FileSpec spec1(&rand); 803 FileSpec spec1(&rand);
804 spec0.ModifyTo(ChangeListMutator(cl), &spec1); 804 spec0.ModifyTo(ChangeListMutator(cl), &spec1);
805 805
806 Options options; 806 Options options;
807 options.encode_srcwin_maxsz = size; 807 options.encode_srcwin_maxsz = size;
808 options.iopt_size = 128; 808 options.iopt_size = 128;
809 options.smatch_cfg = XD3_SMATCH_SLOW; 809 options.smatch_cfg = XD3_SMATCH_SLOW;
810 options.size_known = false; 810 options.size_known = false;
811 811
812 Block block; 812 Block block;
813 InMemoryEncodeDecode(spec0, spec1, &block, options); 813 InMemoryEncodeDecode(spec0, spec1, &block, options);
814 Delta delta(block); 814 Delta delta(block);
815 815
816 // Allow an additional two byte of add per window 816 IF_DEBUG1(DP(RINT "[stride=%d] changes=%u adds=%"Q"u\n",
817 usize_t allowance = 2 * size / Constants::WINDOW_SIZE; 817 s, changes, delta.AddedBytes()));
818 CHECK_GE(adds + allowance, delta.AddedBytes()); 818 double allowance = Constants::BLOCK_SIZE < 8192 ? 3.0 : 1.1;
819 CHECK_GE(allowance, (double)delta.AddedBytes());
820 }
819} 821}
820 822
821void TestCopyWindow() { 823void TestCopyWindow() {
@@ -927,85 +929,73 @@ void TestCopyFromEnd() {
927} 929}
928 930
929void TestHalfBlockCopy() { 931void TestHalfBlockCopy() {
930 MTRandom rand; 932 // Create a half-block copy, 7.5 blocks apart, in a pair of files:
931 FileSpec spec0(&rand); 933 // 0 1 ... 6 7
932 FileSpec spec1(&rand); 934 // spec0 [bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb][ccccc][bbbb_]
933 935 // spec1 [aaaaa][ccccc][aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa_]
934 // The test takes place over four blocks, but we create a 8-block 936 // where stage=
935 // file to ensure that the whole input doesn't fit in memory. 937 // 0: the final block is full
936 spec0.GenerateFixedSize(Constants::BLOCK_SIZE * 8); 938 // a. (source)spec1->(target)spec0 copies block C: reads 8 source
937 939 // blocks during target block 0.
938 // Create a half-block copy, 2.5 blocks apart, from the second half 940 // b. (source)spec0->(target)spec1 does not copy block C b/c attempt
939 // of the source version to the first half of the target version. 941 // to read past EOF empties block 0 from (virtual) block cache
940 // 0 1 2 3 942 // 1: the final block is less than full.
941 // spec0 [bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb][ccccc][bbbbb...] 943 // a. (same) copies block C
942 // spec1 [aaaaa][ccccc][aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa...] 944 // b. (same) copies block C, unlike 0a, no attempt to read past EOF
943 ChangeList cl1; 945 //
944 cl1.push_back(Change(Change::MODIFY, 946 // "virtual" above refers to XD3_TOOFARBACK, since there is no caching
945 Constants::BLOCK_SIZE / 2, // size 947 // in the API, there is simply a promise not to request blocks that are
946 0)); 948 // beyond source->max_winsize from the last known source file position.
947 cl1.push_back(Change(Change::COPYOVER, 949 for (int stage = 0; stage < 2; stage++)
948 Constants::BLOCK_SIZE / 2, // size
949 Constants::BLOCK_SIZE * 3, // offset
950 Constants::BLOCK_SIZE / 2));
951 cl1.push_back(Change(Change::MODIFY,
952 Constants::BLOCK_SIZE * 7,
953 Constants::BLOCK_SIZE));
954 spec0.ModifyTo(ChangeListMutator(cl1), &spec1);
955
956 const int nocopy_adds = 8 * Constants::BLOCK_SIZE;
957 const int onecopy_adds = nocopy_adds - Constants::BLOCK_SIZE / 2;
958
959 // TODO Note restricted loop
960 for (int b = 4; b <= 4; b++)
961 { 950 {
951 IF_DEBUG1 (DP(RINT "half_block_copy stage %d\n", stage));
952
953 MTRandom rand;
954 FileSpec spec0(&rand);
955 FileSpec spec1(&rand);
956
957 spec0.GenerateFixedSize(Constants::BLOCK_SIZE * 8 - stage);
958
959 ChangeList cl1;
960 cl1.push_back(Change(Change::MODIFY,
961 Constants::BLOCK_SIZE / 2, // size
962 0));
963 cl1.push_back(Change(Change::COPYOVER,
964 Constants::BLOCK_SIZE / 2, // size
965 Constants::BLOCK_SIZE * 7, // offset
966 Constants::BLOCK_SIZE / 2));
967 cl1.push_back(Change(Change::MODIFY,
968 Constants::BLOCK_SIZE * 7,
969 Constants::BLOCK_SIZE - stage));
970 spec0.ModifyTo(ChangeListMutator(cl1), &spec1);
971
962 Options options; 972 Options options;
963 options.encode_srcwin_maxsz = Constants::BLOCK_SIZE * b; 973 options.encode_srcwin_maxsz = Constants::BLOCK_SIZE * 8;
964 974
965 Block block0; 975 Block block0;
966 Block block1; 976 Block block1;
967 InMemoryEncodeDecode(spec0, spec1, &block0, options); 977 InMemoryEncodeDecode(spec0, spec1, &block0, options);
968 InMemoryEncodeDecode(spec1, spec0, &block1, options); 978 InMemoryEncodeDecode(spec1, spec0, &block1, options);
979
969 Delta delta0(block0); 980 Delta delta0(block0);
970 Delta delta1(block1); 981 Delta delta1(block1);
971 982
972 // The first block never copies from the last source block, by 983 const int yes =
973 // design, because if the last source block is available when 984 Constants::BLOCK_SIZE * 8 - Constants::BLOCK_SIZE / 2;
974 // the first target block is ready, the caller is expected to 985 const int no =
975 // use a single block. 986 Constants::BLOCK_SIZE * 8 - Constants::BLOCK_SIZE / 2;
976 CHECK_EQ(nocopy_adds, delta0.AddedBytes()); 987
977 if (Constants::BLOCK_SIZE < 8192 || b > 3) 988 if (stage == 0)
978 { 989 {
979 // For small-block inputs, the entire file is read into one 990 CHECK_EQ(yes, delta0.AddedBytes());
980 // block (the min source window size is 16kB). 991 CHECK_EQ(no, delta1.AddedBytes());
981 // 992 }
982 // For large blocks, at least 4 blocks of source window are
983 // needed.
984 CHECK_EQ(onecopy_adds, delta1.AddedBytes());
985 }
986 else 993 else
987 { 994 {
988 // When there are fewer than 3 source blocks. 995 CHECK_EQ(yes, delta0.AddedBytes());
989 CHECK_EQ(nocopy_adds, delta1.AddedBytes()); 996 CHECK_EQ(yes, delta1.AddedBytes());
990 } 997 }
991 } 998 }
992
993 Options options;
994 options.encode_srcwin_maxsz = Constants::BLOCK_SIZE * 4;
995 options.block_size = Constants::BLOCK_SIZE * 4;
996
997 // Test the whole-buffer case.
998 Block block0;
999 Block block1;
1000 InMemoryEncodeDecode(spec0, spec1, &block0, options);
1001 InMemoryEncodeDecode(spec1, spec0, &block1, options);
1002 Delta delta0(block0);
1003 Delta delta1(block1);
1004 // This <= >= are only for blocksize = 512, which has irregular readsize.
1005 CHECK_LE(onecopy_adds, delta0.AddedBytes());
1006 CHECK_GE(onecopy_adds + 1, delta0.AddedBytes());
1007
1008 CHECK_EQ(onecopy_adds, delta1.AddedBytes());
1009} 999}
1010 1000
1011void FourWayMergeTest(const FileSpec &spec0, 1001void FourWayMergeTest(const FileSpec &spec0,
@@ -1299,10 +1289,10 @@ int main(int argc, char **argv)
1299 mcmd.push_back("test"); 1289 mcmd.push_back("test");
1300 mcmd.push_back(NULL); 1290 mcmd.push_back(NULL);
1301 1291
1302 // UnitTest<SmallBlock>(); 1292 UnitTest<SmallBlock>();
1303 // MainTest<SmallBlock>(); 1293 MainTest<SmallBlock>();
1304 // MainTest<MixedBlock>(); 1294 MainTest<MixedBlock>();
1305 // MainTest<OversizeBlock>(); 1295 MainTest<OversizeBlock>();
1306 MainTest<LargeBlock>(); 1296 MainTest<LargeBlock>();
1307 1297
1308 CHECK_EQ(0, xd3_main_cmdline(mcmd.size() - 1, 1298 CHECK_EQ(0, xd3_main_cmdline(mcmd.size() - 1,
@@ -1310,3 +1300,4 @@ int main(int argc, char **argv)
1310 1300
1311 return 0; 1301 return 0;
1312} 1302}
1303