~bzr-pqm/bzr/bzr.dev

5557.1.15 by John Arbash Meinel
Merge bzr.dev 5597 to resolve NEWS, aka bzr-2.3.txt
1
# Copyright (C) 2005-2009, 2011 Canonical Ltd
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
2
#
846 by Martin Pool
- start adding refactored/simplified hash cache
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.
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
7
#
846 by Martin Pool
- start adding refactored/simplified hash cache
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.
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
12
#
846 by Martin Pool
- start adding refactored/simplified hash cache
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
846 by Martin Pool
- start adding refactored/simplified hash cache
16
1185.1.40 by Robert Collins
Merge what applied of Alexander Belchenko's win32 patch.
17
import os
1845.1.3 by Martin Pool
Improvements to hashcache testing:
18
import stat
1185.1.40 by Robert Collins
Merge what applied of Alexander Belchenko's win32 patch.
19
import time
1534.4.51 by Robert Collins
Test the disk layout of format3 working trees.
20
2929.3.1 by Vincent Ladeuil
Fix python2.6 deprecation warnings (still 4 failures 5 errors in test suite).
21
from bzrlib import osutils
1534.4.51 by Robert Collins
Test the disk layout of format3 working trees.
22
from bzrlib.errors import BzrError
23
from bzrlib.hashcache import HashCache
5579.3.1 by Jelmer Vernooij
Remove unused imports.
24
from bzrlib.tests import (
25
    OsFifoFeature,
26
    TestCaseInTempDir,
27
    )
846 by Martin Pool
- start adding refactored/simplified hash cache
28
29
30
def sha1(t):
2929.3.1 by Vincent Ladeuil
Fix python2.6 deprecation warnings (still 4 failures 5 errors in test suite).
31
    return osutils.sha(t).hexdigest()
846 by Martin Pool
- start adding refactored/simplified hash cache
32
33
34
def pause():
1845.1.2 by mbp at sourcefrog
Use larger time window on hashcache to be safe with fractional times
35
    time.sleep(5.0)
1185.33.109 by Denys Duchier
test_hashcache: catch no exceptions
36
37
1141 by Martin Pool
- rename FunctionalTest to TestCaseInTempDir
38
class TestHashCache(TestCaseInTempDir):
1845.1.3 by Martin Pool
Improvements to hashcache testing:
39
    """Test the hashcache against a real directory"""
1102 by Martin Pool
- merge test refactoring from robertc
40
1845.1.1 by mbp at sourcefrog
Refactor and improve hashcache tests
41
    def make_hashcache(self):
866 by Martin Pool
- use new path-based hashcache for WorkingTree- squash mtime/ctime to whole seconds- update and if necessary write out hashcache when WorkingTree object is created.
42
        # make a dummy bzr directory just to hold the cache
43
        os.mkdir('.bzr')
1534.4.51 by Robert Collins
Test the disk layout of format3 working trees.
44
        hc = HashCache('.', '.bzr/stat-cache')
1845.1.1 by mbp at sourcefrog
Refactor and improve hashcache tests
45
        return hc
46
47
    def reopen_hashcache(self):
48
        hc = HashCache('.', '.bzr/stat-cache')
49
        hc.read()
50
        return hc
51
52
    def test_hashcache_initial_miss(self):
53
        """Get correct hash from an empty hashcache"""
54
        hc = self.make_hashcache()
55
        self.build_tree_contents([('foo', 'hello')])
56
        self.assertEquals(hc.get_sha1('foo'),
57
                          'aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d')
58
        self.assertEquals(hc.miss_count, 1)
59
        self.assertEquals(hc.hit_count, 0)
60
61
    def test_hashcache_new_file(self):
62
        hc = self.make_hashcache()
63
        self.build_tree_contents([('foo', 'goodbye')])
64
        # now read without pausing; it may not be possible to cache it as its
65
        # so new
66
        self.assertEquals(hc.get_sha1('foo'), sha1('goodbye'))
67
68
    def test_hashcache_nonexistent_file(self):
