~bzr-pqm/bzr/bzr.dev

4763.2.4 by John Arbash Meinel
merge bzr.2.1 in preparation for NEWS entry.
1
# Copyright (C) 2006-2010 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,
4911.1.1 by John Arbash Meinel
Threads don't have 'get_ident()' attributes. I think spiv meant 'getName()'.
30
    debug,
2309.2.5 by Alexander Belchenko
test_bzr_connect_to_bzr_ssh: win32-compatibility
31
    errors,
32
    osutils,
2598.5.1 by Aaron Bentley
Start eliminating the use of None to indicate null revision
33
    revision as _mod_revision,
5273.1.7 by Vincent Ladeuil
No more use of the get_transport imported *symbol*, all uses are through
34
    transport,
4797.3.21 by John Arbash Meinel
Use urlutils.local_path_to_url to handle both windows and linux.
35
    urlutils,
2309.2.5 by Alexander Belchenko
test_bzr_connect_to_bzr_ssh: win32-compatibility
36
    )
1910.19.7 by Andrew Bennetts
Allow specifying the host/interface to bzr serve, and use the new test
37
from bzrlib.branch import Branch
1910.19.11 by Andrew Bennetts
General code cleanup based on review comments and other observations.
38
from bzrlib.bzrdir import BzrDir
4544.1.2 by Andrew Bennetts
Add test that would catch the lack of ChrootServer in cmd_serve.
39
from bzrlib.smart import client, medium
4634.43.15 by Andrew Bennetts
Rename BzrServerMaker -> BzrServerFactory.
40
from bzrlib.smart.server import BzrServerFactory, SmartTCPServer
4634.43.7 by Andrew Bennetts
Add some unit tests for parts of userdir expansion.
41
from bzrlib.tests import (
4700.1.3 by Robert Collins
Merge trunk.
42
    TestCaseWithMemoryTransport,
4634.43.7 by Andrew Bennetts
Add some unit tests for parts of userdir expansion.
43
    TestCaseWithTransport,
44
    TestSkipped,
45
    )
4544.1.2 by Andrew Bennetts
Add test that would catch the lack of ChrootServer in cmd_serve.
46
from bzrlib.trace import mutter
5273.1.7 by Vincent Ladeuil
No more use of the get_transport imported *symbol*, all uses are through
47
from bzrlib.transport import remote
1910.19.11 by Andrew Bennetts
General code cleanup based on review comments and other observations.
48
4911.1.1 by John Arbash Meinel
Threads don't have 'get_ident()' attributes. I think spiv meant 'getName()'.
49
4815.3.7 by Gordon Tyler
Made a few changes at the suggestion of vila.
50
class TestBzrServeBase(TestCaseWithTransport):
4815.3.3 by Gordon Tyler
Changed test_bzr_serve_quiet to use in-process execution of the command.
51
52
    def run_bzr_serve_then_func(self, serve_args, retcode=0, func=None,
53
                                *func_args, **func_kwargs):
54
        """Run 'bzr serve', and run the given func in a thread once the server
55
        has started.
56
        
57
        When 'func' terminates, the server will be terminated too.
58
        
59
        Returns stdout and stderr.
60
        """
61
        # install hook
62
        def on_server_start(backing_urls, tcp_server):
63
            t = threading.Thread(
64
                target=on_server_start_thread, args=(tcp_server,))
65
            t.start()
66
        def on_server_start_thread(tcp_server):
67
            try:
68
                # Run func if set
69
                self.tcp_server = tcp_server
70
                if not func is None:
71
                    try:
72
                        func(*func_args, **func_kwargs)
73
                    except Exception, e:
74
                        # Log errors to make some test failures a little less
75
                        # mysterious.
76
                        mutter('func broke: %r', e)
77
            finally:
78
                # Then stop the server
79
                mutter('interrupting...')
80
                thread.interrupt_main()
81
        SmartTCPServer.hooks.install_named_hook(
82
            'server_started_ex', on_server_start,
83
            'run_bzr_serve_then_func hook')
84
        # start a TCP server
85
        try:
4815.3.7 by Gordon Tyler
Made a few changes at the suggestion of vila.
86
            out, err = self.run_bzr(['serve'] + list(serve_args))
87
        except KeyboardInterrupt, e:
88
            out, err = e.args
89
        return out, err
90
91
92
class TestBzrServe(TestBzrServeBase):
1910.19.11 by Andrew Bennetts
General code cleanup based on review comments and other observations.
93
4695.3.1 by Vincent Ladeuil
Fix test failures with no C extensions loaded.
94
    def setUp(self):
