/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
2221.5.1 by Dmitry Vasiliev
Added support for Putty's SSH implementation
1
# Copyright (C) 2005 Robey Pointer <robey@lag.net>
2
# Copyright (C) 2005, 2006, 2007 Canonical Ltd
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
3
#
1185.16.127 by Martin Pool
[patch] paramiko sftp tests (robey)
4
# This program is free software; you can redistribute it and/or modify
5
# it under the terms of the GNU General Public License as published by
6
# the Free Software Foundation; either version 2 of the License, or
7
# (at your option) any later version.
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
8
#
1185.16.127 by Martin Pool
[patch] paramiko sftp tests (robey)
9
# This program is distributed in the hope that it will be useful,
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
# GNU General Public License for more details.
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
13
#
1185.16.127 by Martin Pool
[patch] paramiko sftp tests (robey)
14
# You should have received a copy of the GNU General Public License
15
# along with this program; if not, write to the Free Software
4183.7.1 by Sabin Iacob
update FSF mailing address
16
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
1185.16.127 by Martin Pool
[patch] paramiko sftp tests (robey)
17
18
import os
19
import socket
2321.3.7 by Alexander Belchenko
fixes for passing test_sftp_transport on win32 (thankyou John)
20
import sys
1185.16.127 by Martin Pool
[patch] paramiko sftp tests (robey)
21
import threading
1871.1.3 by Robert Collins
proof of concept slowsocket wrapper.
22
import time
1185.16.127 by Martin Pool
[patch] paramiko sftp tests (robey)
23
2822.1.1 by v.ladeuil+lp at free
Fix #59150 (again) by handling paramiko availability for transport_util.py.
24
try:
25
    import paramiko
26
    paramiko_loaded = True
27
except ImportError:
28
    paramiko_loaded = False
29
2485.8.20 by Vincent Ladeuil
Refactor SFTPTransport. Test suite passes.
30
from bzrlib import (
31
    bzrdir,
3777.1.1 by Aaron Bentley
Use auth.conf for sftp
32
    config,
2485.8.20 by Vincent Ladeuil
Refactor SFTPTransport. Test suite passes.
33
    errors,
3686.1.2 by John Arbash Meinel
Start moving the readv code into a helper.
34
    tests,
35
    transport as _mod_transport,
4222.3.13 by Jelmer Vernooij
Add tests to ensure sftp and ftp don't prompt for usernames.
36
    ui,
2485.8.20 by Vincent Ladeuil
Refactor SFTPTransport. Test suite passes.
37
    )
38
from bzrlib.osutils import (
39
    pathjoin,
40
    lexists,
41
    set_or_unset_env,
42
    )
43
from bzrlib.tests import (
44
    TestCaseWithTransport,
45
    TestCase,
46
    TestSkipped,
47
    )
2929.3.7 by Vincent Ladeuil
Rename bzrlib/test/HttpServer.py to bzrlib/tests/http_server.py and fix uses.
48
from bzrlib.tests.http_server import HttpServer
1986.1.10 by Robert Collins
Merge from bzr.dev, fixing found bugs handling 'has('/')' in MemoryTransport and SFTP transports.
49
from bzrlib.transport import get_transport
1711.2.132 by John Arbash Meinel
Clean up PEP8 and unused imports in bench_sftp.py, and missing import in bzrlib/tests/test_sftp_transport.py
50
import bzrlib.transport.http
2822.1.1 by v.ladeuil+lp at free
Fix #59150 (again) by handling paramiko availability for transport_util.py.
51
52
if paramiko_loaded:
3686.1.2 by John Arbash Meinel
Start moving the readv code into a helper.
53
    from bzrlib.transport import sftp as _mod_sftp
2822.1.1 by v.ladeuil+lp at free
Fix #59150 (again) by handling paramiko availability for transport_util.py.
54
    from bzrlib.transport.sftp import (
55
        SFTPAbsoluteServer,
56
        SFTPHomeDirServer,
57
        SFTPTransport,
58
        )
59
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
60
from bzrlib.workingtree import WorkingTree
1185.16.127 by Martin Pool
[patch] paramiko sftp tests (robey)
61
1874.1.12 by Carl Friedrich Bolz
More fixes according to John's comments.
62
1874.1.14 by Carl Friedrich Bolz
Rename setup method to make its intent clearer. Some PEP 8 issues.
63
def set_test_transport_to_sftp(testcase):
1874.1.9 by Carl Friedrich Bolz
Try to fix all the issues outline by john and Robert.
64
    """A helper to set transports on test case instances."""
1874.1.6 by holger krekel
(cfbolz, hpk) Factor out common set_transport code.
65
    if getattr(testcase, '_get_remote_is_absolute', None) is None:
66
        testcase._get_remote_is_absolute = True
67
    if testcase._get_remote_is_absolute:
2018.5.114 by Robert Collins
Commit current test pass improvements.
68
        testcase.transport_server = SFTPAbsoluteServer
1874.1.6 by holger krekel
(cfbolz, hpk) Factor out common set_transport code.
69
    else:
2018.5.114 by Robert Collins
Commit current test pass improvements.
70
        testcase.transport_server = SFTPHomeDirServer
2004.1.25 by v.ladeuil+lp at free
Shuffle http related test code. Hopefully it ends up at the right place :)
71
    testcase.transport_readonly_server = HttpServer
