~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
#
974.1.44 by aaron.bentley at utoronto
Added test of double-add in ImmutableStore
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
#
974.1.44 by aaron.bentley at utoronto
Added test of double-add in ImmutableStore
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
#
974.1.44 by aaron.bentley at utoronto
Added test of double-add in ImmutableStore
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
974.1.44 by aaron.bentley at utoronto
Added test of double-add in ImmutableStore
16
1442.1.24 by Robert Collins
Pull up _check_id and _relpath from Text and CompressedText stores into TransportStore
17
"""Test Store implementations."""
18
1092.2.24 by Robert Collins
merge from martins newformat branch - brings in transport abstraction
19
from cStringIO import StringIO
1185.1.46 by Robert Collins
Aarons branch --basis patch
20
import os
1185.16.157 by John Arbash Meinel
Added ability for TextStore to handle both compressed and uncompressed, it just looks for one type first
21
import gzip
1185.1.41 by Robert Collins
massive patch from Alexander Belchenko - many PEP8 fixes, removes unused function uuid
22
1594.2.23 by Robert Collins
Test versioned file storage handling of clean/dirty status for accessed versioned files.
23
import bzrlib.errors as errors
5579.3.1 by Jelmer Vernooij
Remove unused imports.
24
from bzrlib.errors import BzrError
1393.2.2 by John Arbash Meinel
Updated stores to use Transport
25
from bzrlib.store.text import TextStore
1594.2.23 by Robert Collins
Test versioned file storage handling of clean/dirty status for accessed versioned files.
26
from bzrlib.tests import TestCase, TestCaseInTempDir, TestCaseWithTransport
1442.1.24 by Robert Collins
Pull up _check_id and _relpath from Text and CompressedText stores into TransportStore
27
import bzrlib.store as store
3785.1.1 by Aaron Bentley
Switch from dict to Registry for plugin_cmds
28
import bzrlib.store.versioned
1594.2.23 by Robert Collins
Test versioned file storage handling of clean/dirty status for accessed versioned files.
29
import bzrlib.transactions as transactions
1442.1.24 by Robert Collins
Pull up _check_id and _relpath from Text and CompressedText stores into TransportStore
30
import bzrlib.transport as transport
1442.1.46 by Robert Collins
test simple has_id
31
from bzrlib.transport.memory import MemoryTransport
974.1.44 by aaron.bentley at utoronto
Added test of double-add in ImmutableStore
32
1185.1.41 by Robert Collins
massive patch from Alexander Belchenko - many PEP8 fixes, removes unused function uuid
33
1442.1.34 by Robert Collins
Remove the Store.get multiple-get interface which was not used, and remove much spurious duplication in teststore.py.
34
class TestStores(object):
1185.16.146 by Martin Pool
Fix up assert with sideeffects in CompressedTextStore._copy_one
35
    """Mixin template class that provides some common tests for stores"""
1442.1.34 by Robert Collins
Remove the Store.get multiple-get interface which was not used, and remove much spurious duplication in teststore.py.
36
37
    def check_content(self, store, fileid, value):
1442.1.35 by Robert Collins
convert all users of __getitem__ into TransportStores to use .get instead
38
        f = store.get(fileid)
1442.1.34 by Robert Collins
Remove the Store.get multiple-get interface which was not used, and remove much spurious duplication in teststore.py.
39
        self.assertEqual(f.read(), value)
40
41
    def fill_store(self, store):
42
        store.add(StringIO('hello'), 'a')
43
        store.add(StringIO('other'), 'b')
44
        store.add(StringIO('something'), 'c')
45
        store.add(StringIO('goodbye'), '123123')
46
47
    def test_copy_all(self):
48
        """Test copying"""
49
        os.mkdir('a')
50
        store_a = self.get_store('a')
1955.3.13 by John Arbash Meinel
Run the full test suite, and fix up any deprecation warnings.
51
        store_a.add(StringIO('foo'), '1')
1442.1.34 by Robert Collins
Remove the Store.get multiple-get interface which was not used, and remove much spurious duplication in teststore.py.
52
        os.mkdir('b')
53
        store_b = self.get_store('b')
1563.2.35 by Robert Collins
cleanup deprecation warnings and finish conversion so the inventory is knit based too.
54
        store_b.copy_all_ids(store_a)
