~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

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

  • Committer: Joe Julian
  • Date: 2010-01-10 02:25:31 UTC
  • mto: (4634.119.7 2.0)
  • mto: This revision was merged to the branch mainline in revision 4959.
  • Revision ID: joe@julianfamily.org-20100110022531-wqk61rsagz8xsiga
Added MANIFEST.in to allow bdist_rpm to have all the required include files and tools. bdist_rpm will still fail to build correctly on some distributions due to a disttools bug http://bugs.python.org/issue644744

Show diffs side-by-side

added added

removed removed

Lines of Context:
12
12
#
13
13
# You should have received a copy of the GNU General Public License
14
14
# along with this program; if not, write to the Free Software
15
 
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
16
 
17
17
 
18
18
"""Tests of the bzr serve command."""
20
20
import os
21
21
import signal
22
22
import subprocess
 
23
import sys
 
24
import thread
23
25
import threading
24
26
 
25
 
from bzrlib import errors
 
27
from bzrlib import (
 
28
    errors,
 
29
    osutils,
 
30
    revision as _mod_revision,
 
31
    transport,
 
32
    )
26
33
from bzrlib.branch import Branch
27
34
from bzrlib.bzrdir import BzrDir
28
35
from bzrlib.errors import ParamikoNotPresent
 
36
from bzrlib.smart import client, medium
 
37
from bzrlib.smart.server import SmartTCPServer
29
38
from bzrlib.tests import TestCaseWithTransport, TestSkipped
30
 
from bzrlib.transport import get_transport, smart
 
39
from bzrlib.trace import mutter
 
40
from bzrlib.transport import get_transport, remote
31
41
 
32
42
 
33
43
class TestBzrServe(TestCaseWithTransport):
39
49
        process.stdin.close()
40
50
        # Hide stdin from the subprocess module, so it won't fail to close it.
41
51
        process.stdin = None
42
 
        result = self.finish_bzr_subprocess(process, retcode=0)
 
52
        result = self.finish_bzr_subprocess(process)
43
53
        self.assertEqual('', result[0])
44
54
        self.assertEqual('', result[1])
45
 
    
 
55
 
46
56
    def assertServerFinishesCleanly(self, process):
47
57
        """Shutdown the bzr serve instance process looking for errors."""
48
58
        # Shutdown the server
51
61
        self.assertEqual('', result[0])
52
62
        self.assertEqual('bzr: interrupted\n', result[1])
53
63
 
 
64
    def make_read_requests(self, branch):
 
65
        """Do some read only requests."""
 
66
        branch.lock_read()
 
67
        try:
 
68
            branch.repository.all_revision_ids()
 
69
            self.assertEqual(_mod_revision.NULL_REVISION,
 
70
                             _mod_revision.ensure_null(branch.last_revision()))
 
71
        finally:
 
72
            branch.unlock()
 
73
 
54
74
    def start_server_inet(self, extra_options=()):
55
75
        """Start a bzr server subprocess using the --inet option.
56
76
 
64
84
        # Connect to the server
65
85
        # We use this url because while this is no valid URL to connect to this
66
86
        # server instance, the transport needs a URL.
67
 
        medium = smart.SmartSimplePipesClientMedium(
68
 
            process.stdout, process.stdin)
69
 
        transport = smart.SmartTransport('bzr://localhost/', medium=medium)
 
87
        url = 'bzr://localhost/'
 
88
        client_medium = medium.SmartSimplePipesClientMedium(
 
89
            process.stdout, process.stdin, url)
 
90
        transport = remote.RemoteTransport(url, medium=client_medium)
70
91
        return process, transport
71
92
 
72
93
    def start_server_port(self, extra_options=()):
80
101
        args = ['serve', '--port', 'localhost:0']
81
102
        args.extend(extra_options)
82
103
        process = self.start_bzr_subprocess(args, skip_if_plan_to_signal=True)
83
 
        port_line = process.stdout.readline()
 
104
        port_line = process.stderr.readline()
84
105
        prefix = 'listening on port: '
85
106
        self.assertStartsWith(port_line, prefix)
86
107
        port = int(port_line[len(prefix):])
100
121
 
101
122
        # We get a working branch
102
123
        branch = BzrDir.open_from_transport(transport).open_branch()
103
 
        branch.repository.get_revision_graph()
104
 
        self.assertEqual(None, branch.last_revision())
 
124
        self.make_read_requests(branch)
105
125
        self.assertInetServerShutsdownCleanly(process)
106
126
 
107
127
    def test_bzr_serve_port_readonly(self):
119
139
 
120
140
        # Connect to the server
121
141
        branch = Branch.open(url)
122
 
 
123
 
        # We get a working branch
124
 
        branch.repository.get_revision_graph()
125
 
        self.assertEqual(None, branch.last_revision())
126
 
 
127
 
        self.assertServerFinishesCleanly(process)
128
 
 
129
 
    def test_bzr_serve_no_args(self):
130
 
        """'bzr serve' with no arguments or options should not traceback."""
131
 
        out, err = self.run_bzr_error(
132
 
            ['bzr serve requires one of --inet or --port'], 'serve')
 
142
        self.make_read_requests(branch)
 
143
        self.assertServerFinishesCleanly(process)
 
144
 
 
145
    def test_bzr_serve_supports_protocol(self):
 
146
        # Make a branch
 
147
        self.make_branch('.')
 
148
 
 
149
        process, url = self.start_server_port(['--allow-writes',
 
150
                                               '--protocol=bzr'])
 
151
 
 
152
        # Connect to the server
 
153
        branch = Branch.open(url)
 
154
        self.make_read_requests(branch)
 
155
        self.assertServerFinishesCleanly(process)
133
156
 
134
157
    def test_bzr_connect_to_bzr_ssh(self):
135
158
        """User acceptance that get_transport of a bzr+ssh:// behaves correctly.
