/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_transport.py

  • Committer: Robert Collins
  • Date: 2007-03-27 21:45:59 UTC
  • mfrom: (2379 +trunk)
  • mto: (2018.5.109 hpss)
  • mto: This revision was merged to the branch mainline in revision 2435.
  • Revision ID: robertc@robertcollins.net-20070327214559-3zto1rfp3g7dnzl9
Merge bzr.dev.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Copyright (C) 2004, 2005, 2006 Canonical Ltd
 
2
#
 
3
# This program is free software; you can redistribute it and/or modify
 
4
# it under the terms of the GNU General Public License as published by
 
5
# the Free Software Foundation; either version 2 of the License, or
 
6
# (at your option) any later version.
 
7
#
 
8
# This program is distributed in the hope that it will be useful,
 
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
11
# GNU General Public License for more details.
 
12
#
 
13
# You should have received a copy of the GNU General Public License
 
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
 
16
 
 
17
 
 
18
import os
 
19
import sys
 
20
import stat
 
21
from cStringIO import StringIO
 
22
 
 
23
import bzrlib
 
24
from bzrlib import urlutils
 
25
from bzrlib.errors import (
 
26
    ConnectionError,
 
27
    DependencyNotPresent,
 
28
    FileExists,
 
29
    InvalidURLJoin,
 
30
    NoSuchFile,
 
31
    PathNotChild,
 
32
    TransportNotPossible,
 
33
    UnsupportedProtocol,
 
34
    )
 
35
from bzrlib.tests import TestCase, TestCaseInTempDir
 
36
from bzrlib.transport import (_CoalescedOffset,
 
37
                              _get_protocol_handlers,
 
38
                              _get_transport_modules,
 
39
                              get_transport,
 
40
                              _protocol_handlers,
 
41
                              register_lazy_transport,
 
42
                              _set_protocol_handlers,
 
43
                              Transport,
 
44
                              )
 
45
from bzrlib.transport.chroot import ChrootServer
 
46
from bzrlib.transport.memory import MemoryTransport
 
47
from bzrlib.transport.local import (LocalTransport,
 
48
                                    EmulatedWin32LocalTransport)
 
49
 
 
50
 
 
51
# TODO: Should possibly split transport-specific tests into their own files.
 
52
 
 
53
 
 
54
class TestTransport(TestCase):
 
55
    """Test the non transport-concrete class functionality."""
 
56
 
 
57
    def test__get_set_protocol_handlers(self):
 
58
        handlers = _get_protocol_handlers()
 
59
        self.assertNotEqual({}, handlers)
 
60
        try:
 
61
            _set_protocol_handlers({})
 
62
            self.assertEqual({}, _get_protocol_handlers())
 
63
        finally:
 
64
            _set_protocol_handlers(handlers)
 
65
 
 
66
    def test_get_transport_modules(self):
 
67
        handlers = _get_protocol_handlers()
 
68
        class SampleHandler(object):
 
69
            """I exist, isnt that enough?"""
 
70
        try:
 
71
            my_handlers = {}
 
72
            _set_protocol_handlers(my_handlers)
 
73
            register_lazy_transport('foo', 'bzrlib.tests.test_transport', 'TestTransport.SampleHandler')
 
74
            register_lazy_transport('bar', 'bzrlib.tests.test_transport', 'TestTransport.SampleHandler')
 
75
            self.assertEqual([SampleHandler.__module__],
 
76
                             _get_transport_modules())
 
77
        finally:
 
78
            _set_protocol_handlers(handlers)
 
79
 
 
80
    def test_transport_dependency(self):
 
81
        """Transport with missing dependency causes no error"""
 
82
        saved_handlers = _get_protocol_handlers()
 
83
        try:
 
84
            register_lazy_transport('foo', 'bzrlib.tests.test_transport',
 
85
                    'BadTransportHandler')
 
86
            try:
 
87
                get_transport('foo://fooserver/foo')
 
88
            except UnsupportedProtocol, e:
 