1442.1.35 by Robert Collins
convert all users of __getitem__ into TransportStores to use .get instead
55
        self.assertEqual(store_a.get('1').read(), 'foo')
56
        self.assertEqual(store_b.get('1').read(), 'foo')
1442.1.34 by Robert Collins
Remove the Store.get multiple-get interface which was not used, and remove much spurious duplication in teststore.py.
57
        # TODO: Switch the exception form UnlistableStore to
58
        #       or make Stores throw UnlistableStore if their
59
        #       Transport doesn't support listing
60
        # store_c = RemoteStore('http://example.com/')
61
        # self.assertRaises(UnlistableStore, copy_all, store_c, store_b)
62
63
    def test_get(self):
64
        store = self.get_store()
65
        self.fill_store(store)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
66
1442.1.34 by Robert Collins
Remove the Store.get multiple-get interface which was not used, and remove much spurious duplication in teststore.py.
67
        self.check_content(store, 'a', 'hello')
68
        self.check_content(store, 'b', 'other')
69
        self.check_content(store, 'c', 'something')
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
70
1442.1.34 by Robert Collins
Remove the Store.get multiple-get interface which was not used, and remove much spurious duplication in teststore.py.
71
        # Make sure that requesting a non-existing file fails
72
        self.assertRaises(KeyError, self.check_content, store, 'd', None)
73
974.1.44 by aaron.bentley at utoronto
Added test of double-add in ImmutableStore
74
    def test_multiple_add(self):
75
        """Multiple add with same ID should raise a BzrError"""
1442.1.34 by Robert Collins
Remove the Store.get multiple-get interface which was not used, and remove much spurious duplication in teststore.py.
76
        store = self.get_store()
77
        self.fill_store(store)
78
        self.assertRaises(BzrError, store.add, StringIO('goodbye'), '123123')
79
80
81
class TestCompressedTextStore(TestCaseInTempDir, TestStores):
82
1185.33.66 by Martin Pool
[patch] use unicode literals for all hardcoded paths (Alexander Belchenko)
83
    def get_store(self, path=u'.'):
1685.1.68 by Martin Pool
clean up test kipple
84
        t = transport.get_transport(path)
1185.16.157 by John Arbash Meinel
Added ability for TextStore to handle both compressed and uncompressed, it just looks for one type first
85
        return TextStore(t, compressed=True)
1185.11.1 by John Arbash Meinel
(broken) Transport work is merged in. Tests do not pass yet.
86
1092.2.1 by Robert Collins
minor refactors to store, create an ImmutableMemoryStore for testing or other such operations
87
    def test_total_size(self):
1185.33.66 by Martin Pool
[patch] use unicode literals for all hardcoded paths (Alexander Belchenko)
88
        store = self.get_store(u'.')
1442.1.43 by Robert Collins
add registration of suffixes, in preparation for ensuring iteration is regular
89
        store.register_suffix('dsc')
1092.2.1 by Robert Collins
minor refactors to store, create an ImmutableMemoryStore for testing or other such operations
90
        store.add(StringIO('goodbye'), '123123')
1442.1.43 by Robert Collins
add registration of suffixes, in preparation for ensuring iteration is regular
91
        store.add(StringIO('goodbye2'), '123123', 'dsc')
1092.2.1 by Robert Collins
minor refactors to store, create an ImmutableMemoryStore for testing or other such operations
92
        # these get gzipped - content should be stable
93
        self.assertEqual(store.total_size(), (2, 55))
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
94
1442.1.32 by Robert Collins
Teach CompressedTextStore._relpath to support file suffixes too.
95
    def test__relpath_suffixed(self):
1185.58.4 by John Arbash Meinel
Added permission checking to Branch, and propogated that change into the stores.
96
        my_store = TextStore(MockTransport(),
97
                             prefixed=True, compressed=True)
1442.1.43 by Robert Collins
add registration of suffixes, in preparation for ensuring iteration is regular
98
        my_store.register_suffix('dsc')
1185.16.157 by John Arbash Meinel
Added ability for TextStore to handle both compressed and uncompressed, it just looks for one type first
99
        self.assertEqual('45/foo.dsc', my_store._relpath('foo', ['dsc']))
