diff options
Diffstat (limited to 'test')
21 files changed, 310 insertions, 240 deletions
diff --git a/test/helper_tools/dumperview.py b/test/helper_tools/dumperview.py index be56fe14..d417d767 100755 --- a/test/helper_tools/dumperview.py +++ b/test/helper_tools/dumperview.py @@ -4,12 +4,12 @@ import click from mitmproxy.addons import dumper from mitmproxy.test import tflow from mitmproxy.test import taddons -from mitmproxy.tools import dump +from mitmproxy.tools import options def show(flow_detail, flows): d = dumper.Dumper() - with taddons.context(options=dump.Options()) as ctx: + with taddons.context(options=options.Options()) as ctx: ctx.configure(d, flow_detail=flow_detail) for f in flows: ctx.cycle(d, f) diff --git a/test/mitmproxy/addons/test_core.py b/test/mitmproxy/addons/test_core.py new file mode 100644 index 00000000..7b9e9614 --- /dev/null +++ b/test/mitmproxy/addons/test_core.py @@ -0,0 +1,43 @@ +from mitmproxy import exceptions +from mitmproxy.addons import core +from mitmproxy.test import taddons +import pytest +from unittest import mock + + +def test_simple(): + sa = core.Core() + with taddons.context() as tctx: + with pytest.raises(exceptions.OptionsError): + tctx.configure(sa, body_size_limit = "invalid") + tctx.configure(sa, body_size_limit = "1m") + assert tctx.options._processed["body_size_limit"] + + with pytest.raises(exceptions.OptionsError, match="mutually exclusive"): + tctx.configure( + sa, + add_upstream_certs_to_client_chain = True, + upstream_cert = False + ) + with pytest.raises(exceptions.OptionsError, match="Invalid mode"): + tctx.configure( + sa, + mode = "Flibble" + ) + + +@mock.patch("mitmproxy.platform.original_addr", None) +def test_no_transparent(): + sa = core.Core() + with taddons.context() as tctx: + with pytest.raises(Exception, match="Transparent mode not supported"): + tctx.configure(sa, mode = "transparent") + + +@mock.patch("mitmproxy.platform.original_addr") +def test_modes(m): + sa = core.Core() + with taddons.context() as tctx: + tctx.configure(sa, mode = "reverse:http://localhost") + with pytest.raises(Exception, match="Invalid mode"): + tctx.configure(sa, mode = "reverse:") diff --git a/test/mitmproxy/addons/test_dumper.py b/test/mitmproxy/addons/test_dumper.py index 22d2c2c6..47374617 100644 --- a/test/mitmproxy/addons/test_dumper.py +++ b/test/mitmproxy/addons/test_dumper.py @@ -9,13 +9,13 @@ from mitmproxy.test import tutils from mitmproxy.addons import dumper from mitmproxy import exceptions -from mitmproxy.tools import dump from mitmproxy import http +from mitmproxy import options def test_configure(): d = dumper.Dumper() - with taddons.context(options=dump.Options()) as ctx: + with taddons.context(options=options.Options()) as ctx: ctx.configure(d, filtstr="~b foo") assert d.filter @@ -34,7 +34,7 @@ def test_configure(): def test_simple(): sio = io.StringIO() d = dumper.Dumper(sio) - with taddons.context(options=dump.Options()) as ctx: + with taddons.context(options=options.Options()) as ctx: ctx.configure(d, flow_detail=0) d.response(tflow.tflow(resp=True)) assert not sio.getvalue() @@ -103,7 +103,7 @@ def test_echo_body(): sio = io.StringIO() d = dumper.Dumper(sio) - with taddons.context(options=dump.Options()) as ctx: + with taddons.context(options=options.Options()) as ctx: ctx.configure(d, flow_detail=3) d._echo_message(f.response) t = sio.getvalue() @@ -113,7 +113,7 @@ def test_echo_body(): def test_echo_request_line(): sio = io.StringIO() d = dumper.Dumper(sio) - with taddons.context(options=dump.Options()) as ctx: + with taddons.context(options=options.Options()) as ctx: ctx.configure(d, flow_detail=3, showhost=True) f = tflow.tflow(client_conn=None, server_conn=True, resp=True) f.request.is_replay = True @@ -148,7 +148,7 @@ class TestContentView: view_auto.side_effect = exceptions.ContentViewException("") sio = io.StringIO() d = dumper.Dumper(sio) - with taddons.context(options=dump.Options()) as ctx: + with taddons.context(options=options.Options()) as ctx: ctx.configure(d, flow_detail=4, verbosity=3) d.response(tflow.tflow()) assert "Content viewer failed" in ctx.master.event_log[0][1] @@ -157,7 +157,7 @@ class TestContentView: def test_tcp(): sio = io.StringIO() d = dumper.Dumper(sio) - with taddons.context(options=dump.Options()) as ctx: + with taddons.context(options=options.Options()) as ctx: ctx.configure(d, flow_detail=3, showhost=True) f = tflow.ttcpflow() d.tcp_message(f) @@ -172,7 +172,7 @@ def test_tcp(): def test_websocket(): sio = io.StringIO() d = dumper.Dumper(sio) - with taddons.context(options=dump.Options()) as ctx: + with taddons.context(options=options.Options()) as ctx: ctx.configure(d, flow_detail=3, showhost=True) f = tflow.twebsocketflow() d.websocket_message(f) diff --git a/test/mitmproxy/addons/test_intercept.py b/test/mitmproxy/addons/test_intercept.py index cf5ba6e8..465e6433 100644 --- a/test/mitmproxy/addons/test_intercept.py +++ b/test/mitmproxy/addons/test_intercept.py @@ -7,15 +7,9 @@ from mitmproxy.test import taddons from mitmproxy.test import tflow -class Options(options.Options): - def __init__(self, *, intercept=None, **kwargs): - self.intercept = intercept - super().__init__(**kwargs) - - def test_simple(): r = intercept.Intercept() - with taddons.context(options=Options()) as tctx: + with taddons.context(options=options.Options()) as tctx: assert not r.filt tctx.configure(r, intercept="~q") assert r.filt diff --git a/test/mitmproxy/addons/test_proxyauth.py b/test/mitmproxy/addons/test_proxyauth.py index dd5829ab..14782755 100644 --- a/test/mitmproxy/addons/test_proxyauth.py +++ b/test/mitmproxy/addons/test_proxyauth.py @@ -28,40 +28,43 @@ def test_configure(): up = proxyauth.ProxyAuth() with taddons.context() as ctx: with pytest.raises(exceptions.OptionsError): - ctx.configure(up, auth_singleuser="foo") + ctx.configure(up, proxyauth="foo") - ctx.configure(up, auth_singleuser="foo:bar") + ctx.configure(up, proxyauth="foo:bar") assert up.singleuser == ["foo", "bar"] - ctx.configure(up, auth_singleuser=None) + ctx.configure(up, proxyauth=None) assert up.singleuser is None - ctx.configure(up, auth_nonanonymous=True) + ctx.configure(up, proxyauth="any") assert up.nonanonymous - ctx.configure(up, auth_nonanonymous=False) + ctx.configure(up, proxyauth=None) assert not up.nonanonymous with pytest.raises(exceptions.OptionsError): - ctx.configure(up, auth_htpasswd=tutils.test_data.path("mitmproxy/net/data/server.crt")) + ctx.configure( + up, + proxyauth= "@" + tutils.test_data.path("mitmproxy/net/data/server.crt") + ) with pytest.raises(exceptions.OptionsError): - ctx.configure(up, auth_htpasswd="nonexistent") + ctx.configure(up, proxyauth="@nonexistent") ctx.configure( up, - auth_htpasswd=tutils.test_data.path( + proxyauth= "@" + tutils.test_data.path( "mitmproxy/net/data/htpasswd" ) ) assert up.htpasswd assert up.htpasswd.check_password("test", "test") assert not up.htpasswd.check_password("test", "foo") - ctx.configure(up, auth_htpasswd=None) + ctx.configure(up, proxyauth=None) assert not up.htpasswd with pytest.raises(exceptions.OptionsError): - ctx.configure(up, auth_nonanonymous=True, mode="transparent") + ctx.configure(up, proxyauth="any", mode="transparent") with pytest.raises(exceptions.OptionsError): - ctx.configure(up, auth_nonanonymous=True, mode="socks5") + ctx.configure(up, proxyauth="any", mode="socks5") ctx.configure(up, mode="regular") assert up.mode == "regular" @@ -70,7 +73,7 @@ def test_configure(): def test_check(): up = proxyauth.ProxyAuth() with taddons.context() as ctx: - ctx.configure(up, auth_nonanonymous=True, mode="regular") + ctx.configure(up, proxyauth="any", mode="regular") f = tflow.tflow() assert not up.check(f) f.request.headers["Proxy-Authorization"] = proxyauth.mkauth( @@ -86,18 +89,17 @@ def test_check(): ) assert not up.check(f) - ctx.configure(up, auth_nonanonymous=False, auth_singleuser="test:test") + ctx.configure(up, proxyauth="test:test") f.request.headers["Proxy-Authorization"] = proxyauth.mkauth( "test", "test" ) assert up.check(f) - ctx.configure(up, auth_nonanonymous=False, auth_singleuser="test:foo") + ctx.configure(up, proxyauth="test:foo") assert not up.check(f) ctx.configure( up, - auth_singleuser=None, - auth_htpasswd=tutils.test_data.path( + proxyauth="@" + tutils.test_data.path( "mitmproxy/net/data/htpasswd" ) ) @@ -114,7 +116,7 @@ def test_check(): def test_authenticate(): up = proxyauth.ProxyAuth() with taddons.context() as ctx: - ctx.configure(up, auth_nonanonymous=True, mode="regular") + ctx.configure(up, proxyauth="any", mode="regular") f = tflow.tflow() assert not f.response @@ -147,7 +149,7 @@ def test_authenticate(): def test_handlers(): up = proxyauth.ProxyAuth() with taddons.context() as ctx: - ctx.configure(up, auth_nonanonymous=True, mode="regular") + ctx.configure(up, proxyauth="any", mode="regular") f = tflow.tflow() assert not f.response diff --git a/test/mitmproxy/addons/test_replace.py b/test/mitmproxy/addons/test_replace.py index 126c6e3d..8c280c51 100644 --- a/test/mitmproxy/addons/test_replace.py +++ b/test/mitmproxy/addons/test_replace.py @@ -22,11 +22,11 @@ class TestReplace: def test_configure(self): r = replace.Replace() with taddons.context() as tctx: - tctx.configure(r, replacements=[("one", "two", "three")]) + tctx.configure(r, replacements=["one/two/three"]) with pytest.raises(Exception, match="Invalid filter pattern"): - tctx.configure(r, replacements=[("~b", "two", "three")]) + tctx.configure(r, replacements=["/~b/two/three"]) with pytest.raises(Exception, match="Invalid regular expression"): - tctx.configure(r, replacements=[("foo", "+", "three")]) + tctx.configure(r, replacements=["/foo/+/three"]) tctx.configure(r, replacements=["/a/b/c/"]) def test_simple(self): @@ -35,8 +35,8 @@ class TestReplace: tctx.configure( r, replacements = [ - ("~q", "foo", "bar"), - ("~s", "foo", "bar"), + "/~q/foo/bar", + "/~s/foo/bar", ] ) f = tflow.tflow() @@ -58,10 +58,10 @@ class TestUpstreamProxy(tservers.HTTPUpstreamProxyTest): self.proxy.tmaster.addons.add(sa) self.proxy.tmaster.options.replacements = [ - ("~q", "foo", "bar"), - ("~q", "bar", "baz"), - ("~q", "foo", "oh noes!"), - ("~s", "baz", "ORLY") + "/~q/foo/bar", + "/~q/bar/baz", + "/~q/foo/oh noes!", + "/~s/baz/ORLY" ] p = self.pathoc() with p.connect(): @@ -81,9 +81,9 @@ class TestReplaceFile: tctx.configure( r, replacement_files = [ - ("~q", "foo", rp), - ("~s", "foo", rp), - ("~b nonexistent", "nonexistent", "nonexistent"), + "/~q/foo/" + rp, + "/~s/foo/" + rp, + "/~b nonexistent/nonexistent/nonexistent", ] ) f = tflow.tflow() diff --git a/test/mitmproxy/addons/test_setheaders.py b/test/mitmproxy/addons/test_setheaders.py index 6355f2be..3aaee7f4 100644 --- a/test/mitmproxy/addons/test_setheaders.py +++ b/test/mitmproxy/addons/test_setheaders.py @@ -21,7 +21,7 @@ class TestSetHeaders: sh = setheaders.SetHeaders() with taddons.context() as tctx: with pytest.raises(Exception, match="Invalid setheader filter pattern"): - tctx.configure(sh, setheaders = [("~b", "one", "two")]) + tctx.configure(sh, setheaders = ["/~b/one/two"]) tctx.configure(sh, setheaders = ["/foo/bar/voing"]) def test_setheaders(self): @@ -30,8 +30,8 @@ class TestSetHeaders: tctx.configure( sh, setheaders = [ - ("~q", "one", "two"), - ("~s", "one", "three") + "/~q/one/two", + "/~s/one/three" ] ) f = tflow.tflow() @@ -47,8 +47,8 @@ class TestSetHeaders: tctx.configure( sh, setheaders = [ - ("~s", "one", "two"), - ("~s", "one", "three") + "/~s/one/two", + "/~s/one/three" ] ) f = tflow.tflow(resp=True) @@ -60,8 +60,8 @@ class TestSetHeaders: tctx.configure( sh, setheaders = [ - ("~q", "one", "two"), - ("~q", "one", "three") + "/~q/one/two", + "/~q/one/three" ] ) f = tflow.tflow() diff --git a/test/mitmproxy/addons/test_streambodies.py b/test/mitmproxy/addons/test_streambodies.py index b982c66d..c6ce5e81 100644 --- a/test/mitmproxy/addons/test_streambodies.py +++ b/test/mitmproxy/addons/test_streambodies.py @@ -1,13 +1,16 @@ +from mitmproxy import exceptions from mitmproxy.test import tflow from mitmproxy.test import taddons - from mitmproxy.addons import streambodies +import pytest def test_simple(): sa = streambodies.StreamBodies() with taddons.context() as tctx: - tctx.configure(sa, stream_large_bodies = 10) + 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"" diff --git a/test/mitmproxy/addons/test_streamfile.py b/test/mitmproxy/addons/test_streamfile.py index 4922fc0b..4105c1fc 100644 --- a/test/mitmproxy/addons/test_streamfile.py +++ b/test/mitmproxy/addons/test_streamfile.py @@ -7,13 +7,13 @@ from mitmproxy.test import taddons from mitmproxy import io from mitmproxy import exceptions -from mitmproxy.tools import dump +from mitmproxy import options from mitmproxy.addons import streamfile def test_configure(): sa = streamfile.StreamFile() - with taddons.context(options=dump.Options()) as tctx: + with taddons.context(options=options.Options()) as tctx: with tutils.tmpdir() as tdir: p = os.path.join(tdir, "foo") with pytest.raises(exceptions.OptionsError): @@ -59,7 +59,7 @@ def test_simple(): tctx.configure(sa, streamfile=None) assert rd(p)[0].response - tctx.configure(sa, streamfile=p, streamfile_append=True) + tctx.configure(sa, streamfile="+" + p) f = tflow.tflow() sa.request(f) tctx.configure(sa, streamfile=None) diff --git a/test/mitmproxy/addons/test_termlog.py b/test/mitmproxy/addons/test_termlog.py index 70c3a7f2..2133b74d 100644 --- a/test/mitmproxy/addons/test_termlog.py +++ b/test/mitmproxy/addons/test_termlog.py @@ -3,7 +3,7 @@ import pytest from mitmproxy.addons import termlog from mitmproxy import log -from mitmproxy.tools.dump import Options +from mitmproxy.options import Options from mitmproxy.test import taddons diff --git a/test/mitmproxy/addons/test_view.py b/test/mitmproxy/addons/test_view.py index a063416f..b7842314 100644 --- a/test/mitmproxy/addons/test_view.py +++ b/test/mitmproxy/addons/test_view.py @@ -15,23 +15,6 @@ def tft(*, method="get", start=0): return f -class Options(options.Options): - def __init__( - self, - *, - filter=None, - console_order=None, - console_order_reversed=False, - console_focus_follow=False, - **kwargs - ): - self.filter = filter - self.console_order = console_order - self.console_order_reversed = console_order_reversed - self.console_focus_follow = console_focus_follow - super().__init__(**kwargs) - - def test_order_refresh(): v = view.View() sargs = [] @@ -42,7 +25,7 @@ def test_order_refresh(): v.sig_view_refresh.connect(save) tf = tflow.tflow(resp=True) - with taddons.context(options=Options()) as tctx: + with taddons.context(options=options.Options()) as tctx: tctx.configure(v, console_order="time") v.add(tf) tf.request.timestamp_start = 1 @@ -149,7 +132,7 @@ def test_filter(): def test_order(): v = view.View() - with taddons.context(options=Options()) as tctx: + with taddons.context(options=options.Options()) as tctx: v.request(tft(method="get", start=1)) v.request(tft(method="put", start=2)) v.request(tft(method="get", start=3)) @@ -280,7 +263,7 @@ def test_signals(): def test_focus_follow(): v = view.View() - with taddons.context(options=Options()) as tctx: + with taddons.context(options=options.Options()) as tctx: tctx.configure(v, console_focus_follow=True, filter="~m get") v.add(tft(start=5)) @@ -394,7 +377,7 @@ def test_settings(): def test_configure(): v = view.View() - with taddons.context(options=Options()) as tctx: + with taddons.context(options=options.Options()) as tctx: tctx.configure(v, filter="~q") with pytest.raises(Exception, match="Invalid interception filter"): tctx.configure(v, filter="~~") diff --git a/test/mitmproxy/proxy/protocol/test_http2.py b/test/mitmproxy/proxy/protocol/test_http2.py index 871d02fe..1f695cc5 100644 --- a/test/mitmproxy/proxy/protocol/test_http2.py +++ b/test/mitmproxy/proxy/protocol/test_http2.py @@ -100,7 +100,7 @@ class _Http2TestBase: def get_options(cls): opts = options.Options( listen_port=0, - no_upstream_cert=False, + upstream_cert=True, ssl_insecure=True ) opts.cadir = os.path.join(tempfile.gettempdir(), "mitmproxy") @@ -499,7 +499,8 @@ class TestBodySizeLimit(_Http2Test): return True def test_body_size_limit(self): - self.config.options.body_size_limit = 20 + self.config.options.body_size_limit = "20" + self.config.options._processed["body_size_limit"] = 20 client, h2_conn = self._setup_connection() diff --git a/test/mitmproxy/proxy/protocol/test_websocket.py b/test/mitmproxy/proxy/protocol/test_websocket.py index bac0e527..486e9d64 100644 --- a/test/mitmproxy/proxy/protocol/test_websocket.py +++ b/test/mitmproxy/proxy/protocol/test_websocket.py @@ -64,7 +64,7 @@ class _WebSocketTestBase: def get_options(cls): opts = options.Options( listen_port=0, - no_upstream_cert=False, + upstream_cert=True, ssl_insecure=True, websocket=True, ) diff --git a/test/mitmproxy/proxy/test_server.py b/test/mitmproxy/proxy/test_server.py index 56b09b9a..aa45761a 100644 --- a/test/mitmproxy/proxy/test_server.py +++ b/test/mitmproxy/proxy/test_server.py @@ -10,7 +10,7 @@ from mitmproxy import options from mitmproxy.addons import script from mitmproxy.addons import proxyauth from mitmproxy import http -from mitmproxy.proxy.config import HostMatcher, parse_server_spec +from mitmproxy.proxy.config import HostMatcher import mitmproxy.net.http from mitmproxy.net import tcp from mitmproxy.net import socks @@ -302,7 +302,7 @@ class TestHTTP(tservers.HTTPProxyTest, CommonMixin): class TestHTTPAuth(tservers.HTTPProxyTest): def test_auth(self): self.master.addons.add(proxyauth.ProxyAuth()) - self.master.options.auth_singleuser = "test:test" + self.master.options.proxyauth = "test:test" assert self.pathod("202").status_code == 407 p = self.pathoc() with p.connect(): @@ -321,7 +321,7 @@ class TestHTTPAuth(tservers.HTTPProxyTest): class TestHTTPReverseAuth(tservers.ReverseProxyTest): def test_auth(self): self.master.addons.add(proxyauth.ProxyAuth()) - self.master.options.auth_singleuser = "test:test" + self.master.options.proxyauth = "test:test" assert self.pathod("202").status_code == 401 p = self.pathoc() with p.connect(): @@ -342,22 +342,22 @@ class TestHTTPS(tservers.HTTPProxyTest, CommonMixin, TcpMixin): def test_clientcert_file(self): try: - self.config.clientcerts = os.path.join( + self.config.client_certs = os.path.join( tutils.test_data.path("mitmproxy/data/clientcert"), "client.pem") f = self.pathod("304") assert f.status_code == 304 assert self.server.last_log()["request"]["clientcert"]["keyinfo"] finally: - self.config.clientcerts = None + self.config.client_certs = None def test_clientcert_dir(self): try: - self.config.clientcerts = tutils.test_data.path("mitmproxy/data/clientcert") + self.config.client_certs = tutils.test_data.path("mitmproxy/data/clientcert") f = self.pathod("304") assert f.status_code == 304 assert self.server.last_log()["request"]["clientcert"]["keyinfo"] finally: - self.config.clientcerts = None + self.config.client_certs = None def test_error_post_connect(self): p = self.pathoc() @@ -579,8 +579,6 @@ class TestHttps2Http(tservers.ReverseProxyTest): @classmethod def get_options(cls): opts = super().get_options() - s = parse_server_spec(opts.upstream_server) - opts.upstream_server = "http://{}:{}".format(s.address[0], s.address[1]) return opts def pathoc(self, ssl, sni=None): @@ -870,11 +868,11 @@ class TestServerConnect(tservers.HTTPProxyTest): @classmethod def get_options(cls): opts = tservers.HTTPProxyTest.get_options() - opts.no_upstream_cert = True + opts.upstream_cert = False return opts def test_unnecessary_serverconnect(self): - """A replayed/fake response with no_upstream_cert should not connect to an upstream server""" + """A replayed/fake response with no upstream_cert should not connect to an upstream server""" assert self.pathod("200").status_code == 200 for msg in self.proxy.tmaster.tlog: assert "serverconnect" not in msg diff --git a/test/mitmproxy/test_flow.py b/test/mitmproxy/test_flow.py index 0ac3bfd6..f4d32cbb 100644 --- a/test/mitmproxy/test_flow.py +++ b/test/mitmproxy/test_flow.py @@ -63,8 +63,7 @@ class TestSerialize: r = self._treader() s = tservers.TestState() opts = options.Options( - mode="reverse", - upstream_server="https://use-this-domain" + mode="reverse:https://use-this-domain" ) conf = ProxyConfig(opts) fm = master.Master(opts, DummyServer(conf)) diff --git a/test/mitmproxy/test_optmanager.py b/test/mitmproxy/test_optmanager.py index 161b0dcf..ba31c750 100644 --- a/test/mitmproxy/test_optmanager.py +++ b/test/mitmproxy/test_optmanager.py @@ -1,6 +1,8 @@ import copy import os import pytest +import typing +import argparse from mitmproxy import options from mitmproxy import optmanager @@ -9,48 +11,51 @@ from mitmproxy.test import tutils class TO(optmanager.OptManager): - def __init__(self, one=None, two=None): - self.one = one - self.two = two + def __init__(self): super().__init__() + self.add_option("one", None, typing.Optional[int], "help") + self.add_option("two", 2, typing.Optional[int], "help") + self.add_option("bool", False, bool, "help") class TD(optmanager.OptManager): - def __init__(self, *, one="done", two="dtwo", three="error"): - self.one = one - self.two = two - self.three = three + def __init__(self): super().__init__() + self.add_option("one", "done", str, "help") + self.add_option("two", "dtwo", str, "help") class TD2(TD): - def __init__(self, *, three="dthree", four="dfour", **kwargs): - self.three = three - self.four = four - super().__init__(three=three, **kwargs) + def __init__(self): + super().__init__() + self.add_option("three", "dthree", str, "help") + self.add_option("four", "dfour", str, "help") class TM(optmanager.OptManager): - def __init__(self, one="one", two=["foo"], three=None): - self.one = one - self.two = two - self.three = three + def __init__(self): super().__init__() + self.add_option("two", ["foo"], typing.Sequence[str], "help") + self.add_option("one", None, typing.Optional[str], "help") -def test_defaults(): - assert TD2.default("one") == "done" - assert TD2.default("two") == "dtwo" - assert TD2.default("three") == "dthree" - assert TD2.default("four") == "dfour" +def test_add_option(): + o = TO() + with pytest.raises(ValueError, match="already exists"): + o.add_option("one", None, typing.Optional[int], "help") + +def test_defaults(): o = TD2() - assert o._defaults == { + defaults = { "one": "done", "two": "dtwo", "three": "dthree", "four": "dfour", } + for k, v in defaults.items(): + assert o.default(k) == v + assert not o.has_changed("one") newvals = dict( one="xone", @@ -64,18 +69,19 @@ def test_defaults(): assert v == getattr(o, k) o.reset() assert not o.has_changed("one") - for k, v in o._defaults.items(): - assert v == getattr(o, k) + + for k in o.keys(): + assert not o.has_changed(k) def test_options(): - o = TO(two="three") - assert o.keys() == set(["one", "two"]) + o = TO() + assert o.keys() == set(["bool", "one", "two"]) assert o.one is None - assert o.two == "three" - o.one = "one" - assert o.one == "one" + assert o.two == 2 + o.one = 1 + assert o.one == 1 with pytest.raises(TypeError): TO(nonexistent = "value") @@ -91,34 +97,38 @@ def test_options(): o.changed.connect(sub) - o.one = "ninety" + o.one = 90 assert len(rec) == 1 - assert rec[-1].one == "ninety" + assert rec[-1].one == 90 - o.update(one="oink") + o.update(one=3) assert len(rec) == 2 - assert rec[-1].one == "oink" + assert rec[-1].one == 3 def test_setter(): - o = TO(two="three") + o = TO() f = o.setter("two") - f("xxx") - assert o.two == "xxx" + f(99) + assert o.two == 99 with pytest.raises(Exception, match="No such option"): o.setter("nonexistent") def test_toggler(): - o = TO(two=True) - f = o.toggler("two") + o = TO() + f = o.toggler("bool") + assert o.bool is False f() - assert o.two is False + assert o.bool is True f() - assert o.two is True + assert o.bool is False with pytest.raises(Exception, match="No such option"): o.toggler("nonexistent") + with pytest.raises(Exception, match="boolean options"): + o.toggler("one") + class Rec(): def __init__(self): @@ -132,19 +142,19 @@ def test_subscribe(): o = TO() r = Rec() o.subscribe(r, ["two"]) - o.one = "foo" + o.one = 2 assert not r.called - o.two = "foo" + o.two = 3 assert r.called assert len(o.changed.receivers) == 1 del r - o.two = "bar" + o.two = 4 assert len(o.changed.receivers) == 0 def test_rollback(): - o = TO(one="two") + o = TO() rec = [] @@ -157,27 +167,35 @@ def test_rollback(): recerr.append(kwargs) def err(opts, updated): - if opts.one == "ten": + if opts.one == 10: + raise exceptions.OptionsError() + if opts.bool is True: raise exceptions.OptionsError() o.changed.connect(sub) o.changed.connect(err) o.errored.connect(errsub) - o.one = "ten" + assert o.one is None + o.one = 10 + o.bool = True assert isinstance(recerr[0]["exc"], exceptions.OptionsError) - assert o.one == "two" - assert len(rec) == 2 - assert rec[0].one == "ten" - assert rec[1].one == "two" + assert o.one is None + assert o.bool is False + assert len(rec) == 4 + assert rec[0].one == 10 + assert rec[1].one is None + assert rec[2].bool is True + assert rec[3].bool is False + + with pytest.raises(exceptions.OptionsError): + with o.rollback(set(["one"]), reraise=True): + raise exceptions.OptionsError() -def test_repr(): - assert repr(TO()) == "test.mitmproxy.test_optmanager.TO({'one': None, 'two': None})" - assert repr(TO(one='x' * 60)) == """test.mitmproxy.test_optmanager.TO({ - 'one': 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', - 'two': None -})""" +def test_simple(): + assert repr(TO()) + assert "one" in TO() def test_serialize(): @@ -249,3 +267,85 @@ def test_merge(): assert m.one == "two" m.merge(dict(two=["bar"])) assert m.two == ["foo", "bar"] + + +def test_option(): + o = optmanager._Option("test", 1, int, None, None) + assert o.current() == 1 + with pytest.raises(TypeError): + o.set("foo") + with pytest.raises(TypeError): + optmanager._Option("test", 1, str, None, None) + + o2 = optmanager._Option("test", 1, int, None, None) + assert o2 == o + o2.set(5) + assert o2 != o + + +def test_dump(): + o = options.Options() + assert optmanager.dump(o) + + +class TTypes(optmanager.OptManager): + def __init__(self): + super().__init__() + self.add_option("str", "str", str, "help") + self.add_option("optstr", "optstr", typing.Optional[str], "help", "help") + self.add_option("bool", False, bool, "help") + self.add_option("bool_on", True, bool, "help") + self.add_option("int", 0, int, "help") + self.add_option("optint", 0, typing.Optional[int], "help") + self.add_option("seqstr", [], typing.Sequence[str], "help") + self.add_option("unknown", 0.0, float, "help") + + +def test_make_parser(): + parser = argparse.ArgumentParser() + opts = TTypes() + opts.make_parser(parser, "str", short="a") + opts.make_parser(parser, "bool", short="b") + opts.make_parser(parser, "int", short="c") + opts.make_parser(parser, "seqstr", short="d") + opts.make_parser(parser, "bool_on", short="e") + with pytest.raises(ValueError): + opts.make_parser(parser, "unknown") + + +def test_set(): + opts = TTypes() + + opts.set("str=foo") + assert opts.str == "foo" + with pytest.raises(TypeError): + opts.set("str") + + opts.set("optstr=foo") + assert opts.optstr == "foo" + opts.set("optstr") + assert opts.optstr is None + + opts.set("bool=false") + assert opts.bool is False + opts.set("bool") + assert opts.bool is True + opts.set("bool=true") + assert opts.bool is True + with pytest.raises(exceptions.OptionsError): + opts.set("bool=wobble") + + opts.set("int=1") + assert opts.int == 1 + with pytest.raises(exceptions.OptionsError): + opts.set("int=wobble") + opts.set("optint") + assert opts.optint is None + + assert opts.seqstr == [] + opts.set("seqstr=foo") + assert opts.seqstr == ["foo"] + opts.set("seqstr=bar") + assert opts.seqstr == ["foo", "bar"] + opts.set("seqstr") + assert opts.seqstr == [] diff --git a/test/mitmproxy/test_proxy.py b/test/mitmproxy/test_proxy.py index 37cec57a..7a49c530 100644 --- a/test/mitmproxy/test_proxy.py +++ b/test/mitmproxy/test_proxy.py @@ -1,4 +1,3 @@ -import os import argparse from unittest import mock from OpenSSL import SSL @@ -6,6 +5,7 @@ import pytest from mitmproxy.tools import cmdline +from mitmproxy.tools import main from mitmproxy import options from mitmproxy.proxy import ProxyConfig from mitmproxy.proxy.server import DummyServer, ProxyServer, ConnectionHandler @@ -30,10 +30,10 @@ class TestProcessProxyOptions: def p(self, *args): parser = MockParser() - cmdline.common_options(parser) - args = parser.parse_args(args=args) opts = options.Options() - opts.merge(cmdline.get_common_options(args)) + cmdline.common_options(parser, opts) + args = parser.parse_args(args=args) + main.process_options(parser, opts, args) pconf = config.ProxyConfig(opts) return parser, pconf @@ -45,44 +45,6 @@ class TestProcessProxyOptions: def test_simple(self): assert self.p() - def test_cadir(self): - with tutils.tmpdir() as cadir: - self.assert_noerr("--cadir", cadir) - - @mock.patch("mitmproxy.platform.original_addr", None) - def test_no_transparent(self): - with pytest.raises(Exception, match="Transparent mode not supported"): - self.p("-T") - - @mock.patch("mitmproxy.platform.original_addr") - def test_modes(self, _): - self.assert_noerr("-R", "http://localhost") - with pytest.raises(Exception, match="expected one argument"): - self.p("-R") - with pytest.raises(Exception, match="Invalid server specification"): - self.p("-R", "reverse") - - self.assert_noerr("-T") - - self.assert_noerr("-U", "http://localhost") - with pytest.raises(Exception, match="Invalid server specification"): - self.p("-U", "upstream") - - self.assert_noerr("--upstream-auth", "test:test") - with pytest.raises(Exception, match="expected one argument"): - self.p("--upstream-auth") - with pytest.raises(Exception, match="mutually exclusive"): - self.p("-R", "http://localhost", "-T") - - def test_client_certs(self): - with tutils.tmpdir() as cadir: - self.assert_noerr("--client-certs", cadir) - self.assert_noerr( - "--client-certs", - os.path.join(tutils.test_data.path("mitmproxy/data/clientcert"), "client.pem")) - with pytest.raises(Exception, match="path does not exist"): - self.p("--client-certs", "nonexistent") - def test_certs(self): self.assert_noerr( "--cert", @@ -91,19 +53,9 @@ class TestProcessProxyOptions: self.p("--cert", "nonexistent") def test_insecure(self): - p = self.assert_noerr("--insecure") + p = self.assert_noerr("--ssl-insecure") assert p.openssl_verification_mode_server == SSL.VERIFY_NONE - def test_upstream_trusted_cadir(self): - expected_dir = "/path/to/a/ca/dir" - p = self.assert_noerr("--upstream-trusted-cadir", expected_dir) - assert p.options.ssl_verify_upstream_trusted_cadir == expected_dir - - def test_upstream_trusted_ca(self): - expected_file = "/path/to/a/cert/file" - p = self.assert_noerr("--upstream-trusted-ca", expected_file) - assert p.options.ssl_verify_upstream_trusted_ca == expected_file - class TestProxyServer: @@ -131,19 +83,19 @@ class TestDummyServer: class TestConnectionHandler: def test_fatal_error(self, capsys): - config = mock.Mock() - root_layer = mock.Mock() - root_layer.side_effect = RuntimeError - config.options.mode.return_value = root_layer + opts = options.Options() + pconf = config.ProxyConfig(opts) + channel = mock.Mock() def ask(_, x): - return x + raise RuntimeError + channel.ask = ask c = ConnectionHandler( mock.MagicMock(), ("127.0.0.1", 8080), - config, + pconf, channel ) c.handle() diff --git a/test/mitmproxy/tools/test_cmdline.py b/test/mitmproxy/tools/test_cmdline.py index 96d5ae31..65cfeb07 100644 --- a/test/mitmproxy/tools/test_cmdline.py +++ b/test/mitmproxy/tools/test_cmdline.py @@ -1,31 +1,30 @@ import argparse from mitmproxy.tools import cmdline +from mitmproxy.tools import main +from mitmproxy import options def test_common(): parser = argparse.ArgumentParser() - cmdline.common_options(parser) - opts = parser.parse_args(args=[]) - - assert cmdline.get_common_options(opts) - - opts.stickycookie_filt = "foo" - opts.stickyauth_filt = "foo" - v = cmdline.get_common_options(opts) - assert v["stickycookie"] == "foo" - assert v["stickyauth"] == "foo" + opts = options.Options() + cmdline.common_options(parser, opts) + args = parser.parse_args(args=[]) + assert main.process_options(parser, opts, args) def test_mitmproxy(): - ap = cmdline.mitmproxy() + opts = options.Options() + ap = cmdline.mitmproxy(opts) assert ap def test_mitmdump(): - ap = cmdline.mitmdump() + opts = options.Options() + ap = cmdline.mitmdump(opts) assert ap def test_mitmweb(): - ap = cmdline.mitmweb() + opts = options.Options() + ap = cmdline.mitmweb(opts) assert ap diff --git a/test/mitmproxy/tools/test_dump.py b/test/mitmproxy/tools/test_dump.py index b4183725..2542ec4b 100644 --- a/test/mitmproxy/tools/test_dump.py +++ b/test/mitmproxy/tools/test_dump.py @@ -3,8 +3,10 @@ import pytest from unittest import mock from mitmproxy import proxy +from mitmproxy import exceptions from mitmproxy import log from mitmproxy import controller +from mitmproxy import options from mitmproxy.tools import dump from mitmproxy.test import tutils @@ -12,8 +14,8 @@ from .. import tservers class TestDumpMaster(tservers.MasterTest): - def mkmaster(self, flt, **options): - o = dump.Options(filtstr=flt, verbosity=-1, flow_detail=0, **options) + def mkmaster(self, flt, **opts): + o = options.Options(filtstr=flt, verbosity=-1, flow_detail=0, **opts) m = dump.DumpMaster(o, proxy.DummyServer(), with_termlog=False, with_dumper=False) return m @@ -25,9 +27,9 @@ class TestDumpMaster(tservers.MasterTest): self.mkmaster(None, rfile=p), 1, b"", ) - with pytest.raises(dump.DumpError): + with pytest.raises(exceptions.OptionsError): self.mkmaster(None, rfile="/nonexistent") - with pytest.raises(dump.DumpError): + with pytest.raises(exceptions.OptionsError): self.mkmaster(None, rfile="test_dump.py") def test_has_error(self): @@ -40,13 +42,13 @@ class TestDumpMaster(tservers.MasterTest): @pytest.mark.parametrize("termlog", [False, True]) def test_addons_termlog(self, termlog): with mock.patch('sys.stdout'): - o = dump.Options() + o = options.Options() m = dump.DumpMaster(o, proxy.DummyServer(), with_termlog=termlog) assert (m.addons.get('termlog') is not None) == termlog @pytest.mark.parametrize("dumper", [False, True]) def test_addons_dumper(self, dumper): with mock.patch('sys.stdout'): - o = dump.Options() + o = options.Options() m = dump.DumpMaster(o, proxy.DummyServer(), with_dumper=dumper) assert (m.addons.get('dumper') is not None) == dumper diff --git a/test/mitmproxy/tservers.py b/test/mitmproxy/tservers.py index 9a289ae5..a8aaa358 100644 --- a/test/mitmproxy/tservers.py +++ b/test/mitmproxy/tservers.py @@ -288,7 +288,7 @@ class ReverseProxyTest(ProxyTestBase): @classmethod def get_options(cls): opts = ProxyTestBase.get_options() - opts.upstream_server = "".join( + s = "".join( [ "https" if cls.ssl else "http", "://", @@ -296,7 +296,7 @@ class ReverseProxyTest(ProxyTestBase): str(cls.server.port) ] ) - opts.mode = "reverse" + opts.mode = "reverse:" + s return opts def pathoc(self, sni=None): @@ -373,9 +373,9 @@ class ChainProxyTest(ProxyTestBase): def get_options(cls): opts = super().get_options() if cls.chain: # First proxy is in normal mode. + s = "http://127.0.0.1:%s" % cls.chain[0].port opts.update( - mode="upstream", - upstream_server="http://127.0.0.1:%s" % cls.chain[0].port + mode="upstream:" + s, ) return opts diff --git a/test/mitmproxy/utils/test_typecheck.py b/test/mitmproxy/utils/test_typecheck.py index 67981be4..d99a914f 100644 --- a/test/mitmproxy/utils/test_typecheck.py +++ b/test/mitmproxy/utils/test_typecheck.py @@ -16,12 +16,6 @@ class T(TBase): super(T, self).__init__(42) -def test_get_arg_type_from_constructor_annotation(): - assert typecheck.get_arg_type_from_constructor_annotation(T, "foo") == str - assert typecheck.get_arg_type_from_constructor_annotation(T, "bar") == int - assert not typecheck.get_arg_type_from_constructor_annotation(T, "baz") - - def test_check_type(): typecheck.check_type("foo", 42, int) with pytest.raises(TypeError): |