1
# Copyright (C) 2005, 2006 Canonical
1
# Copyright (C) 2005, 2006 Canonical Ltd
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
20
20
# TODO: Should be renamed to bzrlib.transport.http.tests?
23
from bzrlib.errors import DependencyNotPresent
28
from bzrlib.errors import DependencyNotPresent, UnsupportedProtocol
29
from bzrlib import osutils
24
30
from bzrlib.tests import TestCase, TestSkipped
25
from bzrlib.transport import Transport
31
from bzrlib.transport import get_transport, Transport
26
32
from bzrlib.transport.http import extract_auth, HttpTransportBase
27
33
from bzrlib.transport.http._urllib import HttpTransport_urllib
28
34
from bzrlib.tests.HTTPTestUtil import TestCaseWithWebserver
31
class FakeManager (object):
37
class FakeManager(object):
33
39
def __init__(self):
34
40
self.credentials = []
37
43
self.credentials.append([realm, host, username, password])
46
class RecordingServer(object):
47
"""A fake HTTP server.
49
It records the bytes sent to it, and replies with a 200.
52
def __init__(self, expect_body_tail=None):
55
:type expect_body_tail: str
56
:param expect_body_tail: a reply won't be sent until this string is
59
self._expect_body_tail = expect_body_tail
62
self.received_bytes = ''
65
self._sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
66
self._sock.bind(('127.0.0.1', 0))
67
self.host, self.port = self._sock.getsockname()
68
self._ready = threading.Event()
69
self._thread = threading.Thread(target=self._accept_read_and_reply)
70
self._thread.setDaemon(True)
74
def _accept_read_and_reply(self):
77
self._sock.settimeout(5)
79
conn, address = self._sock.accept()
80
# On win32, the accepted connection will be non-blocking to start
81
# with because we're using settimeout.
82
conn.setblocking(True)
83
while not self.received_bytes.endswith(self._expect_body_tail):
84
self.received_bytes += conn.recv(4096)
85
conn.sendall('HTTP/1.1 200 OK\r\n')
86
except socket.timeout:
87
# Make sure the client isn't stuck waiting for us to e.g. accept.
94
# We might have already closed it. We don't care.
40
100
class TestHttpUrls(TestCase):
42
102
def test_url_parsing(self):
68
128
self.assertRaises(ValueError,
71
self.assertRaises(ValueError,
75
132
def test_http_root_urls(self):
76
133
"""Construction of URLs from server root"""
126
183
self.assertTrue(server.logs[0].find(
127
184
'"GET /foo/bar HTTP/1.1" 200 - "-" "bzr/%s' % bzrlib.__version__) > -1)
186
def test_get_smart_medium(self):
187
# For HTTP, get_smart_medium should return the transport object.
188
server = self.get_readonly_server()
189
http_transport = self._transport(server.get_url())
190
medium = http_transport.get_smart_medium()
191
self.assertIs(medium, http_transport)
130
194
class TestHttpConnections_urllib(TestCaseWithWebserver, TestHttpMixins):
135
199
TestCaseWithWebserver.setUp(self)
136
200
self._prep_tree()
202
def test_has_on_bogus_host(self):
204
# Get a random address, so that we can be sure there is no
205
# http handler there.
207
s.bind(('localhost', 0))
208
t = self._transport('http://%s:%s/' % s.getsockname())
209
self.assertRaises(urllib2.URLError, t.has, 'foo/bar')
140
212
class TestHttpConnections_pycurl(TestCaseWithWebserver, TestHttpMixins):
190
261
self.assertEqual([[10, 12], [22, 26]], ranges)
264
class TestPost(TestCase):
266
def _test_post_body_is_received(self, scheme):
267
server = RecordingServer(expect_body_tail='end-of-body')
269
self.addCleanup(server.tearDown)
270
url = '%s://%s:%s/' % (scheme, server.host, server.port)
272
http_transport = get_transport(url)
273
except UnsupportedProtocol:
274
raise TestSkipped('%s not available' % scheme)
275
code, response = http_transport._post('abc def end-of-body')
277
server.received_bytes.startswith('POST /.bzr/smart HTTP/1.'))
278
self.assertTrue('content-length: 19\r' in server.received_bytes.lower())
279
# The transport should not be assuming that the server can accept
280
# chunked encoding the first time it connects, because HTTP/1.1, so we
281
# check for the literal string.
283
server.received_bytes.endswith('\r\n\r\nabc def end-of-body'))
285
def test_post_body_is_received_urllib(self):
286
self._test_post_body_is_received('http+urllib')
288
def test_post_body_is_received_pycurl(self):
289
self._test_post_body_is_received('http+pycurl')
193
292
class TestRangeHeader(TestCase):
194
293
"""Test range_header method"""
213
312
self.check_header('0-9,300-5000,-50',
214
313
ranges=[(0,9), (300,5000)],
317
class TestRecordingServer(TestCase):
319
def test_create(self):
320
server = RecordingServer(expect_body_tail=None)
321
self.assertEqual('', server.received_bytes)
322
self.assertEqual(None, server.host)
323
self.assertEqual(None, server.port)
325
def test_setUp_and_tearDown(self):
326
server = RecordingServer(expect_body_tail=None)
329
self.assertNotEqual(None, server.host)
330
self.assertNotEqual(None, server.port)
333
self.assertEqual(None, server.host)
334
self.assertEqual(None, server.port)
336
def test_send_receive_bytes(self):
337
server = RecordingServer(expect_body_tail='c')
339
self.addCleanup(server.tearDown)
340
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
341
sock.connect((server.host, server.port))
343
self.assertEqual('HTTP/1.1 200 OK\r\n',
344
osutils.recv_all(sock, 4096))
345
self.assertEqual('abc', server.received_bytes)