From 22eebfd574c95bbaf600aa67f14e52a44345e678 Mon Sep 17 00:00:00 2001 From: Aldo Cortesi Date: Wed, 19 Oct 2016 14:25:11 +1300 Subject: addons.Addons -> addonmanager, builtins -> addons --- test/mitmproxy/addons/__init__.py | 0 test/mitmproxy/addons/test_anticache.py | 23 ++ test/mitmproxy/addons/test_anticomp.py | 22 ++ test/mitmproxy/addons/test_clientplayback.py | 37 ++++ test/mitmproxy/addons/test_dumper.py | 84 ++++++++ test/mitmproxy/addons/test_filestreamer.py | 41 ++++ test/mitmproxy/addons/test_onboarding.py | 16 ++ test/mitmproxy/addons/test_replace.py | 71 +++++++ test/mitmproxy/addons/test_script.py | 233 ++++++++++++++++++++ test/mitmproxy/addons/test_serverplayback.py | 282 +++++++++++++++++++++++++ test/mitmproxy/addons/test_setheaders.py | 64 ++++++ test/mitmproxy/addons/test_stickyauth.py | 23 ++ test/mitmproxy/addons/test_stickycookie.py | 130 ++++++++++++ test/mitmproxy/addons/test_streambodies.py | 28 +++ test/mitmproxy/addons/test_termlog.py | 17 ++ test/mitmproxy/addons/test_wsgiapp.py | 41 ++++ test/mitmproxy/builtins/__init__.py | 0 test/mitmproxy/builtins/test_anticache.py | 23 -- test/mitmproxy/builtins/test_anticomp.py | 22 -- test/mitmproxy/builtins/test_clientplayback.py | 37 ---- test/mitmproxy/builtins/test_dumper.py | 84 -------- test/mitmproxy/builtins/test_filestreamer.py | 41 ---- test/mitmproxy/builtins/test_onboarding.py | 16 -- test/mitmproxy/builtins/test_replace.py | 71 ------- test/mitmproxy/builtins/test_script.py | 233 -------------------- test/mitmproxy/builtins/test_serverplayback.py | 282 ------------------------- test/mitmproxy/builtins/test_setheaders.py | 64 ------ test/mitmproxy/builtins/test_stickyauth.py | 23 -- test/mitmproxy/builtins/test_stickycookie.py | 130 ------------ test/mitmproxy/builtins/test_streambodies.py | 28 --- test/mitmproxy/builtins/test_termlog.py | 17 -- test/mitmproxy/builtins/test_wsgiapp.py | 41 ---- test/mitmproxy/script/test_concurrent.py | 2 +- test/mitmproxy/test_addonmanager.py | 23 ++ test/mitmproxy/test_addons.py | 23 -- test/mitmproxy/test_examples.py | 2 +- test/mitmproxy/test_server.py | 2 +- test/mitmproxy/tools/benchtool.py | 2 +- test/netlib/http/test_request.py | 2 +- test/netlib/http/test_response.py | 2 +- 40 files changed, 1141 insertions(+), 1141 deletions(-) create mode 100644 test/mitmproxy/addons/__init__.py create mode 100644 test/mitmproxy/addons/test_anticache.py create mode 100644 test/mitmproxy/addons/test_anticomp.py create mode 100644 test/mitmproxy/addons/test_clientplayback.py create mode 100644 test/mitmproxy/addons/test_dumper.py create mode 100644 test/mitmproxy/addons/test_filestreamer.py create mode 100644 test/mitmproxy/addons/test_onboarding.py create mode 100644 test/mitmproxy/addons/test_replace.py create mode 100644 test/mitmproxy/addons/test_script.py create mode 100644 test/mitmproxy/addons/test_serverplayback.py create mode 100644 test/mitmproxy/addons/test_setheaders.py create mode 100644 test/mitmproxy/addons/test_stickyauth.py create mode 100644 test/mitmproxy/addons/test_stickycookie.py create mode 100644 test/mitmproxy/addons/test_streambodies.py create mode 100644 test/mitmproxy/addons/test_termlog.py create mode 100644 test/mitmproxy/addons/test_wsgiapp.py delete mode 100644 test/mitmproxy/builtins/__init__.py delete mode 100644 test/mitmproxy/builtins/test_anticache.py delete mode 100644 test/mitmproxy/builtins/test_anticomp.py delete mode 100644 test/mitmproxy/builtins/test_clientplayback.py delete mode 100644 test/mitmproxy/builtins/test_dumper.py delete mode 100644 test/mitmproxy/builtins/test_filestreamer.py delete mode 100644 test/mitmproxy/builtins/test_onboarding.py delete mode 100644 test/mitmproxy/builtins/test_replace.py delete mode 100644 test/mitmproxy/builtins/test_script.py delete mode 100644 test/mitmproxy/builtins/test_serverplayback.py delete mode 100644 test/mitmproxy/builtins/test_setheaders.py delete mode 100644 test/mitmproxy/builtins/test_stickyauth.py delete mode 100644 test/mitmproxy/builtins/test_stickycookie.py delete mode 100644 test/mitmproxy/builtins/test_streambodies.py delete mode 100644 test/mitmproxy/builtins/test_termlog.py delete mode 100644 test/mitmproxy/builtins/test_wsgiapp.py create mode 100644 test/mitmproxy/test_addonmanager.py delete mode 100644 test/mitmproxy/test_addons.py (limited to 'test') diff --git a/test/mitmproxy/addons/__init__.py b/test/mitmproxy/addons/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/test/mitmproxy/addons/test_anticache.py b/test/mitmproxy/addons/test_anticache.py new file mode 100644 index 00000000..f7418f38 --- /dev/null +++ b/test/mitmproxy/addons/test_anticache.py @@ -0,0 +1,23 @@ +from .. import tutils, mastertest +from mitmproxy.addons import anticache +from mitmproxy import master +from mitmproxy import options +from mitmproxy import proxy + + +class TestAntiCache(mastertest.MasterTest): + def test_simple(self): + o = options.Options(anticache = True) + m = master.Master(o, proxy.DummyServer()) + sa = anticache.AntiCache() + m.addons.add(sa) + + f = tutils.tflow(resp=True) + m.request(f) + + f = tutils.tflow(resp=True) + f.request.headers["if-modified-since"] = "test" + f.request.headers["if-none-match"] = "test" + m.request(f) + assert "if-modified-since" not in f.request.headers + assert "if-none-match" not in f.request.headers diff --git a/test/mitmproxy/addons/test_anticomp.py b/test/mitmproxy/addons/test_anticomp.py new file mode 100644 index 00000000..5f95013f --- /dev/null +++ b/test/mitmproxy/addons/test_anticomp.py @@ -0,0 +1,22 @@ +from .. import tutils, mastertest +from mitmproxy.addons import anticomp +from mitmproxy import master +from mitmproxy import options +from mitmproxy import proxy + + +class TestAntiComp(mastertest.MasterTest): + def test_simple(self): + o = options.Options(anticomp = True) + m = master.Master(o, proxy.DummyServer()) + sa = anticomp.AntiComp() + m.addons.add(sa) + + f = tutils.tflow(resp=True) + m.request(f) + + f = tutils.tflow(resp=True) + + f.request.headers["Accept-Encoding"] = "foobar" + m.request(f) + assert f.request.headers["Accept-Encoding"] == "identity" diff --git a/test/mitmproxy/addons/test_clientplayback.py b/test/mitmproxy/addons/test_clientplayback.py new file mode 100644 index 00000000..c5407d18 --- /dev/null +++ b/test/mitmproxy/addons/test_clientplayback.py @@ -0,0 +1,37 @@ +import mock + +from mitmproxy.addons import clientplayback +from mitmproxy import options + +from .. import tutils, mastertest + + +class TestClientPlayback: + def test_playback(self): + cp = clientplayback.ClientPlayback() + cp.configure(options.Options(), []) + assert cp.count() == 0 + f = tutils.tflow(resp=True) + cp.load([f]) + assert cp.count() == 1 + RP = "mitmproxy.protocol.http_replay.RequestReplayThread" + with mock.patch(RP) as rp: + assert not cp.current + with mastertest.mockctx(): + cp.tick() + rp.assert_called() + assert cp.current + + cp.keepserving = False + cp.flows = None + cp.current = None + with mock.patch("mitmproxy.master.Master.shutdown") as sd: + with mastertest.mockctx(): + cp.tick() + sd.assert_called() + + def test_configure(self): + cp = clientplayback.ClientPlayback() + cp.configure( + options.Options(), [] + ) diff --git a/test/mitmproxy/addons/test_dumper.py b/test/mitmproxy/addons/test_dumper.py new file mode 100644 index 00000000..ce2d2de9 --- /dev/null +++ b/test/mitmproxy/addons/test_dumper.py @@ -0,0 +1,84 @@ +import io + +from .. import tutils, mastertest + +from mitmproxy.addons import dumper +from mitmproxy import exceptions +from mitmproxy import dump +from mitmproxy import models +from mitmproxy import proxy +import netlib.tutils +import mock + + +class TestDumper(mastertest.MasterTest): + def test_simple(self): + d = dumper.Dumper() + sio = io.StringIO() + + updated = {"tfile", "flow_detail"} + d.configure(dump.Options(tfile = sio, flow_detail = 0), updated) + d.response(tutils.tflow()) + assert not sio.getvalue() + + d.configure(dump.Options(tfile = sio, flow_detail = 4), updated) + d.response(tutils.tflow()) + assert sio.getvalue() + + sio = io.StringIO() + d.configure(dump.Options(tfile = sio, flow_detail = 4), updated) + d.response(tutils.tflow(resp=True)) + assert "<<" in sio.getvalue() + + sio = io.StringIO() + d.configure(dump.Options(tfile = sio, flow_detail = 4), updated) + d.response(tutils.tflow(err=True)) + assert "<<" in sio.getvalue() + + sio = io.StringIO() + d.configure(dump.Options(tfile = sio, flow_detail = 4), updated) + flow = tutils.tflow() + flow.request = netlib.tutils.treq() + flow.request.stickycookie = True + flow.client_conn = mock.MagicMock() + flow.client_conn.address.host = "foo" + flow.response = netlib.tutils.tresp(content=None) + flow.response.is_replay = True + flow.response.status_code = 300 + d.response(flow) + assert sio.getvalue() + + sio = io.StringIO() + d.configure(dump.Options(tfile = sio, flow_detail = 4), updated) + flow = tutils.tflow(resp=netlib.tutils.tresp(content=b"{")) + flow.response.headers["content-type"] = "application/json" + flow.response.status_code = 400 + d.response(flow) + assert sio.getvalue() + + sio = io.StringIO() + d.configure(dump.Options(tfile = sio), updated) + flow = tutils.tflow() + flow.request.content = None + flow.response = models.HTTPResponse.wrap(netlib.tutils.tresp()) + flow.response.content = None + d.response(flow) + assert "content missing" in sio.getvalue() + + +class TestContentView(mastertest.MasterTest): + @mock.patch("mitmproxy.contentviews.ViewAuto.__call__") + def test_contentview(self, view_auto): + view_auto.side_effect = exceptions.ContentViewException("") + + sio = io.StringIO() + o = dump.Options( + flow_detail=4, + verbosity=3, + tfile=sio, + ) + m = mastertest.RecordingMaster(o, proxy.DummyServer()) + d = dumper.Dumper() + m.addons.add(d) + m.response(tutils.tflow()) + assert "Content viewer failed" in m.event_log[0][1] diff --git a/test/mitmproxy/addons/test_filestreamer.py b/test/mitmproxy/addons/test_filestreamer.py new file mode 100644 index 00000000..a85fcd0c --- /dev/null +++ b/test/mitmproxy/addons/test_filestreamer.py @@ -0,0 +1,41 @@ +from .. import tutils, mastertest + +import os.path + +from mitmproxy.addons import filestreamer +from mitmproxy import master +from mitmproxy.flow import io +from mitmproxy import options +from mitmproxy import proxy + + +class TestStream(mastertest.MasterTest): + def test_stream(self): + with tutils.tmpdir() as tdir: + p = os.path.join(tdir, "foo") + + def r(): + r = io.FlowReader(open(p, "rb")) + return list(r.stream()) + + o = options.Options( + outfile = (p, "wb") + ) + m = master.Master(o, proxy.DummyServer()) + sa = filestreamer.FileStreamer() + + m.addons.add(sa) + f = tutils.tflow(resp=True) + m.request(f) + m.response(f) + m.addons.remove(sa) + + assert r()[0].response + + m.options.outfile = (p, "ab") + + m.addons.add(sa) + f = tutils.tflow() + m.request(f) + m.addons.remove(sa) + assert not r()[1].response diff --git a/test/mitmproxy/addons/test_onboarding.py b/test/mitmproxy/addons/test_onboarding.py new file mode 100644 index 00000000..63125c23 --- /dev/null +++ b/test/mitmproxy/addons/test_onboarding.py @@ -0,0 +1,16 @@ +from mitmproxy.addons import onboarding +from .. import tservers + + +class TestApp(tservers.HTTPProxyTest): + def addons(self): + return [onboarding.Onboarding()] + + def test_basic(self): + assert self.app("/").status_code == 200 + + def test_cert(self): + for ext in ["pem", "p12"]: + resp = self.app("/cert/%s" % ext) + assert resp.status_code == 200 + assert resp.content diff --git a/test/mitmproxy/addons/test_replace.py b/test/mitmproxy/addons/test_replace.py new file mode 100644 index 00000000..94c2f832 --- /dev/null +++ b/test/mitmproxy/addons/test_replace.py @@ -0,0 +1,71 @@ +from .. import tutils, mastertest, tservers +from mitmproxy.addons import replace +from mitmproxy import master +from mitmproxy import options +from mitmproxy import proxy + + +class TestReplace(mastertest.MasterTest): + def test_configure(self): + r = replace.Replace() + updated = set(["replacements"]) + r.configure(options.Options( + replacements=[("one", "two", "three")] + ), updated) + tutils.raises( + "invalid filter pattern", + r.configure, + options.Options( + replacements=[("~b", "two", "three")] + ), + updated + ) + tutils.raises( + "invalid regular expression", + r.configure, + options.Options( + replacements=[("foo", "+", "three")] + ), + updated + ) + + def test_simple(self): + o = options.Options( + replacements = [ + ("~q", "foo", "bar"), + ("~s", "foo", "bar"), + ] + ) + m = master.Master(o, proxy.DummyServer()) + sa = replace.Replace() + m.addons.add(sa) + + f = tutils.tflow() + f.request.content = b"foo" + m.request(f) + assert f.request.content == b"bar" + + f = tutils.tflow(resp=True) + f.response.content = b"foo" + m.response(f) + assert f.response.content == b"bar" + + +class TestUpstreamProxy(tservers.HTTPUpstreamProxyTest): + ssl = False + + def test_order(self): + sa = replace.Replace() + self.proxy.tmaster.addons.add(sa) + + self.proxy.tmaster.options.replacements = [ + ("~q", "foo", "bar"), + ("~q", "bar", "baz"), + ("~q", "foo", "oh noes!"), + ("~s", "baz", "ORLY") + ] + p = self.pathoc() + with p.connect(): + req = p.request("get:'%s/p/418:b\"foo\"'" % self.server.urlbase) + assert req.content == b"ORLY" + assert req.status_code == 418 diff --git a/test/mitmproxy/addons/test_script.py b/test/mitmproxy/addons/test_script.py new file mode 100644 index 00000000..83e60fbd --- /dev/null +++ b/test/mitmproxy/addons/test_script.py @@ -0,0 +1,233 @@ +import traceback + +import sys +import time + +import re +from mitmproxy import exceptions +from mitmproxy import options +from mitmproxy import proxy +from mitmproxy.addons import script +from mitmproxy import master + +from .. import tutils, mastertest + + +class TestParseCommand: + def test_empty_command(self): + with tutils.raises(exceptions.AddonError): + script.parse_command("") + + with tutils.raises(exceptions.AddonError): + script.parse_command(" ") + + def test_no_script_file(self): + with tutils.raises("not found"): + script.parse_command("notfound") + + with tutils.tmpdir() as dir: + with tutils.raises("not a file"): + script.parse_command(dir) + + def test_parse_args(self): + with tutils.chdir(tutils.test_data.dirname): + assert script.parse_command("data/addonscripts/recorder.py") == ("data/addonscripts/recorder.py", []) + assert script.parse_command("data/addonscripts/recorder.py foo bar") == ("data/addonscripts/recorder.py", ["foo", "bar"]) + assert script.parse_command("data/addonscripts/recorder.py 'foo bar'") == ("data/addonscripts/recorder.py", ["foo bar"]) + + @tutils.skip_not_windows + def test_parse_windows(self): + with tutils.chdir(tutils.test_data.dirname): + assert script.parse_command( + "data\\addonscripts\\recorder.py" + ) == ("data\\addonscripts\\recorder.py", []) + assert script.parse_command( + "data\\addonscripts\\recorder.py 'foo \\ bar'" + ) == ("data\\addonscripts\\recorder.py", ['foo \\ bar']) + + +def test_load_script(): + ns = script.load_script( + tutils.test_data.path( + "data/addonscripts/recorder.py" + ), [] + ) + assert ns.start + + +class TestScript(mastertest.MasterTest): + def test_simple(self): + o = options.Options() + m = master.Master(o, proxy.DummyServer()) + sc = script.Script( + tutils.test_data.path( + "data/addonscripts/recorder.py" + ) + ) + m.addons.add(sc) + assert sc.ns.call_log == [ + ("solo", "start", (), {}), + ("solo", "configure", (o, o.keys()), {}) + ] + + sc.ns.call_log = [] + f = tutils.tflow(resp=True) + m.request(f) + + recf = sc.ns.call_log[0] + assert recf[1] == "request" + + def test_reload(self): + o = options.Options() + m = mastertest.RecordingMaster(o, proxy.DummyServer()) + with tutils.tmpdir(): + with open("foo.py", "w"): + pass + sc = script.Script("foo.py") + m.addons.add(sc) + + for _ in range(100): + with open("foo.py", "a") as f: + f.write(".") + m.addons.invoke_with_context(sc, "tick") + time.sleep(0.1) + if m.event_log: + return + raise AssertionError("Change event not detected.") + + def test_exception(self): + o = options.Options() + m = mastertest.RecordingMaster(o, proxy.DummyServer()) + sc = script.Script( + tutils.test_data.path("data/addonscripts/error.py") + ) + m.addons.add(sc) + f = tutils.tflow(resp=True) + m.request(f) + assert m.event_log[0][0] == "error" + assert len(m.event_log[0][1].splitlines()) == 6 + assert re.search('addonscripts/error.py", line \d+, in request', m.event_log[0][1]) + assert re.search('addonscripts/error.py", line \d+, in mkerr', m.event_log[0][1]) + assert m.event_log[0][1].endswith("ValueError: Error!\n") + + def test_addon(self): + o = options.Options() + m = master.Master(o, proxy.DummyServer()) + sc = script.Script( + tutils.test_data.path( + "data/addonscripts/addon.py" + ) + ) + m.addons.add(sc) + assert sc.ns.event_log == [ + 'scriptstart', 'addonstart', 'addonconfigure' + ] + + +class TestCutTraceback: + def raise_(self, i): + if i > 0: + self.raise_(i - 1) + raise RuntimeError() + + def test_simple(self): + try: + self.raise_(4) + except RuntimeError: + tb = sys.exc_info()[2] + tb_cut = script.cut_traceback(tb, "test_simple") + assert len(traceback.extract_tb(tb_cut)) == 5 + + tb_cut2 = script.cut_traceback(tb, "nonexistent") + assert len(traceback.extract_tb(tb_cut2)) == len(traceback.extract_tb(tb)) + + +class TestScriptLoader(mastertest.MasterTest): + def test_run_once(self): + o = options.Options(scripts=[]) + m = master.Master(o, proxy.DummyServer()) + sl = script.ScriptLoader() + m.addons.add(sl) + + f = tutils.tflow(resp=True) + with m.handlecontext(): + sc = sl.run_once( + tutils.test_data.path( + "data/addonscripts/recorder.py" + ), [f] + ) + evts = [i[1] for i in sc.ns.call_log] + assert evts == ['start', 'requestheaders', 'request', 'responseheaders', 'response', 'done'] + + with m.handlecontext(): + tutils.raises( + "file not found", + sl.run_once, + "nonexistent", + [f] + ) + + def test_simple(self): + o = options.Options(scripts=[]) + m = master.Master(o, proxy.DummyServer()) + sc = script.ScriptLoader() + m.addons.add(sc) + assert len(m.addons) == 1 + o.update( + scripts = [ + tutils.test_data.path("data/addonscripts/recorder.py") + ] + ) + assert len(m.addons) == 2 + o.update(scripts = []) + assert len(m.addons) == 1 + + def test_dupes(self): + o = options.Options(scripts=["one", "one"]) + m = master.Master(o, proxy.DummyServer()) + sc = script.ScriptLoader() + tutils.raises(exceptions.OptionsError, m.addons.add, o, sc) + + def test_order(self): + rec = tutils.test_data.path("data/addonscripts/recorder.py") + + o = options.Options( + scripts = [ + "%s %s" % (rec, "a"), + "%s %s" % (rec, "b"), + "%s %s" % (rec, "c"), + ] + ) + m = mastertest.RecordingMaster(o, proxy.DummyServer()) + sc = script.ScriptLoader() + m.addons.add(sc) + + debug = [(i[0], i[1]) for i in m.event_log if i[0] == "debug"] + assert debug == [ + ('debug', 'a start'), ('debug', 'a configure'), + ('debug', 'b start'), ('debug', 'b configure'), + ('debug', 'c start'), ('debug', 'c configure') + ] + m.event_log[:] = [] + + o.scripts = [ + "%s %s" % (rec, "c"), + "%s %s" % (rec, "a"), + "%s %s" % (rec, "b"), + ] + debug = [(i[0], i[1]) for i in m.event_log if i[0] == "debug"] + # No events, only order has changed + assert debug == [] + + o.scripts = [ + "%s %s" % (rec, "x"), + "%s %s" % (rec, "a"), + ] + debug = [(i[0], i[1]) for i in m.event_log if i[0] == "debug"] + assert debug == [ + ('debug', 'c done'), + ('debug', 'b done'), + ('debug', 'x start'), + ('debug', 'x configure'), + ('debug', 'a configure'), + ] diff --git a/test/mitmproxy/addons/test_serverplayback.py b/test/mitmproxy/addons/test_serverplayback.py new file mode 100644 index 00000000..649b3c22 --- /dev/null +++ b/test/mitmproxy/addons/test_serverplayback.py @@ -0,0 +1,282 @@ +from .. import tutils, mastertest + +import netlib.tutils +from mitmproxy.addons import serverplayback +from mitmproxy import options +from mitmproxy import proxy +from mitmproxy import exceptions + + +class TestServerPlayback: + def test_server_playback(self): + sp = serverplayback.ServerPlayback() + sp.configure(options.Options(), []) + f = tutils.tflow(resp=True) + + assert not sp.flowmap + + sp.load([f]) + assert sp.flowmap + assert sp.next_flow(f) + assert not sp.flowmap + + def test_ignore_host(self): + sp = serverplayback.ServerPlayback() + sp.configure(options.Options(server_replay_ignore_host=True), []) + + r = tutils.tflow(resp=True) + r2 = tutils.tflow(resp=True) + + r.request.host = "address" + r2.request.host = "address" + assert sp._hash(r) == sp._hash(r2) + r2.request.host = "wrong_address" + assert sp._hash(r) == sp._hash(r2) + + def test_ignore_content(self): + s = serverplayback.ServerPlayback() + s.configure(options.Options(server_replay_ignore_content=False), []) + + r = tutils.tflow(resp=True) + r2 = tutils.tflow(resp=True) + + r.request.content = b"foo" + r2.request.content = b"foo" + assert s._hash(r) == s._hash(r2) + r2.request.content = b"bar" + assert not s._hash(r) == s._hash(r2) + + s.configure(options.Options(server_replay_ignore_content=True), []) + r = tutils.tflow(resp=True) + r2 = tutils.tflow(resp=True) + r.request.content = b"foo" + r2.request.content = b"foo" + assert s._hash(r) == s._hash(r2) + r2.request.content = b"bar" + assert s._hash(r) == s._hash(r2) + r2.request.content = b"" + assert s._hash(r) == s._hash(r2) + r2.request.content = None + assert s._hash(r) == s._hash(r2) + + def test_ignore_content_wins_over_params(self): + s = serverplayback.ServerPlayback() + s.configure( + options.Options( + server_replay_ignore_content=True, + server_replay_ignore_payload_params=[ + "param1", "param2" + ] + ), + [] + ) + # NOTE: parameters are mutually exclusive in options + + r = tutils.tflow(resp=True) + r.request.headers["Content-Type"] = "application/x-www-form-urlencoded" + r.request.content = b"paramx=y" + + r2 = tutils.tflow(resp=True) + r2.request.headers["Content-Type"] = "application/x-www-form-urlencoded" + r2.request.content = b"paramx=x" + + # same parameters + assert s._hash(r) == s._hash(r2) + + def test_ignore_payload_params_other_content_type(self): + s = serverplayback.ServerPlayback() + s.configure( + options.Options( + server_replay_ignore_content=False, + server_replay_ignore_payload_params=[ + "param1", "param2" + ] + ), + [] + + ) + r = tutils.tflow(resp=True) + r.request.headers["Content-Type"] = "application/json" + r.request.content = b'{"param1":"1"}' + r2 = tutils.tflow(resp=True) + r2.request.headers["Content-Type"] = "application/json" + r2.request.content = b'{"param1":"1"}' + # same content + assert s._hash(r) == s._hash(r2) + # distint content (note only x-www-form-urlencoded payload is analysed) + r2.request.content = b'{"param1":"2"}' + assert not s._hash(r) == s._hash(r2) + + def test_hash(self): + s = serverplayback.ServerPlayback() + s.configure(options.Options(), []) + + r = tutils.tflow() + r2 = tutils.tflow() + + assert s._hash(r) + assert s._hash(r) == s._hash(r2) + r.request.headers["foo"] = "bar" + assert s._hash(r) == s._hash(r2) + r.request.path = "voing" + assert s._hash(r) != s._hash(r2) + + r.request.path = "path?blank_value" + r2.request.path = "path?" + assert s._hash(r) != s._hash(r2) + + def test_headers(self): + s = serverplayback.ServerPlayback() + s.configure(options.Options(server_replay_use_headers=["foo"]), []) + + r = tutils.tflow(resp=True) + r.request.headers["foo"] = "bar" + r2 = tutils.tflow(resp=True) + assert not s._hash(r) == s._hash(r2) + r2.request.headers["foo"] = "bar" + assert s._hash(r) == s._hash(r2) + r2.request.headers["oink"] = "bar" + assert s._hash(r) == s._hash(r2) + + r = tutils.tflow(resp=True) + r2 = tutils.tflow(resp=True) + assert s._hash(r) == s._hash(r2) + + def test_load(self): + s = serverplayback.ServerPlayback() + s.configure(options.Options(), []) + + r = tutils.tflow(resp=True) + r.request.headers["key"] = "one" + + r2 = tutils.tflow(resp=True) + r2.request.headers["key"] = "two" + + s.load([r, r2]) + + assert s.count() == 2 + + n = s.next_flow(r) + assert n.request.headers["key"] == "one" + assert s.count() == 1 + + n = s.next_flow(r) + assert n.request.headers["key"] == "two" + assert not s.flowmap + assert s.count() == 0 + + assert not s.next_flow(r) + + def test_load_with_server_replay_nopop(self): + s = serverplayback.ServerPlayback() + s.configure(options.Options(server_replay_nopop=True), []) + + r = tutils.tflow(resp=True) + r.request.headers["key"] = "one" + + r2 = tutils.tflow(resp=True) + r2.request.headers["key"] = "two" + + s.load([r, r2]) + + assert s.count() == 2 + s.next_flow(r) + assert s.count() == 2 + + def test_ignore_params(self): + s = serverplayback.ServerPlayback() + s.configure( + options.Options( + server_replay_ignore_params=["param1", "param2"] + ), + [] + ) + + r = tutils.tflow(resp=True) + r.request.path = "/test?param1=1" + r2 = tutils.tflow(resp=True) + r2.request.path = "/test" + assert s._hash(r) == s._hash(r2) + r2.request.path = "/test?param1=2" + assert s._hash(r) == s._hash(r2) + r2.request.path = "/test?param2=1" + assert s._hash(r) == s._hash(r2) + r2.request.path = "/test?param3=2" + assert not s._hash(r) == s._hash(r2) + + def test_ignore_payload_params(self): + s = serverplayback.ServerPlayback() + s.configure( + options.Options( + server_replay_ignore_payload_params=["param1", "param2"] + ), + [] + ) + + r = tutils.tflow(resp=True) + r.request.headers["Content-Type"] = "application/x-www-form-urlencoded" + r.request.content = b"paramx=x¶m1=1" + r2 = tutils.tflow(resp=True) + r2.request.headers["Content-Type"] = "application/x-www-form-urlencoded" + r2.request.content = b"paramx=x¶m1=1" + # same parameters + assert s._hash(r) == s._hash(r2) + # ignored parameters != + r2.request.content = b"paramx=x¶m1=2" + assert s._hash(r) == s._hash(r2) + # missing parameter + r2.request.content = b"paramx=x" + assert s._hash(r) == s._hash(r2) + # ignorable parameter added + r2.request.content = b"paramx=x¶m1=2" + assert s._hash(r) == s._hash(r2) + # not ignorable parameter changed + r2.request.content = b"paramx=y¶m1=1" + assert not s._hash(r) == s._hash(r2) + # not ignorable parameter missing + r2.request.content = b"param1=1" + assert not s._hash(r) == s._hash(r2) + + def test_server_playback_full(self): + s = serverplayback.ServerPlayback() + o = options.Options(refresh_server_playback = True, keepserving=False) + m = mastertest.RecordingMaster(o, proxy.DummyServer()) + m.addons.add(s) + + f = tutils.tflow() + f.response = netlib.tutils.tresp(content=f.request.content) + s.load([f, f]) + + tf = tutils.tflow() + assert not tf.response + m.request(tf) + assert tf.response == f.response + + tf = tutils.tflow() + tf.request.content = b"gibble" + assert not tf.response + m.request(tf) + assert not tf.response + + assert not s.stop + s.tick() + assert not s.stop + + tf = tutils.tflow() + m.request(tutils.tflow()) + assert s.stop + + def test_server_playback_kill(self): + s = serverplayback.ServerPlayback() + o = options.Options(refresh_server_playback = True, replay_kill_extra=True) + m = mastertest.RecordingMaster(o, proxy.DummyServer()) + m.addons.add(s) + + f = tutils.tflow() + f.response = netlib.tutils.tresp(content=f.request.content) + s.load([f]) + + f = tutils.tflow() + f.request.host = "nonexistent" + m.request(f) + assert f.reply.value == exceptions.Kill diff --git a/test/mitmproxy/addons/test_setheaders.py b/test/mitmproxy/addons/test_setheaders.py new file mode 100644 index 00000000..0fbbd4cb --- /dev/null +++ b/test/mitmproxy/addons/test_setheaders.py @@ -0,0 +1,64 @@ +from .. import tutils, mastertest + +from mitmproxy.addons import setheaders +from mitmproxy import options +from mitmproxy import proxy + + +class TestSetHeaders(mastertest.MasterTest): + def mkmaster(self, **opts): + o = options.Options(**opts) + m = mastertest.RecordingMaster(o, proxy.DummyServer()) + sh = setheaders.SetHeaders() + m.addons.add(sh) + return m, sh + + def test_configure(self): + sh = setheaders.SetHeaders() + o = options.Options( + setheaders = [("~b", "one", "two")] + ) + tutils.raises( + "invalid setheader filter pattern", + sh.configure, o, o.keys() + ) + + def test_setheaders(self): + m, sh = self.mkmaster( + setheaders = [ + ("~q", "one", "two"), + ("~s", "one", "three") + ] + ) + f = tutils.tflow() + f.request.headers["one"] = "xxx" + m.request(f) + assert f.request.headers["one"] == "two" + + f = tutils.tflow(resp=True) + f.response.headers["one"] = "xxx" + m.response(f) + assert f.response.headers["one"] == "three" + + m, sh = self.mkmaster( + setheaders = [ + ("~s", "one", "two"), + ("~s", "one", "three") + ] + ) + f = tutils.tflow(resp=True) + f.request.headers["one"] = "xxx" + f.response.headers["one"] = "xxx" + m.response(f) + assert f.response.headers.get_all("one") == ["two", "three"] + + m, sh = self.mkmaster( + setheaders = [ + ("~q", "one", "two"), + ("~q", "one", "three") + ] + ) + f = tutils.tflow() + f.request.headers["one"] = "xxx" + m.request(f) + assert f.request.headers.get_all("one") == ["two", "three"] diff --git a/test/mitmproxy/addons/test_stickyauth.py b/test/mitmproxy/addons/test_stickyauth.py new file mode 100644 index 00000000..459dc5f7 --- /dev/null +++ b/test/mitmproxy/addons/test_stickyauth.py @@ -0,0 +1,23 @@ +from .. import tutils, mastertest +from mitmproxy.addons import stickyauth +from mitmproxy import master +from mitmproxy import options +from mitmproxy import proxy + + +class TestStickyAuth(mastertest.MasterTest): + def test_simple(self): + o = options.Options(stickyauth = ".*") + m = master.Master(o, proxy.DummyServer()) + sa = stickyauth.StickyAuth() + m.addons.add(sa) + + f = tutils.tflow(resp=True) + f.request.headers["authorization"] = "foo" + m.request(f) + + assert "address" in sa.hosts + + f = tutils.tflow(resp=True) + m.request(f) + assert f.request.headers["authorization"] == "foo" diff --git a/test/mitmproxy/addons/test_stickycookie.py b/test/mitmproxy/addons/test_stickycookie.py new file mode 100644 index 00000000..29c9e198 --- /dev/null +++ b/test/mitmproxy/addons/test_stickycookie.py @@ -0,0 +1,130 @@ +from .. import tutils, mastertest +from mitmproxy.addons import stickycookie +from mitmproxy import master +from mitmproxy import options +from mitmproxy import proxy +from netlib import tutils as ntutils + + +def test_domain_match(): + assert stickycookie.domain_match("www.google.com", ".google.com") + assert stickycookie.domain_match("google.com", ".google.com") + + +class TestStickyCookie(mastertest.MasterTest): + def mk(self): + o = options.Options(stickycookie = ".*") + m = master.Master(o, proxy.DummyServer()) + sc = stickycookie.StickyCookie() + m.addons.add(sc) + return m, sc + + def test_config(self): + sc = stickycookie.StickyCookie() + o = options.Options(stickycookie = "~b") + tutils.raises( + "invalid filter", + sc.configure, o, o.keys() + ) + + def test_simple(self): + m, sc = self.mk() + m.addons.add(sc) + + f = tutils.tflow(resp=True) + f.response.headers["set-cookie"] = "foo=bar" + m.request(f) + + f.reply.acked = False + m.response(f) + + assert sc.jar + assert "cookie" not in f.request.headers + + f = f.copy() + f.reply.acked = False + m.request(f) + assert f.request.headers["cookie"] == "foo=bar" + + def _response(self, m, sc, cookie, host): + f = tutils.tflow(req=ntutils.treq(host=host, port=80), resp=True) + f.response.headers["Set-Cookie"] = cookie + m.response(f) + return f + + def test_response(self): + m, sc = self.mk() + + c = "SSID=mooo; domain=.google.com, FOO=bar; Domain=.google.com; Path=/; " \ + "Expires=Wed, 13-Jan-2021 22:23:01 GMT; Secure; " + + self._response(m, sc, c, "host") + assert not sc.jar.keys() + + self._response(m, sc, c, "www.google.com") + assert sc.jar.keys() + + sc.jar.clear() + self._response( + m, sc, "SSID=mooo", "www.google.com" + ) + assert list(sc.jar.keys())[0] == ('www.google.com', 80, '/') + + def test_response_multiple(self): + m, sc = self.mk() + + # Test setting of multiple cookies + c1 = "somecookie=test; Path=/" + c2 = "othercookie=helloworld; Path=/" + f = self._response(m, sc, c1, "www.google.com") + f.response.headers["Set-Cookie"] = c2 + m.response(f) + googlekey = list(sc.jar.keys())[0] + assert len(sc.jar[googlekey].keys()) == 2 + + def test_response_weird(self): + m, sc = self.mk() + + # Test setting of weird cookie keys + f = tutils.tflow(req=ntutils.treq(host="www.google.com", port=80), resp=True) + cs = [ + "foo/bar=hello", + "foo:bar=world", + "foo@bar=fizz", + ] + for c in cs: + f.response.headers["Set-Cookie"] = c + m.response(f) + googlekey = list(sc.jar.keys())[0] + assert len(sc.jar[googlekey].keys()) == len(cs) + + def test_response_overwrite(self): + m, sc = self.mk() + + # Test overwriting of a cookie value + c1 = "somecookie=helloworld; Path=/" + c2 = "somecookie=newvalue; Path=/" + f = self._response(m, sc, c1, "www.google.com") + f.response.headers["Set-Cookie"] = c2 + m.response(f) + googlekey = list(sc.jar.keys())[0] + assert len(sc.jar[googlekey].keys()) == 1 + assert list(sc.jar[googlekey]["somecookie"].items())[0][1] == "newvalue" + + def test_response_delete(self): + m, sc = self.mk() + + # Test that a cookie is be deleted + # by setting the expire time in the past + f = self._response(m, sc, "duffer=zafar; Path=/", "www.google.com") + f.response.headers["Set-Cookie"] = "duffer=; Expires=Thu, 01-Jan-1970 00:00:00 GMT" + m.response(f) + assert not sc.jar.keys() + + def test_request(self): + m, sc = self.mk() + + f = self._response(m, sc, "SSID=mooo", "www.google.com") + assert "cookie" not in f.request.headers + m.request(f) + assert "cookie" in f.request.headers diff --git a/test/mitmproxy/addons/test_streambodies.py b/test/mitmproxy/addons/test_streambodies.py new file mode 100644 index 00000000..cf416c86 --- /dev/null +++ b/test/mitmproxy/addons/test_streambodies.py @@ -0,0 +1,28 @@ +from .. import tutils, mastertest +from mitmproxy import master +from mitmproxy import options +from mitmproxy import proxy + +from mitmproxy.addons import streambodies + + +class TestStreamBodies(mastertest.MasterTest): + def test_simple(self): + o = options.Options(stream_large_bodies = 10) + m = master.Master(o, proxy.DummyServer()) + sa = streambodies.StreamBodies() + m.addons.add(sa) + + f = tutils.tflow() + f.request.content = b"" + f.request.headers["Content-Length"] = "1024" + assert not f.request.stream + m.requestheaders(f) + assert f.request.stream + + f = tutils.tflow(resp=True) + f.response.content = b"" + f.response.headers["Content-Length"] = "1024" + assert not f.response.stream + m.responseheaders(f) + assert f.response.stream diff --git a/test/mitmproxy/addons/test_termlog.py b/test/mitmproxy/addons/test_termlog.py new file mode 100644 index 00000000..a9f18a51 --- /dev/null +++ b/test/mitmproxy/addons/test_termlog.py @@ -0,0 +1,17 @@ +from .. import mastertest +import io + +from mitmproxy.addons import termlog +from mitmproxy import log +from mitmproxy import dump + + +class TestTermLog(mastertest.MasterTest): + def test_simple(self): + t = termlog.TermLog() + sio = io.StringIO() + t.configure(dump.Options(tfile = sio, verbosity = 2), set([])) + t.log(log.LogEntry("one", "info")) + assert "one" in sio.getvalue() + t.log(log.LogEntry("two", "debug")) + assert "two" not in sio.getvalue() diff --git a/test/mitmproxy/addons/test_wsgiapp.py b/test/mitmproxy/addons/test_wsgiapp.py new file mode 100644 index 00000000..760ee460 --- /dev/null +++ b/test/mitmproxy/addons/test_wsgiapp.py @@ -0,0 +1,41 @@ +import flask + +from .. import tservers +from mitmproxy.addons import wsgiapp + +tapp = flask.Flask(__name__) + + +@tapp.route("/") +def hello(): + return "testapp" + + +@tapp.route("/error") +def error(): + raise ValueError("An exception...") + + +def errapp(environ, start_response): + raise ValueError("errapp") + + +class TestApp(tservers.HTTPProxyTest): + def addons(self): + return [ + wsgiapp.WSGIApp(tapp, "testapp", 80), + wsgiapp.WSGIApp(errapp, "errapp", 80) + ] + + def test_simple(self): + p = self.pathoc() + with p.connect(): + ret = p.request("get:'http://testapp/'") + assert ret.status_code == 200 + + def test_app_err(self): + p = self.pathoc() + with p.connect(): + ret = p.request("get:'http://errapp/'") + assert ret.status_code == 500 + assert b"ValueError" in ret.content diff --git a/test/mitmproxy/builtins/__init__.py b/test/mitmproxy/builtins/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/test/mitmproxy/builtins/test_anticache.py b/test/mitmproxy/builtins/test_anticache.py deleted file mode 100644 index 790ae97d..00000000 --- a/test/mitmproxy/builtins/test_anticache.py +++ /dev/null @@ -1,23 +0,0 @@ -from .. import tutils, mastertest -from mitmproxy.builtins import anticache -from mitmproxy import master -from mitmproxy import options -from mitmproxy import proxy - - -class TestAntiCache(mastertest.MasterTest): - def test_simple(self): - o = options.Options(anticache = True) - m = master.Master(o, proxy.DummyServer()) - sa = anticache.AntiCache() - m.addons.add(sa) - - f = tutils.tflow(resp=True) - m.request(f) - - f = tutils.tflow(resp=True) - f.request.headers["if-modified-since"] = "test" - f.request.headers["if-none-match"] = "test" - m.request(f) - assert "if-modified-since" not in f.request.headers - assert "if-none-match" not in f.request.headers diff --git a/test/mitmproxy/builtins/test_anticomp.py b/test/mitmproxy/builtins/test_anticomp.py deleted file mode 100644 index d5a0d6eb..00000000 --- a/test/mitmproxy/builtins/test_anticomp.py +++ /dev/null @@ -1,22 +0,0 @@ -from .. import tutils, mastertest -from mitmproxy.builtins import anticomp -from mitmproxy import master -from mitmproxy import options -from mitmproxy import proxy - - -class TestAntiComp(mastertest.MasterTest): - def test_simple(self): - o = options.Options(anticomp = True) - m = master.Master(o, proxy.DummyServer()) - sa = anticomp.AntiComp() - m.addons.add(sa) - - f = tutils.tflow(resp=True) - m.request(f) - - f = tutils.tflow(resp=True) - - f.request.headers["Accept-Encoding"] = "foobar" - m.request(f) - assert f.request.headers["Accept-Encoding"] == "identity" diff --git a/test/mitmproxy/builtins/test_clientplayback.py b/test/mitmproxy/builtins/test_clientplayback.py deleted file mode 100644 index e2c5be7e..00000000 --- a/test/mitmproxy/builtins/test_clientplayback.py +++ /dev/null @@ -1,37 +0,0 @@ -import mock - -from mitmproxy.builtins import clientplayback -from mitmproxy import options - -from .. import tutils, mastertest - - -class TestClientPlayback: - def test_playback(self): - cp = clientplayback.ClientPlayback() - cp.configure(options.Options(), []) - assert cp.count() == 0 - f = tutils.tflow(resp=True) - cp.load([f]) - assert cp.count() == 1 - RP = "mitmproxy.protocol.http_replay.RequestReplayThread" - with mock.patch(RP) as rp: - assert not cp.current - with mastertest.mockctx(): - cp.tick() - rp.assert_called() - assert cp.current - - cp.keepserving = False - cp.flows = None - cp.current = None - with mock.patch("mitmproxy.master.Master.shutdown") as sd: - with mastertest.mockctx(): - cp.tick() - sd.assert_called() - - def test_configure(self): - cp = clientplayback.ClientPlayback() - cp.configure( - options.Options(), [] - ) diff --git a/test/mitmproxy/builtins/test_dumper.py b/test/mitmproxy/builtins/test_dumper.py deleted file mode 100644 index d5291bc4..00000000 --- a/test/mitmproxy/builtins/test_dumper.py +++ /dev/null @@ -1,84 +0,0 @@ -import io - -from .. import tutils, mastertest - -from mitmproxy.builtins import dumper -from mitmproxy import exceptions -from mitmproxy import dump -from mitmproxy import models -from mitmproxy import proxy -import netlib.tutils -import mock - - -class TestDumper(mastertest.MasterTest): - def test_simple(self): - d = dumper.Dumper() - sio = io.StringIO() - - updated = {"tfile", "flow_detail"} - d.configure(dump.Options(tfile = sio, flow_detail = 0), updated) - d.response(tutils.tflow()) - assert not sio.getvalue() - - d.configure(dump.Options(tfile = sio, flow_detail = 4), updated) - d.response(tutils.tflow()) - assert sio.getvalue() - - sio = io.StringIO() - d.configure(dump.Options(tfile = sio, flow_detail = 4), updated) - d.response(tutils.tflow(resp=True)) - assert "<<" in sio.getvalue() - - sio = io.StringIO() - d.configure(dump.Options(tfile = sio, flow_detail = 4), updated) - d.response(tutils.tflow(err=True)) - assert "<<" in sio.getvalue() - - sio = io.StringIO() - d.configure(dump.Options(tfile = sio, flow_detail = 4), updated) - flow = tutils.tflow() - flow.request = netlib.tutils.treq() - flow.request.stickycookie = True - flow.client_conn = mock.MagicMock() - flow.client_conn.address.host = "foo" - flow.response = netlib.tutils.tresp(content=None) - flow.response.is_replay = True - flow.response.status_code = 300 - d.response(flow) - assert sio.getvalue() - - sio = io.StringIO() - d.configure(dump.Options(tfile = sio, flow_detail = 4), updated) - flow = tutils.tflow(resp=netlib.tutils.tresp(content=b"{")) - flow.response.headers["content-type"] = "application/json" - flow.response.status_code = 400 - d.response(flow) - assert sio.getvalue() - - sio = io.StringIO() - d.configure(dump.Options(tfile = sio), updated) - flow = tutils.tflow() - flow.request.content = None - flow.response = models.HTTPResponse.wrap(netlib.tutils.tresp()) - flow.response.content = None - d.response(flow) - assert "content missing" in sio.getvalue() - - -class TestContentView(mastertest.MasterTest): - @mock.patch("mitmproxy.contentviews.ViewAuto.__call__") - def test_contentview(self, view_auto): - view_auto.side_effect = exceptions.ContentViewException("") - - sio = io.StringIO() - o = dump.Options( - flow_detail=4, - verbosity=3, - tfile=sio, - ) - m = mastertest.RecordingMaster(o, proxy.DummyServer()) - d = dumper.Dumper() - m.addons.add(d) - m.response(tutils.tflow()) - assert "Content viewer failed" in m.event_log[0][1] diff --git a/test/mitmproxy/builtins/test_filestreamer.py b/test/mitmproxy/builtins/test_filestreamer.py deleted file mode 100644 index 35fe1ca2..00000000 --- a/test/mitmproxy/builtins/test_filestreamer.py +++ /dev/null @@ -1,41 +0,0 @@ -from .. import tutils, mastertest - -import os.path - -from mitmproxy.builtins import filestreamer -from mitmproxy import master -from mitmproxy.flow import io -from mitmproxy import options -from mitmproxy import proxy - - -class TestStream(mastertest.MasterTest): - def test_stream(self): - with tutils.tmpdir() as tdir: - p = os.path.join(tdir, "foo") - - def r(): - r = io.FlowReader(open(p, "rb")) - return list(r.stream()) - - o = options.Options( - outfile = (p, "wb") - ) - m = master.Master(o, proxy.DummyServer()) - sa = filestreamer.FileStreamer() - - m.addons.add(sa) - f = tutils.tflow(resp=True) - m.request(f) - m.response(f) - m.addons.remove(sa) - - assert r()[0].response - - m.options.outfile = (p, "ab") - - m.addons.add(sa) - f = tutils.tflow() - m.request(f) - m.addons.remove(sa) - assert not r()[1].response diff --git a/test/mitmproxy/builtins/test_onboarding.py b/test/mitmproxy/builtins/test_onboarding.py deleted file mode 100644 index 3226aec3..00000000 --- a/test/mitmproxy/builtins/test_onboarding.py +++ /dev/null @@ -1,16 +0,0 @@ -from mitmproxy.builtins import onboarding -from .. import tservers - - -class TestApp(tservers.HTTPProxyTest): - def addons(self): - return [onboarding.Onboarding()] - - def test_basic(self): - assert self.app("/").status_code == 200 - - def test_cert(self): - for ext in ["pem", "p12"]: - resp = self.app("/cert/%s" % ext) - assert resp.status_code == 200 - assert resp.content diff --git a/test/mitmproxy/builtins/test_replace.py b/test/mitmproxy/builtins/test_replace.py deleted file mode 100644 index 35f3d430..00000000 --- a/test/mitmproxy/builtins/test_replace.py +++ /dev/null @@ -1,71 +0,0 @@ -from .. import tutils, mastertest, tservers -from mitmproxy.builtins import replace -from mitmproxy import master -from mitmproxy import options -from mitmproxy import proxy - - -class TestReplace(mastertest.MasterTest): - def test_configure(self): - r = replace.Replace() - updated = set(["replacements"]) - r.configure(options.Options( - replacements=[("one", "two", "three")] - ), updated) - tutils.raises( - "invalid filter pattern", - r.configure, - options.Options( - replacements=[("~b", "two", "three")] - ), - updated - ) - tutils.raises( - "invalid regular expression", - r.configure, - options.Options( - replacements=[("foo", "+", "three")] - ), - updated - ) - - def test_simple(self): - o = options.Options( - replacements = [ - ("~q", "foo", "bar"), - ("~s", "foo", "bar"), - ] - ) - m = master.Master(o, proxy.DummyServer()) - sa = replace.Replace() - m.addons.add(sa) - - f = tutils.tflow() - f.request.content = b"foo" - m.request(f) - assert f.request.content == b"bar" - - f = tutils.tflow(resp=True) - f.response.content = b"foo" - m.response(f) - assert f.response.content == b"bar" - - -class TestUpstreamProxy(tservers.HTTPUpstreamProxyTest): - ssl = False - - def test_order(self): - sa = replace.Replace() - self.proxy.tmaster.addons.add(sa) - - self.proxy.tmaster.options.replacements = [ - ("~q", "foo", "bar"), - ("~q", "bar", "baz"), - ("~q", "foo", "oh noes!"), - ("~s", "baz", "ORLY") - ] - p = self.pathoc() - with p.connect(): - req = p.request("get:'%s/p/418:b\"foo\"'" % self.server.urlbase) - assert req.content == b"ORLY" - assert req.status_code == 418 diff --git a/test/mitmproxy/builtins/test_script.py b/test/mitmproxy/builtins/test_script.py deleted file mode 100644 index ab4343b5..00000000 --- a/test/mitmproxy/builtins/test_script.py +++ /dev/null @@ -1,233 +0,0 @@ -import traceback - -import sys -import time - -import re -from mitmproxy import exceptions -from mitmproxy import options -from mitmproxy import proxy -from mitmproxy.builtins import script -from mitmproxy import master - -from .. import tutils, mastertest - - -class TestParseCommand: - def test_empty_command(self): - with tutils.raises(exceptions.AddonError): - script.parse_command("") - - with tutils.raises(exceptions.AddonError): - script.parse_command(" ") - - def test_no_script_file(self): - with tutils.raises("not found"): - script.parse_command("notfound") - - with tutils.tmpdir() as dir: - with tutils.raises("not a file"): - script.parse_command(dir) - - def test_parse_args(self): - with tutils.chdir(tutils.test_data.dirname): - assert script.parse_command("data/addonscripts/recorder.py") == ("data/addonscripts/recorder.py", []) - assert script.parse_command("data/addonscripts/recorder.py foo bar") == ("data/addonscripts/recorder.py", ["foo", "bar"]) - assert script.parse_command("data/addonscripts/recorder.py 'foo bar'") == ("data/addonscripts/recorder.py", ["foo bar"]) - - @tutils.skip_not_windows - def test_parse_windows(self): - with tutils.chdir(tutils.test_data.dirname): - assert script.parse_command( - "data\\addonscripts\\recorder.py" - ) == ("data\\addonscripts\\recorder.py", []) - assert script.parse_command( - "data\\addonscripts\\recorder.py 'foo \\ bar'" - ) == ("data\\addonscripts\\recorder.py", ['foo \\ bar']) - - -def test_load_script(): - ns = script.load_script( - tutils.test_data.path( - "data/addonscripts/recorder.py" - ), [] - ) - assert ns.start - - -class TestScript(mastertest.MasterTest): - def test_simple(self): - o = options.Options() - m = master.Master(o, proxy.DummyServer()) - sc = script.Script( - tutils.test_data.path( - "data/addonscripts/recorder.py" - ) - ) - m.addons.add(sc) - assert sc.ns.call_log == [ - ("solo", "start", (), {}), - ("solo", "configure", (o, o.keys()), {}) - ] - - sc.ns.call_log = [] - f = tutils.tflow(resp=True) - m.request(f) - - recf = sc.ns.call_log[0] - assert recf[1] == "request" - - def test_reload(self): - o = options.Options() - m = mastertest.RecordingMaster(o, proxy.DummyServer()) - with tutils.tmpdir(): - with open("foo.py", "w"): - pass - sc = script.Script("foo.py") - m.addons.add(sc) - - for _ in range(100): - with open("foo.py", "a") as f: - f.write(".") - m.addons.invoke_with_context(sc, "tick") - time.sleep(0.1) - if m.event_log: - return - raise AssertionError("Change event not detected.") - - def test_exception(self): - o = options.Options() - m = mastertest.RecordingMaster(o, proxy.DummyServer()) - sc = script.Script( - tutils.test_data.path("data/addonscripts/error.py") - ) - m.addons.add(sc) - f = tutils.tflow(resp=True) - m.request(f) - assert m.event_log[0][0] == "error" - assert len(m.event_log[0][1].splitlines()) == 6 - assert re.search('addonscripts/error.py", line \d+, in request', m.event_log[0][1]) - assert re.search('addonscripts/error.py", line \d+, in mkerr', m.event_log[0][1]) - assert m.event_log[0][1].endswith("ValueError: Error!\n") - - def test_addon(self): - o = options.Options() - m = master.Master(o, proxy.DummyServer()) - sc = script.Script( - tutils.test_data.path( - "data/addonscripts/addon.py" - ) - ) - m.addons.add(sc) - assert sc.ns.event_log == [ - 'scriptstart', 'addonstart', 'addonconfigure' - ] - - -class TestCutTraceback: - def raise_(self, i): - if i > 0: - self.raise_(i - 1) - raise RuntimeError() - - def test_simple(self): - try: - self.raise_(4) - except RuntimeError: - tb = sys.exc_info()[2] - tb_cut = script.cut_traceback(tb, "test_simple") - assert len(traceback.extract_tb(tb_cut)) == 5 - - tb_cut2 = script.cut_traceback(tb, "nonexistent") - assert len(traceback.extract_tb(tb_cut2)) == len(traceback.extract_tb(tb)) - - -class TestScriptLoader(mastertest.MasterTest): - def test_run_once(self): - o = options.Options(scripts=[]) - m = master.Master(o, proxy.DummyServer()) - sl = script.ScriptLoader() - m.addons.add(sl) - - f = tutils.tflow(resp=True) - with m.handlecontext(): - sc = sl.run_once( - tutils.test_data.path( - "data/addonscripts/recorder.py" - ), [f] - ) - evts = [i[1] for i in sc.ns.call_log] - assert evts == ['start', 'requestheaders', 'request', 'responseheaders', 'response', 'done'] - - with m.handlecontext(): - tutils.raises( - "file not found", - sl.run_once, - "nonexistent", - [f] - ) - - def test_simple(self): - o = options.Options(scripts=[]) - m = master.Master(o, proxy.DummyServer()) - sc = script.ScriptLoader() - m.addons.add(sc) - assert len(m.addons) == 1 - o.update( - scripts = [ - tutils.test_data.path("data/addonscripts/recorder.py") - ] - ) - assert len(m.addons) == 2 - o.update(scripts = []) - assert len(m.addons) == 1 - - def test_dupes(self): - o = options.Options(scripts=["one", "one"]) - m = master.Master(o, proxy.DummyServer()) - sc = script.ScriptLoader() - tutils.raises(exceptions.OptionsError, m.addons.add, o, sc) - - def test_order(self): - rec = tutils.test_data.path("data/addonscripts/recorder.py") - - o = options.Options( - scripts = [ - "%s %s" % (rec, "a"), - "%s %s" % (rec, "b"), - "%s %s" % (rec, "c"), - ] - ) - m = mastertest.RecordingMaster(o, proxy.DummyServer()) - sc = script.ScriptLoader() - m.addons.add(sc) - - debug = [(i[0], i[1]) for i in m.event_log if i[0] == "debug"] - assert debug == [ - ('debug', 'a start'), ('debug', 'a configure'), - ('debug', 'b start'), ('debug', 'b configure'), - ('debug', 'c start'), ('debug', 'c configure') - ] - m.event_log[:] = [] - - o.scripts = [ - "%s %s" % (rec, "c"), - "%s %s" % (rec, "a"), - "%s %s" % (rec, "b"), - ] - debug = [(i[0], i[1]) for i in m.event_log if i[0] == "debug"] - # No events, only order has changed - assert debug == [] - - o.scripts = [ - "%s %s" % (rec, "x"), - "%s %s" % (rec, "a"), - ] - debug = [(i[0], i[1]) for i in m.event_log if i[0] == "debug"] - assert debug == [ - ('debug', 'c done'), - ('debug', 'b done'), - ('debug', 'x start'), - ('debug', 'x configure'), - ('debug', 'a configure'), - ] diff --git a/test/mitmproxy/builtins/test_serverplayback.py b/test/mitmproxy/builtins/test_serverplayback.py deleted file mode 100644 index c51814f5..00000000 --- a/test/mitmproxy/builtins/test_serverplayback.py +++ /dev/null @@ -1,282 +0,0 @@ -from .. import tutils, mastertest - -import netlib.tutils -from mitmproxy.builtins import serverplayback -from mitmproxy import options -from mitmproxy import proxy -from mitmproxy import exceptions - - -class TestServerPlayback: - def test_server_playback(self): - sp = serverplayback.ServerPlayback() - sp.configure(options.Options(), []) - f = tutils.tflow(resp=True) - - assert not sp.flowmap - - sp.load([f]) - assert sp.flowmap - assert sp.next_flow(f) - assert not sp.flowmap - - def test_ignore_host(self): - sp = serverplayback.ServerPlayback() - sp.configure(options.Options(server_replay_ignore_host=True), []) - - r = tutils.tflow(resp=True) - r2 = tutils.tflow(resp=True) - - r.request.host = "address" - r2.request.host = "address" - assert sp._hash(r) == sp._hash(r2) - r2.request.host = "wrong_address" - assert sp._hash(r) == sp._hash(r2) - - def test_ignore_content(self): - s = serverplayback.ServerPlayback() - s.configure(options.Options(server_replay_ignore_content=False), []) - - r = tutils.tflow(resp=True) - r2 = tutils.tflow(resp=True) - - r.request.content = b"foo" - r2.request.content = b"foo" - assert s._hash(r) == s._hash(r2) - r2.request.content = b"bar" - assert not s._hash(r) == s._hash(r2) - - s.configure(options.Options(server_replay_ignore_content=True), []) - r = tutils.tflow(resp=True) - r2 = tutils.tflow(resp=True) - r.request.content = b"foo" - r2.request.content = b"foo" - assert s._hash(r) == s._hash(r2) - r2.request.content = b"bar" - assert s._hash(r) == s._hash(r2) - r2.request.content = b"" - assert s._hash(r) == s._hash(r2) - r2.request.content = None - assert s._hash(r) == s._hash(r2) - - def test_ignore_content_wins_over_params(self): - s = serverplayback.ServerPlayback() - s.configure( - options.Options( - server_replay_ignore_content=True, - server_replay_ignore_payload_params=[ - "param1", "param2" - ] - ), - [] - ) - # NOTE: parameters are mutually exclusive in options - - r = tutils.tflow(resp=True) - r.request.headers["Content-Type"] = "application/x-www-form-urlencoded" - r.request.content = b"paramx=y" - - r2 = tutils.tflow(resp=True) - r2.request.headers["Content-Type"] = "application/x-www-form-urlencoded" - r2.request.content = b"paramx=x" - - # same parameters - assert s._hash(r) == s._hash(r2) - - def test_ignore_payload_params_other_content_type(self): - s = serverplayback.ServerPlayback() - s.configure( - options.Options( - server_replay_ignore_content=False, - server_replay_ignore_payload_params=[ - "param1", "param2" - ] - ), - [] - - ) - r = tutils.tflow(resp=True) - r.request.headers["Content-Type"] = "application/json" - r.request.content = b'{"param1":"1"}' - r2 = tutils.tflow(resp=True) - r2.request.headers["Content-Type"] = "application/json" - r2.request.content = b'{"param1":"1"}' - # same content - assert s._hash(r) == s._hash(r2) - # distint content (note only x-www-form-urlencoded payload is analysed) - r2.request.content = b'{"param1":"2"}' - assert not s._hash(r) == s._hash(r2) - - def test_hash(self): - s = serverplayback.ServerPlayback() - s.configure(options.Options(), []) - - r = tutils.tflow() - r2 = tutils.tflow() - - assert s._hash(r) - assert s._hash(r) == s._hash(r2) - r.request.headers["foo"] = "bar" - assert s._hash(r) == s._hash(r2) - r.request.path = "voing" - assert s._hash(r) != s._hash(r2) - - r.request.path = "path?blank_value" - r2.request.path = "path?" - assert s._hash(r) != s._hash(r2) - - def test_headers(self): - s = serverplayback.ServerPlayback() - s.configure(options.Options(server_replay_use_headers=["foo"]), []) - - r = tutils.tflow(resp=True) - r.request.headers["foo"] = "bar" - r2 = tutils.tflow(resp=True) - assert not s._hash(r) == s._hash(r2) - r2.request.headers["foo"] = "bar" - assert s._hash(r) == s._hash(r2) - r2.request.headers["oink"] = "bar" - assert s._hash(r) == s._hash(r2) - - r = tutils.tflow(resp=True) - r2 = tutils.tflow(resp=True) - assert s._hash(r) == s._hash(r2) - - def test_load(self): - s = serverplayback.ServerPlayback() - s.configure(options.Options(), []) - - r = tutils.tflow(resp=True) - r.request.headers["key"] = "one" - - r2 = tutils.tflow(resp=True) - r2.request.headers["key"] = "two" - - s.load([r, r2]) - - assert s.count() == 2 - - n = s.next_flow(r) - assert n.request.headers["key"] == "one" - assert s.count() == 1 - - n = s.next_flow(r) - assert n.request.headers["key"] == "two" - assert not s.flowmap - assert s.count() == 0 - - assert not s.next_flow(r) - - def test_load_with_server_replay_nopop(self): - s = serverplayback.ServerPlayback() - s.configure(options.Options(server_replay_nopop=True), []) - - r = tutils.tflow(resp=True) - r.request.headers["key"] = "one" - - r2 = tutils.tflow(resp=True) - r2.request.headers["key"] = "two" - - s.load([r, r2]) - - assert s.count() == 2 - s.next_flow(r) - assert s.count() == 2 - - def test_ignore_params(self): - s = serverplayback.ServerPlayback() - s.configure( - options.Options( - server_replay_ignore_params=["param1", "param2"] - ), - [] - ) - - r = tutils.tflow(resp=True) - r.request.path = "/test?param1=1" - r2 = tutils.tflow(resp=True) - r2.request.path = "/test" - assert s._hash(r) == s._hash(r2) - r2.request.path = "/test?param1=2" - assert s._hash(r) == s._hash(r2) - r2.request.path = "/test?param2=1" - assert s._hash(r) == s._hash(r2) - r2.request.path = "/test?param3=2" - assert not s._hash(r) == s._hash(r2) - - def test_ignore_payload_params(self): - s = serverplayback.ServerPlayback() - s.configure( - options.Options( - server_replay_ignore_payload_params=["param1", "param2"] - ), - [] - ) - - r = tutils.tflow(resp=True) - r.request.headers["Content-Type"] = "application/x-www-form-urlencoded" - r.request.content = b"paramx=x¶m1=1" - r2 = tutils.tflow(resp=True) - r2.request.headers["Content-Type"] = "application/x-www-form-urlencoded" - r2.request.content = b"paramx=x¶m1=1" - # same parameters - assert s._hash(r) == s._hash(r2) - # ignored parameters != - r2.request.content = b"paramx=x¶m1=2" - assert s._hash(r) == s._hash(r2) - # missing parameter - r2.request.content = b"paramx=x" - assert s._hash(r) == s._hash(r2) - # ignorable parameter added - r2.request.content = b"paramx=x¶m1=2" - assert s._hash(r) == s._hash(r2) - # not ignorable parameter changed - r2.request.content = b"paramx=y¶m1=1" - assert not s._hash(r) == s._hash(r2) - # not ignorable parameter missing - r2.request.content = b"param1=1" - assert not s._hash(r) == s._hash(r2) - - def test_server_playback_full(self): - s = serverplayback.ServerPlayback() - o = options.Options(refresh_server_playback = True, keepserving=False) - m = mastertest.RecordingMaster(o, proxy.DummyServer()) - m.addons.add(s) - - f = tutils.tflow() - f.response = netlib.tutils.tresp(content=f.request.content) - s.load([f, f]) - - tf = tutils.tflow() - assert not tf.response - m.request(tf) - assert tf.response == f.response - - tf = tutils.tflow() - tf.request.content = b"gibble" - assert not tf.response - m.request(tf) - assert not tf.response - - assert not s.stop - s.tick() - assert not s.stop - - tf = tutils.tflow() - m.request(tutils.tflow()) - assert s.stop - - def test_server_playback_kill(self): - s = serverplayback.ServerPlayback() - o = options.Options(refresh_server_playback = True, replay_kill_extra=True) - m = mastertest.RecordingMaster(o, proxy.DummyServer()) - m.addons.add(s) - - f = tutils.tflow() - f.response = netlib.tutils.tresp(content=f.request.content) - s.load([f]) - - f = tutils.tflow() - f.request.host = "nonexistent" - m.request(f) - assert f.reply.value == exceptions.Kill diff --git a/test/mitmproxy/builtins/test_setheaders.py b/test/mitmproxy/builtins/test_setheaders.py deleted file mode 100644 index bac8b02e..00000000 --- a/test/mitmproxy/builtins/test_setheaders.py +++ /dev/null @@ -1,64 +0,0 @@ -from .. import tutils, mastertest - -from mitmproxy.builtins import setheaders -from mitmproxy import options -from mitmproxy import proxy - - -class TestSetHeaders(mastertest.MasterTest): - def mkmaster(self, **opts): - o = options.Options(**opts) - m = mastertest.RecordingMaster(o, proxy.DummyServer()) - sh = setheaders.SetHeaders() - m.addons.add(sh) - return m, sh - - def test_configure(self): - sh = setheaders.SetHeaders() - o = options.Options( - setheaders = [("~b", "one", "two")] - ) - tutils.raises( - "invalid setheader filter pattern", - sh.configure, o, o.keys() - ) - - def test_setheaders(self): - m, sh = self.mkmaster( - setheaders = [ - ("~q", "one", "two"), - ("~s", "one", "three") - ] - ) - f = tutils.tflow() - f.request.headers["one"] = "xxx" - m.request(f) - assert f.request.headers["one"] == "two" - - f = tutils.tflow(resp=True) - f.response.headers["one"] = "xxx" - m.response(f) - assert f.response.headers["one"] == "three" - - m, sh = self.mkmaster( - setheaders = [ - ("~s", "one", "two"), - ("~s", "one", "three") - ] - ) - f = tutils.tflow(resp=True) - f.request.headers["one"] = "xxx" - f.response.headers["one"] = "xxx" - m.response(f) - assert f.response.headers.get_all("one") == ["two", "three"] - - m, sh = self.mkmaster( - setheaders = [ - ("~q", "one", "two"), - ("~q", "one", "three") - ] - ) - f = tutils.tflow() - f.request.headers["one"] = "xxx" - m.request(f) - assert f.request.headers.get_all("one") == ["two", "three"] diff --git a/test/mitmproxy/builtins/test_stickyauth.py b/test/mitmproxy/builtins/test_stickyauth.py deleted file mode 100644 index 22523548..00000000 --- a/test/mitmproxy/builtins/test_stickyauth.py +++ /dev/null @@ -1,23 +0,0 @@ -from .. import tutils, mastertest -from mitmproxy.builtins import stickyauth -from mitmproxy import master -from mitmproxy import options -from mitmproxy import proxy - - -class TestStickyAuth(mastertest.MasterTest): - def test_simple(self): - o = options.Options(stickyauth = ".*") - m = master.Master(o, proxy.DummyServer()) - sa = stickyauth.StickyAuth() - m.addons.add(sa) - - f = tutils.tflow(resp=True) - f.request.headers["authorization"] = "foo" - m.request(f) - - assert "address" in sa.hosts - - f = tutils.tflow(resp=True) - m.request(f) - assert f.request.headers["authorization"] == "foo" diff --git a/test/mitmproxy/builtins/test_stickycookie.py b/test/mitmproxy/builtins/test_stickycookie.py deleted file mode 100644 index c70b03d8..00000000 --- a/test/mitmproxy/builtins/test_stickycookie.py +++ /dev/null @@ -1,130 +0,0 @@ -from .. import tutils, mastertest -from mitmproxy.builtins import stickycookie -from mitmproxy import master -from mitmproxy import options -from mitmproxy import proxy -from netlib import tutils as ntutils - - -def test_domain_match(): - assert stickycookie.domain_match("www.google.com", ".google.com") - assert stickycookie.domain_match("google.com", ".google.com") - - -class TestStickyCookie(mastertest.MasterTest): - def mk(self): - o = options.Options(stickycookie = ".*") - m = master.Master(o, proxy.DummyServer()) - sc = stickycookie.StickyCookie() - m.addons.add(sc) - return m, sc - - def test_config(self): - sc = stickycookie.StickyCookie() - o = options.Options(stickycookie = "~b") - tutils.raises( - "invalid filter", - sc.configure, o, o.keys() - ) - - def test_simple(self): - m, sc = self.mk() - m.addons.add(sc) - - f = tutils.tflow(resp=True) - f.response.headers["set-cookie"] = "foo=bar" - m.request(f) - - f.reply.acked = False - m.response(f) - - assert sc.jar - assert "cookie" not in f.request.headers - - f = f.copy() - f.reply.acked = False - m.request(f) - assert f.request.headers["cookie"] == "foo=bar" - - def _response(self, m, sc, cookie, host): - f = tutils.tflow(req=ntutils.treq(host=host, port=80), resp=True) - f.response.headers["Set-Cookie"] = cookie - m.response(f) - return f - - def test_response(self): - m, sc = self.mk() - - c = "SSID=mooo; domain=.google.com, FOO=bar; Domain=.google.com; Path=/; " \ - "Expires=Wed, 13-Jan-2021 22:23:01 GMT; Secure; " - - self._response(m, sc, c, "host") - assert not sc.jar.keys() - - self._response(m, sc, c, "www.google.com") - assert sc.jar.keys() - - sc.jar.clear() - self._response( - m, sc, "SSID=mooo", "www.google.com" - ) - assert list(sc.jar.keys())[0] == ('www.google.com', 80, '/') - - def test_response_multiple(self): - m, sc = self.mk() - - # Test setting of multiple cookies - c1 = "somecookie=test; Path=/" - c2 = "othercookie=helloworld; Path=/" - f = self._response(m, sc, c1, "www.google.com") - f.response.headers["Set-Cookie"] = c2 - m.response(f) - googlekey = list(sc.jar.keys())[0] - assert len(sc.jar[googlekey].keys()) == 2 - - def test_response_weird(self): - m, sc = self.mk() - - # Test setting of weird cookie keys - f = tutils.tflow(req=ntutils.treq(host="www.google.com", port=80), resp=True) - cs = [ - "foo/bar=hello", - "foo:bar=world", - "foo@bar=fizz", - ] - for c in cs: - f.response.headers["Set-Cookie"] = c - m.response(f) - googlekey = list(sc.jar.keys())[0] - assert len(sc.jar[googlekey].keys()) == len(cs) - - def test_response_overwrite(self): - m, sc = self.mk() - - # Test overwriting of a cookie value - c1 = "somecookie=helloworld; Path=/" - c2 = "somecookie=newvalue; Path=/" - f = self._response(m, sc, c1, "www.google.com") - f.response.headers["Set-Cookie"] = c2 - m.response(f) - googlekey = list(sc.jar.keys())[0] - assert len(sc.jar[googlekey].keys()) == 1 - assert list(sc.jar[googlekey]["somecookie"].items())[0][1] == "newvalue" - - def test_response_delete(self): - m, sc = self.mk() - - # Test that a cookie is be deleted - # by setting the expire time in the past - f = self._response(m, sc, "duffer=zafar; Path=/", "www.google.com") - f.response.headers["Set-Cookie"] = "duffer=; Expires=Thu, 01-Jan-1970 00:00:00 GMT" - m.response(f) - assert not sc.jar.keys() - - def test_request(self): - m, sc = self.mk() - - f = self._response(m, sc, "SSID=mooo", "www.google.com") - assert "cookie" not in f.request.headers - m.request(f) - assert "cookie" in f.request.headers diff --git a/test/mitmproxy/builtins/test_streambodies.py b/test/mitmproxy/builtins/test_streambodies.py deleted file mode 100644 index 4a8c2474..00000000 --- a/test/mitmproxy/builtins/test_streambodies.py +++ /dev/null @@ -1,28 +0,0 @@ -from .. import tutils, mastertest -from mitmproxy import master -from mitmproxy import options -from mitmproxy import proxy - -from mitmproxy.builtins import streambodies - - -class TestStreamBodies(mastertest.MasterTest): - def test_simple(self): - o = options.Options(stream_large_bodies = 10) - m = master.Master(o, proxy.DummyServer()) - sa = streambodies.StreamBodies() - m.addons.add(sa) - - f = tutils.tflow() - f.request.content = b"" - f.request.headers["Content-Length"] = "1024" - assert not f.request.stream - m.requestheaders(f) - assert f.request.stream - - f = tutils.tflow(resp=True) - f.response.content = b"" - f.response.headers["Content-Length"] = "1024" - assert not f.response.stream - m.responseheaders(f) - assert f.response.stream diff --git a/test/mitmproxy/builtins/test_termlog.py b/test/mitmproxy/builtins/test_termlog.py deleted file mode 100644 index 49a8be83..00000000 --- a/test/mitmproxy/builtins/test_termlog.py +++ /dev/null @@ -1,17 +0,0 @@ -from .. import mastertest -import io - -from mitmproxy.builtins import termlog -from mitmproxy import log -from mitmproxy import dump - - -class TestTermLog(mastertest.MasterTest): - def test_simple(self): - t = termlog.TermLog() - sio = io.StringIO() - t.configure(dump.Options(tfile = sio, verbosity = 2), set([])) - t.log(log.LogEntry("one", "info")) - assert "one" in sio.getvalue() - t.log(log.LogEntry("two", "debug")) - assert "two" not in sio.getvalue() diff --git a/test/mitmproxy/builtins/test_wsgiapp.py b/test/mitmproxy/builtins/test_wsgiapp.py deleted file mode 100644 index a39ec5c3..00000000 --- a/test/mitmproxy/builtins/test_wsgiapp.py +++ /dev/null @@ -1,41 +0,0 @@ -import flask - -from .. import tservers -from mitmproxy.builtins import wsgiapp - -testapp = flask.Flask(__name__) - - -@testapp.route("/") -def hello(): - return "testapp" - - -@testapp.route("/error") -def error(): - raise ValueError("An exception...") - - -def errapp(environ, start_response): - raise ValueError("errapp") - - -class TestApp(tservers.HTTPProxyTest): - def addons(self): - return [ - wsgiapp.WSGIApp(testapp, "testapp", 80), - wsgiapp.WSGIApp(errapp, "errapp", 80) - ] - - def test_simple(self): - p = self.pathoc() - with p.connect(): - ret = p.request("get:'http://testapp/'") - assert ret.status_code == 200 - - def test_app_err(self): - p = self.pathoc() - with p.connect(): - ret = p.request("get:'http://errapp/'") - assert ret.status_code == 500 - assert b"ValueError" in ret.content diff --git a/test/mitmproxy/script/test_concurrent.py b/test/mitmproxy/script/test_concurrent.py index bebd8dea..51c36abf 100644 --- a/test/mitmproxy/script/test_concurrent.py +++ b/test/mitmproxy/script/test_concurrent.py @@ -1,6 +1,6 @@ from test.mitmproxy import tutils, mastertest from mitmproxy import controller -from mitmproxy.builtins import script +from mitmproxy.addons import script from mitmproxy import options from mitmproxy import proxy from mitmproxy import master diff --git a/test/mitmproxy/test_addonmanager.py b/test/mitmproxy/test_addonmanager.py new file mode 100644 index 00000000..7a50148e --- /dev/null +++ b/test/mitmproxy/test_addonmanager.py @@ -0,0 +1,23 @@ +from mitmproxy import addonmanager +from mitmproxy import options +from mitmproxy import master +from mitmproxy import proxy + + +class TAddon: + def __init__(self, name): + self.name = name + + def __repr__(self): + return "Addon(%s)" % self.name + + +def test_simple(): + o = options.Options() + m = master.Master(o, proxy.DummyServer(o)) + a = addonmanager.AddonManager(m) + a.add(TAddon("one")) + assert a.get("one") + assert not a.get("two") + a.clear() + assert not a.chain diff --git a/test/mitmproxy/test_addons.py b/test/mitmproxy/test_addons.py deleted file mode 100644 index dcf14398..00000000 --- a/test/mitmproxy/test_addons.py +++ /dev/null @@ -1,23 +0,0 @@ -from mitmproxy import addons -from mitmproxy import options -from mitmproxy import master -from mitmproxy import proxy - - -class TAddon: - def __init__(self, name): - self.name = name - - def __repr__(self): - return "Addon(%s)" % self.name - - -def test_simple(): - o = options.Options() - m = master.Master(o, proxy.DummyServer(o)) - a = addons.Addons(m) - a.add(TAddon("one")) - assert a.get("one") - assert not a.get("two") - a.clear() - assert not a.chain diff --git a/test/mitmproxy/test_examples.py b/test/mitmproxy/test_examples.py index ee5080e8..7551c1c8 100644 --- a/test/mitmproxy/test_examples.py +++ b/test/mitmproxy/test_examples.py @@ -5,7 +5,7 @@ import shlex from mitmproxy import options from mitmproxy import contentviews from mitmproxy import proxy -from mitmproxy.builtins import script +from mitmproxy.addons import script from mitmproxy import master import netlib.utils diff --git a/test/mitmproxy/test_server.py b/test/mitmproxy/test_server.py index 6679625b..7616b5a7 100644 --- a/test/mitmproxy/test_server.py +++ b/test/mitmproxy/test_server.py @@ -5,7 +5,7 @@ import time import netlib.tutils from mitmproxy import controller from mitmproxy import options -from mitmproxy.builtins import script +from mitmproxy.addons import script from mitmproxy.models import HTTPResponse, HTTPFlow from mitmproxy.proxy.config import HostMatcher, parse_server_spec from netlib import tcp, http, socks diff --git a/test/mitmproxy/tools/benchtool.py b/test/mitmproxy/tools/benchtool.py index bc68645c..9e2ab8ee 100644 --- a/test/mitmproxy/tools/benchtool.py +++ b/test/mitmproxy/tools/benchtool.py @@ -38,7 +38,7 @@ def main(profiler, clock_type, concurrency): if profiler == "yappi": yappi.set_clock_type(clock_type) - yappi.start(builtins=True) + yappi.start(addons=True) print("Start mitmdump...") mitmdump(["-k", "-q", "-S", "1024example"]) diff --git a/test/netlib/http/test_request.py b/test/netlib/http/test_request.py index 87eb9c35..336dc86d 100644 --- a/test/netlib/http/test_request.py +++ b/test/netlib/http/test_request.py @@ -15,7 +15,7 @@ class TestRequestData: class TestRequestCore: """ - Tests for builtins and the attributes that are directly proxied from the data structure + Tests for addons and the attributes that are directly proxied from the data structure """ def test_repr(self): request = treq() diff --git a/test/netlib/http/test_response.py b/test/netlib/http/test_response.py index 0953f278..725f2b33 100644 --- a/test/netlib/http/test_response.py +++ b/test/netlib/http/test_response.py @@ -19,7 +19,7 @@ class TestResponseData: class TestResponseCore: """ - Tests for builtins and the attributes that are directly proxied from the data structure + Tests for addons and the attributes that are directly proxied from the data structure """ def test_repr(self): response = tresp() -- cgit v1.2.3