]> arthur.barton.de Git - bup.git/blob - lib/bup/t/thashsplit.py
1a95f4052d543c54e8d49f0acd00ff140bb5a3fc
[bup.git] / lib / bup / t / thashsplit.py
1 from io import BytesIO
2
3 from wvtest import *
4
5 from bup import hashsplit, _helpers, helpers
6 from buptest import no_lingering_errors
7
8
9 def nr_regions(x, max_count=None):
10     return list(hashsplit._nonresident_page_regions(bytearray(x), 1, max_count))
11
12
13 @wvtest
14 def test_nonresident_page_regions():
15     with no_lingering_errors():
16         WVPASSEQ(nr_regions([]), [])
17         WVPASSEQ(nr_regions([1]), [])
18         WVPASSEQ(nr_regions([0]), [(0, 1)])
19         WVPASSEQ(nr_regions([1, 0]), [(1, 1)])
20         WVPASSEQ(nr_regions([0, 0]), [(0, 2)])
21         WVPASSEQ(nr_regions([1, 0, 1]), [(1, 1)])
22         WVPASSEQ(nr_regions([1, 0, 0]), [(1, 2)])
23         WVPASSEQ(nr_regions([0, 1, 0]), [(0, 1), (2, 1)])
24         WVPASSEQ(nr_regions([0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0]),
25                  [(0, 2), (5, 3), (9, 2)])
26         WVPASSEQ(nr_regions([2, 42, 3, 101]), [(0, 2)])
27         # Test limit
28         WVPASSEQ(nr_regions([0, 0, 0], None), [(0, 3)])
29         WVPASSEQ(nr_regions([0, 0, 0], 1), [(0, 1), (1, 1), (2, 1)])
30         WVPASSEQ(nr_regions([0, 0, 0], 2), [(0, 2), (2, 1)])
31         WVPASSEQ(nr_regions([0, 0, 0], 3), [(0, 3)])
32         WVPASSEQ(nr_regions([0, 0, 0], 4), [(0, 3)])
33         WVPASSEQ(nr_regions([0, 0, 1], None), [(0, 2)])
34         WVPASSEQ(nr_regions([0, 0, 1], 1), [(0, 1), (1, 1)])
35         WVPASSEQ(nr_regions([0, 0, 1], 2), [(0, 2)])
36         WVPASSEQ(nr_regions([0, 0, 1], 3), [(0, 2)])
37         WVPASSEQ(nr_regions([1, 0, 0], None), [(1, 2)])
38         WVPASSEQ(nr_regions([1, 0, 0], 1), [(1, 1), (2, 1)])
39         WVPASSEQ(nr_regions([1, 0, 0], 2), [(1, 2)])
40         WVPASSEQ(nr_regions([1, 0, 0], 3), [(1, 2)])
41         WVPASSEQ(nr_regions([1, 0, 0, 0, 1], None), [(1, 3)])
42         WVPASSEQ(nr_regions([1, 0, 0, 0, 1], 1), [(1, 1), (2, 1), (3, 1)])
43         WVPASSEQ(nr_regions([1, 0, 0, 0, 1], 2), [(1, 2), (3, 1)])
44         WVPASSEQ(nr_regions([1, 0, 0, 0, 1], 3), [(1, 3)])
45         WVPASSEQ(nr_regions([1, 0, 0, 0, 1], 4), [(1, 3)])
46
47
48 @wvtest
49 def test_uncache_ours_upto():
50     history = []
51     def mock_fadvise_pages_done(f, ofs, len):
52         history.append((f, ofs, len))
53
54     with no_lingering_errors():
55         uncache_upto = hashsplit._uncache_ours_upto
56         page_size = helpers.sc_page_size
57         orig_pages_done = hashsplit._fadvise_pages_done
58         try:
59             hashsplit._fadvise_pages_done = mock_fadvise_pages_done
60             history = []
61             uncache_upto(42, 0, (0, 1), iter([]))
62             WVPASSEQ([], history)
63             uncache_upto(42, page_size, (0, 1), iter([]))
64             WVPASSEQ([(42, 0, 1)], history)
65             history = []
66             uncache_upto(42, page_size, (0, 3), iter([(5, 2)]))
67             WVPASSEQ([], history)
68             uncache_upto(42, 2 * page_size, (0, 3), iter([(5, 2)]))
69             WVPASSEQ([], history)
70             uncache_upto(42, 3 * page_size, (0, 3), iter([(5, 2)]))
71             WVPASSEQ([(42, 0, 3)], history)
72             history = []
73             uncache_upto(42, 5 * page_size, (0, 3), iter([(5, 2)]))
74             WVPASSEQ([(42, 0, 3)], history)
75             history = []
76             uncache_upto(42, 6 * page_size, (0, 3), iter([(5, 2)]))
77             WVPASSEQ([(42, 0, 3)], history)
78             history = []
79             uncache_upto(42, 7 * page_size, (0, 3), iter([(5, 2)]))
80             WVPASSEQ([(42, 0, 3), (42, 5, 2)], history)
81         finally:
82             hashsplit._fadvise_pages_done = orig_pages_done
83
84
85 @wvtest
86 def test_rolling_sums():
87     with no_lingering_errors():
88         WVPASS(_helpers.selftest())
89
90 @wvtest
91 def test_fanout_behaviour():
92
93     # Drop in replacement for bupsplit, but splitting if the int value of a
94     # byte >= BUP_BLOBBITS
95     basebits = _helpers.blobbits()
96     def splitbuf(buf):
97         ofs = 0
98         for c in buf:
99             ofs += 1
100             if ord(c) >= basebits:
101                 return ofs, ord(c)
102         return 0, 0
103
104     with no_lingering_errors():
105         old_splitbuf = _helpers.splitbuf
106         _helpers.splitbuf = splitbuf
107         old_BLOB_MAX = hashsplit.BLOB_MAX
108         hashsplit.BLOB_MAX = 4
109         old_BLOB_READ_SIZE = hashsplit.BLOB_READ_SIZE
110         hashsplit.BLOB_READ_SIZE = 10
111         old_fanout = hashsplit.fanout
112         hashsplit.fanout = 2
113
114         levels = lambda f: [(len(b), l) for b, l in
115             hashsplit.hashsplit_iter([f], True, None)]
116         # Return a string of n null bytes
117         z = lambda n: '\x00' * n
118         # Return a byte which will be split with a level of n
119         sb = lambda n: chr(basebits + n)
120
121         split_never = BytesIO(z(16))
122         split_first = BytesIO(z(1) + sb(3) + z(14))
123         split_end   = BytesIO(z(13) + sb(1) + z(2))
124         split_many  = BytesIO(sb(1) + z(3) + sb(2) + z(4) +
125                               sb(0) + z(4) + sb(5) + z(1))
126         WVPASSEQ(levels(split_never), [(4, 0), (4, 0), (4, 0), (4, 0)])
127         WVPASSEQ(levels(split_first), [(2, 3), (4, 0), (4, 0), (4, 0), (2, 0)])
128         WVPASSEQ(levels(split_end), [(4, 0), (4, 0), (4, 0), (2, 1), (2, 0)])
129         WVPASSEQ(levels(split_many),
130             [(1, 1), (4, 2), (4, 0), (1, 0), (4, 0), (1, 5), (1, 0)])
131
132         _helpers.splitbuf = old_splitbuf
133         hashsplit.BLOB_MAX = old_BLOB_MAX
134         hashsplit.BLOB_READ_SIZE = old_BLOB_READ_SIZE
135         hashsplit.fanout = old_fanout