/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
1185.16.127 by Martin Pool
[patch] paramiko sftp tests (robey)
1
# Copyright (C) 2005 Robey Pointer <robey@lag.net>, Canonical Ltd
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
2
#
1185.16.127 by Martin Pool
[patch] paramiko sftp tests (robey)
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
7
#
1185.16.127 by Martin Pool
[patch] paramiko sftp tests (robey)
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
# GNU General Public License for more details.
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
12
#
1185.16.127 by Martin Pool
[patch] paramiko sftp tests (robey)
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
17
import os
18
import socket
19
import threading
1871.1.3 by Robert Collins
proof of concept slowsocket wrapper.
20
import time
1185.16.127 by Martin Pool
[patch] paramiko sftp tests (robey)
21
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.
22
import bzrlib.bzrdir as bzrdir
1524.1.1 by Robert Collins
Test sftp with relative, absolute-in-homedir and absolute-not-in-homedir
23
import bzrlib.errors as errors
1530.1.7 by Robert Collins
merge integration.
24
from bzrlib.osutils import pathjoin, lexists
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.
25
from bzrlib.tests import TestCaseWithTransport, TestCase, TestSkipped
1524.1.1 by Robert Collins
Test sftp with relative, absolute-in-homedir and absolute-not-in-homedir
26
import bzrlib.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
27
import bzrlib.transport.http
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
28
from bzrlib.workingtree import WorkingTree
1185.16.127 by Martin Pool
[patch] paramiko sftp tests (robey)
29
30
try:
31
    import paramiko
32
    paramiko_loaded = True
33
except ImportError:
34
    paramiko_loaded = False
35
1874.1.12 by Carl Friedrich Bolz
More fixes according to John's comments.
36
1874.1.14 by Carl Friedrich Bolz
Rename setup method to make its intent clearer. Some PEP 8 issues.
37
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.
38
    """A helper to set transports on test case instances."""
1874.1.6 by holger krekel
(cfbolz, hpk) Factor out common set_transport code.
39
    from bzrlib.transport.sftp import SFTPAbsoluteServer, SFTPHomeDirServer
40
    if getattr(testcase, '_get_remote_is_absolute', None) is None:
41
        testcase._get_remote_is_absolute = True
42
    if testcase._get_remote_is_absolute:
43
        testcase.transport_server = SFTPAbsoluteServer
44
    else:
45
        testcase.transport_server = SFTPHomeDirServer
46
    testcase.transport_readonly_server = bzrlib.transport.http.HttpServer
1530.1.6 by Robert Collins
Trim duplicate sftp tests.
47
1874.1.9 by Carl Friedrich Bolz
Try to fix all the issues outline by john and Robert.
48
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.
49
class TestCaseWithSFTPServer(TestCaseWithTransport):
1530.1.6 by Robert Collins
Trim duplicate sftp tests.
50
    """A test case base class that provides a sftp server on localhost."""
1185.16.127 by Martin Pool
[patch] paramiko sftp tests (robey)
51
52
    def setUp(self):
1524.1.1 by Robert Collins
Test sftp with relative, absolute-in-homedir and absolute-not-in-homedir
53
        super(TestCaseWithSFTPServer, self).setUp()
1874.1.9 by Carl Friedrich Bolz
Try to fix all the issues outline by john and Robert.
54
        if not paramiko_loaded:
55
            raise TestSkipped('you must have paramiko to run this test')
1874.1.14 by Carl Friedrich Bolz
Rename setup method to make its intent clearer. Some PEP 8 issues.
56
        set_test_transport_to_sftp(self) 
1524.1.1 by Robert Collins
Test sftp with relative, absolute-in-homedir and absolute-not-in-homedir
57
58
    def get_transport(self, path=None):
59
        """Return a transport relative to self._test_root."""
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.
60
        return bzrlib.transport.get_transport(self.get_url(path))
1530.1.6 by Robert Collins
Trim duplicate sftp tests.
61
62
63
class SFTPLockTests (TestCaseWithSFTPServer):
1185.16.127 by Martin Pool
[patch] paramiko sftp tests (robey)
64
1185.49.3 by John Arbash Meinel
Added a form of locking to sftp branches. Refactored _sftp_open_exclusive to take a relative path
65
    def test_sftp_locks(self):
