13
13
# You should have received a copy of the GNU General Public License
14
14
# along with this program; if not, write to the Free Software
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21
18
from cStringIO import StringIO
24
21
from bzrlib import (
28
from bzrlib.errors import (ConnectionError,
26
from bzrlib.errors import (DependencyNotPresent,
38
32
UnsupportedProtocol,
40
34
from bzrlib.tests import TestCase, TestCaseInTempDir
41
from bzrlib.transport import (_CoalescedOffset,
35
from bzrlib.transport import (_clear_protocol_handlers,
42
37
ConnectedTransport,
43
38
_get_protocol_handlers,
44
39
_set_protocol_handlers,
74
68
def test_get_transport_modules(self):
75
69
handlers = _get_protocol_handlers()
70
# don't pollute the current handlers
71
_clear_protocol_handlers()
76
72
class SampleHandler(object):
77
73
"""I exist, isnt that enough?"""
79
75
_clear_protocol_handlers()
80
76
register_transport_proto('foo')
81
register_lazy_transport('foo', 'bzrlib.tests.test_transport', 'TestTransport.SampleHandler')
77
register_lazy_transport('foo', 'bzrlib.tests.test_transport',
78
'TestTransport.SampleHandler')
82
79
register_transport_proto('bar')
83
register_lazy_transport('bar', 'bzrlib.tests.test_transport', 'TestTransport.SampleHandler')
84
self.assertEqual([SampleHandler.__module__, 'bzrlib.transport.chroot'],
80
register_lazy_transport('bar', 'bzrlib.tests.test_transport',
81
'TestTransport.SampleHandler')
82
self.assertEqual([SampleHandler.__module__,
83
'bzrlib.transport.chroot'],
85
84
_get_transport_modules())
87
86
_set_protocol_handlers(handlers)
89
88
def test_transport_dependency(self):
90
89
"""Transport with missing dependency causes no error"""
91
90
saved_handlers = _get_protocol_handlers()
91
# don't pollute the current handlers
92
_clear_protocol_handlers()
93
94
register_transport_proto('foo')
94
95
register_lazy_transport('foo', 'bzrlib.tests.test_transport',
123
124
_set_protocol_handlers(saved_handlers)
126
def test_ssh_hints(self):
127
"""Transport ssh:// should raise an error pointing out bzr+ssh://"""
129
get_transport('ssh://fooserver/foo')
130
except UnsupportedProtocol, e:
132
self.assertEquals('Unsupported protocol'
133
' for url "ssh://fooserver/foo":'
134
' bzr supports bzr+ssh to operate over ssh, use "bzr+ssh://fooserver/foo".',
137
self.fail('Did not raise UnsupportedProtocol')
125
139
def test_LateReadError(self):
126
140
"""The LateReadError helper should raise on read()."""
127
141
a_file = LateReadError('a path')
153
167
class TestCoalesceOffsets(TestCase):
155
def check(self, expected, offsets, limit=0, fudge=0):
169
def check(self, expected, offsets, limit=0, max_size=0, fudge=0):
156
170
coalesce = Transport._coalesce_offsets
157
171
exp = [_CoalescedOffset(*x) for x in expected]
158
out = list(coalesce(offsets, limit=limit, fudge_factor=fudge))
172
out = list(coalesce(offsets, limit=limit, fudge_factor=fudge,
159
174
self.assertEqual(exp, out)
161
176
def test_coalesce_empty(self):
168
183
self.check([(0, 10, [(0, 10)]),
169
184
(20, 10, [(0, 10)]),
170
185
], [(0, 10), (20, 10)])
172
187
def test_coalesce_unsorted(self):
173
188
self.check([(20, 10, [(0, 10)]),
174
189
(0, 10, [(0, 10)]),
179
194
[(0, 10), (10, 10)])
181
196
def test_coalesce_overlapped(self):
182
self.check([(0, 15, [(0, 10), (5, 10)])],
197
self.assertRaises(ValueError,
198
self.check, [(0, 15, [(0, 10), (5, 10)])],
185
201
def test_coalesce_limit(self):
186
202
self.check([(10, 50, [(0, 10), (10, 10), (20, 10),
207
223
], [(10, 10), (30, 10), (100, 10)],
226
def test_coalesce_max_size(self):
227
self.check([(10, 20, [(0, 10), (10, 10)]),
229
# If one range is above max_size, it gets its own coalesced
231
(100, 80, [(0, 80),]),],
232
[(10, 10), (20, 10), (30, 50), (100, 80)],
236
def test_coalesce_no_max_size(self):
237
self.check([(10, 170, [(0, 10), (10, 10), (20, 50), (70, 100)]),],
238
[(10, 10), (20, 10), (30, 50), (80, 100)],
241
def test_coalesce_default_limit(self):
242
# By default we use a 100MB max size.
243
ten_mb = 10*1024*1024
244
self.check([(0, 10*ten_mb, [(i*ten_mb, ten_mb) for i in range(10)]),
245
(10*ten_mb, ten_mb, [(0, ten_mb)])],
246
[(i*ten_mb, ten_mb) for i in range(11)])
247
self.check([(0, 11*ten_mb, [(i*ten_mb, ten_mb) for i in range(11)]),],
248
[(i*ten_mb, ten_mb) for i in range(11)],
249
max_size=1*1024*1024*1024)
212
252
class TestMemoryTransport(TestCase):
341
381
self.assertEqual(server, relpath_cloned.server)
342
382
self.assertEqual(server, abspath_cloned.server)
343
383
server.tearDown()
345
385
def test_chroot_url_preserves_chroot(self):
346
386
"""Calling get_transport on a chroot transport's base should produce a
347
387
transport with exactly the same behaviour as the original chroot
359
399
self.assertEqual(transport.server, new_transport.server)
360
400
self.assertEqual(transport.base, new_transport.base)
361
401
server.tearDown()
363
403
def test_urljoin_preserves_chroot(self):
364
404
"""Using urlutils.join(url, '..') on a chroot URL should not produce a
365
405
URL that escapes the intended chroot.
416
456
self.assertEqual(True, transport.is_readonly())
418
458
def test_http_parameters(self):
419
from bzrlib.tests.HttpServer import HttpServer
459
from bzrlib.tests.http_server import HttpServer
420
460
import bzrlib.transport.readonly as readonly
421
# connect to . via http which is not listable
461
# connect to '.' via http which is not listable
422
462
server = HttpServer()
449
489
def test_http_parameters(self):
450
490
# the listable and is_readonly parameters
451
491
# are not changed by the fakenfs decorator
452
from bzrlib.tests.HttpServer import HttpServer
453
# connect to . via http which is not listable
492
from bzrlib.tests.http_server import HttpServer
493
# connect to '.' via http which is not listable
454
494
server = HttpServer()
525
565
class TestTransportImplementation(TestCaseInTempDir):
526
566
"""Implementation verification for transports.
528
568
To verify a transport we need a server factory, which is a callable
529
569
that accepts no parameters and returns an implementation of
530
570
bzrlib.transport.Server.
532
572
That Server is then used to construct transport instances and test
533
573
the transport via loopback activity.
535
Currently this assumes that the Transport object is connected to the
536
current working directory. So that whatever is done
537
through the transport, should show up in the working
575
Currently this assumes that the Transport object is connected to the
576
current working directory. So that whatever is done
577
through the transport, should show up in the working
538
578
directory, and vice-versa. This is a bug, because its possible to have
539
URL schemes which provide access to something that may not be
540
result in storage on the local disk, i.e. due to file system limits, or
579
URL schemes which provide access to something that may not be
580
result in storage on the local disk, i.e. due to file system limits, or
541
581
due to it being a database or some other non-filesystem tool.
543
583
This also tests to make sure that the functions work with both
544
584
generators and lists (assuming iter(list) is effectively a generator)
548
588
super(TestTransportImplementation, self).setUp()
549
589
self._server = self.transport_server()
572
612
class TestLocalTransports(TestCase):
574
614
def test_get_transport_from_abspath(self):
575
here = os.path.abspath('.')
615
here = osutils.abspath('.')
576
616
t = get_transport(here)
577
617
self.assertIsInstance(t, LocalTransport)
578
618
self.assertEquals(t.base, urlutils.local_path_to_url(here) + '/')
580
620
def test_get_transport_from_relpath(self):
581
here = os.path.abspath('.')
621
here = osutils.abspath('.')
582
622
t = get_transport('.')
583
623
self.assertIsInstance(t, LocalTransport)
584
624
self.assertEquals(t.base, urlutils.local_path_to_url('.') + '/')
586
626
def test_get_transport_from_local_url(self):
587
here = os.path.abspath('.')
627
here = osutils.abspath('.')
588
628
here_url = urlutils.local_path_to_url(here) + '/'
589
629
t = get_transport(here_url)
590
630
self.assertIsInstance(t, LocalTransport)
591
631
self.assertEquals(t.base, here_url)
593
633
def test_local_abspath(self):
594
here = os.path.abspath('.')
634
here = osutils.abspath('.')
595
635
t = get_transport(here)
596
636
self.assertEquals(t.local_abspath(''), here)
615
655
"""Tests for connected to remote server transports"""
617
657
def test_parse_url(self):
618
t = ConnectedTransport('sftp://simple.example.com/home/source')
658
t = ConnectedTransport('http://simple.example.com/home/source')
619
659
self.assertEquals(t._host, 'simple.example.com')
620
660
self.assertEquals(t._port, None)
621
661
self.assertEquals(t._path, '/home/source/')
622
662
self.failUnless(t._user is None)
623
663
self.failUnless(t._password is None)
625
self.assertEquals(t.base, 'sftp://simple.example.com/home/source/')
665
self.assertEquals(t.base, 'http://simple.example.com/home/source/')
667
def test_parse_url_with_at_in_user(self):
669
t = ConnectedTransport('ftp://user@host.com@www.host.com/')
670
self.assertEquals(t._user, 'user@host.com')
627
672
def test_parse_quoted_url(self):
628
673
t = ConnectedTransport('http://ro%62ey:h%40t@ex%41mple.com:2222/path')
661
706
self.assertEquals(t.relpath('sftp://host.com/dev/%path/sub'), 'sub')
663
708
def test_connection_sharing_propagate_credentials(self):
664
t = ConnectedTransport('foo://user@host.com/abs/path')
709
t = ConnectedTransport('ftp://user@host.com/abs/path')
710
self.assertEquals('user', t._user)
711
self.assertEquals('host.com', t._host)
665
712
self.assertIs(None, t._get_connection())
666
713
self.assertIs(None, t._password)
667
714
c = t.clone('subdir')
668
self.assertEquals(None, c._get_connection())
715
self.assertIs(None, c._get_connection())
669
716
self.assertIs(None, t._password)
671
718
# Simulate the user entering a password
712
759
self.assertIsNot(t1, t2)
715
def get_test_permutations():
716
"""Return transport permutations to be used in testing.
718
This module registers some transports, but they're only for testing
719
registration. We don't really want to run all the transport tests against
762
class TestTransportTrace(TestCase):
765
transport = get_transport('trace+memory://')
766
self.assertIsInstance(
767
transport, bzrlib.transport.trace.TransportTraceDecorator)
769
def test_clone_preserves_activity(self):
770
transport = get_transport('trace+memory://')
771
transport2 = transport.clone('.')
772
self.assertTrue(transport is not transport2)
773
self.assertTrue(transport._activity is transport2._activity)
775
# the following specific tests are for the operations that have made use of
776
# logging in tests; we could test every single operation but doing that
777
# still won't cause a test failure when the top level Transport API
778
# changes; so there is little return doing that.
780
transport = get_transport('trace+memory:///')
781
transport.put_bytes('foo', 'barish')
784
# put_bytes records the bytes, not the content to avoid memory
786
expected_result.append(('put_bytes', 'foo', 6, None))
787
# get records the file name only.
788
expected_result.append(('get', 'foo'))
789
self.assertEqual(expected_result, transport._activity)
791
def test_readv(self):
792
transport = get_transport('trace+memory:///')
793
transport.put_bytes('foo', 'barish')
794
list(transport.readv('foo', [(0, 1), (3, 2)], adjust_for_latency=True,
797
# put_bytes records the bytes, not the content to avoid memory
799
expected_result.append(('put_bytes', 'foo', 6, None))
800
# readv records the supplied offset request
801
expected_result.append(('readv', 'foo', [(0, 1), (3, 2)], True, 6))
802
self.assertEqual(expected_result, transport._activity)