1442.1.32 by Robert Collins
Teach CompressedTextStore._relpath to support file suffixes too.
100
1404 by Robert Collins
only pull remote text weaves once per fetch operation
101
1092.2.1 by Robert Collins
minor refactors to store, create an ImmutableMemoryStore for testing or other such operations
102
class TestMemoryStore(TestCase):
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
103
1092.2.1 by Robert Collins
minor refactors to store, create an ImmutableMemoryStore for testing or other such operations
104
    def get_store(self):
1651.1.7 by Martin Pool
Move small ImmutableMemoryStore class into test module,
105
        return TextStore(MemoryTransport())
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
106
1092.2.1 by Robert Collins
minor refactors to store, create an ImmutableMemoryStore for testing or other such operations
107
    def test_add_and_retrieve(self):
108
        store = self.get_store()
109
        store.add(StringIO('hello'), 'aa')
1442.1.35 by Robert Collins
convert all users of __getitem__ into TransportStores to use .get instead
110
        self.assertNotEqual(store.get('aa'), None)
111
        self.assertEqual(store.get('aa').read(), 'hello')
1092.2.1 by Robert Collins
minor refactors to store, create an ImmutableMemoryStore for testing or other such operations
112
        store.add(StringIO('hello world'), 'bb')
1442.1.35 by Robert Collins
convert all users of __getitem__ into TransportStores to use .get instead
113
        self.assertNotEqual(store.get('bb'), None)
114
        self.assertEqual(store.get('bb').read(), 'hello world')
1092.2.1 by Robert Collins
minor refactors to store, create an ImmutableMemoryStore for testing or other such operations
115
116
    def test_missing_is_absent(self):
117
        store = self.get_store()
118
        self.failIf('aa' in store)
119
120
    def test_adding_fails_when_present(self):
1442.1.24 by Robert Collins
Pull up _check_id and _relpath from Text and CompressedText stores into TransportStore
121
        my_store = self.get_store()
122
        my_store.add(StringIO('hello'), 'aa')
1442.1.44 by Robert Collins
Many transport related tweaks:
123
        self.assertRaises(BzrError,
1442.1.24 by Robert Collins
Pull up _check_id and _relpath from Text and CompressedText stores into TransportStore
124
                          my_store.add, StringIO('hello'), 'aa')
1092.2.1 by Robert Collins
minor refactors to store, create an ImmutableMemoryStore for testing or other such operations
125
126
    def test_total_size(self):
127
        store = self.get_store()
128
        store.add(StringIO('goodbye'), '123123')
129
        store.add(StringIO('goodbye2'), '123123.dsc')
130
        self.assertEqual(store.total_size(), (2, 15))
1393.2.1 by John Arbash Meinel
Merged in split-storage-2 branch. Need to cleanup a little bit more still.
131
        # TODO: Switch the exception form UnlistableStore to
132
        #       or make Stores throw UnlistableStore if their
133
        #       Transport doesn't support listing
134
        # store_c = RemoteStore('http://example.com/')
135
        # self.assertRaises(UnlistableStore, copy_all, store_c, store_b)
136
1404 by Robert Collins
only pull remote text weaves once per fetch operation
137
1442.1.34 by Robert Collins
Remove the Store.get multiple-get interface which was not used, and remove much spurious duplication in teststore.py.
138
class TestTextStore(TestCaseInTempDir, TestStores):
139
1185.33.66 by Martin Pool
[patch] use unicode literals for all hardcoded paths (Alexander Belchenko)
140
    def get_store(self, path=u'.'):
1685.1.68 by Martin Pool
clean up test kipple
141
        t = transport.get_transport(path)
1185.16.157 by John Arbash Meinel
Added ability for TextStore to handle both compressed and uncompressed, it just looks for one type first
142
        return TextStore(t, compressed=False)
1442.1.34 by Robert Collins
Remove the Store.get multiple-get interface which was not used, and remove much spurious duplication in teststore.py.
143
144
    def test_total_size(self):
145
        store = self.get_store()
146
        store.add(StringIO('goodbye'), '123123')
147
        store.add(StringIO('goodbye2'), '123123.dsc')
148
        self.assertEqual(store.total_size(), (2, 15))
1393.2.2 by John Arbash Meinel
Updated stores to use Transport
149
        # TODO: Switch the exception form UnlistableStore to