4815.3.6 by Gordon Tyler
Fixed super call in TestBzrServe.
95
        super(TestBzrServe, self).setUp()
4695.3.2 by Vincent Ladeuil
Simplified and claried as per Robert's review.
96
        self.disable_missing_extensions_warning()
4695.3.1 by Vincent Ladeuil
Fix test failures with no C extensions loaded.
97
2018.2.3 by Andrew Bennetts
Starting factoring out the smart server client "medium" from the protocol.
98
    def assertInetServerShutsdownCleanly(self, process):
2020.1.1 by Robert Collins
Add readonly support to the smart server, enabled by default via `bzr server`.
99
        """Shutdown the server process looking for errors."""
2018.2.3 by Andrew Bennetts
Starting factoring out the smart server client "medium" from the protocol.
100
        # Shutdown the server: the server should shut down when it cannot read
101
        # from stdin anymore.
102
        process.stdin.close()
1910.19.11 by Andrew Bennetts
General code cleanup based on review comments and other observations.
103
        # Hide stdin from the subprocess module, so it won't fail to close it.
104
        process.stdin = None
2581.1.2 by Martin Pool
Remove unnecessary retcode=0 to run_bzr calls
105
        result = self.finish_bzr_subprocess(process)
1910.19.11 by Andrew Bennetts
General code cleanup based on review comments and other observations.
106
        self.assertEqual('', result[0])
107
        self.assertEqual('', result[1])
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
108
2020.1.1 by Robert Collins
Add readonly support to the smart server, enabled by default via `bzr server`.
109
    def assertServerFinishesCleanly(self, process):
110
        """Shutdown the bzr serve instance process looking for errors."""
111
        # Shutdown the server
112
        result = self.finish_bzr_subprocess(process, retcode=3,
113
                                            send_signal=signal.SIGINT)
114
        self.assertEqual('', result[0])
115
        self.assertEqual('bzr: interrupted\n', result[1])
116
3287.6.4 by Robert Collins
Fix up deprecation warnings for get_revision_graph.
117
    def make_read_requests(self, branch):
118
        """Do some read only requests."""
119
        branch.lock_read()
120
        try:
121
            branch.repository.all_revision_ids()
122
            self.assertEqual(_mod_revision.NULL_REVISION,
123
                             _mod_revision.ensure_null(branch.last_revision()))
124
        finally:
125
            branch.unlock()
126
2020.1.1 by Robert Collins
Add readonly support to the smart server, enabled by default via `bzr server`.
127
    def start_server_inet(self, extra_options=()):
128
        """Start a bzr server subprocess using the --inet option.
129
130
        :param extra_options: extra options to give the server.
131
        :return: a tuple with the bzr process handle for passing to
132
            finish_bzr_subprocess, a client for the server, and a transport.
133
        """
134
        # Serve from the current directory
4911.1.1 by John Arbash Meinel
Threads don't have 'get_ident()' attributes. I think spiv meant 'getName()'.
135
        args = ['serve', '--inet']
136
        args.extend(extra_options)
137
        process = self.start_bzr_subprocess(args)
2020.1.1 by Robert Collins
Add readonly support to the smart server, enabled by default via `bzr server`.
138
139
        # Connect to the server
140
        # We use this url because while this is no valid URL to connect to this
141
        # server instance, the transport needs a URL.
3431.3.7 by Andrew Bennetts
Fix incidental breakage in blackbox/test_serve.py
142
        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.
143
        self.permit_url(url)
2018.5.15 by Andrew Bennetts
Tidy some imports, and bugs introduced when adding server.py
144
        client_medium = medium.SmartSimplePipesClientMedium(
3431.3.7 by Andrew Bennetts
Fix incidental breakage in blackbox/test_serve.py
145
            process.stdout, process.stdin, url)
146
        transport = remote.RemoteTransport(url, medium=client_medium)
2018.2.3 by Andrew Bennetts
Starting factoring out the smart server client "medium" from the protocol.
147
        return process, transport
2020.1.1 by Robert Collins
Add readonly support to the smart server, enabled by default via `bzr server`.
148
149
    def start_server_port(self, extra_options=()):
150
        """Start a bzr server subprocess.
151
152
        :param extra_options: extra options to give the server.
153
        :return: a tuple with the bzr process handle for passing to
154
            finish_bzr_subprocess, and the base url for the server.
155
        """
156
        # Serve from the current directory
157
        args = ['serve', '--port', 'localhost:0']
158
        args.extend(extra_options)
159
        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.
160
        port_line = process.stderr.readline()
