diff --git a/test/mitmproxy/console/test_master.py b/test/mitmproxy/console/test_master.py index 8195b1d19..1c89467cb 100644 --- a/test/mitmproxy/console/test_master.py +++ b/test/mitmproxy/console/test_master.py @@ -4,7 +4,7 @@ from mitmproxy.tools import console from mitmproxy import proxy from mitmproxy import options from mitmproxy.tools.console import common -from .. import mastertest +from .. import tservers def test_format_keyvals(): @@ -23,7 +23,7 @@ def test_options(): assert options.Options(replay_kill_extra=True) -class TestMaster(mastertest.MasterTest): +class TestMaster(tservers.MasterTest): def mkmaster(self, **opts): if "verbosity" not in opts: opts["verbosity"] = 1 diff --git a/test/mitmproxy/mastertest.py b/test/mitmproxy/mastertest.py deleted file mode 100644 index e3bb30691..000000000 --- a/test/mitmproxy/mastertest.py +++ /dev/null @@ -1,56 +0,0 @@ -import contextlib - -from mitmproxy.test import tflow - -import mitmproxy.test.tutils - -from mitmproxy import master -from mitmproxy import io -from mitmproxy import proxy -from mitmproxy import http -from mitmproxy import options - - -class MasterTest: - - def cycle(self, master, content): - f = tflow.tflow(req=mitmproxy.test.tutils.treq(content=content)) - master.clientconnect(f.client_conn) - master.serverconnect(f.server_conn) - master.request(f) - if not f.error: - f.response = http.HTTPResponse.wrap( - mitmproxy.test.tutils.tresp(content=content) - ) - master.response(f) - master.clientdisconnect(f) - return f - - def dummy_cycle(self, master, n, content): - for i in range(n): - self.cycle(master, content) - master.shutdown() - - def flowfile(self, path): - f = open(path, "wb") - fw = io.FlowWriter(f) - t = tflow.tflow(resp=True) - fw.add(t) - f.close() - - -class RecordingMaster(master.Master): - def __init__(self, *args, **kwargs): - master.Master.__init__(self, *args, **kwargs) - self.event_log = [] - - def add_log(self, e, level): - self.event_log.append((level, e)) - - -@contextlib.contextmanager -def mockctx(): - o = options.Options(refresh_server_playback = True, keepserving=False) - m = RecordingMaster(o, proxy.DummyServer(o)) - with m.handlecontext(): - yield diff --git a/test/mitmproxy/net/http/test_request.py b/test/mitmproxy/net/http/test_request.py index 5c588c471..6fe57010b 100644 --- a/test/mitmproxy/net/http/test_request.py +++ b/test/mitmproxy/net/http/test_request.py @@ -1,5 +1,4 @@ -# -*- coding: utf-8 -*- - +from unittest import mock import pytest from mitmproxy.net.http import Headers @@ -9,8 +8,19 @@ from .test_message import _test_decoded_attr, _test_passthrough_attr class TestRequestData: def test_init(self): + with pytest.raises(UnicodeEncodeError): + treq(method="fööbär") + with pytest.raises(UnicodeEncodeError): + treq(scheme="fööbär") + assert treq(host="fööbär").host == "fööbär" + with pytest.raises(UnicodeEncodeError): + treq(path="/fööbär") + with pytest.raises(UnicodeEncodeError): + treq(http_version="föö/bä.r") with pytest.raises(ValueError): treq(headers="foobar") + with pytest.raises(ValueError): + treq(content="foobar") assert isinstance(treq(headers=()).headers, Headers) @@ -25,15 +35,19 @@ class TestRequestCore: request.host = None assert repr(request) == "Request(GET /path)" - def replace(self): + def test_replace(self): r = treq() r.path = b"foobarfoo" r.replace(b"foo", "bar") - assert r.path == b"barbarbar" + assert r.path == "barbarbar" r.path = b"foobarfoo" r.replace(b"foo", "bar", count=1) - assert r.path == b"barbarfoo" + assert r.path == "barbarfoo" + + r.path = "foobarfoo" + r.replace("foo", "bar", count=1) + assert r.path == "barbarfoo" def test_first_line_format(self): _test_passthrough_attr(treq(), "first_line_format") @@ -43,6 +57,7 @@ class TestRequestCore: def test_scheme(self): _test_decoded_attr(treq(), "scheme") + assert treq(scheme=None).scheme is None def test_port(self): _test_passthrough_attr(treq(), "port") @@ -172,6 +187,9 @@ class TestRequestUtils: request.query["foo"] = "bar" assert request.query["foo"] == "bar" assert request.path == "/path?foo=bar" + request.query = [('foo', 'bar')] + assert request.query["foo"] == "bar" + assert request.path == "/path?foo=bar" def test_get_cookies_none(self): request = treq() @@ -206,6 +224,9 @@ class TestRequestUtils: result = request.cookies result["cookiename"] = "foo" assert request.cookies["cookiename"] == "foo" + request.cookies = [["one", "uno"], ["two", "due"]] + assert request.cookies["one"] == "uno" + assert request.cookies["two"] == "due" def test_get_path_components(self): request = treq(path=b"/foo/bar") @@ -258,6 +279,8 @@ class TestRequestUtils: request.headers["Content-Type"] = "application/x-www-form-urlencoded" assert list(request.urlencoded_form.items()) == [("foobar", "baz")] + request.raw_content = b"\xFF" + assert len(request.urlencoded_form) == 0 def test_set_urlencoded_form(self): request = treq() @@ -271,3 +294,12 @@ class TestRequestUtils: request.headers["Content-Type"] = "multipart/form-data" assert list(request.multipart_form.items()) == [] + + with mock.patch('mitmproxy.net.http.multipart.decode') as m: + m.side_effect = ValueError + assert list(request.multipart_form.items()) == [] + + def test_set_multipart_form(self): + request = treq(content=b"foobar") + with pytest.raises(NotImplementedError): + request.multipart_form = "foobar" diff --git a/test/mitmproxy/net/http/test_response.py b/test/mitmproxy/net/http/test_response.py index 9c528fd01..fa1770feb 100644 --- a/test/mitmproxy/net/http/test_response.py +++ b/test/mitmproxy/net/http/test_response.py @@ -1,6 +1,7 @@ import email import time import pytest +from unittest import mock from mitmproxy.net.http import Headers from mitmproxy.net.http import Response @@ -13,6 +14,12 @@ class TestResponseData: def test_init(self): with pytest.raises(ValueError): tresp(headers="foobar") + with pytest.raises(UnicodeEncodeError): + tresp(http_version="föö/bä.r") + with pytest.raises(UnicodeEncodeError): + tresp(reason="fööbär") + with pytest.raises(ValueError): + tresp(content="foobar") assert isinstance(tresp(headers=()).headers, Headers) @@ -133,9 +140,10 @@ class TestResponseUtils: def test_set_cookies(self): resp = tresp() resp.cookies["foo"] = ("bar", {}) - assert len(resp.cookies) == 1 assert resp.cookies["foo"] == ("bar", CookieAttrs()) + resp.cookies = [["one", ("uno", CookieAttrs())], ["two", ("due", CookieAttrs())]] + assert list(resp.cookies.keys()) == ["one", "two"] def test_refresh(self): r = tresp() @@ -156,3 +164,7 @@ class TestResponseUtils: r.refresh() # Cookie refreshing is tested in test_cookies, we just make sure that it's triggered here. assert cookie != r.headers["set-cookie"] + + with mock.patch('mitmproxy.net.http.cookies.refresh_set_cookie_header') as m: + m.side_effect = ValueError + r.refresh(n) diff --git a/test/mitmproxy/script/test_concurrent.py b/test/mitmproxy/script/test_concurrent.py index 90cdc3d88..fb932d9a2 100644 --- a/test/mitmproxy/script/test_concurrent.py +++ b/test/mitmproxy/script/test_concurrent.py @@ -7,7 +7,7 @@ from mitmproxy.addons import script import time -from test.mitmproxy import mastertest +from .. import tservers class Thing: @@ -16,7 +16,7 @@ class Thing: self.live = True -class TestConcurrent(mastertest.MasterTest): +class TestConcurrent(tservers.MasterTest): def test_concurrent(self): with taddons.context() as tctx: sc = script.Script( diff --git a/test/mitmproxy/test_examples.py b/test/mitmproxy/test_examples.py index dae52e234..f3603fca8 100644 --- a/test/mitmproxy/test_examples.py +++ b/test/mitmproxy/test_examples.py @@ -14,7 +14,7 @@ from mitmproxy.test import tutils from mitmproxy.net.http import Headers from mitmproxy.net.http import cookies -from . import mastertest +from . import tservers example_dir = tutils.test_data.push("../examples") @@ -38,7 +38,7 @@ def tscript(cmd, args=""): return m, sc -class TestScripts(mastertest.MasterTest): +class TestScripts(tservers.MasterTest): def test_add_header(self): m, _ = tscript("simple/add_header.py") f = tflow.tflow(resp=tutils.tresp()) diff --git a/test/mitmproxy/test_tools_dump.py b/test/mitmproxy/test_tools_dump.py index a471354c6..f8a888717 100644 --- a/test/mitmproxy/test_tools_dump.py +++ b/test/mitmproxy/test_tools_dump.py @@ -8,10 +8,10 @@ from mitmproxy import controller from mitmproxy.tools import dump from mitmproxy.test import tutils -from . import mastertest +from . import tservers -class TestDumpMaster(mastertest.MasterTest): +class TestDumpMaster(tservers.MasterTest): def mkmaster(self, flt, **options): o = dump.Options(filtstr=flt, verbosity=-1, flow_detail=0, **options) m = dump.DumpMaster(o, proxy.DummyServer(), with_termlog=False, with_dumper=False) diff --git a/test/mitmproxy/test_web_master.py b/test/mitmproxy/test_web_master.py index 3591284dd..d4190ffb7 100644 --- a/test/mitmproxy/test_web_master.py +++ b/test/mitmproxy/test_web_master.py @@ -3,10 +3,10 @@ from mitmproxy import proxy from mitmproxy import options from mitmproxy.proxy.config import ProxyConfig -from . import mastertest +from . import tservers -class TestWebMaster(mastertest.MasterTest): +class TestWebMaster(tservers.MasterTest): def mkmaster(self, **opts): o = options.Options(**opts) c = ProxyConfig(o) diff --git a/test/mitmproxy/tservers.py b/test/mitmproxy/tservers.py index c9a7e595e..298fddcb9 100644 --- a/test/mitmproxy/tservers.py +++ b/test/mitmproxy/tservers.py @@ -7,11 +7,43 @@ import mitmproxy.platform from mitmproxy.proxy.config import ProxyConfig from mitmproxy.proxy.server import ProxyServer from mitmproxy import master -import pathod.test -import pathod.pathoc from mitmproxy import controller from mitmproxy import options from mitmproxy import exceptions +from mitmproxy import io +from mitmproxy import http +import pathod.test +import pathod.pathoc + +from mitmproxy.test import tflow +from mitmproxy.test import tutils + + +class MasterTest: + + def cycle(self, master, content): + f = tflow.tflow(req=tutils.treq(content=content)) + master.clientconnect(f.client_conn) + master.serverconnect(f.server_conn) + master.request(f) + if not f.error: + f.response = http.HTTPResponse.wrap( + tutils.tresp(content=content) + ) + master.response(f) + master.clientdisconnect(f) + return f + + def dummy_cycle(self, master, n, content): + for i in range(n): + self.cycle(master, content) + master.shutdown() + + def flowfile(self, path): + with open(path, "wb") as f: + fw = io.FlowWriter(f) + t = tflow.tflow(resp=True) + fw.add(t) class TestState: diff --git a/tox.ini b/tox.ini index fff4d9139..7bd33dda0 100644 --- a/tox.ini +++ b/tox.ini @@ -14,7 +14,7 @@ commands = pytest --timeout 60 --cov-report='' --cov=mitmproxy --cov=pathod \ --full-cov=mitmproxy/ \ --no-full-cov=mitmproxy/contentviews/__init__.py --no-full-cov=mitmproxy/contentviews/protobuf.py --no-full-cov=mitmproxy/contentviews/wbxml.py --no-full-cov=mitmproxy/contentviews/xml_html.py \ - --no-full-cov=mitmproxy/net/tcp.py --no-full-cov=mitmproxy/net/http/cookies.py --no-full-cov=mitmproxy/net/http/encoding.py --no-full-cov=mitmproxy/net/http/message.py --no-full-cov=mitmproxy/net/http/request.py --no-full-cov=mitmproxy/net/http/response.py --no-full-cov=mitmproxy/net/http/url.py \ + --no-full-cov=mitmproxy/net/tcp.py --no-full-cov=mitmproxy/net/http/cookies.py --no-full-cov=mitmproxy/net/http/encoding.py --no-full-cov=mitmproxy/net/http/message.py --no-full-cov=mitmproxy/net/http/url.py \ --no-full-cov=mitmproxy/proxy/protocol/ --no-full-cov=mitmproxy/proxy/config.py --no-full-cov=mitmproxy/proxy/root_context.py --no-full-cov=mitmproxy/proxy/server.py \ --no-full-cov=mitmproxy/tools/ \ --no-full-cov=mitmproxy/certs.py --no-full-cov=mitmproxy/connections.py --no-full-cov=mitmproxy/controller.py --no-full-cov=mitmproxy/export.py --no-full-cov=mitmproxy/flow.py --no-full-cov=mitmproxy/flowfilter.py --no-full-cov=mitmproxy/http.py --no-full-cov=mitmproxy/io_compat.py --no-full-cov=mitmproxy/master.py --no-full-cov=mitmproxy/optmanager.py \