/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
2052.3.2 by John Arbash Meinel
Change Copyright .. by Canonical to Copyright ... Canonical
1
# Copyright (C) 2006 Canonical Ltd
1910.19.7 by Andrew Bennetts
Allow specifying the host/interface to bzr serve, and use the new test
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
1910.19.7 by Andrew Bennetts
Allow specifying the host/interface to bzr serve, and use the new test
16
17
18
"""Tests of the bzr serve command."""
19
2018.1.2 by Andrew Bennetts
Tidy imports, skip test if paramiko isn't installed.
20
import os
4634.43.7 by Andrew Bennetts
Add some unit tests for parts of userdir expansion.
21
import os.path
1910.19.7 by Andrew Bennetts
Allow specifying the host/interface to bzr serve, and use the new test
22
import signal
2018.1.2 by Andrew Bennetts
Tidy imports, skip test if paramiko isn't installed.
23
import subprocess
2309.2.5 by Alexander Belchenko
test_bzr_connect_to_bzr_ssh: win32-compatibility
24
import sys
4544.1.2 by Andrew Bennetts
Add test that would catch the lack of ChrootServer in cmd_serve.
25
import thread
2018.1.2 by Andrew Bennetts
Tidy imports, skip test if paramiko isn't installed.
26
import threading
1910.19.7 by Andrew Bennetts
Allow specifying the host/interface to bzr serve, and use the new test
27
2309.2.5 by Alexander Belchenko
test_bzr_connect_to_bzr_ssh: win32-compatibility
28
from bzrlib import (
4634.43.8 by Andrew Bennetts
Test for recovering the --directory value from the transport cmd_serve passes to bzr_serve.
29
    builtins,
2309.2.5 by Alexander Belchenko
test_bzr_connect_to_bzr_ssh: win32-compatibility
30
    errors,
31
    osutils,
2598.5.1 by Aaron Bentley
Start eliminating the use of None to indicate null revision
32
    revision as _mod_revision,
2309.2.5 by Alexander Belchenko
test_bzr_connect_to_bzr_ssh: win32-compatibility
33
    )
1910.19.7 by Andrew Bennetts
Allow specifying the host/interface to bzr serve, and use the new test
34
from bzrlib.branch import Branch
1910.19.11 by Andrew Bennetts
General code cleanup based on review comments and other observations.
35
from bzrlib.bzrdir import BzrDir
2018.1.2 by Andrew Bennetts
Tidy imports, skip test if paramiko isn't installed.
36
from bzrlib.errors import ParamikoNotPresent
4544.1.2 by Andrew Bennetts
Add test that would catch the lack of ChrootServer in cmd_serve.
37
from bzrlib.smart import client, medium
4634.43.15 by Andrew Bennetts
Rename BzrServerMaker -> BzrServerFactory.
38
from bzrlib.smart.server import BzrServerFactory, SmartTCPServer
4634.43.7 by Andrew Bennetts
Add some unit tests for parts of userdir expansion.
39
from bzrlib.tests import (
40
    TestCaseWithTransport,
41
    TestCaseWithMemoryTransport,
42
    TestSkipped,
43
    )
4544.1.2 by Andrew Bennetts
Add test that would catch the lack of ChrootServer in cmd_serve.
44
from bzrlib.trace import mutter
2018.5.21 by Andrew Bennetts
Move bzrlib.transport.smart to bzrlib.smart
45
from bzrlib.transport import get_transport, remote
1910.19.11 by Andrew Bennetts
General code cleanup based on review comments and other observations.
46
47
1910.19.7 by Andrew Bennetts
Allow specifying the host/interface to bzr serve, and use the new test
48
class TestBzrServe(TestCaseWithTransport):
1910.19.11 by Andrew Bennetts
General code cleanup based on review comments and other observations.
49
4695.3.1 by Vincent Ladeuil
Fix test failures with no C extensions loaded.
50
    def setUp(self):
51
        super(TestBzrServe, self).setUp()
4695.3.2 by Vincent Ladeuil
Simplified and claried as per Robert's review.
52
        self.disable_missing_extensions_warning()