89
                e_str = str(e)
 
90
                self.assertEquals('Unsupported protocol'
 
91
                                  ' for url "foo://fooserver/foo":'
 
92
                                  ' Unable to import library "some_lib":'
 
93
                                  ' testing missing dependency', str(e))
 
94
            else:
 
95
                self.fail('Did not raise UnsupportedProtocol')
 
96
        finally:
 
97
            # restore original values
 
98
            _set_protocol_handlers(saved_handlers)
 
99
            
 
100
    def test_transport_fallback(self):
 
101
        """Transport with missing dependency causes no error"""
 
102
        saved_handlers = _get_protocol_handlers()
 
103
        try:
 
104
            _set_protocol_handlers({})
 
105
            register_lazy_transport('foo', 'bzrlib.tests.test_transport',
 
106
                    'BackupTransportHandler')
 
107
            register_lazy_transport('foo', 'bzrlib.tests.test_transport',
 
108
                    'BadTransportHandler')
 
109
            t = get_transport('foo://fooserver/foo')
 
110
            self.assertTrue(isinstance(t, BackupTransportHandler))
 
111
        finally:
 
112
            _set_protocol_handlers(saved_handlers)
 
113
 
 
114
    def test__combine_paths(self):
 
115
        t = Transport('/')
 
116
        self.assertEqual('/home/sarah/project/foo',
 
117
                         t._combine_paths('/home/sarah', 'project/foo'))
 
118
        self.assertEqual('/etc',
 
119
                         t._combine_paths('/home/sarah', '../../etc'))
 
120
        self.assertEqual('/etc',
 
121
                         t._combine_paths('/home/sarah', '../../../etc'))
 
122
        self.assertEqual('/etc',
 
123
                         t._combine_paths('/home/sarah', '/etc'))
 
124
 
 
125
 
 
126
class TestCoalesceOffsets(TestCase):
 
127
    
 
128
    def check(self, expected, offsets, limit=0, fudge=0):
 
129
        coalesce = Transport._coalesce_offsets
 
130
        exp = [_CoalescedOffset(*x) for x in expected]
 
131
        out = list(coalesce(offsets, limit=limit, fudge_factor=fudge))
 
132
        self.assertEqual(exp, out)
 
133
 
 
134
    def test_coalesce_empty(self):
 
135
        self.check([], [])
 
136
 
 
137
    def test_coalesce_simple(self):
 
138
        self.check([(0, 10, [(0, 10)])], [(0, 10)])
 
139
 
 
140
    def test_coalesce_unrelated(self):
 
141
        self.check([(0, 10, [(0, 10)]),
 
142
                    (20, 10, [(0, 10)]),
 
143
                   ], [(0, 10), (20, 10)])
 
144
            
 
145
    def test_coalesce_unsorted(self):
 
146
        self.check([(20, 10, [(0, 10)]),
 
147
                    (0, 10, [(0, 10)]),
 
148
                   ], [(20, 10), (0, 10)])
 
149
 
 
150
    def test_coalesce_nearby(self):
 
151
        self.check([(0, 20, [(0, 10), (10, 10)])],
 
152
                   [(0, 10), (10, 10)])
 
153
 
 
154
    def test_coalesce_overlapped(self):
 
155
        self.check([(0, 15, [(0, 10), (5, 10)])],
 
156
                   [(0, 10), (5, 10)])
 
157
 
 
158
    def test_coalesce_limit(self):
 
159
        self.check([(10, 50, [(0, 10), (10, 10), (20, 10),
 
160
                              (30, 10), (40, 10)]),
 
161
                    (60, 50, [(0, 10), (10, 10), (20, 10),
 
162
                              (30, 10), (40, 10)]),
 
163
                   ], [(10, 10), (20, 10), (30, 10), (40, 10),
 
164
                       (50, 10), (60, 10), (70, 10), (80, 10),
 
165
                       (90, 10), (100, 10)],
 
166
                    limit=5)
 
