24
25
from bzrlib import (
31
from bzrlib.directory_service import directories
32
from bzrlib.transport import (
42
import bzrlib.transport.trace
43
from bzrlib.tests import (
31
from bzrlib.errors import (DependencyNotPresent,
39
from bzrlib.tests import features, TestCase, TestCaseInTempDir
40
from bzrlib.transport import (_clear_protocol_handlers,
43
_get_protocol_handlers,
44
_set_protocol_handlers,
45
_get_transport_modules,
48
register_lazy_transport,
49
register_transport_proto,
52
from bzrlib.transport.chroot import ChrootServer
53
from bzrlib.transport.memory import MemoryTransport
54
from bzrlib.transport.local import (LocalTransport,
55
EmulatedWin32LocalTransport)
56
from bzrlib.transport.pathfilter import PathFilteringServer
49
59
# TODO: Should possibly split transport-specific tests into their own files.
52
class TestTransport(tests.TestCase):
62
class TestTransport(TestCase):
53
63
"""Test the non transport-concrete class functionality."""
55
65
def test__get_set_protocol_handlers(self):
56
handlers = transport._get_protocol_handlers()
57
self.assertNotEqual([], handlers.keys())
58
transport._clear_protocol_handlers()
59
self.addCleanup(transport._set_protocol_handlers, handlers)
60
self.assertEqual([], transport._get_protocol_handlers().keys())
66
handlers = _get_protocol_handlers()
67
self.assertNotEqual([], handlers.keys( ))
69
_clear_protocol_handlers()
70
self.assertEqual([], _get_protocol_handlers().keys())
72
_set_protocol_handlers(handlers)
62
74
def test_get_transport_modules(self):
63
handlers = transport._get_protocol_handlers()
64
self.addCleanup(transport._set_protocol_handlers, handlers)
75
handlers = _get_protocol_handlers()
65
76
# don't pollute the current handlers
66
transport._clear_protocol_handlers()
77
_clear_protocol_handlers()
68
78
class SampleHandler(object):
69
79
"""I exist, isnt that enough?"""
70
transport._clear_protocol_handlers()
71
transport.register_transport_proto('foo')
72
transport.register_lazy_transport('foo',
73
'bzrlib.tests.test_transport',
74
'TestTransport.SampleHandler')
75
transport.register_transport_proto('bar')
76
transport.register_lazy_transport('bar',
77
'bzrlib.tests.test_transport',
78
'TestTransport.SampleHandler')
79
self.assertEqual([SampleHandler.__module__,
80
'bzrlib.transport.chroot',
81
'bzrlib.transport.pathfilter'],
82
transport._get_transport_modules())
81
_clear_protocol_handlers()
82
register_transport_proto('foo')
83
register_lazy_transport('foo', 'bzrlib.tests.test_transport',
84
'TestTransport.SampleHandler')
85
register_transport_proto('bar')
86
register_lazy_transport('bar', 'bzrlib.tests.test_transport',
87
'TestTransport.SampleHandler')
88
self.assertEqual([SampleHandler.__module__,
89
'bzrlib.transport.chroot',
90
'bzrlib.transport.pathfilter'],
91
_get_transport_modules())
93
_set_protocol_handlers(handlers)
84
95
def test_transport_dependency(self):
85
96
"""Transport with missing dependency causes no error"""
86
saved_handlers = transport._get_protocol_handlers()
87
self.addCleanup(transport._set_protocol_handlers, saved_handlers)
97
saved_handlers = _get_protocol_handlers()
88
98
# don't pollute the current handlers
89
transport._clear_protocol_handlers()
90
transport.register_transport_proto('foo')
91
transport.register_lazy_transport(
92
'foo', 'bzrlib.tests.test_transport', 'BadTransportHandler')
99
_clear_protocol_handlers()
94
transport.get_transport_from_url('foo://fooserver/foo')
95
except errors.UnsupportedProtocol, e:
97
self.assertEquals('Unsupported protocol'
98
' for url "foo://fooserver/foo":'
99
' Unable to import library "some_lib":'
100
' testing missing dependency', str(e))
102
self.fail('Did not raise UnsupportedProtocol')
101
register_transport_proto('foo')
102
register_lazy_transport('foo', 'bzrlib.tests.test_transport',
103
'BadTransportHandler')
105
get_transport('foo://fooserver/foo')
106
except UnsupportedProtocol, e:
108
self.assertEquals('Unsupported protocol'
109
' for url "foo://fooserver/foo":'
110
' Unable to import library "some_lib":'
111
' testing missing dependency', str(e))
113
self.fail('Did not raise UnsupportedProtocol')
115
# restore original values
116
_set_protocol_handlers(saved_handlers)
104
118
def test_transport_fallback(self):
105
119
"""Transport with missing dependency causes no error"""
106
saved_handlers = transport._get_protocol_handlers()
107
self.addCleanup(transport._set_protocol_handlers, saved_handlers)
108
transport._clear_protocol_handlers()
109
transport.register_transport_proto('foo')
110
transport.register_lazy_transport(
111
'foo', 'bzrlib.tests.test_transport', 'BackupTransportHandler')
112
transport.register_lazy_transport(
113
'foo', 'bzrlib.tests.test_transport', 'BadTransportHandler')
114
t = transport.get_transport_from_url('foo://fooserver/foo')
115
self.assertTrue(isinstance(t, BackupTransportHandler))
120
saved_handlers = _get_protocol_handlers()
122
_clear_protocol_handlers()
123
register_transport_proto('foo')
124
register_lazy_transport('foo', 'bzrlib.tests.test_transport',
125
'BackupTransportHandler')
126
register_lazy_transport('foo', 'bzrlib.tests.test_transport',
127
'BadTransportHandler')
128
t = get_transport('foo://fooserver/foo')
129
self.assertTrue(isinstance(t, BackupTransportHandler))
131
_set_protocol_handlers(saved_handlers)
117
133
def test_ssh_hints(self):
118
134
"""Transport ssh:// should raise an error pointing out bzr+ssh://"""
120
transport.get_transport_from_url('ssh://fooserver/foo')
121
except errors.UnsupportedProtocol, e:
136
get_transport('ssh://fooserver/foo')
137
except UnsupportedProtocol, e:
123
139
self.assertEquals('Unsupported protocol'
124
140
' for url "ssh://fooserver/foo":'
125
' bzr supports bzr+ssh to operate over ssh,'
126
' use "bzr+ssh://fooserver/foo".',
141
' bzr supports bzr+ssh to operate over ssh, use "bzr+ssh://fooserver/foo".',
129
144
self.fail('Did not raise UnsupportedProtocol')
131
146
def test_LateReadError(self):
132
147
"""The LateReadError helper should raise on read()."""
133
a_file = transport.LateReadError('a path')
148
a_file = LateReadError('a path')
136
except errors.ReadError, error:
151
except ReadError, error:
137
152
self.assertEqual('a path', error.path)
138
self.assertRaises(errors.ReadError, a_file.read, 40)
153
self.assertRaises(ReadError, a_file.read, 40)
156
def test__combine_paths(self):
158
self.assertEqual('/home/sarah/project/foo',
159
t._combine_paths('/home/sarah', 'project/foo'))
160
self.assertEqual('/etc',
161
t._combine_paths('/home/sarah', '../../etc'))
162
self.assertEqual('/etc',
163
t._combine_paths('/home/sarah', '../../../etc'))
164
self.assertEqual('/etc',
165
t._combine_paths('/home/sarah', '/etc'))
141
167
def test_local_abspath_non_local_transport(self):
142
168
# the base implementation should throw
143
t = memory.MemoryTransport()
169
t = MemoryTransport()
144
170
e = self.assertRaises(errors.NotLocalUrl, t.local_abspath, 't')
145
171
self.assertEqual('memory:///t is not a local path.', str(e))
148
class TestCoalesceOffsets(tests.TestCase):
174
class TestCoalesceOffsets(TestCase):
150
176
def check(self, expected, offsets, limit=0, max_size=0, fudge=0):
151
coalesce = transport.Transport._coalesce_offsets
152
exp = [transport._CoalescedOffset(*x) for x in expected]
177
coalesce = Transport._coalesce_offsets
178
exp = [_CoalescedOffset(*x) for x in expected]
153
179
out = list(coalesce(offsets, limit=limit, fudge_factor=fudge,
154
180
max_size=max_size))
155
181
self.assertEqual(exp, out)
201
227
def test_coalesce_fudge(self):
202
228
self.check([(10, 30, [(0, 10), (20, 10)]),
203
(100, 10, [(0, 10)]),
229
(100, 10, [(0, 10),]),
204
230
], [(10, 10), (30, 10), (100, 10)],
207
233
def test_coalesce_max_size(self):
208
234
self.check([(10, 20, [(0, 10), (10, 10)]),
209
235
(30, 50, [(0, 50)]),
210
236
# If one range is above max_size, it gets its own coalesced
212
(100, 80, [(0, 80)]),],
238
(100, 80, [(0, 80),]),],
213
239
[(10, 10), (20, 10), (30, 50), (100, 80)],
216
243
def test_coalesce_no_max_size(self):
217
self.check([(10, 170, [(0, 10), (10, 10), (20, 50), (70, 100)])],
244
self.check([(10, 170, [(0, 10), (10, 10), (20, 50), (70, 100)]),],
218
245
[(10, 10), (20, 10), (30, 50), (80, 100)],
221
248
def test_coalesce_default_limit(self):
222
249
# By default we use a 100MB max size.
223
ten_mb = 10 * 1024 * 1024
224
self.check([(0, 10 * ten_mb, [(i * ten_mb, ten_mb) for i in range(10)]),
250
ten_mb = 10*1024*1024
251
self.check([(0, 10*ten_mb, [(i*ten_mb, ten_mb) for i in range(10)]),
225
252
(10*ten_mb, ten_mb, [(0, ten_mb)])],
226
253
[(i*ten_mb, ten_mb) for i in range(11)])
227
self.check([(0, 11 * ten_mb, [(i * ten_mb, ten_mb) for i in range(11)])],
228
[(i * ten_mb, ten_mb) for i in range(11)],
254
self.check([(0, 11*ten_mb, [(i*ten_mb, ten_mb) for i in range(11)]),],
255
[(i*ten_mb, ten_mb) for i in range(11)],
229
256
max_size=1*1024*1024*1024)
232
class TestMemoryServer(tests.TestCase):
234
def test_create_server(self):
235
server = memory.MemoryServer()
236
server.start_server()
237
url = server.get_url()
238
self.assertTrue(url in transport.transport_list_registry)
239
t = transport.get_transport_from_url(url)
242
self.assertFalse(url in transport.transport_list_registry)
243
self.assertRaises(errors.UnsupportedProtocol,
244
transport.get_transport, url)
247
class TestMemoryTransport(tests.TestCase):
259
class TestMemoryTransport(TestCase):
249
261
def test_get_transport(self):
250
memory.MemoryTransport()
252
264
def test_clone(self):
253
t = memory.MemoryTransport()
254
self.assertTrue(isinstance(t, memory.MemoryTransport))
255
self.assertEqual("memory:///", t.clone("/").base)
265
transport = MemoryTransport()
266
self.assertTrue(isinstance(transport, MemoryTransport))
267
self.assertEqual("memory:///", transport.clone("/").base)
257
269
def test_abspath(self):
258
t = memory.MemoryTransport()
259
self.assertEqual("memory:///relpath", t.abspath('relpath'))
270
transport = MemoryTransport()
271
self.assertEqual("memory:///relpath", transport.abspath('relpath'))
261
273
def test_abspath_of_root(self):
262
t = memory.MemoryTransport()
263
self.assertEqual("memory:///", t.base)
264
self.assertEqual("memory:///", t.abspath('/'))
274
transport = MemoryTransport()
275
self.assertEqual("memory:///", transport.base)
276
self.assertEqual("memory:///", transport.abspath('/'))
266
278
def test_abspath_of_relpath_starting_at_root(self):
267
t = memory.MemoryTransport()
268
self.assertEqual("memory:///foo", t.abspath('/foo'))
279
transport = MemoryTransport()
280
self.assertEqual("memory:///foo", transport.abspath('/foo'))
270
282
def test_append_and_get(self):
271
t = memory.MemoryTransport()
272
t.append_bytes('path', 'content')
273
self.assertEqual(t.get('path').read(), 'content')
274
t.append_file('path', StringIO('content'))
275
self.assertEqual(t.get('path').read(), 'contentcontent')
283
transport = MemoryTransport()
284
transport.append_bytes('path', 'content')
285
self.assertEqual(transport.get('path').read(), 'content')
286
transport.append_file('path', StringIO('content'))
287
self.assertEqual(transport.get('path').read(), 'contentcontent')
277
289
def test_put_and_get(self):
278
t = memory.MemoryTransport()
279
t.put_file('path', StringIO('content'))
280
self.assertEqual(t.get('path').read(), 'content')
281
t.put_bytes('path', 'content')
282
self.assertEqual(t.get('path').read(), 'content')
290
transport = MemoryTransport()
291
transport.put_file('path', StringIO('content'))
292
self.assertEqual(transport.get('path').read(), 'content')
293
transport.put_bytes('path', 'content')
294
self.assertEqual(transport.get('path').read(), 'content')
284
296
def test_append_without_dir_fails(self):
285
t = memory.MemoryTransport()
286
self.assertRaises(errors.NoSuchFile,
287
t.append_bytes, 'dir/path', 'content')
297
transport = MemoryTransport()
298
self.assertRaises(NoSuchFile,
299
transport.append_bytes, 'dir/path', 'content')
289
301
def test_put_without_dir_fails(self):
290
t = memory.MemoryTransport()
291
self.assertRaises(errors.NoSuchFile,
292
t.put_file, 'dir/path', StringIO('content'))
302
transport = MemoryTransport()
303
self.assertRaises(NoSuchFile,
304
transport.put_file, 'dir/path', StringIO('content'))
294
306
def test_get_missing(self):
295
transport = memory.MemoryTransport()
296
self.assertRaises(errors.NoSuchFile, transport.get, 'foo')
307
transport = MemoryTransport()
308
self.assertRaises(NoSuchFile, transport.get, 'foo')
298
310
def test_has_missing(self):
299
t = memory.MemoryTransport()
300
self.assertEquals(False, t.has('foo'))
311
transport = MemoryTransport()
312
self.assertEquals(False, transport.has('foo'))
302
314
def test_has_present(self):
303
t = memory.MemoryTransport()
304
t.append_bytes('foo', 'content')
305
self.assertEquals(True, t.has('foo'))
315
transport = MemoryTransport()
316
transport.append_bytes('foo', 'content')
317
self.assertEquals(True, transport.has('foo'))
307
319
def test_list_dir(self):
308
t = memory.MemoryTransport()
309
t.put_bytes('foo', 'content')
311
t.put_bytes('dir/subfoo', 'content')
312
t.put_bytes('dirlike', 'content')
320
transport = MemoryTransport()
321
transport.put_bytes('foo', 'content')
322
transport.mkdir('dir')
323
transport.put_bytes('dir/subfoo', 'content')
324
transport.put_bytes('dirlike', 'content')
314
self.assertEquals(['dir', 'dirlike', 'foo'], sorted(t.list_dir('.')))
315
self.assertEquals(['subfoo'], sorted(t.list_dir('dir')))
326
self.assertEquals(['dir', 'dirlike', 'foo'], sorted(transport.list_dir('.')))
327
self.assertEquals(['subfoo'], sorted(transport.list_dir('dir')))
317
329
def test_mkdir(self):
318
t = memory.MemoryTransport()
320
t.append_bytes('dir/path', 'content')
321
self.assertEqual(t.get('dir/path').read(), 'content')
330
transport = MemoryTransport()
331
transport.mkdir('dir')
332
transport.append_bytes('dir/path', 'content')
333
self.assertEqual(transport.get('dir/path').read(), 'content')
323
335
def test_mkdir_missing_parent(self):
324
t = memory.MemoryTransport()
325
self.assertRaises(errors.NoSuchFile, t.mkdir, 'dir/dir')
336
transport = MemoryTransport()
337
self.assertRaises(NoSuchFile,
338
transport.mkdir, 'dir/dir')
327
340
def test_mkdir_twice(self):
328
t = memory.MemoryTransport()
330
self.assertRaises(errors.FileExists, t.mkdir, 'dir')
341
transport = MemoryTransport()
342
transport.mkdir('dir')
343
self.assertRaises(FileExists, transport.mkdir, 'dir')
332
345
def test_parameters(self):
333
t = memory.MemoryTransport()
334
self.assertEqual(True, t.listable())
335
self.assertEqual(False, t.is_readonly())
346
transport = MemoryTransport()
347
self.assertEqual(True, transport.listable())
348
self.assertEqual(False, transport.is_readonly())
337
350
def test_iter_files_recursive(self):
338
t = memory.MemoryTransport()
340
t.put_bytes('dir/foo', 'content')
341
t.put_bytes('dir/bar', 'content')
342
t.put_bytes('bar', 'content')
343
paths = set(t.iter_files_recursive())
351
transport = MemoryTransport()
352
transport.mkdir('dir')
353
transport.put_bytes('dir/foo', 'content')
354
transport.put_bytes('dir/bar', 'content')
355
transport.put_bytes('bar', 'content')
356
paths = set(transport.iter_files_recursive())
344
357
self.assertEqual(set(['dir/foo', 'dir/bar', 'bar']), paths)
346
359
def test_stat(self):
347
t = memory.MemoryTransport()
348
t.put_bytes('foo', 'content')
349
t.put_bytes('bar', 'phowar')
350
self.assertEqual(7, t.stat('foo').st_size)
351
self.assertEqual(6, t.stat('bar').st_size)
354
class ChrootDecoratorTransportTest(tests.TestCase):
360
transport = MemoryTransport()
361
transport.put_bytes('foo', 'content')
362
transport.put_bytes('bar', 'phowar')
363
self.assertEqual(7, transport.stat('foo').st_size)
364
self.assertEqual(6, transport.stat('bar').st_size)
367
class ChrootDecoratorTransportTest(TestCase):
355
368
"""Chroot decoration specific tests."""
357
370
def test_abspath(self):
358
371
# The abspath is always relative to the chroot_url.
359
server = chroot.ChrootServer(
360
transport.get_transport_from_url('memory:///foo/bar/'))
372
server = ChrootServer(get_transport('memory:///foo/bar/'))
361
373
self.start_server(server)
362
t = transport.get_transport_from_url(server.get_url())
363
self.assertEqual(server.get_url(), t.abspath('/'))
374
transport = get_transport(server.get_url())
375
self.assertEqual(server.get_url(), transport.abspath('/'))
365
subdir_t = t.clone('subdir')
366
self.assertEqual(server.get_url(), subdir_t.abspath('/'))
377
subdir_transport = transport.clone('subdir')
378
self.assertEqual(server.get_url(), subdir_transport.abspath('/'))
368
380
def test_clone(self):
369
server = chroot.ChrootServer(
370
transport.get_transport_from_url('memory:///foo/bar/'))
381
server = ChrootServer(get_transport('memory:///foo/bar/'))
371
382
self.start_server(server)
372
t = transport.get_transport_from_url(server.get_url())
383
transport = get_transport(server.get_url())
373
384
# relpath from root and root path are the same
374
relpath_cloned = t.clone('foo')
375
abspath_cloned = t.clone('/foo')
385
relpath_cloned = transport.clone('foo')
386
abspath_cloned = transport.clone('/foo')
376
387
self.assertEqual(server, relpath_cloned.server)
377
388
self.assertEqual(server, abspath_cloned.server)
401
411
This is so that it is not possible to escape a chroot by doing::
402
412
url = chroot_transport.base
403
413
parent_url = urlutils.join(url, '..')
404
new_t = transport.get_transport_from_url(parent_url)
414
new_transport = get_transport(parent_url)
406
server = chroot.ChrootServer(
407
transport.get_transport_from_url('memory:///path/'))
416
server = ChrootServer(get_transport('memory:///path/'))
408
417
self.start_server(server)
409
t = transport.get_transport_from_url(server.get_url())
418
transport = get_transport(server.get_url())
410
419
self.assertRaises(
411
errors.InvalidURLJoin, urlutils.join, t.base, '..')
414
class TestChrootServer(tests.TestCase):
420
InvalidURLJoin, urlutils.join, transport.base, '..')
423
class ChrootServerTest(TestCase):
416
425
def test_construct(self):
417
backing_transport = memory.MemoryTransport()
418
server = chroot.ChrootServer(backing_transport)
426
backing_transport = MemoryTransport()
427
server = ChrootServer(backing_transport)
419
428
self.assertEqual(backing_transport, server.backing_transport)
421
430
def test_setUp(self):
422
backing_transport = memory.MemoryTransport()
423
server = chroot.ChrootServer(backing_transport)
424
server.start_server()
425
self.addCleanup(server.stop_server)
426
self.assertTrue(server.scheme
427
in transport._get_protocol_handlers().keys())
431
backing_transport = MemoryTransport()
432
server = ChrootServer(backing_transport)
435
self.assertTrue(server.scheme in _get_protocol_handlers().keys())
429
def test_stop_server(self):
430
backing_transport = memory.MemoryTransport()
431
server = chroot.ChrootServer(backing_transport)
432
server.start_server()
434
self.assertFalse(server.scheme
435
in transport._get_protocol_handlers().keys())
439
def test_tearDown(self):
440
backing_transport = MemoryTransport()
441
server = ChrootServer(backing_transport)
444
self.assertFalse(server.scheme in _get_protocol_handlers().keys())
437
446
def test_get_url(self):
438
backing_transport = memory.MemoryTransport()
439
server = chroot.ChrootServer(backing_transport)
440
server.start_server()
441
self.addCleanup(server.stop_server)
442
self.assertEqual('chroot-%d:///' % id(server), server.get_url())
445
class PathFilteringDecoratorTransportTest(tests.TestCase):
447
backing_transport = MemoryTransport()
448
server = ChrootServer(backing_transport)
451
self.assertEqual('chroot-%d:///' % id(server), server.get_url())
456
class PathFilteringDecoratorTransportTest(TestCase):
446
457
"""Pathfilter decoration specific tests."""
448
459
def test_abspath(self):
449
460
# The abspath is always relative to the base of the backing transport.
450
server = pathfilter.PathFilteringServer(
451
transport.get_transport_from_url('memory:///foo/bar/'),
461
server = PathFilteringServer(get_transport('memory:///foo/bar/'),
453
server.start_server()
454
t = transport.get_transport_from_url(server.get_url())
455
self.assertEqual(server.get_url(), t.abspath('/'))
464
transport = get_transport(server.get_url())
465
self.assertEqual(server.get_url(), transport.abspath('/'))
457
subdir_t = t.clone('subdir')
458
self.assertEqual(server.get_url(), subdir_t.abspath('/'))
467
subdir_transport = transport.clone('subdir')
468
self.assertEqual(server.get_url(), subdir_transport.abspath('/'))
461
471
def make_pf_transport(self, filter_func=None):
462
472
"""Make a PathFilteringTransport backed by a MemoryTransport.
464
474
:param filter_func: by default this will be a no-op function. Use this
465
475
parameter to override it."""
466
476
if filter_func is None:
467
477
filter_func = lambda x: x
468
server = pathfilter.PathFilteringServer(
469
transport.get_transport_from_url('memory:///foo/bar/'), filter_func)
470
server.start_server()
471
self.addCleanup(server.stop_server)
472
return transport.get_transport_from_url(server.get_url())
478
server = PathFilteringServer(
479
get_transport('memory:///foo/bar/'), filter_func)
481
self.addCleanup(server.tearDown)
482
return get_transport(server.get_url())
474
484
def test__filter(self):
475
485
# _filter (with an identity func as filter_func) always returns
476
486
# paths relative to the base of the backing transport.
477
t = self.make_pf_transport()
478
self.assertEqual('foo', t._filter('foo'))
479
self.assertEqual('foo/bar', t._filter('foo/bar'))
480
self.assertEqual('', t._filter('..'))
481
self.assertEqual('', t._filter('/'))
487
transport = self.make_pf_transport()
488
self.assertEqual('foo', transport._filter('foo'))
489
self.assertEqual('foo/bar', transport._filter('foo/bar'))
490
self.assertEqual('', transport._filter('..'))
491
self.assertEqual('', transport._filter('/'))
482
492
# The base of the pathfiltering transport is taken into account too.
483
t = t.clone('subdir1/subdir2')
484
self.assertEqual('subdir1/subdir2/foo', t._filter('foo'))
485
self.assertEqual('subdir1/subdir2/foo/bar', t._filter('foo/bar'))
486
self.assertEqual('subdir1', t._filter('..'))
487
self.assertEqual('', t._filter('/'))
493
transport = transport.clone('subdir1/subdir2')
494
self.assertEqual('subdir1/subdir2/foo', transport._filter('foo'))
496
'subdir1/subdir2/foo/bar', transport._filter('foo/bar'))
497
self.assertEqual('subdir1', transport._filter('..'))
498
self.assertEqual('', transport._filter('/'))
489
500
def test_filter_invocation(self):
492
502
def filter(path):
493
503
filter_log.append(path)
495
t = self.make_pf_transport(filter)
505
transport = self.make_pf_transport(filter)
497
507
self.assertEqual(['abc'], filter_log)
498
508
del filter_log[:]
499
t.clone('abc').has('xyz')
509
transport.clone('abc').has('xyz')
500
510
self.assertEqual(['abc/xyz'], filter_log)
501
511
del filter_log[:]
512
transport.has('/abc')
503
513
self.assertEqual(['abc'], filter_log)
505
515
def test_clone(self):
506
t = self.make_pf_transport()
516
transport = self.make_pf_transport()
507
517
# relpath from root and root path are the same
508
relpath_cloned = t.clone('foo')
509
abspath_cloned = t.clone('/foo')
510
self.assertEqual(t.server, relpath_cloned.server)
511
self.assertEqual(t.server, abspath_cloned.server)
518
relpath_cloned = transport.clone('foo')
519
abspath_cloned = transport.clone('/foo')
520
self.assertEqual(transport.server, relpath_cloned.server)
521
self.assertEqual(transport.server, abspath_cloned.server)
513
523
def test_url_preserves_pathfiltering(self):
514
524
"""Calling get_transport on a pathfiltered transport's base should
519
529
otherwise) the filtering by doing::
520
530
url = filtered_transport.base
521
531
parent_url = urlutils.join(url, '..')
522
new_t = transport.get_transport_from_url(parent_url)
532
new_transport = get_transport(parent_url)
524
t = self.make_pf_transport()
525
new_t = transport.get_transport_from_url(t.base)
526
self.assertEqual(t.server, new_t.server)
527
self.assertEqual(t.base, new_t.base)
530
class ReadonlyDecoratorTransportTest(tests.TestCase):
534
transport = self.make_pf_transport()
535
new_transport = get_transport(transport.base)
536
self.assertEqual(transport.server, new_transport.server)
537
self.assertEqual(transport.base, new_transport.base)
540
class ReadonlyDecoratorTransportTest(TestCase):
531
541
"""Readonly decoration specific tests."""
533
543
def test_local_parameters(self):
544
import bzrlib.transport.readonly as readonly
534
545
# connect to . in readonly mode
535
t = readonly.ReadonlyTransportDecorator('readonly+.')
536
self.assertEqual(True, t.listable())
537
self.assertEqual(True, t.is_readonly())
546
transport = readonly.ReadonlyTransportDecorator('readonly+.')
547
self.assertEqual(True, transport.listable())
548
self.assertEqual(True, transport.is_readonly())
539
550
def test_http_parameters(self):
540
551
from bzrlib.tests.http_server import HttpServer
552
import bzrlib.transport.readonly as readonly
541
553
# connect to '.' via http which is not listable
542
554
server = HttpServer()
543
555
self.start_server(server)
544
t = transport.get_transport_from_url('readonly+' + server.get_url())
545
self.assertIsInstance(t, readonly.ReadonlyTransportDecorator)
546
self.assertEqual(False, t.listable())
547
self.assertEqual(True, t.is_readonly())
550
class FakeNFSDecoratorTests(tests.TestCaseInTempDir):
556
transport = get_transport('readonly+' + server.get_url())
557
self.failUnless(isinstance(transport,
558
readonly.ReadonlyTransportDecorator))
559
self.assertEqual(False, transport.listable())
560
self.assertEqual(True, transport.is_readonly())
563
class FakeNFSDecoratorTests(TestCaseInTempDir):
551
564
"""NFS decorator specific tests."""
553
566
def get_nfs_transport(self, url):
567
import bzrlib.transport.fakenfs as fakenfs
554
568
# connect to url with nfs decoration
555
569
return fakenfs.FakeNFSTransportDecorator('fakenfs+' + url)
557
571
def test_local_parameters(self):
558
572
# the listable and is_readonly parameters
559
573
# are not changed by the fakenfs decorator
560
t = self.get_nfs_transport('.')
561
self.assertEqual(True, t.listable())
562
self.assertEqual(False, t.is_readonly())
574
transport = self.get_nfs_transport('.')
575
self.assertEqual(True, transport.listable())
576
self.assertEqual(False, transport.is_readonly())
564
578
def test_http_parameters(self):
565
579
# the listable and is_readonly parameters
677
class TestTransportFromPath(tests.TestCaseInTempDir):
679
def test_with_path(self):
680
t = transport.get_transport_from_path(self.test_dir)
681
self.assertIsInstance(t, local.LocalTransport)
682
self.assertEquals(t.base.rstrip("/"),
683
urlutils.local_path_to_url(self.test_dir))
685
def test_with_url(self):
686
t = transport.get_transport_from_path("file:")
687
self.assertIsInstance(t, local.LocalTransport)
688
self.assertEquals(t.base.rstrip("/"),
689
urlutils.local_path_to_url(os.path.join(self.test_dir, "file:")))
692
class TestTransportFromUrl(tests.TestCaseInTempDir):
694
def test_with_path(self):
695
self.assertRaises(errors.InvalidURL, transport.get_transport_from_url,
698
def test_with_url(self):
699
url = urlutils.local_path_to_url(self.test_dir)
700
t = transport.get_transport_from_url(url)
701
self.assertIsInstance(t, local.LocalTransport)
702
self.assertEquals(t.base.rstrip("/"), url)
704
def test_with_url_and_segment_parameters(self):
705
url = urlutils.local_path_to_url(self.test_dir)+",branch=foo"
706
t = transport.get_transport_from_url(url)
707
self.assertIsInstance(t, local.LocalTransport)
708
self.assertEquals(t.base.rstrip("/"), url)
709
with open(os.path.join(self.test_dir, "afile"), 'w') as f:
711
self.assertTrue(t.has("afile"))
714
class TestLocalTransports(tests.TestCase):
693
class TestLocalTransports(TestCase):
716
695
def test_get_transport_from_abspath(self):
717
696
here = osutils.abspath('.')
718
t = transport.get_transport(here)
719
self.assertIsInstance(t, local.LocalTransport)
697
t = get_transport(here)
698
self.assertIsInstance(t, LocalTransport)
720
699
self.assertEquals(t.base, urlutils.local_path_to_url(here) + '/')
722
701
def test_get_transport_from_relpath(self):
723
702
here = osutils.abspath('.')
724
t = transport.get_transport('.')
725
self.assertIsInstance(t, local.LocalTransport)
703
t = get_transport('.')
704
self.assertIsInstance(t, LocalTransport)
726
705
self.assertEquals(t.base, urlutils.local_path_to_url('.') + '/')
728
707
def test_get_transport_from_local_url(self):
729
708
here = osutils.abspath('.')
730
709
here_url = urlutils.local_path_to_url(here) + '/'
731
t = transport.get_transport(here_url)
732
self.assertIsInstance(t, local.LocalTransport)
710
t = get_transport(here_url)
711
self.assertIsInstance(t, LocalTransport)
733
712
self.assertEquals(t.base, here_url)
735
714
def test_local_abspath(self):
736
715
here = osutils.abspath('.')
737
t = transport.get_transport(here)
716
t = get_transport(here)
738
717
self.assertEquals(t.local_abspath(''), here)
741
class TestLocalTransportWriteStream(tests.TestCaseWithTransport):
743
def test_local_fdatasync_calls_fdatasync(self):
744
"""Check fdatasync on a stream tries to flush the data to the OS.
746
We can't easily observe the external effect but we can at least see
750
fdatasync = getattr(os, 'fdatasync', sentinel)
751
if fdatasync is sentinel:
752
raise tests.TestNotApplicable('fdatasync not supported')
753
t = self.get_transport('.')
754
calls = self.recordCalls(os, 'fdatasync')
755
w = t.open_write_stream('out')
758
with open('out', 'rb') as f:
759
# Should have been flushed.
760
self.assertEquals(f.read(), 'foo')
761
self.assertEquals(len(calls), 1, calls)
763
def test_missing_directory(self):
764
t = self.get_transport('.')
765
self.assertRaises(errors.NoSuchFile, t.open_write_stream, 'dir/foo')
768
class TestWin32LocalTransport(tests.TestCase):
720
class TestWin32LocalTransport(TestCase):
770
722
def test_unc_clone_to_root(self):
771
723
# Win32 UNC path like \\HOST\path
772
724
# clone to root should stop at least at \\HOST part
774
t = local.EmulatedWin32LocalTransport('file://HOST/path/to/some/dir/')
726
t = EmulatedWin32LocalTransport('file://HOST/path/to/some/dir/')
775
727
for i in xrange(4):
776
728
t = t.clone('..')
777
729
self.assertEquals(t.base, 'file://HOST/')
780
732
self.assertEquals(t.base, 'file://HOST/')
783
class TestConnectedTransport(tests.TestCase):
735
class TestConnectedTransport(TestCase):
784
736
"""Tests for connected to remote server transports"""
786
738
def test_parse_url(self):
787
t = transport.ConnectedTransport(
788
'http://simple.example.com/home/source')
789
self.assertEquals(t._parsed_url.host, 'simple.example.com')
790
self.assertEquals(t._parsed_url.port, None)
791
self.assertEquals(t._parsed_url.path, '/home/source/')
792
self.assertTrue(t._parsed_url.user is None)
793
self.assertTrue(t._parsed_url.password is None)
739
t = ConnectedTransport('http://simple.example.com/home/source')
740
self.assertEquals(t._host, 'simple.example.com')
741
self.assertEquals(t._port, None)
742
self.assertEquals(t._path, '/home/source/')
743
self.failUnless(t._user is None)
744
self.failUnless(t._password is None)
795
746
self.assertEquals(t.base, 'http://simple.example.com/home/source/')
797
748
def test_parse_url_with_at_in_user(self):
799
t = transport.ConnectedTransport('ftp://user@host.com@www.host.com/')
800
self.assertEquals(t._parsed_url.user, 'user@host.com')
750
t = ConnectedTransport('ftp://user@host.com@www.host.com/')
751
self.assertEquals(t._user, 'user@host.com')
802
753
def test_parse_quoted_url(self):
803
t = transport.ConnectedTransport(
804
'http://ro%62ey:h%40t@ex%41mple.com:2222/path')
805
self.assertEquals(t._parsed_url.host, 'exAmple.com')
806
self.assertEquals(t._parsed_url.port, 2222)
807
self.assertEquals(t._parsed_url.user, 'robey')
808
self.assertEquals(t._parsed_url.password, 'h@t')
809
self.assertEquals(t._parsed_url.path, '/path/')
754
t = ConnectedTransport('http://ro%62ey:h%40t@ex%41mple.com:2222/path')
755
self.assertEquals(t._host, 'exAmple.com')
756
self.assertEquals(t._port, 2222)
757
self.assertEquals(t._user, 'robey')
758
self.assertEquals(t._password, 'h@t')
759
self.assertEquals(t._path, '/path/')
811
761
# Base should not keep track of the password
812
self.assertEquals(t.base, 'http://ro%62ey@ex%41mple.com:2222/path/')
762
self.assertEquals(t.base, 'http://robey@exAmple.com:2222/path/')
814
764
def test_parse_invalid_url(self):
815
765
self.assertRaises(errors.InvalidURL,
816
transport.ConnectedTransport,
817
767
'sftp://lily.org:~janneke/public/bzr/gub')
819
769
def test_relpath(self):
820
t = transport.ConnectedTransport('sftp://user@host.com/abs/path')
770
t = ConnectedTransport('sftp://user@host.com/abs/path')
822
self.assertEquals(t.relpath('sftp://user@host.com/abs/path/sub'),
772
self.assertEquals(t.relpath('sftp://user@host.com/abs/path/sub'), 'sub')
824
773
self.assertRaises(errors.PathNotChild, t.relpath,
825
774
'http://user@host.com/abs/path/sub')
826
775
self.assertRaises(errors.PathNotChild, t.relpath,
865
814
self.assertIs(new_password, c._get_credentials())
868
class TestReusedTransports(tests.TestCase):
817
class TestReusedTransports(TestCase):
869
818
"""Tests for transport reuse"""
871
820
def test_reuse_same_transport(self):
872
821
possible_transports = []
873
t1 = transport.get_transport_from_url('http://foo/',
874
possible_transports=possible_transports)
822
t1 = get_transport('http://foo/',
823
possible_transports=possible_transports)
875
824
self.assertEqual([t1], possible_transports)
876
t2 = transport.get_transport_from_url('http://foo/',
877
possible_transports=[t1])
825
t2 = get_transport('http://foo/', possible_transports=[t1])
878
826
self.assertIs(t1, t2)
880
828
# Also check that final '/' are handled correctly
881
t3 = transport.get_transport_from_url('http://foo/path/')
882
t4 = transport.get_transport_from_url('http://foo/path',
883
possible_transports=[t3])
829
t3 = get_transport('http://foo/path/')
830
t4 = get_transport('http://foo/path', possible_transports=[t3])
884
831
self.assertIs(t3, t4)
886
t5 = transport.get_transport_from_url('http://foo/path')
887
t6 = transport.get_transport_from_url('http://foo/path/',
888
possible_transports=[t5])
833
t5 = get_transport('http://foo/path')
834
t6 = get_transport('http://foo/path/', possible_transports=[t5])
889
835
self.assertIs(t5, t6)
891
837
def test_don_t_reuse_different_transport(self):
892
t1 = transport.get_transport_from_url('http://foo/path')
893
t2 = transport.get_transport_from_url('http://bar/path',
894
possible_transports=[t1])
838
t1 = get_transport('http://foo/path')
839
t2 = get_transport('http://bar/path', possible_transports=[t1])
895
840
self.assertIsNot(t1, t2)
898
class TestTransportTrace(tests.TestCase):
843
class TestTransportTrace(TestCase):
900
def test_decorator(self):
901
t = transport.get_transport_from_url('trace+memory://')
846
transport = get_transport('trace+memory://')
902
847
self.assertIsInstance(
903
t, bzrlib.transport.trace.TransportTraceDecorator)
848
transport, bzrlib.transport.trace.TransportTraceDecorator)
905
850
def test_clone_preserves_activity(self):
906
t = transport.get_transport_from_url('trace+memory://')
908
self.assertTrue(t is not t2)
909
self.assertTrue(t._activity is t2._activity)
851
transport = get_transport('trace+memory://')
852
transport2 = transport.clone('.')
853
self.assertTrue(transport is not transport2)
854
self.assertTrue(transport._activity is transport2._activity)
911
856
# the following specific tests are for the operations that have made use of
912
857
# logging in tests; we could test every single operation but doing that
913
858
# still won't cause a test failure when the top level Transport API
914
859
# changes; so there is little return doing that.
915
860
def test_get(self):
916
t = transport.get_transport_from_url('trace+memory:///')
917
t.put_bytes('foo', 'barish')
861
transport = get_transport('trace+memory:///')
862
transport.put_bytes('foo', 'barish')
919
864
expected_result = []
920
865
# put_bytes records the bytes, not the content to avoid memory
922
867
expected_result.append(('put_bytes', 'foo', 6, None))
923
868
# get records the file name only.
924
869
expected_result.append(('get', 'foo'))
925
self.assertEqual(expected_result, t._activity)
870
self.assertEqual(expected_result, transport._activity)
927
872
def test_readv(self):
928
t = transport.get_transport_from_url('trace+memory:///')
929
t.put_bytes('foo', 'barish')
930
list(t.readv('foo', [(0, 1), (3, 2)],
931
adjust_for_latency=True, upper_limit=6))
873
transport = get_transport('trace+memory:///')
874
transport.put_bytes('foo', 'barish')
875
list(transport.readv('foo', [(0, 1), (3, 2)], adjust_for_latency=True,
932
877
expected_result = []
933
878
# put_bytes records the bytes, not the content to avoid memory
935
880
expected_result.append(('put_bytes', 'foo', 6, None))
936
881
# readv records the supplied offset request
937
882
expected_result.append(('readv', 'foo', [(0, 1), (3, 2)], True, 6))
938
self.assertEqual(expected_result, t._activity)
883
self.assertEqual(expected_result, transport._activity)
941
886
class TestSSHConnections(tests.TestCaseWithTransport):
943
888
def test_bzr_connect_to_bzr_ssh(self):
944
"""get_transport of a bzr+ssh:// behaves correctly.
889
"""User acceptance that get_transport of a bzr+ssh:// behaves correctly.
946
891
bzr+ssh:// should cause bzr to run a remote bzr smart server over SSH.