4695.3.1 by Vincent Ladeuil
Fix test failures with no C extensions loaded.
53
2018.2.3 by Andrew Bennetts
Starting factoring out the smart server client "medium" from the protocol.
54
    def assertInetServerShutsdownCleanly(self, process):
2020.1.1 by Robert Collins
Add readonly support to the smart server, enabled by default via `bzr server`.
55
        """Shutdown the server process looking for errors."""
2018.2.3 by Andrew Bennetts
Starting factoring out the smart server client "medium" from the protocol.
56
        # Shutdown the server: the server should shut down when it cannot read
57
        # from stdin anymore.
58
        process.stdin.close()
1910.19.11 by Andrew Bennetts
General code cleanup based on review comments and other observations.
59
        # Hide stdin from the subprocess module, so it won't fail to close it.
60
        process.stdin = None
2581.1.2 by Martin Pool
Remove unnecessary retcode=0 to run_bzr calls
61
        result = self.finish_bzr_subprocess(process)
1910.19.11 by Andrew Bennetts
General code cleanup based on review comments and other observations.
62
        self.assertEqual('', result[0])
63
        self.assertEqual('', result[1])
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
64
2020.1.1 by Robert Collins
Add readonly support to the smart server, enabled by default via `bzr server`.
65
    def assertServerFinishesCleanly(self, process):
66
        """Shutdown the bzr serve instance process looking for errors."""
67
        # Shutdown the server
68
        result = self.finish_bzr_subprocess(process, retcode=3,
69
                                            send_signal=signal.SIGINT)
70
        self.assertEqual('', result[0])
71
        self.assertEqual('bzr: interrupted\n', result[1])
72
3287.6.4 by Robert Collins
Fix up deprecation warnings for get_revision_graph.
73
    def make_read_requests(self, branch):
74
        """Do some read only requests."""
75
        branch.lock_read()
76
        try:
77
            branch.repository.all_revision_ids()
78
            self.assertEqual(_mod_revision.NULL_REVISION,
79
                             _mod_revision.ensure_null(branch.last_revision()))
80
        finally:
81
            branch.unlock()
82
2020.1.1 by Robert Collins
Add readonly support to the smart server, enabled by default via `bzr server`.
83
    def start_server_inet(self, extra_options=()):
84
        """Start a bzr server subprocess using the --inet option.
85
86
        :param extra_options: extra options to give the server.
87
        :return: a tuple with the bzr process handle for passing to
88
            finish_bzr_subprocess, a client for the server, and a transport.
89
        """
90
        # Serve from the current directory
91
        process = self.start_bzr_subprocess(['serve', '--inet'])
92
93
        # Connect to the server
94
        # We use this url because while this is no valid URL to connect to this
95
        # server instance, the transport needs a URL.
3431.3.7 by Andrew Bennetts
Fix incidental breakage in blackbox/test_serve.py
96
        url = 'bzr://localhost/'
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.
97
        self.permit_url(url)
2018.5.15 by Andrew Bennetts
Tidy some imports, and bugs introduced when adding server.py
98
        client_medium = medium.SmartSimplePipesClientMedium(
3431.3.7 by Andrew Bennetts
Fix incidental breakage in blackbox/test_serve.py
99
            process.stdout, process.stdin, url)
100
        transport = remote.RemoteTransport(url, medium=client_medium)
2018.2.3 by Andrew Bennetts
Starting factoring out the smart server client "medium" from the protocol.
101
        return process, transport
2020.1.1 by Robert Collins
Add readonly support to the smart server, enabled by default via `bzr server`.
102
103
    def start_server_port(self, extra_options=()):
104
        """Start a bzr server subprocess.
105
106
        :param extra_options: extra options to give the server.
107
        :return: a tuple with the bzr process handle for passing to
108
            finish_bzr_subprocess, and the base url for the server.
109
        """
110
        # Serve from the current directory
111
        args = ['serve', '--port', 'localhost:0']
112
        args.extend(extra_options)
113
        process = self.start_bzr_subprocess(args, skip_if_plan_to_signal=True)
3955.1.7 by Jonathan Lange
Fix some tests that assumed the port was on stderr rather than stdout.
114
        port_line = process.stderr.readline()