66
        from bzrlib.errors import LockError
67
        t = self.get_transport()
68
69
        l = t.lock_write('bogus')
70
        self.failUnlessExists('bogus.write-lock')
71
72
        # Don't wait for the lock, locking an already locked
73
        # file should raise an assert
74
        self.assertRaises(LockError, t.lock_write, 'bogus')
75
76
        l.unlock()
1185.31.33 by John Arbash Meinel
A couple more path.join statements needed changing.
77
        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
78
79
        open('something.write-lock', 'wb').write('fake lock\n')
80
        self.assertRaises(LockError, t.lock_write, 'something')
81
        os.remove('something.write-lock')
82
83
        l = t.lock_write('something')
84
85
        l2 = t.lock_write('bogus')
86
87
        l.unlock()
88
        l2.unlock()
89
1185.49.10 by John Arbash Meinel
Use a weakref dictionary to enable re-use of a connection (for sftp).
90
    def test_multiple_connections(self):
91
        t = self.get_transport()
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.
92
        self.assertTrue('sftpserver - new connection' in self.get_server().logs)
93
        self.get_server().logs = []
1185.49.10 by John Arbash Meinel
Use a weakref dictionary to enable re-use of a connection (for sftp).
94
        # The second request should reuse the first connection
95
        # SingleListener only allows for a single connection,
96
        # So the next line fails unless the connection is reused
97
        t2 = self.get_transport()
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.
98
        self.assertEquals(self.get_server().logs, [])
1524.1.1 by Robert Collins
Test sftp with relative, absolute-in-homedir and absolute-not-in-homedir
99
100
1530.1.6 by Robert Collins
Trim duplicate sftp tests.
101
class SFTPTransportTestRelative(TestCaseWithSFTPServer):
1524.1.1 by Robert Collins
Test sftp with relative, absolute-in-homedir and absolute-not-in-homedir
102
    """Test the SFTP transport with homedir based relative paths."""
103
104
    def test__remote_path(self):
105
        t = self.get_transport()
106
        # try what is currently used:
107
        # remote path = self._abspath(relpath)
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.
108
        self.assertEqual(self.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
109
        # we dont os.path.join because windows gives us the wrong path
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.
110
        root_segments = self.test_dir.split('/')
1524.1.1 by Robert Collins
Test sftp with relative, absolute-in-homedir and absolute-not-in-homedir
111
        root_parent = '/'.join(root_segments[:-1])
112
        # .. should be honoured
113
        self.assertEqual(root_parent + '/sibling', t._remote_path('../sibling'))
114
        # /  should be illegal ?
115
        ### FIXME decide and then test for all transports. RBC20051208
116
1530.1.6 by Robert Collins
Trim duplicate sftp tests.
117
118
class SFTPTransportTestRelative(TestCaseWithSFTPServer):
119
    """Test the SFTP transport with homedir based relative paths."""
120
121
    def setUp(self):
122
        self._get_remote_is_absolute = False
123
        super(SFTPTransportTestRelative, self).setUp()
124
1524.1.1 by Robert Collins
Test sftp with relative, absolute-in-homedir and absolute-not-in-homedir
125
    def test__remote_path_relative_root(self):
126
        # relative paths are preserved
127
        t = self.get_transport('')
128
        self.assertEqual('a', t._remote_path('a'))
129
130
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
131
class FakeSFTPTransport (object):
132
    _sftp = object()
133
fake = FakeSFTPTransport()
134
135
1185.49.14 by John Arbash Meinel
[merge] bzr.dev
136
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
137
    def setUp(self):
138
        TestCase.setUp(self)
139
        if not paramiko_loaded:
140
            raise TestSkipped('you must have paramiko to run this test')
141
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
142
    def test_parse_url(self):
143
        from bzrlib.transport.sftp import SFTPTransport
1534.1.8 by Robert Collins
Update SFTP Urls as per mailing list thread.
144
        s = SFTPTransport('sftp://simple.example.com/home/source', clone_from=fake)
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
145
        self.assertEquals(s._host, 'simple.example.com')
1185.49.23 by John Arbash Meinel
bugreport from Matthieu Moy: relpath was failing, but throwing an unhelpful exception.
146
        self.assertEquals(s._port, None)
1185.48.5 by James Henstridge
Change SFTP url parsing back to treat the path in sftp://host/path as
147
        self.assertEquals(s._path, '/home/source')
1185.49.19 by John Arbash Meinel
Testing that sftp.base gets properly sanitized
148
        self.failUnless(s._password is None)
149
1534.1.8 by Robert Collins
Update SFTP Urls as per mailing list thread.
150
        self.assertEquals(s.base, 'sftp://simple.example.com/home/source/')
151
152
        s = SFTPTransport('sftp://ro%62ey:h%40t@example.com:2222/~/relative', clone_from=fake)
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)
155
        self.assertEquals(s._username, 'robey')