167
 
 
168
    def test_coalesce_no_limit(self):
 
169
        self.check([(10, 100, [(0, 10), (10, 10), (20, 10),
 
170
                               (30, 10), (40, 10), (50, 10),
 
171
                               (60, 10), (70, 10), (80, 10),
 
172
                               (90, 10)]),
 
173
                   ], [(10, 10), (20, 10), (30, 10), (40, 10),
 
174
                       (50, 10), (60, 10), (70, 10), (80, 10),
 
175
                       (90, 10), (100, 10)])
 
176
 
 
177
    def test_coalesce_fudge(self):
 
178
        self.check([(10, 30, [(0, 10), (20, 10)]),
 
179
                    (100, 10, [(0, 10),]),
 
180
                   ], [(10, 10), (30, 10), (100, 10)],
 
181
                   fudge=10
 
182
                  )
 
183
 
 
184
 
 
185
class TestMemoryTransport(TestCase):
 
186
 
 
187
    def test_get_transport(self):
 
188
        MemoryTransport()
 
189
 
 
190
    def test_clone(self):
 
191
        transport = MemoryTransport()
 
192
        self.assertTrue(isinstance(transport, MemoryTransport))
 
193
        self.assertEqual("memory:///", transport.clone("/").base)
 
194
 
 
195
    def test_abspath(self):
 
196
        transport = MemoryTransport()
 
197
        self.assertEqual("memory:///relpath", transport.abspath('relpath'))
 
198
 
 
199
    def test_abspath_of_root(self):
 
200
        transport = MemoryTransport()
 
201
        self.assertEqual("memory:///", transport.base)
 
202
        self.assertEqual("memory:///", transport.abspath('/'))
 
203
 
 
204
    def test_abspath_of_relpath_starting_at_root(self):
 
205
        transport = MemoryTransport()
 
206
        self.assertEqual("memory:///foo", transport.abspath('/foo'))
 
207
 
 
208
    def test_append_and_get(self):
 
209
        transport = MemoryTransport()
 
210
        transport.append_bytes('path', 'content')
 
211
        self.assertEqual(transport.get('path').read(), 'content')
 
212
        transport.append_file('path', StringIO('content'))
 
213
        self.assertEqual(transport.get('path').read(), 'contentcontent')
 
214
 
 
215
    def test_put_and_get(self):
 
216
        transport = MemoryTransport()
 
217
        transport.put_file('path', StringIO('content'))
 
218
        self.assertEqual(transport.get('path').read(), 'content')
 
219
        transport.put_bytes('path', 'content')
 
220
        self.assertEqual(transport.get('path').read(), 'content')
 
221
 
 
222
    def test_append_without_dir_fails(self):
 
223
        transport = MemoryTransport()
 
224
        self.assertRaises(NoSuchFile,
 
225
                          transport.append_bytes, 'dir/path', 'content')
 
226
 
 
227
    def test_put_without_dir_fails(self):
 
228
        transport = MemoryTransport()
 
229
        self.assertRaises(NoSuchFile,
 
230
                          transport.put_file, 'dir/path', StringIO('content'))
 
231
 
 
232
    def test_get_missing(self):
 
233
        transport = MemoryTransport()
 
234
        self.assertRaises(NoSuchFile, transport.get, 'foo')
 
235
 
 
236
    def test_has_missing(self):
 
237
        transport = MemoryTransport()
 
238
        self.assertEquals(False, transport.has('foo'))
 
239
 
 
240
    def test_has_present(self):
 
241
        transport = MemoryTransport()
 
242
        transport.append_bytes('foo', 'content')
 
243
        self.assertEquals(True, transport.has('foo'))
 
244
 
 
245
    def test_list_dir(self):
 
246
        transport = MemoryTransport()
 
247
        transport.put_bytes('foo', 'content')
 
248
        transport.mkdir('dir')
 
249
        transport.put_bytes('dir/subfoo', 'content')
 
250
        transport.put_bytes('dirlike', 'content')
 
