blob: 3dd066462b9bcb138be8540c829aaea8be2487a7 [file] [log] [blame]
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
#
import os, sys
from time import sleep
import system_test
from system_test import TestCase, Qdrouterd, Process, SkipIfNeeded
from subprocess import PIPE
def python_37_available():
if sys.version_info >= (3, 7):
return True
def curl_available():
popen_args = ['curl', '--version']
try:
process = Process(popen_args,
name='curl_check',
stdout=PIPE,
expect=None,
universal_newlines=True)
out = process.communicate()[0]
return True
except:
return False
def quart_available():
popen_args = ['quart', '--version']
try:
process = Process(popen_args,
name='curl_check',
stdout=PIPE,
expect=None,
universal_newlines=True)
out = process.communicate()[0]
parts = out.split(".")
if int(parts[1]) >= 13:
return True
return False
except Exception as e:
print (e)
print("quart_not_available")
return False
def skip_test():
if python_37_available() and quart_available() and curl_available():
return False
return True
class Http2TestBase(TestCase):
def run_curl(self, args=None, regexp=None, address=None):
# Tell with -m / --max-time the maximum time, in seconds, that you
# allow the command line to spend before curl exits with a
# timeout error code (28).
local_args = ["--http2-prior-knowledge"]
if args:
local_args = args + ["--http2-prior-knowledge"]
popen_args = ['curl',
str(address),
'--max-time', str(system_test.TIMEOUT)] + local_args
p = self.popen(popen_args,
name='curl-' + self.id(), stdout=PIPE, expect=None,
universal_newlines=True)
out = p.communicate()[0]
assert (p.returncode == 0)
return out
class CommonHttp2Tests():
"""
The tests in this class are run by both Http2TestOneRouter and
Http2TestTwoRouter
"""
@SkipIfNeeded(skip_test(), "Python 3.7 or greater, Quart 0.13.0 or greater and curl needed to run http2 tests")
# Tests the HTTP2 head request
def test_head_request(self):
# Run curl 127.0.0.1:port --http2-prior-knowledge --head
address = self.router_qdra.http_addresses[0]
out = self.run_curl(args=["--head"], address=address)
self.assertIn('HTTP/2 200', out)
self.assertIn('server: hypercorn-h2', out)
self.assertIn('content-type: text/html; charset=utf-8', out)
@SkipIfNeeded(skip_test(), "Python 3.7 or greater, Quart 0.13.0 or greater and curl needed to run http2 tests")
def test_get_request(self):
# Run curl 127.0.0.1:port --http2-prior-knowledge
address = self.router_qdra.http_addresses[0]
out = self.run_curl(address=address)
i = 0
ret_string = ""
while (i < 1000):
ret_string += str(i) + ","
i += 1
self.assertIn(ret_string, out)
@SkipIfNeeded(skip_test(), "Python 3.7 or greater, Quart 0.13.0 or greater and curl needed to run http2 tests")
def test_large_get_request(self):
# Tests a large get request. Response is more than 50k which means it
# will span many qd_http2_buffer_t objects.
# Run curl 127.0.0.1:port/largeget --http2-prior-knowledge
address = self.router_qdra.http_addresses[0] + "/largeget"
out = self.run_curl(address=address)
self.assertIn("49996,49997,49998,49999", out)
@SkipIfNeeded(skip_test(), "Python 3.7 or greater, Quart 0.13.0 or greater and curl needed to run http2 tests")
def test_post_request(self):
# curl -d "fname=John&lname=Doe" -X POST 127.0.0.1:9000/myinfo --http2-prior-knowledge
address = self.router_qdra.http_addresses[0] + "/myinfo"
out = self.run_curl(args=['-d', 'fname=John&lname=Doe', '-X', 'POST'], address=address)
self.assertIn('Success! Your first name is John, last name is Doe', out)
@SkipIfNeeded(skip_test(), "Python 3.7 or greater, Quart 0.13.0 or greater and curl needed to run http2 tests")
def test_delete_request(self):
# curl -X DELETE "http://127.0.0.1:9000/myinfo/delete/22122" -H "accept: application/json" --http2-prior-knowledge
address = self.router_qdra.http_addresses[0] + "/myinfo/delete/22122"
out = self.run_curl(args=['-X', 'DELETE'], address=address)
self.assertIn('{"fname": "John", "lname": "Doe", "id": "22122"}', out)
@SkipIfNeeded(skip_test(), "Python 3.7 or greater, Quart 0.13.0 or greater and curl needed to run http2 tests")
def test_put_request(self):
# curl -d "fname=John&lname=Doe" -X PUT 127.0.0.1:9000/myinfo --http2-prior-knowledge
address = self.router_qdra.http_addresses[0] + "/myinfo"
out = self.run_curl(args=['-d', 'fname=John&lname=Doe', '-X', 'PUT'], address=address)
self.assertIn('Success! Your first name is John, last name is Doe', out)
@SkipIfNeeded(skip_test(), "Python 3.7 or greater, Quart 0.13.0 or greater and curl needed to run http2 tests")
def test_patch_request(self):
# curl -d "fname=John&lname=Doe" -X PATCH 127.0.0.1:9000/myinfo --http2-prior-knowledge
address = self.router_qdra.http_addresses[0] + "/patch"
out = self.run_curl(args=['--data', '{\"op\":\"add\",\"path\":\"/user\",\"value\":\"jane\"}', '-X', 'PATCH'], address=address)
self.assertIn('"op":"add"', out)
@SkipIfNeeded(skip_test(), "Python 3.7 or greater, Quart 0.13.0 or greater and curl needed to run http2 tests")
def test_404(self):
# Run curl 127.0.0.1:port/unavilable --http2-prior-knowledge
address = self.router_qdra.http_addresses[0] + "/unavilable"
out = self.run_curl(address=address)
self.assertIn('404 Not Found', out)
@SkipIfNeeded(skip_test(), "Python 3.7 or greater, Quart 0.13.0 or greater and curl needed to run http2 tests")
def test_500(self):
# Run curl 127.0.0.1:port/unavilable --http2-prior-knowledge
address = self.router_qdra.http_addresses[0] + "/test/500"
out = self.run_curl(address=address)
self.assertIn('500 Internal Server Error', out)
@SkipIfNeeded(skip_test(), "Python 3.7 or greater, Quart 0.13.0 or greater and curl needed to run http2 tests")
def test_get_image_png(self):
# Run curl 127.0.0.1:port --http2-prior-knowledge
passed = False
try:
address = self.router_qdra.http_addresses[0] + "/images/balanced-routing.png"
self.run_curl(address=address)
except UnicodeDecodeError as u:
if "codec can't decode byte 0x89" in str(u):
passed = True
self.assertTrue(passed)
@SkipIfNeeded(skip_test(), "Python 3.7 or greater, Quart 0.13.0 or greater and curl needed to run http2 tests")
def test_get_image_jpg(self):
# Run curl 127.0.0.1:port --http2-prior-knowledge
passed = False
try:
address = self.router_qdra.http_addresses[0] + "/images/apache.jpg"
self.run_curl(address=address)
except UnicodeDecodeError as u:
print (u)
if "codec can't decode byte 0xff" in str(u):
passed = True
self.assertTrue(passed)
class Http2TestOneRouter(Http2TestBase, CommonHttp2Tests):
@classmethod
def setUpClass(cls):
super(Http2TestOneRouter, cls).setUpClass()
if skip_test():
return
cls.http2_server_name = "http2_server"
os.environ["QUART_APP"] = "http2server:app"
os.environ['SERVER_LISTEN_PORT'] = str(cls.tester.get_port())
cls.http2_server = cls.tester.http2server(name=cls.http2_server_name,
listen_port=int(os.getenv('SERVER_LISTEN_PORT')),
py_string='python3',
server_file="http2_server.py")
name = "http2-test-router"
config = Qdrouterd.Config([
('router', {'mode': 'standalone', 'id': 'QDR'}),
('listener', {'port': cls.tester.get_port(), 'role': 'normal', 'host': '0.0.0.0'}),
('httpListener', {'port': cls.tester.get_port(), 'address': 'examples',
'host': '127.0.0.1', 'protocolVersion': 'HTTP2'}),
('httpConnector',
{'port': os.getenv('SERVER_LISTEN_PORT'), 'address': 'examples',
'host': '127.0.0.1', 'protocolVersion': 'HTTP2'})
])
cls.router_qdra = cls.tester.qdrouterd(name, config, wait=True)
class Http2TestTwoRouter(Http2TestBase, CommonHttp2Tests):
@classmethod
def setUpClass(cls):
super(Http2TestTwoRouter, cls).setUpClass()
if skip_test():
return
cls.http2_server_name = "http2_server"
os.environ["QUART_APP"] = "http2server:app"
os.environ['SERVER_LISTEN_PORT'] = str(cls.tester.get_port())
cls.http2_server = cls.tester.http2server(name=cls.http2_server_name,
listen_port=int(os.getenv('SERVER_LISTEN_PORT')),
py_string='python3',
server_file="http2_server.py")
name = "http2-test-router"
inter_router_port = cls.tester.get_port()
config_qdra = Qdrouterd.Config([
('router', {'mode': 'interior', 'id': 'QDR.A'}),
('listener', {'port': cls.tester.get_port(), 'role': 'normal', 'host': '0.0.0.0'}),
('httpListener', {'port': cls.tester.get_port(), 'address': 'examples',
'host': '127.0.0.1', 'protocolVersion': 'HTTP2'}),
('listener', {'role': 'inter-router', 'port': inter_router_port})
])
config_qdrb = Qdrouterd.Config([
('router', {'mode': 'interior', 'id': 'QDR.B'}),
('listener', {'port': cls.tester.get_port(), 'role': 'normal', 'host': '0.0.0.0'}),
('httpConnector',
{'port': os.getenv('SERVER_LISTEN_PORT'), 'address': 'examples',
'host': '127.0.0.1', 'protocolVersion': 'HTTP2'}),
('connector', {'name': 'connectorToA', 'role': 'inter-router',
'port': inter_router_port,
'verifyHostname': 'no'})
])
cls.router_qdra = cls.tester.qdrouterd(name, config_qdra, wait=True)
cls.router_qdrb = cls.tester.qdrouterd(name, config_qdrb, wait=True)
cls.router_qdra.wait_router_connected('QDR.B')
cls.router_qdrb.wait_router_connected('QDR.A')
sleep(2)