150
        #       or make Stores throw UnlistableStore if their
151
        #       Transport doesn't support listing
152
        # store_c = RemoteStore('http://example.com/')
153
        # self.assertRaises(UnlistableStore, copy_all, store_c, store_b)
1442.1.24 by Robert Collins
Pull up _check_id and _relpath from Text and CompressedText stores into TransportStore
154
155
1185.16.157 by John Arbash Meinel
Added ability for TextStore to handle both compressed and uncompressed, it just looks for one type first
156
class TestMixedTextStore(TestCaseInTempDir, TestStores):
157
1185.33.66 by Martin Pool
[patch] use unicode literals for all hardcoded paths (Alexander Belchenko)
158
    def get_store(self, path=u'.', compressed=True):
1685.1.68 by Martin Pool
clean up test kipple
159
        t = transport.get_transport(path)
1185.16.157 by John Arbash Meinel
Added ability for TextStore to handle both compressed and uncompressed, it just looks for one type first
160
        return TextStore(t, compressed=compressed)
161
162
    def test_get_mixed(self):
1185.33.66 by Martin Pool
[patch] use unicode literals for all hardcoded paths (Alexander Belchenko)
163
        cs = self.get_store(u'.', compressed=True)
164
        s = self.get_store(u'.', compressed=False)
1185.16.157 by John Arbash Meinel
Added ability for TextStore to handle both compressed and uncompressed, it just looks for one type first
165
        cs.add(StringIO('hello there'), 'a')
166
167
        self.failUnlessExists('a.gz')
168
        self.failIf(os.path.lexists('a'))
169
170
        self.assertEquals(gzip.GzipFile('a.gz').read(), 'hello there')
171
172
        self.assertEquals(cs.has_id('a'), True)
173
        self.assertEquals(s.has_id('a'), True)
174
        self.assertEquals(cs.get('a').read(), 'hello there')
175
        self.assertEquals(s.get('a').read(), 'hello there')
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
176
1185.16.157 by John Arbash Meinel
Added ability for TextStore to handle both compressed and uncompressed, it just looks for one type first
177
        self.assertRaises(BzrError, s.add, StringIO('goodbye'), 'a')
178
179
        s.add(StringIO('goodbye'), 'b')
180
        self.failUnlessExists('b')
181
        self.failIf(os.path.lexists('b.gz'))
182
        self.assertEquals(open('b').read(), 'goodbye')
183
184
        self.assertEquals(cs.has_id('b'), True)
185
        self.assertEquals(s.has_id('b'), True)
186
        self.assertEquals(cs.get('b').read(), 'goodbye')
187
        self.assertEquals(s.get('b').read(), 'goodbye')
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
188
1185.16.157 by John Arbash Meinel
Added ability for TextStore to handle both compressed and uncompressed, it just looks for one type first
189
        self.assertRaises(BzrError, cs.add, StringIO('again'), 'b')
190
1442.1.24 by Robert Collins
Pull up _check_id and _relpath from Text and CompressedText stores into TransportStore
191
class MockTransport(transport.Transport):
192
    """A fake transport for testing with."""
193
1442.1.30 by Robert Collins
Add stuf has and mkdir to MockTransport to enable testing store adds
194
    def has(self, filename):
195
        return False
196
1442.1.24 by Robert Collins
Pull up _check_id and _relpath from Text and CompressedText stores into TransportStore
197
    def __init__(self, url=None):
198
        if url is None:
199
            url = "http://example.com"
200
        super(MockTransport, self).__init__(url)
201
1442.1.30 by Robert Collins
Add stuf has and mkdir to MockTransport to enable testing store adds
202
    def mkdir(self, filename):
203
        return
204
1442.1.24 by Robert Collins
Pull up _check_id and _relpath from Text and CompressedText stores into TransportStore
205
1442.1.29 by Robert Collins
create an instrumented transport store for testing common logic.
206
class InstrumentedTransportStore(store.TransportStore):
207
    """An instrumented TransportStore.
208
209
    Here we replace template method worker methods with calls that record the
210
    expected results.
211
    """
212
213
    def _add(self, filename, file):
214
        self._calls.append(("_add", filename, file))
215
216
    def __init__(self, transport, prefixed=False):