251
 
 
252
        self.assertEquals(['dir', 'dirlike', 'foo'], sorted(transport.list_dir('.')))
 
253
        self.assertEquals(['subfoo'], sorted(transport.list_dir('dir')))
 
254
 
 
255
    def test_mkdir(self):
 
256
        transport = MemoryTransport()
 
257
        transport.mkdir('dir')
 
258
        transport.append_bytes('dir/path', 'content')
 
259
        self.assertEqual(transport.get('dir/path').read(), 'content')
 
260
 
 
261
    def test_mkdir_missing_parent(self):
 
262
        transport = MemoryTransport()
 
263
        self.assertRaises(NoSuchFile,
 
264
                          transport.mkdir, 'dir/dir')
 
265
 
 
266
    def test_mkdir_twice(self):
 
267
        transport = MemoryTransport()
 
268
        transport.mkdir('dir')
 
269
        self.assertRaises(FileExists, transport.mkdir, 'dir')
 
270
 
 
271
    def test_parameters(self):
 
272
        transport = MemoryTransport()
 
273
        self.assertEqual(True, transport.listable())
 
274
        self.assertEqual(False, transport.should_cache())
 
275
        self.assertEqual(False, transport.is_readonly())
 
276
 
 
277
    def test_iter_files_recursive(self):
 
278
        transport = MemoryTransport()
 
279
        transport.mkdir('dir')
 
280
        transport.put_bytes('dir/foo', 'content')
 
281
        transport.put_bytes('dir/bar', 'content')
 
282
        transport.put_bytes('bar', 'content')
 
283
        paths = set(transport.iter_files_recursive())
 
284
        self.assertEqual(set(['dir/foo', 'dir/bar', 'bar']), paths)
 
285
 
 
286
    def test_stat(self):
 
287
        transport = MemoryTransport()
 
288
        transport.put_bytes('foo', 'content')
 
289
        transport.put_bytes('bar', 'phowar')
 
290
        self.assertEqual(7, transport.stat('foo').st_size)
 
291
        self.assertEqual(6, transport.stat('bar').st_size)
 
292
 
 
293
 
 
294
class ChrootDecoratorTransportTest(TestCase):
 
295
    """Chroot decoration specific tests."""
 
296
 
 
297
    def test_abspath(self):
 
298
        # The abspath is always relative to the chroot_url.
 
299
        server = ChrootServer(get_transport('memory:///foo/bar/'))
 
300
        server.setUp()
 
301
        transport = get_transport(server.get_url())
 
302
        self.assertEqual(server.get_url(), transport.abspath('/'))
 
303
 
 
304
        subdir_transport = transport.clone('subdir')
 
305
        self.assertEqual(server.get_url(), subdir_transport.abspath('/'))
 
306
        server.tearDown()
 
307
 
 
308
    def test_clone(self):
 
309
        server = ChrootServer(get_transport('memory:///foo/bar/'))
 
310
        server.setUp()
 
311
        transport = get_transport(server.get_url())
 
312
        # relpath from root and root path are the same
 
313
        relpath_cloned = transport.clone('foo')
 
314
        abspath_cloned = transport.clone('/foo')
 
315
        self.assertEqual(server, relpath_cloned.server)
 
316
        self.assertEqual(server, abspath_cloned.server)
 
317
        server.tearDown()
 
318
    
 
319
    def test_chroot_url_preserves_chroot(self):
 
320
        """Calling get_transport on a chroot transport's base should produce a
 
321
        transport with exactly the same behaviour as the original chroot
 
322
        transport.
 
323
 
 
324
        This is so that it is not possible to escape a chroot by doing::
 
325
            url = chroot_transport.base
 
326
            parent_url = urlutils.join(url, '..')
 
327
            new_transport = get_transport(parent_url)
 
328
        """
 
329
        server = ChrootServer(get_transport('memory:///path/subpath'))
 
330
        server.setUp()
 
331
        transport = get_transport(server.get_url())
 
332
        new_transport = get_transport(transport.base)
 
