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