~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_transactions.py

  • Committer: John Arbash Meinel
  • Date: 2007-03-01 21:56:19 UTC
  • mto: (2255.7.84 dirstate)
  • mto: This revision was merged to the branch mainline in revision 2322.
  • Revision ID: john@arbash-meinel.com-20070301215619-wpt6kz8yem3ypu1b
Update to dirstate locking.
Move all of WT4.lock_* functions locally, so that they can
properly interact and cleanup around when we lock/unlock the
dirstate file.
Change all Lock objects to be non-blocking. So that if someone
grabs a lock on the DirState we find out immediately, rather
than blocking.
Change WT4.unlock() so that if the dirstate is dirty, it will
save the contents even if it only has a read lock.
It does this by trying to take a write lock, if it fails
we just ignore it. If it succeeds, then we can flush to disk.
This is more important now that DirState tracks file changes.
It allows 'bzr status' to update the cached stat and sha values.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Copyright (C) 2005 Canonical Ltd
 
2
#   Authors: Robert Collins <robert.collins@canonical.com>
 
3
#
 
4
# This program is free software; you can redistribute it and/or modify
 
5
# it under the terms of the GNU General Public License as published by
 
6
# the Free Software Foundation; either version 2 of the License, or
 
7
# (at your option) any later version.
 
8
#
 
9
# This program is distributed in the hope that it will be useful,
 
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
12
# GNU General Public License for more details.
 
13
#
 
14
# You should have received a copy of the GNU General Public License
 
15
# along with this program; if not, write to the Free Software
 
16
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
17
 
 
18
"""Tests for the behaviour of the Transaction concept in bzr."""
 
19
 
 
20
# import system imports here
 
21
import os
 
22
import sys
 
23
 
 
24
#import bzrlib specific imports here
 
25
import bzrlib.errors as errors
 
26
from bzrlib.tests import TestCase, TestCaseInTempDir
 
27
import bzrlib.transactions as transactions
 
28
 
 
29
 
 
30
class DummyWeave(object):
 
31
    """A class that can be instantiated and compared."""
 
32
 
 
33
    def __init__(self, message):
 
34
        self._message = message
 
35
        self.finished = False
 
36
 
 
37
    def __eq__(self, other):
 
38
        if other is None:
 
39
            return False
 
40
        return self._message == other._message
 
41
 
 
42
    def transaction_finished(self):
 
43
        self.finished = True
 
44
 
 
45
 
 
46
class TestSymbols(TestCase):
 
47
 
 
48
    def test_public_symbols(self):
 
49
        from bzrlib.transactions import ReadOnlyTransaction
 
50
        from bzrlib.transactions import PassThroughTransaction
 
51
 
 
52
 
 
53
class TestReadOnlyTransaction(TestCase):
 
54
 
 
55
    def setUp(self):
 
56
        self.transaction = transactions.ReadOnlyTransaction()
 
57
        super(TestReadOnlyTransaction, self).setUp()
 
58
 
 
59
    def test_register_clean(self):
 
60
        self.transaction.register_clean("anobject")
 
61
 
 
62
    def test_register_dirty_raises(self):
 
63
        self.assertRaises(errors.ReadOnlyError, 
 
64
                          self.transaction.register_dirty,"anobject")
 
65
    
 
66
    def test_map(self):
 
67
        self.assertNotEqual(None, getattr(self.transaction, "map", None))
 
68
    
 
69
    def test_add_and_get(self):
 
70
        weave = "a weave"
 
71
        self.transaction.map.add_weave("id", weave)
 
72
        self.assertEqual(weave, self.transaction.map.find_weave("id"))
 
73
 
 
74
    def test_finish_returns(self):
 
75
        self.transaction.finish()
 
76
 
 
77
    def test_finish_does_not_tell_versioned_file_finished(self):
 
78
        # read only transactions never write, so theres no
 
79
        # need to inform versioned files about finishing
 
80
        weave = DummyWeave('a weave')
 
81
        self.transaction.finish()
 
82
        self.assertFalse(weave.finished)
 
83
 
 
84
    def test_zero_size_cache(self):
 
85
        self.transaction.set_cache_size(0)
 
86
        weave = DummyWeave('a weave')
 
87
        self.transaction.map.add_weave("id", weave)
 
88
        self.assertEqual(weave, self.transaction.map.find_weave("id"))
 
89
        weave = None
 
90
        # add an object, should fall right out if there are no references
 
91
        self.transaction.register_clean(self.transaction.map.find_weave("id"))
 
92
        self.assertEqual(None, self.transaction.map.find_weave("id"))
 
93
        # but if we have a reference it should stick around
 
94
        weave = DummyWeave("another weave")
 
95
        self.transaction.map.add_weave("id", weave)
 
96
        self.transaction.register_clean(self.transaction.map.find_weave("id"))
 
97
        self.assertEqual(weave, self.transaction.map.find_weave("id"))
 
98
        del weave
 
99
        # its not a weakref system
 
100
        self.assertEqual(DummyWeave("another weave"),
 
101
                         self.transaction.map.find_weave("id"))
 