1530.1.6 by Robert Collins
Trim duplicate sftp tests.
72
1874.1.9 by Carl Friedrich Bolz
Try to fix all the issues outline by john and Robert.
73
1534.4.50 by Robert Collins
Got the bzrdir api straightened out, plenty of refactoring to use it pending, but the api is up and running.
74
class TestCaseWithSFTPServer(TestCaseWithTransport):
1530.1.6 by Robert Collins
Trim duplicate sftp tests.
75
    """A test case base class that provides a sftp server on localhost."""
1185.16.127 by Martin Pool
[patch] paramiko sftp tests (robey)
76
77
    def setUp(self):
1524.1.1 by Robert Collins
Test sftp with relative, absolute-in-homedir and absolute-not-in-homedir
78
        super(TestCaseWithSFTPServer, self).setUp()
1874.1.9 by Carl Friedrich Bolz
Try to fix all the issues outline by john and Robert.
79
        if not paramiko_loaded:
80
            raise TestSkipped('you must have paramiko to run this test')
2381.1.1 by Robert Collins
Split out hpss test fixes which dont depend on new or altered API's.
81
        set_test_transport_to_sftp(self)
1524.1.1 by Robert Collins
Test sftp with relative, absolute-in-homedir and absolute-not-in-homedir
82
1530.1.6 by Robert Collins
Trim duplicate sftp tests.
83
3686.1.2 by John Arbash Meinel
Start moving the readv code into a helper.
84
class SFTPLockTests(TestCaseWithSFTPServer):
1185.16.127 by Martin Pool
[patch] paramiko sftp tests (robey)
85
1185.49.3 by John Arbash Meinel
Added a form of locking to sftp branches. Refactored _sftp_open_exclusive to take a relative path
86
    def test_sftp_locks(self):
87
        from bzrlib.errors import LockError
88
        t = self.get_transport()
89
90
        l = t.lock_write('bogus')
91
        self.failUnlessExists('bogus.write-lock')
92
93
        # Don't wait for the lock, locking an already locked
94
        # file should raise an assert
95
        self.assertRaises(LockError, t.lock_write, 'bogus')
96
97
        l.unlock()
1185.31.33 by John Arbash Meinel
A couple more path.join statements needed changing.
98
        self.failIf(lexists('bogus.write-lock'))
1185.49.3 by John Arbash Meinel
Added a form of locking to sftp branches. Refactored _sftp_open_exclusive to take a relative path
99
100
        open('something.write-lock', 'wb').write('fake lock\n')
101
        self.assertRaises(LockError, t.lock_write, 'something')
102
        os.remove('something.write-lock')
103
104
        l = t.lock_write('something')
105
106
        l2 = t.lock_write('bogus')
107
108
        l.unlock()
109
        l2.unlock()
110
1524.1.1 by Robert Collins
Test sftp with relative, absolute-in-homedir and absolute-not-in-homedir
111
1530.1.6 by Robert Collins
Trim duplicate sftp tests.
112
class SFTPTransportTestRelative(TestCaseWithSFTPServer):
1524.1.1 by Robert Collins
Test sftp with relative, absolute-in-homedir and absolute-not-in-homedir
113
    """Test the SFTP transport with homedir based relative paths."""
114
115
    def test__remote_path(self):