1910.19.7 by Andrew Bennetts
Allow specifying the host/interface to bzr serve, and use the new test
115
        prefix = 'listening on port: '
116
        self.assertStartsWith(port_line, prefix)
117
        port = int(port_line[len(prefix):])
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.
118
        url = 'bzr://localhost:%d/' % port
119
        self.permit_url(url)
120
        return process, url
2020.1.1 by Robert Collins
Add readonly support to the smart server, enabled by default via `bzr server`.
121
122
    def test_bzr_serve_inet_readonly(self):
123
        """bzr server should provide a read only filesystem by default."""
2018.2.3 by Andrew Bennetts
Starting factoring out the smart server client "medium" from the protocol.
124
        process, transport = self.start_server_inet()
2020.1.1 by Robert Collins
Add readonly support to the smart server, enabled by default via `bzr server`.
125
        self.assertRaises(errors.TransportNotPossible, transport.mkdir, 'adir')
2018.2.3 by Andrew Bennetts
Starting factoring out the smart server client "medium" from the protocol.
126
        self.assertInetServerShutsdownCleanly(process)
2020.1.1 by Robert Collins
Add readonly support to the smart server, enabled by default via `bzr server`.
127
128
    def test_bzr_serve_inet_readwrite(self):
129
        # Make a branch
130
        self.make_branch('.')
131
2018.2.3 by Andrew Bennetts
Starting factoring out the smart server client "medium" from the protocol.
132
        process, transport = self.start_server_inet(['--allow-writes'])
2020.1.1 by Robert Collins
Add readonly support to the smart server, enabled by default via `bzr server`.
133
134
        # We get a working branch
135
        branch = BzrDir.open_from_transport(transport).open_branch()
3287.6.4 by Robert Collins
Fix up deprecation warnings for get_revision_graph.
136
        self.make_read_requests(branch)
2018.2.3 by Andrew Bennetts
Starting factoring out the smart server client "medium" from the protocol.
137
        self.assertInetServerShutsdownCleanly(process)
2020.1.1 by Robert Collins
Add readonly support to the smart server, enabled by default via `bzr server`.
138
139
    def test_bzr_serve_port_readonly(self):
140
        """bzr server should provide a read only filesystem by default."""
141
        process, url = self.start_server_port()
142
        transport = get_transport(url)
143
        self.assertRaises(errors.TransportNotPossible, transport.mkdir, 'adir')
144
        self.assertServerFinishesCleanly(process)
145
146
    def test_bzr_serve_port_readwrite(self):
147
        # Make a branch
148
        self.make_branch('.')
149
150
        process, url = self.start_server_port(['--allow-writes'])
1910.19.7 by Andrew Bennetts
Allow specifying the host/interface to bzr serve, and use the new test
151
152
        # Connect to the server
2020.1.1 by Robert Collins
Add readonly support to the smart server, enabled by default via `bzr server`.
153
        branch = Branch.open(url)
3287.6.4 by Robert Collins
Fix up deprecation warnings for get_revision_graph.
154
        self.make_read_requests(branch)
2020.1.1 by Robert Collins
Add readonly support to the smart server, enabled by default via `bzr server`.
155
        self.assertServerFinishesCleanly(process)
1910.19.7 by Andrew Bennetts
Allow specifying the host/interface to bzr serve, and use the new test
156
4370.4.2 by Jelmer Vernooij
Add --protocol option to 'bzr serve'.
157
    def test_bzr_serve_supports_protocol(self):
158
        # Make a branch
159
        self.make_branch('.')
160
161
        process, url = self.start_server_port(['--allow-writes',
162
                                               '--protocol=bzr'])
163
164
        # Connect to the server
165
        branch = Branch.open(url)
166
        self.make_read_requests(branch)
167
        self.assertServerFinishesCleanly(process)
168
2018.1.1 by Andrew Bennetts
Make bzr+ssh:// actually work (at least with absolute paths).
169
    def test_bzr_connect_to_bzr_ssh(self):
