Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

set defaults for settings, and respect max_frame_size in sending #7

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion tornado_http2/connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ def __init__(self, stream, is_client, params=None, context=None):
self._initial_settings_written = Future()
self._serving_future = None
self._settings = {}

self.streams = {}
self.next_stream_id = 1 if is_client else 2
self.hpack_decoder = HpackDecoder(
Expand Down
4 changes: 3 additions & 1 deletion tornado_http2/stream.py
Original file line number Diff line number Diff line change
Expand Up @@ -323,7 +323,9 @@ def _write_chunk(self, chunk, callback=None):
if chunk:
yield self.write_lock.acquire()
while chunk:
allowance = yield self.window.consume(len(chunk))
bytes_to_write = min(len(chunk), self.conn.setting(
constants.Setting.MAX_FRAME_SIZE))
allowance = yield self.window.consume(bytes_to_write)

yield self.conn._write_frame(
Frame(constants.FrameType.DATA, 0,
Expand Down
3 changes: 2 additions & 1 deletion tornado_http2/test/benchmark.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ def benchmark(version):

def print_result(label, elapsed):
print('HTTP/%s: %d requests in %0.3fs: %f QPS' % (label, options.n, elapsed,
options.n / elapsed))
options.n / elapsed))


@gen.coroutine
Expand All @@ -58,5 +58,6 @@ def main():
elapsed = yield benchmark(int(version))
print_result(version, elapsed)


if __name__ == '__main__':
IOLoop.current().run_sync(main)
8 changes: 7 additions & 1 deletion tornado_http2/test/encoding_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

from tornado_http2.encoding import BitEncoder, BitDecoder, EODError


class TestData(object):
def __init__(self, *args):
self.args = args
Expand All @@ -14,20 +15,23 @@ def decode(self, test, decoder):
for arg in self.args:
test.assertEqual(self.decode_value(decoder), arg)


class Bits(TestData):
def encode_value(self, encoder, arg):
encoder.write_bit(arg)

def decode_value(self, decoder):
return decoder.read_bit()


class HpackInt(TestData):
def encode_value(self, encoder, arg):
encoder.write_hpack_int(arg)

def decode_value(self, decoder):
return decoder.read_hpack_int()


class HuffChar(TestData):
def __init__(self, data):
# convert strings to a sequence of bytes
Expand All @@ -39,6 +43,7 @@ def encode_value(self, encoder, arg):
def decode_value(self, decoder):
return decoder.read_huffman_char(None)


test_data = [
('1-bit', [Bits(1)], [0b10000000], False),
('5-bits', [Bits(1, 0, 1, 1, 0)], [0b10110000], False),
Expand Down Expand Up @@ -78,7 +83,8 @@ def decode_value(self, decoder):
# Individual huffman-encoded characters
('huff1', [HuffChar(b'a')], [0b00011000], False),
('huff2', [HuffChar(b'Hi')], [0b11000110, 0b01100000], False),
]
]


class BitEncodingTest(unittest.TestCase):
def test_bit_encoder(self):
Expand Down
1 change: 1 addition & 0 deletions tornado_http2/test/runtests.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,6 @@ def configure_httpclient():
logging.getLogger("tornado.access").setLevel(logging.CRITICAL)
tornado.testing.main()


if __name__ == '__main__':
main()
21 changes: 18 additions & 3 deletions tornado_http2/test/server_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,30 +15,45 @@ def get(self):

class ServerTest(AsyncHTTP2TestCase):
def get_app(self):
class LargeResponseHandler(RequestHandler):
class LargeChunkedResponseHandler(RequestHandler):
@gen.coroutine
def get(self):
for i in range(200):
self.write(b'a' * 1024)
yield self.flush()

class ExtraLargeResponseHandler(RequestHandler):
"""Send the data all at once"""

def get(self):
self.write(b'a' * 1024 * 200)
self.flush()

return Application([
('/hello', HelloHandler),
('/large', LargeResponseHandler),
('/large', LargeChunkedResponseHandler),
('/extralarge', ExtraLargeResponseHandler),
])

def test_hello(self):
resp = self.fetch('/hello')
resp.rethrow()
self.assertEqual(resp.body, b'Hello HTTP/2.0')

def test_large_response(self):
def test_large_response_chunked(self):
# This mainly tests that WINDOW_UPDATE frames are sent as needed,
# since this response exceeds the default 64KB window.
resp = self.fetch('/large')
resp.rethrow()
self.assertEqual(len(resp.body), 200 * 1024)

def test_large_response(self):
# This mainly tests that the server will respect the MAX_FRAME_SIZE
# when sending data on the connection.
resp = self.fetch('/extralarge')
resp.rethrow()
self.assertEqual(len(resp.body), 200 * 1024)


class HTTPSTest(AsyncHTTP2TestCase):
def get_app(self):
Expand Down