2823.1.4 by Vincent Ladeuil
Use assertIsSameRealPath to avoid OSX aliasing (specifically /tmp
116
        if sys.platform == 'darwin':
2823.1.11 by Vincent Ladeuil
Review feedback.
117
            # This test is about sftp absolute path handling. There is already
118
            # (in this test) a TODO about windows needing an absolute path
119
            # without drive letter. To me, using self.test_dir is a trick to
120
            # get an absolute path for comparison purposes.  That fails for OSX
121
            # because the sftp server doesn't resolve the links (and it doesn't
122
            # have to). --vila 20070924
2823.1.8 by Vincent Ladeuil
Rewrite expected failure message
123
            self.knownFailure('Mac OSX symlinks /tmp to /private/tmp,'
124
                              ' testing against self.test_dir'
125
                              ' is not appropriate')
1524.1.1 by Robert Collins
Test sftp with relative, absolute-in-homedir and absolute-not-in-homedir
126
        t = self.get_transport()
2321.3.7 by Alexander Belchenko
fixes for passing test_sftp_transport on win32 (thankyou John)
127
        # This test require unix-like absolute path
128
        test_dir = self.test_dir
129
        if sys.platform == 'win32':
130
            # using hack suggested by John Meinel.
131
            # TODO: write another mock server for this test
132
            #       and use absolute path without drive letter
133
            test_dir = '/' + test_dir
1524.1.1 by Robert Collins
Test sftp with relative, absolute-in-homedir and absolute-not-in-homedir
134
        # try what is currently used:
135
        # remote path = self._abspath(relpath)
2823.1.14 by Vincent Ladeuil
Fix 141382 by comparing real paths.
136
        self.assertIsSameRealPath(test_dir + '/relative',
137
                                  t._remote_path('relative'))
1524.1.1 by Robert Collins
Test sftp with relative, absolute-in-homedir and absolute-not-in-homedir
138
        # we dont os.path.join because windows gives us the wrong path
2321.3.7 by Alexander Belchenko
fixes for passing test_sftp_transport on win32 (thankyou John)
139
        root_segments = test_dir.split('/')
1524.1.1 by Robert Collins
Test sftp with relative, absolute-in-homedir and absolute-not-in-homedir
140
        root_parent = '/'.join(root_segments[:-1])
141
        # .. should be honoured
2823.1.14 by Vincent Ladeuil
Fix 141382 by comparing real paths.
142
        self.assertIsSameRealPath(root_parent + '/sibling',
143
                                  t._remote_path('../sibling'))
1524.1.1 by Robert Collins
Test sftp with relative, absolute-in-homedir and absolute-not-in-homedir
144
        # /  should be illegal ?
145
        ### FIXME decide and then test for all transports. RBC20051208
146
1530.1.6 by Robert Collins
Trim duplicate sftp tests.
147
1986.1.10 by Robert Collins
Merge from bzr.dev, fixing found bugs handling 'has('/')' in MemoryTransport and SFTP transports.
148
class SFTPTransportTestRelativeRoot(TestCaseWithSFTPServer):
1530.1.6 by Robert Collins
Trim duplicate sftp tests.
149
    """Test the SFTP transport with homedir based relative paths."""
150
151
    def setUp(self):
2485.8.43 by Vincent Ladeuil
Cleaning.
152
        # Only SFTPHomeDirServer is tested here
1530.1.6 by Robert Collins
Trim duplicate sftp tests.
153
        self._get_remote_is_absolute = False
1986.1.10 by Robert Collins
Merge from bzr.dev, fixing found bugs handling 'has('/')' in MemoryTransport and SFTP transports.
154
        super(SFTPTransportTestRelativeRoot, self).setUp()
1530.1.6 by Robert Collins
Trim duplicate sftp tests.
155
1524.1.1 by Robert Collins
Test sftp with relative, absolute-in-homedir and absolute-not-in-homedir
156
    def test__remote_path_relative_root(self):
157
        # relative paths are preserved
158
        t = self.get_transport('')
2485.8.27 by Vincent Ladeuil
Hearing jam saying "vila, you're trying too hard", I simplified again.
159
        self.assertEqual('/~/', t._path)
160
        # the remote path should be relative to home dir
161
        # (i.e. not begining with a '/')
1524.1.1 by Robert Collins
Test sftp with relative, absolute-in-homedir and absolute-not-in-homedir
162
        self.assertEqual('a', t._remote_path('a'))
163
164
1185.49.14 by John Arbash Meinel
[merge] bzr.dev
165
class SFTPNonServerTest(TestCase):
1185.58.12 by John Arbash Meinel
Changing so that sftp tests are skipped rather than hidden when paramiko isn't present
166
    def setUp(self):
167
        TestCase.setUp(self)
168
        if not paramiko_loaded:
169
            raise TestSkipped('you must have paramiko to run this test')
170
2485.8.20 by Vincent Ladeuil
Refactor SFTPTransport. Test suite passes.
171
    def test_parse_url_with_home_dir(self):
2485.8.38 by Vincent Ladeuil
Finish sftp refactoring. Test suite passing.
172
        s = SFTPTransport('sftp://ro%62ey:h%40t@example.com:2222/~/relative')
1185.40.4 by Robey Pointer
fix sftp urls to support the ietf draft url spec wrt relative vs absolute sftp urls (this will break existing branch urls); fix username/password parsing in sftp urls; add unit tests to make sure sftp url parsing is working
173
        self.assertEquals(s._host, 'example.com')
174
        self.assertEquals(s._port, 2222)
2485.8.20 by Vincent Ladeuil
Refactor SFTPTransport. Test suite passes.
175
        self.assertEquals(s._user, 'robey')
2485.8.38 by Vincent Ladeuil
Finish sftp refactoring. Test suite passing.
176
        self.assertEquals(s._password, 'h@t')
2485.8.27 by Vincent Ladeuil
Hearing jam saying "vila, you're trying too hard", I simplified again.
177
        self.assertEquals(s._path, '/~/relative/')
1185.49.23 by John Arbash Meinel
bugreport from Matthieu Moy: relpath was failing, but throwing an unhelpful exception.
178
179
    def test_relpath(self):
2485.8.38 by Vincent Ladeuil
Finish sftp refactoring. Test suite passing.
180
        s = SFTPTransport('sftp://user@host.com/abs/path')
2485.8.20 by Vincent Ladeuil
Refactor SFTPTransport. Test suite passes.
181
        self.assertRaises(errors.PathNotChild, s.relpath,
182
                          'sftp://user@host.com/~/rel/path/sub')
1185.33.58 by Martin Pool
[patch] Better error when sftp urls are given with invalid port numbers (Matthieu Moy)
183
2013.1.2 by John Arbash Meinel
Add a test that we can always fall back to the paramiko vendor
184
    def test_get_paramiko_vendor(self):
185
        """Test that if no 'ssh' is available we get builtin paramiko"""
186
        from bzrlib.transport import ssh
187
        # set '.' as the only location in the path, forcing no 'ssh' to exist
2221.5.18 by Dmitry Vasiliev
Fixed variable name
188
        orig_vendor = ssh._ssh_vendor_manager._cached_ssh_vendor
2013.1.2 by John Arbash Meinel
Add a test that we can always fall back to the paramiko vendor
189
        orig_path = set_or_unset_env('PATH', '.')
190
        try:
191
            # No vendor defined yet, query for one
2221.5.18 by Dmitry Vasiliev
Fixed variable name
192
            ssh._ssh_vendor_manager.clear_cache()
2013.1.2 by John Arbash Meinel
Add a test that we can always fall back to the paramiko vendor
193
            vendor = ssh._get_ssh_vendor()
194
            self.assertIsInstance(vendor, ssh.ParamikoVendor)
195
        finally:
196
            set_or_unset_env('PATH', orig_path)
2221.5.18 by Dmitry Vasiliev
Fixed variable name
197
            ssh._ssh_vendor_manager._cached_ssh_vendor = orig_vendor
2013.1.2 by John Arbash Meinel
Add a test that we can always fall back to the paramiko vendor
198
1986.1.10 by Robert Collins
Merge from bzr.dev, fixing found bugs handling 'has('/')' in MemoryTransport and SFTP transports.
199
    def test_abspath_root_sibling_server(self):
200
        from bzrlib.transport.sftp import SFTPSiblingAbsoluteServer
201
        server = SFTPSiblingAbsoluteServer()
202
        server.setUp()
203
        try:
204
            transport = get_transport(server.get_url())
205
            self.assertFalse(transport.abspath('/').endswith('/~/'))
206
            self.assertTrue(transport.abspath('/').endswith('/'))
207
            del transport
208
        finally:
209
            server.tearDown()
210
1185.40.4 by Robey Pointer
fix sftp urls to support the ietf draft url spec wrt relative vs absolute sftp urls (this will break existing branch urls); fix username/password parsing in sftp urls; add unit tests to make sure sftp url parsing is working
211
1185.49.3 by John Arbash Meinel
Added a form of locking to sftp branches. Refactored _sftp_open_exclusive to take a relative path
212
class SFTPBranchTest(TestCaseWithSFTPServer):
213
    """Test some stuff when accessing a bzr Branch over sftp"""
214
215
    def test_lock_file(self):
1666.1.4 by Robert Collins
* 'Metadir' is now the default disk format. This improves behaviour in
216
        # old format branches use a special lock file on sftp.
217
        b = self.make_branch('', format=bzrdir.BzrDirFormat6())
218
        b = bzrlib.branch.Branch.open(self.get_url())
1185.49.3 by John Arbash Meinel
Added a form of locking to sftp branches. Refactored _sftp_open_exclusive to take a relative path
219
        self.failUnlessExists('.bzr/')
220
        self.failUnlessExists('.bzr/branch-format')
221
        self.failUnlessExists('.bzr/branch-lock')
222
1185.31.33 by John Arbash Meinel
A couple more path.join statements needed changing.
223
        self.failIf(lexists('.bzr/branch-lock.write-lock'))
1185.49.3 by John Arbash Meinel
Added a form of locking to sftp branches. Refactored _sftp_open_exclusive to take a relative path
224
        b.lock_write()
225
        self.failUnlessExists('.bzr/branch-lock.write-lock')
226
        b.unlock()
1185.31.33 by John Arbash Meinel
A couple more path.join statements needed changing.
227
        self.failIf(lexists('.bzr/branch-lock.write-lock'))
1185.49.3 by John Arbash Meinel
Added a form of locking to sftp branches. Refactored _sftp_open_exclusive to take a relative path
228
1185.49.26 by John Arbash Meinel
Adding tests for remote sftp branches without working trees, plus a bugfix to allow push to still work with a warning.
229
    def test_push_support(self):
230
        self.build_tree(['a/', 'a/foo'])
1534.4.50 by Robert Collins
Got the bzrdir api straightened out, plenty of refactoring to use it pending, but the api is up and running.
231
        t = bzrdir.BzrDir.create_standalone_workingtree('a')
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
232
        b = t.branch
1185.49.26 by John Arbash Meinel
Adding tests for remote sftp branches without working trees, plus a bugfix to allow push to still work with a warning.
233
        t.add('foo')
234
        t.commit('foo', rev_id='a1')
235
1534.4.50 by Robert Collins
Got the bzrdir api straightened out, plenty of refactoring to use it pending, but the api is up and running.
236
        b2 = bzrdir.BzrDir.create_branch_and_repo(self.get_url('/b'))
1185.49.26 by John Arbash Meinel
Adding tests for remote sftp branches without working trees, plus a bugfix to allow push to still work with a warning.
237
        b2.pull(b)
238
239
        self.assertEquals(b2.revision_history(), ['a1'])
240
1185.31.48 by John Arbash Meinel
Added a small test to sftp to make sure some replacing was going on in the remote side.
241
        open('a/foo', 'wt').write('something new in foo\n')
242
        t.commit('new', rev_id='a2')
243
        b2.pull(b)
244
245
        self.assertEquals(b2.revision_history(), ['a1', 'a2'])
246
1185.49.3 by John Arbash Meinel
Added a form of locking to sftp branches. Refactored _sftp_open_exclusive to take a relative path
247
1185.49.32 by John Arbash Meinel
Update tests to show that all ssh vendor failed connections work correctly, has some stipple from real ssh
248
class SSHVendorConnection(TestCaseWithSFTPServer):
249
    """Test that the ssh vendors can all connect.
250
251
    Verify that a full-handshake (SSH over loopback TCP) sftp connection works.
252
253
    We have 3 sftp implementations in the test suite:
254
      'loopback': Doesn't use ssh, just uses a local socket. Most tests are
255
                  done this way to save the handshaking time, so it is not
256
                  tested again here
257
      'none':     This uses paramiko's built-in ssh client and server, and layers
258
                  sftp on top of it.
259
      None:       If 'ssh' exists on the machine, then it will be spawned as a
260
                  child process.
261
    """
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
262
1185.49.32 by John Arbash Meinel
Update tests to show that all ssh vendor failed connections work correctly, has some stipple from real ssh
263
    def setUp(self):
264
        super(SSHVendorConnection, self).setUp()
1534.4.50 by Robert Collins
Got the bzrdir api straightened out, plenty of refactoring to use it pending, but the api is up and running.
265
        from bzrlib.transport.sftp import SFTPFullAbsoluteServer
1185.49.32 by John Arbash Meinel
Update tests to show that all ssh vendor failed connections work correctly, has some stipple from real ssh
266
267
        def create_server():
268
            """Just a wrapper so that when created, it will set _vendor"""
269
            # SFTPFullAbsoluteServer can handle any vendor,
270
            # it just needs to be set between the time it is instantiated
271
            # and the time .setUp() is called
272
            server = SFTPFullAbsoluteServer()
273
            server._vendor = self._test_vendor
274
            return server
275
        self._test_vendor = 'loopback'
2018.5.42 by Robert Collins
Various hopefully improvements, but wsgi is broken, handing over to spiv :).
276
        self.vfs_transport_server = create_server