141
164
        except ParamikoNotPresent:
142
165
            raise TestSkipped('Paramiko not installed')
143
166
        from bzrlib.tests.stub_sftp import StubServer
144
 
        
 
167
 
145
168
        # Make a branch
146
169
        self.make_branch('a_branch')
147
170
 
160
183
                proc = subprocess.Popen(
161
184
                    command, shell=True, stdin=subprocess.PIPE,
162
185
                    stdout=subprocess.PIPE, stderr=subprocess.PIPE)
163
 
                
 
186
 
164
187
                # XXX: horribly inefficient, not to mention ugly.
165
188
                # Start a thread for each of stdin/out/err, and relay bytes from
166
189
                # the subprocess to channel and vice versa.
192
215
 
193
216
        # Access the branch via a bzr+ssh URL.  The BZR_REMOTE_PATH environment
194
217
        # variable is used to tell bzr what command to run on the remote end.
195
 
        path_to_branch = os.path.abspath('a_branch')
196
 
        
 
218
        path_to_branch = osutils.abspath('a_branch')
 
219
 
197
220
        orig_bzr_remote_path = os.environ.get('BZR_REMOTE_PATH')
198
 
        os.environ['BZR_REMOTE_PATH'] = self.get_bzr_path()
 
221
        bzr_remote_path = self.get_bzr_path()
 
222
        if sys.platform == 'win32':
 
223
            bzr_remote_path = sys.executable + ' ' + self.get_bzr_path()
 
224
        os.environ['BZR_REMOTE_PATH'] = bzr_remote_path
199
225
        try:
 
226
            if sys.platform == 'win32':
 
227
                path_to_branch = os.path.splitdrive(path_to_branch)[1]
200
228
            branch = Branch.open(
201
229
                'bzr+ssh://fred:secret@localhost:%d%s' % (port, path_to_branch))
202
 
            
203
 
            branch.repository.get_revision_graph()
204
 
            self.assertEqual(None, branch.last_revision())
 
230
            self.make_read_requests(branch)
205
231
            # Check we can perform write operations
206
232
            branch.bzrdir.root_transport.mkdir('foo')
207
233
        finally:
214
240
 
215
241
        self.assertEqual(
216
242
            ['%s serve --inet --directory=/ --allow-writes'
217
 
             % self.get_bzr_path()],
 
243
             % bzr_remote_path],
218
244
            self.command_executed)
219
 
        
 
245
 
 
246
 
 
247
class TestCmdServeChrooting(TestCaseWithTransport):
 
248
 
 
249
    def test_serve_tcp(self):
 
250
        """'bzr serve' wraps the given --directory in a ChrootServer.
 
251
 
 
252
        So requests that search up through the parent directories (like
 
253
        find_repositoryV3) will give "not found" responses, rather than
 
254
        InvalidURLJoin or jail break errors.
 
255
        """
 
256
        t = self.get_transport()
 
257
        t.mkdir('server-root')
 
258
        self.run_bzr_serve_then_func(
 
259
            ['--port', '0', '--directory', t.local_abspath('server-root'),
 
260
             '--allow-writes'],
 
261
            self.when_server_started)
 
262
        # The when_server_started method issued a find_repositoryV3 that should
 
263
        # fail with 'norepository' because there are no repositories inside the
 
264
        # --directory.
 
265
        self.assertEqual(('norepository',), self.client_resp)
 
266
        
 
267
    def run_bzr_serve_then_func(self, serve_args, func, *func_args,
 
268
            **func_kwargs):
 
269
        """Run 'bzr serve', and run the given func in a thread once the server
 
270
        has started.
 
271
        
 
272
        When 'func' terminates, the server will be terminated too.
 
273
        """
 
274
        # install hook
 
275
        def on_server_start(backing_urls, tcp_server):
 
276
            t = threading.Thread(
 
277
                target=on_server_start_thread, args=(tcp_server,))
 
278
            t.start()
 
279
        def on_server_start_thread(tcp_server):
 
280
            try:
 
281
                # Run func
 
282
                self.tcp_server = tcp_server
 
283
                try:
 
284
                    func(*func_args, **func_kwargs)
 
285
                except Exception, e:
 
286
                    # Log errors to make some test failures a little less
 
287
                    # mysterious.
 
288
                    mutter('func broke: %r', e)
 
289
            finally:
 
290
                # Then stop the server
 
291
                mutter('interrupting...')
 
292
                thread.interrupt_main()
 
293
        SmartTCPServer.hooks.install_named_hook(
 
294
            'server_started_ex', on_server_start,
 
295
            'run_bzr_serve_then_func hook')
 
296
        # start a TCP server
 
297
        try:
 
298
            self.run_bzr(['serve'] + list(serve_args))
 
299
        except KeyboardInterrupt:
 
300
            pass
 
301
 
 
302
    def when_server_started(self):
 
303
        # Connect to the TCP server and issue some requests and see what comes
 
304
        # back.
 
305
        client_medium = medium.SmartTCPClientMedium(
 
306
            '127.0.0.1', self.tcp_server.port,
 
307
            'bzr://localhost:%d/' % (self.tcp_server.port,))
 
308
        smart_client = client._SmartClient(client_medium)
 
309
        resp = smart_client.call('mkdir', 'foo', '')
 
310
        resp = smart_client.call('BzrDirFormat.initialize', 'foo/')
 
311
        try:
 
312
            resp = smart_client.call('BzrDir.find_repositoryV3', 'foo/')
 
313
        except errors.ErrorFromSmartServer, e:
 
314
            resp = e.error_tuple
 
315
        self.client_resp = resp
 
316
        client_medium.disconnect()
 
317
 
 
318
 
 
319