/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
16
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
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,
26
    errors,
27
    )
28
from bzrlib.osutils import (
29
    pathjoin,
30
    lexists,
31
    set_or_unset_env,
32
    )
33
from bzrlib.tests import (
34
    TestCaseWithTransport,
35
    TestCase,
36
    TestSkipped,
37
    )
2004.1.25 by v.ladeuil+lp at free
Shuffle http related test code. Hopefully it ends up at the right place :)
38
from bzrlib.tests.HttpServer import HttpServer
1986.1.10 by Robert Collins
Merge from bzr.dev, fixing found bugs handling 'has('/')' in MemoryTransport and SFTP transports.
39
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
40
import bzrlib.transport.http
2485.8.20 by Vincent Ladeuil
Refactor SFTPTransport. Test suite passes.
41
from bzrlib.transport.sftp import (
42
    SFTPAbsoluteServer,
43
    SFTPHomeDirServer,
44
    SFTPTransport,
45
    )
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
46
from bzrlib.workingtree import WorkingTree
1185.16.127 by Martin Pool
[patch] paramiko sftp tests (robey)
47
48
try:
49
    import paramiko
50
    paramiko_loaded = True
51
except ImportError:
52
    paramiko_loaded = False
53
1874.1.12 by Carl Friedrich Bolz
More fixes according to John's comments.
54
1874.1.14 by Carl Friedrich Bolz
Rename setup method to make its intent clearer. Some PEP 8 issues.
55
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.
56
    """A helper to set transports on test case instances."""
1874.1.6 by holger krekel
(cfbolz, hpk) Factor out common set_transport code.
57
    if getattr(testcase, '_get_remote_is_absolute', None) is None:
58
        testcase._get_remote_is_absolute = True
59
    if testcase._get_remote_is_absolute:
2018.5.114 by Robert Collins
Commit current test pass improvements.
60
        testcase.transport_server = SFTPAbsoluteServer
1874.1.6 by holger krekel
(cfbolz, hpk) Factor out common set_transport code.
61
    else:
2018.5.114 by Robert Collins
Commit current test pass improvements.
62
        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 :)
63
    testcase.transport_readonly_server = HttpServer
1530.1.6 by Robert Collins
Trim duplicate sftp tests.
64
1874.1.9 by Carl Friedrich Bolz
Try to fix all the issues outline by john and Robert.
65
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.
66
class TestCaseWithSFTPServer(TestCaseWithTransport):
1530.1.6 by Robert Collins
Trim duplicate sftp tests.
67
    """A test case base class that provides a sftp server on localhost."""
1185.16.127 by Martin Pool
[patch] paramiko sftp tests (robey)
68
69
    def setUp(self):
1524.1.1 by Robert Collins
Test sftp with relative, absolute-in-homedir and absolute-not-in-homedir
70
        super(TestCaseWithSFTPServer, self).setUp()
1874.1.9 by Carl Friedrich Bolz
Try to fix all the issues outline by john and Robert.
71
        if not paramiko_loaded:
72
            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.
73
        set_test_transport_to_sftp(self)
1524.1.1 by Robert Collins
Test sftp with relative, absolute-in-homedir and absolute-not-in-homedir
74
1530.1.6 by Robert Collins
Trim duplicate sftp tests.
75
76
class SFTPLockTests (TestCaseWithSFTPServer):
1185.16.127 by Martin Pool
[patch] paramiko sftp tests (robey)
77
1185.49.3 by John Arbash Meinel
Added a form of locking to sftp branches. Refactored _sftp_open_exclusive to take a relative path
78
    def test_sftp_locks(self):
79
        from bzrlib.errors import LockError
80
        t = self.get_transport()
81
82
        l = t.lock_write('bogus')
83
        self.failUnlessExists('bogus.write-lock')
84
85
        # Don't wait for the lock, locking an already locked
86
        # file should raise an assert
87
        self.assertRaises(LockError, t.lock_write, 'bogus')
88
89
        l.unlock()
