42
40
self.assertEqual(f.read(), value)
44
42
def fill_store(self, store):
45
store.add(BytesIO(b'hello'), b'a')
46
store.add(BytesIO(b'other'), b'b')
47
store.add(BytesIO(b'something'), b'c')
48
store.add(BytesIO(b'goodbye'), b'123123')
43
store.add(StringIO('hello'), 'a')
44
store.add(StringIO('other'), 'b')
45
store.add(StringIO('something'), 'c')
46
store.add(StringIO('goodbye'), '123123')
48
def test_copy_all(self):
51
store_a = self.get_store('a')
52
store_a.add(StringIO('foo'), '1')
54
store_b = self.get_store('b')
55
store_b.copy_all_ids(store_a)
56
self.assertEqual(store_a.get('1').read(), 'foo')
57
self.assertEqual(store_b.get('1').read(), 'foo')
58
# TODO: Switch the exception form UnlistableStore to
59
# or make Stores throw UnlistableStore if their
60
# Transport doesn't support listing
61
# store_c = RemoteStore('http://example.com/')
62
# self.assertRaises(UnlistableStore, copy_all, store_c, store_b)
50
64
def test_get(self):
51
65
store = self.get_store()
52
66
self.fill_store(store)
54
self.check_content(store, b'a', b'hello')
55
self.check_content(store, b'b', b'other')
56
self.check_content(store, b'c', b'something')
68
self.check_content(store, 'a', 'hello')
69
self.check_content(store, 'b', 'other')
70
self.check_content(store, 'c', 'something')
58
72
# Make sure that requesting a non-existing file fails
59
self.assertRaises(KeyError, self.check_content, store, b'd', None)
73
self.assertRaises(KeyError, self.check_content, store, 'd', None)
61
75
def test_multiple_add(self):
62
76
"""Multiple add with same ID should raise a BzrError"""
63
77
store = self.get_store()
64
78
self.fill_store(store)
65
self.assertRaises(BzrError, store.add, BytesIO(b'goodbye'), b'123123')
79
self.assertRaises(BzrError, store.add, StringIO('goodbye'), '123123')
68
82
class TestCompressedTextStore(TestCaseInTempDir, TestStores):
70
84
def get_store(self, path=u'.'):
71
t = transport.get_transport_from_path(path)
85
t = transport.get_transport(path)
72
86
return TextStore(t, compressed=True)
74
88
def test_total_size(self):
75
89
store = self.get_store(u'.')
76
90
store.register_suffix('dsc')
77
store.add(BytesIO(b'goodbye'), b'123123')
78
store.add(BytesIO(b'goodbye2'), b'123123', 'dsc')
91
store.add(StringIO('goodbye'), '123123')
92
store.add(StringIO('goodbye2'), '123123', 'dsc')
79
93
# these get gzipped - content should be stable
80
94
self.assertEqual(store.total_size(), (2, 55))
143
157
class TestMixedTextStore(TestCaseInTempDir, TestStores):
145
159
def get_store(self, path=u'.', compressed=True):
146
t = transport.get_transport_from_path(path)
160
t = transport.get_transport(path)
147
161
return TextStore(t, compressed=compressed)
149
163
def test_get_mixed(self):
150
164
cs = self.get_store(u'.', compressed=True)
151
165
s = self.get_store(u'.', compressed=False)
152
cs.add(BytesIO(b'hello there'), b'a')
154
self.assertPathExists('a.gz')
155
self.assertFalse(os.path.lexists('a'))
157
with gzip.GzipFile('a.gz') as f:
158
self.assertEqual(f.read(), b'hello there')
160
self.assertEqual(cs.has_id(b'a'), True)
161
self.assertEqual(s.has_id(b'a'), True)
162
self.assertEqual(cs.get(b'a').read(), b'hello there')
163
self.assertEqual(s.get(b'a').read(), b'hello there')
165
self.assertRaises(BzrError, s.add, BytesIO(b'goodbye'), b'a')
167
s.add(BytesIO(b'goodbye'), b'b')
168
self.assertPathExists('b')
169
self.assertFalse(os.path.lexists('b.gz'))
170
with open('b', 'rb') as f:
171
self.assertEqual(f.read(), b'goodbye')
173
self.assertEqual(cs.has_id(b'b'), True)
174
self.assertEqual(s.has_id(b'b'), True)
175
self.assertEqual(cs.get(b'b').read(), b'goodbye')
176
self.assertEqual(s.get(b'b').read(), b'goodbye')
178
self.assertRaises(BzrError, cs.add, BytesIO(b'again'), b'b')
166
cs.add(StringIO('hello there'), 'a')
168
self.failUnlessExists('a.gz')
169
self.failIf(os.path.lexists('a'))
171
self.assertEquals(gzip.GzipFile('a.gz').read(), 'hello there')
173
self.assertEquals(cs.has_id('a'), True)
174
self.assertEquals(s.has_id('a'), True)
175
self.assertEquals(cs.get('a').read(), 'hello there')
176
self.assertEquals(s.get('a').read(), 'hello there')
178
self.assertRaises(BzrError, s.add, StringIO('goodbye'), 'a')
180
s.add(StringIO('goodbye'), 'b')
181
self.failUnlessExists('b')
182
self.failIf(os.path.lexists('b.gz'))
183
self.assertEquals(open('b').read(), 'goodbye')
185
self.assertEquals(cs.has_id('b'), True)
186
self.assertEquals(s.has_id('b'), True)
187
self.assertEquals(cs.get('b').read(), 'goodbye')
188
self.assertEquals(s.get('b').read(), 'goodbye')
190
self.assertRaises(BzrError, cs.add, StringIO('again'), 'b')
181
192
class MockTransport(transport.Transport):
182
193
"""A fake transport for testing with."""
231
242
class TestTransportStore(TestCase):
233
244
def test__relpath_invalid(self):
234
my_store = TransportStore(MockTransport())
235
self.assertRaises(ValueError, my_store._relpath, b'/foo')
236
self.assertRaises(ValueError, my_store._relpath, b'foo/')
245
my_store = store.TransportStore(MockTransport())
246
self.assertRaises(ValueError, my_store._relpath, '/foo')
247
self.assertRaises(ValueError, my_store._relpath, 'foo/')
238
249
def test_register_invalid_suffixes(self):
239
my_store = TransportStore(MockTransport())
250
my_store = store.TransportStore(MockTransport())
240
251
self.assertRaises(ValueError, my_store.register_suffix, '/')
241
252
self.assertRaises(ValueError, my_store.register_suffix, '.gz/bar')
243
254
def test__relpath_unregister_suffixes(self):
244
my_store = TransportStore(MockTransport())
245
self.assertRaises(ValueError, my_store._relpath, b'foo', [b'gz'])
246
self.assertRaises(ValueError, my_store._relpath,
247
b'foo', [b'dsc', b'gz'])
255
my_store = store.TransportStore(MockTransport())
256
self.assertRaises(ValueError, my_store._relpath, 'foo', ['gz'])
257
self.assertRaises(ValueError, my_store._relpath, 'foo', ['dsc', 'gz'])
249
259
def test__relpath_simple(self):
250
my_store = TransportStore(MockTransport())
251
self.assertEqual("foo", my_store._relpath(b'foo'))
260
my_store = store.TransportStore(MockTransport())
261
self.assertEqual("foo", my_store._relpath('foo'))
253
263
def test__relpath_prefixed(self):
254
my_store = TransportStore(MockTransport(), True)
255
self.assertEqual('45/foo', my_store._relpath(b'foo'))
264
my_store = store.TransportStore(MockTransport(), True)
265
self.assertEqual('45/foo', my_store._relpath('foo'))
257
267
def test__relpath_simple_suffixed(self):
258
my_store = TransportStore(MockTransport())
268
my_store = store.TransportStore(MockTransport())
259
269
my_store.register_suffix('bar')
260
270
my_store.register_suffix('baz')
261
self.assertEqual('foo.baz', my_store._relpath(b'foo', ['baz']))
262
self.assertEqual('foo.bar.baz', my_store._relpath(
263
b'foo', ['bar', 'baz']))
271
self.assertEqual('foo.baz', my_store._relpath('foo', ['baz']))
272
self.assertEqual('foo.bar.baz', my_store._relpath('foo', ['bar', 'baz']))
265
274
def test__relpath_prefixed_suffixed(self):
266
my_store = TransportStore(MockTransport(), True)
275
my_store = store.TransportStore(MockTransport(), True)
267
276
my_store.register_suffix('bar')
268
277
my_store.register_suffix('baz')
269
self.assertEqual('45/foo.baz', my_store._relpath(b'foo', ['baz']))
278
self.assertEqual('45/foo.baz', my_store._relpath('foo', ['baz']))
270
279
self.assertEqual('45/foo.bar.baz',
271
my_store._relpath(b'foo', ['bar', 'baz']))
280
my_store._relpath('foo', ['bar', 'baz']))
273
282
def test_add_simple(self):
274
stream = BytesIO(b"content")
283
stream = StringIO("content")
275
284
my_store = InstrumentedTransportStore(MockTransport())
276
my_store.add(stream, b"foo")
285
my_store.add(stream, "foo")
277
286
self.assertEqual([("_add", "foo", stream)], my_store._calls)
279
288
def test_add_prefixed(self):
280
stream = BytesIO(b"content")
289
stream = StringIO("content")
281
290
my_store = InstrumentedTransportStore(MockTransport(), True)
282
my_store.add(stream, b"foo")
291
my_store.add(stream, "foo")
283
292
self.assertEqual([("_add", "45/foo", stream)], my_store._calls)
285
294
def test_add_simple_suffixed(self):
286
stream = BytesIO(b"content")
295
stream = StringIO("content")
287
296
my_store = InstrumentedTransportStore(MockTransport())
288
297
my_store.register_suffix('dsc')
289
my_store.add(stream, b"foo", b'dsc')
298
my_store.add(stream, "foo", 'dsc')
290
299
self.assertEqual([("_add", "foo.dsc", stream)], my_store._calls)
292
301
def test_add_simple_suffixed(self):
293
stream = BytesIO(b"content")
302
stream = StringIO("content")
294
303
my_store = InstrumentedTransportStore(MockTransport(), True)
295
304
my_store.register_suffix('dsc')
296
my_store.add(stream, b"foo", 'dsc')
305
my_store.add(stream, "foo", 'dsc')
297
306
self.assertEqual([("_add", "45/foo.dsc", stream)], my_store._calls)
299
308
def get_populated_store(self, prefixed=False,
300
store_class=TextStore, compressed=False):
309
store_class=TextStore, compressed=False):
301
310
my_store = store_class(MemoryTransport(), prefixed,
302
311
compressed=compressed)
303
312
my_store.register_suffix('sig')
304
stream = BytesIO(b"signature")
305
my_store.add(stream, b"foo", 'sig')
306
stream = BytesIO(b"content")
307
my_store.add(stream, b"foo")
308
stream = BytesIO(b"signature for missing base")
309
my_store.add(stream, b"missing", 'sig')
313
stream = StringIO("signature")
314
my_store.add(stream, "foo", 'sig')
315
stream = StringIO("content")
316
my_store.add(stream, "foo")
317
stream = StringIO("signature for missing base")
318
my_store.add(stream, "missing", 'sig')
312
321
def test_has_simple(self):
313
322
my_store = self.get_populated_store()
314
self.assertEqual(True, my_store.has_id(b'foo'))
323
self.assertEqual(True, my_store.has_id('foo'))
315
324
my_store = self.get_populated_store(True)
316
self.assertEqual(True, my_store.has_id(b'foo'))
325
self.assertEqual(True, my_store.has_id('foo'))
318
327
def test_has_suffixed(self):
319
328
my_store = self.get_populated_store()
320
self.assertEqual(True, my_store.has_id(b'foo', 'sig'))
329
self.assertEqual(True, my_store.has_id('foo', 'sig'))
321
330
my_store = self.get_populated_store(True)
322
self.assertEqual(True, my_store.has_id(b'foo', 'sig'))
331
self.assertEqual(True, my_store.has_id('foo', 'sig'))
324
333
def test_has_suffixed_no_base(self):
325
334
my_store = self.get_populated_store()
326
self.assertEqual(False, my_store.has_id(b'missing'))
335
self.assertEqual(False, my_store.has_id('missing'))
327
336
my_store = self.get_populated_store(True)
328
self.assertEqual(False, my_store.has_id(b'missing'))
337
self.assertEqual(False, my_store.has_id('missing'))
330
339
def test_get_simple(self):
331
340
my_store = self.get_populated_store()
332
self.assertEqual(b'content', my_store.get(b'foo').read())
341
self.assertEqual('content', my_store.get('foo').read())
333
342
my_store = self.get_populated_store(True)
334
self.assertEqual(b'content', my_store.get(b'foo').read())
343
self.assertEqual('content', my_store.get('foo').read())
336
345
def test_get_suffixed(self):
337
346
my_store = self.get_populated_store()
338
self.assertEqual(b'signature', my_store.get(b'foo', 'sig').read())
347
self.assertEqual('signature', my_store.get('foo', 'sig').read())
339
348
my_store = self.get_populated_store(True)
340
self.assertEqual(b'signature', my_store.get(b'foo', 'sig').read())
349
self.assertEqual('signature', my_store.get('foo', 'sig').read())
342
351
def test_get_suffixed_no_base(self):
343
352
my_store = self.get_populated_store()
344
self.assertEqual(b'signature for missing base',
345
my_store.get(b'missing', 'sig').read())
353
self.assertEqual('signature for missing base',
354
my_store.get('missing', 'sig').read())
346
355
my_store = self.get_populated_store(True)
347
self.assertEqual(b'signature for missing base',
348
my_store.get(b'missing', 'sig').read())
356
self.assertEqual('signature for missing base',
357
my_store.get('missing', 'sig').read())
350
359
def test___iter__no_suffix(self):
351
360
my_store = TextStore(MemoryTransport(),
352
361
prefixed=False, compressed=False)
353
stream = BytesIO(b"content")
354
my_store.add(stream, b"foo")
355
self.assertEqual({b'foo'},
362
stream = StringIO("content")
363
my_store.add(stream, "foo")
364
self.assertEqual(set(['foo']),
356
365
set(my_store.__iter__()))
358
367
def test___iter__(self):
359
self.assertEqual({b'foo'},
368
self.assertEqual(set(['foo']),
360
369
set(self.get_populated_store().__iter__()))
361
self.assertEqual({b'foo'},
370
self.assertEqual(set(['foo']),
362
371
set(self.get_populated_store(True).__iter__()))
364
373
def test___iter__compressed(self):
365
self.assertEqual({b'foo'},
374
self.assertEqual(set(['foo']),
366
375
set(self.get_populated_store(
367
376
compressed=True).__iter__()))
368
self.assertEqual({b'foo'},
377
self.assertEqual(set(['foo']),
369
378
set(self.get_populated_store(
370
379
True, compressed=True).__iter__()))
372
381
def test___len__(self):
373
382
self.assertEqual(1, len(self.get_populated_store()))
384
def test_copy_suffixes(self):
385
from_store = self.get_populated_store()
386
to_store = TextStore(MemoryTransport(),
387
prefixed=True, compressed=True)
388
to_store.register_suffix('sig')
389
to_store.copy_all_ids(from_store)
390
self.assertEqual(1, len(to_store))
391
self.assertEqual(set(['foo']), set(to_store.__iter__()))
392
self.assertEqual('content', to_store.get('foo').read())
393
self.assertEqual('signature', to_store.get('foo', 'sig').read())
394
self.assertRaises(KeyError, to_store.get, 'missing', 'sig')
375
396
def test_relpath_escaped(self):
376
my_store = TransportStore(MemoryTransport())
377
self.assertEqual('%25', my_store._relpath(b'%'))
397
my_store = store.TransportStore(MemoryTransport())
398
self.assertEqual('%25', my_store._relpath('%'))
379
400
def test_escaped_uppercase(self):
380
401
"""Uppercase letters are escaped for safety on Windows"""
381
my_store = TransportStore(MemoryTransport(), prefixed=True,
402
my_store = store.TransportStore(MemoryTransport(), prefixed=True,
383
404
# a particularly perverse file-id! :-)
384
self.assertEqual(my_store._relpath(b'C:<>'), 'be/%2543%253a%253c%253e')
405
self.assertEquals(my_store._relpath('C:<>'), 'be/%2543%253a%253c%253e')
387
408
class TestVersionFileStore(TestCaseWithTransport):
393
414
super(TestVersionFileStore, self).setUp()
394
self.vfstore = VersionedFileStore(MemoryTransport(),
395
versionedfile_class=WeaveFile)
415
self.vfstore = store.versioned.VersionedFileStore(MemoryTransport())
396
416
self.vfstore.get_scope = self.get_scope
397
417
self._transaction = None
399
419
def test_get_weave_registers_dirty_in_write(self):
400
420
self._transaction = transactions.WriteTransaction()
401
vf = self.vfstore.get_weave_or_empty(b'id', self._transaction)
421
vf = self.vfstore.get_weave_or_empty('id', self._transaction)
402
422
self._transaction.finish()
403
423
self._transaction = None
404
self.assertRaises(errors.OutSideTransaction,
405
vf.add_lines, b'b', [], [])
424
self.assertRaises(errors.OutSideTransaction, vf.add_lines, 'b', [], [])
406
425
self._transaction = transactions.WriteTransaction()
407
vf = self.vfstore.get_weave(b'id', self._transaction)
426
vf = self.vfstore.get_weave('id', self._transaction)
408
427
self._transaction.finish()
409
428
self._transaction = None
410
self.assertRaises(errors.OutSideTransaction,
411
vf.add_lines, b'b', [], [])
429
self.assertRaises(errors.OutSideTransaction, vf.add_lines, 'b', [], [])
413
431
def test_get_weave_readonly_cant_write(self):
414
432
self._transaction = transactions.WriteTransaction()
415
vf = self.vfstore.get_weave_or_empty(b'id', self._transaction)
433
vf = self.vfstore.get_weave_or_empty('id', self._transaction)
416
434
self._transaction.finish()
417
435
self._transaction = transactions.ReadOnlyTransaction()
418
vf = self.vfstore.get_weave_or_empty(b'id', self._transaction)
419
self.assertRaises(errors.ReadOnlyError, vf.add_lines, b'b', [], [])
436
vf = self.vfstore.get_weave_or_empty('id', self._transaction)
437
self.assertRaises(errors.ReadOnlyError, vf.add_lines, 'b', [], [])
421
439
def test___iter__escaped(self):
422
self.vfstore = VersionedFileStore(MemoryTransport(),
423
prefixed=True, escaped=True, versionedfile_class=WeaveFile)
440
self.vfstore = store.versioned.VersionedFileStore(MemoryTransport(),
441
prefixed=True, escaped=True)
424
442
self.vfstore.get_scope = self.get_scope
425
443
self._transaction = transactions.WriteTransaction()
426
vf = self.vfstore.get_weave_or_empty(b' ', self._transaction)
427
vf.add_lines(b'a', [], [])
444
vf = self.vfstore.get_weave_or_empty(' ', self._transaction)
445
vf.add_lines('a', [], [])
429
447
self._transaction.finish()
430
self.assertEqual([b' '], list(self.vfstore))
448
self.assertEqual([' '], list(self.vfstore))