~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_hashcache.py

  • Committer: Martin Pool
  • Date: 2006-07-12 05:22:48 UTC
  • mto: This revision was merged to the branch mainline in revision 1856.
  • Revision ID: mbp@sourcefrog.net-20060712052248-789ab09214cf9fef
      Improvements to hashcache testing:
      
       - moves the functions that depend on the OS state into HashCache
       - removes dead 'FixThisError' (??) from test_hashcache
       - adds new FakeHashCache, which gives the test suite control of
         how the files and clock appear to the hashcache
       - new tests using this which check three key behaviours:
         - new files are not inserted in the cache
         - old files are inserted in the cache and can hit
         - if a file is modified within a short time window, we don't get
           an incorrect cached result

Show diffs side-by-side

added added

removed removed

Lines of Context:
16
16
 
17
17
import os
18
18
import sha
 
19
import stat
19
20
import sys
20
21
import time
21
22
 
22
23
from bzrlib.errors import BzrError
23
24
from bzrlib.hashcache import HashCache
24
 
from bzrlib.tests import TestCaseInTempDir, TestSkipped
 
25
from bzrlib.tests import TestCaseInTempDir, TestSkipped, TestCase
25
26
 
26
27
 
27
28
def sha1(t):
32
33
    time.sleep(5.0)
33
34
 
34
35
 
35
 
class FixThisError(Exception):
36
 
    pass
37
 
    
38
 
 
39
36
class TestHashCache(TestCaseInTempDir):
 
37
    """Test the hashcache against a real directory"""
40
38
 
41
39
    def make_hashcache(self):
42
40
        # make a dummy bzr directory just to hold the cache
58
56
        self.assertEquals(hc.miss_count, 1)
59
57
        self.assertEquals(hc.hit_count, 0)
60
58
 
61
 
    def test_hashcache_hit_old_file(self):
62
 
        """An old file gives a cache hit"""
63
 
        return ### this takes too long to run properly; skipped
64
 
        hc = self.make_hashcache()
65
 
        self.build_tree_contents([('foo', 'hello')])
66
 
        pause() # make sure file's old enough to cache
67
 
        self.assertEquals(hc.get_sha1('foo'),
68
 
                          'aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d')
69
 
        self.assertEquals(hc.miss_count, 1)
70
 
        self.assertEquals(hc.hit_count, 0)
71
 
        # now should hit on second try
72
 
        self.assertEquals(hc.get_sha1('foo'),
73
 
                          'aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d')
74
 
        self.assertEquals(hc.miss_count, 1)
75
 
        self.assertEquals(hc.hit_count, 1)
76
 
        # and hit again on third try
77
 
        self.assertEquals(hc.get_sha1('foo'),
78
 
                          'aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d')
79
 
        self.assertEquals(hc.miss_count, 1)
80
 
        self.assertEquals(hc.hit_count, 2)
81
 
 
82
59
    def test_hashcache_new_file(self):
83
60
        hc = self.make_hashcache()
84
61
        self.build_tree_contents([('foo', 'goodbye')])
143
120
        # such combinations don't usually occur for the filesystem where
144
121
        # people test bzr.
145
122
        self.assertRaises(BzrError, hc.get_sha1, 'a')
 
123
 
 
124
 
 
125
class FakeHashCache(HashCache):
 
126
    """Hashcache that consults a fake clock rather than the real one.
 
127
 
 
128
    This lets us examine how old or new files would be handled, without
 
129
    actually having to wait for time to pass.
 
130
    """
 
131
    def __init__(self):
 
132
        # set root and cache file name to none to make sure we won't touch the
 
133
        # real filesystem
 
134
        HashCache.__init__(self, '.', 'hashcache')
 
135
        self._files = {}
 
136
        # simulated clock running forward as operations happen
 
137
        self._clock = 0
 
138
 
 
139
    def put_file(self, filename, file_contents):
 
140
        abspath = './' + filename
 
141
        self._files[abspath] = (file_contents, self._clock)
 
142
 
 
143
    def _fingerprint(self, abspath):
 
144
        entry = self._files[abspath]
 
145
        return (len(entry[0]),
 
146
                entry[1], entry[1],
 
147
                10, 20,
 
148
                stat.S_IFREG | 0600)
 
149
 
 
150
    def _really_sha1_file(self, abspath):
 
151
        if abspath in self._files:
 
152
            return sha1(self._files[abspath][0])
 
153
        else:
 
154
            return None
 
155
 
 
156
    def _cutoff_time(self):
 
157
        return self._clock - 2
 
158
 
 
159
    def pretend_to_sleep(self, secs):
 
160
        self._clock += secs
 
161
 
 
162
    
 
163
class TestHashCacheFakeFilesystem(TestCaseInTempDir):
 
164
    """Tests the hashcache using a simulated OS.
 
165
    """
 
166
 
 
167
    def make_hashcache(self):
 
168
        return FakeHashCache()
 
169
 
 
170
    def test_hashcache_miss_new_file(self):
 
171
        """A new file gives the right sha1 but misses"""
 
172
        hc = self.make_hashcache()
 
173
        hc.put_file('foo', 'hello')
 
174
        self.assertEquals(hc.get_sha1('foo'), sha1('hello'))
 
175
        self.assertEquals(hc.miss_count, 1)
 
176
        self.assertEquals(hc.hit_count, 0)
 
177
        # if we try again it's still too new; 
 
178
        self.assertEquals(hc.get_sha1('foo'), sha1('hello'))
 
179
        self.assertEquals(hc.miss_count, 2)
 
180
        self.assertEquals(hc.hit_count, 0)
 
181
 
 
182
    def test_hashcache_old_file(self):
 
183
        """An old file gives the right sha1 and hits"""
 
184
        hc = self.make_hashcache()
 
185
        hc.put_file('foo', 'hello')
 
186
        hc.pretend_to_sleep(20)
 
187
        # file is new; should get the correct hash but miss
 
188
        self.assertEquals(hc.get_sha1('foo'), sha1('hello'))
 
189
        self.assertEquals(hc.miss_count, 1)
 
190
        self.assertEquals(hc.hit_count, 0)
 
191
        # and can now be hit
 
192
        self.assertEquals(hc.get_sha1('foo'), sha1('hello'))
 
193
        self.assertEquals(hc.miss_count, 1)
 
194
        self.assertEquals(hc.hit_count, 1)
 
195
        hc.pretend_to_sleep(3)
 
196
        # and again
 
197
        self.assertEquals(hc.get_sha1('foo'), sha1('hello'))
 
198
        self.assertEquals(hc.miss_count, 1)
 
199
        self.assertEquals(hc.hit_count, 2)
 
200
 
 
201
    def test_hashcache_invalidates(self):
 
202
        hc = self.make_hashcache()
 
203
        hc.put_file('foo', 'hello')
 
204
        hc.pretend_to_sleep(20)
 
205
        hc.get_sha1('foo')
 
206
        hc.put_file('foo', 'h1llo')
 
207
        self.assertEquals(hc.get_sha1('foo'), sha1('h1llo'))
 
208
        self.assertEquals(hc.miss_count, 2)
 
209
        self.assertEquals(hc.hit_count, 0)