21
21
from cStringIO import StringIO
24
from bzrlib.errors import (NoSuchFile, FileExists,
28
from bzrlib.errors import (ConnectionError,
25
34
TransportNotPossible,
28
35
UnsupportedProtocol,
30
37
from bzrlib.tests import TestCase, TestCaseInTempDir
31
38
from bzrlib.transport import (_CoalescedOffset,
32
39
_get_protocol_handlers,
40
_set_protocol_handlers,
33
41
_get_transport_modules,
35
43
register_lazy_transport,
36
_set_protocol_handlers,
44
register_transport_proto,
45
_clear_protocol_handlers,
48
from bzrlib.transport.chroot import ChrootServer
39
49
from bzrlib.transport.memory import MemoryTransport
40
from bzrlib.transport.local import LocalTransport
50
from bzrlib.transport.local import (LocalTransport,
51
EmulatedWin32LocalTransport)
54
# TODO: Should possibly split transport-specific tests into their own files.
43
57
class TestTransport(TestCase):
46
60
def test__get_set_protocol_handlers(self):
47
61
handlers = _get_protocol_handlers()
48
self.assertNotEqual({}, handlers)
62
self.assertNotEqual([], handlers.keys( ))
50
_set_protocol_handlers({})
51
self.assertEqual({}, _get_protocol_handlers())
64
_clear_protocol_handlers()
65
self.assertEqual([], _get_protocol_handlers().keys())
53
67
_set_protocol_handlers(handlers)
57
71
class SampleHandler(object):
58
72
"""I exist, isnt that enough?"""
61
_set_protocol_handlers(my_handlers)
74
_clear_protocol_handlers()
75
register_transport_proto('foo')
62
76
register_lazy_transport('foo', 'bzrlib.tests.test_transport', 'TestTransport.SampleHandler')
77
register_transport_proto('bar')
63
78
register_lazy_transport('bar', 'bzrlib.tests.test_transport', 'TestTransport.SampleHandler')
64
self.assertEqual([SampleHandler.__module__],
79
self.assertEqual([SampleHandler.__module__, 'bzrlib.transport.chroot'],
65
80
_get_transport_modules())
67
82
_set_protocol_handlers(handlers)
90
106
"""Transport with missing dependency causes no error"""
91
107
saved_handlers = _get_protocol_handlers()
93
_set_protocol_handlers({})
109
_clear_protocol_handlers()
110
register_transport_proto('foo')
94
111
register_lazy_transport('foo', 'bzrlib.tests.test_transport',
95
112
'BackupTransportHandler')
96
113
register_lazy_transport('foo', 'bzrlib.tests.test_transport',
101
118
_set_protocol_handlers(saved_handlers)
120
def test__combine_paths(self):
122
self.assertEqual('/home/sarah/project/foo',
123
t._combine_paths('/home/sarah', 'project/foo'))
124
self.assertEqual('/etc',
125
t._combine_paths('/home/sarah', '../../etc'))
126
self.assertEqual('/etc',
127
t._combine_paths('/home/sarah', '../../../etc'))
128
self.assertEqual('/etc',
129
t._combine_paths('/home/sarah', '/etc'))
131
def test_local_abspath_non_local_transport(self):
132
# the base implementation should throw
133
t = MemoryTransport()
134
e = self.assertRaises(errors.NotLocalUrl, t.local_abspath, 't')
135
self.assertEqual('memory:///t is not a local path.', str(e))
104
138
class TestCoalesceOffsets(TestCase):
219
254
transport.append_bytes('foo', 'content')
220
255
self.assertEquals(True, transport.has('foo'))
257
def test_list_dir(self):
258
transport = MemoryTransport()
259
transport.put_bytes('foo', 'content')
260
transport.mkdir('dir')
261
transport.put_bytes('dir/subfoo', 'content')
262
transport.put_bytes('dirlike', 'content')
264
self.assertEquals(['dir', 'dirlike', 'foo'], sorted(transport.list_dir('.')))
265
self.assertEquals(['subfoo'], sorted(transport.list_dir('dir')))
222
267
def test_mkdir(self):
223
268
transport = MemoryTransport()
224
269
transport.mkdir('dir')
257
302
self.assertEqual(7, transport.stat('foo').st_size)
258
303
self.assertEqual(6, transport.stat('bar').st_size)
306
class ChrootDecoratorTransportTest(TestCase):
307
"""Chroot decoration specific tests."""
309
def test_abspath(self):
310
# The abspath is always relative to the chroot_url.
311
server = ChrootServer(get_transport('memory:///foo/bar/'))
313
transport = get_transport(server.get_url())
314
self.assertEqual(server.get_url(), transport.abspath('/'))
316
subdir_transport = transport.clone('subdir')
317
self.assertEqual(server.get_url(), subdir_transport.abspath('/'))
320
def test_clone(self):
321
server = ChrootServer(get_transport('memory:///foo/bar/'))
323
transport = get_transport(server.get_url())
324
# relpath from root and root path are the same
325
relpath_cloned = transport.clone('foo')
326
abspath_cloned = transport.clone('/foo')
327
self.assertEqual(server, relpath_cloned.server)
328
self.assertEqual(server, abspath_cloned.server)
331
def test_chroot_url_preserves_chroot(self):
332
"""Calling get_transport on a chroot transport's base should produce a
333
transport with exactly the same behaviour as the original chroot
336
This is so that it is not possible to escape a chroot by doing::
337
url = chroot_transport.base
338
parent_url = urlutils.join(url, '..')
339
new_transport = get_transport(parent_url)
341
server = ChrootServer(get_transport('memory:///path/subpath'))
343
transport = get_transport(server.get_url())
344
new_transport = get_transport(transport.base)
345
self.assertEqual(transport.server, new_transport.server)
346
self.assertEqual(transport.base, new_transport.base)
349
def test_urljoin_preserves_chroot(self):
350
"""Using urlutils.join(url, '..') on a chroot URL should not produce a
351
URL that escapes the intended chroot.
353
This is so that it is not possible to escape a chroot by doing::
354
url = chroot_transport.base
355
parent_url = urlutils.join(url, '..')
356
new_transport = get_transport(parent_url)
358
server = ChrootServer(get_transport('memory:///path/'))
360
transport = get_transport(server.get_url())
362
InvalidURLJoin, urlutils.join, transport.base, '..')
366
class ChrootServerTest(TestCase):
368
def test_construct(self):
369
backing_transport = MemoryTransport()
370
server = ChrootServer(backing_transport)
371
self.assertEqual(backing_transport, server.backing_transport)
373
def test_setUp(self):
374
backing_transport = MemoryTransport()
375
server = ChrootServer(backing_transport)
377
self.assertTrue(server.scheme in _get_protocol_handlers().keys())
379
def test_tearDown(self):
380
backing_transport = MemoryTransport()
381
server = ChrootServer(backing_transport)
384
self.assertFalse(server.scheme in _get_protocol_handlers().keys())
386
def test_get_url(self):
387
backing_transport = MemoryTransport()
388
server = ChrootServer(backing_transport)
390
self.assertEqual('chroot-%d:///' % id(server), server.get_url())
261
394
class ReadonlyDecoratorTransportTest(TestCase):
262
395
"""Readonly decoration specific tests."""
405
538
super(TestTransportImplementation, self).setUp()
406
539
self._server = self.transport_server()
407
540
self._server.setUp()
541
self.addCleanup(self._server.tearDown)
410
super(TestTransportImplementation, self).tearDown()
411
self._server.tearDown()
413
543
def get_transport(self):
414
544
"""Return a connected transport to the local directory."""
415
545
base_url = self._server.get_url()
416
546
# try getting the transport via the regular interface:
417
547
t = get_transport(base_url)
418
if not isinstance(t, self.transport_class):
548
if not isinstance(t, self.transport_class):
419
549
# we did not get the correct transport class type. Override the
420
550
# regular connection behaviour by direct construction.
421
551
t = self.transport_class(base_url)
555
class TestLocalTransports(TestCase):
557
def test_get_transport_from_abspath(self):
558
here = os.path.abspath('.')
559
t = get_transport(here)
560
self.assertIsInstance(t, LocalTransport)
561
self.assertEquals(t.base, urlutils.local_path_to_url(here) + '/')
563
def test_get_transport_from_relpath(self):
564
here = os.path.abspath('.')
565
t = get_transport('.')
566
self.assertIsInstance(t, LocalTransport)
567
self.assertEquals(t.base, urlutils.local_path_to_url('.') + '/')
569
def test_get_transport_from_local_url(self):
570
here = os.path.abspath('.')
571
here_url = urlutils.local_path_to_url(here) + '/'
572
t = get_transport(here_url)
573
self.assertIsInstance(t, LocalTransport)
574
self.assertEquals(t.base, here_url)
576
def test_local_abspath(self):
577
here = os.path.abspath('.')
578
t = get_transport(here)
579
self.assertEquals(t.local_abspath(''), here)
582
class TestWin32LocalTransport(TestCase):
584
def test_unc_clone_to_root(self):
585
# Win32 UNC path like \\HOST\path
586
# clone to root should stop at least at \\HOST part
588
t = EmulatedWin32LocalTransport('file://HOST/path/to/some/dir/')
591
self.assertEquals(t.base, 'file://HOST/')
592
# make sure we reach the root
594
self.assertEquals(t.base, 'file://HOST/')
597
def get_test_permutations():
598
"""Return transport permutations to be used in testing.
600
This module registers some transports, but they're only for testing
601
registration. We don't really want to run all the transport tests against