1910.19.7 by Andrew Bennetts
Allow specifying the host/interface to bzr serve, and use the new test
161
        prefix = 'listening on port: '
162
        self.assertStartsWith(port_line, prefix)
163
        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.
164
        url = 'bzr://localhost:%d/' % port
165
        self.permit_url(url)
166
        return process, url
4815.3.1 by Gordon Tyler
Added test_bzr_serve_quiet which tests that the output of 'bzr serve --quiet' is really quiet.
167
    
168
    def test_bzr_serve_quiet(self):
169
        self.make_branch('.')
4815.3.3 by Gordon Tyler
Changed test_bzr_serve_quiet to use in-process execution of the command.
170
        args = ['--port', 'localhost:0', '--quiet']
171
        out, err = self.run_bzr_serve_then_func(args, retcode=3)
4815.3.2 by Gordon Tyler
test_bzr_serve_quiet should be skipped if signals are not available.
172
        self.assertEqual('', out)
173
        self.assertEqual('', err)
2020.1.1 by Robert Collins
Add readonly support to the smart server, enabled by default via `bzr server`.
174
175
    def test_bzr_serve_inet_readonly(self):
176
        """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.
177
        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`.
178
        self.assertRaises(errors.TransportNotPossible, transport.mkdir, 'adir')
2018.2.3 by Andrew Bennetts
Starting factoring out the smart server client "medium" from the protocol.
179
        self.assertInetServerShutsdownCleanly(process)
2020.1.1 by Robert Collins
Add readonly support to the smart server, enabled by default via `bzr server`.
180
181
    def test_bzr_serve_inet_readwrite(self):
182
        # Make a branch
183
        self.make_branch('.')
184
2018.2.3 by Andrew Bennetts
Starting factoring out the smart server client "medium" from the protocol.
185
        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`.
186
4911.1.1 by John Arbash Meinel
Threads don't have 'get_ident()' attributes. I think spiv meant 'getName()'.
187
        # We get a working branch, and can create a directory
2020.1.1 by Robert Collins
Add readonly support to the smart server, enabled by default via `bzr server`.
188
        branch = BzrDir.open_from_transport(transport).open_branch()
3287.6.4 by Robert Collins
Fix up deprecation warnings for get_revision_graph.
189
        self.make_read_requests(branch)
4911.1.1 by John Arbash Meinel
Threads don't have 'get_ident()' attributes. I think spiv meant 'getName()'.
190
        transport.mkdir('adir')
2018.2.3 by Andrew Bennetts
Starting factoring out the smart server client "medium" from the protocol.
191
        self.assertInetServerShutsdownCleanly(process)
2020.1.1 by Robert Collins
Add readonly support to the smart server, enabled by default via `bzr server`.
192
193
    def test_bzr_serve_port_readonly(self):
194
        """bzr server should provide a read only filesystem by default."""
195
        process, url = self.start_server_port()
5273.1.7 by Vincent Ladeuil
No more use of the get_transport imported *symbol*, all uses are through
196
        t = transport.get_transport(url)
197
        self.assertRaises(errors.TransportNotPossible, t.mkdir, 'adir')
2020.1.1 by Robert Collins
Add readonly support to the smart server, enabled by default via `bzr server`.
198
        self.assertServerFinishesCleanly(process)
199
200
    def test_bzr_serve_port_readwrite(self):
201
        # Make a branch
202
        self.make_branch('.')
203
204
        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
205
206
        # Connect to the server
2020.1.1 by Robert Collins
Add readonly support to the smart server, enabled by default via `bzr server`.
207
        branch = Branch.open(url)
3287.6.4 by Robert Collins
Fix up deprecation warnings for get_revision_graph.
208
        self.make_read_requests(branch)
2020.1.1 by Robert Collins
Add readonly support to the smart server, enabled by default via `bzr server`.
209
        self.assertServerFinishesCleanly(process)
1910.19.7 by Andrew Bennetts
Allow specifying the host/interface to bzr serve, and use the new test
210
4370.4.2 by Jelmer Vernooij
Add --protocol option to 'bzr serve'.
211
    def test_bzr_serve_supports_protocol(self):
212
        # Make a branch
213
        self.make_branch('.')
214
215
        process, url = self.start_server_port(['--allow-writes',
216
                                               '--protocol=bzr'])
217
218
        # Connect to the server
219
        branch = Branch.open(url)
220
        self.make_read_requests(branch)
221
        self.assertServerFinishesCleanly(process)
222
4911.1.1 by John Arbash Meinel
Threads don't have 'get_ident()' attributes. I think spiv meant 'getName()'.
223
    def test_bzr_serve_dhpss(self):
224
        # This is a smoke test that the server doesn't crash when run with
225
        # -Dhpss, and does drop some hpss logging to the file.
226
        self.make_branch('.')
227
        log_fname = os.getcwd() + '/server.log'
228
        self._captureVar('BZR_LOG', log_fname)
229
        process, transport = self.start_server_inet(['-Dhpss'])
230
        branch = BzrDir.open_from_transport(transport).open_branch()
231
        self.make_read_requests(branch)
232
        self.assertInetServerShutsdownCleanly(process)
233
        f = open(log_fname, 'rb')
234
        content = f.read()
235
        f.close()
4913.1.1 by John Arbash Meinel
Switch to using thread.get_ident() which is available on all python versions.
236
        self.assertContainsRe(content, r'hpss request: \[[0-9-]+\]')
4911.1.1 by John Arbash Meinel
Threads don't have 'get_ident()' attributes. I think spiv meant 'getName()'.
237
4544.1.2 by Andrew Bennetts
Add test that would catch the lack of ChrootServer in cmd_serve.
238
4815.3.7 by Gordon Tyler
Made a few changes at the suggestion of vila.
239
class TestCmdServeChrooting(TestBzrServeBase):
4544.1.2 by Andrew Bennetts
Add test that would catch the lack of ChrootServer in cmd_serve.
240
241
    def test_serve_tcp(self):
242
        """'bzr serve' wraps the given --directory in a ChrootServer.