1185.31.33 by John Arbash Meinel
A couple more path.join statements needed changing.
90
        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
91
92
        open('something.write-lock', 'wb').write('fake lock\n')
93
        self.assertRaises(LockError, t.lock_write, 'something')
94
        os.remove('something.write-lock')
95
96
        l = t.lock_write('something')
97
98
        l2 = t.lock_write('bogus')
99
100
        l.unlock()
101
        l2.unlock()
102
1524.1.1 by Robert Collins
Test sftp with relative, absolute-in-homedir and absolute-not-in-homedir
103
1530.1.6 by Robert Collins
Trim duplicate sftp tests.
104
class SFTPTransportTestRelative(TestCaseWithSFTPServer):
1524.1.1 by Robert Collins
Test sftp with relative, absolute-in-homedir and absolute-not-in-homedir
105
    """Test the SFTP transport with homedir based relative paths."""
106
107
    def test__remote_path(self):
108
        t = self.get_transport()
2321.3.7 by Alexander Belchenko
fixes for passing test_sftp_transport on win32 (thankyou John)
109
        # This test require unix-like absolute path
110
        test_dir = self.test_dir
111
        if sys.platform == 'win32':
112
            # using hack suggested by John Meinel.
113
            # TODO: write another mock server for this test
114
            #       and use absolute path without drive letter
115
            test_dir = '/' + test_dir
1524.1.1 by Robert Collins
Test sftp with relative, absolute-in-homedir and absolute-not-in-homedir
116
        # try what is currently used:
117
        # remote path = self._abspath(relpath)
2321.3.7 by Alexander Belchenko
fixes for passing test_sftp_transport on win32 (thankyou John)
118
        self.assertEqual(test_dir + '/relative', t._remote_path('relative'))
1524.1.1 by Robert Collins
Test sftp with relative, absolute-in-homedir and absolute-not-in-homedir
119
        # 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)
120
        root_segments = test_dir.split('/')
1524.1.1 by Robert Collins
Test sftp with relative, absolute-in-homedir and absolute-not-in-homedir
121
        root_parent = '/'.join(root_segments[:-1])
122
        # .. should be honoured
123
        self.assertEqual(root_parent + '/sibling', t._remote_path('../sibling'))
124
        # /  should be illegal ?
125
        ### FIXME decide and then test for all transports. RBC20051208
126
1530.1.6 by Robert Collins
Trim duplicate sftp tests.
127
1986.1.10 by Robert Collins
Merge from bzr.dev, fixing found bugs handling 'has('/')' in MemoryTransport and SFTP transports.
128
class SFTPTransportTestRelativeRoot(TestCaseWithSFTPServer):
1530.1.6 by Robert Collins
Trim duplicate sftp tests.
129
    """Test the SFTP transport with homedir based relative paths."""
130
131
    def setUp(self):
2485.8.43 by Vincent Ladeuil
Cleaning.
132
        # Only SFTPHomeDirServer is tested here
1530.1.6 by Robert Collins
Trim duplicate sftp tests.
133
        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.
134
        super(SFTPTransportTestRelativeRoot, self).setUp()
1530.1.6 by Robert Collins
Trim duplicate sftp tests.
135
1524.1.1 by Robert Collins
Test sftp with relative, absolute-in-homedir and absolute-not-in-homedir
136
    def test__remote_path_relative_root(self):
137
        # relative paths are preserved
138
        t = self.get_transport('')
2485.8.27 by Vincent Ladeuil
Hearing jam saying "vila, you're trying too hard", I simplified again.
139
        self.assertEqual('/~/', t._path)
140
        # the remote path should be relative to home dir
141
        # (i.e. not begining with a '/')
1524.1.1 by Robert Collins
Test sftp with relative, absolute-in-homedir and absolute-not-in-homedir
142
        self.assertEqual('a', t._remote_path('a'))
143
144
1185.49.14 by John Arbash Meinel
[merge] bzr.dev
145
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
146
    def setUp(self):
147
        TestCase.setUp(self)
