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