217
        super(InstrumentedTransportStore, self).__init__(transport, prefixed)
218
        self._calls = []
219
220
221
class TestInstrumentedTransportStore(TestCase):
222
223
    def test__add_records(self):
224
        my_store = InstrumentedTransportStore(MockTransport())
1442.1.30 by Robert Collins
Add stuf has and mkdir to MockTransport to enable testing store adds
225
        my_store._add("filename", "file")
1442.1.29 by Robert Collins
create an instrumented transport store for testing common logic.
226
        self.assertEqual([("_add", "filename", "file")], my_store._calls)
227
228
1442.1.24 by Robert Collins
Pull up _check_id and _relpath from Text and CompressedText stores into TransportStore
229
class TestMockTransport(TestCase):
230
231
    def test_isinstance(self):
232
        self.failUnless(isinstance(MockTransport(), transport.Transport))
233
1442.1.30 by Robert Collins
Add stuf has and mkdir to MockTransport to enable testing store adds
234
    def test_has(self):
235
        self.assertEqual(False, MockTransport().has('foo'))
236
237
    def test_mkdir(self):
238
        MockTransport().mkdir('45')
239
1442.1.24 by Robert Collins
Pull up _check_id and _relpath from Text and CompressedText stores into TransportStore
240
241
class TestTransportStore(TestCase):
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
242
1442.1.24 by Robert Collins
Pull up _check_id and _relpath from Text and CompressedText stores into TransportStore
243
    def test__relpath_invalid(self):
244
        my_store = store.TransportStore(MockTransport())
245
        self.assertRaises(ValueError, my_store._relpath, '/foo')
246
        self.assertRaises(ValueError, my_store._relpath, 'foo/')
247
1442.1.43 by Robert Collins
add registration of suffixes, in preparation for ensuring iteration is regular
248
    def test_register_invalid_suffixes(self):
249
        my_store = store.TransportStore(MockTransport())
250
        self.assertRaises(ValueError, my_store.register_suffix, '/')
251
        self.assertRaises(ValueError, my_store.register_suffix, '.gz/bar')
252
253
    def test__relpath_unregister_suffixes(self):
254
        my_store = store.TransportStore(MockTransport())
255
        self.assertRaises(ValueError, my_store._relpath, 'foo', ['gz'])
256
        self.assertRaises(ValueError, my_store._relpath, 'foo', ['dsc', 'gz'])
1442.1.27 by Robert Collins
Check that file suffixes in TransportStore are also valid
257
1442.1.25 by Robert Collins
Test TransportStore._relpath for simple cases: pull up _prefixed attribute as a result.
258
    def test__relpath_simple(self):
259
        my_store = store.TransportStore(MockTransport())
260
        self.assertEqual("foo", my_store._relpath('foo'))
1442.1.26 by Robert Collins
Pull up _relpath with gz suffix for CompressedTextStore into TransportStore
261
262
    def test__relpath_prefixed(self):
263
        my_store = store.TransportStore(MockTransport(), True)
264
        self.assertEqual('45/foo', my_store._relpath('foo'))
265
266
    def test__relpath_simple_suffixed(self):
267
        my_store = store.TransportStore(MockTransport())
1442.1.43 by Robert Collins
add registration of suffixes, in preparation for ensuring iteration is regular
268
        my_store.register_suffix('bar')
1185.16.157 by John Arbash Meinel
Added ability for TextStore to handle both compressed and uncompressed, it just looks for one type first
269
        my_store.register_suffix('baz')
270
        self.assertEqual('foo.baz', my_store._relpath('foo', ['baz']))
271
        self.assertEqual('foo.bar.baz', my_store._relpath('foo', ['bar', 'baz']))
1442.1.27 by Robert Collins
Check that file suffixes in TransportStore are also valid
272
273
    def test__relpath_prefixed_suffixed(self):
274
        my_store = store.TransportStore(MockTransport(), True)
1442.1.43 by Robert Collins
add registration of suffixes, in preparation for ensuring iteration is regular
275
        my_store.register_suffix('bar')
1185.16.157 by John Arbash Meinel
Added ability for TextStore to handle both compressed and uncompressed, it just looks for one type first
276
        my_store.register_suffix('baz')
277
        self.assertEqual('45/foo.baz', my_store._relpath('foo', ['baz']))
