diff options
Diffstat (limited to 'test')
-rw-r--r-- | test/mitmproxy/addons/test_check_ca.py | 4 | ||||
-rw-r--r-- | test/mitmproxy/addons/test_clientplayback.py | 170 | ||||
-rw-r--r-- | test/mitmproxy/addons/test_readfile.py | 2 | ||||
-rw-r--r-- | test/mitmproxy/addons/test_save.py | 10 | ||||
-rw-r--r-- | test/mitmproxy/addons/test_script.py | 17 | ||||
-rw-r--r-- | test/mitmproxy/addons/test_view.py | 8 | ||||
-rw-r--r-- | test/mitmproxy/proxy/protocol/test_http_replay.py | 1 | ||||
-rw-r--r-- | test/mitmproxy/proxy/test_server.py | 42 | ||||
-rw-r--r-- | test/mitmproxy/test_addonmanager.py | 2 | ||||
-rw-r--r-- | test/mitmproxy/test_command.py | 19 | ||||
-rw-r--r-- | test/mitmproxy/test_flow.py | 35 | ||||
-rw-r--r-- | test/mitmproxy/tools/web/test_app.py | 9 |
12 files changed, 168 insertions, 151 deletions
diff --git a/test/mitmproxy/addons/test_check_ca.py b/test/mitmproxy/addons/test_check_ca.py index 5e820b6d..27e6f7e6 100644 --- a/test/mitmproxy/addons/test_check_ca.py +++ b/test/mitmproxy/addons/test_check_ca.py @@ -12,11 +12,11 @@ class TestCheckCA: async def test_check_ca(self, expired): msg = 'The mitmproxy certificate authority has expired!' - with taddons.context() as tctx: + a = check_ca.CheckCA() + with taddons.context(a) as tctx: tctx.master.server = mock.MagicMock() tctx.master.server.config.certstore.default_ca.has_expired = mock.MagicMock( return_value = expired ) - a = check_ca.CheckCA() tctx.configure(a) assert await tctx.master.await_log(msg) == expired diff --git a/test/mitmproxy/addons/test_clientplayback.py b/test/mitmproxy/addons/test_clientplayback.py index f172af83..1b385e23 100644 --- a/test/mitmproxy/addons/test_clientplayback.py +++ b/test/mitmproxy/addons/test_clientplayback.py @@ -1,13 +1,16 @@ +import time import pytest -from unittest import mock -from mitmproxy.test import tflow +from mitmproxy.test import tflow, tutils from mitmproxy import io from mitmproxy import exceptions +from mitmproxy.net import http as net_http from mitmproxy.addons import clientplayback from mitmproxy.test import taddons +from .. import tservers + def tdump(path, flows): with open(path, "wb") as f: @@ -21,48 +24,87 @@ class MockThread(): return False -class TestClientPlayback: - def test_playback(self): - cp = clientplayback.ClientPlayback() - with taddons.context(cp) as tctx: - assert cp.count() == 0 - f = tflow.tflow(resp=True) - cp.start_replay([f]) - assert cp.count() == 1 - RP = "mitmproxy.proxy.protocol.http_replay.RequestReplayThread" - with mock.patch(RP) as rp: - assert not cp.current_thread - cp.tick() - assert rp.called - assert cp.current_thread - - cp.flows = [] - cp.current_thread.is_alive.return_value = False - assert cp.count() == 1 - cp.tick() - assert cp.count() == 0 - assert tctx.master.has_event("update") - assert tctx.master.has_event("processing_complete") +class TBase(tservers.HTTPProxyTest): + @staticmethod + def wait_response(flow): + """ + Race condition: We don't want to replay the flow while it is still live. + """ + s = time.time() + while True: + if flow.response or flow.error: + break + time.sleep(0.001) + if time.time() - s > 5: + raise RuntimeError("Flow is live for too long.") - cp.current_thread = MockThread() - cp.tick() - assert cp.current_thread is None + @staticmethod + def reset(f): + f.live = False + f.repsonse = False + f.error = False - cp.start_replay([f]) - cp.stop_replay() - assert not cp.flows + def addons(self): + return [clientplayback.ClientPlayback()] + + def test_replay(self): + cr = self.master.addons.get("clientplayback") - df = tflow.DummyFlow(tflow.tclient_conn(), tflow.tserver_conn(), True) - with pytest.raises(exceptions.CommandError, match="Can't replay live flow."): - cp.start_replay([df]) + assert self.pathod("304").status_code == 304 + assert len(self.master.state.flows) == 1 + l = self.master.state.flows[-1] + assert l.response.status_code == 304 + l.request.path = "/p/305" + cr.start_replay([l]) + self.wait_response(l) + assert l.response.status_code == 305 + # Disconnect error + cr.stop_replay() + self.reset(l) + l.request.path = "/p/305:d0" + cr.start_replay([l]) + self.wait_response(l) + if isinstance(self, tservers.HTTPUpstreamProxyTest): + assert l.response.status_code == 502 + else: + assert l.error + + # # Port error + cr.stop_replay() + self.reset(l) + l.request.port = 1 + # In upstream mode, we get a 502 response from the upstream proxy server. + # In upstream mode with ssl, the replay will fail as we cannot establish + # SSL with the upstream proxy. + cr.start_replay([l]) + self.wait_response(l) + if isinstance(self, tservers.HTTPUpstreamProxyTest): + assert l.response.status_code == 502 + else: + assert l.error + + +class TestHTTPProxy(TBase, tservers.HTTPProxyTest): + pass + + +class TestHTTPSProxy(TBase, tservers.HTTPProxyTest): + ssl = True + + +class TestUpstreamProxy(TBase, tservers.HTTPUpstreamProxyTest): + pass + + +class TestClientPlayback: def test_load_file(self, tmpdir): cp = clientplayback.ClientPlayback() with taddons.context(cp): fpath = str(tmpdir.join("flows")) tdump(fpath, [tflow.tflow(resp=True)]) cp.load_file(fpath) - assert cp.flows + assert cp.count() == 1 with pytest.raises(exceptions.CommandError): cp.load_file("/nonexistent") @@ -71,11 +113,63 @@ class TestClientPlayback: with taddons.context(cp) as tctx: path = str(tmpdir.join("flows")) tdump(path, [tflow.tflow()]) + assert cp.count() == 0 tctx.configure(cp, client_replay=[path]) - cp.configured = False + assert cp.count() == 1 tctx.configure(cp, client_replay=[]) - cp.configured = False - tctx.configure(cp) - cp.configured = False with pytest.raises(exceptions.OptionsError): tctx.configure(cp, client_replay=["nonexistent"]) + + def test_check(self): + cp = clientplayback.ClientPlayback() + with taddons.context(cp): + f = tflow.tflow(resp=True) + f.live = True + assert "live flow" in cp.check(f) + + f = tflow.tflow(resp=True) + f.intercepted = True + assert "intercepted flow" in cp.check(f) + + f = tflow.tflow(resp=True) + f.request = None + assert "missing request" in cp.check(f) + + f = tflow.tflow(resp=True) + f.request.raw_content = None + assert "missing content" in cp.check(f) + + @pytest.mark.asyncio + async def test_playback(self): + cp = clientplayback.ClientPlayback() + with taddons.context(cp) as ctx: + assert cp.count() == 0 + f = tflow.tflow(resp=True) + cp.start_replay([f]) + assert cp.count() == 1 + + cp.stop_replay() + assert cp.count() == 0 + + f.live = True + cp.start_replay([f]) + assert cp.count() == 0 + await ctx.master.await_log("live") + + def test_http2(self): + cp = clientplayback.ClientPlayback() + with taddons.context(cp): + req = tutils.treq( + headers = net_http.Headers( + ( + (b":authority", b"foo"), + (b"header", b"qvalue"), + (b"content-length", b"7") + ) + ) + ) + f = tflow.tflow(req=req) + f.request.http_version = "HTTP/2.0" + cp.start_replay([f]) + assert f.request.http_version == "HTTP/1.1" + assert ":authority" not in f.request.headers diff --git a/test/mitmproxy/addons/test_readfile.py b/test/mitmproxy/addons/test_readfile.py index f7e0c5c5..d22382a8 100644 --- a/test/mitmproxy/addons/test_readfile.py +++ b/test/mitmproxy/addons/test_readfile.py @@ -42,7 +42,7 @@ def corrupt_data(): class TestReadFile: def test_configure(self): rf = readfile.ReadFile() - with taddons.context() as tctx: + with taddons.context(rf) as tctx: tctx.configure(rf, readfile_filter="~q") with pytest.raises(Exception, match="Invalid readfile filter"): tctx.configure(rf, readfile_filter="~~") diff --git a/test/mitmproxy/addons/test_save.py b/test/mitmproxy/addons/test_save.py index 4486ff78..4aa1f648 100644 --- a/test/mitmproxy/addons/test_save.py +++ b/test/mitmproxy/addons/test_save.py @@ -11,7 +11,7 @@ from mitmproxy.addons import view def test_configure(tmpdir): sa = save.Save() - with taddons.context() as tctx: + with taddons.context(sa) as tctx: with pytest.raises(exceptions.OptionsError): tctx.configure(sa, save_stream_file=str(tmpdir)) with pytest.raises(Exception, match="Invalid filter"): @@ -32,7 +32,7 @@ def rd(p): def test_tcp(tmpdir): sa = save.Save() - with taddons.context() as tctx: + with taddons.context(sa) as tctx: p = str(tmpdir.join("foo")) tctx.configure(sa, save_stream_file=p) @@ -45,7 +45,7 @@ def test_tcp(tmpdir): def test_websocket(tmpdir): sa = save.Save() - with taddons.context() as tctx: + with taddons.context(sa) as tctx: p = str(tmpdir.join("foo")) tctx.configure(sa, save_stream_file=p) @@ -73,12 +73,12 @@ def test_save_command(tmpdir): v = view.View() tctx.master.addons.add(v) tctx.master.addons.add(sa) - tctx.master.commands.call_args("save.file", ["@shown", p]) + tctx.master.commands.call_strings("save.file", ["@shown", p]) def test_simple(tmpdir): sa = save.Save() - with taddons.context() as tctx: + with taddons.context(sa) as tctx: p = str(tmpdir.join("foo")) tctx.configure(sa, save_stream_file=p) diff --git a/test/mitmproxy/addons/test_script.py b/test/mitmproxy/addons/test_script.py index c358f019..91637489 100644 --- a/test/mitmproxy/addons/test_script.py +++ b/test/mitmproxy/addons/test_script.py @@ -92,14 +92,13 @@ class TestScript: @pytest.mark.asyncio async def test_simple(self, tdata): - with taddons.context() as tctx: - sc = script.Script( - tdata.path( - "mitmproxy/data/addonscripts/recorder/recorder.py" - ), - True, - ) - tctx.master.addons.add(sc) + sc = script.Script( + tdata.path( + "mitmproxy/data/addonscripts/recorder/recorder.py" + ), + True, + ) + with taddons.context(sc) as tctx: tctx.configure(sc) await tctx.master.await_log("recorder running") rec = tctx.master.addons.get("recorder") @@ -284,7 +283,7 @@ class TestScriptLoader: rec = tdata.path("mitmproxy/data/addonscripts/recorder") sc = script.ScriptLoader() sc.is_running = True - with taddons.context() as tctx: + with taddons.context(sc) as tctx: tctx.configure( sc, scripts = [ diff --git a/test/mitmproxy/addons/test_view.py b/test/mitmproxy/addons/test_view.py index 62a6aeb0..bd724950 100644 --- a/test/mitmproxy/addons/test_view.py +++ b/test/mitmproxy/addons/test_view.py @@ -155,7 +155,7 @@ def test_create(): def test_orders(): v = view.View() - with taddons.context(): + with taddons.context(v): assert v.order_options() @@ -303,7 +303,7 @@ def test_setgetval(): def test_order(): v = view.View() - with taddons.context() as tctx: + with taddons.context(v) as tctx: v.request(tft(method="get", start=1)) v.request(tft(method="put", start=2)) v.request(tft(method="get", start=3)) @@ -434,7 +434,7 @@ def test_signals(): def test_focus_follow(): v = view.View() - with taddons.context() as tctx: + with taddons.context(v) as tctx: console_addon = consoleaddons.ConsoleAddon(tctx.master) tctx.configure(console_addon) tctx.configure(v, console_focus_follow=True, view_filter="~m get") @@ -553,7 +553,7 @@ def test_settings(): def test_configure(): v = view.View() - with taddons.context() as tctx: + with taddons.context(v) as tctx: tctx.configure(v, view_filter="~q") with pytest.raises(Exception, match="Invalid interception filter"): tctx.configure(v, view_filter="~~") diff --git a/test/mitmproxy/proxy/protocol/test_http_replay.py b/test/mitmproxy/proxy/protocol/test_http_replay.py deleted file mode 100644 index 777ab4dd..00000000 --- a/test/mitmproxy/proxy/protocol/test_http_replay.py +++ /dev/null @@ -1 +0,0 @@ -# TODO: write tests diff --git a/test/mitmproxy/proxy/test_server.py b/test/mitmproxy/proxy/test_server.py index 936414ab..914f9184 100644 --- a/test/mitmproxy/proxy/test_server.py +++ b/test/mitmproxy/proxy/test_server.py @@ -31,48 +31,6 @@ class CommonMixin: def test_large(self): assert len(self.pathod("200:b@50k").content) == 1024 * 50 - @staticmethod - def wait_until_not_live(flow): - """ - Race condition: We don't want to replay the flow while it is still live. - """ - s = time.time() - while flow.live: - time.sleep(0.001) - if time.time() - s > 5: - raise RuntimeError("Flow is live for too long.") - - def test_replay(self): - assert self.pathod("304").status_code == 304 - assert len(self.master.state.flows) == 1 - l = self.master.state.flows[-1] - assert l.response.status_code == 304 - l.request.path = "/p/305" - self.wait_until_not_live(l) - rt = self.master.replay_request(l, block=True) - assert l.response.status_code == 305 - - # Disconnect error - l.request.path = "/p/305:d0" - rt = self.master.replay_request(l, block=True) - assert rt - if isinstance(self, tservers.HTTPUpstreamProxyTest): - assert l.response.status_code == 502 - else: - assert l.error - - # Port error - l.request.port = 1 - # In upstream mode, we get a 502 response from the upstream proxy server. - # In upstream mode with ssl, the replay will fail as we cannot establish - # SSL with the upstream proxy. - rt = self.master.replay_request(l, block=True) - assert rt - if isinstance(self, tservers.HTTPUpstreamProxyTest): - assert l.response.status_code == 502 - else: - assert l.error - def test_http(self): f = self.pathod("304") assert f.status_code == 304 diff --git a/test/mitmproxy/test_addonmanager.py b/test/mitmproxy/test_addonmanager.py index 796ae1bd..1ef1521d 100644 --- a/test/mitmproxy/test_addonmanager.py +++ b/test/mitmproxy/test_addonmanager.py @@ -47,7 +47,7 @@ class AOption: def test_command(): with taddons.context() as tctx: tctx.master.addons.add(TAddon("test")) - assert tctx.master.commands.call("test.command") == "here" + assert tctx.master.commands.execute("test.command") == "here" def test_halt(): diff --git a/test/mitmproxy/test_command.py b/test/mitmproxy/test_command.py index 3d0a43f8..ea1017e7 100644 --- a/test/mitmproxy/test_command.py +++ b/test/mitmproxy/test_command.py @@ -242,16 +242,19 @@ def test_simple(): a = TAddon() c.add("one.two", a.cmd1) assert c.commands["one.two"].help == "cmd1 help" - assert(c.call("one.two foo") == "ret foo") + assert(c.execute("one.two foo") == "ret foo") + assert(c.call("one.two", "foo") == "ret foo") with pytest.raises(exceptions.CommandError, match="Unknown"): - c.call("nonexistent") + c.execute("nonexistent") with pytest.raises(exceptions.CommandError, match="Invalid"): - c.call("") + c.execute("") with pytest.raises(exceptions.CommandError, match="argument mismatch"): - c.call("one.two too many args") + c.execute("one.two too many args") + with pytest.raises(exceptions.CommandError, match="Unknown"): + c.call("nonexistent") c.add("empty", a.empty) - c.call("empty") + c.execute("empty") fp = io.StringIO() c.dump(fp) @@ -340,13 +343,13 @@ def test_decorator(): a = TDec() c.collect_commands(a) assert "cmd1" in c.commands - assert c.call("cmd1 bar") == "ret bar" + assert c.execute("cmd1 bar") == "ret bar" assert "empty" in c.commands - assert c.call("empty") is None + assert c.execute("empty") is None with taddons.context() as tctx: tctx.master.addons.add(a) - assert tctx.master.commands.call("cmd1 bar") == "ret bar" + assert tctx.master.commands.execute("cmd1 bar") == "ret bar" def test_verify_arg_signature(): diff --git a/test/mitmproxy/test_flow.py b/test/mitmproxy/test_flow.py index a6f194a7..4956a1d2 100644 --- a/test/mitmproxy/test_flow.py +++ b/test/mitmproxy/test_flow.py @@ -1,17 +1,14 @@ import io -from unittest import mock import pytest -from mitmproxy.test import tflow, tutils, taddons +from mitmproxy.test import tflow, taddons import mitmproxy.io from mitmproxy import flowfilter from mitmproxy import options from mitmproxy.io import tnetstring -from mitmproxy.exceptions import FlowReadException, ReplayException +from mitmproxy.exceptions import FlowReadException from mitmproxy import flow from mitmproxy import http -from mitmproxy.net import http as net_http -from mitmproxy import master from . import tservers @@ -122,34 +119,6 @@ class TestFlowMaster: assert s.flows[1].handshake_flow == f.handshake_flow assert len(s.flows[1].messages) == len(f.messages) - def test_replay(self): - opts = options.Options() - fm = master.Master(opts) - f = tflow.tflow(resp=True) - f.request.content = None - with pytest.raises(ReplayException, match="missing"): - fm.replay_request(f) - - f.request = None - with pytest.raises(ReplayException, match="request"): - fm.replay_request(f) - - f.intercepted = True - with pytest.raises(ReplayException, match="intercepted"): - fm.replay_request(f) - - f.live = True - with pytest.raises(ReplayException, match="live"): - fm.replay_request(f) - - req = tutils.treq(headers=net_http.Headers(((b":authority", b"foo"), (b"header", b"qvalue"), (b"content-length", b"7")))) - f = tflow.tflow(req=req) - f.request.http_version = "HTTP/2.0" - with mock.patch('mitmproxy.proxy.protocol.http_replay.RequestReplayThread.run'): - rt = fm.replay_request(f) - assert rt.f.request.http_version == "HTTP/1.1" - assert ":authority" not in rt.f.request.headers - @pytest.mark.asyncio async def test_all(self): opts = options.Options( diff --git a/test/mitmproxy/tools/web/test_app.py b/test/mitmproxy/tools/web/test_app.py index 00188895..668d3c07 100644 --- a/test/mitmproxy/tools/web/test_app.py +++ b/test/mitmproxy/tools/web/test_app.py @@ -9,7 +9,6 @@ import tornado.testing from tornado import httpclient from tornado import websocket -from mitmproxy import exceptions from mitmproxy import options from mitmproxy.test import tflow from mitmproxy.tools.web import app @@ -186,13 +185,9 @@ class TestApp(tornado.testing.AsyncHTTPTestCase): assert not f._backup def test_flow_replay(self): - with mock.patch("mitmproxy.master.Master.replay_request") as replay_request: + with mock.patch("mitmproxy.command.CommandManager.call") as replay_call: assert self.fetch("/flows/42/replay", method="POST").code == 200 - assert replay_request.called - replay_request.side_effect = exceptions.ReplayException( - "out of replays" - ) - assert self.fetch("/flows/42/replay", method="POST").code == 400 + assert replay_call.called def test_flow_content(self): f = self.view.get_by_id("42") |