~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/blackbox/test_serve.py

  • Committer: Robert Collins
  • Date: 2009-09-18 06:54:38 UTC
  • mto: This revision was merged to the branch mainline in revision 4710.
  • Revision ID: robertc@robertcollins.net-20090918065438-vagan0yap39j89xl
Focus and move out of blackbox the acceptance test for bzr+ssh connection handshake/process spawning.

Show diffs side-by-side

added added

removed removed

Lines of Context:
33
33
    )
34
34
from bzrlib.branch import Branch
35
35
from bzrlib.bzrdir import BzrDir
36
 
from bzrlib.errors import ParamikoNotPresent
37
36
from bzrlib.smart import client, medium
38
37
from bzrlib.smart.server import SmartTCPServer
39
 
from bzrlib.tests import TestCaseWithTransport, TestSkipped
 
38
from bzrlib.tests import ParamikoFeature, TestCaseWithTransport, TestSkipped
40
39
from bzrlib.trace import mutter
41
40
from bzrlib.transport import get_transport, remote
42
41
 
162
161
        self.make_read_requests(branch)
163
162
        self.assertServerFinishesCleanly(process)
164
163
 
165
 
    def test_bzr_connect_to_bzr_ssh(self):
166
 
        """User acceptance that get_transport of a bzr+ssh:// behaves correctly.
167
 
 
168
 
        bzr+ssh:// should cause bzr to run a remote bzr smart server over SSH.
169
 
        """
170
 
        try:
171
 
            # SFTPFullAbsoluteServer has a get_url method, and doesn't
172
 
            # override the interface (doesn't change self._vendor).
173
 
            from bzrlib.transport.sftp import SFTPFullAbsoluteServer
174
 
        except ParamikoNotPresent:
175
 
            raise TestSkipped('Paramiko not installed')
176
 
        from bzrlib.tests.stub_sftp import StubServer
177
 
 
178
 
        # Make a branch
179
 
        self.make_branch('a_branch')
180
 
 
181
 
        # Start an SSH server
182
 
        self.command_executed = []
183
 
        # XXX: This is horrible -- we define a really dumb SSH server that
184
 
        # executes commands, and manage the hooking up of stdin/out/err to the
185
 
        # SSH channel ourselves.  Surely this has already been implemented
186
 
        # elsewhere?
187
 
        class StubSSHServer(StubServer):
188
 
 
189
 
            test = self
190
 
 
191
 
            def check_channel_exec_request(self, channel, command):
192
 
                self.test.command_executed.append(command)
193
 
                proc = subprocess.Popen(
194
 
                    command, shell=True, stdin=subprocess.PIPE,
195
 
                    stdout=subprocess.PIPE, stderr=subprocess.PIPE)
196
 
 
197
 
                # XXX: horribly inefficient, not to mention ugly.
198
 
                # Start a thread for each of stdin/out/err, and relay bytes from
199
 
                # the subprocess to channel and vice versa.
200
 
                def ferry_bytes(read, write, close):
201
 
                    while True:
202
 
                        bytes = read(1)
203
 
                        if bytes == '':
204
 
                            close()
205
 
                            break
206
 
                        write(bytes)
207
 
 
208
 
                file_functions = [
209
 
                    (channel.recv, proc.stdin.write, proc.stdin.close),
210
 
                    (proc.stdout.read, channel.sendall, channel.close),
211
 
                    (proc.stderr.read, channel.sendall_stderr, channel.close)]
212
 
                for read, write, close in file_functions:
213
 
                    t = threading.Thread(
214
 
                        target=ferry_bytes, args=(read, write, close))
215
 
                    t.start()
216
 
 
217
 
                return True
218
 
 
219
 
        ssh_server = SFTPFullAbsoluteServer(StubSSHServer)
220
 
        # XXX: We *don't* want to override the default SSH vendor, so we set
221
 
        # _vendor to what _get_ssh_vendor returns.
222
 
        self.start_server(ssh_server)
223
 
        port = ssh_server._listener.port
224
 
 
225
 
        # Access the branch via a bzr+ssh URL.  The BZR_REMOTE_PATH environment
226
 
        # variable is used to tell bzr what command to run on the remote end.
227
 
        path_to_branch = osutils.abspath('a_branch')
228
 
 
229
 
        orig_bzr_remote_path = os.environ.get('BZR_REMOTE_PATH')
230
 
        bzr_remote_path = self.get_bzr_path()
231
 
        if sys.platform == 'win32':
232
 
            bzr_remote_path = sys.executable + ' ' + self.get_bzr_path()
233
 
        os.environ['BZR_REMOTE_PATH'] = bzr_remote_path
234
 
        try:
235
 
            if sys.platform == 'win32':
236
 
                path_to_branch = os.path.splitdrive(path_to_branch)[1]
237
 
            url_suffix = '@localhost:%d%s' % (port, path_to_branch)
238
 
            self.permit_url('bzr+ssh://fred' + url_suffix)
239
 
            branch = Branch.open('bzr+ssh://fred:secret' + url_suffix)
240
 
            self.make_read_requests(branch)
241
 
            # Check we can perform write operations
242
 
            branch.bzrdir.root_transport.mkdir('foo')
243
 
        finally:
244
 
            # Restore the BZR_REMOTE_PATH environment variable back to its
245
 
            # original state.
246
 
            if orig_bzr_remote_path is None:
247
 
                del os.environ['BZR_REMOTE_PATH']
248
 
            else:
249
 
                os.environ['BZR_REMOTE_PATH'] = orig_bzr_remote_path
250
 
 
251
 
        self.assertEqual(
252
 
            ['%s serve --inet --directory=/ --allow-writes'
253
 
             % bzr_remote_path],
254
 
            self.command_executed)
255
 
 
256
164
 
257
165
class TestCmdServeChrooting(TestCaseWithTransport):
258
166