28
transport as _mod_transport,
32
from bzrlib.directory_service import directories
33
31
from bzrlib.transport import (
43
import bzrlib.transport.trace
44
from bzrlib.tests import (
36
from bzrlib.errors import (DependencyNotPresent,
44
from bzrlib.tests import features, TestCase, TestCaseInTempDir
45
from bzrlib.transport import (_clear_protocol_handlers,
48
_get_protocol_handlers,
49
_set_protocol_handlers,
50
_get_transport_modules,
53
register_lazy_transport,
54
register_transport_proto,
57
from bzrlib.transport.chroot import ChrootServer
58
from bzrlib.transport.local import (LocalTransport,
59
EmulatedWin32LocalTransport)
60
from bzrlib.transport.pathfilter import PathFilteringServer
50
63
# TODO: Should possibly split transport-specific tests into their own files.
53
class TestTransport(tests.TestCase):
66
class TestTransport(TestCase):
54
67
"""Test the non transport-concrete class functionality."""
56
69
def test__get_set_protocol_handlers(self):
57
handlers = transport._get_protocol_handlers()
58
self.assertNotEqual([], handlers.keys())
59
transport._clear_protocol_handlers()
60
self.addCleanup(transport._set_protocol_handlers, handlers)
61
self.assertEqual([], transport._get_protocol_handlers().keys())
70
handlers = _get_protocol_handlers()
71
self.assertNotEqual([], handlers.keys( ))
73
_clear_protocol_handlers()
74
self.assertEqual([], _get_protocol_handlers().keys())
76
_set_protocol_handlers(handlers)
63
78
def test_get_transport_modules(self):
64
handlers = transport._get_protocol_handlers()
65
self.addCleanup(transport._set_protocol_handlers, handlers)
79
handlers = _get_protocol_handlers()
66
80
# don't pollute the current handlers
67
transport._clear_protocol_handlers()
81
_clear_protocol_handlers()
69
82
class SampleHandler(object):
70
83
"""I exist, isnt that enough?"""
71
transport._clear_protocol_handlers()
72
transport.register_transport_proto('foo')
73
transport.register_lazy_transport('foo',
74
'bzrlib.tests.test_transport',
75
'TestTransport.SampleHandler')
76
transport.register_transport_proto('bar')
77
transport.register_lazy_transport('bar',
78
'bzrlib.tests.test_transport',
79
'TestTransport.SampleHandler')
80
self.assertEqual([SampleHandler.__module__,
81
'bzrlib.transport.chroot',
82
'bzrlib.transport.pathfilter'],
83
transport._get_transport_modules())
85
_clear_protocol_handlers()
86
register_transport_proto('foo')
87
register_lazy_transport('foo', 'bzrlib.tests.test_transport',
88
'TestTransport.SampleHandler')
89
register_transport_proto('bar')
90
register_lazy_transport('bar', 'bzrlib.tests.test_transport',
91
'TestTransport.SampleHandler')
92
self.assertEqual([SampleHandler.__module__,
93
'bzrlib.transport.chroot',
94
'bzrlib.transport.pathfilter'],
95
_get_transport_modules())
97
_set_protocol_handlers(handlers)
85
99
def test_transport_dependency(self):
86
100
"""Transport with missing dependency causes no error"""
87
saved_handlers = transport._get_protocol_handlers()
88
self.addCleanup(transport._set_protocol_handlers, saved_handlers)
101
saved_handlers = _get_protocol_handlers()
89
102
# don't pollute the current handlers
90
transport._clear_protocol_handlers()
91
transport.register_transport_proto('foo')
92
transport.register_lazy_transport(
93
'foo', 'bzrlib.tests.test_transport', 'BadTransportHandler')
103
_clear_protocol_handlers()
95
transport.get_transport_from_url('foo://fooserver/foo')
96
except errors.UnsupportedProtocol, e:
98
self.assertEquals('Unsupported protocol'
99
' for url "foo://fooserver/foo":'
100
' Unable to import library "some_lib":'
101
' testing missing dependency', str(e))
103
self.fail('Did not raise UnsupportedProtocol')
105
register_transport_proto('foo')
106
register_lazy_transport('foo', 'bzrlib.tests.test_transport',
107
'BadTransportHandler')
109
get_transport('foo://fooserver/foo')
110
except UnsupportedProtocol, e:
112
self.assertEquals('Unsupported protocol'
113
' for url "foo://fooserver/foo":'
114
' Unable to import library "some_lib":'
115
' testing missing dependency', str(e))
117
self.fail('Did not raise UnsupportedProtocol')
119
# restore original values
120
_set_protocol_handlers(saved_handlers)
105
122
def test_transport_fallback(self):
106
123
"""Transport with missing dependency causes no error"""
107
saved_handlers = transport._get_protocol_handlers()
108
self.addCleanup(transport._set_protocol_handlers, saved_handlers)
109
transport._clear_protocol_handlers()
110
transport.register_transport_proto('foo')
111
transport.register_lazy_transport(
112
'foo', 'bzrlib.tests.test_transport', 'BackupTransportHandler')
113
transport.register_lazy_transport(
114
'foo', 'bzrlib.tests.test_transport', 'BadTransportHandler')
115
t = transport.get_transport_from_url('foo://fooserver/foo')
116
self.assertTrue(isinstance(t, BackupTransportHandler))
124
saved_handlers = _get_protocol_handlers()
126
_clear_protocol_handlers()
127
register_transport_proto('foo')
128
register_lazy_transport('foo', 'bzrlib.tests.test_transport',
129
'BackupTransportHandler')
130
register_lazy_transport('foo', 'bzrlib.tests.test_transport',
131
'BadTransportHandler')
132
t = get_transport('foo://fooserver/foo')
133
self.assertTrue(isinstance(t, BackupTransportHandler))
135
_set_protocol_handlers(saved_handlers)
118
137
def test_ssh_hints(self):
119
138
"""Transport ssh:// should raise an error pointing out bzr+ssh://"""
121
transport.get_transport_from_url('ssh://fooserver/foo')
122
except errors.UnsupportedProtocol, e:
140
get_transport('ssh://fooserver/foo')
141
except UnsupportedProtocol, e:
124
143
self.assertEquals('Unsupported protocol'
125
144
' for url "ssh://fooserver/foo":'
126
' bzr supports bzr+ssh to operate over ssh,'
127
' use "bzr+ssh://fooserver/foo".',
145
' bzr supports bzr+ssh to operate over ssh, use "bzr+ssh://fooserver/foo".',
130
148
self.fail('Did not raise UnsupportedProtocol')
132
150
def test_LateReadError(self):
133
151
"""The LateReadError helper should raise on read()."""
134
a_file = transport.LateReadError('a path')
152
a_file = LateReadError('a path')
137
except errors.ReadError, error:
155
except ReadError, error:
138
156
self.assertEqual('a path', error.path)
139
self.assertRaises(errors.ReadError, a_file.read, 40)
157
self.assertRaises(ReadError, a_file.read, 40)
160
def test__combine_paths(self):
162
self.assertEqual('/home/sarah/project/foo',
163
t._combine_paths('/home/sarah', 'project/foo'))
164
self.assertEqual('/etc',
165
t._combine_paths('/home/sarah', '../../etc'))
166
self.assertEqual('/etc',
167
t._combine_paths('/home/sarah', '../../../etc'))
168
self.assertEqual('/etc',
169
t._combine_paths('/home/sarah', '/etc'))
142
171
def test_local_abspath_non_local_transport(self):
143
172
# the base implementation should throw
144
173
t = memory.MemoryTransport()
202
231
def test_coalesce_fudge(self):
203
232
self.check([(10, 30, [(0, 10), (20, 10)]),
204
(100, 10, [(0, 10)]),
233
(100, 10, [(0, 10),]),
205
234
], [(10, 10), (30, 10), (100, 10)],
208
237
def test_coalesce_max_size(self):
209
238
self.check([(10, 20, [(0, 10), (10, 10)]),
210
239
(30, 50, [(0, 50)]),
211
240
# If one range is above max_size, it gets its own coalesced
213
(100, 80, [(0, 80)]),],
242
(100, 80, [(0, 80),]),],
214
243
[(10, 10), (20, 10), (30, 50), (100, 80)],
217
247
def test_coalesce_no_max_size(self):
218
self.check([(10, 170, [(0, 10), (10, 10), (20, 50), (70, 100)])],
248
self.check([(10, 170, [(0, 10), (10, 10), (20, 50), (70, 100)]),],
219
249
[(10, 10), (20, 10), (30, 50), (80, 100)],
222
252
def test_coalesce_default_limit(self):
223
253
# By default we use a 100MB max size.
224
ten_mb = 10 * 1024 * 1024
225
self.check([(0, 10 * ten_mb, [(i * ten_mb, ten_mb) for i in range(10)]),
254
ten_mb = 10*1024*1024
255
self.check([(0, 10*ten_mb, [(i*ten_mb, ten_mb) for i in range(10)]),
226
256
(10*ten_mb, ten_mb, [(0, ten_mb)])],
227
257
[(i*ten_mb, ten_mb) for i in range(11)])
228
self.check([(0, 11 * ten_mb, [(i * ten_mb, ten_mb) for i in range(11)])],
229
[(i * ten_mb, ten_mb) for i in range(11)],
258
self.check([(0, 11*ten_mb, [(i*ten_mb, ten_mb) for i in range(11)]),],
259
[(i*ten_mb, ten_mb) for i in range(11)],
230
260
max_size=1*1024*1024*1024)
233
class TestMemoryServer(tests.TestCase):
263
class TestMemoryServer(TestCase):
235
265
def test_create_server(self):
236
266
server = memory.MemoryServer()
237
267
server.start_server()
238
268
url = server.get_url()
239
self.assertTrue(url in transport.transport_list_registry)
240
t = transport.get_transport_from_url(url)
269
self.assertTrue(url in _mod_transport.transport_list_registry)
270
t = _mod_transport.get_transport(url)
242
272
server.stop_server()
243
self.assertFalse(url in transport.transport_list_registry)
273
self.assertFalse(url in _mod_transport.transport_list_registry)
244
274
self.assertRaises(errors.UnsupportedProtocol,
245
transport.get_transport, url)
248
class TestMemoryTransport(tests.TestCase):
275
_mod_transport.get_transport, url)
278
class TestMemoryTransport(TestCase):
250
280
def test_get_transport(self):
251
281
memory.MemoryTransport()
253
283
def test_clone(self):
254
t = memory.MemoryTransport()
255
self.assertTrue(isinstance(t, memory.MemoryTransport))
256
self.assertEqual("memory:///", t.clone("/").base)
284
transport = memory.MemoryTransport()
285
self.assertTrue(isinstance(transport, memory.MemoryTransport))
286
self.assertEqual("memory:///", transport.clone("/").base)
258
288
def test_abspath(self):
259
t = memory.MemoryTransport()
260
self.assertEqual("memory:///relpath", t.abspath('relpath'))
289
transport = memory.MemoryTransport()
290
self.assertEqual("memory:///relpath", transport.abspath('relpath'))
262
292
def test_abspath_of_root(self):
263
t = memory.MemoryTransport()
264
self.assertEqual("memory:///", t.base)
265
self.assertEqual("memory:///", t.abspath('/'))
293
transport = memory.MemoryTransport()
294
self.assertEqual("memory:///", transport.base)
295
self.assertEqual("memory:///", transport.abspath('/'))
267
297
def test_abspath_of_relpath_starting_at_root(self):
268
t = memory.MemoryTransport()
269
self.assertEqual("memory:///foo", t.abspath('/foo'))
298
transport = memory.MemoryTransport()
299
self.assertEqual("memory:///foo", transport.abspath('/foo'))
271
301
def test_append_and_get(self):
272
t = memory.MemoryTransport()
273
t.append_bytes('path', 'content')
274
self.assertEqual(t.get('path').read(), 'content')
275
t.append_file('path', StringIO('content'))
276
self.assertEqual(t.get('path').read(), 'contentcontent')
302
transport = memory.MemoryTransport()
303
transport.append_bytes('path', 'content')
304
self.assertEqual(transport.get('path').read(), 'content')
305
transport.append_file('path', StringIO('content'))
306
self.assertEqual(transport.get('path').read(), 'contentcontent')
278
308
def test_put_and_get(self):
279
t = memory.MemoryTransport()
280
t.put_file('path', StringIO('content'))
281
self.assertEqual(t.get('path').read(), 'content')
282
t.put_bytes('path', 'content')
283
self.assertEqual(t.get('path').read(), 'content')
309
transport = memory.MemoryTransport()
310
transport.put_file('path', StringIO('content'))
311
self.assertEqual(transport.get('path').read(), 'content')
312
transport.put_bytes('path', 'content')
313
self.assertEqual(transport.get('path').read(), 'content')
285
315
def test_append_without_dir_fails(self):
286
t = memory.MemoryTransport()
287
self.assertRaises(errors.NoSuchFile,
288
t.append_bytes, 'dir/path', 'content')
316
transport = memory.MemoryTransport()
317
self.assertRaises(NoSuchFile,
318
transport.append_bytes, 'dir/path', 'content')
290
320
def test_put_without_dir_fails(self):
291
t = memory.MemoryTransport()
292
self.assertRaises(errors.NoSuchFile,
293
t.put_file, 'dir/path', StringIO('content'))
321
transport = memory.MemoryTransport()
322
self.assertRaises(NoSuchFile,
323
transport.put_file, 'dir/path', StringIO('content'))
295
325
def test_get_missing(self):
296
326
transport = memory.MemoryTransport()
297
self.assertRaises(errors.NoSuchFile, transport.get, 'foo')
327
self.assertRaises(NoSuchFile, transport.get, 'foo')
299
329
def test_has_missing(self):
300
t = memory.MemoryTransport()
301
self.assertEquals(False, t.has('foo'))
330
transport = memory.MemoryTransport()
331
self.assertEquals(False, transport.has('foo'))
303
333
def test_has_present(self):
304
t = memory.MemoryTransport()
305
t.append_bytes('foo', 'content')
306
self.assertEquals(True, t.has('foo'))
334
transport = memory.MemoryTransport()
335
transport.append_bytes('foo', 'content')
336
self.assertEquals(True, transport.has('foo'))
308
338
def test_list_dir(self):
309
t = memory.MemoryTransport()
310
t.put_bytes('foo', 'content')
312
t.put_bytes('dir/subfoo', 'content')
313
t.put_bytes('dirlike', 'content')
339
transport = memory.MemoryTransport()
340
transport.put_bytes('foo', 'content')
341
transport.mkdir('dir')
342
transport.put_bytes('dir/subfoo', 'content')
343
transport.put_bytes('dirlike', 'content')
315
self.assertEquals(['dir', 'dirlike', 'foo'], sorted(t.list_dir('.')))
316
self.assertEquals(['subfoo'], sorted(t.list_dir('dir')))
345
self.assertEquals(['dir', 'dirlike', 'foo'], sorted(transport.list_dir('.')))
346
self.assertEquals(['subfoo'], sorted(transport.list_dir('dir')))
318
348
def test_mkdir(self):
319
t = memory.MemoryTransport()
321
t.append_bytes('dir/path', 'content')
322
self.assertEqual(t.get('dir/path').read(), 'content')
349
transport = memory.MemoryTransport()
350
transport.mkdir('dir')
351
transport.append_bytes('dir/path', 'content')
352
self.assertEqual(transport.get('dir/path').read(), 'content')
324
354
def test_mkdir_missing_parent(self):
325
t = memory.MemoryTransport()
326
self.assertRaises(errors.NoSuchFile, t.mkdir, 'dir/dir')
355
transport = memory.MemoryTransport()
356
self.assertRaises(NoSuchFile,
357
transport.mkdir, 'dir/dir')
328
359
def test_mkdir_twice(self):
329
t = memory.MemoryTransport()
331
self.assertRaises(errors.FileExists, t.mkdir, 'dir')
360
transport = memory.MemoryTransport()
361
transport.mkdir('dir')
362
self.assertRaises(FileExists, transport.mkdir, 'dir')
333
364
def test_parameters(self):
334
t = memory.MemoryTransport()
335
self.assertEqual(True, t.listable())
336
self.assertEqual(False, t.is_readonly())
365
transport = memory.MemoryTransport()
366
self.assertEqual(True, transport.listable())
367
self.assertEqual(False, transport.is_readonly())
338
369
def test_iter_files_recursive(self):
339
t = memory.MemoryTransport()
341
t.put_bytes('dir/foo', 'content')
342
t.put_bytes('dir/bar', 'content')
343
t.put_bytes('bar', 'content')
344
paths = set(t.iter_files_recursive())
370
transport = memory.MemoryTransport()
371
transport.mkdir('dir')
372
transport.put_bytes('dir/foo', 'content')
373
transport.put_bytes('dir/bar', 'content')
374
transport.put_bytes('bar', 'content')
375
paths = set(transport.iter_files_recursive())
345
376
self.assertEqual(set(['dir/foo', 'dir/bar', 'bar']), paths)
347
378
def test_stat(self):
348
t = memory.MemoryTransport()
349
t.put_bytes('foo', 'content')
350
t.put_bytes('bar', 'phowar')
351
self.assertEqual(7, t.stat('foo').st_size)
352
self.assertEqual(6, t.stat('bar').st_size)
355
class ChrootDecoratorTransportTest(tests.TestCase):
379
transport = memory.MemoryTransport()
380
transport.put_bytes('foo', 'content')
381
transport.put_bytes('bar', 'phowar')
382
self.assertEqual(7, transport.stat('foo').st_size)
383
self.assertEqual(6, transport.stat('bar').st_size)
386
class ChrootDecoratorTransportTest(TestCase):
356
387
"""Chroot decoration specific tests."""
358
389
def test_abspath(self):
359
390
# The abspath is always relative to the chroot_url.
360
server = chroot.ChrootServer(
361
transport.get_transport_from_url('memory:///foo/bar/'))
391
server = ChrootServer(get_transport('memory:///foo/bar/'))
362
392
self.start_server(server)
363
t = transport.get_transport_from_url(server.get_url())
364
self.assertEqual(server.get_url(), t.abspath('/'))
393
transport = get_transport(server.get_url())
394
self.assertEqual(server.get_url(), transport.abspath('/'))
366
subdir_t = t.clone('subdir')
367
self.assertEqual(server.get_url(), subdir_t.abspath('/'))
396
subdir_transport = transport.clone('subdir')
397
self.assertEqual(server.get_url(), subdir_transport.abspath('/'))
369
399
def test_clone(self):
370
server = chroot.ChrootServer(
371
transport.get_transport_from_url('memory:///foo/bar/'))
400
server = ChrootServer(get_transport('memory:///foo/bar/'))
372
401
self.start_server(server)
373
t = transport.get_transport_from_url(server.get_url())
402
transport = get_transport(server.get_url())
374
403
# relpath from root and root path are the same
375
relpath_cloned = t.clone('foo')
376
abspath_cloned = t.clone('/foo')
404
relpath_cloned = transport.clone('foo')
405
abspath_cloned = transport.clone('/foo')
377
406
self.assertEqual(server, relpath_cloned.server)
378
407
self.assertEqual(server, abspath_cloned.server)
402
430
This is so that it is not possible to escape a chroot by doing::
403
431
url = chroot_transport.base
404
432
parent_url = urlutils.join(url, '..')
405
new_t = transport.get_transport_from_url(parent_url)
433
new_transport = get_transport(parent_url)
407
server = chroot.ChrootServer(
408
transport.get_transport_from_url('memory:///path/'))
435
server = ChrootServer(get_transport('memory:///path/'))
409
436
self.start_server(server)
410
t = transport.get_transport_from_url(server.get_url())
437
transport = get_transport(server.get_url())
411
438
self.assertRaises(
412
errors.InvalidURLJoin, urlutils.join, t.base, '..')
415
class TestChrootServer(tests.TestCase):
439
InvalidURLJoin, urlutils.join, transport.base, '..')
442
class ChrootServerTest(TestCase):
417
444
def test_construct(self):
418
445
backing_transport = memory.MemoryTransport()
419
server = chroot.ChrootServer(backing_transport)
446
server = ChrootServer(backing_transport)
420
447
self.assertEqual(backing_transport, server.backing_transport)
422
449
def test_setUp(self):
423
450
backing_transport = memory.MemoryTransport()
424
server = chroot.ChrootServer(backing_transport)
451
server = ChrootServer(backing_transport)
425
452
server.start_server()
426
self.addCleanup(server.stop_server)
427
self.assertTrue(server.scheme
428
in transport._get_protocol_handlers().keys())
454
self.assertTrue(server.scheme in _get_protocol_handlers().keys())
430
458
def test_stop_server(self):
431
459
backing_transport = memory.MemoryTransport()
432
server = chroot.ChrootServer(backing_transport)
460
server = ChrootServer(backing_transport)
433
461
server.start_server()
434
462
server.stop_server()
435
self.assertFalse(server.scheme
436
in transport._get_protocol_handlers().keys())
463
self.assertFalse(server.scheme in _get_protocol_handlers().keys())
438
465
def test_get_url(self):
439
466
backing_transport = memory.MemoryTransport()
440
server = chroot.ChrootServer(backing_transport)
467
server = ChrootServer(backing_transport)
441
468
server.start_server()
442
self.addCleanup(server.stop_server)
443
self.assertEqual('chroot-%d:///' % id(server), server.get_url())
446
class TestHooks(tests.TestCase):
447
"""Basic tests for transport hooks"""
449
def _get_connected_transport(self):
450
return transport.ConnectedTransport("bogus:nowhere")
452
def test_transporthooks_initialisation(self):
453
"""Check all expected transport hook points are set up"""
454
hookpoint = transport.TransportHooks()
455
self.assertTrue("post_connect" in hookpoint,
456
"post_connect not in %s" % (hookpoint,))
458
def test_post_connect(self):
459
"""Ensure the post_connect hook is called when _set_transport is"""
461
transport.Transport.hooks.install_named_hook("post_connect",
463
t = self._get_connected_transport()
464
self.assertLength(0, calls)
465
t._set_connection("connection", "auth")
466
self.assertEqual(calls, [t])
469
class PathFilteringDecoratorTransportTest(tests.TestCase):
470
self.assertEqual('chroot-%d:///' % id(server), server.get_url())
475
class PathFilteringDecoratorTransportTest(TestCase):
470
476
"""Pathfilter decoration specific tests."""
472
478
def test_abspath(self):
473
479
# The abspath is always relative to the base of the backing transport.
474
server = pathfilter.PathFilteringServer(
475
transport.get_transport_from_url('memory:///foo/bar/'),
480
server = PathFilteringServer(get_transport('memory:///foo/bar/'),
477
482
server.start_server()
478
t = transport.get_transport_from_url(server.get_url())
479
self.assertEqual(server.get_url(), t.abspath('/'))
483
transport = get_transport(server.get_url())
484
self.assertEqual(server.get_url(), transport.abspath('/'))
481
subdir_t = t.clone('subdir')
482
self.assertEqual(server.get_url(), subdir_t.abspath('/'))
486
subdir_transport = transport.clone('subdir')
487
self.assertEqual(server.get_url(), subdir_transport.abspath('/'))
483
488
server.stop_server()
485
490
def make_pf_transport(self, filter_func=None):
486
491
"""Make a PathFilteringTransport backed by a MemoryTransport.
488
493
:param filter_func: by default this will be a no-op function. Use this
489
494
parameter to override it."""
490
495
if filter_func is None:
491
496
filter_func = lambda x: x
492
server = pathfilter.PathFilteringServer(
493
transport.get_transport_from_url('memory:///foo/bar/'), filter_func)
497
server = PathFilteringServer(
498
get_transport('memory:///foo/bar/'), filter_func)
494
499
server.start_server()
495
500
self.addCleanup(server.stop_server)
496
return transport.get_transport_from_url(server.get_url())
501
return get_transport(server.get_url())
498
503
def test__filter(self):
499
504
# _filter (with an identity func as filter_func) always returns
500
505
# paths relative to the base of the backing transport.
501
t = self.make_pf_transport()
502
self.assertEqual('foo', t._filter('foo'))
503
self.assertEqual('foo/bar', t._filter('foo/bar'))
504
self.assertEqual('', t._filter('..'))
505
self.assertEqual('', t._filter('/'))
506
transport = self.make_pf_transport()
507
self.assertEqual('foo', transport._filter('foo'))
508
self.assertEqual('foo/bar', transport._filter('foo/bar'))
509
self.assertEqual('', transport._filter('..'))
510
self.assertEqual('', transport._filter('/'))
506
511
# The base of the pathfiltering transport is taken into account too.
507
t = t.clone('subdir1/subdir2')
508
self.assertEqual('subdir1/subdir2/foo', t._filter('foo'))
509
self.assertEqual('subdir1/subdir2/foo/bar', t._filter('foo/bar'))
510
self.assertEqual('subdir1', t._filter('..'))
511
self.assertEqual('', t._filter('/'))
512
transport = transport.clone('subdir1/subdir2')
513
self.assertEqual('subdir1/subdir2/foo', transport._filter('foo'))
515
'subdir1/subdir2/foo/bar', transport._filter('foo/bar'))
516
self.assertEqual('subdir1', transport._filter('..'))
517
self.assertEqual('', transport._filter('/'))
513
519
def test_filter_invocation(self):
516
521
def filter(path):
517
522
filter_log.append(path)
519
t = self.make_pf_transport(filter)
524
transport = self.make_pf_transport(filter)
521
526
self.assertEqual(['abc'], filter_log)
522
527
del filter_log[:]
523
t.clone('abc').has('xyz')
528
transport.clone('abc').has('xyz')
524
529
self.assertEqual(['abc/xyz'], filter_log)
525
530
del filter_log[:]
531
transport.has('/abc')
527
532
self.assertEqual(['abc'], filter_log)
529
534
def test_clone(self):
530
t = self.make_pf_transport()
535
transport = self.make_pf_transport()
531
536
# relpath from root and root path are the same
532
relpath_cloned = t.clone('foo')
533
abspath_cloned = t.clone('/foo')
534
self.assertEqual(t.server, relpath_cloned.server)
535
self.assertEqual(t.server, abspath_cloned.server)
537
relpath_cloned = transport.clone('foo')
538
abspath_cloned = transport.clone('/foo')
539
self.assertEqual(transport.server, relpath_cloned.server)
540
self.assertEqual(transport.server, abspath_cloned.server)
537
542
def test_url_preserves_pathfiltering(self):
538
543
"""Calling get_transport on a pathfiltered transport's base should
701
class TestTransportFromPath(tests.TestCaseInTempDir):
703
def test_with_path(self):
704
t = transport.get_transport_from_path(self.test_dir)
705
self.assertIsInstance(t, local.LocalTransport)
706
self.assertEquals(t.base.rstrip("/"),
707
urlutils.local_path_to_url(self.test_dir))
709
def test_with_url(self):
710
t = transport.get_transport_from_path("file:")
711
self.assertIsInstance(t, local.LocalTransport)
712
self.assertEquals(t.base.rstrip("/"),
713
urlutils.local_path_to_url(os.path.join(self.test_dir, "file:")))
716
class TestTransportFromUrl(tests.TestCaseInTempDir):
718
def test_with_path(self):
719
self.assertRaises(errors.InvalidURL, transport.get_transport_from_url,
722
def test_with_url(self):
723
url = urlutils.local_path_to_url(self.test_dir)
724
t = transport.get_transport_from_url(url)
725
self.assertIsInstance(t, local.LocalTransport)
726
self.assertEquals(t.base.rstrip("/"), url)
728
def test_with_url_and_segment_parameters(self):
729
url = urlutils.local_path_to_url(self.test_dir)+",branch=foo"
730
t = transport.get_transport_from_url(url)
731
self.assertIsInstance(t, local.LocalTransport)
732
self.assertEquals(t.base.rstrip("/"), url)
733
with open(os.path.join(self.test_dir, "afile"), 'w') as f:
735
self.assertTrue(t.has("afile"))
738
class TestLocalTransports(tests.TestCase):
708
class TestLocalTransports(TestCase):
740
710
def test_get_transport_from_abspath(self):
741
711
here = osutils.abspath('.')
742
t = transport.get_transport(here)
743
self.assertIsInstance(t, local.LocalTransport)
712
t = get_transport(here)
713
self.assertIsInstance(t, LocalTransport)
744
714
self.assertEquals(t.base, urlutils.local_path_to_url(here) + '/')
746
716
def test_get_transport_from_relpath(self):
747
717
here = osutils.abspath('.')
748
t = transport.get_transport('.')
749
self.assertIsInstance(t, local.LocalTransport)
718
t = get_transport('.')
719
self.assertIsInstance(t, LocalTransport)
750
720
self.assertEquals(t.base, urlutils.local_path_to_url('.') + '/')
752
722
def test_get_transport_from_local_url(self):
753
723
here = osutils.abspath('.')
754
724
here_url = urlutils.local_path_to_url(here) + '/'
755
t = transport.get_transport(here_url)
756
self.assertIsInstance(t, local.LocalTransport)
725
t = get_transport(here_url)
726
self.assertIsInstance(t, LocalTransport)
757
727
self.assertEquals(t.base, here_url)
759
729
def test_local_abspath(self):
760
730
here = osutils.abspath('.')
761
t = transport.get_transport(here)
731
t = get_transport(here)
762
732
self.assertEquals(t.local_abspath(''), here)
765
class TestLocalTransportMutation(tests.TestCaseInTempDir):
767
def test_local_transport_mkdir(self):
768
here = osutils.abspath('.')
769
t = transport.get_transport(here)
771
self.assertTrue(os.path.exists('test'))
773
def test_local_transport_mkdir_permission_denied(self):
774
# See https://bugs.launchpad.net/bzr/+bug/606537
775
here = osutils.abspath('.')
776
t = transport.get_transport(here)
777
def fake_chmod(path, mode):
778
e = OSError('permission denied')
779
e.errno = errno.EPERM
781
self.overrideAttr(os, 'chmod', fake_chmod)
783
t.mkdir('test2', mode=0707)
784
self.assertTrue(os.path.exists('test'))
785
self.assertTrue(os.path.exists('test2'))
788
class TestLocalTransportWriteStream(tests.TestCaseWithTransport):
790
def test_local_fdatasync_calls_fdatasync(self):
791
"""Check fdatasync on a stream tries to flush the data to the OS.
793
We can't easily observe the external effect but we can at least see
797
fdatasync = getattr(os, 'fdatasync', sentinel)
798
if fdatasync is sentinel:
799
raise tests.TestNotApplicable('fdatasync not supported')
800
t = self.get_transport('.')
801
calls = self.recordCalls(os, 'fdatasync')
802
w = t.open_write_stream('out')
805
with open('out', 'rb') as f:
806
# Should have been flushed.
807
self.assertEquals(f.read(), 'foo')
808
self.assertEquals(len(calls), 1, calls)
810
def test_missing_directory(self):
811
t = self.get_transport('.')
812
self.assertRaises(errors.NoSuchFile, t.open_write_stream, 'dir/foo')
815
class TestWin32LocalTransport(tests.TestCase):
735
class TestWin32LocalTransport(TestCase):
817
737
def test_unc_clone_to_root(self):
818
738
# Win32 UNC path like \\HOST\path
819
739
# clone to root should stop at least at \\HOST part
821
t = local.EmulatedWin32LocalTransport('file://HOST/path/to/some/dir/')
741
t = EmulatedWin32LocalTransport('file://HOST/path/to/some/dir/')
822
742
for i in xrange(4):
823
743
t = t.clone('..')
824
744
self.assertEquals(t.base, 'file://HOST/')
827
747
self.assertEquals(t.base, 'file://HOST/')
830
class TestConnectedTransport(tests.TestCase):
750
class TestConnectedTransport(TestCase):
831
751
"""Tests for connected to remote server transports"""
833
753
def test_parse_url(self):
834
t = transport.ConnectedTransport(
835
'http://simple.example.com/home/source')
836
self.assertEquals(t._parsed_url.host, 'simple.example.com')
837
self.assertEquals(t._parsed_url.port, None)
838
self.assertEquals(t._parsed_url.path, '/home/source/')
839
self.assertTrue(t._parsed_url.user is None)
840
self.assertTrue(t._parsed_url.password is None)
754
t = ConnectedTransport('http://simple.example.com/home/source')
755
self.assertEquals(t._host, 'simple.example.com')
756
self.assertEquals(t._port, None)
757
self.assertEquals(t._path, '/home/source/')
758
self.failUnless(t._user is None)
759
self.failUnless(t._password is None)
842
761
self.assertEquals(t.base, 'http://simple.example.com/home/source/')
844
763
def test_parse_url_with_at_in_user(self):
846
t = transport.ConnectedTransport('ftp://user@host.com@www.host.com/')
847
self.assertEquals(t._parsed_url.user, 'user@host.com')
765
t = ConnectedTransport('ftp://user@host.com@www.host.com/')
766
self.assertEquals(t._user, 'user@host.com')
849
768
def test_parse_quoted_url(self):
850
t = transport.ConnectedTransport(
851
'http://ro%62ey:h%40t@ex%41mple.com:2222/path')
852
self.assertEquals(t._parsed_url.host, 'exAmple.com')
853
self.assertEquals(t._parsed_url.port, 2222)
854
self.assertEquals(t._parsed_url.user, 'robey')
855
self.assertEquals(t._parsed_url.password, 'h@t')
856
self.assertEquals(t._parsed_url.path, '/path/')
769
t = ConnectedTransport('http://ro%62ey:h%40t@ex%41mple.com:2222/path')
770
self.assertEquals(t._host, 'exAmple.com')
771
self.assertEquals(t._port, 2222)
772
self.assertEquals(t._user, 'robey')
773
self.assertEquals(t._password, 'h@t')
774
self.assertEquals(t._path, '/path/')
858
776
# Base should not keep track of the password
859
self.assertEquals(t.base, 'http://ro%62ey@ex%41mple.com:2222/path/')
777
self.assertEquals(t.base, 'http://robey@exAmple.com:2222/path/')
861
779
def test_parse_invalid_url(self):
862
780
self.assertRaises(errors.InvalidURL,
863
transport.ConnectedTransport,
864
782
'sftp://lily.org:~janneke/public/bzr/gub')
866
784
def test_relpath(self):
867
t = transport.ConnectedTransport('sftp://user@host.com/abs/path')
785
t = ConnectedTransport('sftp://user@host.com/abs/path')
869
self.assertEquals(t.relpath('sftp://user@host.com/abs/path/sub'),
787
self.assertEquals(t.relpath('sftp://user@host.com/abs/path/sub'), 'sub')
871
788
self.assertRaises(errors.PathNotChild, t.relpath,
872
789
'http://user@host.com/abs/path/sub')
873
790
self.assertRaises(errors.PathNotChild, t.relpath,
912
829
self.assertIs(new_password, c._get_credentials())
915
class TestReusedTransports(tests.TestCase):
832
class TestReusedTransports(TestCase):
916
833
"""Tests for transport reuse"""
918
835
def test_reuse_same_transport(self):
919
836
possible_transports = []
920
t1 = transport.get_transport_from_url('http://foo/',
921
possible_transports=possible_transports)
837
t1 = get_transport('http://foo/',
838
possible_transports=possible_transports)
922
839
self.assertEqual([t1], possible_transports)
923
t2 = transport.get_transport_from_url('http://foo/',
924
possible_transports=[t1])
840
t2 = get_transport('http://foo/', possible_transports=[t1])
925
841
self.assertIs(t1, t2)
927
843
# Also check that final '/' are handled correctly
928
t3 = transport.get_transport_from_url('http://foo/path/')
929
t4 = transport.get_transport_from_url('http://foo/path',
930
possible_transports=[t3])
844
t3 = get_transport('http://foo/path/')
845
t4 = get_transport('http://foo/path', possible_transports=[t3])
931
846
self.assertIs(t3, t4)
933
t5 = transport.get_transport_from_url('http://foo/path')
934
t6 = transport.get_transport_from_url('http://foo/path/',
935
possible_transports=[t5])
848
t5 = get_transport('http://foo/path')
849
t6 = get_transport('http://foo/path/', possible_transports=[t5])
936
850
self.assertIs(t5, t6)
938
852
def test_don_t_reuse_different_transport(self):
939
t1 = transport.get_transport_from_url('http://foo/path')
940
t2 = transport.get_transport_from_url('http://bar/path',
941
possible_transports=[t1])
853
t1 = get_transport('http://foo/path')
854
t2 = get_transport('http://bar/path', possible_transports=[t1])
942
855
self.assertIsNot(t1, t2)
945
class TestTransportTrace(tests.TestCase):
858
class TestTransportTrace(TestCase):
947
def test_decorator(self):
948
t = transport.get_transport_from_url('trace+memory://')
861
transport = get_transport('trace+memory://')
949
862
self.assertIsInstance(
950
t, bzrlib.transport.trace.TransportTraceDecorator)
863
transport, bzrlib.transport.trace.TransportTraceDecorator)
952
865
def test_clone_preserves_activity(self):
953
t = transport.get_transport_from_url('trace+memory://')
955
self.assertTrue(t is not t2)
956
self.assertTrue(t._activity is t2._activity)
866
transport = get_transport('trace+memory://')
867
transport2 = transport.clone('.')
868
self.assertTrue(transport is not transport2)
869
self.assertTrue(transport._activity is transport2._activity)
958
871
# the following specific tests are for the operations that have made use of
959
872
# logging in tests; we could test every single operation but doing that
960
873
# still won't cause a test failure when the top level Transport API
961
874
# changes; so there is little return doing that.
962
875
def test_get(self):
963
t = transport.get_transport_from_url('trace+memory:///')
964
t.put_bytes('foo', 'barish')
876
transport = get_transport('trace+memory:///')
877
transport.put_bytes('foo', 'barish')
966
879
expected_result = []
967
880
# put_bytes records the bytes, not the content to avoid memory
969
882
expected_result.append(('put_bytes', 'foo', 6, None))
970
883
# get records the file name only.
971
884
expected_result.append(('get', 'foo'))
972
self.assertEqual(expected_result, t._activity)
885
self.assertEqual(expected_result, transport._activity)
974
887
def test_readv(self):
975
t = transport.get_transport_from_url('trace+memory:///')
976
t.put_bytes('foo', 'barish')
977
list(t.readv('foo', [(0, 1), (3, 2)],
978
adjust_for_latency=True, upper_limit=6))
888
transport = get_transport('trace+memory:///')
889
transport.put_bytes('foo', 'barish')
890
list(transport.readv('foo', [(0, 1), (3, 2)], adjust_for_latency=True,
979
892
expected_result = []
980
893
# put_bytes records the bytes, not the content to avoid memory
982
895
expected_result.append(('put_bytes', 'foo', 6, None))
983
896
# readv records the supplied offset request
984
897
expected_result.append(('readv', 'foo', [(0, 1), (3, 2)], True, 6))
985
self.assertEqual(expected_result, t._activity)
898
self.assertEqual(expected_result, transport._activity)
988
901
class TestSSHConnections(tests.TestCaseWithTransport):
990
903
def test_bzr_connect_to_bzr_ssh(self):
991
"""get_transport of a bzr+ssh:// behaves correctly.
904
"""User acceptance that get_transport of a bzr+ssh:// behaves correctly.
993
906
bzr+ssh:// should cause bzr to run a remote bzr smart server over SSH.