/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
3885.1.1 by John Arbash Meinel
Start working on a FIFOCache.
1
# Copyright (C) 2008 Canonical Ltd
2
#
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
7
#
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
# GNU General Public License for more details.
12
#
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
4183.7.1 by Sabin Iacob
update FSF mailing address
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
3885.1.1 by John Arbash Meinel
Start working on a FIFOCache.
16
17
"""Tests for the fifo_cache module."""
18
6624 by Jelmer Vernooij
Merge Python3 porting work ('py3 pokes')
19
from .. import (
3885.1.1 by John Arbash Meinel
Start working on a FIFOCache.
20
    fifo_cache,
21
    tests,
22
    )
6656.1.1 by Martin
Apply 2to3 dict fixer and clean up resulting mess using view helpers
23
from ..sixish import (
24
    viewitems,
25
    viewkeys,
26
    viewvalues,
27
    )
3885.1.1 by John Arbash Meinel
Start working on a FIFOCache.
28
29
30
class TestFIFOCache(tests.TestCase):
31
    """Test that FIFO cache properly keeps track of entries."""
32
33
    def test_add_is_present(self):
34
        c = fifo_cache.FIFOCache()
35
        c[1] = 2
36
        self.assertTrue(1 in c)
37
        self.assertEqual(1, len(c))
38
        self.assertEqual(2, c[1])
39
        self.assertEqual(2, c.get(1))
40
        self.assertEqual(2, c.get(1, None))
6656.1.1 by Martin
Apply 2to3 dict fixer and clean up resulting mess using view helpers
41
        self.assertEqual([1], list(c))
42
        self.assertEqual({1}, viewkeys(c))
43
        self.assertEqual([(1, 2)], sorted(viewitems(c)))
44
        self.assertEqual([2], sorted(viewvalues(c)))
3885.1.4 by John Arbash Meinel
Implement setdefault.
45
        self.assertEqual({1: 2}, c)
3885.1.1 by John Arbash Meinel
Start working on a FIFOCache.
46
3882.6.11 by John Arbash Meinel
comment update
47
    def test_cache_size(self):
48
        c = fifo_cache.FIFOCache()
49
        self.assertEqual(100, c.cache_size())
50
        c.resize(20, 5)
51
        self.assertEqual(20, c.cache_size())
52
3885.1.1 by John Arbash Meinel
Start working on a FIFOCache.
53
    def test_missing(self):
54
        c = fifo_cache.FIFOCache()
55
        self.assertRaises(KeyError, c.__getitem__, 1)
56
        self.assertFalse(1 in c)
57
        self.assertEqual(0, len(c))
58
        self.assertEqual(None, c.get(1))
59
        self.assertEqual(None, c.get(1, None))
6656.1.1 by Martin
Apply 2to3 dict fixer and clean up resulting mess using view helpers
60
        self.assertEqual([], list(c))
61
        self.assertEqual(set(), viewkeys(c))
62
        self.assertEqual([], list(viewitems(c)))
63
        self.assertEqual([], list(viewvalues(c)))
3885.1.4 by John Arbash Meinel
Implement setdefault.
64
        self.assertEqual({}, c)
3885.1.1 by John Arbash Meinel
Start working on a FIFOCache.
65
66
    def test_add_maintains_fifo(self):
67
        c = fifo_cache.FIFOCache(4, 4)
68
        c[1] = 2
69
        c[2] = 3
70
        c[3] = 4
71
        c[4] = 5
6656.1.1 by Martin
Apply 2to3 dict fixer and clean up resulting mess using view helpers
72
        self.assertEqual({1, 2, 3, 4}, viewkeys(c))
3885.1.1 by John Arbash Meinel
Start working on a FIFOCache.
73
        c[5] = 6
74
        # This should pop out the oldest entry
6656.1.1 by Martin
Apply 2to3 dict fixer and clean up resulting mess using view helpers
75
        self.assertEqual({2, 3, 4, 5}, viewkeys(c))
3885.1.1 by John Arbash Meinel
Start working on a FIFOCache.
76
        # Replacing an item doesn't change the stored keys
77
        c[2] = 7
6656.1.1 by Martin
Apply 2to3 dict fixer and clean up resulting mess using view helpers
78
        self.assertEqual({2, 3, 4, 5}, viewkeys(c))
3885.1.1 by John Arbash Meinel
Start working on a FIFOCache.
79
        # But it does change the position in the FIFO
80
        c[6] = 7
6656.1.1 by Martin
Apply 2to3 dict fixer and clean up resulting mess using view helpers
81
        self.assertEqual({2, 4, 5, 6}, viewkeys(c))
3885.1.1 by John Arbash Meinel
Start working on a FIFOCache.
82
        self.assertEqual([4, 5, 2, 6], list(c._queue))