148
        if not paramiko_loaded:
149
            raise TestSkipped('you must have paramiko to run this test')
150
2485.8.20 by Vincent Ladeuil
Refactor SFTPTransport. Test suite passes.
151
    def test_parse_url_with_home_dir(self):
2485.8.38 by Vincent Ladeuil
Finish sftp refactoring. Test suite passing.
152
        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
153
        self.assertEquals(s._host, 'example.com')
154
        self.assertEquals(s._port, 2222)
2485.8.20 by Vincent Ladeuil
Refactor SFTPTransport. Test suite passes.
155
        self.assertEquals(s._user, 'robey')
2485.8.38 by Vincent Ladeuil
Finish sftp refactoring. Test suite passing.
156
        self.assertEquals(s._password, 'h@t')
2485.8.27 by Vincent Ladeuil
Hearing jam saying "vila, you're trying too hard", I simplified again.
157
        self.assertEquals(s._path, '/~/relative/')
1185.49.23 by John Arbash Meinel
bugreport from Matthieu Moy: relpath was failing, but throwing an unhelpful exception.
158
159
    def test_relpath(self):
2485.8.38 by Vincent Ladeuil
Finish sftp refactoring. Test suite passing.
160
        s = SFTPTransport('sftp://user@host.com/abs/path')
2485.8.20 by Vincent Ladeuil
Refactor SFTPTransport. Test suite passes.
161
        self.assertRaises(errors.PathNotChild, s.relpath,
162
                          '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)
163
2013.1.2 by John Arbash Meinel
Add a test that we can always fall back to the paramiko vendor
164
    def test_get_paramiko_vendor(self):
165
        """Test that if no 'ssh' is available we get builtin paramiko"""
166
        from bzrlib.transport import ssh
167
        # set '.' as the only location in the path, forcing no 'ssh' to exist
2221.5.18 by Dmitry Vasiliev
Fixed variable name
168
        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
169
        orig_path = set_or_unset_env('PATH', '.')
170
        try:
171
            # No vendor defined yet, query for one
2221.5.18 by Dmitry Vasiliev
Fixed variable name
172
            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
173
            vendor = ssh._get_ssh_vendor()
174
            self.assertIsInstance(vendor, ssh.ParamikoVendor)
175
        finally:
176
            set_or_unset_env('PATH', orig_path)
2221.5.18 by Dmitry Vasiliev
Fixed variable name
177
            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
178
1986.1.10 by Robert Collins
Merge from bzr.dev, fixing found bugs handling 'has('/')' in MemoryTransport and SFTP transports.
179
    def test_abspath_root_sibling_server(self):
180
        from bzrlib.transport.sftp import SFTPSiblingAbsoluteServer
181
        server = SFTPSiblingAbsoluteServer()
182
        server.setUp()
183
        try:
184
            transport = get_transport(server.get_url())
185
            self.assertFalse(transport.abspath('/').endswith('/~/'))
186
            self.assertTrue(transport.abspath('/').endswith('/'))
187
            del transport
188
        finally:
189
            server.tearDown()
190
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
191
1185.49.3 by John Arbash Meinel
Added a form of locking to sftp branches. Refactored _sftp_open_exclusive to take a relative path
192
class SFTPBranchTest(TestCaseWithSFTPServer):
193
    """Test some stuff when accessing a bzr Branch over sftp"""
194
195
    def test_lock_file(self):
1666.1.4 by Robert Collins
* 'Metadir' is now the default disk format. This improves behaviour in
196
        # old format branches use a special lock file on sftp.
197
        b = self.make_branch('', format=bzrdir.BzrDirFormat6())
198
        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
199
        self.failUnlessExists('.bzr/')
200
        self.failUnlessExists('.bzr/branch-format')
201
        self.failUnlessExists('.bzr/branch-lock')
202
1185.31.33 by John Arbash Meinel
A couple more path.join statements needed changing.
203
        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
204
        b.lock_write()
205
        self.failUnlessExists('.bzr/branch-lock.write-lock')
206
        b.unlock()
1185.31.33 by John Arbash Meinel
A couple more path.join statements needed changing.
207
        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
208
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.
209
    def test_push_support(self):
210
        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.
211
        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.
212
        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.
213
        t.add('foo')
214
        t.commit('foo', rev_id='a1')
215
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.
216
        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.
217
        b2.pull(b)
218
219
        self.assertEquals(b2.revision_history(), ['a1'])
220
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.
221
        open('a/foo', 'wt').write('something new in foo\n')
222
        t.commit('new', rev_id='a2')
223
        b2.pull(b)
224
225
        self.assertEquals(b2.revision_history(), ['a1', 'a2'])
226
1185.49.3 by John Arbash Meinel
Added a form of locking to sftp branches. Refactored _sftp_open_exclusive to take a relative path
227
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
228
class SSHVendorConnection(TestCaseWithSFTPServer):
229
    """Test that the ssh vendors can all connect.
230
231
    Verify that a full-handshake (SSH over loopback TCP) sftp connection works.
232
233
    We have 3 sftp implementations in the test suite:
234
      'loopback': Doesn't use ssh, just uses a local socket. Most tests are
235
                  done this way to save the handshaking time, so it is not
236
                  tested again here
237
      'none':     This uses paramiko's built-in ssh client and server, and layers
238
                  sftp on top of it.
239
      None:       If 'ssh' exists on the machine, then it will be spawned as a
240
                  child process.
241
    """
1547.1.4 by Robey Pointer
add a single full-handshake test to verify that sftp-over-ssh works
242
    
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
243
    def setUp(self):
244
        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.
245
        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
246
247
        def create_server():
248
            """Just a wrapper so that when created, it will set _vendor"""
249
            # SFTPFullAbsoluteServer can handle any vendor,
250
            # it just needs to be set between the time it is instantiated
251
            # and the time .setUp() is called
252
            server = SFTPFullAbsoluteServer()
253
            server._vendor = self._test_vendor
254
            return server
255
        self._test_vendor = 'loopback'
2018.5.42 by Robert Collins
Various hopefully improvements, but wsgi is broken, handing over to spiv :).
256
        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
