~bzr-pqm/bzr/bzr.dev

2052.3.2 by John Arbash Meinel
Change Copyright .. by Canonical to Copyright ... Canonical
1
# Copyright (C) 2005 Canonical Ltd
1417.1.6 by Robert Collins
introduce transactions for grouping actions done to and with branches
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
1594.2.20 by Robert Collins
Add finished() notifications to transactions.
142
    def test_writable(self):
143
        self.assertFalse(self.transaction.writeable())
144
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.
145
1417.1.6 by Robert Collins
introduce transactions for grouping actions done to and with branches
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
    
1417.1.8 by Robert Collins
use transactions in the weave store interface, which enables caching for log
155
    def test_register_dirty(self):
156
        transaction = transactions.PassThroughTransaction()
157
        transaction.register_dirty("anobject")
158
    
1417.1.6 by Robert Collins
introduce transactions for grouping actions done to and with branches
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()
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.
172
1594.2.20 by Robert Collins
Add finished() notifications to transactions.
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
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.
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"))
1563.2.34 by Robert Collins
Remove the commit and rollback transaction methods as misleading, and implement a WriteTransaction
188
1594.2.20 by Robert Collins
Add finished() notifications to transactions.
189
    def test_writable(self):
190
        transaction = transactions.PassThroughTransaction()
191
        self.assertTrue(transaction.writeable())
1563.2.34 by Robert Collins
Remove the commit and rollback transaction methods as misleading, and implement a WriteTransaction
192
        
1594.2.20 by Robert Collins
Add finished() notifications to transactions.
193
1563.2.34 by Robert Collins
Remove the commit and rollback transaction methods as misleading, and implement a WriteTransaction
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
1594.2.20 by Robert Collins
Add finished() notifications to transactions.
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
1563.2.34 by Robert Collins
Remove the commit and rollback transaction methods as misleading, and implement a WriteTransaction
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"))
1594.2.20 by Robert Collins
Add finished() notifications to transactions.
301
302
    def test_writable(self):
303
        self.assertTrue(self.transaction.writeable())