1185.49.32 by John Arbash Meinel
Update tests to show that all ssh vendor failed connections work correctly, has some stipple from real ssh
277
        f = open('a_file', 'wb')
278
        try:
279
            f.write('foobar\n')
280
        finally:
281
            f.close()
282
283
    def set_vendor(self, vendor):
284
        self._test_vendor = vendor
285
286
    def test_connection_paramiko(self):
1951.1.8 by Andrew Bennetts
Make _get_ssh_vendor return the vendor object, rather than just a string.
287
        from bzrlib.transport import ssh
288
        self.set_vendor(ssh.ParamikoVendor())
1185.49.32 by John Arbash Meinel
Update tests to show that all ssh vendor failed connections work correctly, has some stipple from real ssh
289
        t = self.get_transport()
290
        self.assertEqual('foobar\n', t.get('a_file').read())
291
292
    def test_connection_vendor(self):
293
        raise TestSkipped("We don't test spawning real ssh,"
294
                          " because it prompts for a password."
295
                          " Enable this test if we figure out"
296
                          " how to prevent this.")
297
        self.set_vendor(None)
298
        t = self.get_transport()
299
        self.assertEqual('foobar\n', t.get('a_file').read())
300
301
302
class SSHVendorBadConnection(TestCaseWithTransport):
303
    """Test that the ssh vendors handle bad connection properly
304
305
    We don't subclass TestCaseWithSFTPServer, because we don't actually
306
    need an SFTP connection.
307
    """