257
        f = open('a_file', 'wb')
258
        try:
259
            f.write('foobar\n')
260
        finally:
261
            f.close()
262
263
    def set_vendor(self, vendor):
264
        self._test_vendor = vendor
265
266
    def test_connection_paramiko(self):
1951.1.8 by Andrew Bennetts
Make _get_ssh_vendor return the vendor object, rather than just a string.
267
        from bzrlib.transport import ssh
268
        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
269
        t = self.get_transport()
270
        self.assertEqual('foobar\n', t.get('a_file').read())
271
272
    def test_connection_vendor(self):
273
        raise TestSkipped("We don't test spawning real ssh,"
274
                          " because it prompts for a password."
275
                          " Enable this test if we figure out"
276
                          " how to prevent this.")
277
        self.set_vendor(None)
278
        t = self.get_transport()
279
        self.assertEqual('foobar\n', t.get('a_file').read())
280
281
282
class SSHVendorBadConnection(TestCaseWithTransport):
283
    """Test that the ssh vendors handle bad connection properly
284
285
    We don't subclass TestCaseWithSFTPServer, because we don't actually
286
    need an SFTP connection.
287
    """
288
289
    def setUp(self):
290
        if not paramiko_loaded:
291
            raise TestSkipped('you must have paramiko to run this test')
292
        super(SSHVendorBadConnection, self).setUp()
1951.1.10 by Andrew Bennetts
Move register_ssh_vendor, _ssh_vendor and _get_ssh_vendor into ssh.py
293
        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
294
1185.49.35 by John Arbash Meinel
Update tests to use a truly unused port
295
        # open a random port, so we know nobody else is using it
296
        # but don't actually listen on the port.
297
        s = socket.socket()
298
        s.bind(('localhost', 0))
299
        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
