def test_copy(self): f = tflow.twebsocketflow() f.get_state() f2 = f.copy() a = f.get_state() b = f2.get_state() del a["id"] del b["id"] assert a == b assert not f == f2 assert f is not f2 assert f.client_key == f2.client_key assert f.client_protocol == f2.client_protocol assert f.client_extensions == f2.client_extensions assert f.server_accept == f2.server_accept assert f.server_protocol == f2.server_protocol assert f.server_extensions == f2.server_extensions assert f.messages is not f2.messages assert f.handshake_flow is not f2.handshake_flow for m in f.messages: m2 = m.copy() m2.set_state(m2.get_state()) assert m is not m2 assert m.get_state() == m2.get_state() f = tflow.twebsocketflow(err=True) f2 = f.copy() assert f is not f2 assert f.handshake_flow is not f2.handshake_flow assert f.error.get_state() == f2.error.get_state() assert f.error is not f2.error
def test_serialize(self): b = io.BytesIO() d = tflow.twebsocketflow().get_state() tnetstring.dump(d, b) assert b.getvalue() b = io.BytesIO() d = tflow.twebsocketflow().handshake_flow.get_state() tnetstring.dump(d, b) assert b.getvalue()
def test_match(self): f = tflow.twebsocketflow() assert not flowfilter.match("~b nonexistent", f) assert flowfilter.match(None, f) assert not flowfilter.match("~b nonexistent", f) f = tflow.twebsocketflow(err=True) assert flowfilter.match("~e", f) with pytest.raises(ValueError): flowfilter.match("~", f)
def test_kill(self): f = tflow.twebsocketflow() with pytest.raises(ControlException): f.intercept() f.resume() f.kill() f = tflow.twebsocketflow() f.intercept() assert f.killable f.kill() assert not f.killable
def test_kill(self): f = tflow.twebsocketflow() with pytest.raises(ControlException): f.intercept() f.resume() f.kill() f = tflow.twebsocketflow() f.intercept() assert f.killable f.kill() assert not f.killable assert f.reply.value == Kill
def test_websocket(tmpdir): sa = save.Save() with taddons.context(sa) as tctx: p = str(tmpdir.join("foo")) tctx.configure(sa, save_stream_file=p) f = tflow.twebsocketflow() sa.request(f) sa.websocket_end(f) f = tflow.twebsocketflow() sa.request(f) sa.websocket_error(f) tctx.configure(sa, save_stream_file=None) assert len(rd(p)) == 2
async def test_inject_fail() -> None: ps = Proxyserver() with taddons.context(ps) as tctx: ps.inject_websocket( tflow.tflow(), True, b"test" ) await tctx.master.await_log("Cannot inject WebSocket messages into non-WebSocket flows.", level="warn") ps.inject_tcp( tflow.tflow(), True, b"test" ) await tctx.master.await_log("Cannot inject TCP messages into non-TCP flows.", level="warn") ps.inject_websocket( tflow.twebsocketflow(), True, b"test" ) await tctx.master.await_log("Flow is not from a live connection.", level="warn") ps.inject_websocket( tflow.ttcpflow(), True, b"test" ) await tctx.master.await_log("Flow is not from a live connection.", level="warn")
def test_websocket(): sio = io.StringIO() d = dumper.Dumper(sio) with taddons.context(d) as ctx: ctx.configure(d, flow_detail=3, showhost=True) f = tflow.twebsocketflow() d.websocket_message(f) assert "it's me" in sio.getvalue() sio.truncate(0) d.websocket_end(f) assert "WebSocket connection closed by" in sio.getvalue() f = tflow.twebsocketflow(client_conn=True, err=True) d.websocket_error(f) assert "Error in WebSocket" in sio.getvalue()
def test_websocket(): sio = io.StringIO() d = dumper.Dumper(sio) with taddons.context(options=options.Options()) as ctx: ctx.configure(d, flow_detail=3, showhost=True) f = tflow.twebsocketflow() d.websocket_message(f) assert "it's me" in sio.getvalue() sio.truncate(0) d.websocket_end(f) assert "WebSocket connection closed by" in sio.getvalue() f = tflow.twebsocketflow(client_conn=True, err=True) d.websocket_error(f) assert "Error in WebSocket" in sio.getvalue()
def test_simple(): sa = streambodies.StreamBodies() with taddons.context(sa) as tctx: with pytest.raises(exceptions.OptionsError): tctx.configure(sa, stream_large_bodies="invalid") tctx.configure(sa, stream_large_bodies="10") f = tflow.tflow() f.request.content = b"" f.request.headers["Content-Length"] = "1024" assert not f.request.stream sa.requestheaders(f) assert f.request.stream f = tflow.tflow(resp=True) f.response.content = b"" f.response.headers["Content-Length"] = "1024" assert not f.response.stream sa.responseheaders(f) assert f.response.stream f = tflow.tflow(resp=True) f.response.headers["content-length"] = "invalid" tctx.cycle(sa, f) tctx.configure(sa, stream_websockets=True) f = tflow.twebsocketflow() assert not f.stream sa.websocket_start(f) assert f.stream
def test_simple(): sa = streambodies.StreamBodies() with taddons.context() as tctx: with pytest.raises(exceptions.OptionsError): tctx.configure(sa, stream_large_bodies = "invalid") tctx.configure(sa, stream_large_bodies = "10") f = tflow.tflow() f.request.content = b"" f.request.headers["Content-Length"] = "1024" assert not f.request.stream sa.requestheaders(f) assert f.request.stream f = tflow.tflow(resp=True) f.response.content = b"" f.response.headers["Content-Length"] = "1024" assert not f.response.stream sa.responseheaders(f) assert f.response.stream f = tflow.tflow(resp=True) f.response.headers["content-length"] = "invalid" tctx.cycle(sa, f) tctx.configure(sa, stream_websockets = True) f = tflow.twebsocketflow() assert not f.stream sa.websocket_start(f) assert f.stream
async def test_load_websocket_flow(self): opts = options.Options(mode="reverse:https://use-this-domain") s = tservers.TestState() with taddons.context(s, options=opts) as ctx: f = tflow.twebsocketflow() await ctx.master.load_flow(f.handshake_flow) await ctx.master.load_flow(f) assert s.flows[0].request.host == "use-this-domain" assert s.flows[1].handshake_flow == f.handshake_flow assert len(s.flows[1].messages) == len(f.messages)
def test_inject_message(self): f = tflow.twebsocketflow() with pytest.raises(ValueError): f.inject_message(None, 'foobar') f.inject_message(f.client_conn, 'foobar') assert f._inject_messages_client.qsize() == 1 f.inject_message(f.server_conn, 'foobar') assert f._inject_messages_client.qsize() == 1
def test_websocket(tmpdir): sa = save.Save() with taddons.context(sa) as tctx: p = str(tmpdir.join("foo")) tctx.configure(sa, save_stream_file=p) f = tflow.twebsocketflow() sa.websocket_start(f) sa.websocket_end(f) tctx.configure(sa, save_stream_file=None) assert rd(p)
def test_websocket_flow(err): f = tflow.twebsocketflow(err=err) i = eventsequence.iterate(f) assert next(i) == ("websocket_start", f) assert len(f.messages) == 0 assert next(i) == ("websocket_message", f) assert len(f.messages) == 1 assert next(i) == ("websocket_message", f) assert len(f.messages) == 2 if err: assert next(i) == ("websocket_error", f) assert next(i) == ("websocket_end", f)
async def test_load_websocket_flow(self): opts = options.Options( mode="reverse:https://use-this-domain" ) s = tservers.TestState() with taddons.context(s, options=opts) as ctx: f = tflow.twebsocketflow() await ctx.master.load_flow(f.handshake_flow) await ctx.master.load_flow(f) assert s.flows[0].request.host == "use-this-domain" assert s.flows[1].handshake_flow == f.handshake_flow assert len(s.flows[1].messages) == len(f.messages)
async def test_start_stop(tdata): cp = ClientPlayback() with taddons.context(cp) as tctx: cp.start_replay([tflow.tflow()]) assert cp.count() == 1 cp.start_replay([tflow.twebsocketflow()]) await tctx.master.await_log("Can only replay HTTP flows.", level="warn") assert cp.count() == 1 cp.stop_replay() assert cp.count() == 0
def test_load_websocket_flow(self): s = tservers.TestState() opts = options.Options( mode="reverse:https://use-this-domain" ) fm = master.Master(opts) fm.addons.add(s) f = tflow.twebsocketflow() fm.load_flow(f.handshake_flow) fm.load_flow(f) assert s.flows[0].request.host == "use-this-domain" assert s.flows[1].handshake_flow == f.handshake_flow assert len(s.flows[1].messages) == len(f.messages)
def test_websocket_flow(err): f = tflow.twebsocketflow(err=err) i = eventsequence.iterate(f) assert next(i) == ("websocket_start", f) assert len(f.messages) == 0 assert next(i) == ("websocket_message", f) assert len(f.messages) == 1 assert next(i) == ("websocket_message", f) assert len(f.messages) == 2 assert next(i) == ("websocket_message", f) assert len(f.messages) == 3 if err: assert next(i) == ("websocket_error", f) assert next(i) == ("websocket_end", f)
async def test_start_stop(tdata): cp = ClientPlayback() with taddons.context(cp) as tctx: cp.start_replay([tflow.tflow(live=False)]) assert cp.count() == 1 ws_flow = tflow.twebsocketflow() ws_flow.live = False cp.start_replay([ws_flow]) await tctx.master.await_log("Can't replay WebSocket flows.", level="warn") assert cp.count() == 1 cp.stop_replay() assert cp.count() == 0
def test_websocket(): sio = io.StringIO() d = dumper.Dumper(sio) with taddons.context(d) as ctx: ctx.configure(d, flow_detail=3, showhost=True) f = tflow.twebsocketflow() d.websocket_message(f) assert "it's me" in sio.getvalue() sio.truncate(0) d.websocket_end(f) assert "WebSocket connection closed by" in sio.getvalue() sio.truncate(0) f = tflow.twebsocketflow(err=True) d.websocket_end(f) assert "Error in WebSocket" in sio.getvalue() assert "(reason:" not in sio.getvalue() sio.truncate(0) f = tflow.twebsocketflow(err=True, close_reason='Some lame excuse') d.websocket_end(f) assert "Error in WebSocket" in sio.getvalue() assert "(reason: Some lame excuse)" in sio.getvalue() sio.truncate(0) f = tflow.twebsocketflow(close_code=4000) d.websocket_end(f) assert "UNKNOWN_ERROR=4000" in sio.getvalue() assert "(reason:" not in sio.getvalue() sio.truncate(0) f = tflow.twebsocketflow(close_code=4000, close_reason='I swear I had a reason') d.websocket_end(f) assert "UNKNOWN_ERROR=4000" in sio.getvalue() assert "(reason: I swear I had a reason)" in sio.getvalue()
def test_websocket_flow(err): f = tflow.twebsocketflow(err=err) i = eventsequence.iterate(f) assert isinstance(next(i), layers.websocket.WebsocketStartHook) assert len(f.messages) == 0 assert isinstance(next(i), layers.websocket.WebsocketMessageHook) assert len(f.messages) == 1 assert isinstance(next(i), layers.websocket.WebsocketMessageHook) assert len(f.messages) == 2 assert isinstance(next(i), layers.websocket.WebsocketMessageHook) assert len(f.messages) == 3 if err: assert isinstance(next(i), layers.websocket.WebsocketErrorHook) else: assert isinstance(next(i), layers.websocket.WebsocketEndHook)
def test_websocket_flow(): f = tflow.twebsocketflow() i = eventsequence.iterate(f) assert isinstance(next(i), layers.http.HttpRequestHeadersHook) assert isinstance(next(i), layers.http.HttpRequestHook) assert isinstance(next(i), layers.http.HttpResponseHeadersHook) assert isinstance(next(i), layers.http.HttpResponseHook) assert isinstance(next(i), layers.websocket.WebsocketStartHook) assert len(f.websocket.messages) == 0 assert isinstance(next(i), layers.websocket.WebsocketMessageHook) assert len(f.websocket.messages) == 1 assert isinstance(next(i), layers.websocket.WebsocketMessageHook) assert len(f.websocket.messages) == 2 assert isinstance(next(i), layers.websocket.WebsocketMessageHook) assert len(f.websocket.messages) == 3 assert isinstance(next(i), layers.websocket.WebsocketEndHook)
def flow(self): return tflow.twebsocketflow()
def err(self): return tflow.twebsocketflow(err=True)
def flow(self) -> http.HTTPFlow: return tflow.twebsocketflow()
def test_repr(self): assert repr( tflow.twebsocketflow().websocket) == "<WebSocketData (3 messages)>"
def test_state(self): f = tflow.twebsocketflow() f2 = http.HTTPFlow.from_state(f.get_state()) f2.set_state(f.get_state())
def test_message_kill(self): f = tflow.twebsocketflow() assert not f.messages[-1].killed f.messages[-1].kill() assert f.messages[-1].killed
def test_unsupported_dumps(self): w = tflow.twebsocketflow() with pytest.raises(exceptions.TypeError): protobuf.dumps(w)
def test_repr(self): f = tflow.twebsocketflow() assert f.message_info(f.messages[0]) assert 'WebSocketFlow' in repr(f) assert 'binary message: ' in repr(f.messages[0]) assert 'text message: ' in repr(f.messages[1])
def err(self) -> http.HTTPFlow: return tflow.twebsocketflow(err=True)