308
309
    def setUp(self):
310
        if not paramiko_loaded:
311
            raise TestSkipped('you must have paramiko to run this test')
312
        super(SSHVendorBadConnection, self).setUp()
1951.1.10 by Andrew Bennetts
Move register_ssh_vendor, _ssh_vendor and _get_ssh_vendor into ssh.py
313
        import bzrlib.transport.ssh
1185.49.32 by John Arbash Meinel
Update tests to show that all ssh vendor failed connections work correctly, has some stipple from real ssh
314
1185.49.35 by John Arbash Meinel
Update tests to use a truly unused port
315
        # open a random port, so we know nobody else is using it
316
        # but don't actually listen on the port.
317
        s = socket.socket()
318
        s.bind(('localhost', 0))
319
        self.bogus_url = 'sftp://%s:%s/' % s.getsockname()
1185.49.32 by John Arbash Meinel
Update tests to show that all ssh vendor failed connections work correctly, has some stipple from real ssh
320
2221.5.18 by Dmitry Vasiliev
Fixed variable name
321
        orig_vendor = bzrlib.transport.ssh._ssh_vendor_manager._cached_ssh_vendor
1185.49.35 by John Arbash Meinel
Update tests to use a truly unused port
322
        def reset():
2221.5.18 by Dmitry Vasiliev
Fixed variable name
323
            bzrlib.transport.ssh._ssh_vendor_manager._cached_ssh_vendor = orig_vendor
1185.49.35 by John Arbash Meinel
Update tests to use a truly unused port
324
            s.close()
325
        self.addCleanup(reset)
1185.49.32 by John Arbash Meinel
Update tests to show that all ssh vendor failed connections work correctly, has some stipple from real ssh
326
327
    def set_vendor(self, vendor):
1951.1.10 by Andrew Bennetts
Move register_ssh_vendor, _ssh_vendor and _get_ssh_vendor into ssh.py
328
        import bzrlib.transport.ssh
2221.5.18 by Dmitry Vasiliev
Fixed variable name
329
        bzrlib.transport.ssh._ssh_vendor_manager._cached_ssh_vendor = vendor
1185.49.32 by John Arbash Meinel
Update tests to show that all ssh vendor failed connections work correctly, has some stipple from real ssh
330
331
    def test_bad_connection_paramiko(self):
332
        """Test that a real connection attempt raises the right error"""
