Skip to content

Commit 0d5e4c2

Browse files
committed
fix wsgi tests by using external server and reading input properly
1 parent 8b666fb commit 0d5e4c2

File tree

3 files changed

+120
-113
lines changed

3 files changed

+120
-113
lines changed

gabbi/tests/external_server.py

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
2+
import sys
3+
from wsgiref import simple_server
4+
5+
from gabbi.tests import simple_wsgi
6+
7+
def run(port):
8+
server = simple_server.make_server("127.0.0.1", int(port), simple_wsgi.SimpleWsgi())
9+
server.serve_forever()
10+
11+
if __name__ == "__main__":
12+
port = sys.argv[1]
13+
run(port)

gabbi/tests/simple_wsgi.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,8 @@ def __call__(self, environ, start_response):
6464
return []
6565

6666
if request_method.startswith('P'):
67-
body = environ['wsgi.input'].read()
67+
length = int(environ.get('CONTENT_LENGTH', '0'))
68+
body = environ['wsgi.input'].read(length)
6869
if body:
6970
if not content_type_header:
7071
start_response('400 Bad request', headers)

gabbi/tests/test_runner.py

+105-112
Original file line numberDiff line numberDiff line change
@@ -14,31 +14,52 @@
1414
"""
1515

1616
from io import StringIO
17+
import os
18+
import subprocess
19+
import socket
1720
import sys
21+
import time
1822
import unittest
19-
from uuid import uuid4
20-
21-
from wsgi_intercept.interceptor import Urllib3Interceptor
2223

2324
from gabbi import exception
2425
from gabbi.handlers import base
2526
from gabbi.handlers.jsonhandler import JSONHandler
2627
from gabbi import runner
27-
from gabbi.tests.simple_wsgi import SimpleWsgi
28+
29+
30+
def get_free_port():
31+
sock = socket.socket()
32+
sock.bind(('', 0))
33+
return sock.getsockname()[1]
34+
35+
class ForkedWSGIServer:
36+
37+
def __init__(self, port):
38+
self.port = port
39+
40+
def start(self):
41+
self.process = subprocess.Popen([
42+
"python", "gabbi/tests/external_server.py", str(self.port)],
43+
env=os.environ.update({"PYTHONPATH": "."}),
44+
close_fds=True)
45+
# We need to sleep a bit to let the wsgi server start.
46+
time.sleep(.2)
47+
48+
def stop(self):
49+
self.process.terminate()
2850

2951

3052
class RunnerTest(unittest.TestCase):
3153

54+
port = get_free_port()
55+
3256
def setUp(self):
3357
super(RunnerTest, self).setUp()
3458

35-
# NB: random host ensures that we're not accidentally connecting to an
36-
# actual server
37-
host, port = (str(uuid4()), 8000)
38-
self.host = host
39-
self.port = port
40-
self.server = lambda: Urllib3Interceptor(
41-
SimpleWsgi, host=host, port=port)
59+
self.host = "localhost"
60+
self.resolved_host = "1.0.0.127.in-addr.arpa"
61+
self.server = ForkedWSGIServer(self.port)
62+
self.server.start()
4263

4364
self._stdin = sys.stdin
4465

@@ -49,41 +70,39 @@ def setUp(self):
4970
sys.stderr = StringIO() # swallow output to avoid confusion
5071

5172
self._argv = sys.argv
52-
sys.argv = ['gabbi-run', '%s:%s' % (host, port)]
73+
sys.argv = ['gabbi-run', '%s:%s' % (self.host, self.port)]
5374

5475
def tearDown(self):
5576
sys.stdin = self._stdin
5677
sys.stdout = self._stdout
5778
sys.stderr = self._stderr
5879
sys.argv = self._argv
80+
self.server.stop()
5981

6082
def test_input_files(self):
6183
sys.argv = ['gabbi-run', 'http://%s:%s/foo' % (self.host, self.port)]
6284

6385
sys.argv.append('--')
6486
sys.argv.append('gabbi/tests/gabbits_runner/success.yaml')
6587

66-
with self.server():
67-
try:
68-
runner.run()
69-
except SystemExit as err:
70-
self.assertSuccess(err)
88+
try:
89+
runner.run()
90+
except SystemExit as err:
91+
self.assertSuccess(err)
7192

7293
sys.argv.append('gabbi/tests/gabbits_runner/failure.yaml')
7394

74-
with self.server():
75-
try:
76-
runner.run()
77-
except SystemExit as err:
78-
self.assertFailure(err)
95+
try:
96+
runner.run()
97+
except SystemExit as err:
98+
self.assertFailure(err)
7999

80100
sys.argv.append('gabbi/tests/gabbits_runner/success_alt.yaml')
81101

82-
with self.server():
83-
try:
84-
runner.run()
85-
except SystemExit as err:
86-
self.assertFailure(err)
102+
try:
103+
runner.run()
104+
except SystemExit as err:
105+
self.assertFailure(err)
87106

88107
def test_unsafe_yaml(self):
89108
sys.argv = ['gabbi-run', 'http://%s:%s/nan' % (self.host, self.port)]
@@ -92,11 +111,10 @@ def test_unsafe_yaml(self):
92111
sys.argv.append('--')
93112
sys.argv.append('gabbi/tests/gabbits_runner/nan.yaml')
94113

95-
with self.server():
96-
try:
97-
runner.run()
98-
except SystemExit as err:
99-
self.assertSuccess(err)
114+
try:
115+
runner.run()
116+
except SystemExit as err:
117+
self.assertSuccess(err)
100118

101119
def test_target_url_parsing(self):
102120
sys.argv = ['gabbi-run', 'http://%s:%s/foo' % (self.host, self.port)]
@@ -108,36 +126,11 @@ def test_target_url_parsing(self):
108126
status: 200
109127
response_headers:
110128
x-gabbi-url: http://%s:%s/foo/baz
111-
""" % (self.host, self.port))
112-
with self.server():
113-
try:
114-
runner.run()
115-
except SystemExit as err:
116-
self.assertSuccess(err)
117-
118-
def test_target_url_parsing_standard_port(self):
119-
# NOTE(cdent): For reasons unclear this regularly fails in
120-
# py.test and sometimes fails with testr. So there is
121-
# some state that is not being properly cleard somewhere.
122-
# Within SimpleWsgi, the environ thinks url_scheme is
123-
# 'https'.
124-
self.server = lambda: Urllib3Interceptor(
125-
SimpleWsgi, host=self.host, port=80)
126-
sys.argv = ['gabbi-run', 'http://%s/foo' % self.host]
127-
128-
sys.stdin = StringIO("""
129-
tests:
130-
- name: expected success
131-
GET: /baz
132-
status: 200
133-
response_headers:
134-
x-gabbi-url: http://%s/foo/baz
135-
""" % self.host)
136-
with self.server():
137-
try:
138-
runner.run()
139-
except SystemExit as err:
140-
self.assertSuccess(err)
129+
""" % (self.resolved_host, self.port))
130+
try:
131+
runner.run()
132+
except SystemExit as err:
133+
self.assertSuccess(err)
141134

142135
def test_custom_response_handler(self):
143136
sys.stdin = StringIO("""
@@ -160,11 +153,11 @@ def test_custom_response_handler(self):
160153
h1: Hello World
161154
p: lorem ipsum dolor sit amet
162155
""")
163-
with self.server():
164-
try:
165-
runner.run()
166-
except SystemExit as err:
167-
self.assertSuccess(err)
156+
157+
try:
158+
runner.run()
159+
except SystemExit as err:
160+
self.assertSuccess(err)
168161

169162
sys.stdin = StringIO("""
170163
tests:
@@ -173,11 +166,11 @@ def test_custom_response_handler(self):
173166
response_html:
174167
h1: lipsum
175168
""")
176-
with self.server():
177-
try:
178-
runner.run()
179-
except SystemExit as err:
180-
self.assertFailure(err)
169+
170+
try:
171+
runner.run()
172+
except SystemExit as err:
173+
self.assertFailure(err)
181174

182175
sys.argv.insert(3, "-r")
183176
sys.argv.insert(4, "gabbi.tests.test_intercept:StubResponseHandler")
@@ -191,11 +184,11 @@ def test_custom_response_handler(self):
191184
response_test:
192185
- COWAnother line
193186
""")
194-
with self.server():
195-
try:
196-
runner.run()
197-
except SystemExit as err:
198-
self.assertSuccess(err)
187+
188+
try:
189+
runner.run()
190+
except SystemExit as err:
191+
self.assertSuccess(err)
199192

