def test_on_priority_updates(self): client_conn = Connection( self.client_stream, client_side=True, on_unhandled=mock.Mock()) client_conn.initiate_connection() stream_id = client_conn.get_next_available_stream_id() client_conn.send_request( stream_id, HttpRequest(headers=[ (":method", "GET"), (":path", "/"), ("aaa", "bbb")])) client_conn.send_priority_updates( stream_id, 0, 10, False) server_conn = Connection( self.server_stream, client_side=False, on_priority_updates=self.on_priority_updates, on_unhandled=mock.Mock()) server_conn.initiate_connection() yield server_conn.read_bytes() self.assertIsNotNone(self.priority_updates) self.assertEqual( self.priority_updates, dict(stream_id=stream_id, depends_on=0, weight=10, exclusive=False))
class TestHttp2Layer(ProxyAsyncTestCase): def setUp(self): super(TestHttp2Layer, self).setUp() self.asyncSetUp() self.src_events = [] self.dest_events = [] @gen_test def asyncSetUp(self): self.client_stream, src_stream = yield self.create_iostream_pair() dest_stream, self.server_stream = yield self.create_iostream_pair() server_state = ServerContext(config={}, interceptor=mock.Mock( **{ "publish.return_value": None, "request.return_value": None, "response.return_value": None, })) self.http_layer = Http2Layer( server_state, LayerContext(mode="socks", src_stream=src_stream, dest_stream=dest_stream)) def record_src_event(self, *args): self.src_events.append(args) def record_dest_event(self, *args): self.dest_events.append(args) def ignore_event(self, *args): pass @coroutine def read_until_new_event(self, conn, events): curr_count = len(events) while curr_count == len(events): yield conn.read_bytes() @gen_test def test_req_and_resp(self): self.client_conn = Connection(self.client_stream, client_side=True, on_response=self.record_src_event, on_unhandled=self.ignore_event) self.server_conn = Connection(self.server_stream, client_side=False, on_request=self.record_dest_event, on_unhandled=self.ignore_event) result_future = self.http_layer.process_and_return_context() self.client_conn.initiate_connection() self.server_conn.initiate_connection() self.client_conn.send_request( 1, HttpRequest(headers=[(":method", "GET"), (":path", "/"), ("aaa", "bbb")])) yield self.read_until_new_event(self.server_conn, self.dest_events) self.server_conn.send_response( 1, HttpResponse(headers=[(":status", "200"), ("aaa", "bbb")], body=b"ccc")) yield self.read_until_new_event(self.client_conn, self.src_events) self.client_stream.close() self.server_stream.close() result = yield result_future self.assertIsNotNone(result) self.assertIsInstance(result, LayerContext) self.assertEqual(len(self.src_events), 1) stream_id, response = self.src_events[0] self.assertEqual(stream_id, 1) self.assertEqual(response.code, "200") self.assertEqual(response.version, "HTTP/2") self.assertEqual(response.headers, HttpHeaders([(":status", "200"), ("aaa", "bbb")])) self.assertEqual(response.body, b"ccc") self.assertEqual(len(self.dest_events), 1) stream_id, request, _ = self.dest_events[0] self.assertEqual(stream_id, 1) self.assertEqual(request.method, "GET") self.assertEqual(request.path, "/") self.assertEqual(request.version, "HTTP/2") self.assertEqual( request.headers, HttpHeaders([(":method", "GET"), (":path", "/"), ("aaa", "bbb")])) @gen_test def test_req_with_priority_updated(self): self.client_conn = Connection(self.client_stream, client_side=True, on_unhandled=self.ignore_event) self.server_conn = Connection(self.server_stream, client_side=False, on_request=self.record_dest_event, on_unhandled=self.ignore_event) result_future = self.http_layer.process_and_return_context() self.client_conn.initiate_connection() self.server_conn.initiate_connection() self.client_conn.send_request( 1, HttpRequest(headers=[(":method", "GET"), (":path", "/"), ("aaa", "bbb")]), priority_weight=10, priority_depends_on=0, priority_exclusive=False) yield self.read_until_new_event(self.server_conn, self.dest_events) self.client_stream.close() self.server_stream.close() yield result_future self.assertEqual(len(self.dest_events), 1) stream_id, request, priority_updated = self.dest_events[0] self.assertEqual(stream_id, 1) self.assertEqual(request.method, "GET") self.assertEqual(request.path, "/") self.assertEqual(request.version, "HTTP/2") self.assertEqual( request.headers, HttpHeaders([(":method", "GET"), (":path", "/"), ("aaa", "bbb")])) self.assertIsNotNone(priority_updated) self.assertEqual(priority_updated.weight, 10) self.assertEqual(priority_updated.exclusive, False) self.assertEqual(priority_updated.depends_on, 0) @gen_test def test_push(self): self.client_conn = Connection(self.client_stream, client_side=True, on_response=self.record_src_event, on_push=self.record_src_event, on_unhandled=self.ignore_event) self.server_conn = Connection(self.server_stream, client_side=False, on_request=self.record_dest_event, on_unhandled=self.ignore_event) result_future = self.http_layer.process_and_return_context() self.client_conn.initiate_connection() self.server_conn.initiate_connection() self.client_conn.send_request( 1, HttpRequest(headers=[(":method", "GET"), (":path", "/"), ("aaa", "bbb")])) yield self.read_until_new_event(self.server_conn, self.dest_events) self.server_conn.send_pushed_stream( 1, 2, HttpRequest(headers=[(":method", "GET"), (":path", "/resource")])) yield self.read_until_new_event(self.client_conn, self.src_events) self.server_conn.send_response( 2, HttpResponse(headers=[(":status", "200"), ("aaa", "bbb")], body=b"ccc")) yield self.read_until_new_event(self.client_conn, self.src_events) self.client_stream.close() self.server_stream.close() yield result_future self.assertEqual(len(self.src_events), 2) stream_id, parent_stream_id, request = self.src_events[0] self.assertEqual(stream_id, 2) self.assertEqual(parent_stream_id, 1) self.assertEqual(request.method, "GET") self.assertEqual(request.path, "/resource") self.assertEqual(request.version, "HTTP/2") self.assertEqual( request.headers, HttpHeaders([(":method", "GET"), (":path", "/resource")])) stream_id, response = self.src_events[1] self.assertEqual(stream_id, 2) self.assertEqual(response.code, "200") self.assertEqual(response.version, "HTTP/2") self.assertEqual(response.headers, HttpHeaders([(":status", "200"), ("aaa", "bbb")])) @gen_test def test_window_updates(self): self.client_conn = Connection(self.client_stream, client_side=True, on_window_updates=self.record_src_event, on_unhandled=self.ignore_event) self.server_conn = Connection(self.server_stream, client_side=False, on_window_updates=self.record_dest_event, on_unhandled=self.ignore_event) result_future = self.http_layer.process_and_return_context() self.client_conn.initiate_connection() self.server_conn.initiate_connection() self.client_conn.send_window_updates(0, 100) yield self.read_until_new_event(self.server_conn, self.dest_events) self.client_conn.send_request( 1, HttpRequest(headers=[(":method", "GET"), (":path", "/"), ("aaa", "bbb")])) self.client_conn.send_window_updates(1, 200) yield self.read_until_new_event(self.server_conn, self.dest_events) self.server_conn.send_window_updates(1, 300) yield self.read_until_new_event(self.client_conn, self.src_events) self.client_stream.close() self.server_stream.close() yield result_future print self.src_events self.assertEqual(len(self.src_events), 1) self.assertEqual(self.src_events[0], (1, 300)) self.assertEqual(len(self.dest_events), 2) self.assertEqual(self.dest_events[0], (0, 100)) self.assertEqual(self.dest_events[1], (1, 200)) @gen_test def test_priority_updated(self): self.client_conn = Connection(self.client_stream, client_side=True, on_unhandled=self.ignore_event) self.server_conn = Connection( self.server_stream, client_side=False, on_priority_updates=self.record_dest_event, on_unhandled=self.ignore_event) result_future = self.http_layer.process_and_return_context() self.client_conn.initiate_connection() self.server_conn.initiate_connection() self.client_conn.send_request( 1, HttpRequest(headers=[(":method", "GET"), (":path", "/"), ("aaa", "bbb")])) self.client_conn.send_priority_updates(1, 0, 10, False) yield self.read_until_new_event(self.server_conn, self.dest_events) self.client_stream.close() self.server_stream.close() yield result_future self.assertEqual(len(self.dest_events), 1) self.assertEqual(self.dest_events[0], (1, 0, 10, False)) @gen_test def test_reset(self): self.client_conn = Connection(self.client_stream, client_side=True, on_reset=self.record_src_event, on_unhandled=self.ignore_event) self.server_conn = Connection(self.server_stream, client_side=False, on_request=self.record_dest_event, on_reset=self.record_dest_event, on_unhandled=self.ignore_event) result_future = self.http_layer.process_and_return_context() self.client_conn.initiate_connection() self.server_conn.initiate_connection() self.client_conn.send_request( 1, HttpRequest(headers=[(":method", "GET"), (":path", "/"), ("aaa", "bbb")])) yield self.read_until_new_event(self.server_conn, self.dest_events) self.client_conn.send_reset(1, 0) yield self.read_until_new_event(self.server_conn, self.dest_events) self.client_conn.send_request( 3, HttpRequest(headers=[(":method", "GET"), (":path", "/"), ("aaa", "bbb")])) yield self.read_until_new_event(self.server_conn, self.dest_events) self.server_conn.send_reset(3, 0) yield self.read_until_new_event(self.client_conn, self.src_events) self.client_stream.close() self.server_stream.close() yield result_future self.assertEqual(len(self.src_events), 1) self.assertEqual(self.src_events[0], (3, 0)) self.assertEqual(len(self.dest_events), 3) # NOTE: req, reset, req self.assertEqual(self.dest_events[1], (1, 0)) @gen_test def test_src_send_terminate(self): self.client_conn = Connection(self.client_stream, client_side=True, on_unhandled=self.ignore_event) self.server_conn = Connection(self.server_stream, client_side=False, on_terminate=self.record_dest_event, on_unhandled=self.ignore_event) result_future = self.http_layer.process_and_return_context() self.client_conn.initiate_connection() self.server_conn.initiate_connection() self.client_conn.send_terminate() yield self.read_until_new_event(self.server_conn, self.dest_events) self.client_stream.close() self.server_stream.close() yield result_future self.assertEqual(len(self.dest_events), 1) self.assertEqual(self.dest_events[0], (None, 0, 0)) @gen_test def test_dest_send_terminate(self): self.client_conn = Connection(self.client_stream, client_side=True, on_terminate=self.record_src_event, on_settings=self.record_src_event, on_unhandled=self.ignore_event) self.server_conn = Connection(self.server_stream, client_side=False, on_unhandled=self.ignore_event) result_future = self.http_layer.process_and_return_context() self.client_conn.initiate_connection() self.server_conn.initiate_connection() # NOTE: because hyper-h2 will always send SettingsChanged when init # Than client will receive two setting frame from destination and server yield self.read_until_new_event(self.client_conn, self.src_events) yield self.read_until_new_event(self.client_conn, self.src_events) self.server_conn.send_terminate() yield self.read_until_new_event(self.client_conn, self.src_events) self.client_stream.close() self.server_stream.close() yield result_future self.assertEqual(len(self.src_events), 3) self.assertEqual(self.src_events[2], (None, 0, 0)) @gen_test def test_safe_mapping_id(self): self.client_conn = Connection(self.client_stream, client_side=True, on_unhandled=self.ignore_event) self.server_conn = Connection(self.server_stream, client_side=False, on_request=self.record_dest_event, on_unhandled=self.ignore_event) result_future = self.http_layer.process_and_return_context() self.client_conn.initiate_connection() self.server_conn.initiate_connection() self.assertEqual( self.http_layer.safe_mapping_id(self.http_layer.src_to_dest_ids, 1), 0) self.client_conn.send_request( 1, HttpRequest(headers=[(":method", "GET"), (":path", "/"), ("aaa", "bbb")])) yield self.read_until_new_event(self.server_conn, self.dest_events) self.assertEqual( self.http_layer.safe_mapping_id(self.http_layer.src_to_dest_ids, 1), 1) self.client_stream.close() self.server_stream.close() yield result_future @gen_test def test_replay(self): self.http_layer.context.mode = "replay" self.client_conn = Connection(self.client_stream, client_side=True, on_unhandled=self.ignore_event) self.server_conn = Connection(self.server_stream, client_side=False, on_request=self.record_dest_event, on_unhandled=self.ignore_event) result_future = self.http_layer.process_and_return_context() self.client_conn.initiate_connection() self.server_conn.initiate_connection() self.client_conn.send_request( 1, HttpRequest(headers=[(":method", "GET"), (":path", "/"), ("aaa", "bbb")])) yield self.read_until_new_event(self.server_conn, self.dest_events) self.server_conn.send_response( 1, HttpResponse(headers=[(":status", "200"), ("aaa", "bbb")], body=b"ccc")) result = yield result_future self.assertIsNotNone(result) self.assertIsInstance(result, LayerContext) self.assertEqual(len(self.dest_events), 1) stream_id, request, _ = self.dest_events[0] self.assertEqual(stream_id, 1) self.assertEqual(request.method, "GET") self.assertEqual(request.path, "/") self.assertEqual(request.version, "HTTP/2") self.assertEqual( request.headers, HttpHeaders([(":method", "GET"), (":path", "/"), ("aaa", "bbb")])) def tearDown(self): self.client_stream.close() self.server_stream.close() self.http_layer.src_stream.close() self.http_layer.dest_stream.close()
class Http2Layer(ApplicationLayer): ''' Http2Layer: Responsible for handling the http2 request and response. ''' def __init__(self, server_state, context): super(Http2Layer, self).__init__(server_state, context) self.src_conn = Connection( self.src_stream, client_side=False, conn_type="source", on_request=self.on_request, on_settings=self.on_src_settings, on_window_updates=self.on_src_window_updates, on_priority_updates=self.on_src_priority_updates, on_reset=self.on_src_reset, on_terminate=self.on_src_terminate, readonly=(context.mode == "replay")) self.dest_conn = Connection( self.dest_stream, client_side=True, conn_type="destination", on_response=self.on_response, on_push=self.on_push, on_settings=self.on_dest_settings, on_window_updates=self.on_dest_window_updates, on_terminate=self.on_dest_terminate, on_reset=self.on_dest_reset) self.streams = dict() self.src_to_dest_ids = dict([(0, 0)]) self.dest_to_src_ids = dict([(0, 0)]) self._future = concurrent.Future() @gen.coroutine def process_and_return_context(self): yield self._init_h2_connection() self.src_stream.read_until_close( streaming_callback=self.src_conn.receive) self.src_stream.set_close_callback(self.on_src_close) self.dest_stream.read_until_close( streaming_callback=self.dest_conn.receive) self.dest_stream.set_close_callback(self.on_dest_close) result = yield self._future raise gen.Return(result) @gen.coroutine def _init_h2_connection(self): self.dest_conn.initiate_connection() yield self.dest_conn.flush() self.src_conn.initiate_connection() yield self.src_conn.flush() def on_src_close(self): logger.debug("{0}: src stream closed".format(self)) self.dest_stream.close() self.layer_finish() def on_dest_close(self): logger.debug("{0}: dest stream closed".format(self)) self.src_stream.close() self.layer_finish() def layer_finish(self): if self._future.running(): self._future.set_result(self.context) def update_ids(self, src_stream_id, dest_stream_id): self.src_to_dest_ids[src_stream_id] = dest_stream_id self.dest_to_src_ids[dest_stream_id] = src_stream_id def on_request(self, stream_id, request, priority_updated): dest_stream_id = self.dest_conn.get_next_available_stream_id() self.update_ids(stream_id, dest_stream_id) if priority_updated: priority_weight = priority_updated.weight priority_exclusive = priority_updated.exclusive priority_depends_on = self.safe_mapping_id( self.src_to_dest_ids, priority_updated.depends_on) else: priority_weight = None priority_exclusive = None priority_depends_on = None stream = Stream(self, self.context, stream_id, dest_stream_id) stream.on_request( request, priority_weight=priority_weight, priority_exclusive=priority_exclusive, priority_depends_on=priority_depends_on) self.streams[stream_id] = stream def on_push(self, pushed_stream_id, parent_stream_id, request): self.update_ids(pushed_stream_id, pushed_stream_id) target_parent_stream_id = self.dest_to_src_ids[parent_stream_id] stream = Stream(self, self.context, pushed_stream_id, pushed_stream_id) stream.on_push(request, target_parent_stream_id) self.streams[pushed_stream_id] = stream def on_response(self, stream_id, response): src_stream_id = self.dest_to_src_ids[stream_id] self.streams[src_stream_id].on_response(response) self.on_finish(src_stream_id) def on_finish(self, src_stream_id): stream = self.streams[src_stream_id] self.interceptor.publish( layer_context=self.context, request=stream.request, response=stream.response) del self.streams[src_stream_id] if self.context.mode == "replay": self.src_stream.close() self.dest_stream.close() def on_src_settings(self, changed_settings): new_settings = { id: cs.new_value for (id, cs) in changed_settings.iteritems() } self.dest_conn.send_update_settings(new_settings) def on_dest_settings(self, changed_settings): new_settings = { id: cs.new_value for (id, cs) in changed_settings.iteritems() } self.src_conn.send_update_settings(new_settings) def on_src_window_updates(self, stream_id, delta): target_stream_id = self.safe_mapping_id(self.src_to_dest_ids, stream_id) self.dest_conn.send_window_updates(target_stream_id, delta) def on_dest_window_updates(self, stream_id, delta): target_stream_id = self.safe_mapping_id(self.dest_to_src_ids, stream_id) self.src_conn.send_window_updates(target_stream_id, delta) def on_src_priority_updates(self, stream_id, depends_on, weight, exclusive): target_stream_id = self.safe_mapping_id( self.src_to_dest_ids, stream_id) target_depends_on = self.safe_mapping_id( self.src_to_dest_ids, depends_on) if target_stream_id: self.dest_conn.send_priority_updates( target_stream_id, target_depends_on, weight, exclusive) def safe_mapping_id(self, ids, stream_id): if stream_id in ids: return ids[stream_id] return 0 def on_src_reset(self, stream_id, error_code): target_stream_id = self.src_to_dest_ids[stream_id] self.dest_conn.send_reset(target_stream_id, error_code) def on_dest_reset(self, stream_id, error_code): target_stream_id = self.dest_to_src_ids[stream_id] self.src_conn.send_reset(target_stream_id, error_code) def on_src_terminate(self, additional_data, error_code, last_stream_id): self.dest_conn.send_terminate( error_code=error_code, additional_data=additional_data, last_stream_id=last_stream_id) def on_dest_terminate(self, additional_data, error_code, last_stream_id): self.src_conn.send_terminate( error_code=error_code, additional_data=additional_data, last_stream_id=last_stream_id)
class TestHttp2Layer(ProxyAsyncTestCase): def setUp(self): super(TestHttp2Layer, self).setUp() self.asyncSetUp() self.src_events = [] self.dest_events = [] @gen_test def asyncSetUp(self): self.client_stream, src_stream = yield self.create_iostream_pair() dest_stream, self.server_stream = yield self.create_iostream_pair() server_state = ServerContext( config={}, interceptor=mock.Mock(**{ "publish.return_value": None, "request.return_value": None, "response.return_value": None, }) ) self.http_layer = Http2Layer( server_state, LayerContext(mode="socks", src_stream=src_stream, dest_stream=dest_stream)) def record_src_event(self, *args): self.src_events.append(args) def record_dest_event(self, *args): self.dest_events.append(args) def ignore_event(self, *args): pass @coroutine def read_until_new_event(self, conn, events): curr_count = len(events) while curr_count == len(events): yield conn.read_bytes() @gen_test def test_req_and_resp(self): self.client_conn = Connection( self.client_stream, client_side=True, on_response=self.record_src_event, on_unhandled=self.ignore_event) self.server_conn = Connection( self.server_stream, client_side=False, on_request=self.record_dest_event, on_unhandled=self.ignore_event) result_future = self.http_layer.process_and_return_context() self.client_conn.initiate_connection() self.server_conn.initiate_connection() self.client_conn.send_request( 1, HttpRequest(headers=[ (":method", "GET"), (":path", "/"), ("aaa", "bbb")])) yield self.read_until_new_event(self.server_conn, self.dest_events) self.server_conn.send_response( 1, HttpResponse(headers=[(":status", "200"), ("aaa", "bbb")], body=b"ccc")) yield self.read_until_new_event(self.client_conn, self.src_events) self.client_stream.close() self.server_stream.close() result = yield result_future self.assertIsNotNone(result) self.assertIsInstance(result, LayerContext) self.assertEqual(len(self.src_events), 1) stream_id, response = self.src_events[0] self.assertEqual(stream_id, 1) self.assertEqual(response.code, "200") self.assertEqual(response.version, "HTTP/2") self.assertEqual( response.headers, HttpHeaders([(":status", "200"), ("aaa", "bbb")])) self.assertEqual(response.body, b"ccc") self.assertEqual(len(self.dest_events), 1) stream_id, request, _ = self.dest_events[0] self.assertEqual(stream_id, 1) self.assertEqual(request.method, "GET") self.assertEqual(request.path, "/") self.assertEqual(request.version, "HTTP/2") self.assertEqual( request.headers, HttpHeaders([(":method", "GET"), (":path", "/"), ("aaa", "bbb")])) @gen_test def test_req_with_priority_updated(self): self.client_conn = Connection( self.client_stream, client_side=True, on_unhandled=self.ignore_event) self.server_conn = Connection( self.server_stream, client_side=False, on_request=self.record_dest_event, on_unhandled=self.ignore_event) result_future = self.http_layer.process_and_return_context() self.client_conn.initiate_connection() self.server_conn.initiate_connection() self.client_conn.send_request( 1, HttpRequest(headers=[ (":method", "GET"), (":path", "/"), ("aaa", "bbb")]), priority_weight=10, priority_depends_on=0, priority_exclusive=False) yield self.read_until_new_event(self.server_conn, self.dest_events) self.client_stream.close() self.server_stream.close() yield result_future self.assertEqual(len(self.dest_events), 1) stream_id, request, priority_updated = self.dest_events[0] self.assertEqual(stream_id, 1) self.assertEqual(request.method, "GET") self.assertEqual(request.path, "/") self.assertEqual(request.version, "HTTP/2") self.assertEqual( request.headers, HttpHeaders([(":method", "GET"), (":path", "/"), ("aaa", "bbb")])) self.assertIsNotNone(priority_updated) self.assertEqual(priority_updated.weight, 10) self.assertEqual(priority_updated.exclusive, False) self.assertEqual(priority_updated.depends_on, 0) @gen_test def test_push(self): self.client_conn = Connection( self.client_stream, client_side=True, on_response=self.record_src_event, on_push=self.record_src_event, on_unhandled=self.ignore_event) self.server_conn = Connection( self.server_stream, client_side=False, on_request=self.record_dest_event, on_unhandled=self.ignore_event) result_future = self.http_layer.process_and_return_context() self.client_conn.initiate_connection() self.server_conn.initiate_connection() self.client_conn.send_request( 1, HttpRequest(headers=[ (":method", "GET"), (":path", "/"), ("aaa", "bbb")])) yield self.read_until_new_event(self.server_conn, self.dest_events) self.server_conn.send_pushed_stream(1, 2, HttpRequest( headers=[(":method", "GET"), (":path", "/resource")])) yield self.read_until_new_event(self.client_conn, self.src_events) self.server_conn.send_response( 2, HttpResponse(headers=[(":status", "200"), ("aaa", "bbb")], body=b"ccc")) yield self.read_until_new_event(self.client_conn, self.src_events) self.client_stream.close() self.server_stream.close() yield result_future self.assertEqual(len(self.src_events), 2) stream_id, parent_stream_id, request = self.src_events[0] self.assertEqual(stream_id, 2) self.assertEqual(parent_stream_id, 1) self.assertEqual(request.method, "GET") self.assertEqual(request.path, "/resource") self.assertEqual(request.version, "HTTP/2") self.assertEqual( request.headers, HttpHeaders([(":method", "GET"), (":path", "/resource")])) stream_id, response = self.src_events[1] self.assertEqual(stream_id, 2) self.assertEqual(response.code, "200") self.assertEqual(response.version, "HTTP/2") self.assertEqual( response.headers, HttpHeaders([(":status", "200"), ("aaa", "bbb")])) @gen_test def test_window_updates(self): self.client_conn = Connection( self.client_stream, client_side=True, on_window_updates=self.record_src_event, on_unhandled=self.ignore_event) self.server_conn = Connection( self.server_stream, client_side=False, on_window_updates=self.record_dest_event, on_unhandled=self.ignore_event) result_future = self.http_layer.process_and_return_context() self.client_conn.initiate_connection() self.server_conn.initiate_connection() self.client_conn.send_window_updates(0, 100) yield self.read_until_new_event(self.server_conn, self.dest_events) self.client_conn.send_request( 1, HttpRequest(headers=[ (":method", "GET"), (":path", "/"), ("aaa", "bbb")])) self.client_conn.send_window_updates(1, 200) yield self.read_until_new_event(self.server_conn, self.dest_events) self.server_conn.send_window_updates(1, 300) yield self.read_until_new_event(self.client_conn, self.src_events) self.client_stream.close() self.server_stream.close() yield result_future print self.src_events self.assertEqual(len(self.src_events), 1) self.assertEqual(self.src_events[0], (1, 300)) self.assertEqual(len(self.dest_events), 2) self.assertEqual(self.dest_events[0], (0, 100)) self.assertEqual(self.dest_events[1], (1, 200)) @gen_test def test_priority_updated(self): self.client_conn = Connection( self.client_stream, client_side=True, on_unhandled=self.ignore_event) self.server_conn = Connection( self.server_stream, client_side=False, on_priority_updates=self.record_dest_event, on_unhandled=self.ignore_event) result_future = self.http_layer.process_and_return_context() self.client_conn.initiate_connection() self.server_conn.initiate_connection() self.client_conn.send_request( 1, HttpRequest(headers=[ (":method", "GET"), (":path", "/"), ("aaa", "bbb")])) self.client_conn.send_priority_updates(1, 0, 10, False) yield self.read_until_new_event(self.server_conn, self.dest_events) self.client_stream.close() self.server_stream.close() yield result_future self.assertEqual(len(self.dest_events), 1) self.assertEqual(self.dest_events[0], (1, 0, 10, False)) @gen_test def test_reset(self): self.client_conn = Connection( self.client_stream, client_side=True, on_reset=self.record_src_event, on_unhandled=self.ignore_event) self.server_conn = Connection( self.server_stream, client_side=False, on_request=self.record_dest_event, on_reset=self.record_dest_event, on_unhandled=self.ignore_event) result_future = self.http_layer.process_and_return_context() self.client_conn.initiate_connection() self.server_conn.initiate_connection() self.client_conn.send_request( 1, HttpRequest(headers=[ (":method", "GET"), (":path", "/"), ("aaa", "bbb")])) yield self.read_until_new_event(self.server_conn, self.dest_events) self.client_conn.send_reset(1, 0) yield self.read_until_new_event(self.server_conn, self.dest_events) self.client_conn.send_request( 3, HttpRequest(headers=[ (":method", "GET"), (":path", "/"), ("aaa", "bbb")])) yield self.read_until_new_event(self.server_conn, self.dest_events) self.server_conn.send_reset(3, 0) yield self.read_until_new_event(self.client_conn, self.src_events) self.client_stream.close() self.server_stream.close() yield result_future self.assertEqual(len(self.src_events), 1) self.assertEqual(self.src_events[0], (3, 0)) self.assertEqual(len(self.dest_events), 3) # NOTE: req, reset, req self.assertEqual(self.dest_events[1], (1, 0)) @gen_test def test_src_send_terminate(self): self.client_conn = Connection( self.client_stream, client_side=True, on_unhandled=self.ignore_event) self.server_conn = Connection( self.server_stream, client_side=False, on_terminate=self.record_dest_event, on_unhandled=self.ignore_event) result_future = self.http_layer.process_and_return_context() self.client_conn.initiate_connection() self.server_conn.initiate_connection() self.client_conn.send_terminate() yield self.read_until_new_event(self.server_conn, self.dest_events) self.client_stream.close() self.server_stream.close() yield result_future self.assertEqual(len(self.dest_events), 1) self.assertEqual(self.dest_events[0], (None, 0, 0)) @gen_test def test_dest_send_terminate(self): self.client_conn = Connection( self.client_stream, client_side=True, on_terminate=self.record_src_event, on_settings=self.record_src_event, on_unhandled=self.ignore_event) self.server_conn = Connection( self.server_stream, client_side=False, on_unhandled=self.ignore_event) result_future = self.http_layer.process_and_return_context() self.client_conn.initiate_connection() self.server_conn.initiate_connection() # NOTE: because hyper-h2 will always send SettingsChanged when init # Than client will receive two setting frame from destination and server yield self.read_until_new_event(self.client_conn, self.src_events) yield self.read_until_new_event(self.client_conn, self.src_events) self.server_conn.send_terminate() yield self.read_until_new_event(self.client_conn, self.src_events) self.client_stream.close() self.server_stream.close() yield result_future self.assertEqual(len(self.src_events), 3) self.assertEqual(self.src_events[2], (None, 0, 0)) @gen_test def test_safe_mapping_id(self): self.client_conn = Connection( self.client_stream, client_side=True, on_unhandled=self.ignore_event) self.server_conn = Connection( self.server_stream, client_side=False, on_request=self.record_dest_event, on_unhandled=self.ignore_event) result_future = self.http_layer.process_and_return_context() self.client_conn.initiate_connection() self.server_conn.initiate_connection() self.assertEqual( self.http_layer.safe_mapping_id(self.http_layer.src_to_dest_ids, 1), 0) self.client_conn.send_request( 1, HttpRequest(headers=[ (":method", "GET"), (":path", "/"), ("aaa", "bbb")])) yield self.read_until_new_event(self.server_conn, self.dest_events) self.assertEqual( self.http_layer.safe_mapping_id(self.http_layer.src_to_dest_ids, 1), 1) self.client_stream.close() self.server_stream.close() yield result_future @gen_test def test_replay(self): self.http_layer.context.mode = "replay" self.client_conn = Connection( self.client_stream, client_side=True, on_unhandled=self.ignore_event) self.server_conn = Connection( self.server_stream, client_side=False, on_request=self.record_dest_event, on_unhandled=self.ignore_event) result_future = self.http_layer.process_and_return_context() self.client_conn.initiate_connection() self.server_conn.initiate_connection() self.client_conn.send_request( 1, HttpRequest(headers=[ (":method", "GET"), (":path", "/"), ("aaa", "bbb")])) yield self.read_until_new_event(self.server_conn, self.dest_events) self.server_conn.send_response( 1, HttpResponse(headers=[(":status", "200"), ("aaa", "bbb")], body=b"ccc")) result = yield result_future self.assertIsNotNone(result) self.assertIsInstance(result, LayerContext) self.assertEqual(len(self.dest_events), 1) stream_id, request, _ = self.dest_events[0] self.assertEqual(stream_id, 1) self.assertEqual(request.method, "GET") self.assertEqual(request.path, "/") self.assertEqual(request.version, "HTTP/2") self.assertEqual( request.headers, HttpHeaders([(":method", "GET"), (":path", "/"), ("aaa", "bbb")])) def tearDown(self): self.client_stream.close() self.server_stream.close() self.http_layer.src_stream.close() self.http_layer.dest_stream.close()