~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
2221.5.1 by Dmitry Vasiliev
Added support for Putty's SSH implementation
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
2221.5.1 by Dmitry Vasiliev
Added support for Putty's SSH implementation
16
17
from bzrlib.tests import TestCase
18
from bzrlib.errors import SSHVendorNotFound, UnknownSSH
19
from bzrlib.transport.ssh import (
20
    OpenSSHSubprocessVendor,
2221.5.16 by Dmitry Vasiliev
Added comments for test_cached_vendor
21
    PLinkSubprocessVendor,
2221.5.1 by Dmitry Vasiliev
Added support for Putty's SSH implementation
22
    SSHCorpSubprocessVendor,
2221.5.16 by Dmitry Vasiliev
Added comments for test_cached_vendor
23
    SSHVendorManager,
2221.5.1 by Dmitry Vasiliev
Added support for Putty's SSH implementation
24
    )
25
26
27
class TestSSHVendorManager(SSHVendorManager):
28
29
    _ssh_version_string = ""
30
31
    def set_ssh_version_string(self, version):
32
        self._ssh_version_string = version
33
34
    def _get_ssh_version_string(self, args):
35
        return self._ssh_version_string
36
37
38
class SSHVendorManagerTests(TestCase):
39
40
    def test_register_vendor(self):
41
        manager = TestSSHVendorManager()
42
        self.assertRaises(SSHVendorNotFound, manager.get_vendor, {})
2221.5.6 by Dmitry Vasiliev
Changed tests to make sure the vendor manager returns the same object as was registered
43
        vendor = object()
44
        manager.register_vendor("vendor", vendor)
45
        self.assertIs(manager.get_vendor({"BZR_SSH": "vendor"}), vendor)
2221.5.1 by Dmitry Vasiliev
Added support for Putty's SSH implementation
46
47
    def test_default_vendor(self):
48
        manager = TestSSHVendorManager()
49
        self.assertRaises(SSHVendorNotFound, manager.get_vendor, {})
2221.5.6 by Dmitry Vasiliev
Changed tests to make sure the vendor manager returns the same object as was registered
50
        vendor = object()
51
        manager.register_default_vendor(vendor)
52
        self.assertIs(manager.get_vendor({}), vendor)
2221.5.1 by Dmitry Vasiliev
Added support for Putty's SSH implementation
53
54
    def test_get_vendor_by_environment(self):
55
        manager = TestSSHVendorManager()
56
        self.assertRaises(SSHVendorNotFound, manager.get_vendor, {})
57
        self.assertRaises(UnknownSSH,
58
            manager.get_vendor, {"BZR_SSH": "vendor"})
2221.5.6 by Dmitry Vasiliev
Changed tests to make sure the vendor manager returns the same object as was registered
59
        vendor = object()
60
        manager.register_vendor("vendor", vendor)
61
        self.assertIs(manager.get_vendor({"BZR_SSH": "vendor"}), vendor)
2221.5.1 by Dmitry Vasiliev
Added support for Putty's SSH implementation
62
63
    def test_get_vendor_by_inspection_openssh(self):
64
        manager = TestSSHVendorManager()
65
        self.assertRaises(SSHVendorNotFound, manager.get_vendor, {})
66
        manager.set_ssh_version_string("OpenSSH")
67
        self.assertIsInstance(manager.get_vendor({}), OpenSSHSubprocessVendor)
68
69
    def test_get_vendor_by_inspection_sshcorp(self):
70
        manager = TestSSHVendorManager()
71
        self.assertRaises(SSHVendorNotFound, manager.get_vendor, {})
72
        manager.set_ssh_version_string("SSH Secure Shell")
73
        self.assertIsInstance(manager.get_vendor({}), SSHCorpSubprocessVendor)
74
75
    def test_get_vendor_by_inspection_plink(self):
76
        manager = TestSSHVendorManager()
77
        self.assertRaises(SSHVendorNotFound, manager.get_vendor, {})
78
        manager.set_ssh_version_string("plink")
4636.3.1 by Alexander Belchenko
Disabled auto-detection of plink SSH client to avoid many problems. On Windows paramiko wil be used as default. Nevertheless user can force usage of plink via env variable BZR_SSH=plink
79
        # Auto-detect of plink vendor disabled, on Windows recommended
80
        # default ssh-client is paramiko
81
        # see https://bugs.launchpad.net/bugs/414743
82
        #~self.assertIsInstance(manager.get_vendor({}), PLinkSubprocessVendor)
83
        self.assertRaises(SSHVendorNotFound, manager.get_vendor, {})
2221.5.1 by Dmitry Vasiliev
Added support for Putty's SSH implementation
84
85
    def test_cached_vendor(self):