2018.1.7 by Andrew Bennetts
Use bzrlib rather than a bzr subprocess in test_bzr_connect_to_bzr_ssh.
170
        """User acceptance that get_transport of a bzr+ssh:// behaves correctly.
171
172
        bzr+ssh:// should cause bzr to run a remote bzr smart server over SSH.
173
        """
2018.1.2 by Andrew Bennetts
Tidy imports, skip test if paramiko isn't installed.
174
        try:
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.
175
            # SFTPFullAbsoluteServer has a get_url method, and doesn't
176
            # override the interface (doesn't change self._vendor).
177
            from bzrlib.transport.sftp import SFTPFullAbsoluteServer
2018.1.2 by Andrew Bennetts
Tidy imports, skip test if paramiko isn't installed.
178
        except ParamikoNotPresent:
179
            raise TestSkipped('Paramiko not installed')
180
        from bzrlib.tests.stub_sftp import StubServer
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
181
2018.1.1 by Andrew Bennetts
Make bzr+ssh:// actually work (at least with absolute paths).
182
        # Make a branch
2018.1.2 by Andrew Bennetts
Tidy imports, skip test if paramiko isn't installed.
183
        self.make_branch('a_branch')
2018.1.1 by Andrew Bennetts
Make bzr+ssh:// actually work (at least with absolute paths).
184
185
        # Start an SSH server
2018.1.11 by Andrew Bennetts
Improvements to test_bzr_connect_to_bzr_ssh based on review comments
186
        self.command_executed = []
2018.1.1 by Andrew Bennetts
Make bzr+ssh:// actually work (at least with absolute paths).
187
        # XXX: This is horrible -- we define a really dumb SSH server that
188
        # executes commands, and manage the hooking up of stdin/out/err to the
189
        # SSH channel ourselves.  Surely this has already been implemented
190
        # elsewhere?
2018.1.2 by Andrew Bennetts
Tidy imports, skip test if paramiko isn't installed.
191
        class StubSSHServer(StubServer):
192
2018.1.1 by Andrew Bennetts
Make bzr+ssh:// actually work (at least with absolute paths).
193
            test = self
194
195
            def check_channel_exec_request(self, channel, command):
2018.1.11 by Andrew Bennetts
Improvements to test_bzr_connect_to_bzr_ssh based on review comments
196
                self.test.command_executed.append(command)
2018.1.1 by Andrew Bennetts
Make bzr+ssh:// actually work (at least with absolute paths).
197
                proc = subprocess.Popen(
198
                    command, shell=True, stdin=subprocess.PIPE,
199
                    stdout=subprocess.PIPE, stderr=subprocess.PIPE)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
200
2018.1.1 by Andrew Bennetts
Make bzr+ssh:// actually work (at least with absolute paths).
201
                # XXX: horribly inefficient, not to mention ugly.
2018.1.11 by Andrew Bennetts
Improvements to test_bzr_connect_to_bzr_ssh based on review comments
202
                # Start a thread for each of stdin/out/err, and relay bytes from
203
                # the subprocess to channel and vice versa.
204
                def ferry_bytes(read, write, close):
2018.1.1 by Andrew Bennetts
Make bzr+ssh:// actually work (at least with absolute paths).
205
                    while True:
2018.1.11 by Andrew Bennetts
Improvements to test_bzr_connect_to_bzr_ssh based on review comments
206
                        bytes = read(1)
2018.1.1 by Andrew Bennetts
Make bzr+ssh:// actually work (at least with absolute paths).
207
                        if bytes == '':
2018.1.11 by Andrew Bennetts
Improvements to test_bzr_connect_to_bzr_ssh based on review comments
208
                            close()
2018.1.1 by Andrew Bennetts
Make bzr+ssh:// actually work (at least with absolute paths).
209
                            break
2018.1.11 by Andrew Bennetts
Improvements to test_bzr_connect_to_bzr_ssh based on review comments
210
                        write(bytes)
2018.1.1 by Andrew Bennetts
Make bzr+ssh:// actually work (at least with absolute paths).
211
2018.1.11 by Andrew Bennetts
Improvements to test_bzr_connect_to_bzr_ssh based on review comments
212
                file_functions = [
213
                    (channel.recv, proc.stdin.write, proc.stdin.close),
214
                    (proc.stdout.read, channel.sendall, channel.close),
215
                    (proc.stderr.read, channel.sendall_stderr, channel.close)]