69
        hc = self.make_hashcache()
70
        self.assertEquals(hc.get_sha1('no-name-yet'), None)
71
72
    def test_hashcache_replaced_file(self):
73
        hc = self.make_hashcache()
74
        self.build_tree_contents([('foo', 'goodbye')])
75
        self.assertEquals(hc.get_sha1('foo'), sha1('goodbye'))
76
        os.remove('foo')
77
        self.assertEquals(hc.get_sha1('foo'), None)
78
        self.build_tree_contents([('foo', 'new content')])
79
        self.assertEquals(hc.get_sha1('foo'), sha1('new content'))
80
81
    def test_hashcache_not_file(self):
82
        hc = self.make_hashcache()
83
        self.build_tree(['subdir/'])
846 by Martin Pool
- start adding refactored/simplified hash cache
84
        self.assertEquals(hc.get_sha1('subdir'), None)
848 by Martin Pool
doc
85
1845.1.1 by mbp at sourcefrog
Refactor and improve hashcache tests
86
    def test_hashcache_load(self):
87
        hc = self.make_hashcache()
88
        self.build_tree_contents([('foo', 'contents')])
861 by Martin Pool
- more hash-cache tests
89
        pause()
1845.1.1 by mbp at sourcefrog
Refactor and improve hashcache tests
90
        self.assertEquals(hc.get_sha1('foo'), sha1('contents'))
866 by Martin Pool
- use new path-based hashcache for WorkingTree- squash mtime/ctime to whole seconds- update and if necessary write out hashcache when WorkingTree object is created.
91
        hc.write()
1845.1.1 by mbp at sourcefrog
Refactor and improve hashcache tests
92
        hc = self.reopen_hashcache()
93
        self.assertEquals(hc.get_sha1('foo'), sha1('contents'))
1185.60.5 by Aaron Bentley
Reactivated hashcache tests
94
        self.assertEquals(hc.hit_count, 1)
1845.1.1 by mbp at sourcefrog
Refactor and improve hashcache tests
95
96
    def test_hammer_hashcache(self):
97
        hc = self.make_hashcache()
1845.1.2 by mbp at sourcefrog
Use larger time window on hashcache to be safe with fractional times
98
        for i in xrange(10000):
99
            self.log('start writing at %s', time.time())
1845.1.1 by mbp at sourcefrog
Refactor and improve hashcache tests
100
            f = file('foo', 'w')
101
            try:
102
                last_content = '%08x' % i
103
                f.write(last_content)
104
            finally:
105
                f.close()
1845.1.2 by mbp at sourcefrog
Use larger time window on hashcache to be safe with fractional times
106
            last_sha1 = sha1(last_content)
107
            self.log("iteration %d: %r -> %r",
108
                     i, last_content, last_sha1)
109
            got_sha1 = hc.get_sha1('foo')
110
            self.assertEquals(got_sha1, last_sha1)
1845.1.1 by mbp at sourcefrog
Refactor and improve hashcache tests
111
            hc.write()
112
            hc = self.reopen_hashcache()
1185.33.106 by Denys Duchier
check that hashcache can raise BzrError
113
114
    def test_hashcache_raise(self):
115
        """check that hashcache can raise BzrError"""
2949.5.2 by Alexander Belchenko
John's review
116
        self.requireFeature(OsFifoFeature)
1845.1.1 by mbp at sourcefrog
Refactor and improve hashcache tests
117
        hc = self.make_hashcache()
1845.1.2 by mbp at sourcefrog
Use larger time window on hashcache to be safe with fractional times
118
        os.mkfifo('a')
119
        # It's possible that the system supports fifos but the filesystem
120
        # can't.  In that case we should skip at this point.  But in fact
121
        # such combinations don't usually occur for the filesystem where
122
        # people test bzr.
123
        self.assertRaises(BzrError, hc.get_sha1, 'a')