86
        manager = TestSSHVendorManager()
87
        self.assertRaises(SSHVendorNotFound, manager.get_vendor, {})
2221.5.6 by Dmitry Vasiliev
Changed tests to make sure the vendor manager returns the same object as was registered
88
        vendor = object()
89
        manager.register_vendor("vendor", vendor)
2221.5.1 by Dmitry Vasiliev
Added support for Putty's SSH implementation
90
        self.assertRaises(SSHVendorNotFound, manager.get_vendor, {})
2221.5.16 by Dmitry Vasiliev
Added comments for test_cached_vendor
91
        # Once the vendor is found the result is cached (mainly because of the
92
        # 'get_vendor' sometimes can be an expensive operation) and later
93
        # invocations of the 'get_vendor' just returns the cached value.
2221.5.6 by Dmitry Vasiliev
Changed tests to make sure the vendor manager returns the same object as was registered
94
        self.assertIs(manager.get_vendor({"BZR_SSH": "vendor"}), vendor)
95
        self.assertIs(manager.get_vendor({}), vendor)
2221.5.16 by Dmitry Vasiliev
Added comments for test_cached_vendor
96
        # The cache can be cleared by the 'clear_cache' method
97
        manager.clear_cache()
98
        self.assertRaises(SSHVendorNotFound, manager.get_vendor, {})
2221.5.1 by Dmitry Vasiliev
Added support for Putty's SSH implementation
99
2221.5.17 by Dmitry Vasiliev
Added comments for test_get_vendor_search_order
100
    def test_get_vendor_search_order(self):
101
        # The 'get_vendor' method search for SSH vendors as following:
102
        #
103
        #   1. Check previously cached value
104
        #   2. Check BZR_SSH environment variable
105
        #   3. Check the system for known SSH vendors
106
        #   4. Fall back to the default vendor if registered
107
        #
108
        # Let's now check the each check method in the reverse order
109
        # clearing the cache between each invocation:
110
2221.5.1 by Dmitry Vasiliev
Added support for Putty's SSH implementation
111
        manager = TestSSHVendorManager()
2221.5.17 by Dmitry Vasiliev
Added comments for test_get_vendor_search_order
112
        # At first no vendors are found
2221.5.1 by Dmitry Vasiliev
Added support for Putty's SSH implementation
113
        self.assertRaises(SSHVendorNotFound, manager.get_vendor, {})
114
2221.5.17 by Dmitry Vasiliev
Added comments for test_get_vendor_search_order
115
        # If the default vendor is registered it will be returned
2221.5.6 by Dmitry Vasiliev
Changed tests to make sure the vendor manager returns the same object as was registered
116
        default_vendor = object()
117
        manager.register_default_vendor(default_vendor)
118
        self.assertIs(manager.get_vendor({}), default_vendor)
2221.5.1 by Dmitry Vasiliev
Added support for Putty's SSH implementation
119
2221.5.17 by Dmitry Vasiliev
Added comments for test_get_vendor_search_order
120
        # If the known vendor is found in the system it will be returned
2221.5.8 by Dmitry Vasiliev
Added SSHVendorManager.clear_cache() method
121
        manager.clear_cache()
2221.5.1 by Dmitry Vasiliev
Added support for Putty's SSH implementation
122
        manager.set_ssh_version_string("OpenSSH")
123
        self.assertIsInstance(manager.get_vendor({}), OpenSSHSubprocessVendor)
124
2221.5.17 by Dmitry Vasiliev
Added comments for test_get_vendor_search_order
125
        # If the BZR_SSH environment variable is found it will be treated as
126
        # the vendor name
2221.5.8 by Dmitry Vasiliev
Added SSHVendorManager.clear_cache() method
127
        manager.clear_cache()
2221.5.6 by Dmitry Vasiliev
Changed tests to make sure the vendor manager returns the same object as was registered
128
        vendor = object()
129
        manager.register_vendor("vendor", vendor)
130
        self.assertIs(manager.get_vendor({"BZR_SSH": "vendor"}), vendor)
2221.5.1 by Dmitry Vasiliev
Added support for Putty's SSH implementation
131
2221.5.17 by Dmitry Vasiliev
Added comments for test_get_vendor_search_order
132
        # Last cached value always checked first
2221.5.6 by Dmitry Vasiliev
Changed tests to make sure the vendor manager returns the same object as was registered
133
        self.assertIs(manager.get_vendor({}), vendor)
2221.5.1 by Dmitry Vasiliev
Added support for Putty's SSH implementation
134
4595.17.1 by Martin
Add ability to give a path to a particular ssh client in BZR_SSH envvar
135
    def test_get_vendor_from_path_win32_plink(self):
136
        manager = TestSSHVendorManager()