216
                for read, write, close in file_functions:
217
                    t = threading.Thread(
218
                        target=ferry_bytes, args=(read, write, close))
219
                    t.start()
2018.1.1 by Andrew Bennetts
Make bzr+ssh:// actually work (at least with absolute paths).
220
221
                return True
222
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.
223
        ssh_server = SFTPFullAbsoluteServer(StubSSHServer)
2018.1.7 by Andrew Bennetts
Use bzrlib rather than a bzr subprocess in test_bzr_connect_to_bzr_ssh.
224
        # XXX: We *don't* want to override the default SSH vendor, so we set
225
        # _vendor to what _get_ssh_vendor returns.
4659.1.2 by Robert Collins
Refactor creation and shutdown of test servers to use a common helper,
226
        self.start_server(ssh_server)
2018.1.1 by Andrew Bennetts
Make bzr+ssh:// actually work (at least with absolute paths).
227
        port = ssh_server._listener.port
228
229
        # Access the branch via a bzr+ssh URL.  The BZR_REMOTE_PATH environment
230
        # variable is used to tell bzr what command to run on the remote end.
2309.2.5 by Alexander Belchenko
test_bzr_connect_to_bzr_ssh: win32-compatibility
231
        path_to_branch = osutils.abspath('a_branch')
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
232
2018.1.7 by Andrew Bennetts
Use bzrlib rather than a bzr subprocess in test_bzr_connect_to_bzr_ssh.
233
        orig_bzr_remote_path = os.environ.get('BZR_REMOTE_PATH')
2309.2.5 by Alexander Belchenko
test_bzr_connect_to_bzr_ssh: win32-compatibility
234
        bzr_remote_path = self.get_bzr_path()
235
        if sys.platform == 'win32':
236
            bzr_remote_path = sys.executable + ' ' + self.get_bzr_path()
237
        os.environ['BZR_REMOTE_PATH'] = bzr_remote_path
2018.1.7 by Andrew Bennetts
Use bzrlib rather than a bzr subprocess in test_bzr_connect_to_bzr_ssh.
238
        try:
2309.2.5 by Alexander Belchenko
test_bzr_connect_to_bzr_ssh: win32-compatibility
239
            if sys.platform == 'win32':
240
                path_to_branch = os.path.splitdrive(path_to_branch)[1]
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.
241
            url_suffix = '@localhost:%d%s' % (port, path_to_branch)
242
            self.permit_url('bzr+ssh://fred' + url_suffix)
243
            branch = Branch.open('bzr+ssh://fred:secret' + url_suffix)
3287.6.4 by Robert Collins
Fix up deprecation warnings for get_revision_graph.
244
            self.make_read_requests(branch)
2018.1.10 by Andrew Bennetts
Merge --allow-writes from Robert
245
            # Check we can perform write operations
246
            branch.bzrdir.root_transport.mkdir('foo')
2018.1.7 by Andrew Bennetts
Use bzrlib rather than a bzr subprocess in test_bzr_connect_to_bzr_ssh.
247
        finally:
248
            # Restore the BZR_REMOTE_PATH environment variable back to its
249
            # original state.
250
            if orig_bzr_remote_path is None:
251
                del os.environ['BZR_REMOTE_PATH']
252
            else:
253
                os.environ['BZR_REMOTE_PATH'] = orig_bzr_remote_path
254
2018.1.1 by Andrew Bennetts
Make bzr+ssh:// actually work (at least with absolute paths).
255
        self.assertEqual(
2018.1.11 by Andrew Bennetts
Improvements to test_bzr_connect_to_bzr_ssh based on review comments
256
            ['%s serve --inet --directory=/ --allow-writes'
2309.2.5 by Alexander Belchenko
test_bzr_connect_to_bzr_ssh: win32-compatibility
257
             % bzr_remote_path],
2018.1.1 by Andrew Bennetts
Make bzr+ssh:// actually work (at least with absolute paths).
258
            self.command_executed)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
