~bzr-pqm/bzr/bzr.dev

1417.1.6 by Robert Collins
introduce transactions for grouping actions done to and with branches
1
# Copyright (C) 2005 by 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
1185.31.25 by John Arbash Meinel
Renamed all of the tests from selftest/foo.py to tests/test_foo.py
26
from bzrlib.tests import TestCase, TestCaseInTempDir
1417.1.6 by Robert Collins
introduce transactions for grouping actions done to and with branches
27
import bzrlib.transactions as transactions
28
29
1417.1.10 by Robert Collins
add a cache bound to Transactions, and a precious facility, so that we keep inventory.weave in memory, but can discard weaves for other such files.
30
class DummyWeave(object):
31
    """A class that can be instantiated and compared."""
32
33
    def __init__(self, message):
34
        self._message = message
1594.2.20 by Robert Collins
Add finished() notifications to transactions.
35
        self.finished = False
1417.1.10 by Robert Collins
add a cache bound to Transactions, and a precious facility, so that we keep inventory.weave in memory, but can discard weaves for other such files.
36
37
    def __eq__(self, other):
38
        if other is None:
39
            return False
40
        return self._message == other._message
41
1594.2.20 by Robert Collins
Add finished() notifications to transactions.
42
    def transaction_finished(self):
43
        self.finished = True
44
1417.1.10 by Robert Collins
add a cache bound to Transactions, and a precious facility, so that we keep inventory.weave in memory, but can discard weaves for other such files.
45
46
class TestSymbols(TestCase):
47
1417.1.12 by Robert Collins
cache revision history during read transactions
48
    def test_public_symbols(self):
1417.1.10 by Robert Collins
add a cache bound to Transactions, and a precious facility, so that we keep inventory.weave in memory, but can discard weaves for other such files.
49
        from bzrlib.transactions import ReadOnlyTransaction
50
        from bzrlib.transactions import PassThroughTransaction
51
52
1417.1.6 by Robert Collins
introduce transactions for grouping actions done to and with branches
53
class TestReadOnlyTransaction(TestCase):
54
1417.1.10 by Robert Collins
add a cache bound to Transactions, and a precious facility, so that we keep inventory.weave in memory, but can discard weaves for other such files.
55
    def setUp(self):
56
        self.transaction = transactions.ReadOnlyTransaction()
57
        super(TestReadOnlyTransaction, self).setUp()
1417.1.6 by Robert Collins
introduce transactions for grouping actions done to and with branches
58
59
    def test_register_clean(self):
1417.1.10 by Robert Collins
add a cache bound to Transactions, and a precious facility, so that we keep inventory.weave in memory, but can discard weaves for other such files.
60
        self.transaction.register_clean("anobject")
1417.1.8 by Robert Collins
use transactions in the weave store interface, which enables caching for log
61
62
    def test_register_dirty_raises(self):
63
        self.assertRaises(errors.ReadOnlyError, 
1417.1.10 by Robert Collins
add a cache bound to Transactions, and a precious facility, so that we keep inventory.weave in memory, but can discard weaves for other such files.
64
                          self.transaction.register_dirty,"anobject")
1417.1.6 by Robert Collins
introduce transactions for grouping actions done to and with branches
65
    
66
    def test_map(self):
1417.1.10 by Robert Collins
add a cache bound to Transactions, and a precious facility, so that we keep inventory.weave in memory, but can discard weaves for other such files.
67
        self.assertNotEqual(None, getattr(self.transaction, "map", None))
1417.1.6 by Robert Collins
introduce transactions for grouping actions done to and with branches
68
    
69
    def test_add_and_get(self):
70
        weave = "a weave"
1417.1.10 by Robert Collins
add a cache bound to Transactions, and a precious facility, so that we keep inventory.weave in memory, but can discard weaves for other such files.
71
        self.transaction.map.add_weave("id", weave)
72
        self.assertEqual(weave, self.transaction.map.find_weave("id"))
1417.1.6 by Robert Collins
introduce transactions for grouping actions done to and with branches
73
74
    def test_finish_returns(self):
1417.1.10 by Robert Collins
add a cache bound to Transactions, and a precious facility, so that we keep inventory.weave in memory, but can discard weaves for other such files.
75
        self.transaction.finish()
1417.1.6 by Robert Collins
introduce transactions for grouping actions done to and with branches
76
1594.2.20 by Robert Collins
Add finished() notifications to transactions.
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
1417.1.10 by Robert Collins
add a cache bound to Transactions, and a precious facility, so that we keep inventory.weave in memory, but can discard weaves for other such files.
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"))
1417.1.6 by Robert Collins
introduce transactions for grouping actions done to and with branches
102
        