1951.1.8 by Andrew Bennetts
Make _get_ssh_vendor return the vendor object, rather than just a string.
333
        from bzrlib.transport import ssh
334
        self.set_vendor(ssh.ParamikoVendor())
2485.8.38 by Vincent Ladeuil
Finish sftp refactoring. Test suite passing.
335
        t = bzrlib.transport.get_transport(self.bogus_url)
336
        self.assertRaises(errors.ConnectionError, t.get, 'foobar')
1185.49.32 by John Arbash Meinel
Update tests to show that all ssh vendor failed connections work correctly, has some stipple from real ssh
337
338
    def test_bad_connection_ssh(self):
339
        """None => auto-detect vendor"""
340
        self.set_vendor(None)
1185.49.33 by John Arbash Meinel
Spawn another bzr instance using run_bzr_subprocess, so we don't get stipple
341
        # This is how I would normally test the connection code
342
        # it makes it very clear what we are testing.
343
        # However, 'ssh' will create stipple on the output, so instead
344
        # I'm using run_bzr_subprocess, and parsing the output
345
        # try:
346
        #     t = bzrlib.transport.get_transport(self.bogus_url)
347
        # except errors.ConnectionError:
348
        #     # Correct error
349
        #     pass
350
        # except errors.NameError, e:
351
        #     if 'SSHException' in str(e):
352
        #         raise TestSkipped('Known NameError bug in paramiko 1.6.1')
353
        #     raise
354
        # else:
355
        #     self.fail('Excepted ConnectionError to be raised')
356
2665.4.1 by Aaron Bentley
teach run_bzr_subprocess to accept either a list of strings or a string
357
        out, err = self.run_bzr_subprocess(['log', self.bogus_url], retcode=3)
1185.49.33 by John Arbash Meinel
Spawn another bzr instance using run_bzr_subprocess, so we don't get stipple
358
        self.assertEqual('', out)
359
        if "NameError: global name 'SSHException'" in err:
360
            # We aren't fixing this bug, because it is a bug in
361
            # paramiko, but we know about it, so we don't have to
362
            # fail the test
363
            raise TestSkipped('Known NameError bug with paramiko-1.6.1')
2052.4.4 by John Arbash Meinel
Create a SocketConnectionError to make creating nice errors easier
364
        self.assertContainsRe(err, r'bzr: ERROR: Unable to connect to SSH host'
365
                                   r' 127\.0\.0\.1:\d+; ')
1185.49.32 by John Arbash Meinel
Update tests to show that all ssh vendor failed connections work correctly, has some stipple from real ssh
366
1871.1.3 by Robert Collins
proof of concept slowsocket wrapper.
367
368
class SFTPLatencyKnob(TestCaseWithSFTPServer):
369
    """Test that the testing SFTPServer's latency knob works."""
370
1874.1.9 by Carl Friedrich Bolz
Try to fix all the issues outline by john and Robert.
371
    def test_latency_knob_slows_transport(self):
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
372
        # change the latency knob to 500ms. We take about 40ms for a
1871.1.3 by Robert Collins
proof of concept slowsocket wrapper.
373
        # loopback connection ordinarily.
1874.1.9 by Carl Friedrich Bolz
Try to fix all the issues outline by john and Robert.
374
        start_time = time.time()
375
        self.get_server().add_latency = 0.5
376
        transport = self.get_transport()
2485.8.38 by Vincent Ladeuil
Finish sftp refactoring. Test suite passing.
377
        transport.has('not me') # Force connection by issuing a request
1874.1.9 by Carl Friedrich Bolz
Try to fix all the issues outline by john and Robert.
378
        with_latency_knob_time = time.time() - start_time
379
        self.assertTrue(with_latency_knob_time > 0.4)
380
381
    def test_default(self):
382
        # This test is potentially brittle: under extremely high machine load
383
        # it could fail, but that is quite unlikely
2631.1.1 by Aaron Bentley
Disable timing-sensitive test
384
        raise TestSkipped('Timing-sensitive test')
1874.1.9 by Carl Friedrich Bolz
Try to fix all the issues outline by john and Robert.
385
        start_time = time.time()
386
        transport = self.get_transport()
2485.8.38 by Vincent Ladeuil
Finish sftp refactoring. Test suite passing.
387
        transport.has('not me') # Force connection by issuing a request
1874.1.9 by Carl Friedrich Bolz
Try to fix all the issues outline by john and Robert.
388
        regular_time = time.time() - start_time
389
        self.assertTrue(regular_time < 0.5)
390
1874.1.2 by Carl Friedrich Bolz
Refined the SocketDelay to charge latency only once per round-trip and to
391
392
class FakeSocket(object):
1874.1.9 by Carl Friedrich Bolz
Try to fix all the issues outline by john and Robert.
393
    """Fake socket object used to test the SocketDelay wrapper without
394
    using a real socket.
395
    """
1874.1.2 by Carl Friedrich Bolz
Refined the SocketDelay to charge latency only once per round-trip and to
396
397
    def __init__(self):
398
        self._data = ""
399
400
    def send(self, data, flags=0):
401
        self._data += data
402
        return len(data)
403
404
    def sendall(self, data, flags=0):
405
        self._data += data
406
        return len(data)
407
408
    def recv(self, size, flags=0):
409
        if size < len(self._data):
410
            result = self._data[:size]
411
            self._data = self._data[size:]