102
        
 
103
    def test_small_cache(self):
 
104
        self.transaction.set_cache_size(1)
 
105
        # add an object, should not fall right out if there are no references
 
106
        #sys.getrefcounts(foo)
 
107
        self.transaction.map.add_weave("id", DummyWeave("a weave"))
 
108
        self.transaction.register_clean(self.transaction.map.find_weave("id"))
 
109
        self.assertEqual(DummyWeave("a weave"),
 
110
                         self.transaction.map.find_weave("id"))
 
111
        self.transaction.map.add_weave("id2", DummyWeave("a weave also"))
 
112
        self.transaction.register_clean(self.transaction.map.find_weave("id2"))
 
113
        # currently a fifo
 
114
        self.assertEqual(None, self.transaction.map.find_weave("id"))
 
115
        self.assertEqual(DummyWeave("a weave also"),
 
116
                         self.transaction.map.find_weave("id2"))
 
117
 
 
118
    def test_small_cache_with_references(self):
 
119
        # if we have a reference it should stick around
 
120
        weave = "a weave"
 
121
        weave2 = "another weave"
 
122
        self.transaction.map.add_weave("id", weave)
 
123
        self.transaction.map.add_weave("id2", weave2)
 
124
        self.assertEqual(weave, self.transaction.map.find_weave("id"))
 
125
        self.assertEqual(weave2, self.transaction.map.find_weave("id2"))
 
126
        weave = None
 
127
        # its not a weakref system
 
128
        self.assertEqual("a weave", self.transaction.map.find_weave("id"))
 
129
 
 
130
    def test_precious_with_zero_size_cache(self):
 
131
        self.transaction.set_cache_size(0)
 
132
        weave = DummyWeave('a weave')
 
133
        self.transaction.map.add_weave("id", weave)
 
134
        self.assertEqual(weave, self.transaction.map.find_weave("id"))
 
135
        weave = None
 
136
        # add an object, should not fall out even with no references.
 
137
        self.transaction.register_clean(self.transaction.map.find_weave("id"),
 
138
                                        precious=True)
 
139
        self.assertEqual(DummyWeave('a weave'),
 
140
                         self.transaction.map.find_weave("id"))
 
141
 
 
142
    def test_writable(self):
 
143
        self.assertFalse(self.transaction.writeable())
 
144
 
 
145
 
 
146
class TestPassThroughTransaction(TestCase):
 
147
 
 
148
    def test_construct(self):
 
149
        transactions.PassThroughTransaction()
 
150
 
 
151
    def test_register_clean(self):
 
152
        transaction = transactions.PassThroughTransaction()
 
153
        transaction.register_clean("anobject")
 
154
    
 
155
    def test_register_dirty(self):
 
156
        transaction = transactions.PassThroughTransaction()
 
157
        transaction.register_dirty("anobject")
 
158
    
 
159
    def test_map(self):
 
160
        transaction = transactions.PassThroughTransaction()
 
161
        self.assertNotEqual(None, getattr(transaction, "map", None))
 
162
    
 
163
    def test_add_and_get(self):
 
164
        transaction = transactions.PassThroughTransaction()
 
165
        weave = "a weave"
 
166
        transaction.map.add_weave("id", weave)
 
167
        self.assertEqual(None, transaction.map.find_weave("id"))
 
168
        
 
169
    def test_finish_returns(self):
 
170
        transaction = transactions.PassThroughTransaction()
 
171
        transaction.finish()
 
172
 
 
173
    def test_finish_tells_versioned_file_finished(self):
 
174
        # pass through transactions allow writes so they
 
175
        # need to inform versioned files about finishing
 
176
        weave = DummyWeave('a weave')
 
177
        transaction = transactions.PassThroughTransaction()
 
178
        transaction.register_dirty(weave)
 
179
        transaction.finish()
 
180
        self.assertTrue(weave.finished)
 
181
 
 
182
    def test_cache_is_ignored(self):
 
183
        transaction = transactions.PassThroughTransaction()
 
184
        transaction.set_cache_size(100)
 
185
        weave = "a weave"
 
186
        transaction.map.add_weave("id", weave)
 
187
        self.assertEqual(None, transaction.map.find_weave("id"))
 
188
 
 
189
    def test_writable(self):
 
190
        transaction = transactions.PassThroughTransaction()
 
191
        self.assertTrue(transaction.writeable())
 
192
        
 
193
 
 
194
class TestWriteTransaction(TestCase):
 
195
 
 
196
    def setUp(self):
 
197
        self.transaction = transactions.WriteTransaction()
 
198
        super(TestWriteTransaction, self).setUp()
 
199
 
 
200
    def test_register_clean(self):
 
201
        self.transaction.register_clean("anobject")
 
202
    
 
203
    def test_register_dirty(self):
 
204
        self.transaction.register_dirty("anobject")
 
205
    
 
206
    def test_map(self):
 
207
        self.assertNotEqual(None, getattr(self.transaction, "map", None))
 
208
    
 
209
    def test_add_and_get(self):
 