137
        manager.set_ssh_version_string("plink: Release 0.60")
138
        plink_path = "C:/Program Files/PuTTY/plink.exe"
139
        vendor = manager.get_vendor({"BZR_SSH": plink_path})
140
        self.assertIsInstance(vendor, PLinkSubprocessVendor)
141
        args = vendor._get_vendor_specific_argv("user", "host", 22, ["bzr"])
142
        self.assertEqual(args[0], plink_path)
143
144
    def test_get_vendor_from_path_nix_openssh(self):
145
        manager = TestSSHVendorManager()
146
        manager.set_ssh_version_string(
147
            "OpenSSH_5.1p1 Debian-5, OpenSSL, 0.9.8g 19 Oct 2007")
148
        openssh_path = "/usr/bin/ssh"
149
        vendor = manager.get_vendor({"BZR_SSH": openssh_path})
150
        self.assertIsInstance(vendor, OpenSSHSubprocessVendor)
151
        args = vendor._get_vendor_specific_argv("user", "host", 22, ["bzr"])
152
        self.assertEqual(args[0], openssh_path)
153
2221.5.1 by Dmitry Vasiliev
Added support for Putty's SSH implementation
154
155
class SubprocessVendorsTests(TestCase):
156
2221.5.3 by Dmitry Vasiliev
Fixed plink's arguments order. Added tests for such a case.
157
    def test_openssh_command_arguments(self):
158
        vendor = OpenSSHSubprocessVendor()
159
        self.assertEqual(
160
            vendor._get_vendor_specific_argv(
161
                "user", "host", 100, command=["bzr"]),
162
            ["ssh", "-oForwardX11=no", "-oForwardAgent=no",
163
                "-oClearAllForwardings=yes", "-oProtocol=2",
164
                "-oNoHostAuthenticationForLocalhost=yes",
165
                "-p", "100",
166
                "-l", "user",
167
                "host", "bzr"]
168
            )
169
170
    def test_openssh_subsystem_arguments(self):
171
        vendor = OpenSSHSubprocessVendor()
172
        self.assertEqual(
173
            vendor._get_vendor_specific_argv(
174
                "user", "host", 100, subsystem="sftp"),
175
            ["ssh", "-oForwardX11=no", "-oForwardAgent=no",
176
                "-oClearAllForwardings=yes", "-oProtocol=2",
177
                "-oNoHostAuthenticationForLocalhost=yes",
178
                "-p", "100",
179
                "-l", "user",
180
                "-s", "host", "sftp"]
181
            )
182
183
    def test_sshcorp_command_arguments(self):
184
        vendor = SSHCorpSubprocessVendor()
185
        self.assertEqual(
186
            vendor._get_vendor_specific_argv(
187
                "user", "host", 100, command=["bzr"]),
188
            ["ssh", "-x",
189
                "-p", "100",
190
                "-l", "user",
191
                "host", "bzr"]
192
            )
193
194
    def test_sshcorp_subsystem_arguments(self):
195
        vendor = SSHCorpSubprocessVendor()
196
        self.assertEqual(
197
            vendor._get_vendor_specific_argv(
198
                "user", "host", 100, subsystem="sftp"),
199
            ["ssh", "-x",
200
                "-p", "100",
201
                "-l", "user",
202
                "-s", "sftp", "host"]
203
            )
204
205
    def test_plink_command_arguments(self):
206
        vendor = PLinkSubprocessVendor()
207
        self.assertEqual(
208
            vendor._get_vendor_specific_argv(
209
                "user", "host", 100, command=["bzr"]),
3220.1.2 by Dmitry Vasiliev
Re-enabled auto-detection of plink vendor and fixed tests
210
            ["plink", "-x", "-a", "-ssh", "-2", "-batch",
2221.5.3 by Dmitry Vasiliev
Fixed plink's arguments order. Added tests for such a case.
211
                "-P", "100",
212
                "-l", "user",
213
                "host", "bzr"]
214
            )
215
216
    def test_plink_subsystem_arguments(self):
217
        vendor = PLinkSubprocessVendor()
218
        self.assertEqual(
219
            vendor._get_vendor_specific_argv(
220
                "user", "host", 100, subsystem="sftp"),
3220.1.2 by Dmitry Vasiliev
Re-enabled auto-detection of plink vendor and fixed tests
221
            ["plink", "-x", "-a", "-ssh", "-2", "-batch",
2221.5.3 by Dmitry Vasiliev
Fixed plink's arguments order. Added tests for such a case.
222
                "-P", "100",
223
                "-l", "user",
224
                "-s", "host", "sftp"]
2221.5.1 by Dmitry Vasiliev
Added support for Putty's SSH implementation
225
            )