333
        self.assertEqual(transport.server, new_transport.server)
 
334
        self.assertEqual(transport.base, new_transport.base)
 
335
        server.tearDown()
 
336
        
 
337
    def test_urljoin_preserves_chroot(self):
 
338
        """Using urlutils.join(url, '..') on a chroot URL should not produce a
 
339
        URL that escapes the intended chroot.
 
340
 
 
341
        This is so that it is not possible to escape a chroot by doing::
 
342
            url = chroot_transport.base
 
343
            parent_url = urlutils.join(url, '..')
 
344
            new_transport = get_transport(parent_url)
 
345
        """
 
346
        server = ChrootServer(get_transport('memory:///path/'))
 
347
        server.setUp()
 
348
        transport = get_transport(server.get_url())
 
349
        self.assertRaises(
 
350
            InvalidURLJoin, urlutils.join, transport.base, '..')
 
351
        server.tearDown()
 
352
 
 
353
 
 
354
class ChrootServerTest(TestCase):
 
355
 
 
356
    def test_construct(self):
 
357
        backing_transport = MemoryTransport()
 
358
        server = ChrootServer(backing_transport)
 
359
        self.assertEqual(backing_transport, server.backing_transport)
 
360
 
 
361
    def test_setUp(self):
 
362
        backing_transport = MemoryTransport()
 
363
        server = ChrootServer(backing_transport)
 
364
        server.setUp()
 
365
        self.assertTrue(server.scheme in _protocol_handlers.keys())
 
366
 
 
367
    def test_tearDown(self):
 
368
        backing_transport = MemoryTransport()
 
369
        server = ChrootServer(backing_transport)
 
370
        server.setUp()
 
371
        server.tearDown()
 
372
        self.assertFalse(server.scheme in _protocol_handlers.keys())
 
373
 
 
374
    def test_get_url(self):
 
375
        backing_transport = MemoryTransport()
 
376
        server = ChrootServer(backing_transport)
 
377
        server.setUp()
 
378
        self.assertEqual('chroot-%d:///' % id(server), server.get_url())
 
379
        server.tearDown()
 
380
 
 
381
 
 
382
class FakeTransport(object):
 
383
    # XXX: FakeTransport copied from test_wsgi.py
 
384
 
 
385
    def __init__(self):
 
386
        self.calls = []
 
387
        self.base = 'fake:///'
 
388
 
 
389
    def abspath(self, relpath):
 
390
        return 'fake:///' + relpath
 
391
 
 
392
    def clone(self, relpath):
 
393
        self.calls.append(('clone', relpath))
 
394
        return self
 
395
 
 
396
 
 
397
class ReadonlyDecoratorTransportTest(TestCase):
 
398
    """Readonly decoration specific tests."""
 
399
 
 
400
    def test_local_parameters(self):
 
401
        import bzrlib.transport.readonly as readonly
 
402
        # connect to . in readonly mode
 
403
        transport = readonly.ReadonlyTransportDecorator('readonly+.')
 
404
        self.assertEqual(True, transport.listable())
 
405
        self.assertEqual(False, transport.should_cache())
 
406
        self.assertEqual(True, transport.is_readonly())
 
407
 
 
408
    def test_http_parameters(self):
 
409
        from bzrlib.tests.HttpServer import HttpServer
 
410
        import bzrlib.transport.readonly as readonly
 
411
        # connect to . via http which is not listable
 
412
        server = HttpServer()
 
413
        server.setUp()
 
414
        try:
 
415
            transport = get_transport('readonly+' + server.get_url())
 
416
            self.failUnless(isinstance(transport,
 
417
                                       readonly.ReadonlyTransportDecorator))
 
418
            self.assertEqual(False, transport.listable())
 
419
            self.assertEqual(True, transport.should_cache())
 
420
            self.assertEqual(True, transport.is_readonly())
 
421
        finally:
 
422
            server.tearDown()
 
