~bzr-pqm/bzr/bzr.dev

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