1
# Copyright (C) 2005, 2006, 2009, 2011 Canonical Ltd
2
# Authors: Robert Collins <robert.collins@canonical.com>
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.
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.
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18
"""Tests for the behaviour of the Transaction concept in bzr."""
20
# import breezy specific imports here
21
import breezy.errors as errors
22
from breezy.tests import TestCase
23
import breezy.transactions as transactions
26
class DummyWeave(object):
27
"""A class that can be instantiated and compared."""
29
def __init__(self, message):
30
self._message = message
33
def __eq__(self, other):
36
return self._message == other._message
39
return hash((type(self), self._message))
41
def transaction_finished(self):
45
class TestSymbols(TestCase):
47
def test_public_symbols(self):
48
from breezy.transactions import ReadOnlyTransaction # noqa: F401
49
from breezy.transactions import PassThroughTransaction # noqa: F401
52
class TestReadOnlyTransaction(TestCase):
55
self.transaction = transactions.ReadOnlyTransaction()
56
super(TestReadOnlyTransaction, self).setUp()
58
def test_register_clean(self):
59
self.transaction.register_clean("anobject")
61
def test_register_dirty_raises(self):
62
self.assertRaises(errors.ReadOnlyError,
63
self.transaction.register_dirty, "anobject")
66
self.assertNotEqual(None, getattr(self.transaction, "map", None))
68
def test_add_and_get(self):
70
self.transaction.map.add_weave("id", weave)
71
self.assertEqual(weave, self.transaction.map.find_weave("id"))
73
def test_finish_returns(self):
74
self.transaction.finish()
76
def test_finish_does_not_tell_versioned_file_finished(self):
77
# read only transactions never write, so theres no
78
# need to inform versioned files about finishing
79
weave = DummyWeave('a weave')
80
self.transaction.finish()
81
self.assertFalse(weave.finished)
83
def test_zero_size_cache(self):
84
self.transaction.set_cache_size(0)
85
weave = DummyWeave('a weave')
86
self.transaction.map.add_weave("id", weave)
87
self.assertEqual(weave, self.transaction.map.find_weave("id"))
89
# add an object, should fall right out if there are no references
90
self.transaction.register_clean(self.transaction.map.find_weave("id"))
91
self.assertEqual(None, self.transaction.map.find_weave("id"))
92
# but if we have a reference it should stick around
93
weave = DummyWeave("another weave")
94
self.transaction.map.add_weave("id", weave)
95
self.transaction.register_clean(self.transaction.map.find_weave("id"))
96
self.assertEqual(weave, self.transaction.map.find_weave("id"))
98
# its not a weakref system
99
self.assertEqual(DummyWeave("another weave"),
100
self.transaction.map.find_weave("id"))
102
def test_small_cache(self):
103
self.transaction.set_cache_size(1)
104
# add an object, should not fall right out if there are no references
105
# sys.getrefcounts(foo)
106
self.transaction.map.add_weave("id", DummyWeave("a weave"))
107
self.transaction.register_clean(self.transaction.map.find_weave("id"))
108
self.assertEqual(DummyWeave("a weave"),
109
self.transaction.map.find_weave("id"))
110
self.transaction.map.add_weave("id2", DummyWeave("a weave also"))
111
self.transaction.register_clean(self.transaction.map.find_weave("id2"))
113
self.assertEqual(None, self.transaction.map.find_weave("id"))
114
self.assertEqual(DummyWeave("a weave also"),
115
self.transaction.map.find_weave("id2"))
117
def test_small_cache_with_references(self):
118
# if we have a reference it should stick around
120
weave2 = "another weave"
121
self.transaction.map.add_weave("id", weave)
122
self.transaction.map.add_weave("id2", weave2)
123
self.assertEqual(weave, self.transaction.map.find_weave("id"))
124
self.assertEqual(weave2, self.transaction.map.find_weave("id2"))
126
# its not a weakref system
127
self.assertEqual("a weave", self.transaction.map.find_weave("id"))
129
def test_precious_with_zero_size_cache(self):
130
self.transaction.set_cache_size(0)
131
weave = DummyWeave('a weave')
132
self.transaction.map.add_weave("id", weave)
133
self.assertEqual(weave, self.transaction.map.find_weave("id"))
135
# add an object, should not fall out even with no references.
136
self.transaction.register_clean(self.transaction.map.find_weave("id"),
138
self.assertEqual(DummyWeave('a weave'),
139
self.transaction.map.find_weave("id"))
141
def test_writable(self):
142
self.assertFalse(self.transaction.writeable())
145
class TestPassThroughTransaction(TestCase):
147
def test_construct(self):
148
transactions.PassThroughTransaction()
150
def test_register_clean(self):
151
transaction = transactions.PassThroughTransaction()
152
transaction.register_clean("anobject")
154
def test_register_dirty(self):
155
transaction = transactions.PassThroughTransaction()
156
transaction.register_dirty("anobject")
159
transaction = transactions.PassThroughTransaction()
160
self.assertNotEqual(None, getattr(transaction, "map", None))
162
def test_add_and_get(self):
163
transaction = transactions.PassThroughTransaction()
165
transaction.map.add_weave("id", weave)
166
self.assertEqual(None, transaction.map.find_weave("id"))
168
def test_finish_returns(self):
169
transaction = transactions.PassThroughTransaction()
172
def test_finish_tells_versioned_file_finished(self):
173
# pass through transactions allow writes so they
174
# need to inform versioned files about finishing
175
weave = DummyWeave('a weave')
176
transaction = transactions.PassThroughTransaction()
177
transaction.register_dirty(weave)
179
self.assertTrue(weave.finished)
181
def test_cache_is_ignored(self):
182
transaction = transactions.PassThroughTransaction()
183
transaction.set_cache_size(100)
185
transaction.map.add_weave("id", weave)
186
self.assertEqual(None, transaction.map.find_weave("id"))
188
def test_writable(self):
189
transaction = transactions.PassThroughTransaction()
190
self.assertTrue(transaction.writeable())
193
class TestWriteTransaction(TestCase):
196
self.transaction = transactions.WriteTransaction()
197
super(TestWriteTransaction, self).setUp()
199
def test_register_clean(self):
200
self.transaction.register_clean("anobject")
202
def test_register_dirty(self):
203
self.transaction.register_dirty("anobject")
206
self.assertNotEqual(None, getattr(self.transaction, "map", None))
208
def test_add_and_get(self):
210
self.transaction.map.add_weave("id", weave)
211
self.assertEqual(weave, self.transaction.map.find_weave("id"))
213
def test_finish_returns(self):
214
self.transaction.finish()
216
def test_finish_tells_versioned_file_finished(self):
217
# write transactions allow writes so they
218
# need to inform versioned files about finishing
219
weave = DummyWeave('a weave')
220
self.transaction.register_dirty(weave)
221
self.transaction.finish()
222
self.assertTrue(weave.finished)
224
def test_zero_size_cache(self):
225
self.transaction.set_cache_size(0)
226
# add an object, should fall right out if there are no references
227
weave = DummyWeave('a weave')
228
self.transaction.map.add_weave("id", weave)
229
self.assertEqual(weave, self.transaction.map.find_weave("id"))
231
self.transaction.register_clean(self.transaction.map.find_weave("id"))
232
self.assertEqual(None, self.transaction.map.find_weave("id"))
233
# but if we have a reference to a clean object it should stick around
234
weave = DummyWeave("another weave")
235
self.transaction.map.add_weave("id", weave)
236
self.transaction.register_clean(self.transaction.map.find_weave("id"))
237
self.assertEqual(weave, self.transaction.map.find_weave("id"))
239
# its not a weakref system
240
self.assertEqual(DummyWeave("another weave"),
241
self.transaction.map.find_weave("id"))
243
def test_zero_size_cache_dirty_objects(self):
244
self.transaction.set_cache_size(0)
245
# add a dirty object, which should not fall right out.
246
weave = DummyWeave('a weave')
247
self.transaction.map.add_weave("id", weave)
248
self.assertEqual(weave, self.transaction.map.find_weave("id"))
250
self.transaction.register_dirty(self.transaction.map.find_weave("id"))
251
self.assertNotEqual(None, self.transaction.map.find_weave("id"))
253
def test_clean_to_dirty(self):
254
# a clean object may become dirty.
255
weave = DummyWeave('A weave')
256
self.transaction.map.add_weave("id", weave)
257
self.transaction.register_clean(weave)
258
self.transaction.register_dirty(weave)
259
self.assertTrue(self.transaction.is_dirty(weave))
260
self.assertFalse(self.transaction.is_clean(weave))
262
def test_small_cache(self):
263
self.transaction.set_cache_size(1)
264
# add an object, should not fall right out if there are no references
265
# sys.getrefcounts(foo)
266
self.transaction.map.add_weave("id", DummyWeave("a weave"))
267
self.transaction.register_clean(self.transaction.map.find_weave("id"))
268
self.assertEqual(DummyWeave("a weave"),
269
self.transaction.map.find_weave("id"))
270
self.transaction.map.add_weave("id2", DummyWeave("a weave also"))
271
self.transaction.register_clean(self.transaction.map.find_weave("id2"))
273
self.assertEqual(None, self.transaction.map.find_weave("id"))
274
self.assertEqual(DummyWeave("a weave also"),
275
self.transaction.map.find_weave("id2"))
277
def test_small_cache_with_references(self):
278
# if we have a reference it should stick around
280
weave2 = "another weave"
281
self.transaction.map.add_weave("id", weave)
282
self.transaction.map.add_weave("id2", weave2)
283
self.assertEqual(weave, self.transaction.map.find_weave("id"))
284
self.assertEqual(weave2, self.transaction.map.find_weave("id2"))
286
# its not a weakref system
287
self.assertEqual("a weave", self.transaction.map.find_weave("id"))
289
def test_precious_with_zero_size_cache(self):
290
self.transaction.set_cache_size(0)
291
weave = DummyWeave('a weave')
292
self.transaction.map.add_weave("id", weave)
293
self.assertEqual(weave, self.transaction.map.find_weave("id"))
295
# add an object, should not fall out even with no references.
296
self.transaction.register_clean(self.transaction.map.find_weave("id"),
298
self.assertEqual(DummyWeave('a weave'),
299
self.transaction.map.find_weave("id"))
301
def test_writable(self):
302
self.assertTrue(self.transaction.writeable())