259
4544.1.2 by Andrew Bennetts
Add test that would catch the lack of ChrootServer in cmd_serve.
260
261
class TestCmdServeChrooting(TestCaseWithTransport):
262
263
    def test_serve_tcp(self):
264
        """'bzr serve' wraps the given --directory in a ChrootServer.
265
266
        So requests that search up through the parent directories (like
267
        find_repositoryV3) will give "not found" responses, rather than
268
        InvalidURLJoin or jail break errors.
269
        """
270
        t = self.get_transport()
271
        t.mkdir('server-root')
272
        self.run_bzr_serve_then_func(
4676.3.3 by Vincent Ladeuil
Force IPV4 to fix failure on IPV6-enabled hosts.
273
            ['--port', '127.0.0.1:0',
274
             '--directory', t.local_abspath('server-root'),
4544.1.2 by Andrew Bennetts
Add test that would catch the lack of ChrootServer in cmd_serve.
275
             '--allow-writes'],
276
            self.when_server_started)
277
        # The when_server_started method issued a find_repositoryV3 that should
278
        # fail with 'norepository' because there are no repositories inside the
279
        # --directory.
4676.3.3 by Vincent Ladeuil
Force IPV4 to fix failure on IPV6-enabled hosts.
280
        self.assertEqual(('norepository',), self.client_resp)
4676.3.1 by Vincent Ladeuil
Marking TestCmdServeChrooting.test_serve_tcp as expected failure
281
4544.1.2 by Andrew Bennetts
Add test that would catch the lack of ChrootServer in cmd_serve.
282
    def run_bzr_serve_then_func(self, serve_args, func, *func_args,
283
            **func_kwargs):
284
        """Run 'bzr serve', and run the given func in a thread once the server
285
        has started.
286
        
287
        When 'func' terminates, the server will be terminated too.
288
        """
289
        # install hook
4544.1.3 by Andrew Bennetts
Pass backing_urls to the new server_started_ex hook.
290
        def on_server_start(backing_urls, tcp_server):
291
            t = threading.Thread(
292
                target=on_server_start_thread, args=(tcp_server,))
4544.1.2 by Andrew Bennetts
Add test that would catch the lack of ChrootServer in cmd_serve.
293
            t.start()
294
        def on_server_start_thread(tcp_server):
295
            try:
296
                # Run func
297
                self.tcp_server = tcp_server
298
                try:
299
                    func(*func_args, **func_kwargs)
300
                except Exception, e:
301
                    # Log errors to make some test failures a little less
302
                    # mysterious.
303
                    mutter('func broke: %r', e)
304
            finally:
305
                # Then stop the server
306
                mutter('interrupting...')
307
                thread.interrupt_main()
308
        SmartTCPServer.hooks.install_named_hook(
309
            'server_started_ex', on_server_start,
310
            'run_bzr_serve_then_func hook')
311
        # start a TCP server
312
        try:
313
            self.run_bzr(['serve'] + list(serve_args))
314
        except KeyboardInterrupt:
315
            pass
316
317
    def when_server_started(self):
318
        # Connect to the TCP server and issue some requests and see what comes
319
        # back.
320
        client_medium = medium.SmartTCPClientMedium(
321
            '127.0.0.1', self.tcp_server.port,
322
            'bzr://localhost:%d/' % (self.tcp_server.port,))
323
        smart_client = client._SmartClient(client_medium)
324
        resp = smart_client.call('mkdir', 'foo', '')
325
        resp = smart_client.call('BzrDirFormat.initialize', 'foo/')
326
        try:
327
            resp = smart_client.call('BzrDir.find_repositoryV3', 'foo/')
328
        except errors.ErrorFromSmartServer, e:
329
            resp = e.error_tuple
330
        self.client_resp = resp
331
        client_medium.disconnect()
332
333
4634.43.7 by Andrew Bennetts
Add some unit tests for parts of userdir expansion.
334
class TestUserdirExpansion(TestCaseWithMemoryTransport):
335
336
    def fake_expanduser(self, path):