423
 
 
424
 
 
425
class FakeNFSDecoratorTests(TestCaseInTempDir):
 
426
    """NFS decorator specific tests."""
 
427
 
 
428
    def get_nfs_transport(self, url):
 
429
        import bzrlib.transport.fakenfs as fakenfs
 
430
        # connect to url with nfs decoration
 
431
        return fakenfs.FakeNFSTransportDecorator('fakenfs+' + url)
 
432
 
 
433
    def test_local_parameters(self):
 
434
        # the listable, should_cache and is_readonly parameters
 
435
        # are not changed by the fakenfs decorator
 
436
        transport = self.get_nfs_transport('.')
 
437
        self.assertEqual(True, transport.listable())
 
438
        self.assertEqual(False, transport.should_cache())
 
439
        self.assertEqual(False, transport.is_readonly())
 
440
 
 
441
    def test_http_parameters(self):
 
442
        # the listable, should_cache and is_readonly parameters
 
443
        # are not changed by the fakenfs decorator
 
444
        from bzrlib.tests.HttpServer import HttpServer
 
445
        # connect to . via http which is not listable
 
446
        server = HttpServer()
 
447
        server.setUp()
 
448
        try:
 
449
            transport = self.get_nfs_transport(server.get_url())
 
450
            self.assertIsInstance(
 
451
                transport, bzrlib.transport.fakenfs.FakeNFSTransportDecorator)
 
452
            self.assertEqual(False, transport.listable())
 
453
            self.assertEqual(True, transport.should_cache())
 
454
            self.assertEqual(True, transport.is_readonly())
 
455
        finally:
 
456
            server.tearDown()
 
457
 
 
458
    def test_fakenfs_server_default(self):
 
459
        # a FakeNFSServer() should bring up a local relpath server for itself
 
460
        import bzrlib.transport.fakenfs as fakenfs
 
461
        server = fakenfs.FakeNFSServer()
 
462
        server.setUp()
 
463
        try:
 
464
            # the url should be decorated appropriately
 
465
            self.assertStartsWith(server.get_url(), 'fakenfs+')
 
466
            # and we should be able to get a transport for it
 
467
            transport = get_transport(server.get_url())
 
468
            # which must be a FakeNFSTransportDecorator instance.
 
469
            self.assertIsInstance(
 
470
                transport, fakenfs.FakeNFSTransportDecorator)
 
471
        finally:
 
472
            server.tearDown()
 
473
 
 
474
    def test_fakenfs_rename_semantics(self):
 
475
        # a FakeNFS transport must mangle the way rename errors occur to
 
476
        # look like NFS problems.
 
477
        transport = self.get_nfs_transport('.')
 
478
        self.build_tree(['from/', 'from/foo', 'to/', 'to/bar'],
 
479
                        transport=transport)
 
480
        self.assertRaises(bzrlib.errors.ResourceBusy,
 
481
                          transport.rename, 'from', 'to')
 
482
 
 
483
 
 
484
class FakeVFATDecoratorTests(TestCaseInTempDir):
 
485
    """Tests for simulation of VFAT restrictions"""
 
486
 
 
487
    def get_vfat_transport(self, url):
 
488
        """Return vfat-backed transport for test directory"""
 
489
        from bzrlib.transport.fakevfat import FakeVFATTransportDecorator
 
490
        return FakeVFATTransportDecorator('vfat+' + url)
 
491
 
 
492
    def test_transport_creation(self):
 
493
        from bzrlib.transport.fakevfat import FakeVFATTransportDecorator
 
494
        transport = self.get_vfat_transport('.')
 
495
        self.assertIsInstance(transport, FakeVFATTransportDecorator)
 
496
 
 
497
    def test_transport_mkdir(self):
 
498
        transport = self.get_vfat_transport('.')
 
499
        transport.mkdir('HELLO')
 
500
        self.assertTrue(transport.has('hello'))
 
501
        self.assertTrue(transport.has('Hello'))
 
502
 
 
503
    def test_forbidden_chars(self):
 
