~bzr-pqm/bzr/bzr.dev

4763.2.4 by John Arbash Meinel
merge bzr.2.1 in preparation for NEWS entry.
1
# Copyright (C) 2007-2010 Canonical Ltd
2485.8.5 by Vincent Ladeuil
Factor out InstrumentedTransport.
2
#
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
7
#
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
# GNU General Public License for more details.
12
#
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
4183.7.1 by Sabin Iacob
update FSF mailing address
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
2485.8.5 by Vincent Ladeuil
Factor out InstrumentedTransport.
16
2822.1.1 by v.ladeuil+lp at free
Fix #59150 (again) by handling paramiko availability for transport_util.py.
17
import bzrlib.hooks
4913.2.22 by John Arbash Meinel
Found something that was using an attribute I removed.
18
from bzrlib.tests import features
2822.1.1 by v.ladeuil+lp at free
Fix #59150 (again) by handling paramiko availability for transport_util.py.
19
20
# SFTPTransport offers better performances but relies on paramiko, if paramiko
21
# is not available, we fallback to FtpTransport
4913.2.22 by John Arbash Meinel
Found something that was using an attribute I removed.
22
if features.paramiko.available():
4913.2.23 by John Arbash Meinel
Of course, you still need to load the module...
23
    from bzrlib.tests import test_sftp_transport
2822.1.1 by v.ladeuil+lp at free
Fix #59150 (again) by handling paramiko availability for transport_util.py.
24
    from bzrlib.transport import sftp
2822.1.3 by v.ladeuil+lp at free
Fix backing transport and server usage for ftp support.
25
    _backing_scheme = 'sftp'
2822.1.1 by v.ladeuil+lp at free
Fix #59150 (again) by handling paramiko availability for transport_util.py.
26
    _backing_transport_class = sftp.SFTPTransport
27
    _backing_test_class = test_sftp_transport.TestCaseWithSFTPServer
28
else:
29
    from bzrlib.transport import ftp
30
    from bzrlib.tests import test_ftp_transport
2822.1.3 by v.ladeuil+lp at free
Fix backing transport and server usage for ftp support.
31
    _backing_scheme = 'ftp'
2822.1.1 by v.ladeuil+lp at free
Fix #59150 (again) by handling paramiko availability for transport_util.py.
32
    _backing_transport_class = ftp.FtpTransport
33
    _backing_test_class = test_ftp_transport.TestCaseWithFTPServer
34
2485.8.5 by Vincent Ladeuil
Factor out InstrumentedTransport.
35
from bzrlib.transport import (
2822.1.3 by v.ladeuil+lp at free
Fix backing transport and server usage for ftp support.
36
    ConnectedTransport,
4691.2.1 by Robert Collins
Add stronger test isolation by interception BzrDir.open and checking the thing being opened is known to the test suite.
37
    get_transport,
2485.8.5 by Vincent Ladeuil
Factor out InstrumentedTransport.
38
    register_transport,
2485.8.61 by Vincent Ladeuil
From review comments, use a private scheme for testing.
39
    register_urlparse_netloc_protocol,
2485.8.5 by Vincent Ladeuil
Factor out InstrumentedTransport.
40
    unregister_transport,
2485.8.61 by Vincent Ladeuil
From review comments, use a private scheme for testing.
41
    _unregister_urlparse_netloc_protocol,
2485.8.5 by Vincent Ladeuil
Factor out InstrumentedTransport.
42
    )
2822.1.1 by v.ladeuil+lp at free
Fix #59150 (again) by handling paramiko availability for transport_util.py.
43
44
45
46
class TransportHooks(bzrlib.hooks.Hooks):
2485.8.5 by Vincent Ladeuil
Factor out InstrumentedTransport.
47
    """Dict-mapping hook name to a list of callables for transport hooks"""
48
49
    def __init__(self):