243
244
        So requests that search up through the parent directories (like
245
        find_repositoryV3) will give "not found" responses, rather than
246
        InvalidURLJoin or jail break errors.
247
        """
248
        t = self.get_transport()
249
        t.mkdir('server-root')
250
        self.run_bzr_serve_then_func(
4676.3.3 by Vincent Ladeuil
Force IPV4 to fix failure on IPV6-enabled hosts.
251
            ['--port', '127.0.0.1:0',
252
             '--directory', t.local_abspath('server-root'),
4544.1.2 by Andrew Bennetts
Add test that would catch the lack of ChrootServer in cmd_serve.
253
             '--allow-writes'],
4815.3.3 by Gordon Tyler
Changed test_bzr_serve_quiet to use in-process execution of the command.
254
            func=self.when_server_started)
4544.1.2 by Andrew Bennetts
Add test that would catch the lack of ChrootServer in cmd_serve.
255
        # The when_server_started method issued a find_repositoryV3 that should
256
        # fail with 'norepository' because there are no repositories inside the
257
        # --directory.
4676.3.3 by Vincent Ladeuil
Force IPV4 to fix failure on IPV6-enabled hosts.
258
        self.assertEqual(('norepository',), self.client_resp)
4676.3.1 by Vincent Ladeuil
Marking TestCmdServeChrooting.test_serve_tcp as expected failure
259
4544.1.2 by Andrew Bennetts
Add test that would catch the lack of ChrootServer in cmd_serve.
260
    def when_server_started(self):
261
        # Connect to the TCP server and issue some requests and see what comes
262
        # back.
263
        client_medium = medium.SmartTCPClientMedium(
264
            '127.0.0.1', self.tcp_server.port,
265
            'bzr://localhost:%d/' % (self.tcp_server.port,))
266
        smart_client = client._SmartClient(client_medium)
267
        resp = smart_client.call('mkdir', 'foo', '')
268
        resp = smart_client.call('BzrDirFormat.initialize', 'foo/')
269
        try:
270
            resp = smart_client.call('BzrDir.find_repositoryV3', 'foo/')
271
        except errors.ErrorFromSmartServer, e:
272
            resp = e.error_tuple
273
        self.client_resp = resp
274
        client_medium.disconnect()
275
276
4634.43.7 by Andrew Bennetts
Add some unit tests for parts of userdir expansion.
277
class TestUserdirExpansion(TestCaseWithMemoryTransport):
278
279
    def fake_expanduser(self, path):
280
        """A simple, environment-independent, function for the duration of this
281
        test.
282
283
        Paths starting with a path segment of '~user' will expand to start with
284
        '/home/user/'.  Every other path will be unchanged.
285
        """
286
        if path.split('/', 1)[0] == '~user':
287
            return '/home/user' + path[len('~user'):]
288
        return path
289
290
    def make_test_server(self, base_path='/'):
4934.3.3 by Martin Pool
Rename Server.setUp to Server.start_server
291
        """Make and start a BzrServerFactory, backed by a memory transport, and
4634.43.7 by Andrew Bennetts
Add some unit tests for parts of userdir expansion.
292
        creat '/home/user' in that transport.