300
2221.5.18 by Dmitry Vasiliev
Fixed variable name
301
        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
302
        def reset():
2221.5.18 by Dmitry Vasiliev
Fixed variable name
303
            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
304
            s.close()
305
        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
306
307
    def set_vendor(self, vendor):
1951.1.10 by Andrew Bennetts
Move register_ssh_vendor, _ssh_vendor and _get_ssh_vendor into ssh.py
308
        import bzrlib.transport.ssh
2221.5.18 by Dmitry Vasiliev
Fixed variable name
309
        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
310
311
    def test_bad_connection_paramiko(self):
312
        """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.
313
        from bzrlib.transport import ssh
314
        self.set_vendor(ssh.ParamikoVendor())
2485.8.38 by Vincent Ladeuil
Finish sftp refactoring. Test suite passing.
315
        t = bzrlib.transport.get_transport(self.bogus_url)
316
        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
317
318
    def test_bad_connection_ssh(self):
319
        """None => auto-detect vendor"""
320
        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
321
        # This is how I would normally test the connection code
322
        # it makes it very clear what we are testing.
323
        # However, 'ssh' will create stipple on the output, so instead
324
        # I'm using run_bzr_subprocess, and parsing the output
325
        # try:
326
        #     t = bzrlib.transport.get_transport(self.bogus_url)
327
        # except errors.ConnectionError:
328
        #     # Correct error
329
        #     pass
330
        # except errors.NameError, e:
331
        #     if 'SSHException' in str(e):
332
        #         raise TestSkipped('Known NameError bug in paramiko 1.6.1')
333
        #     raise
334
        # else:
335
        #     self.fail('Excepted ConnectionError to be raised')
336
2665.4.1 by Aaron Bentley
teach run_bzr_subprocess to accept either a list of strings or a string
337
        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
338
        self.assertEqual('', out)
339
        if "NameError: global name 'SSHException'" in err:
340
            # We aren't fixing this bug, because it is a bug in
341
            # paramiko, but we know about it, so we don't have to
342
            # fail the test
343
            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
344
        self.assertContainsRe(err, r'bzr: ERROR: Unable to connect to SSH host'
345
                                   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
346
1871.1.3 by Robert Collins
proof of concept slowsocket wrapper.
347
348
class SFTPLatencyKnob(TestCaseWithSFTPServer):
349
    """Test that the testing SFTPServer's latency knob works."""
350
1874.1.9 by Carl Friedrich Bolz
Try to fix all the issues outline by john and Robert.
351
    def test_latency_knob_slows_transport(self):
352
        # change the latency knob to 500ms. We take about 40ms for a 
1871.1.3 by Robert Collins
proof of concept slowsocket wrapper.
353
        # loopback connection ordinarily.
1874.1.9 by Carl Friedrich Bolz
Try to fix all the issues outline by john and Robert.
354
        start_time = time.time()
355
        self.get_server().add_latency = 0.5
356
        transport = self.get_transport()
2485.8.38 by Vincent Ladeuil
Finish sftp refactoring. Test suite passing.
357
        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.
358
        with_latency_knob_time = time.time() - start_time
359
        self.assertTrue(with_latency_knob_time > 0.4)
360
361
    def test_default(self):
362
        # This test is potentially brittle: under extremely high machine load
363
        # it could fail, but that is quite unlikely
2631.1.1 by Aaron Bentley
Disable timing-sensitive test
364
        raise TestSkipped('Timing-sensitive test')
1874.1.9 by Carl Friedrich Bolz
Try to fix all the issues outline by john and Robert.
365
        start_time = time.time()
366
        transport = self.get_transport()
2485.8.38 by Vincent Ladeuil
Finish sftp refactoring. Test suite passing.
367
        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.
368
        regular_time = time.time() - start_time
369
        self.assertTrue(regular_time < 0.5)
370
1874.1.2 by Carl Friedrich Bolz
Refined the SocketDelay to charge latency only once per round-trip and to
371
372
class FakeSocket(object):
1874.1.9 by Carl Friedrich Bolz
Try to fix all the issues outline by john and Robert.
373
    """Fake socket object used to test the SocketDelay wrapper without
374
    using a real socket.
375
    """