156
        self.assertEquals(s._password, 'h@t')
1185.48.5 by James Henstridge
Change SFTP url parsing back to treat the path in sftp://host/path as
157
        self.assertEquals(s._path, 'relative')
1185.33.58 by Martin Pool
[patch] Better error when sftp urls are given with invalid port numbers (Matthieu Moy)
158
1185.49.19 by John Arbash Meinel
Testing that sftp.base gets properly sanitized
159
        # Base should not keep track of the password
1534.1.8 by Robert Collins
Update SFTP Urls as per mailing list thread.
160
        self.assertEquals(s.base, 'sftp://robey@example.com:2222/~/relative/')
1185.49.23 by John Arbash Meinel
bugreport from Matthieu Moy: relpath was failing, but throwing an unhelpful exception.
161
162
    def test_relpath(self):
163
        from bzrlib.transport.sftp import SFTPTransport
1185.31.44 by John Arbash Meinel
Cleaned up Exceptions for all transports.
164
        from bzrlib.errors import PathNotChild
1185.49.23 by John Arbash Meinel
bugreport from Matthieu Moy: relpath was failing, but throwing an unhelpful exception.
165
1534.1.8 by Robert Collins
Update SFTP Urls as per mailing list thread.
166
        s = SFTPTransport('sftp://user@host.com/abs/path', clone_from=fake)
167
        self.assertEquals(s.relpath('sftp://user@host.com/abs/path/sub'), 'sub')
1185.49.23 by John Arbash Meinel
bugreport from Matthieu Moy: relpath was failing, but throwing an unhelpful exception.
168
        # Can't test this one, because we actually get an AssertionError
169
        # TODO: Consider raising an exception rather than an assert
1534.1.8 by Robert Collins
Update SFTP Urls as per mailing list thread.
170
        #self.assertRaises(PathNotChild, s.relpath, 'http://user@host.com/abs/path/sub')
171
        self.assertRaises(PathNotChild, s.relpath, 'sftp://user2@host.com/abs/path/sub')
172
        self.assertRaises(PathNotChild, s.relpath, 'sftp://user@otherhost.com/abs/path/sub')
173
        self.assertRaises(PathNotChild, s.relpath, 'sftp://user@host.com:33/abs/path/sub')
174
        self.assertRaises(PathNotChild, s.relpath, 'sftp://user@host.com/~/rel/path/sub')
1185.49.19 by John Arbash Meinel
Testing that sftp.base gets properly sanitized
175
1185.49.25 by John Arbash Meinel
Added a couple more test cases, just in case.
176
        # Make sure it works when we don't supply a username
1534.1.8 by Robert Collins
Update SFTP Urls as per mailing list thread.
177
        s = SFTPTransport('sftp://host.com/abs/path', clone_from=fake)
178
        self.assertEquals(s.relpath('sftp://host.com/abs/path/sub'), 'sub')
1185.49.25 by John Arbash Meinel
Added a couple more test cases, just in case.
179
180
        # Make sure it works when parts of the path will be url encoded
181
        # TODO: These may be incorrect, we might need to urllib.urlencode() before
182
        # we pass the paths into the SFTPTransport constructor
183
        s = SFTPTransport('sftp://host.com/dev/,path', clone_from=fake)
184
        self.assertEquals(s.relpath('sftp://host.com/dev/,path/sub'), 'sub')
185
        s = SFTPTransport('sftp://host.com/dev/%path', clone_from=fake)
186
        self.assertEquals(s.relpath('sftp://host.com/dev/%path/sub'), 'sub')