1417.1.10 by Robert Collins
add a cache bound to Transactions, and a precious facility, so that we keep inventory.weave in memory, but can discard weaves for other such files.
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
1417.1.12 by Robert Collins
cache revision history during read transactions
142
    def test_precious_revision_history(self):
143
        """Disabled test until revision-history is a real object."""
144
        print "Disabled: test_precious_revision_history"
145
        return
146
        self.transaction.set_cache_size(0)
147
        history = []
148
        self.transaction.map.add_revision_history(history)
149
        self.assertEqual(history, self.transaction.map.find_revision_history())
150
        history = None
151
        # add an object, should not fall out even with no references.
152
        self.transaction.register_clean(
153
            self.transaction.map.find_revision_history(), precious=True)
154
        self.assertEqual([], self.transaction.map.find_revision_history())
155
1594.2.20 by Robert Collins
Add finished() notifications to transactions.
156
    def test_writable(self):
157
        self.assertFalse(self.transaction.writeable())
158
1417.1.10 by Robert Collins
add a cache bound to Transactions, and a precious facility, so that we keep inventory.weave in memory, but can discard weaves for other such files.
159
1417.1.6 by Robert Collins
introduce transactions for grouping actions done to and with branches
160
class TestPassThroughTransaction(TestCase):
161
162
    def test_construct(self):
163
        transactions.PassThroughTransaction()
164
165
    def test_register_clean(self):
166
        transaction = transactions.PassThroughTransaction()
167
        transaction.register_clean("anobject")
168
    
1417.1.8 by Robert Collins
use transactions in the weave store interface, which enables caching for log
169
    def test_register_dirty(self):
170
        transaction = transactions.PassThroughTransaction()
171
        transaction.register_dirty("anobject")
172
    
1417.1.6 by Robert Collins
introduce transactions for grouping actions done to and with branches
173
    def test_map(self):
174
        transaction = transactions.PassThroughTransaction()
175
        self.assertNotEqual(None, getattr(transaction, "map", None))
176
    
177
    def test_add_and_get(self):
178
        transaction = transactions.PassThroughTransaction()
179
        weave = "a weave"
180
        transaction.map.add_weave("id", weave)
181
        self.assertEqual(None, transaction.map.find_weave("id"))
182
        
183
    def test_finish_returns(self):
184
        transaction = transactions.PassThroughTransaction()
185
        transaction.finish()
1417.1.10 by Robert Collins
add a cache bound to Transactions, and a precious facility, so that we keep inventory.weave in memory, but can discard weaves for other such files.
186
1594.2.20 by Robert Collins
Add finished() notifications to transactions.
187
    def test_finish_tells_versioned_file_finished(self):
188
        # pass through transactions allow writes so they
189
        # need to inform versioned files about finishing
190
        weave = DummyWeave('a weave')
191
        transaction = transactions.PassThroughTransaction()
192
        transaction.register_dirty(weave)
193
        transaction.finish()
194
        self.assertTrue(weave.finished)
195
1417.1.10 by Robert Collins
add a cache bound to Transactions, and a precious facility, so that we keep inventory.weave in memory, but can discard weaves for other such files.
196
    def test_cache_is_ignored(self):
197
        transaction = transactions.PassThroughTransaction()
198
        transaction.set_cache_size(100)
199
        weave = "a weave"
200
        transaction.map.add_weave("id", weave)
201
        self.assertEqual(None, transaction.map.find_weave("id"))
1563.2.34 by Robert Collins
Remove the commit and rollback transaction methods as misleading, and implement a WriteTransaction
202
1594.2.20 by Robert Collins
Add finished() notifications to transactions.
203
    def test_writable(self):
204
        transaction = transactions.PassThroughTransaction()
205
        self.assertTrue(transaction.writeable())
1563.2.34 by Robert Collins
Remove the commit and rollback transaction methods as misleading, and implement a WriteTransaction
206
        
1594.2.20 by Robert Collins
Add finished() notifications to transactions.
207
1563.2.34 by Robert Collins
Remove the commit and rollback transaction methods as misleading, and implement a WriteTransaction
208
class TestWriteTransaction(TestCase):
209
210
    def setUp(self):
211
        self.transaction = transactions.WriteTransaction()
212
        super(TestWriteTransaction, self).setUp()
213
214
    def test_register_clean(self):
215
        self.transaction.register_clean("anobject")
216
    
217
    def test_register_dirty(self):
218
        self.transaction.register_dirty("anobject")
219
    
220
    def test_map(self):
221
        self.assertNotEqual(None, getattr(self.transaction, "map", None))
222
    
223
    def test_add_and_get(self):
224
        weave = "a weave"
225
        self.transaction.map.add_weave("id", weave)