293
        """
4634.43.15 by Andrew Bennetts
Rename BzrServerMaker -> BzrServerFactory.
294
        bzr_server = BzrServerFactory(
4634.43.7 by Andrew Bennetts
Add some unit tests for parts of userdir expansion.
295
            self.fake_expanduser, lambda t: base_path)
296
        mem_transport = self.get_transport()
297
        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.
298
        bzr_server.set_up(mem_transport, None, None, inet=True)
299
        self.addCleanup(bzr_server.tear_down)
4634.43.7 by Andrew Bennetts
Add some unit tests for parts of userdir expansion.
300
        return bzr_server
301
302
    def test_bzr_serve_expands_userdir(self):
303
        bzr_server = self.make_test_server()
304
        self.assertTrue(bzr_server.smart_server.backing_transport.has('~user'))
305
306
    def test_bzr_serve_does_not_expand_userdir_outside_base(self):
307
        bzr_server = self.make_test_server('/foo')
308
        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.
309
4634.43.8 by Andrew Bennetts
Test for recovering the --directory value from the transport cmd_serve passes to bzr_serve.
310
    def test_get_base_path(self):
311
        """cmd_serve will turn the --directory option into a LocalTransport
4634.43.15 by Andrew Bennetts
Rename BzrServerMaker -> BzrServerFactory.
312
        (optionally decorated with 'readonly+').  BzrServerFactory can
313
        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.
314
        """
4797.3.4 by John Arbash Meinel
Per review recommendation, use 'osutils.abspath' instead of hardcoded string.
315
        # URLs always include the trailing slash, and get_base_path returns it
316
        base_dir = osutils.abspath('/a/b/c') + '/'
4797.3.21 by John Arbash Meinel
Use urlutils.local_path_to_url to handle both windows and linux.
317
        base_url = urlutils.local_path_to_url(base_dir) + '/'
4634.43.8 by Andrew Bennetts
Test for recovering the --directory value from the transport cmd_serve passes to bzr_serve.
318
        # Define a fake 'protocol' to capture the transport that cmd_serve
319
        # passes to serve_bzr.
320
        def capture_transport(transport, host, port, inet):
321
            self.bzr_serve_transport = transport
322
        cmd = builtins.cmd_serve()
323
        # Read-only
4789.7.1 by John Arbash Meinel
Fix a 'bzr serve' test that didn't expect windows translating '/a' to 'C:/a'.
324
        cmd.run(directory=base_dir, protocol=capture_transport)
4634.43.15 by Andrew Bennetts
Rename BzrServerMaker -> BzrServerFactory.
325
        server_maker = BzrServerFactory()
4634.43.8 by Andrew Bennetts
Test for recovering the --directory value from the transport cmd_serve passes to bzr_serve.
326
        self.assertEqual(
4797.3.21 by John Arbash Meinel
Use urlutils.local_path_to_url to handle both windows and linux.
327
            'readonly+%s' % base_url, self.bzr_serve_transport.base)
4634.43.8 by Andrew Bennetts
Test for recovering the --directory value from the transport cmd_serve passes to bzr_serve.
328
        self.assertEqual(
4789.7.1 by John Arbash Meinel
Fix a 'bzr serve' test that didn't expect windows translating '/a' to 'C:/a'.
329
            base_dir, server_maker.get_base_path(self.bzr_serve_transport))
4634.43.8 by Andrew Bennetts
Test for recovering the --directory value from the transport cmd_serve passes to bzr_serve.
330
        # Read-write
4789.7.1 by John Arbash Meinel
Fix a 'bzr serve' test that didn't expect windows translating '/a' to 'C:/a'.
331
        cmd.run(directory=base_dir, protocol=capture_transport,
4634.43.8 by Andrew Bennetts
Test for recovering the --directory value from the transport cmd_serve passes to bzr_serve.
332
            allow_writes=True)
4634.43.15 by Andrew Bennetts
Rename BzrServerMaker -> BzrServerFactory.
333
        server_maker = BzrServerFactory()
4797.3.21 by John Arbash Meinel
Use urlutils.local_path_to_url to handle both windows and linux.
334
        self.assertEqual(base_url, self.bzr_serve_transport.base)
4789.7.1 by John Arbash Meinel
Fix a 'bzr serve' test that didn't expect windows translating '/a' to 'C:/a'.
335
        self.assertEqual(base_dir,
336
            server_maker.get_base_path(self.bzr_serve_transport))
4634.43.8 by Andrew Bennetts
Test for recovering the --directory value from the transport cmd_serve passes to bzr_serve.
337