278
        self.assertEqual('45/foo.bar.baz',
279
                         my_store._relpath('foo', ['bar', 'baz']))
1442.1.27 by Robert Collins
Check that file suffixes in TransportStore are also valid
280
1442.1.31 by Robert Collins
test that TransportStore.add calls _add appropriately.
281
    def test_add_simple(self):
282
        stream = StringIO("content")
283
        my_store = InstrumentedTransportStore(MockTransport())
284
        my_store.add(stream, "foo")
285
        self.assertEqual([("_add", "foo", stream)], my_store._calls)
286
287
    def test_add_prefixed(self):
288
        stream = StringIO("content")
289
        my_store = InstrumentedTransportStore(MockTransport(), True)
290
        my_store.add(stream, "foo")
291
        self.assertEqual([("_add", "45/foo", stream)], my_store._calls)
1442.1.33 by Robert Collins
teach TransportStore.add to accept an optional file suffix, which does not alter the fileid.
292
293
    def test_add_simple_suffixed(self):
294
        stream = StringIO("content")
295
        my_store = InstrumentedTransportStore(MockTransport())
1442.1.43 by Robert Collins
add registration of suffixes, in preparation for ensuring iteration is regular
296
        my_store.register_suffix('dsc')
1442.1.33 by Robert Collins
teach TransportStore.add to accept an optional file suffix, which does not alter the fileid.
297
        my_store.add(stream, "foo", 'dsc')
298
        self.assertEqual([("_add", "foo.dsc", stream)], my_store._calls)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
299
1442.1.33 by Robert Collins
teach TransportStore.add to accept an optional file suffix, which does not alter the fileid.
300
    def test_add_simple_suffixed(self):
301
        stream = StringIO("content")
302
        my_store = InstrumentedTransportStore(MockTransport(), True)
1442.1.43 by Robert Collins
add registration of suffixes, in preparation for ensuring iteration is regular
303
        my_store.register_suffix('dsc')
1442.1.33 by Robert Collins
teach TransportStore.add to accept an optional file suffix, which does not alter the fileid.
304
        my_store.add(stream, "foo", 'dsc')
305
        self.assertEqual([("_add", "45/foo.dsc", stream)], my_store._calls)
1442.1.46 by Robert Collins
test simple has_id
306
1185.16.157 by John Arbash Meinel
Added ability for TextStore to handle both compressed and uncompressed, it just looks for one type first
307
    def get_populated_store(self, prefixed=False,
1185.16.159 by John Arbash Meinel
Updated the stores, all tests pass, and a store doesn't have to be 100% compressed
308
            store_class=TextStore, compressed=False):
1185.16.157 by John Arbash Meinel
Added ability for TextStore to handle both compressed and uncompressed, it just looks for one type first
309
        my_store = store_class(MemoryTransport(), prefixed,
310
                               compressed=compressed)
1442.1.46 by Robert Collins
test simple has_id
311
        my_store.register_suffix('sig')
1442.1.48 by Robert Collins
test that the presence of a signature does not make a missing base file magically appear present
312
        stream = StringIO("signature")
1442.1.46 by Robert Collins
test simple has_id
313
        my_store.add(stream, "foo", 'sig')
314
        stream = StringIO("content")
315
        my_store.add(stream, "foo")
1442.1.48 by Robert Collins
test that the presence of a signature does not make a missing base file magically appear present
316
        stream = StringIO("signature for missing base")
317
        my_store.add(stream, "missing", 'sig')
1442.1.46 by Robert Collins
test simple has_id
318
        return my_store
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
319
1442.1.46 by Robert Collins
test simple has_id
320
    def test_has_simple(self):
321
        my_store = self.get_populated_store()
322
        self.assertEqual(True, my_store.has_id('foo'))
1442.1.47 by Robert Collins
test for has with suffixed files
323
        my_store = self.get_populated_store(True)
324
        self.assertEqual(True, my_store.has_id('foo'))
325
326
    def test_has_suffixed(self):
327
        my_store = self.get_populated_store()
328
        self.assertEqual(True, my_store.has_id('foo', 'sig'))
329
        my_store = self.get_populated_store(True)
330
        self.assertEqual(True, my_store.has_id('foo', 'sig'))