1845.1.3 by Martin Pool
Improvements to hashcache testing:
124
125
126
class FakeHashCache(HashCache):
127
    """Hashcache that consults a fake clock rather than the real one.
128
129
    This lets us examine how old or new files would be handled, without
130
    actually having to wait for time to pass.
131
    """
132
    def __init__(self):
133
        # set root and cache file name to none to make sure we won't touch the
134
        # real filesystem
135
        HashCache.__init__(self, '.', 'hashcache')
136
        self._files = {}
137
        # simulated clock running forward as operations happen
138
        self._clock = 0
139
140
    def put_file(self, filename, file_contents):
141
        abspath = './' + filename
142
        self._files[abspath] = (file_contents, self._clock)
143
2012.1.7 by Aaron Bentley
Get tree._iter_changed down to ~ 1 stat per file
144
    def _fingerprint(self, abspath, fs=None):
1845.1.3 by Martin Pool
Improvements to hashcache testing:
145
        entry = self._files[abspath]
146
        return (len(entry[0]),
147
                entry[1], entry[1],
148
                10, 20,
149
                stat.S_IFREG | 0600)
150
3368.2.4 by Ian Clatworthy
make content filter lookup a tree responsibility
151
    def _really_sha1_file(self, abspath, filters):
1845.1.3 by Martin Pool
Improvements to hashcache testing:
152
        if abspath in self._files:
153
            return sha1(self._files[abspath][0])
154
        else:
155
            return None
156
157
    def _cutoff_time(self):
158
        return self._clock - 2
159
160
    def pretend_to_sleep(self, secs):
161
        self._clock += secs
162
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
163
1845.1.3 by Martin Pool
Improvements to hashcache testing:
164
class TestHashCacheFakeFilesystem(TestCaseInTempDir):
165
    """Tests the hashcache using a simulated OS.
166
    """
167
168
    def make_hashcache(self):
169
        return FakeHashCache()
170
171
    def test_hashcache_miss_new_file(self):
172
        """A new file gives the right sha1 but misses"""
173
        hc = self.make_hashcache()
174
        hc.put_file('foo', 'hello')
175
        self.assertEquals(hc.get_sha1('foo'), sha1('hello'))
176
        self.assertEquals(hc.miss_count, 1)
177
        self.assertEquals(hc.hit_count, 0)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
178
        # if we try again it's still too new;
1845.1.3 by Martin Pool
Improvements to hashcache testing:
179
        self.assertEquals(hc.get_sha1('foo'), sha1('hello'))
180
        self.assertEquals(hc.miss_count, 2)
181
        self.assertEquals(hc.hit_count, 0)
182
183
    def test_hashcache_old_file(self):
184
        """An old file gives the right sha1 and hits"""
185
        hc = self.make_hashcache()
186
        hc.put_file('foo', 'hello')
187
        hc.pretend_to_sleep(20)
188
        # file is new; should get the correct hash but miss
189
        self.assertEquals(hc.get_sha1('foo'), sha1('hello'))
190
        self.assertEquals(hc.miss_count, 1)
191
        self.assertEquals(hc.hit_count, 0)
192
        # and can now be hit
193
        self.assertEquals(hc.get_sha1('foo'), sha1('hello'))
194
        self.assertEquals(hc.miss_count, 1)
195
        self.assertEquals(hc.hit_count, 1)
196
        hc.pretend_to_sleep(3)
197
        # and again
198
        self.assertEquals(hc.get_sha1('foo'), sha1('hello'))
199
        self.assertEquals(hc.miss_count, 1)
200
        self.assertEquals(hc.hit_count, 2)
201
202
    def test_hashcache_invalidates(self):
203
        hc = self.make_hashcache()
204
        hc.put_file('foo', 'hello')
205
        hc.pretend_to_sleep(20)
206
        hc.get_sha1('foo')
207
        hc.put_file('foo', 'h1llo')
208
        self.assertEquals(hc.get_sha1('foo'), sha1('h1llo'))
209
        self.assertEquals(hc.miss_count, 2)
210
        self.assertEquals(hc.hit_count, 0)