1874.1.2 by Carl Friedrich Bolz
Refined the SocketDelay to charge latency only once per round-trip and to
376
377
    def __init__(self):
378
        self._data = ""
379
380
    def send(self, data, flags=0):
381
        self._data += data
382
        return len(data)
383
384
    def sendall(self, data, flags=0):
385
        self._data += data
386
        return len(data)
387
388
    def recv(self, size, flags=0):
389
        if size < len(self._data):
390
            result = self._data[:size]
391
            self._data = self._data[size:]
392
            return result
393
        else:
394
            result = self._data
395
            self._data = ""
396
            return result
397
1874.1.9 by Carl Friedrich Bolz
Try to fix all the issues outline by john and Robert.
398
1874.1.2 by Carl Friedrich Bolz
Refined the SocketDelay to charge latency only once per round-trip and to
399
class TestSocketDelay(TestCase):
1874.1.9 by Carl Friedrich Bolz
Try to fix all the issues outline by john and Robert.
400
1874.1.2 by Carl Friedrich Bolz
Refined the SocketDelay to charge latency only once per round-trip and to
401
    def setUp(self):
402
        TestCase.setUp(self)
1993.2.2 by John Arbash Meinel
Skip tests that require paramiko (or think they do)
403
        if not paramiko_loaded:
404
            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
405
406
    def test_delay(self):
407
        from bzrlib.transport.sftp import SocketDelay
408
        sending = FakeSocket()
1874.1.9 by Carl Friedrich Bolz
Try to fix all the issues outline by john and Robert.
409
        receiving = SocketDelay(sending, 0.1, bandwidth=1000000,
410
                                really_sleep=False)
1874.1.2 by Carl Friedrich Bolz
Refined the SocketDelay to charge latency only once per round-trip and to
411
        # check that simulated time is charged only per round-trip:
412
        t1 = SocketDelay.simulated_time
413
        receiving.send("connect1")
414
        self.assertEqual(sending.recv(1024), "connect1")
415
        t2 = SocketDelay.simulated_time
416
        self.assertAlmostEqual(t2 - t1, 0.1)
417
        receiving.send("connect2")
418
        self.assertEqual(sending.recv(1024), "connect2")
419
        sending.send("hello")
420
        self.assertEqual(receiving.recv(1024), "hello")
421
        t3 = SocketDelay.simulated_time
422
        self.assertAlmostEqual(t3 - t2, 0.1)
423
        sending.send("hello")
424
        self.assertEqual(receiving.recv(1024), "hello")
425
        sending.send("hello")
426
        self.assertEqual(receiving.recv(1024), "hello")
427
        sending.send("hello")
428
        self.assertEqual(receiving.recv(1024), "hello")
429
        t4 = SocketDelay.simulated_time
430
        self.assertAlmostEqual(t4, t3)
431
432
    def test_bandwidth(self):
433
        from bzrlib.transport.sftp import SocketDelay
434
        sending = FakeSocket()
1874.1.9 by Carl Friedrich Bolz
Try to fix all the issues outline by john and Robert.
435
        receiving = SocketDelay(sending, 0, bandwidth=8.0/(1024*1024),
436
                                really_sleep=False)
1874.1.2 by Carl Friedrich Bolz
Refined the SocketDelay to charge latency only once per round-trip and to
437
        # check that simulated time is charged only per round-trip:
438
        t1 = SocketDelay.simulated_time
439
        receiving.send("connect")
440
        self.assertEqual(sending.recv(1024), "connect")
441
        sending.send("a" * 100)
442
        self.assertEqual(receiving.recv(1024), "a" * 100)
443
        t2 = SocketDelay.simulated_time
444
        self.assertAlmostEqual(t2 - t1, 100 + 7)
445
1874.1.3 by Carl Friedrich Bolz
Merge bzr.dev.
446