/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

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