226
        self.assertEqual(weave, self.transaction.map.find_weave("id"))
227
        
228
    def test_finish_returns(self):
229
        self.transaction.finish()
230
1594.2.20 by Robert Collins
Add finished() notifications to transactions.
231
    def test_finish_tells_versioned_file_finished(self):
232
        # write transactions allow writes so they
233
        # need to inform versioned files about finishing
234
        weave = DummyWeave('a weave')
235
        self.transaction.register_dirty(weave)
236
        self.transaction.finish()
237
        self.assertTrue(weave.finished)
238
1563.2.34 by Robert Collins
Remove the commit and rollback transaction methods as misleading, and implement a WriteTransaction
239
    def test_zero_size_cache(self):
240
        self.transaction.set_cache_size(0)
241
        # add an object, should fall right out if there are no references
242
        weave = DummyWeave('a weave')
243
        self.transaction.map.add_weave("id", weave)
244
        self.assertEqual(weave, self.transaction.map.find_weave("id"))
245
        weave = None
246
        self.transaction.register_clean(self.transaction.map.find_weave("id"))
247
        self.assertEqual(None, self.transaction.map.find_weave("id"))
248
        # but if we have a reference to a clean object it should stick around
249
        weave = DummyWeave("another weave")
250
        self.transaction.map.add_weave("id", weave)
251
        self.transaction.register_clean(self.transaction.map.find_weave("id"))
252
        self.assertEqual(weave, self.transaction.map.find_weave("id"))
253
        del weave
254
        # its not a weakref system
255
        self.assertEqual(DummyWeave("another weave"),
256
                         self.transaction.map.find_weave("id"))
257
258
    def test_zero_size_cache_dirty_objects(self):
259
        self.transaction.set_cache_size(0)
260
        # add a dirty object, which should not fall right out.
261
        weave = DummyWeave('a weave')
262
        self.transaction.map.add_weave("id", weave)
263
        self.assertEqual(weave, self.transaction.map.find_weave("id"))
264
        weave = None
265
        self.transaction.register_dirty(self.transaction.map.find_weave("id"))
266
        self.assertNotEqual(None, self.transaction.map.find_weave("id"))
267
    
268
    def test_clean_to_dirty(self):
269
        # a clean object may become dirty.
270
        weave = DummyWeave('A weave')
271
        self.transaction.map.add_weave("id", weave)
272
        self.transaction.register_clean(weave)
273
        self.transaction.register_dirty(weave)
274
        self.assertTrue(self.transaction.is_dirty(weave))
275
        self.assertFalse(self.transaction.is_clean(weave))
276
277
    def test_small_cache(self):
278
        self.transaction.set_cache_size(1)
279
        # add an object, should not fall right out if there are no references
280
        #sys.getrefcounts(foo)
281
        self.transaction.map.add_weave("id", DummyWeave("a weave"))
282
        self.transaction.register_clean(self.transaction.map.find_weave("id"))
283
        self.assertEqual(DummyWeave("a weave"),
284
                         self.transaction.map.find_weave("id"))
285
        self.transaction.map.add_weave("id2", DummyWeave("a weave also"))
286
        self.transaction.register_clean(self.transaction.map.find_weave("id2"))
287
        # currently a fifo
288
        self.assertEqual(None, self.transaction.map.find_weave("id"))
289
        self.assertEqual(DummyWeave("a weave also"),
290
                         self.transaction.map.find_weave("id2"))
291
292
    def test_small_cache_with_references(self):
293
        # if we have a reference it should stick around
294
        weave = "a weave"
295
        weave2 = "another weave"
296
        self.transaction.map.add_weave("id", weave)
297
        self.transaction.map.add_weave("id2", weave2)
298
        self.assertEqual(weave, self.transaction.map.find_weave("id"))
299
        self.assertEqual(weave2, self.transaction.map.find_weave("id2"))
300
        weave = None
301
        # its not a weakref system
302
        self.assertEqual("a weave", self.transaction.map.find_weave("id"))
303
304
    def test_precious_with_zero_size_cache(self):
305
        self.transaction.set_cache_size(0)
306
        weave = DummyWeave('a weave')
307
        self.transaction.map.add_weave("id", weave)
308
        self.assertEqual(weave, self.transaction.map.find_weave("id"))
309
        weave = None
310
        # add an object, should not fall out even with no references.
311
        self.transaction.register_clean(self.transaction.map.find_weave("id"),
312
                                        precious=True)
313
        self.assertEqual(DummyWeave('a weave'),
314
                         self.transaction.map.find_weave("id"))
1594.2.20 by Robert Collins
Add finished() notifications to transactions.
315
316
    def test_writable(self):
317
        self.assertTrue(self.transaction.writeable())