2822.1.1 by v.ladeuil+lp at free
Fix #59150 (again) by handling paramiko availability for transport_util.py.
50
        super(TransportHooks, self).__init__()
2485.8.34 by Vincent Ladeuil
Refactor mutiple connections detection and fix false positives. Only
51
        # Invoked when the transport has just created a new connection.
52
        # The api signature is (transport, connection, credentials)
53
        self['_set_connection'] = []
2485.8.5 by Vincent Ladeuil
Factor out InstrumentedTransport.
54
2485.8.61 by Vincent Ladeuil
From review comments, use a private scheme for testing.
55
_hooked_scheme = 'hooked'
2485.8.5 by Vincent Ladeuil
Factor out InstrumentedTransport.
56
2822.1.3 by v.ladeuil+lp at free
Fix backing transport and server usage for ftp support.
57
def _change_scheme_in(url, actual, desired):
2822.1.4 by Vincent Ladeuil
Review feedback.
58
    if not url.startswith(actual + '://'):
2822.1.5 by Vincent Ladeuil
Review feeback.
59
        raise AssertionError('url "%r" does not start with "%r]"'
60
                             % (url, actual))
2822.1.3 by v.ladeuil+lp at free
Fix backing transport and server usage for ftp support.
61
    return desired + url[len(actual):]
62
63
2822.1.1 by v.ladeuil+lp at free
Fix #59150 (again) by handling paramiko availability for transport_util.py.
64
class InstrumentedTransport(_backing_transport_class):
2485.8.5 by Vincent Ladeuil
Factor out InstrumentedTransport.
65
    """Instrumented transport class to test commands behavior"""
66
67
    hooks = TransportHooks()
68
2485.8.61 by Vincent Ladeuil
From review comments, use a private scheme for testing.
69
    def __init__(self, base, _from_transport=None):
3376.2.4 by Martin Pool
Remove every assert statement from bzrlib!
70
        if not base.startswith(_hooked_scheme + '://'):
71
            raise ValueError(base)
2822.1.3 by v.ladeuil+lp at free
Fix backing transport and server usage for ftp support.
72
        # We need to trick the backing transport class about the scheme used
2822.1.4 by Vincent Ladeuil
Review feedback.
73
        # We'll do the reverse when we need to talk to the backing server
2822.1.3 by v.ladeuil+lp at free
Fix backing transport and server usage for ftp support.
74
        fake_base = _change_scheme_in(base, _hooked_scheme, _backing_scheme)
75
        super(InstrumentedTransport, self).__init__(
76
            fake_base, _from_transport=_from_transport)
77
        # The following is needed to minimize the effects of our trick above
78
        # while retaining the best compatibility.
79
        self._scheme = _hooked_scheme
80
        base = self._unsplit_url(self._scheme,
81
                                 self._user, self._password,
82
                                 self._host, self._port,
83
                                 self._path)
84
        super(ConnectedTransport, self).__init__(base)
2485.8.61 by Vincent Ladeuil
From review comments, use a private scheme for testing.
85
2485.8.5 by Vincent Ladeuil
Factor out InstrumentedTransport.
86
87
class ConnectionHookedTransport(InstrumentedTransport):
88
    """Transport instrumented to inspect connections"""
89
2485.8.34 by Vincent Ladeuil
Refactor mutiple connections detection and fix false positives. Only
90
    def _set_connection(self, connection, credentials):
91
        """Called when a new connection is created """
92
        super(ConnectionHookedTransport, self)._set_connection(connection,
93
                                                               credentials)
94
        for hook in self.hooks['_set_connection']:
95
            hook(self, connection, credentials)
2485.8.5 by Vincent Ladeuil
Factor out InstrumentedTransport.
96
97
2822.1.1 by v.ladeuil+lp at free
Fix #59150 (again) by handling paramiko availability for transport_util.py.
98
class TestCaseWithConnectionHookedTransport(_backing_test_class):
2485.8.5 by Vincent Ladeuil
Factor out InstrumentedTransport.
99
100
    def setUp(self):
