diff options
Diffstat (limited to 'test')
25 files changed, 270 insertions, 176 deletions
diff --git a/test/mitmproxy/builtins/test_anticache.py b/test/mitmproxy/builtins/test_anticache.py index 5a00af03..ac321e26 100644 --- a/test/mitmproxy/builtins/test_anticache.py +++ b/test/mitmproxy/builtins/test_anticache.py @@ -8,9 +8,10 @@ from mitmproxy import options class TestAntiCache(mastertest.MasterTest): def test_simple(self): s = state.State() - m = master.FlowMaster(options.Options(anticache = True), None, s) + o = options.Options(anticache = True) + m = master.FlowMaster(o, None, s) sa = anticache.AntiCache() - m.addons.add(sa) + m.addons.add(o, sa) f = tutils.tflow(resp=True) self.invoke(m, "request", f) diff --git a/test/mitmproxy/builtins/test_anticomp.py b/test/mitmproxy/builtins/test_anticomp.py index 6bfd54bb..a5f5a270 100644 --- a/test/mitmproxy/builtins/test_anticomp.py +++ b/test/mitmproxy/builtins/test_anticomp.py @@ -8,9 +8,10 @@ from mitmproxy import options class TestAntiComp(mastertest.MasterTest): def test_simple(self): s = state.State() - m = master.FlowMaster(options.Options(anticomp = True), None, s) + o = options.Options(anticomp = True) + m = master.FlowMaster(o, None, s) sa = anticomp.AntiComp() - m.addons.add(sa) + m.addons.add(o, sa) f = tutils.tflow(resp=True) self.invoke(m, "request", f) diff --git a/test/mitmproxy/builtins/test_dumper.py b/test/mitmproxy/builtins/test_dumper.py index 57e3d036..6287fe86 100644 --- a/test/mitmproxy/builtins/test_dumper.py +++ b/test/mitmproxy/builtins/test_dumper.py @@ -15,26 +15,27 @@ class TestDumper(mastertest.MasterTest): d = dumper.Dumper() sio = StringIO() - d.configure(dump.Options(tfile = sio, flow_detail = 0)) + updated = set(["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)) + d.configure(dump.Options(tfile = sio, flow_detail = 4), updated) d.response(tutils.tflow()) assert sio.getvalue() sio = StringIO() - d.configure(dump.Options(tfile = sio, flow_detail = 4)) + d.configure(dump.Options(tfile = sio, flow_detail = 4), updated) d.response(tutils.tflow(resp=True)) assert "<<" in sio.getvalue() sio = StringIO() - d.configure(dump.Options(tfile = sio, flow_detail = 4)) + d.configure(dump.Options(tfile = sio, flow_detail = 4), updated) d.response(tutils.tflow(err=True)) assert "<<" in sio.getvalue() sio = StringIO() - d.configure(dump.Options(tfile = sio, flow_detail = 4)) + d.configure(dump.Options(tfile = sio, flow_detail = 4), updated) flow = tutils.tflow() flow.request = netlib.tutils.treq() flow.request.stickycookie = True @@ -47,7 +48,7 @@ class TestDumper(mastertest.MasterTest): assert sio.getvalue() sio = StringIO() - d.configure(dump.Options(tfile = sio, flow_detail = 4)) + 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 @@ -55,7 +56,7 @@ class TestDumper(mastertest.MasterTest): assert sio.getvalue() sio = StringIO() - d.configure(dump.Options(tfile = sio)) + d.configure(dump.Options(tfile = sio), updated) flow = tutils.tflow() flow.request.content = None flow.response = models.HTTPResponse.wrap(netlib.tutils.tresp()) @@ -72,15 +73,13 @@ class TestContentView(mastertest.MasterTest): s = state.State() sio = StringIO() - m = mastertest.RecordingMaster( - dump.Options( - flow_detail=4, - verbosity=3, - tfile=sio, - ), - None, s + o = dump.Options( + flow_detail=4, + verbosity=3, + tfile=sio, ) + m = mastertest.RecordingMaster(o, None, s) d = dumper.Dumper() - m.addons.add(d) + m.addons.add(o, d) self.invoke(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 index c1d5947f..0e69b340 100644 --- a/test/mitmproxy/builtins/test_filestreamer.py +++ b/test/mitmproxy/builtins/test_filestreamer.py @@ -20,16 +20,13 @@ class TestStream(mastertest.MasterTest): return list(r.stream()) s = state.State() - m = master.FlowMaster( - options.Options( - outfile = (p, "wb") - ), - None, - s + o = options.Options( + outfile = (p, "wb") ) + m = master.FlowMaster(o, None, s) sa = filestreamer.FileStreamer() - m.addons.add(sa) + m.addons.add(o, sa) f = tutils.tflow(resp=True) self.invoke(m, "request", f) self.invoke(m, "response", f) @@ -39,7 +36,7 @@ class TestStream(mastertest.MasterTest): m.options.outfile = (p, "ab") - m.addons.add(sa) + m.addons.add(o, sa) f = tutils.tflow() self.invoke(m, "request", f) m.addons.remove(sa) diff --git a/test/mitmproxy/builtins/test_replace.py b/test/mitmproxy/builtins/test_replace.py index a0b4b722..5e70ce56 100644 --- a/test/mitmproxy/builtins/test_replace.py +++ b/test/mitmproxy/builtins/test_replace.py @@ -8,38 +8,38 @@ from mitmproxy import options 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): s = state.State() - m = master.FlowMaster( - options.Options( - replacements = [ - ("~q", "foo", "bar"), - ("~s", "foo", "bar"), - ] - ), - None, - s + o = options.Options( + replacements = [ + ("~q", "foo", "bar"), + ("~s", "foo", "bar"), + ] ) + m = master.FlowMaster(o, None, s) sa = replace.Replace() - m.addons.add(sa) + m.addons.add(o, sa) f = tutils.tflow() f.request.content = b"foo" diff --git a/test/mitmproxy/builtins/test_script.py b/test/mitmproxy/builtins/test_script.py index f37c7f94..2870fd17 100644 --- a/test/mitmproxy/builtins/test_script.py +++ b/test/mitmproxy/builtins/test_script.py @@ -48,39 +48,41 @@ def test_load_script(): "data/addonscripts/recorder.py" ), [] ) - assert ns["configure"] + assert ns.start class TestScript(mastertest.MasterTest): def test_simple(self): s = state.State() - m = master.FlowMaster(options.Options(), None, s) + o = options.Options() + m = master.FlowMaster(o, None, s) sc = script.Script( tutils.test_data.path( "data/addonscripts/recorder.py" ) ) - m.addons.add(sc) - assert sc.ns["call_log"] == [ + m.addons.add(o, sc) + assert sc.ns.call_log == [ ("solo", "start", (), {}), - ("solo", "configure", (options.Options(),), {}) + ("solo", "configure", (o, o.keys()), {}) ] - sc.ns["call_log"] = [] + sc.ns.call_log = [] f = tutils.tflow(resp=True) self.invoke(m, "request", f) - recf = sc.ns["call_log"][0] + recf = sc.ns.call_log[0] assert recf[1] == "request" def test_reload(self): s = state.State() - m = mastertest.RecordingMaster(options.Options(), None, s) + o = options.Options() + m = mastertest.RecordingMaster(o, None, s) with tutils.tmpdir(): with open("foo.py", "w"): pass sc = script.Script("foo.py") - m.addons.add(sc) + m.addons.add(o, sc) for _ in range(100): with open("foo.py", "a") as f: @@ -93,19 +95,22 @@ class TestScript(mastertest.MasterTest): def test_exception(self): s = state.State() - m = mastertest.RecordingMaster(options.Options(), None, s) + o = options.Options() + m = mastertest.RecordingMaster(o, None, s) sc = script.Script( tutils.test_data.path("data/addonscripts/error.py") ) - m.addons.add(sc) + m.addons.add(o, sc) f = tutils.tflow(resp=True) self.invoke(m, "request", f) assert m.event_log[0][0] == "error" def test_duplicate_flow(self): s = state.State() - fm = master.FlowMaster(None, None, s) + o = options.Options() + fm = master.FlowMaster(o, None, s) fm.addons.add( + o, script.Script( tutils.test_data.path("data/addonscripts/duplicate_flow.py") ) @@ -116,6 +121,20 @@ class TestScript(mastertest.MasterTest): assert not fm.state.view[0].request.is_replay assert fm.state.view[1].request.is_replay + def test_addon(self): + s = state.State() + o = options.Options() + m = master.FlowMaster(o, None, s) + sc = script.Script( + tutils.test_data.path( + "data/addonscripts/addon.py" + ) + ) + m.addons.add(o, sc) + assert sc.ns.event_log == [ + 'scriptstart', 'addonstart', 'addonconfigure' + ] + class TestScriptLoader(mastertest.MasterTest): def test_simple(self): @@ -123,7 +142,7 @@ class TestScriptLoader(mastertest.MasterTest): o = options.Options(scripts=[]) m = master.FlowMaster(o, None, s) sc = script.ScriptLoader() - m.addons.add(sc) + m.addons.add(o, sc) assert len(m.addons) == 1 o.update( scripts = [ @@ -139,7 +158,7 @@ class TestScriptLoader(mastertest.MasterTest): o = options.Options(scripts=["one", "one"]) m = master.FlowMaster(o, None, s) sc = script.ScriptLoader() - tutils.raises(exceptions.OptionsError, m.addons.add, sc) + tutils.raises(exceptions.OptionsError, m.addons.add, o, sc) def test_order(self): rec = tutils.test_data.path("data/addonscripts/recorder.py") @@ -154,7 +173,7 @@ class TestScriptLoader(mastertest.MasterTest): ) m = mastertest.RecordingMaster(o, None, s) sc = script.ScriptLoader() - m.addons.add(sc) + m.addons.add(o, sc) debug = [(i[0], i[1]) for i in m.event_log if i[0] == "debug"] assert debug == [ diff --git a/test/mitmproxy/builtins/test_setheaders.py b/test/mitmproxy/builtins/test_setheaders.py index 4465719d..41c18360 100644 --- a/test/mitmproxy/builtins/test_setheaders.py +++ b/test/mitmproxy/builtins/test_setheaders.py @@ -8,19 +8,20 @@ from mitmproxy import options class TestSetHeaders(mastertest.MasterTest): def mkmaster(self, **opts): s = state.State() - m = mastertest.RecordingMaster(options.Options(**opts), None, s) + o = options.Options(**opts) + m = mastertest.RecordingMaster(o, None, s) sh = setheaders.SetHeaders() - m.addons.add(sh) + m.addons.add(o, 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, - options.Options( - setheaders = [("~b", "one", "two")] - ) + sh.configure, o, o.keys() ) def test_setheaders(self): diff --git a/test/mitmproxy/builtins/test_stickyauth.py b/test/mitmproxy/builtins/test_stickyauth.py index 9233f435..5757fb2d 100644 --- a/test/mitmproxy/builtins/test_stickyauth.py +++ b/test/mitmproxy/builtins/test_stickyauth.py @@ -8,9 +8,10 @@ from mitmproxy import options class TestStickyAuth(mastertest.MasterTest): def test_simple(self): s = state.State() - m = master.FlowMaster(options.Options(stickyauth = ".*"), None, s) + o = options.Options(stickyauth = ".*") + m = master.FlowMaster(o, None, s) sa = stickyauth.StickyAuth() - m.addons.add(sa) + m.addons.add(o, sa) f = tutils.tflow(resp=True) f.request.headers["authorization"] = "foo" diff --git a/test/mitmproxy/builtins/test_stickycookie.py b/test/mitmproxy/builtins/test_stickycookie.py index 81b540db..e9d92c83 100644 --- a/test/mitmproxy/builtins/test_stickycookie.py +++ b/test/mitmproxy/builtins/test_stickycookie.py @@ -14,22 +14,23 @@ def test_domain_match(): class TestStickyCookie(mastertest.MasterTest): def mk(self): s = state.State() - m = master.FlowMaster(options.Options(stickycookie = ".*"), None, s) + o = options.Options(stickycookie = ".*") + m = master.FlowMaster(o, None, s) sc = stickycookie.StickyCookie() - m.addons.add(sc) + m.addons.add(o, sc) return s, m, sc def test_config(self): sc = stickycookie.StickyCookie() + o = options.Options(stickycookie = "~b") tutils.raises( "invalid filter", - sc.configure, - options.Options(stickycookie = "~b") + sc.configure, o, o.keys() ) def test_simple(self): s, m, sc = self.mk() - m.addons.add(sc) + m.addons.add(m.options, sc) f = tutils.tflow(resp=True) f.response.headers["set-cookie"] = "foo=bar" diff --git a/test/mitmproxy/data/addonscripts/addon.py b/test/mitmproxy/data/addonscripts/addon.py new file mode 100644 index 00000000..84173cb6 --- /dev/null +++ b/test/mitmproxy/data/addonscripts/addon.py @@ -0,0 +1,22 @@ +event_log = [] + + +class Addon: + @property + def event_log(self): + return event_log + + def start(self): + event_log.append("addonstart") + + def configure(self, options, updated): + event_log.append("addonconfigure") + + +def configure(options, updated): + event_log.append("addonconfigure") + + +def start(): + event_log.append("scriptstart") + return Addon() diff --git a/test/mitmproxy/data/addonscripts/recorder.py b/test/mitmproxy/data/addonscripts/recorder.py index b6ac8d89..890e6f4e 100644 --- a/test/mitmproxy/data/addonscripts/recorder.py +++ b/test/mitmproxy/data/addonscripts/recorder.py @@ -2,24 +2,24 @@ from mitmproxy import controller from mitmproxy import ctx import sys -call_log = [] -if len(sys.argv) > 1: - name = sys.argv[1] -else: - name = "solo" +class CallLogger: + call_log = [] -# Keep a log of all possible event calls -evts = list(controller.Events) + ["configure"] -for i in evts: - def mkprox(): - evt = i + def __init__(self, name = "solo"): + self.name = name - def prox(*args, **kwargs): - lg = (name, evt, args, kwargs) - if evt != "log": - ctx.log.info(str(lg)) - call_log.append(lg) - ctx.log.debug("%s %s" % (name, evt)) - return prox - globals()[i] = mkprox() + def __getattr__(self, attr): + if attr in controller.Events: + def prox(*args, **kwargs): + lg = (self.name, attr, args, kwargs) + if attr != "log": + ctx.log.info(str(lg)) + self.call_log.append(lg) + ctx.log.debug("%s %s" % (self.name, attr)) + return prox + raise AttributeError + + +def start(): + return CallLogger(*sys.argv[1:]) diff --git a/test/mitmproxy/data/dumpfile-011 b/test/mitmproxy/data/dumpfile-011 Binary files differindex 2534ad89..936ac0cc 100644 --- a/test/mitmproxy/data/dumpfile-011 +++ b/test/mitmproxy/data/dumpfile-011 diff --git a/test/mitmproxy/script/test_concurrent.py b/test/mitmproxy/script/test_concurrent.py index 080746e8..a5f76994 100644 --- a/test/mitmproxy/script/test_concurrent.py +++ b/test/mitmproxy/script/test_concurrent.py @@ -23,7 +23,7 @@ class TestConcurrent(mastertest.MasterTest): "data/addonscripts/concurrent_decorator.py" ) ) - m.addons.add(sc) + m.addons.add(m.options, sc) f1, f2 = tutils.tflow(), tutils.tflow() self.invoke(m, "request", f1) self.invoke(m, "request", f2) diff --git a/test/mitmproxy/test_addons.py b/test/mitmproxy/test_addons.py index 1861d4ac..a5085ea0 100644 --- a/test/mitmproxy/test_addons.py +++ b/test/mitmproxy/test_addons.py @@ -13,8 +13,9 @@ class TAddon: def test_simple(): - m = controller.Master(options.Options()) + o = options.Options() + m = controller.Master(o) a = addons.Addons(m) - a.add(TAddon("one")) + a.add(o, TAddon("one")) assert a.has_addon("one") assert not a.has_addon("two") diff --git a/test/mitmproxy/test_contentview.py b/test/mitmproxy/test_contentview.py index 2db9ab40..aad53b37 100644 --- a/test/mitmproxy/test_contentview.py +++ b/test/mitmproxy/test_contentview.py @@ -59,10 +59,10 @@ class TestContentView: assert f[0] == "Query" def test_view_urlencoded(self): - d = url.encode([("one", "two"), ("three", "four")]) + d = url.encode([("one", "two"), ("three", "four")]).encode() v = cv.ViewURLEncoded() assert v(d) - d = url.encode([("adsfa", "")]) + d = url.encode([("adsfa", "")]).encode() v = cv.ViewURLEncoded() assert v(d) diff --git a/test/mitmproxy/test_examples.py b/test/mitmproxy/test_examples.py index 0ec85f52..34fcc261 100644 --- a/test/mitmproxy/test_examples.py +++ b/test/mitmproxy/test_examples.py @@ -27,10 +27,11 @@ class RaiseMaster(master.FlowMaster): def tscript(cmd, args=""): + o = options.Options() cmd = example_dir.path(cmd) + " " + args - m = RaiseMaster(options.Options(), None, state.State()) + m = RaiseMaster(o, None, state.State()) sc = script.Script(cmd) - m.addons.add(sc) + m.addons.add(o, sc) return m, sc diff --git a/test/mitmproxy/test_flow.py b/test/mitmproxy/test_flow.py index 36b212a7..74992130 100644 --- a/test/mitmproxy/test_flow.py +++ b/test/mitmproxy/test_flow.py @@ -615,6 +615,7 @@ class TestSerialize: def test_roundtrip(self): sio = io.BytesIO() f = tutils.tflow() + f.marked = True f.request.content = bytes(bytearray(range(256))) w = flow.FlowWriter(sio) w.add(f) @@ -627,6 +628,7 @@ class TestSerialize: f2 = l[0] assert f2.get_state() == f.get_state() assert f2.request == f.request + assert f2.marked def test_load_flows(self): r = self._treader() diff --git a/test/mitmproxy/test_optmanager.py b/test/mitmproxy/test_optmanager.py index 67f76ecd..8414e6b5 100644 --- a/test/mitmproxy/test_optmanager.py +++ b/test/mitmproxy/test_optmanager.py @@ -15,6 +15,8 @@ class TO(optmanager.OptManager): def test_options(): o = TO(two="three") + assert o.keys() == set(["one", "two"]) + assert o.one is None assert o.two == "three" o.one = "one" @@ -29,7 +31,7 @@ def test_options(): rec = [] - def sub(opts): + def sub(opts, updated): rec.append(copy.copy(opts)) o.changed.connect(sub) @@ -68,7 +70,7 @@ def test_rollback(): rec = [] - def sub(opts): + def sub(opts, updated): rec.append(copy.copy(opts)) recerr = [] @@ -76,7 +78,7 @@ def test_rollback(): def errsub(opts, **kwargs): recerr.append(kwargs) - def err(opts): + def err(opts, updated): if opts.one == "ten": raise exceptions.OptionsError() diff --git a/test/mitmproxy/test_protocol_http2.py b/test/mitmproxy/test_protocol_http2.py index afbffb67..aa096a72 100644 --- a/test/mitmproxy/test_protocol_http2.py +++ b/test/mitmproxy/test_protocol_http2.py @@ -30,7 +30,7 @@ logging.getLogger("PIL.PngImagePlugin").setLevel(logging.WARNING) requires_alpn = pytest.mark.skipif( not netlib.tcp.HAS_ALPN, - reason="requires OpenSSL with ALPN support") + reason='requires OpenSSL with ALPN support') class _Http2ServerBase(netlib_tservers.ServerTestBase): @@ -80,7 +80,7 @@ class _Http2ServerBase(netlib_tservers.ServerTestBase): print(traceback.format_exc()) break - def handle_server_event(self, h2_conn, rfile, wfile): + def handle_server_event(self, event, h2_conn, rfile, wfile): raise NotImplementedError() @@ -88,7 +88,6 @@ class _Http2TestBase(object): @classmethod def setup_class(cls): - cls.masteroptions = options.Options() opts = cls.get_options() cls.config = ProxyConfig(opts) @@ -145,12 +144,14 @@ class _Http2TestBase(object): wfile, h2_conn, stream_id=1, - headers=[], + headers=None, body=b'', end_stream=None, priority_exclusive=None, priority_depends_on=None, priority_weight=None): + if headers is None: + headers = [] if end_stream is None: end_stream = (len(body) == 0) @@ -172,12 +173,12 @@ class _Http2TestBase(object): class _Http2Test(_Http2TestBase, _Http2ServerBase): @classmethod - def setup_class(self): + def setup_class(cls): _Http2TestBase.setup_class() _Http2ServerBase.setup_class() @classmethod - def teardown_class(self): + def teardown_class(cls): _Http2TestBase.teardown_class() _Http2ServerBase.teardown_class() @@ -187,7 +188,7 @@ class TestSimple(_Http2Test): request_body_buffer = b'' @classmethod - def handle_server_event(self, event, h2_conn, rfile, wfile): + def handle_server_event(cls, event, h2_conn, rfile, wfile): if isinstance(event, h2.events.ConnectionTerminated): return False elif isinstance(event, h2.events.RequestReceived): @@ -214,7 +215,7 @@ class TestSimple(_Http2Test): wfile.write(h2_conn.data_to_send()) wfile.flush() elif isinstance(event, h2.events.DataReceived): - self.request_body_buffer += event.data + cls.request_body_buffer += event.data return True def test_simple(self): @@ -225,7 +226,7 @@ class TestSimple(_Http2Test): client.wfile, h2_conn, headers=[ - (':authority', "127.0.0.1:%s" % self.server.server.address.port), + (':authority', "127.0.0.1:{}".format(self.server.server.address.port)), (':method', 'GET'), (':scheme', 'https'), (':path', '/'), @@ -269,7 +270,7 @@ class TestSimple(_Http2Test): class TestRequestWithPriority(_Http2Test): @classmethod - def handle_server_event(self, event, h2_conn, rfile, wfile): + def handle_server_event(cls, event, h2_conn, rfile, wfile): if isinstance(event, h2.events.ConnectionTerminated): return False elif isinstance(event, h2.events.RequestReceived): @@ -301,14 +302,14 @@ class TestRequestWithPriority(_Http2Test): client.wfile, h2_conn, headers=[ - (':authority', "127.0.0.1:%s" % self.server.server.address.port), + (':authority', "127.0.0.1:{}".format(self.server.server.address.port)), (':method', 'GET'), (':scheme', 'https'), (':path', '/'), ], - priority_exclusive = True, - priority_depends_on = 42424242, - priority_weight = 42, + priority_exclusive=True, + priority_depends_on=42424242, + priority_weight=42, ) done = False @@ -343,7 +344,7 @@ class TestRequestWithPriority(_Http2Test): client.wfile, h2_conn, headers=[ - (':authority', "127.0.0.1:%s" % self.server.server.address.port), + (':authority', "127.0.0.1:{}".format(self.server.server.address.port)), (':method', 'GET'), (':scheme', 'https'), (':path', '/'), @@ -381,11 +382,11 @@ class TestPriority(_Http2Test): priority_data = None @classmethod - def handle_server_event(self, event, h2_conn, rfile, wfile): + def handle_server_event(cls, event, h2_conn, rfile, wfile): if isinstance(event, h2.events.ConnectionTerminated): return False elif isinstance(event, h2.events.PriorityUpdated): - self.priority_data = (event.exclusive, event.depends_on, event.weight) + cls.priority_data = (event.exclusive, event.depends_on, event.weight) elif isinstance(event, h2.events.RequestReceived): import warnings with warnings.catch_warnings(): @@ -415,7 +416,7 @@ class TestPriority(_Http2Test): client.wfile, h2_conn, headers=[ - (':authority', "127.0.0.1:%s" % self.server.server.address.port), + (':authority', "127.0.0.1:{}".format(self.server.server.address.port)), (':method', 'GET'), (':scheme', 'https'), (':path', '/'), @@ -451,11 +452,11 @@ class TestPriorityWithExistingStream(_Http2Test): priority_data = [] @classmethod - def handle_server_event(self, event, h2_conn, rfile, wfile): + def handle_server_event(cls, event, h2_conn, rfile, wfile): if isinstance(event, h2.events.ConnectionTerminated): return False elif isinstance(event, h2.events.PriorityUpdated): - self.priority_data.append((event.exclusive, event.depends_on, event.weight)) + cls.priority_data.append((event.exclusive, event.depends_on, event.weight)) elif isinstance(event, h2.events.RequestReceived): assert not event.priority_updated @@ -486,7 +487,7 @@ class TestPriorityWithExistingStream(_Http2Test): client.wfile, h2_conn, headers=[ - (':authority', "127.0.0.1:%s" % self.server.server.address.port), + (':authority', "127.0.0.1:{}".format(self.server.server.address.port)), (':method', 'GET'), (':scheme', 'https'), (':path', '/'), @@ -527,7 +528,7 @@ class TestPriorityWithExistingStream(_Http2Test): class TestStreamResetFromServer(_Http2Test): @classmethod - def handle_server_event(self, event, h2_conn, rfile, wfile): + def handle_server_event(cls, event, h2_conn, rfile, wfile): if isinstance(event, h2.events.ConnectionTerminated): return False elif isinstance(event, h2.events.RequestReceived): @@ -543,7 +544,7 @@ class TestStreamResetFromServer(_Http2Test): client.wfile, h2_conn, headers=[ - (':authority', "127.0.0.1:%s" % self.server.server.address.port), + (':authority', "127.0.0.1:{}".format(self.server.server.address.port)), (':method', 'GET'), (':scheme', 'https'), (':path', '/'), @@ -578,7 +579,7 @@ class TestStreamResetFromServer(_Http2Test): class TestBodySizeLimit(_Http2Test): @classmethod - def handle_server_event(self, event, h2_conn, rfile, wfile): + def handle_server_event(cls, event, h2_conn, rfile, wfile): if isinstance(event, h2.events.ConnectionTerminated): return False return True @@ -592,7 +593,7 @@ class TestBodySizeLimit(_Http2Test): client.wfile, h2_conn, headers=[ - (':authority', "127.0.0.1:%s" % self.server.server.address.port), + (':authority', "127.0.0.1:{}".format(self.server.server.address.port)), (':method', 'GET'), (':scheme', 'https'), (':path', '/'), @@ -627,7 +628,7 @@ class TestBodySizeLimit(_Http2Test): class TestPushPromise(_Http2Test): @classmethod - def handle_server_event(self, event, h2_conn, rfile, wfile): + def handle_server_event(cls, event, h2_conn, rfile, wfile): if isinstance(event, h2.events.ConnectionTerminated): return False elif isinstance(event, h2.events.RequestReceived): @@ -637,14 +638,14 @@ class TestPushPromise(_Http2Test): h2_conn.send_headers(1, [(':status', '200')]) h2_conn.push_stream(1, 2, [ - (':authority', "127.0.0.1:%s" % self.port), + (':authority', "127.0.0.1:{}".format(cls.port)), (':method', 'GET'), (':scheme', 'https'), (':path', '/pushed_stream_foo'), ('foo', 'bar') ]) h2_conn.push_stream(1, 4, [ - (':authority', "127.0.0.1:%s" % self.port), + (':authority', "127.0.0.1:{}".format(cls.port)), (':method', 'GET'), (':scheme', 'https'), (':path', '/pushed_stream_bar'), @@ -675,7 +676,7 @@ class TestPushPromise(_Http2Test): client, h2_conn = self._setup_connection() self._send_request(client.wfile, h2_conn, stream_id=1, headers=[ - (':authority', "127.0.0.1:%s" % self.server.server.address.port), + (':authority', "127.0.0.1:{}".format(self.server.server.address.port)), (':method', 'GET'), (':scheme', 'https'), (':path', '/'), @@ -728,7 +729,7 @@ class TestPushPromise(_Http2Test): client, h2_conn = self._setup_connection() self._send_request(client.wfile, h2_conn, stream_id=1, headers=[ - (':authority', "127.0.0.1:%s" % self.server.server.address.port), + (':authority', "127.0.0.1:{}".format(self.server.server.address.port)), (':method', 'GET'), (':scheme', 'https'), (':path', '/'), @@ -780,7 +781,7 @@ class TestPushPromise(_Http2Test): class TestConnectionLost(_Http2Test): @classmethod - def handle_server_event(self, event, h2_conn, rfile, wfile): + def handle_server_event(cls, event, h2_conn, rfile, wfile): if isinstance(event, h2.events.RequestReceived): h2_conn.send_headers(1, [(':status', '200')]) wfile.write(h2_conn.data_to_send()) @@ -791,7 +792,7 @@ class TestConnectionLost(_Http2Test): client, h2_conn = self._setup_connection() self._send_request(client.wfile, h2_conn, stream_id=1, headers=[ - (':authority', "127.0.0.1:%s" % self.server.server.address.port), + (':authority', "127.0.0.1:{}".format(self.server.server.address.port)), (':method', 'GET'), (':scheme', 'https'), (':path', '/'), @@ -822,12 +823,12 @@ class TestConnectionLost(_Http2Test): class TestMaxConcurrentStreams(_Http2Test): @classmethod - def setup_class(self): + def setup_class(cls): _Http2TestBase.setup_class() _Http2ServerBase.setup_class(h2_server_settings={h2.settings.MAX_CONCURRENT_STREAMS: 2}) @classmethod - def handle_server_event(self, event, h2_conn, rfile, wfile): + def handle_server_event(cls, event, h2_conn, rfile, wfile): if isinstance(event, h2.events.ConnectionTerminated): return False elif isinstance(event, h2.events.RequestReceived): @@ -848,7 +849,7 @@ class TestMaxConcurrentStreams(_Http2Test): # this will exceed MAX_CONCURRENT_STREAMS on the server connection # and cause mitmproxy to throttle stream creation to the server self._send_request(client.wfile, h2_conn, stream_id=id, headers=[ - (':authority', "127.0.0.1:%s" % self.server.server.address.port), + (':authority', "127.0.0.1:{}".format(self.server.server.address.port)), (':method', 'GET'), (':scheme', 'https'), (':path', '/'), @@ -883,7 +884,7 @@ class TestMaxConcurrentStreams(_Http2Test): class TestConnectionTerminated(_Http2Test): @classmethod - def handle_server_event(self, event, h2_conn, rfile, wfile): + def handle_server_event(cls, event, h2_conn, rfile, wfile): if isinstance(event, h2.events.RequestReceived): h2_conn.close_connection(error_code=5, last_stream_id=42, additional_data=b'foobar') wfile.write(h2_conn.data_to_send()) @@ -894,7 +895,7 @@ class TestConnectionTerminated(_Http2Test): client, h2_conn = self._setup_connection() self._send_request(client.wfile, h2_conn, headers=[ - (':authority', "127.0.0.1:%s" % self.server.server.address.port), + (':authority', "127.0.0.1:{}".format(self.server.server.address.port)), (':method', 'GET'), (':scheme', 'https'), (':path', '/'), diff --git a/test/mitmproxy/test_server.py b/test/mitmproxy/test_server.py index 233af597..6230fc1f 100644 --- a/test/mitmproxy/test_server.py +++ b/test/mitmproxy/test_server.py @@ -291,7 +291,7 @@ class TestHTTP(tservers.HTTPProxyTest, CommonMixin, AppMixin): s = script.Script( tutils.test_data.path("data/addonscripts/stream_modify.py") ) - self.master.addons.add(s) + self.master.addons.add(self.master.options, s) d = self.pathod('200:b"foo"') assert d.content == b"bar" self.master.addons.remove(s) @@ -523,7 +523,7 @@ class TestTransparent(tservers.TransparentProxyTest, CommonMixin, TcpMixin): s = script.Script( tutils.test_data.path("data/addonscripts/tcp_stream_modify.py") ) - self.master.addons.add(s) + self.master.addons.add(self.master.options, s) self._tcpproxy_on() d = self.pathod('200:b"foo"') self._tcpproxy_off() diff --git a/test/mitmproxy/tservers.py b/test/mitmproxy/tservers.py index f5119166..d364162c 100644 --- a/test/mitmproxy/tservers.py +++ b/test/mitmproxy/tservers.py @@ -34,7 +34,7 @@ class TestMaster(flow.FlowMaster): s = ProxyServer(config) state = flow.State() flow.FlowMaster.__init__(self, opts, s, state) - self.addons.add(*builtins.default_addons()) + self.addons.add(opts, *builtins.default_addons()) self.apps.add(testapp, "testapp", 80) self.apps.add(errapp, "errapp", 80) self.clear_log() diff --git a/test/netlib/http/test_message.py b/test/netlib/http/test_message.py index deebd6f2..12e4706c 100644 --- a/test/netlib/http/test_message.py +++ b/test/netlib/http/test_message.py @@ -1,7 +1,6 @@ # -*- coding: utf-8 -*- from __future__ import absolute_import, print_function, division -import mock import six from netlib.tutils import tresp @@ -71,10 +70,6 @@ class TestMessage(object): assert resp != 0 - def test_hash(self): - resp = tresp() - assert hash(resp) - def test_serializable(self): resp = tresp() resp2 = http.Response.from_state(resp.get_state()) @@ -117,14 +112,6 @@ class TestMessageContentEncoding(object): assert r.content == b"message" assert r.raw_content != b"message" - r.raw_content = b"foo" - with mock.patch("netlib.encoding.decode") as e: - assert r.content - assert e.call_count == 1 - e.reset_mock() - assert r.content - assert e.call_count == 0 - def test_modify(self): r = tresp() assert "content-encoding" not in r.headers @@ -135,13 +122,6 @@ class TestMessageContentEncoding(object): r.decode() assert r.raw_content == b"foo" - r.encode("identity") - with mock.patch("netlib.encoding.encode") as e: - r.content = b"foo" - assert e.call_count == 0 - r.content = b"bar" - assert e.call_count == 1 - with tutils.raises(TypeError): r.content = u"foo" @@ -216,15 +196,6 @@ class TestMessageText(object): r.headers["content-type"] = "text/html; charset=utf8" assert r.text == u"ü" - r.encode("identity") - r.raw_content = b"foo" - with mock.patch("netlib.encoding.decode") as e: - assert r.text - assert e.call_count == 2 - e.reset_mock() - assert r.text - assert e.call_count == 0 - def test_guess_json(self): r = tresp(content=b'"\xc3\xbc"') r.headers["content-type"] = "application/json" @@ -249,14 +220,6 @@ class TestMessageText(object): assert r.raw_content == b"\xc3\xbc" assert r.headers["content-length"] == "2" - r.encode("identity") - with mock.patch("netlib.encoding.encode") as e: - e.return_value = b"" - r.text = u"ü" - assert e.call_count == 0 - r.text = u"ä" - assert e.call_count == 2 - def test_unknown_ce(self): r = tresp() r.headers["content-type"] = "text/html; charset=wtf" diff --git a/test/netlib/http/test_url.py b/test/netlib/http/test_url.py index 26b37230..768e5130 100644 --- a/test/netlib/http/test_url.py +++ b/test/netlib/http/test_url.py @@ -1,3 +1,4 @@ +import six from netlib import tutils from netlib.http import url @@ -57,10 +58,49 @@ def test_unparse(): assert url.unparse("https", "foo.com", 443, "") == "https://foo.com" -def test_urlencode(): +if six.PY2: + surrogates = bytes(bytearray(range(256))) +else: + surrogates = bytes(range(256)).decode("utf8", "surrogateescape") + +surrogates_quoted = ( + '%00%01%02%03%04%05%06%07%08%09%0A%0B%0C%0D%0E%0F' + '%10%11%12%13%14%15%16%17%18%19%1A%1B%1C%1D%1E%1F' + '%20%21%22%23%24%25%26%27%28%29%2A%2B%2C-./' + '0123456789%3A%3B%3C%3D%3E%3F' + '%40ABCDEFGHIJKLMNO' + 'PQRSTUVWXYZ%5B%5C%5D%5E_' + '%60abcdefghijklmno' + 'pqrstuvwxyz%7B%7C%7D%7E%7F' + '%80%81%82%83%84%85%86%87%88%89%8A%8B%8C%8D%8E%8F' + '%90%91%92%93%94%95%96%97%98%99%9A%9B%9C%9D%9E%9F' + '%A0%A1%A2%A3%A4%A5%A6%A7%A8%A9%AA%AB%AC%AD%AE%AF' + '%B0%B1%B2%B3%B4%B5%B6%B7%B8%B9%BA%BB%BC%BD%BE%BF' + '%C0%C1%C2%C3%C4%C5%C6%C7%C8%C9%CA%CB%CC%CD%CE%CF' + '%D0%D1%D2%D3%D4%D5%D6%D7%D8%D9%DA%DB%DC%DD%DE%DF' + '%E0%E1%E2%E3%E4%E5%E6%E7%E8%E9%EA%EB%EC%ED%EE%EF' + '%F0%F1%F2%F3%F4%F5%F6%F7%F8%F9%FA%FB%FC%FD%FE%FF' +) + + +def test_encode(): assert url.encode([('foo', 'bar')]) + assert url.encode([('foo', surrogates)]) -def test_urldecode(): +def test_decode(): s = "one=two&three=four" assert len(url.decode(s)) == 2 + assert url.decode(surrogates) + + +def test_quote(): + assert url.quote("foo") == "foo" + assert url.quote("foo bar") == "foo%20bar" + assert url.quote(surrogates) == surrogates_quoted + + +def test_unquote(): + assert url.unquote("foo") == "foo" + assert url.unquote("foo%20bar") == "foo bar" + assert url.unquote(surrogates_quoted) == surrogates diff --git a/test/netlib/test_encoding.py b/test/netlib/test_encoding.py index de10fc48..a5e81379 100644 --- a/test/netlib/test_encoding.py +++ b/test/netlib/test_encoding.py @@ -1,3 +1,4 @@ +import mock from netlib import encoding, tutils @@ -37,3 +38,32 @@ def test_deflate(): ) with tutils.raises(ValueError): encoding.decode(b"bogus", "deflate") + + +def test_cache(): + decode_gzip = mock.MagicMock() + decode_gzip.return_value = b"decoded" + encode_gzip = mock.MagicMock() + encode_gzip.return_value = b"encoded" + + with mock.patch.dict(encoding.custom_decode, gzip=decode_gzip): + with mock.patch.dict(encoding.custom_encode, gzip=encode_gzip): + assert encoding.decode(b"encoded", "gzip") == b"decoded" + assert decode_gzip.call_count == 1 + + # should be cached + assert encoding.decode(b"encoded", "gzip") == b"decoded" + assert decode_gzip.call_count == 1 + + # the other way around as well + assert encoding.encode(b"decoded", "gzip") == b"encoded" + assert encode_gzip.call_count == 0 + + # different encoding + decode_gzip.return_value = b"bar" + assert encoding.encode(b"decoded", "deflate") != b"decoded" + assert encode_gzip.call_count == 0 + + # This is not in the cache anymore + assert encoding.encode(b"decoded", "gzip") == b"encoded" + assert encode_gzip.call_count == 1 diff --git a/test/netlib/test_multidict.py b/test/netlib/test_multidict.py index 038441e7..58ae0f98 100644 --- a/test/netlib/test_multidict.py +++ b/test/netlib/test_multidict.py @@ -45,7 +45,7 @@ class TestMultiDict(object): assert md["foo"] == "bar" with tutils.raises(KeyError): - md["bar"] + assert md["bar"] md_multi = TMultiDict( [("foo", "a"), ("foo", "b")] @@ -101,6 +101,15 @@ class TestMultiDict(object): assert TMultiDict() != self._multi() assert TMultiDict() != 42 + def test_hash(self): + """ + If a class defines mutable objects and implements an __eq__() method, + it should not implement __hash__(), since the implementation of hashable + collections requires that a key's hash value is immutable. + """ + with tutils.raises(TypeError): + assert hash(TMultiDict()) + def test_get_all(self): md = self._multi() assert md.get_all("foo") == ["bar"] @@ -197,6 +206,9 @@ class TestImmutableMultiDict(object): with tutils.raises(TypeError): md.add("foo", "bar") + def test_hash(self): + assert hash(TImmutableMultiDict()) + def test_with_delitem(self): md = TImmutableMultiDict([("foo", "bar")]) assert md.with_delitem("foo").fields == () |