~bzr-pqm/bzr/bzr.dev

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