2485.8.61 by Vincent Ladeuil
From review comments, use a private scheme for testing.
101
        register_urlparse_netloc_protocol(_hooked_scheme)
102
        register_transport(_hooked_scheme, ConnectionHookedTransport)
4985.2.1 by Vincent Ladeuil
Deploy addAttrCleanup on the whole test suite.
103
        self.addCleanup(unregister_transport, _hooked_scheme,
104
                        ConnectionHookedTransport)
105
        self.addCleanup(_unregister_urlparse_netloc_protocol, _hooked_scheme)
2485.8.5 by Vincent Ladeuil
Factor out InstrumentedTransport.
106
        super(TestCaseWithConnectionHookedTransport, self).setUp()
2485.8.59 by Vincent Ladeuil
Update from review comments.
107
        self.reset_connections()
4691.2.1 by Robert Collins
Add stronger test isolation by interception BzrDir.open and checking the thing being opened is known to the test suite.
108
        # Add the 'hooked' url to the permitted url list.
109
        # XXX: See TestCase.start_server. This whole module shouldn't need to
110
        # exist - a bug has been filed on that. once its cleanedup/removed, the
111
        # standard test support code will work and permit the server url
112
        # correctly.
113
        url = self.get_url()
114
        t = get_transport(url)
115
        if t.base.endswith('work/'):
116
            t = t.clone('../..')
117
        self.permit_url(t.base)
2485.8.36 by Vincent Ladeuil
Fix test suite to provide a better debugging experience.
118
2485.8.61 by Vincent Ladeuil
From review comments, use a private scheme for testing.
119
    def get_url(self, relpath=None):
120
        super_self = super(TestCaseWithConnectionHookedTransport, self)
121
        url = super_self.get_url(relpath)
2822.1.3 by v.ladeuil+lp at free
Fix backing transport and server usage for ftp support.
122
        # Replace the backing scheme by our own (see
123
        # InstrumentedTransport.__init__)
124
        url = _change_scheme_in(url, _backing_scheme, _hooked_scheme)
2485.8.61 by Vincent Ladeuil
From review comments, use a private scheme for testing.
125
        return url
126
2814.11.1 by Vincent Ladeuil
Renamed install_hooks to start_logging_connections (as per Martin suggestion).
127
    def start_logging_connections(self):
4985.1.5 by Vincent Ladeuil
Deploying the new overrideAttr facility further reduces the complexity
128
        self.overrideAttr(InstrumentedTransport, 'hooks', TransportHooks())
129
        # We preserved the hooks class attribute. Now we install our hook.
3256.2.13 by Daniel Watkins
Updated uses of Hooks.install_hook to Hooks.install_named_hook in tests.transport_util.
130
        ConnectionHookedTransport.hooks.install_named_hook(
131
            '_set_connection', self._collect_connection, None)
2485.8.5 by Vincent Ladeuil
Factor out InstrumentedTransport.
132
2485.8.34 by Vincent Ladeuil
Refactor mutiple connections detection and fix false positives. Only
133
    def reset_connections(self):
134
        self.connections = []
135
2814.11.1 by Vincent Ladeuil
Renamed install_hooks to start_logging_connections (as per Martin suggestion).
136
    def _collect_connection(self, transport, connection, credentials):
2485.8.56 by Vincent Ladeuil
Fix bug #112173 and bzr branch multiple connections.
137
        # Note: uncomment the following line and use 'bt' under pdb, that will
138
        # identify all the connections made including the extraneous ones.
2485.8.37 by Vincent Ladeuil
Fix merge multiple connections. Test suite *not* passing (sftp
139
        # import pdb; pdb.set_trace()
2485.8.34 by Vincent Ladeuil
Refactor mutiple connections detection and fix false positives. Only
140
        self.connections.append(connection)
2485.8.5 by Vincent Ladeuil
Factor out InstrumentedTransport.
141