337
        """A simple, environment-independent, function for the duration of this
338
        test.
339
340
        Paths starting with a path segment of '~user' will expand to start with
341
        '/home/user/'.  Every other path will be unchanged.
342
        """
343
        if path.split('/', 1)[0] == '~user':
344
            return '/home/user' + path[len('~user'):]
345
        return path
346
347
    def make_test_server(self, base_path='/'):
4634.43.15 by Andrew Bennetts
Rename BzrServerMaker -> BzrServerFactory.
348
        """Make and setUp a BzrServerFactory, backed by a memory transport, and
4634.43.7 by Andrew Bennetts
Add some unit tests for parts of userdir expansion.
349
        creat '/home/user' in that transport.
350
        """
4634.43.15 by Andrew Bennetts
Rename BzrServerMaker -> BzrServerFactory.
351
        bzr_server = BzrServerFactory(
4634.43.7 by Andrew Bennetts
Add some unit tests for parts of userdir expansion.
352
            self.fake_expanduser, lambda t: base_path)
353
        mem_transport = self.get_transport()
354
        mem_transport.mkdir_multi(['home', 'home/user'])
4634.43.19 by Andrew Bennetts
Rename BzrServerFactory's setUp/tearDown to set_up/tear_down; this isn't a TestCase (or transport Server), so we should not use camelCase names.
355
        bzr_server.set_up(mem_transport, None, None, inet=True)
356
        self.addCleanup(bzr_server.tear_down)
4634.43.7 by Andrew Bennetts
Add some unit tests for parts of userdir expansion.
357
        return bzr_server
358
359
    def test_bzr_serve_expands_userdir(self):
360
        bzr_server = self.make_test_server()
361
        self.assertTrue(bzr_server.smart_server.backing_transport.has('~user'))
362
363
    def test_bzr_serve_does_not_expand_userdir_outside_base(self):
364
        bzr_server = self.make_test_server('/foo')
365
        self.assertFalse(bzr_server.smart_server.backing_transport.has('~user'))
4544.1.2 by Andrew Bennetts
Add test that would catch the lack of ChrootServer in cmd_serve.
366
4634.43.8 by Andrew Bennetts
Test for recovering the --directory value from the transport cmd_serve passes to bzr_serve.
367
    def test_get_base_path(self):
368
        """cmd_serve will turn the --directory option into a LocalTransport
4634.43.15 by Andrew Bennetts
Rename BzrServerMaker -> BzrServerFactory.
369
        (optionally decorated with 'readonly+').  BzrServerFactory can
370
        determine the original --directory from that transport.
4634.43.8 by Andrew Bennetts
Test for recovering the --directory value from the transport cmd_serve passes to bzr_serve.
371
        """
372
        # Define a fake 'protocol' to capture the transport that cmd_serve
373
        # passes to serve_bzr.
374
        def capture_transport(transport, host, port, inet):
375
            self.bzr_serve_transport = transport
376
        cmd = builtins.cmd_serve()
377
        # Read-only
378
        cmd.run(directory='/a/b/c', protocol=capture_transport)
4634.43.15 by Andrew Bennetts
Rename BzrServerMaker -> BzrServerFactory.
379
        server_maker = BzrServerFactory()
4634.43.8 by Andrew Bennetts
Test for recovering the --directory value from the transport cmd_serve passes to bzr_serve.
380
        self.assertEqual(
381
            'readonly+file:///a/b/c/', self.bzr_serve_transport.base)
382
        self.assertEqual(
383
            u'/a/b/c/', server_maker.get_base_path(self.bzr_serve_transport))
384
        # Read-write
385
        cmd.run(directory='/a/b/c', protocol=capture_transport,
386
            allow_writes=True)
4634.43.15 by Andrew Bennetts
Rename BzrServerMaker -> BzrServerFactory.
387
        server_maker = BzrServerFactory()
4634.43.8 by Andrew Bennetts
Test for recovering the --directory value from the transport cmd_serve passes to bzr_serve.
388
        self.assertEqual('file:///a/b/c/', self.bzr_serve_transport.base)
389
        self.assertEqual(
390
            u'/a/b/c/', server_maker.get_base_path(self.bzr_serve_transport))
391