412
            return result
413
        else:
414
            result = self._data
415
            self._data = ""
416
            return result
417
1874.1.9 by Carl Friedrich Bolz
Try to fix all the issues outline by john and Robert.
418
1874.1.2 by Carl Friedrich Bolz
Refined the SocketDelay to charge latency only once per round-trip and to
419
class TestSocketDelay(TestCase):
1874.1.9 by Carl Friedrich Bolz
Try to fix all the issues outline by john and Robert.
420
1874.1.2 by Carl Friedrich Bolz
Refined the SocketDelay to charge latency only once per round-trip and to
421
    def setUp(self):
422
        TestCase.setUp(self)
1993.2.2 by John Arbash Meinel
Skip tests that require paramiko (or think they do)
423
        if not paramiko_loaded:
424
            raise TestSkipped('you must have paramiko to run this test')
1874.1.2 by Carl Friedrich Bolz
Refined the SocketDelay to charge latency only once per round-trip and to
425
426
    def test_delay(self):
427
        from bzrlib.transport.sftp import SocketDelay
428
        sending = FakeSocket()
1874.1.9 by Carl Friedrich Bolz
Try to fix all the issues outline by john and Robert.
429
        receiving = SocketDelay(sending, 0.1, bandwidth=1000000,
430
                                really_sleep=False)
1874.1.2 by Carl Friedrich Bolz
Refined the SocketDelay to charge latency only once per round-trip and to
431
        # check that simulated time is charged only per round-trip:
432
        t1 = SocketDelay.simulated_time
433
        receiving.send("connect1")
434
        self.assertEqual(sending.recv(1024), "connect1")
435
        t2 = SocketDelay.simulated_time
436
        self.assertAlmostEqual(t2 - t1, 0.1)
437
        receiving.send("connect2")
438
        self.assertEqual(sending.recv(1024), "connect2")
439
        sending.send("hello")
440
        self.assertEqual(receiving.recv(1024), "hello")
441
        t3 = SocketDelay.simulated_time
442
        self.assertAlmostEqual(t3 - t2, 0.1)
443
        sending.send("hello")
444
        self.assertEqual(receiving.recv(1024), "hello")
445
        sending.send("hello")
446
        self.assertEqual(receiving.recv(1024), "hello")
447
        sending.send("hello")
448
        self.assertEqual(receiving.recv(1024), "hello")
449
        t4 = SocketDelay.simulated_time
450
        self.assertAlmostEqual(t4, t3)
451
452
    def test_bandwidth(self):
453
        from bzrlib.transport.sftp import SocketDelay
454
        sending = FakeSocket()
1874.1.9 by Carl Friedrich Bolz
Try to fix all the issues outline by john and Robert.
455
        receiving = SocketDelay(sending, 0, bandwidth=8.0/(1024*1024),
456
                                really_sleep=False)
1874.1.2 by Carl Friedrich Bolz
Refined the SocketDelay to charge latency only once per round-trip and to
457
        # check that simulated time is charged only per round-trip:
458
        t1 = SocketDelay.simulated_time
459
        receiving.send("connect")
460
        self.assertEqual(sending.recv(1024), "connect")
461
        sending.send("a" * 100)
462
        self.assertEqual(receiving.recv(1024), "a" * 100)
463
        t2 = SocketDelay.simulated_time
464
        self.assertAlmostEqual(t2 - t1, 100 + 7)
465
1874.1.3 by Carl Friedrich Bolz
Merge bzr.dev.
466
3815.2.4 by Martin Pool
merge fix for out-of-order SFTP readv
467
class ReadvFile(object):
468
    """An object that acts like Paramiko's SFTPFile.readv()"""
469
470
    def __init__(self, data):
471
        self._data = data
472
473
    def readv(self, requests):
474
        for start, length in requests:
475
            yield self._data[start:start+length]
476
477
3882.7.16 by Martin Pool
Update SFTP tests to accommodate progress reporting
478
def _null_report_activity(*a, **k):
479
    pass
480
481
3686.1.2 by John Arbash Meinel
Start moving the readv code into a helper.
482
class Test_SFTPReadvHelper(tests.TestCase):
483
3686.1.6 by John Arbash Meinel
Respond to Martin's review comments.
484
    def checkGetRequests(self, expected_requests, offsets):
3741.1.1 by Vincent Ladeuil
Fix test requirement (paramiko).
485
        if not paramiko_loaded:
486
            raise TestSkipped('you must have paramiko to run this test')
3882.7.16 by Martin Pool
Update SFTP tests to accommodate progress reporting
487
        helper = _mod_sftp._SFTPReadvHelper(offsets, 'artificial_test',
488
            _null_report_activity)
3686.1.2 by John Arbash Meinel
Start moving the readv code into a helper.
489
        self.assertEqual(expected_requests, helper._get_requests())
490
491
    def test__get_requests(self):
492
        # Small single requests become a single readv request
3686.1.6 by John Arbash Meinel
Respond to Martin's review comments.
493
        self.checkGetRequests([(0, 100)],
494
                              [(0, 20), (30, 50), (20, 10), (80, 20)])
3686.1.2 by John Arbash Meinel
Start moving the readv code into a helper.
495
        # Non-contiguous ranges are given as multiple requests