187
1185.33.58 by Martin Pool
[patch] Better error when sftp urls are given with invalid port numbers (Matthieu Moy)
188
    def test_parse_invalid_url(self):
1185.31.44 by John Arbash Meinel
Cleaned up Exceptions for all transports.
189
        from bzrlib.transport.sftp import SFTPTransport, TransportError
1185.33.58 by Martin Pool
[patch] Better error when sftp urls are given with invalid port numbers (Matthieu Moy)
190
        try:
191
            s = SFTPTransport('sftp://lilypond.org:~janneke/public_html/bzr/gub',
192
                              clone_from=fake)
193
            self.fail('expected exception not raised')
1185.31.44 by John Arbash Meinel
Cleaned up Exceptions for all transports.
194
        except TransportError, e:
1185.33.58 by Martin Pool
[patch] Better error when sftp urls are given with invalid port numbers (Matthieu Moy)
195
            self.assertEquals(str(e), 
1824.2.1 by Johan Rydberg
Let TransportError inherit BzrNerError.
196
                    'Transport error: ~janneke: invalid port number ')
1185.33.58 by Martin Pool
[patch] Better error when sftp urls are given with invalid port numbers (Matthieu Moy)
197
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
198
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
class SFTPBranchTest(TestCaseWithSFTPServer):
200
    """Test some stuff when accessing a bzr Branch over sftp"""
201
202
    def test_lock_file(self):
1666.1.4 by Robert Collins
* 'Metadir' is now the default disk format. This improves behaviour in
203
        # old format branches use a special lock file on sftp.
204
        b = self.make_branch('', format=bzrdir.BzrDirFormat6())
205
        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
206
        self.failUnlessExists('.bzr/')
207
        self.failUnlessExists('.bzr/branch-format')
208
        self.failUnlessExists('.bzr/branch-lock')
209
1185.31.33 by John Arbash Meinel
A couple more path.join statements needed changing.
210
        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
211
        b.lock_write()
212
        self.failUnlessExists('.bzr/branch-lock.write-lock')
213
        b.unlock()
1185.31.33 by John Arbash Meinel
A couple more path.join statements needed changing.
214
        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
215
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.
216
    def test_push_support(self):
217
        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.
218
        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.
219
        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.
220
        t.add('foo')
221
        t.commit('foo', rev_id='a1')
222
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.
223
        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.
224
        b2.pull(b)
225
226
        self.assertEquals(b2.revision_history(), ['a1'])
227
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.
228
        open('a/foo', 'wt').write('something new in foo\n')
229
        t.commit('new', rev_id='a2')
230
        b2.pull(b)
231
232
        self.assertEquals(b2.revision_history(), ['a1', 'a2'])
233
1185.49.3 by John Arbash Meinel
Added a form of locking to sftp branches. Refactored _sftp_open_exclusive to take a relative path
234
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
235
class SSHVendorConnection(TestCaseWithSFTPServer):
236
    """Test that the ssh vendors can all connect.
237
238
    Verify that a full-handshake (SSH over loopback TCP) sftp connection works.
239
240
    We have 3 sftp implementations in the test suite:
241
      'loopback': Doesn't use ssh, just uses a local socket. Most tests are
242
                  done this way to save the handshaking time, so it is not
243
                  tested again here
244
      'none':     This uses paramiko's built-in ssh client and server, and layers
245
                  sftp on top of it.
246
      None:       If 'ssh' exists on the machine, then it will be spawned as a
247
                  child process.
248
    """
1547.1.4 by Robey Pointer
add a single full-handshake test to verify that sftp-over-ssh works
249
    
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
250
    def setUp(self):
251
        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.
252
        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
253
254
        def create_server():
255
            """Just a wrapper so that when created, it will set _vendor"""
256
            # SFTPFullAbsoluteServer can handle any vendor,
257
            # it just needs to be set between the time it is instantiated
258
            # and the time .setUp() is called
259
            server = SFTPFullAbsoluteServer()
260
            server._vendor = self._test_vendor
261
            return server
262
        self._test_vendor = 'loopback'
263
        self.transport_server = create_server
264
        f = open('a_file', 'wb')
265
        try:
266
            f.write('foobar\n')
267
        finally:
268
            f.close()
269
270
    def set_vendor(self, vendor):