83
84
    def test_default_after_cleanup_count(self):
85
        c = fifo_cache.FIFOCache(5)
86
        self.assertEqual(4, c._after_cleanup_count)
87
        c[1] = 2
88
        c[2] = 3
89
        c[3] = 4
90
        c[4] = 5
91
        c[5] = 6
92
        # So far, everything fits
6656.1.1 by Martin
Apply 2to3 dict fixer and clean up resulting mess using view helpers
93
        self.assertEqual({1, 2, 3, 4, 5}, viewkeys(c))
3885.1.1 by John Arbash Meinel
Start working on a FIFOCache.
94
        c[6] = 7
95
        # But adding one more should shrink down to after_cleanup_count
6656.1.1 by Martin
Apply 2to3 dict fixer and clean up resulting mess using view helpers
96
        self.assertEqual({3, 4, 5, 6}, viewkeys(c))
3885.1.1 by John Arbash Meinel
Start working on a FIFOCache.
97
98
    def test_clear(self):
99
        c = fifo_cache.FIFOCache(5)
100
        c[1] = 2
101
        c[2] = 3
102
        c[3] = 4
103
        c[4] = 5
104
        c[5] = 6
105
        c.cleanup()
6656.1.1 by Martin
Apply 2to3 dict fixer and clean up resulting mess using view helpers
106
        self.assertEqual({2, 3, 4, 5}, viewkeys(c))
3885.1.1 by John Arbash Meinel
Start working on a FIFOCache.
107
        c.clear()
6656.1.1 by Martin
Apply 2to3 dict fixer and clean up resulting mess using view helpers
108
        self.assertEqual(set(), viewkeys(c))
3885.1.1 by John Arbash Meinel
Start working on a FIFOCache.
109
        self.assertEqual([], list(c._queue))
3885.1.4 by John Arbash Meinel
Implement setdefault.
110
        self.assertEqual({}, c)
3885.1.1 by John Arbash Meinel
Start working on a FIFOCache.
111
112
    def test_copy_not_implemented(self):
113
        c = fifo_cache.FIFOCache()
114
        self.assertRaises(NotImplementedError, c.copy)
115
116
    def test_pop_not_implemeted(self):
117
        c = fifo_cache.FIFOCache()
118
        self.assertRaises(NotImplementedError, c.pop, 'key')
119
120
    def test_popitem_not_implemeted(self):
121
        c = fifo_cache.FIFOCache()
122
        self.assertRaises(NotImplementedError, c.popitem)
123
3882.6.11 by John Arbash Meinel
comment update
124
    def test_resize_smaller(self):
125
        c = fifo_cache.FIFOCache()
126
        c[1] = 2
127
        c[2] = 3
128
        c[3] = 4
129
        c[4] = 5
130
        c[5] = 6
131
        # No cleanup, because it is the exact size
132
        c.resize(5)
133
        self.assertEqual({1: 2, 2: 3, 3: 4, 4: 5, 5: 6}, c)
134
        self.assertEqual(5, c.cache_size())
135
        # Adding one more will trigger a cleanup, though
136
        c[6] = 7
137
        self.assertEqual({3: 4, 4: 5, 5: 6, 6: 7}, c)
138
        c.resize(3, 2)
139
        self.assertEqual({5: 6, 6: 7}, c)
140
141
    def test_resize_larger(self):
142
        c = fifo_cache.FIFOCache(5, 4)
143
        c[1] = 2
144
        c[2] = 3
145
        c[3] = 4
146
        c[4] = 5
147
        c[5] = 6
148
        # No cleanup, because it is the exact size
149
        c.resize(10)
150
        self.assertEqual({1: 2, 2: 3, 3: 4, 4: 5, 5: 6}, c)
151
        self.assertEqual(10, c.cache_size())
152
        c[6] = 7
153
        c[7] = 8
154
        c[8] = 9
155
        c[9] = 10
156
        c[10] = 11
157
        self.assertEqual({1: 2, 2: 3, 3: 4, 4: 5, 5: 6, 6: 7, 7: 8, 8: 9,
158
                          9: 10, 10: 11}, c)
159
        c[11] = 12
160
        self.assertEqual({4: 5, 5: 6, 6: 7, 7: 8, 8: 9, 9: 10, 10: 11,
161
                          11: 12}, c)
162
3885.1.4 by John Arbash Meinel
Implement setdefault.
163
    def test_setdefault(self):
164
        c = fifo_cache.FIFOCache(5, 4)
165
        c['one'] = 1
166
        c['two'] = 2
167
        c['three'] = 3
168
        myobj = object()
169
        self.assertIs(myobj, c.setdefault('four', myobj))