210
        weave = "a weave"
 
211
        self.transaction.map.add_weave("id", weave)
 
212
        self.assertEqual(weave, self.transaction.map.find_weave("id"))
 
213
        
 
214
    def test_finish_returns(self):
 
215
        self.transaction.finish()
 
216
 
 
217
    def test_finish_tells_versioned_file_finished(self):
 
218
        # write transactions allow writes so they
 
219
        # need to inform versioned files about finishing
 
220
        weave = DummyWeave('a weave')
 
221
        self.transaction.register_dirty(weave)
 
222
        self.transaction.finish()
 
223
        self.assertTrue(weave.finished)
 
224
 
 
225
    def test_zero_size_cache(self):
 
226
        self.transaction.set_cache_size(0)
 
227
        # add an object, should fall right out if there are no references
 
228
        weave = DummyWeave('a weave')
 
229
        self.transaction.map.add_weave("id", weave)
 
230
        self.assertEqual(weave, self.transaction.map.find_weave("id"))
 
231
        weave = None
 
232
        self.transaction.register_clean(self.transaction.map.find_weave("id"))
 
233
        self.assertEqual(None, self.transaction.map.find_weave("id"))
 
234
        # but if we have a reference to a clean object it should stick around
 
235
        weave = DummyWeave("another weave")
 
236
        self.transaction.map.add_weave("id", weave)
 
237
        self.transaction.register_clean(self.transaction.map.find_weave("id"))
 
238
        self.assertEqual(weave, self.transaction.map.find_weave("id"))
 
239
        del weave
 
240
        # its not a weakref system
 
241
        self.assertEqual(DummyWeave("another weave"),
 
242
                         self.transaction.map.find_weave("id"))
 
243
 
 
244
    def test_zero_size_cache_dirty_objects(self):
 
245
        self.transaction.set_cache_size(0)
 
246
        # add a dirty object, which should not fall right out.
 
247
        weave = DummyWeave('a weave')
 
248
        self.transaction.map.add_weave("id", weave)
 
249
        self.assertEqual(weave, self.transaction.map.find_weave("id"))
 
250
        weave = None
 
251
        self.transaction.register_dirty(self.transaction.map.find_weave("id"))
 
252
        self.assertNotEqual(None, self.transaction.map.find_weave("id"))
 
253
    
 
254
    def test_clean_to_dirty(self):
 
255
        # a clean object may become dirty.
 
256
        weave = DummyWeave('A weave')
 
257
        self.transaction.map.add_weave("id", weave)
 
258
        self.transaction.register_clean(weave)
 
259
        self.transaction.register_dirty(weave)
 
260
        self.assertTrue(self.transaction.is_dirty(weave))
 
261
        self.assertFalse(self.transaction.is_clean(weave))
 
262
 
 
263
    def test_small_cache(self):
 
264
        self.transaction.set_cache_size(1)
 
265
        # add an object, should not fall right out if there are no references
 
266
        #sys.getrefcounts(foo)
 
267
        self.transaction.map.add_weave("id", DummyWeave("a weave"))
 
268
        self.transaction.register_clean(self.transaction.map.find_weave("id"))
 
269
        self.assertEqual(DummyWeave("a weave"),
 
270
                         self.transaction.map.find_weave("id"))
 
271
        self.transaction.map.add_weave("id2", DummyWeave("a weave also"))
 
272
        self.transaction.register_clean(self.transaction.map.find_weave("id2"))
 
273
        # currently a fifo
 
274
        self.assertEqual(None, self.transaction.map.find_weave("id"))
 
275
        self.assertEqual(DummyWeave("a weave also"),
 
276
                         self.transaction.map.find_weave("id2"))
 
277
 
 
278
    def test_small_cache_with_references(self):
 
279
        # if we have a reference it should stick around
 
280
        weave = "a weave"
 
281
        weave2 = "another weave"
 
282
        self.transaction.map.add_weave("id", weave)
 
283
        self.transaction.map.add_weave("id2", weave2)
 
284
        self.assertEqual(weave, self.transaction.map.find_weave("id"))
 
285
        self.assertEqual(weave2, self.transaction.map.find_weave("id2"))
 
286
        weave = None
 
287
        # its not a weakref system
 
288
        self.assertEqual("a weave", self.transaction.map.find_weave("id"))
 
289
 
 
290
    def test_precious_with_zero_size_cache(self):
 
291
        self.transaction.set_cache_size(0)
 
292
        weave = DummyWeave('a weave')
 
293
        self.transaction.map.add_weave("id", weave)
 
294
        self.assertEqual(weave, self.transaction.map.find_weave("id"))
 
295
        weave = None
 
296
        # add an object, should not fall out even with no references.
 
297
        self.transaction.register_clean(self.transaction.map.find_weave("id"),
 
298
                                        precious=True)
 
299
        self.assertEqual(DummyWeave('a weave'),
 
300
                         self.transaction.map.find_weave("id"))
 
301
 
 
302
    def test_writable(self):
 
303
        self.assertTrue(self.transaction.writeable())