1442.1.48 by Robert Collins
test that the presence of a signature does not make a missing base file magically appear present
331
332
    def test_has_suffixed_no_base(self):
333
        my_store = self.get_populated_store()
334
        self.assertEqual(False, my_store.has_id('missing'))
335
        my_store = self.get_populated_store(True)
336
        self.assertEqual(False, my_store.has_id('missing'))
1442.1.50 by Robert Collins
test get with suffixes
337
338
    def test_get_simple(self):
339
        my_store = self.get_populated_store()
340
        self.assertEqual('content', my_store.get('foo').read())
341
        my_store = self.get_populated_store(True)
342
        self.assertEqual('content', my_store.get('foo').read())
343
344
    def test_get_suffixed(self):
345
        my_store = self.get_populated_store()
346
        self.assertEqual('signature', my_store.get('foo', 'sig').read())
347
        my_store = self.get_populated_store(True)
348
        self.assertEqual('signature', my_store.get('foo', 'sig').read())
349
350
    def test_get_suffixed_no_base(self):
351
        my_store = self.get_populated_store()
352
        self.assertEqual('signature for missing base',
353
                         my_store.get('missing', 'sig').read())
354
        my_store = self.get_populated_store(True)
355
        self.assertEqual('signature for missing base',
356
                         my_store.get('missing', 'sig').read())
1442.1.51 by Robert Collins
teach iter about suffixes
357
358
    def test___iter__no_suffix(self):
1185.58.4 by John Arbash Meinel
Added permission checking to Branch, and propogated that change into the stores.
359
        my_store = TextStore(MemoryTransport(),
360
                             prefixed=False, compressed=False)
1442.1.51 by Robert Collins
teach iter about suffixes
361
        stream = StringIO("content")
362
        my_store.add(stream, "foo")
363
        self.assertEqual(set(['foo']),
364
                         set(my_store.__iter__()))
365
366
    def test___iter__(self):
367
        self.assertEqual(set(['foo']),
368
                         set(self.get_populated_store().__iter__()))
369
        self.assertEqual(set(['foo']),
370
                         set(self.get_populated_store(True).__iter__()))
371
372
    def test___iter__compressed(self):
373
        self.assertEqual(set(['foo']),
374
                         set(self.get_populated_store(
1185.16.157 by John Arbash Meinel
Added ability for TextStore to handle both compressed and uncompressed, it just looks for one type first
375
                             compressed=True).__iter__()))
1442.1.51 by Robert Collins
teach iter about suffixes
376
        self.assertEqual(set(['foo']),
377
                         set(self.get_populated_store(
1185.16.157 by John Arbash Meinel
Added ability for TextStore to handle both compressed and uncompressed, it just looks for one type first
378
                             True, compressed=True).__iter__()))
1442.1.51 by Robert Collins
teach iter about suffixes
379
380
    def test___len__(self):
381
        self.assertEqual(1, len(self.get_populated_store()))
1442.1.54 by Robert Collins
Teach store.copy_all about fileid suffixes
382
383
    def test_copy_suffixes(self):
384
        from_store = self.get_populated_store()
1185.58.4 by John Arbash Meinel
Added permission checking to Branch, and propogated that change into the stores.
385
        to_store = TextStore(MemoryTransport(),
386
                             prefixed=True, compressed=True)
1442.1.54 by Robert Collins
Teach store.copy_all about fileid suffixes
387
        to_store.register_suffix('sig')
1563.2.35 by Robert Collins
cleanup deprecation warnings and finish conversion so the inventory is knit based too.
388
        to_store.copy_all_ids(from_store)
1442.1.54 by Robert Collins
Teach store.copy_all about fileid suffixes
389
        self.assertEqual(1, len(to_store))
390
        self.assertEqual(set(['foo']), set(to_store.__iter__()))
391
        self.assertEqual('content', to_store.get('foo').read())
392
        self.assertEqual('signature', to_store.get('foo', 'sig').read())
393
        self.assertRaises(KeyError, to_store.get, 'missing', 'sig')
1469 by Robert Collins
Change Transport.* to work with URL's.
394
395
    def test_relpath_escaped(self):
396
        my_store = store.TransportStore(MemoryTransport())
397
        self.assertEqual('%25', my_store._relpath('%'))