170
        self.assertEqual({'one': 1, 'two': 2, 'three': 3, 'four': myobj}, c)
171
        self.assertEqual(3, c.setdefault('three', myobj))
172
        c.setdefault('five', myobj)
173
        c.setdefault('six', myobj)
174
        self.assertEqual({'three': 3, 'four': myobj, 'five': myobj,
175
                          'six': myobj}, c)
3885.1.1 by John Arbash Meinel
Start working on a FIFOCache.
176
3885.1.3 by John Arbash Meinel
Implement update
177
    def test_update(self):
178
        c = fifo_cache.FIFOCache(5, 4)
179
        # We allow an iterable
180
        c.update([(1, 2), (3, 4)])
181
        self.assertEqual({1: 2, 3: 4}, c)
182
        # Or kwarg form
183
        c.update(foo=3, bar=4)
184
        self.assertEqual({1: 2, 3: 4, 'foo': 3, 'bar': 4}, c)
185
        # Even a dict (This triggers a cleanup)
186
        c.update({'baz': 'biz', 'bing': 'bang'})
187
        self.assertEqual({'foo': 3, 'bar': 4, 'baz': 'biz', 'bing': 'bang'}, c)
188
        # We only allow 1 iterable, just like dict
189
        self.assertRaises(TypeError, c.update, [(1, 2)], [(3, 4)])
190
        # But you can mix and match. kwargs take precedence over iterable
191
        c.update([('a', 'b'), ('d', 'e')], a='c', q='r')
192
        self.assertEqual({'baz': 'biz', 'bing': 'bang',
193
                          'a': 'c', 'd': 'e', 'q': 'r'}, c)
3885.1.1 by John Arbash Meinel
Start working on a FIFOCache.
194
195
    def test_cleanup_funcs(self):
196
        log = []
197
        def logging_cleanup(key, value):
198
            log.append((key, value))
199
        c = fifo_cache.FIFOCache(5, 4)
200
        c.add(1, 2, cleanup=logging_cleanup)
201
        c.add(2, 3, cleanup=logging_cleanup)
202
        c.add(3, 4, cleanup=logging_cleanup)
203
        c.add(4, 5, cleanup=None) # no cleanup for 4
204
        c[5] = 6 # no cleanup for 5
205
        self.assertEqual([], log)
206
        # Adding another key should cleanup 1 & 2
3885.1.5 by John Arbash Meinel
Add tests that *adding* an entry also triggers the cleanup code.
207
        c.add(6, 7, cleanup=logging_cleanup)
3885.1.1 by John Arbash Meinel
Start working on a FIFOCache.
208
        self.assertEqual([(1, 2), (2, 3)], log)
209
        del log[:]
3885.1.5 by John Arbash Meinel
Add tests that *adding* an entry also triggers the cleanup code.
210
        # replacing 3 should trigger a cleanup
211
        c.add(3, 8, cleanup=logging_cleanup)
3885.1.1 by John Arbash Meinel
Start working on a FIFOCache.
212
        self.assertEqual([(3, 4)], log)
3885.1.5 by John Arbash Meinel
Add tests that *adding* an entry also triggers the cleanup code.
213
        del log[:]
214
        c[3] = 9
215
        self.assertEqual([(3, 8)], log)
216
        del log[:]
217
        # Clearing everything should call all remaining cleanups
218
        c.clear()
219
        self.assertEqual([(6, 7)], log)
3885.1.6 by John Arbash Meinel
Test that del x[foo] also triggers a cleanup.
220
        del log[:]
221
        c.add(8, 9, cleanup=logging_cleanup)
222
        # __delitem__ should also trigger a cleanup
223
        del c[8]
224
        self.assertEqual([(8, 9)], log)
3885.1.2 by John Arbash Meinel
Add a test which fails because we don't call cleanup funcs during deconstruction.
225
226
    def test_cleanup_at_deconstruct(self):
227
        log = []
228
        def logging_cleanup(key, value):
229
            log.append((key, value))
230
        c = fifo_cache.FIFOCache()
231
        c.add(1, 2, cleanup=logging_cleanup)
232
        del c
5967.8.2 by Martin Pool
test_fifo_cache shouldn't have a knownfailure for something that's impossible
233
        # As a matter of design, bzr does not (can not) count on anything
234
        # being run from Python __del__ methods, because they may not run for
235
        # a long time, and because in cPython merely having them defined
236
        # interferes with garbage collection.
237
        self.assertEqual([], log)
3885.1.7 by John Arbash Meinel
Add a FIFOSizeCache which is constrained based on the size of the values.
238
239
240
class TestFIFOSizeCache(tests.TestCase):
241
242
    def test_add_is_present(self):