504
        transport = self.get_vfat_transport('.')
 
505
        self.assertRaises(ValueError, transport.has, "<NU>")
 
506
 
 
507
 
 
508
class BadTransportHandler(Transport):
 
509
    def __init__(self, base_url):
 
510
        raise DependencyNotPresent('some_lib', 'testing missing dependency')
 
511
 
 
512
 
 
513
class BackupTransportHandler(Transport):
 
514
    """Test transport that works as a backup for the BadTransportHandler"""
 
515
    pass
 
516
 
 
517
 
 
518
class TestTransportImplementation(TestCaseInTempDir):
 
519
    """Implementation verification for transports.
 
520
    
 
521
    To verify a transport we need a server factory, which is a callable
 
522
    that accepts no parameters and returns an implementation of
 
523
    bzrlib.transport.Server.
 
524
    
 
525
    That Server is then used to construct transport instances and test
 
526
    the transport via loopback activity.
 
527
 
 
528
    Currently this assumes that the Transport object is connected to the 
 
529
    current working directory.  So that whatever is done 
 
530
    through the transport, should show up in the working 
 
531
    directory, and vice-versa. This is a bug, because its possible to have
 
532
    URL schemes which provide access to something that may not be 
 
533
    result in storage on the local disk, i.e. due to file system limits, or 
 
534
    due to it being a database or some other non-filesystem tool.
 
535
 
 
536
    This also tests to make sure that the functions work with both
 
537
    generators and lists (assuming iter(list) is effectively a generator)
 
538
    """
 
539
    
 
540
    def setUp(self):
 
541
        super(TestTransportImplementation, self).setUp()
 
542
        self._server = self.transport_server()
 
543
        self._server.setUp()
 
544
        self.addCleanup(self._server.tearDown)
 
545
 
 
546
    def get_transport(self):
 
547
        """Return a connected transport to the local directory."""
 
548
        base_url = self._server.get_url()
 
549
        # try getting the transport via the regular interface:
 
550
        t = get_transport(base_url)
 
551
        if not isinstance(t, self.transport_class):
 
552
            # we did not get the correct transport class type. Override the
 
553
            # regular connection behaviour by direct construction.
 
554
            t = self.transport_class(base_url)
 
555
        return t
 
556
 
 
557
 
 
558
class TestLocalTransports(TestCase):
 
559
 
 
560
    def test_get_transport_from_abspath(self):
 
561
        here = os.path.abspath('.')
 
562
        t = get_transport(here)
 
563
        self.assertIsInstance(t, LocalTransport)
 
564
        self.assertEquals(t.base, urlutils.local_path_to_url(here) + '/')
 
565
 
 
566
    def test_get_transport_from_relpath(self):
 
567
        here = os.path.abspath('.')
 
568
        t = get_transport('.')
 
569
        self.assertIsInstance(t, LocalTransport)
 
570
        self.assertEquals(t.base, urlutils.local_path_to_url('.') + '/')
 
571
 
 
572
    def test_get_transport_from_local_url(self):
 
573
        here = os.path.abspath('.')
 
574
        here_url = urlutils.local_path_to_url(here) + '/'
 
575
        t = get_transport(here_url)
 
576
        self.assertIsInstance(t, LocalTransport)
 
577
        self.assertEquals(t.base, here_url)
 
578
 
 
579
 
 
580
class TestWin32LocalTransport(TestCase):
 
581
 
 
582
    def test_unc_clone_to_root(self):
 
583
        # Win32 UNC path like \\HOST\path
 
584
        # clone to root should stop at least at \\HOST part
 
585
        # not on \\
 
586
        t = EmulatedWin32LocalTransport('file://HOST/path/to/some/dir/')
 
587
        for i in xrange(4):
 
588
            t = t.clone('..')
 
589
        self.assertEquals(t.base, 'file://HOST/')
 
590
        # make sure we reach the root
 
591
        t = t.clone('..')
 
592
        self.assertEquals(t.base, 'file://HOST/')