271
        self._test_vendor = vendor
272
273
    def test_connection_paramiko(self):
274
        self.set_vendor('none')
275
        t = self.get_transport()
276
        self.assertEqual('foobar\n', t.get('a_file').read())
277
278
    def test_connection_vendor(self):
279
        raise TestSkipped("We don't test spawning real ssh,"
280
                          " because it prompts for a password."
281
                          " Enable this test if we figure out"
282
                          " how to prevent this.")
283
        self.set_vendor(None)
284
        t = self.get_transport()
285
        self.assertEqual('foobar\n', t.get('a_file').read())
286
287
288
class SSHVendorBadConnection(TestCaseWithTransport):
289
    """Test that the ssh vendors handle bad connection properly
290
291
    We don't subclass TestCaseWithSFTPServer, because we don't actually
292
    need an SFTP connection.
293
    """
294
295
    def setUp(self):
296
        if not paramiko_loaded:
297
            raise TestSkipped('you must have paramiko to run this test')
298
        super(SSHVendorBadConnection, self).setUp()
299
        import bzrlib.transport.sftp
300
301
        self._transport_sftp = bzrlib.transport.sftp
302
1185.49.35 by John Arbash Meinel
Update tests to use a truly unused port
303
        # open a random port, so we know nobody else is using it
304
        # but don't actually listen on the port.
305
        s = socket.socket()
306
        s.bind(('localhost', 0))
307
        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
308
309
        orig_vendor = bzrlib.transport.sftp._ssh_vendor
1185.49.35 by John Arbash Meinel
Update tests to use a truly unused port
310
        def 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
311
            bzrlib.transport.sftp._ssh_vendor = orig_vendor
1185.49.35 by John Arbash Meinel
Update tests to use a truly unused port
312
            s.close()
313
        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
314
315
    def set_vendor(self, vendor):
316
        self._transport_sftp._ssh_vendor = vendor
317
318
    def test_bad_connection_paramiko(self):
319
        """Test that a real connection attempt raises the right error"""
320
        self.set_vendor('none')
321
        self.assertRaises(errors.ConnectionError,
322
                          bzrlib.transport.get_transport, self.bogus_url)
323
324
    def test_bad_connection_ssh(self):
325
        """None => auto-detect vendor"""
326
        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
327
        # This is how I would normally test the connection code
328
        # it makes it very clear what we are testing.
329
        # However, 'ssh' will create stipple on the output, so instead
330
        # I'm using run_bzr_subprocess, and parsing the output
331
        # try:
332
        #     t = bzrlib.transport.get_transport(self.bogus_url)
333
        # except errors.ConnectionError:
334
        #     # Correct error
335
        #     pass
336
        # except errors.NameError, e:
337
        #     if 'SSHException' in str(e):
338
        #         raise TestSkipped('Known NameError bug in paramiko 1.6.1')
339
        #     raise
340
        # else:
341
        #     self.fail('Excepted ConnectionError to be raised')
342
343
        out, err = self.run_bzr_subprocess('log', self.bogus_url, retcode=3)
344
        self.assertEqual('', out)
345
        if "NameError: global name 'SSHException'" in err:
346
            # We aren't fixing this bug, because it is a bug in
347
            # paramiko, but we know about it, so we don't have to
348
            # fail the test
349
            raise TestSkipped('Known NameError bug with paramiko-1.6.1')
350
        self.assertContainsRe(err, 'Connection error')
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
351
1871.1.3 by Robert Collins
proof of concept slowsocket wrapper.
352
353
class SFTPLatencyKnob(TestCaseWithSFTPServer):
354
    """Test that the testing SFTPServer's latency knob works."""
355
1874.1.9 by Carl Friedrich Bolz
Try to fix all the issues outline by john and Robert.
356
    def test_latency_knob_slows_transport(self):
357
        # change the latency knob to 500ms. We take about 40ms for a 
1871.1.3 by Robert Collins
proof of concept slowsocket wrapper.
358
        # loopback connection ordinarily.
1874.1.9 by Carl Friedrich Bolz
Try to fix all the issues outline by john and Robert.
359
        start_time = time.time()
360
        self.get_server().add_latency = 0.5
361
        transport = self.get_transport()
362
        with_latency_knob_time = time.time() - start_time