3686.1.6 by John Arbash Meinel
Respond to Martin's review comments.
496
        self.checkGetRequests([(0, 20), (30, 50)],
497
                              [(10, 10), (30, 20), (0, 10), (50, 30)])
3686.1.2 by John Arbash Meinel
Start moving the readv code into a helper.
498
        # Ranges larger than _max_request_size (32kB) are broken up into
499
        # multiple requests, even if it actually spans multiple logical
500
        # requests
3686.1.6 by John Arbash Meinel
Respond to Martin's review comments.
501
        self.checkGetRequests([(0, 32768), (32768, 32768), (65536, 464)],
502
                              [(0, 40000), (40000, 100), (40100, 1900),
503
                               (42000, 24000)])
3777.1.1 by Aaron Bentley
Use auth.conf for sftp
504
3815.2.4 by Martin Pool
merge fix for out-of-order SFTP readv
505
    def checkRequestAndYield(self, expected, data, offsets):
3734.2.18 by Vincent Ladeuil
Fix missing dependency check for paramiko.
506
        if not paramiko_loaded:
507
            raise TestSkipped('you must have paramiko to run this test')
3882.7.16 by Martin Pool
Update SFTP tests to accommodate progress reporting
508
        helper = _mod_sftp._SFTPReadvHelper(offsets, 'artificial_test',
509
            _null_report_activity)
3815.2.4 by Martin Pool
merge fix for out-of-order SFTP readv
510
        data_f = ReadvFile(data)
511
        result = list(helper.request_and_yield_offsets(data_f))
512
        self.assertEqual(expected, result)
513
514
    def test_request_and_yield_offsets(self):
515
        data = 'abcdefghijklmnopqrstuvwxyz'
516
        self.checkRequestAndYield([(0, 'a'), (5, 'f'), (10, 'klm')], data,
517
                                  [(0, 1), (5, 1), (10, 3)])
518
        # Should combine requests, and split them again
519
        self.checkRequestAndYield([(0, 'a'), (1, 'b'), (10, 'klm')], data,
520
                                  [(0, 1), (1, 1), (10, 3)])
521
        # Out of order requests. The requests should get combined, but then be
522
        # yielded out-of-order. We also need one that is at the end of a
523
        # previous range. See bug #293746
524
        self.checkRequestAndYield([(0, 'a'), (10, 'k'), (4, 'efg'), (1, 'bcd')],
525
                                  data, [(0, 1), (10, 1), (4, 3), (1, 3)])
526
3777.1.1 by Aaron Bentley
Use auth.conf for sftp
527
528
class TestUsesAuthConfig(TestCaseWithSFTPServer):
3777.1.4 by Aaron Bentley
bzr+ssh and sftp both use ssh scheme.
529
    """Test that AuthenticationConfig can supply default usernames."""
3777.1.1 by Aaron Bentley
Use auth.conf for sftp
530
3777.1.2 by Aaron Bentley
Make testing more thorough
531
    def get_transport_for_connection(self, set_config):
3777.1.1 by Aaron Bentley
Use auth.conf for sftp
532
        port = self.get_server()._listener.port
3777.1.2 by Aaron Bentley
Make testing more thorough
533
        if set_config:
534
            conf = config.AuthenticationConfig()
535
            conf._get_config().update(
3777.1.4 by Aaron Bentley
bzr+ssh and sftp both use ssh scheme.
536
                {'sftptest': {'scheme': 'ssh', 'port': port, 'user': 'bar'}})
3777.1.2 by Aaron Bentley
Make testing more thorough
537
            conf._save()
3777.1.1 by Aaron Bentley
Use auth.conf for sftp
538
        t = get_transport('sftp://localhost:%d' % port)
3777.1.2 by Aaron Bentley
Make testing more thorough
539
        # force a connection to be performed.
3777.1.1 by Aaron Bentley
Use auth.conf for sftp
540
        t.has('foo')
3777.1.2 by Aaron Bentley
Make testing more thorough
541
        return t
542
543
    def test_sftp_uses_config(self):
544
        t = self.get_transport_for_connection(set_config=True)
3777.1.1 by Aaron Bentley
Use auth.conf for sftp
545
        self.assertEqual('bar', t._get_credentials()[0])
3777.1.2 by Aaron Bentley
Make testing more thorough
546
547
    def test_sftp_is_none_if_no_config(self):
548
        t = self.get_transport_for_connection(set_config=False)
4304.2.1 by Vincent Ladeuil
Fix bug #367726 by reverting some default user handling introduced
549
        self.assertIs(None, t._get_credentials()[0])
4222.3.13 by Jelmer Vernooij
Add tests to ensure sftp and ftp don't prompt for usernames.
550
551
    def test_sftp_doesnt_prompt_username(self):
552
        stdout = tests.StringIOWrapper()
553
        ui.ui_factory = tests.TestUIFactory(stdin='joe\nfoo\n', stdout=stdout)
554
        t = self.get_transport_for_connection(set_config=False)
4304.2.1 by Vincent Ladeuil
Fix bug #367726 by reverting some default user handling introduced
555
        self.assertIs(None, t._get_credentials()[0])
4222.3.13 by Jelmer Vernooij
Add tests to ensure sftp and ftp don't prompt for usernames.
556
        # No prompts should've been printed, stdin shouldn't have been read
557
        self.assertEquals("", stdout.getvalue())
558
        self.assertEquals(0, ui.ui_factory.stdin.tell())