243
        c = fifo_cache.FIFOSizeCache()
244
        c[1] = '2'
245
        self.assertTrue(1 in c)
246
        self.assertEqual(1, len(c))
247
        self.assertEqual('2', c[1])
248
        self.assertEqual('2', c.get(1))
249
        self.assertEqual('2', c.get(1, None))
6656.1.1 by Martin
Apply 2to3 dict fixer and clean up resulting mess using view helpers
250
        self.assertEqual([1], list(c))
251
        self.assertEqual({1}, viewkeys(c))
252
        self.assertEqual([(1, '2')], sorted(viewitems(c)))
253
        self.assertEqual(['2'], sorted(viewvalues(c)))
3885.1.7 by John Arbash Meinel
Add a FIFOSizeCache which is constrained based on the size of the values.
254
        self.assertEqual({1: '2'}, c)
3882.6.11 by John Arbash Meinel
comment update
255
        self.assertEqual(1024*1024, c.cache_size())
3885.1.7 by John Arbash Meinel
Add a FIFOSizeCache which is constrained based on the size of the values.
256
257
    def test_missing(self):
258
        c = fifo_cache.FIFOSizeCache()
259
        self.assertRaises(KeyError, c.__getitem__, 1)
260
        self.assertFalse(1 in c)
261
        self.assertEqual(0, len(c))
262
        self.assertEqual(None, c.get(1))
263
        self.assertEqual(None, c.get(1, None))
6656.1.1 by Martin
Apply 2to3 dict fixer and clean up resulting mess using view helpers
264
        self.assertEqual([], list(c))
265
        self.assertEqual(set(), viewkeys(c))
266
        self.assertEqual([], list(viewitems(c)))
267
        self.assertEqual([], list(viewvalues(c)))
3885.1.7 by John Arbash Meinel
Add a FIFOSizeCache which is constrained based on the size of the values.
268
        self.assertEqual({}, c)
269
270
    def test_add_maintains_fifo(self):
271
        c = fifo_cache.FIFOSizeCache(10, 8)
272
        c[1] = 'ab'
273
        c[2] = 'cde'
274
        c[3] = 'fghi'
275
        self.assertEqual({1: 'ab', 2: 'cde', 3: 'fghi'}, c)
276
        c[4] = 'jkl' # Collapse
277
        self.assertEqual({3: 'fghi', 4: 'jkl'}, c)
278
        # Replacing an item will bump it to the end of the queue
279
        c[3] = 'mnop'
280
        self.assertEqual({3: 'mnop', 4: 'jkl'}, c)
281
        c[5] = 'qrst'
282
        self.assertEqual({3: 'mnop', 5: 'qrst'}, c)
283
284
    def test_adding_large_key(self):
285
        c = fifo_cache.FIFOSizeCache(10, 8)
286
        c[1] = 'abcdefgh' # Adding a large key won't get cached at all
287
        self.assertEqual({}, c)
288
        c[1] = 'abcdefg'
289
        self.assertEqual({1: 'abcdefg'}, c)
290
        # Replacing with a too-large key will remove it
291
        c[1] = 'abcdefgh'
292
        self.assertEqual({}, c)
293
        self.assertEqual(0, c._value_size)
3882.6.11 by John Arbash Meinel
comment update
294
295
    def test_resize_smaller(self):
296
        c = fifo_cache.FIFOSizeCache(20, 16)
297
        c[1] = 'a'
298
        c[2] = 'bc'
299
        c[3] = 'def'
300
        c[4] = 'ghij'
301
        # No cleanup, because it is the exact size
302
        c.resize(10, 8)
303
        self.assertEqual({1: 'a', 2: 'bc', 3: 'def', 4: 'ghij'}, c)
304
        self.assertEqual(10, c.cache_size())
305
        # Adding one more will trigger a cleanup, though
306
        c[5] = 'k'
307
        self.assertEqual({3: 'def', 4: 'ghij', 5: 'k'}, c)
308
        c.resize(5, 4)
309
        self.assertEqual({5: 'k'}, c)
310
311
    def test_resize_larger(self):
312
        c = fifo_cache.FIFOSizeCache(10, 8)
313
        c[1] = 'a'
314
        c[2] = 'bc'
315
        c[3] = 'def'
316
        c[4] = 'ghij'
317
        c.resize(12, 10)
318
        self.assertEqual({1: 'a', 2: 'bc', 3: 'def', 4: 'ghij'}, c)
319
        c[5] = 'kl'
320
        self.assertEqual({1: 'a', 2: 'bc', 3: 'def', 4: 'ghij', 5: 'kl'}, c)
321
        c[6] = 'mn'
322
        self.assertEqual({4: 'ghij', 5: 'kl', 6: 'mn'}, c)