1594.2.23 by Robert Collins
Test versioned file storage handling of clean/dirty status for accessed versioned files.
398
1608.2.12 by Martin Pool
Store-escaping must quote uppercase characters too, so that they're safely
399
    def test_escaped_uppercase(self):
400
        """Uppercase letters are escaped for safety on Windows"""
3350.6.1 by Robert Collins
* New ``versionedfile.KeyMapper`` interface to abstract out the access to
401
        my_store = store.TransportStore(MemoryTransport(), prefixed=True,
402
            escaped=True)
1608.2.12 by Martin Pool
Store-escaping must quote uppercase characters too, so that they're safely
403
        # a particularly perverse file-id! :-)
3350.6.1 by Robert Collins
* New ``versionedfile.KeyMapper`` interface to abstract out the access to
404
        self.assertEquals(my_store._relpath('C:<>'), 'be/%2543%253a%253c%253e')
1608.2.12 by Martin Pool
Store-escaping must quote uppercase characters too, so that they're safely
405
1594.2.23 by Robert Collins
Test versioned file storage handling of clean/dirty status for accessed versioned files.
406
407
class TestVersionFileStore(TestCaseWithTransport):
408
3316.2.3 by Robert Collins
Remove manual notification of transaction finishing on versioned files.
409
    def get_scope(self):
410
        return self._transaction
411
1594.2.23 by Robert Collins
Test versioned file storage handling of clean/dirty status for accessed versioned files.
412
    def setUp(self):
413
        super(TestVersionFileStore, self).setUp()
414
        self.vfstore = store.versioned.VersionedFileStore(MemoryTransport())
3316.2.3 by Robert Collins
Remove manual notification of transaction finishing on versioned files.
415
        self.vfstore.get_scope = self.get_scope
416
        self._transaction = None
1594.2.23 by Robert Collins
Test versioned file storage handling of clean/dirty status for accessed versioned files.
417
418
    def test_get_weave_registers_dirty_in_write(self):
3316.2.3 by Robert Collins
Remove manual notification of transaction finishing on versioned files.
419
        self._transaction = transactions.WriteTransaction()
420
        vf = self.vfstore.get_weave_or_empty('id', self._transaction)
421
        self._transaction.finish()
422
        self._transaction = None
1594.2.23 by Robert Collins
Test versioned file storage handling of clean/dirty status for accessed versioned files.
423
        self.assertRaises(errors.OutSideTransaction, vf.add_lines, 'b', [], [])
3316.2.3 by Robert Collins
Remove manual notification of transaction finishing on versioned files.
424
        self._transaction = transactions.WriteTransaction()
425
        vf = self.vfstore.get_weave('id', self._transaction)
426
        self._transaction.finish()
427
        self._transaction = None
1594.2.23 by Robert Collins
Test versioned file storage handling of clean/dirty status for accessed versioned files.
428
        self.assertRaises(errors.OutSideTransaction, vf.add_lines, 'b', [], [])
429
430
    def test_get_weave_readonly_cant_write(self):
3316.2.3 by Robert Collins
Remove manual notification of transaction finishing on versioned files.
431
        self._transaction = transactions.WriteTransaction()
432
        vf = self.vfstore.get_weave_or_empty('id', self._transaction)
433
        self._transaction.finish()
434
        self._transaction = transactions.ReadOnlyTransaction()
435
        vf = self.vfstore.get_weave_or_empty('id', self._transaction)
1594.2.23 by Robert Collins
Test versioned file storage handling of clean/dirty status for accessed versioned files.
436
        self.assertRaises(errors.ReadOnlyError, vf.add_lines, 'b', [], [])
3350.6.1 by Robert Collins
* New ``versionedfile.KeyMapper`` interface to abstract out the access to
437
438
    def test___iter__escaped(self):
439
        self.vfstore = store.versioned.VersionedFileStore(MemoryTransport(),
440
            prefixed=True, escaped=True)
441
        self.vfstore.get_scope = self.get_scope
442
        self._transaction = transactions.WriteTransaction()
443
        vf = self.vfstore.get_weave_or_empty(' ', self._transaction)
444
        vf.add_lines('a', [], [])
445
        del vf
446
        self._transaction.finish()
447
        self.assertEqual([' '], list(self.vfstore))