200193
sys.argv.insert(5, "-r")
201194
sys.argv.insert(6, "gabbi.tests.custom_response_handler")
@@ -208,11 +201,11 @@ def test_custom_response_handler(self):
208201
- Hello World
209202
- lorem ipsum dolor sit amet
210203
""")
211-
with self.server():
212-
try:
213-
runner.run()
214-
except SystemExit as err:
215-
self.assertSuccess(err)
204+
205+
try:
206+
runner.run()
207+
except SystemExit as err:
208+
self.assertSuccess(err)
216209

217210
def test_exit_code(self):
218211
sys.stdin = StringIO()
@@ -225,6 +218,7 @@ def test_exit_code(self):
225218
GET: /
226219
status: 666
227220
""")
221+
228222
try:
229223
runner.run()
230224
except SystemExit as err:
@@ -236,23 +230,23 @@ def test_exit_code(self):
236230
GET: /
237231
status: 200
238232
""")
239-
with self.server():
240-
try:
241-
runner.run()
242-
except SystemExit as err:
243-
self.assertSuccess(err)
233+
234+
try:
235+
runner.run()
236+
except SystemExit as err:
237+
self.assertSuccess(err)
244238

245239
def test_verbose_output_formatting(self):
246240
"""Confirm that a verbose test handles output properly."""
247241
sys.argv = ['gabbi-run', 'http://%s:%s/foo' % (self.host, self.port)]
248242

249243
sys.argv.append('--')
250244
sys.argv.append('gabbi/tests/gabbits_runner/test_verbose.yaml')
251-
with self.server():
252-
try:
253-
runner.run()
254-
except SystemExit as err:
255-
self.assertSuccess(err)
245+
246+
try:
247+
runner.run()
248+
except SystemExit as err:
249+
self.assertSuccess(err)
256250

257251
sys.stdout.seek(0)
258252
output = sys.stdout.read()
@@ -270,11 +264,10 @@ def test_data_dir_good(self):
270264
sys.argv.append('--')
271265
sys.argv.append('gabbi/tests/gabbits_runner/test_data.yaml')
272266

273-
with self.server():
274-
try:
275-
runner.run()
276-
except SystemExit as err:
277-
self.assertSuccess(err)
267+
try:
268+
runner.run()
269+
except SystemExit as err:
270+
self.assertSuccess(err)
278271

279272
# Compare the verbose output of tests with pretty printed
280273
# data.
@@ -298,21 +291,20 @@ def test_stdin_data_dir(self):
298291
response_json_paths:
299292
$.items.house: blue
300293
""")
301-
with self.server():
302-
try:
303-
runner.run()
304-
except SystemExit as err:
305-
self.assertSuccess(err)
294+
295+
try:
296+
runner.run()
297+
except SystemExit as err:
298+
self.assertSuccess(err)
306299

307300
def _run_verbosity_arg(self):
308301
sys.argv.append('--')
309302
sys.argv.append('gabbi/tests/gabbits_runner/verbosity.yaml')
310303

311-
with self.server():
312-
try:
313-
runner.run()
314-
except SystemExit as err:
315-
self.assertSuccess(err)
304+
try:
305+
runner.run()
306+
except SystemExit as err:
307+
self.assertSuccess(err)
316308

317309
sys.stdout.seek(0)
318310
output = sys.stdout.read()
@@ -365,11 +357,12 @@ def test_quiet_is_quiet(self):
365357
response_headers:
366358
x-gabbi-url: http://%s:%s/foo/baz
367359
""" % (self.host, self.port))
368-
with self.server():
369-
try:
370-
runner.run()
371-
except SystemExit as err:
372-
self.assertSuccess(err)
360+
361+
try:
362+
runner.run()
363+
except SystemExit as err:
364+
self.assertSuccess(err)
365+
373366
sys.stdout.seek(0)
374367
sys.stderr.seek(0)
375368
stdoutput = sys.stdout.read()

0 commit comments

Comments
 (0)