363
        print with_latency_knob_time
364
        self.assertTrue(with_latency_knob_time > 0.4)
365
366
    def test_default(self):
367
        # This test is potentially brittle: under extremely high machine load
368
        # it could fail, but that is quite unlikely
369
        start_time = time.time()
370
        transport = self.get_transport()
371
        regular_time = time.time() - start_time
372
        self.assertTrue(regular_time < 0.5)
373
1874.1.2 by Carl Friedrich Bolz
Refined the SocketDelay to charge latency only once per round-trip and to
374
375
class FakeSocket(object):
1874.1.9 by Carl Friedrich Bolz
Try to fix all the issues outline by john and Robert.
376
    """Fake socket object used to test the SocketDelay wrapper without
377
    using a real socket.
378
    """
1874.1.2 by Carl Friedrich Bolz
Refined the SocketDelay to charge latency only once per round-trip and to
379
380
    def __init__(self):
381
        self._data = ""
382
383
    def send(self, data, flags=0):
384
        self._data += data
385
        return len(data)
386
387
    def sendall(self, data, flags=0):
388
        self._data += data
389
        return len(data)
390
391
    def recv(self, size, flags=0):
392
        if size < len(self._data):
393
            result = self._data[:size]
394
            self._data = self._data[size:]
395
            return result
396
        else:
397
            result = self._data
398
            self._data = ""
399
            return result
400
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
class TestSocketDelay(TestCase):
1874.1.9 by Carl Friedrich Bolz
Try to fix all the issues outline by john and Robert.
403
1874.1.2 by Carl Friedrich Bolz
Refined the SocketDelay to charge latency only once per round-trip and to
404
    def setUp(self):
405
        TestCase.setUp(self)
406
407
    def test_delay(self):
408
        from bzrlib.transport.sftp import SocketDelay
409
        sending = FakeSocket()
1874.1.9 by Carl Friedrich Bolz
Try to fix all the issues outline by john and Robert.
410
        receiving = SocketDelay(sending, 0.1, bandwidth=1000000,
411
                                really_sleep=False)
1874.1.2 by Carl Friedrich Bolz
Refined the SocketDelay to charge latency only once per round-trip and to
412
        # check that simulated time is charged only per round-trip:
413
        t1 = SocketDelay.simulated_time
414
        receiving.send("connect1")
415
        self.assertEqual(sending.recv(1024), "connect1")
416
        t2 = SocketDelay.simulated_time
417
        self.assertAlmostEqual(t2 - t1, 0.1)
418
        receiving.send("connect2")
419
        self.assertEqual(sending.recv(1024), "connect2")
420
        sending.send("hello")
421
        self.assertEqual(receiving.recv(1024), "hello")
422
        t3 = SocketDelay.simulated_time
423
        self.assertAlmostEqual(t3 - t2, 0.1)
424
        sending.send("hello")
425
        self.assertEqual(receiving.recv(1024), "hello")
426
        sending.send("hello")
427
        self.assertEqual(receiving.recv(1024), "hello")
428
        sending.send("hello")
429
        self.assertEqual(receiving.recv(1024), "hello")
430
        t4 = SocketDelay.simulated_time
431
        self.assertAlmostEqual(t4, t3)
432
433
    def test_bandwidth(self):
434
        from bzrlib.transport.sftp import SocketDelay
435
        sending = FakeSocket()
1874.1.9 by Carl Friedrich Bolz
Try to fix all the issues outline by john and Robert.
436
        receiving = SocketDelay(sending, 0, bandwidth=8.0/(1024*1024),
437
                                really_sleep=False)
1874.1.2 by Carl Friedrich Bolz
Refined the SocketDelay to charge latency only once per round-trip and to
438
        # check that simulated time is charged only per round-trip:
439
        t1 = SocketDelay.simulated_time
440
        receiving.send("connect")
441
        self.assertEqual(sending.recv(1024), "connect")
442
        sending.send("a" * 100)
443
        self.assertEqual(receiving.recv(1024), "a" * 100)
444
        t2 = SocketDelay.simulated_time
445
        self.assertAlmostEqual(t2 - t1, 100 + 7)
446
1874.1.3 by Carl Friedrich Bolz
Merge bzr.dev.
447