From 393c1d74afaaed908ea842a7cf804e15a121e7fd Mon Sep 17 00:00:00 2001 From: Shadab Zafar Date: Sat, 2 Jul 2016 18:56:22 +0530 Subject: fix lint issues --- test/mitmproxy/tservers.py | 2 -- 1 file changed, 2 deletions(-) (limited to 'test') diff --git a/test/mitmproxy/tservers.py b/test/mitmproxy/tservers.py index 51f4b4e2..0760cb53 100644 --- a/test/mitmproxy/tservers.py +++ b/test/mitmproxy/tservers.py @@ -11,8 +11,6 @@ import pathod.pathoc from mitmproxy import flow, controller from mitmproxy.cmdline import APP_HOST, APP_PORT -from netlib import strutils - testapp = flask.Flask(__name__) -- cgit v1.2.3 From f623b3d99b46f9cdeabdbea31614270cc1832f3b Mon Sep 17 00:00:00 2001 From: Shadab Zafar Date: Tue, 28 Jun 2016 17:41:30 +0530 Subject: py3++: test_flow_export --- test/mitmproxy/data/test_flow_export/python_post_json.py | 4 ++-- test/mitmproxy/test_flow_export.py | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'test') diff --git a/test/mitmproxy/data/test_flow_export/python_post_json.py b/test/mitmproxy/data/test_flow_export/python_post_json.py index 6c1b9740..5ef110f3 100644 --- a/test/mitmproxy/data/test_flow_export/python_post_json.py +++ b/test/mitmproxy/data/test_flow_export/python_post_json.py @@ -8,8 +8,8 @@ headers = { json = { - u'email': u'example@example.com', - u'name': u'example', + 'email': 'example@example.com', + 'name': 'example', } diff --git a/test/mitmproxy/test_flow_export.py b/test/mitmproxy/test_flow_export.py index 9a263b1b..33c5137a 100644 --- a/test/mitmproxy/test_flow_export.py +++ b/test/mitmproxy/test_flow_export.py @@ -21,15 +21,15 @@ def python_equals(testdata, text): def req_get(): - return netlib.tutils.treq(method='GET', content='', path=b"/path?a=foo&a=bar&b=baz") + return netlib.tutils.treq(method=b'GET', content=b'', path=b"/path?a=foo&a=bar&b=baz") def req_post(): - return netlib.tutils.treq(method='POST', headers=()) + return netlib.tutils.treq(method=b'POST', headers=()) def req_patch(): - return netlib.tutils.treq(method='PATCH', path=b"/path?query=param") + return netlib.tutils.treq(method=b'PATCH', path=b"/path?query=param") class TestExportCurlCommand(): -- cgit v1.2.3 From 45aa2174e235f542d75d0305e7fb498b9b0585f9 Mon Sep 17 00:00:00 2001 From: Shadab Zafar Date: Sun, 3 Jul 2016 21:14:01 +0530 Subject: http2: Remove TestReadRequestConnect test --- test/pathod/test_protocols_http2.py | 31 ------------------------------- 1 file changed, 31 deletions(-) (limited to 'test') diff --git a/test/pathod/test_protocols_http2.py b/test/pathod/test_protocols_http2.py index e42c2858..8d7efc82 100644 --- a/test/pathod/test_protocols_http2.py +++ b/test/pathod/test_protocols_http2.py @@ -367,37 +367,6 @@ class TestReadRequestAbsolute(netlib_tservers.ServerTestBase): assert req.port == 22 -class TestReadRequestConnect(netlib_tservers.ServerTestBase): - class handler(tcp.BaseHandler): - def handle(self): - self.wfile.write( - codecs.decode('00001b0105000000014287bdab4e9c17b7ff44871c92585422e08541871c92585422e085', 'hex_codec')) - self.wfile.write( - codecs.decode('00001d0105000000014287bdab4e9c17b7ff44882f91d35d055c87a741882f91d35d055c87a7', 'hex_codec')) - self.wfile.flush() - - ssl = True - - def test_connect(self): - c = tcp.TCPClient(("127.0.0.1", self.port)) - with c.connect(): - c.convert_to_ssl() - protocol = HTTP2StateProtocol(c, is_server=True) - protocol.connection_preface_performed = True - - req = protocol.read_request(NotImplemented) - assert req.first_line_format == "authority" - assert req.method == "CONNECT" - assert req.host == "address" - assert req.port == 22 - - req = protocol.read_request(NotImplemented) - assert req.first_line_format == "authority" - assert req.method == "CONNECT" - assert req.host == "example.com" - assert req.port == 443 - - class TestReadResponse(netlib_tservers.ServerTestBase): class handler(tcp.BaseHandler): def handle(self): -- cgit v1.2.3 From 8d2042ea8ad7ce30ef8808c3c5e556adf4160cd3 Mon Sep 17 00:00:00 2001 From: Thomas Kriechbaumer Date: Sun, 5 Jun 2016 13:14:23 +0200 Subject: http2: test throttling at MAX_CONCURRENT_STREAMS --- test/mitmproxy/test_protocol_http2.py | 74 ++++++++++++++++++++++++++++++++++- test/netlib/tservers.py | 12 +++--- 2 files changed, 80 insertions(+), 6 deletions(-) (limited to 'test') diff --git a/test/mitmproxy/test_protocol_http2.py b/test/mitmproxy/test_protocol_http2.py index 932c8df2..89bb16c6 100644 --- a/test/mitmproxy/test_protocol_http2.py +++ b/test/mitmproxy/test_protocol_http2.py @@ -3,9 +3,10 @@ from __future__ import (absolute_import, print_function, division) import pytest -import traceback import os +import traceback import tempfile + import h2 from mitmproxy.proxy.config import ProxyConfig @@ -46,6 +47,11 @@ class _Http2ServerBase(netlib_tservers.ServerTestBase): self.wfile.write(h2_conn.data_to_send()) self.wfile.flush() + if 'h2_server_settings' in self.kwargs: + h2_conn.update_settings(self.kwargs['h2_server_settings']) + self.wfile.write(h2_conn.data_to_send()) + self.wfile.flush() + done = False while not done: try: @@ -508,3 +514,69 @@ class TestConnectionLost(_Http2TestBase, _Http2ServerBase): if len(self.master.state.flows) == 1: assert self.master.state.flows[0].response is None + + +@requires_alpn +class TestMaxConcurrentStreams(_Http2TestBase, _Http2ServerBase): + + @classmethod + def setup_class(self): + _Http2TestBase.setup_class() + _Http2ServerBase.setup_class(h2_server_settings={h2.settings.MAX_CONCURRENT_STREAMS: 2}) + + @classmethod + def teardown_class(self): + _Http2TestBase.teardown_class() + _Http2ServerBase.teardown_class() + + @classmethod + def handle_server_event(self, event, h2_conn, rfile, wfile): + if isinstance(event, h2.events.ConnectionTerminated): + return False + elif isinstance(event, h2.events.RequestReceived): + h2_conn.send_headers(event.stream_id, [ + (':status', '200'), + ('X-Stream-ID', str(event.stream_id)), + ]) + h2_conn.send_data(event.stream_id, b'Stream-ID {}'.format(event.stream_id)) + h2_conn.end_stream(event.stream_id) + wfile.write(h2_conn.data_to_send()) + wfile.flush() + return True + + def test_max_concurrent_streams(self): + client, h2_conn = self._setup_connection() + new_streams = [1, 3, 5, 7, 9, 11] + for id in new_streams: + # 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), + (':method', 'GET'), + (':scheme', 'https'), + (':path', '/'), + ('X-Stream-ID', str(id)), + ]) + + ended_streams = 0 + while ended_streams != len(new_streams): + try: + header, body = framereader.http2_read_raw_frame(client.rfile) + events = h2_conn.receive_data(b''.join([header, body])) + except: + break + client.wfile.write(h2_conn.data_to_send()) + client.wfile.flush() + + for event in events: + if isinstance(event, h2.events.StreamEnded): + ended_streams += 1 + + h2_conn.close_connection() + client.wfile.write(h2_conn.data_to_send()) + client.wfile.flush() + + assert len(self.master.state.flows) == len(new_streams) + for flow in self.master.state.flows: + assert flow.response.status_code == 200 + assert "Stream-ID" in flow.response.body diff --git a/test/netlib/tservers.py b/test/netlib/tservers.py index 803aaa72..666f97ac 100644 --- a/test/netlib/tservers.py +++ b/test/netlib/tservers.py @@ -24,7 +24,7 @@ class _ServerThread(threading.Thread): class _TServer(tcp.TCPServer): - def __init__(self, ssl, q, handler_klass, addr): + def __init__(self, ssl, q, handler_klass, addr, **kwargs): """ ssl: A dictionary of SSL parameters: @@ -42,6 +42,8 @@ class _TServer(tcp.TCPServer): self.q = q self.handler_klass = handler_klass + if self.handler_klass is not None: + self.handler_klass.kwargs = kwargs self.last_handler = None def handle_client_connection(self, request, client_address): @@ -89,16 +91,16 @@ class ServerTestBase(object): addr = ("localhost", 0) @classmethod - def setup_class(cls): + def setup_class(cls, **kwargs): cls.q = queue.Queue() - s = cls.makeserver() + s = cls.makeserver(**kwargs) cls.port = s.address.port cls.server = _ServerThread(s) cls.server.start() @classmethod - def makeserver(cls): - return _TServer(cls.ssl, cls.q, cls.handler, cls.addr) + def makeserver(cls, **kwargs): + return _TServer(cls.ssl, cls.q, cls.handler, cls.addr, **kwargs) @classmethod def teardown_class(cls): -- cgit v1.2.3 From 5fecb8c843a4d0874f96d19eb72ebdff66e2f19d Mon Sep 17 00:00:00 2001 From: Thomas Kriechbaumer Date: Sun, 5 Jun 2016 15:30:58 +0200 Subject: http2: test fatal connection termination --- test/mitmproxy/test_protocol_http2.py | 53 ++++++++++++++++++++++++++++++++++- 1 file changed, 52 insertions(+), 1 deletion(-) (limited to 'test') diff --git a/test/mitmproxy/test_protocol_http2.py b/test/mitmproxy/test_protocol_http2.py index 89bb16c6..2eb0b120 100644 --- a/test/mitmproxy/test_protocol_http2.py +++ b/test/mitmproxy/test_protocol_http2.py @@ -4,8 +4,8 @@ from __future__ import (absolute_import, print_function, division) import pytest import os -import traceback import tempfile +import traceback import h2 @@ -580,3 +580,54 @@ class TestMaxConcurrentStreams(_Http2TestBase, _Http2ServerBase): for flow in self.master.state.flows: assert flow.response.status_code == 200 assert "Stream-ID" in flow.response.body + + +@requires_alpn +class TestConnectionTerminated(_Http2TestBase, _Http2ServerBase): + + @classmethod + def setup_class(self): + _Http2TestBase.setup_class() + _Http2ServerBase.setup_class() + + @classmethod + def teardown_class(self): + _Http2TestBase.teardown_class() + _Http2ServerBase.teardown_class() + + @classmethod + def handle_server_event(self, event, h2_conn, rfile, wfile): + if isinstance(event, h2.events.RequestReceived): + h2_conn.close_connection(error_code=5, last_stream_id=42, additional_data='foobar') + wfile.write(h2_conn.data_to_send()) + wfile.flush() + return True + + def test_connection_terminated(self): + 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), + (':method', 'GET'), + (':scheme', 'https'), + (':path', '/'), + ]) + + done = False + connection_terminated_event = None + while not done: + try: + raw = b''.join(framereader.http2_read_raw_frame(client.rfile)) + events = h2_conn.receive_data(raw) + for event in events: + if isinstance(event, h2.events.ConnectionTerminated): + connection_terminated_event = event + done = True + except: + break + + assert len(self.master.state.flows) == 1 + assert connection_terminated_event is not None + assert connection_terminated_event.error_code == 5 + assert connection_terminated_event.last_stream_id == 42 + assert connection_terminated_event.additional_data == 'foobar' -- cgit v1.2.3 From d51cf543bb74755ed5dd17ed02859912ec557ef4 Mon Sep 17 00:00:00 2001 From: Maximilian Hils Date: Tue, 5 Jul 2016 15:11:32 -0700 Subject: remove clean_bin, clarify unicode handling --- test/netlib/test_strutils.py | 40 +++++++++++++++++++++++++--------------- 1 file changed, 25 insertions(+), 15 deletions(-) (limited to 'test') diff --git a/test/netlib/test_strutils.py b/test/netlib/test_strutils.py index 16e5d0b3..33bce714 100644 --- a/test/netlib/test_strutils.py +++ b/test/netlib/test_strutils.py @@ -1,4 +1,3 @@ -# coding=utf-8 import six from netlib import strutils, tutils @@ -15,18 +14,22 @@ def test_native(): assert strutils.native(b"foo") == u"foo" -def test_clean_bin(): - assert strutils.clean_bin(b"one") == u"one" - assert strutils.clean_bin(b"\00ne") == u".ne" - assert strutils.clean_bin(b"\nne") == u"\nne" - assert strutils.clean_bin(b"\nne", False) == u".ne" - assert strutils.clean_bin(u"\u2605".encode("utf8")) == u"..." - - assert strutils.clean_bin(u"one") == u"one" - assert strutils.clean_bin(u"\00ne") == u".ne" - assert strutils.clean_bin(u"\nne") == u"\nne" - assert strutils.clean_bin(u"\nne", False) == u".ne" - assert strutils.clean_bin(u"\u2605") == u"\u2605" +def test_escape_control_characters(): + assert strutils.escape_control_characters(u"one") == u"one" + assert strutils.escape_control_characters(u"\00ne") == u".ne" + assert strutils.escape_control_characters(u"\nne") == u"\nne" + assert strutils.escape_control_characters(u"\nne", False) == u".ne" + assert strutils.escape_control_characters(u"\u2605") == u"\u2605" + assert ( + strutils.escape_control_characters(bytes(bytearray(range(128))).decode()) == + u'.........\t\n..\r.................. !"#$%&\'()*+,-./0123456789:;<' + u'=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~.' + ) + assert ( + strutils.escape_control_characters(bytes(bytearray(range(128))).decode(), False) == + u'................................ !"#$%&\'()*+,-./0123456789:;<' + u'=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~.' + ) def test_bytes_to_escaped_str(): @@ -37,6 +40,14 @@ def test_bytes_to_escaped_str(): assert strutils.bytes_to_escaped_str(b"'") == r"\'" assert strutils.bytes_to_escaped_str(b'"') == r'"' + assert strutils.bytes_to_escaped_str(b"\r\n\t") == "\\r\\n\\t" + assert strutils.bytes_to_escaped_str(b"\r\n\t", True) == "\r\n\t" + + assert strutils.bytes_to_escaped_str(b"\n", True) == "\n" + assert strutils.bytes_to_escaped_str(b"\\n", True) == "\\ \\ n".replace(" ", "") + assert strutils.bytes_to_escaped_str(b"\\\n", True) == "\\ \\ \n".replace(" ", "") + assert strutils.bytes_to_escaped_str(b"\\\\n", True) == "\\ \\ \\ \\ n".replace(" ", "") + with tutils.raises(ValueError): strutils.bytes_to_escaped_str(u"such unicode") @@ -45,10 +56,9 @@ def test_escaped_str_to_bytes(): assert strutils.escaped_str_to_bytes("foo") == b"foo" assert strutils.escaped_str_to_bytes("\x08") == b"\b" assert strutils.escaped_str_to_bytes("&!?=\\\\)") == br"&!?=\)" - assert strutils.escaped_str_to_bytes("ü") == b'\xc3\xbc' assert strutils.escaped_str_to_bytes(u"\\x08") == b"\b" assert strutils.escaped_str_to_bytes(u"&!?=\\\\)") == br"&!?=\)" - assert strutils.escaped_str_to_bytes(u"ü") == b'\xc3\xbc' + assert strutils.escaped_str_to_bytes(u"\u00fc") == b'\xc3\xbc' if six.PY2: with tutils.raises(ValueError): -- cgit v1.2.3 From 444f0a4c397e3d664ce80f65d176d871b8e1194e Mon Sep 17 00:00:00 2001 From: Maximilian Hils Date: Wed, 6 Jul 2016 17:31:08 -0700 Subject: py3++ --- test/mitmproxy/test_examples.py | 10 +++++----- test/netlib/test_strutils.py | 15 ++++----------- 2 files changed, 9 insertions(+), 16 deletions(-) (limited to 'test') diff --git a/test/mitmproxy/test_examples.py b/test/mitmproxy/test_examples.py index 607d6faf..22d3c425 100644 --- a/test/mitmproxy/test_examples.py +++ b/test/mitmproxy/test_examples.py @@ -73,9 +73,9 @@ def test_add_header(): def test_custom_contentviews(): with example("custom_contentviews.py") as ex: pig = ex.ctx.contentview - _, fmt = pig("test!") - assert any('esttay!' in val[0][1] for val in fmt) - assert not pig("gobbledygook") + _, fmt = pig(b"test!") + assert any(b'esttay!' in val[0][1] for val in fmt) + assert not pig(b"gobbledygook") def test_iframe_injector(): @@ -103,7 +103,7 @@ def test_modify_form(): def test_modify_querystring(): - flow = tutils.tflow(req=netutils.treq(path="/search?q=term")) + flow = tutils.tflow(req=netutils.treq(path=b"/search?q=term")) with example("modify_querystring.py") as ex: ex.run("request", flow) assert flow.request.query["mitmproxy"] == "rocks" @@ -126,7 +126,7 @@ def test_modify_response_body(): def test_redirect_requests(): - flow = tutils.tflow(req=netutils.treq(host="example.org")) + flow = tutils.tflow(req=netutils.treq(host=b"example.org")) with example("redirect_requests.py") as ex: ex.run("request", flow) assert flow.request.host == "mitmproxy.org" diff --git a/test/netlib/test_strutils.py b/test/netlib/test_strutils.py index 33bce714..f88e33ed 100644 --- a/test/netlib/test_strutils.py +++ b/test/netlib/test_strutils.py @@ -68,17 +68,10 @@ def test_escaped_str_to_bytes(): strutils.escaped_str_to_bytes(b"very byte") -def test_isBin(): - assert not strutils.isBin("testing\n\r") - assert strutils.isBin("testing\x01") - assert strutils.isBin("testing\x0e") - assert strutils.isBin("testing\x7f") - - -def test_isXml(): - assert not strutils.isXML("foo") - assert strutils.isXML(" Date: Wed, 6 Jul 2016 19:50:06 -0700 Subject: py3++, multidict fixes This commit improves Python 3 compatibility and fixes two multidict issues: 1. Headers.items(multi=True) now decodes fields 2. MultiDict.clear(item) has been removed, as Python's MutableMapping already defines .clear() with different semantics. This is confusing for everyone who expects a dict-like object. `.pop("attr", None)` is not fantastic, but it's the Python way to do it. --- test/mitmproxy/test_web_master.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'test') diff --git a/test/mitmproxy/test_web_master.py b/test/mitmproxy/test_web_master.py index 98f53c93..f0fafe24 100644 --- a/test/mitmproxy/test_web_master.py +++ b/test/mitmproxy/test_web_master.py @@ -13,5 +13,5 @@ class TestWebMaster(mastertest.MasterTest): def test_basic(self): m = self.mkmaster(None) for i in (1, 2, 3): - self.dummy_cycle(m, 1, "") + self.dummy_cycle(m, 1, b"") assert len(m.state.flows) == i -- cgit v1.2.3 From 684b4b5130aa9cc75322dd270172b263615d39dc Mon Sep 17 00:00:00 2001 From: Maximilian Hils Date: Tue, 5 Jul 2016 18:48:45 -0700 Subject: tnetstring: keys are str on py3. migrate flow.io_compat --- test/mitmproxy/test_contrib_tnetstring.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'test') diff --git a/test/mitmproxy/test_contrib_tnetstring.py b/test/mitmproxy/test_contrib_tnetstring.py index 17654ad9..8ae35a25 100644 --- a/test/mitmproxy/test_contrib_tnetstring.py +++ b/test/mitmproxy/test_contrib_tnetstring.py @@ -12,7 +12,7 @@ FORMAT_EXAMPLES = { b'0:}': {}, b'0:]': [], b'51:5:hello,39:11:12345678901#4:this,4:true!0:~4:\x00\x00\x00\x00,]}': - {b'hello': [12345678901, b'this', True, None, b'\x00\x00\x00\x00']}, + {'hello': [12345678901, b'this', True, None, b'\x00\x00\x00\x00']}, b'5:12345#': 12345, b'12:this is cool,': b'this is cool', b'0:,': b'', @@ -43,7 +43,7 @@ def get_random_object(random=random, depth=0): d = {} for _ in range(n): n = random.randint(0, 100) - k = bytes([random.randint(32, 126) for _ in range(n)]) + k = str([random.randint(32, 126) for _ in range(n)]) d[k] = get_random_object(random, depth + 1) return d else: -- cgit v1.2.3 From d406bee988dc01126cfbdfc938b561e10b518610 Mon Sep 17 00:00:00 2001 From: Maximilian Hils Date: Tue, 5 Jul 2016 20:28:13 -0700 Subject: tnetstring3: adapt to unicode support --- test/mitmproxy/test_contrib_tnetstring.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'test') diff --git a/test/mitmproxy/test_contrib_tnetstring.py b/test/mitmproxy/test_contrib_tnetstring.py index 8ae35a25..908cec27 100644 --- a/test/mitmproxy/test_contrib_tnetstring.py +++ b/test/mitmproxy/test_contrib_tnetstring.py @@ -15,7 +15,9 @@ FORMAT_EXAMPLES = { {'hello': [12345678901, b'this', True, None, b'\x00\x00\x00\x00']}, b'5:12345#': 12345, b'12:this is cool,': b'this is cool', + b'19:this is unicode \xe2\x98\x85;': u'this is unicode \u2605', b'0:,': b'', + b'0:;': u'', b'0:~': None, b'4:true!': True, b'5:false!': False, @@ -78,12 +80,6 @@ class Test_Format(unittest.TestCase): self.assertEqual(v, tnetstring.loads(tnetstring.dumps(v))) self.assertEqual((v, b""), tnetstring.pop(tnetstring.dumps(v))) - def test_unicode_handling(self): - with self.assertRaises(ValueError): - tnetstring.dumps(u"hello") - self.assertEqual(tnetstring.dumps(u"hello".encode()), b"5:hello,") - self.assertEqual(type(tnetstring.loads(b"5:hello,")), bytes) - def test_roundtrip_format_unicode(self): for _ in range(500): v = get_random_object() -- cgit v1.2.3 From 8287ce7e6dcf31e65519629bb064044a44de46d1 Mon Sep 17 00:00:00 2001 From: Maximilian Hils Date: Wed, 6 Jul 2016 16:36:04 -0700 Subject: fix tests --- test/mitmproxy/test_contrib_tnetstring.py | 2 +- test/mitmproxy/tutils.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'test') diff --git a/test/mitmproxy/test_contrib_tnetstring.py b/test/mitmproxy/test_contrib_tnetstring.py index 908cec27..05c4a7c9 100644 --- a/test/mitmproxy/test_contrib_tnetstring.py +++ b/test/mitmproxy/test_contrib_tnetstring.py @@ -12,7 +12,7 @@ FORMAT_EXAMPLES = { b'0:}': {}, b'0:]': [], b'51:5:hello,39:11:12345678901#4:this,4:true!0:~4:\x00\x00\x00\x00,]}': - {'hello': [12345678901, b'this', True, None, b'\x00\x00\x00\x00']}, + {b'hello': [12345678901, b'this', True, None, b'\x00\x00\x00\x00']}, b'5:12345#': 12345, b'12:this is cool,': b'this is cool', b'19:this is unicode \xe2\x98\x85;': u'this is unicode \u2605', diff --git a/test/mitmproxy/tutils.py b/test/mitmproxy/tutils.py index d0a09035..5aade60c 100644 --- a/test/mitmproxy/tutils.py +++ b/test/mitmproxy/tutils.py @@ -130,7 +130,7 @@ def tserver_conn(): timestamp_ssl_setup=3, timestamp_end=4, ssl_established=False, - sni="address", + sni=b"address", via=None )) c.reply = controller.DummyReply() -- cgit v1.2.3 From 64a867973d5bac136c2e1c3c11c457d6b04d6649 Mon Sep 17 00:00:00 2001 From: Maximilian Hils Date: Wed, 6 Jul 2016 21:03:17 -0700 Subject: sni is now str, not bytes --- test/mitmproxy/test_server.py | 6 +++--- test/mitmproxy/tutils.py | 2 +- test/netlib/test_tcp.py | 26 +++++++++++++------------- test/pathod/test_pathoc.py | 4 ++-- 4 files changed, 19 insertions(+), 19 deletions(-) (limited to 'test') diff --git a/test/mitmproxy/test_server.py b/test/mitmproxy/test_server.py index 1bbef975..0ab7624e 100644 --- a/test/mitmproxy/test_server.py +++ b/test/mitmproxy/test_server.py @@ -100,10 +100,10 @@ class CommonMixin: if not self.ssl: return - f = self.pathod("304", sni=b"testserver.com") + f = self.pathod("304", sni="testserver.com") assert f.status_code == 304 log = self.server.last_log() - assert log["request"]["sni"] == b"testserver.com" + assert log["request"]["sni"] == "testserver.com" class TcpMixin: @@ -498,7 +498,7 @@ class TestHttps2Http(tservers.ReverseProxyTest): assert p.request("get:'/p/200'").status_code == 200 def test_sni(self): - p = self.pathoc(ssl=True, sni=b"example.com") + p = self.pathoc(ssl=True, sni="example.com") assert p.request("get:'/p/200'").status_code == 200 assert all("Error in handle_sni" not in msg for msg in self.proxy.tlog) diff --git a/test/mitmproxy/tutils.py b/test/mitmproxy/tutils.py index 5aade60c..d0a09035 100644 --- a/test/mitmproxy/tutils.py +++ b/test/mitmproxy/tutils.py @@ -130,7 +130,7 @@ def tserver_conn(): timestamp_ssl_setup=3, timestamp_end=4, ssl_established=False, - sni=b"address", + sni="address", via=None )) c.reply = controller.DummyReply() diff --git a/test/netlib/test_tcp.py b/test/netlib/test_tcp.py index 590bcc01..273427d5 100644 --- a/test/netlib/test_tcp.py +++ b/test/netlib/test_tcp.py @@ -169,7 +169,7 @@ class TestServerSSL(tservers.ServerTestBase): def test_echo(self): c = tcp.TCPClient(("127.0.0.1", self.port)) with c.connect(): - c.convert_to_ssl(sni=b"foo.com", options=SSL.OP_ALL) + c.convert_to_ssl(sni="foo.com", options=SSL.OP_ALL) testval = b"echo!\n" c.wfile.write(testval) c.wfile.flush() @@ -179,7 +179,7 @@ class TestServerSSL(tservers.ServerTestBase): c = tcp.TCPClient(("127.0.0.1", self.port)) with c.connect(): assert not c.get_current_cipher() - c.convert_to_ssl(sni=b"foo.com") + c.convert_to_ssl(sni="foo.com") ret = c.get_current_cipher() assert ret assert "AES" in ret[0] @@ -195,7 +195,7 @@ class TestSSLv3Only(tservers.ServerTestBase): def test_failure(self): c = tcp.TCPClient(("127.0.0.1", self.port)) with c.connect(): - tutils.raises(TlsException, c.convert_to_ssl, sni=b"foo.com") + tutils.raises(TlsException, c.convert_to_ssl, sni="foo.com") class TestSSLUpstreamCertVerificationWBadServerCert(tservers.ServerTestBase): @@ -238,7 +238,7 @@ class TestSSLUpstreamCertVerificationWBadServerCert(tservers.ServerTestBase): with c.connect(): with tutils.raises(InvalidCertificateException): c.convert_to_ssl( - sni=b"example.mitmproxy.org", + sni="example.mitmproxy.org", verify_options=SSL.VERIFY_PEER, ca_pemfile=tutils.test_data.path("data/verificationcerts/trusted-root.crt") ) @@ -272,7 +272,7 @@ class TestSSLUpstreamCertVerificationWBadHostname(tservers.ServerTestBase): with c.connect(): with tutils.raises(InvalidCertificateException): c.convert_to_ssl( - sni=b"mitmproxy.org", + sni="mitmproxy.org", verify_options=SSL.VERIFY_PEER, ca_pemfile=tutils.test_data.path("data/verificationcerts/trusted-root.crt") ) @@ -291,7 +291,7 @@ class TestSSLUpstreamCertVerificationWValidCertChain(tservers.ServerTestBase): c = tcp.TCPClient(("127.0.0.1", self.port)) with c.connect(): c.convert_to_ssl( - sni=b"example.mitmproxy.org", + sni="example.mitmproxy.org", verify_options=SSL.VERIFY_PEER, ca_pemfile=tutils.test_data.path("data/verificationcerts/trusted-root.crt") ) @@ -307,7 +307,7 @@ class TestSSLUpstreamCertVerificationWValidCertChain(tservers.ServerTestBase): c = tcp.TCPClient(("127.0.0.1", self.port)) with c.connect(): c.convert_to_ssl( - sni=b"example.mitmproxy.org", + sni="example.mitmproxy.org", verify_options=SSL.VERIFY_PEER, ca_path=tutils.test_data.path("data/verificationcerts/") ) @@ -371,8 +371,8 @@ class TestSNI(tservers.ServerTestBase): def test_echo(self): c = tcp.TCPClient(("127.0.0.1", self.port)) with c.connect(): - c.convert_to_ssl(sni=b"foo.com") - assert c.sni == b"foo.com" + c.convert_to_ssl(sni="foo.com") + assert c.sni == "foo.com" assert c.rfile.readline() == b"foo.com" @@ -385,7 +385,7 @@ class TestServerCipherList(tservers.ServerTestBase): def test_echo(self): c = tcp.TCPClient(("127.0.0.1", self.port)) with c.connect(): - c.convert_to_ssl(sni=b"foo.com") + c.convert_to_ssl(sni="foo.com") assert c.rfile.readline() == b"['RC4-SHA']" @@ -405,7 +405,7 @@ class TestServerCurrentCipher(tservers.ServerTestBase): def test_echo(self): c = tcp.TCPClient(("127.0.0.1", self.port)) with c.connect(): - c.convert_to_ssl(sni=b"foo.com") + c.convert_to_ssl(sni="foo.com") assert b"RC4-SHA" in c.rfile.readline() @@ -418,7 +418,7 @@ class TestServerCipherListError(tservers.ServerTestBase): def test_echo(self): c = tcp.TCPClient(("127.0.0.1", self.port)) with c.connect(): - tutils.raises("handshake error", c.convert_to_ssl, sni=b"foo.com") + tutils.raises("handshake error", c.convert_to_ssl, sni="foo.com") class TestClientCipherListError(tservers.ServerTestBase): @@ -433,7 +433,7 @@ class TestClientCipherListError(tservers.ServerTestBase): tutils.raises( "cipher specification", c.convert_to_ssl, - sni=b"foo.com", + sni="foo.com", cipher_list="bogus" ) diff --git a/test/pathod/test_pathoc.py b/test/pathod/test_pathoc.py index 28f9f0f8..361a863b 100644 --- a/test/pathod/test_pathoc.py +++ b/test/pathod/test_pathoc.py @@ -54,10 +54,10 @@ class TestDaemonSSL(PathocTestDaemon): def test_sni(self): self.tval( ["get:/p/200"], - sni=b"foobar.com" + sni="foobar.com" ) log = self.d.log() - assert log[0]["request"]["sni"] == b"foobar.com" + assert log[0]["request"]["sni"] == "foobar.com" def test_showssl(self): assert "certificate chain" in self.tval(["get:/p/200"], showssl=True) -- cgit v1.2.3 From 275cf7a6c2189859ad5f5719c8b74b1bc6eebbf2 Mon Sep 17 00:00:00 2001 From: Linmiao Xu Date: Wed, 6 Jul 2016 21:01:04 -0700 Subject: Detect JSON API media type as a json content view IANA assignment here: https://www.iana.org/assignments/media-types/application/vnd.api+json More about JSON API: https://github.com/json-api/json-api --- test/mitmproxy/test_contentview.py | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'test') diff --git a/test/mitmproxy/test_contentview.py b/test/mitmproxy/test_contentview.py index 52fceeac..c11a5fe5 100644 --- a/test/mitmproxy/test_contentview.py +++ b/test/mitmproxy/test_contentview.py @@ -201,6 +201,13 @@ Larry ) assert "Raw" in r[0] + r = cv.get_content_view( + cv.get("Auto"), + b"[1, 2, 3]", + headers=Headers(content_type="application/vnd.api+json") + ) + assert r[0] == "JSON" + tutils.raises( ContentViewException, cv.get_content_view, -- cgit v1.2.3 From f259b9478fb03e816af8abde29ae369342d40e4f Mon Sep 17 00:00:00 2001 From: Maximilian Hils Date: Thu, 7 Jul 2016 01:21:15 -0700 Subject: disable harparser on py3 --- test/mitmproxy/test_examples.py | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'test') diff --git a/test/mitmproxy/test_examples.py b/test/mitmproxy/test_examples.py index 22d3c425..206a0366 100644 --- a/test/mitmproxy/test_examples.py +++ b/test/mitmproxy/test_examples.py @@ -1,6 +1,7 @@ import glob import json import os +import sys from contextlib import contextmanager from mitmproxy import script @@ -133,6 +134,12 @@ def test_redirect_requests(): def test_har_extractor(): + if sys.version_info >= (3, 0): + with tutils.raises("does not work on Python 3"): + with example("har_extractor.py -"): + pass + return + with tutils.raises(script.ScriptException): with example("har_extractor.py"): pass -- cgit v1.2.3 From c870d26bc7fbb1b338a9e4bcb1e60d090bf4d99b Mon Sep 17 00:00:00 2001 From: Shadab Zafar Date: Sat, 2 Jul 2016 18:18:50 +0530 Subject: py3++: test_protocol_http2 --- test/mitmproxy/test_protocol_http2.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'test') diff --git a/test/mitmproxy/test_protocol_http2.py b/test/mitmproxy/test_protocol_http2.py index 2eb0b120..46d3dc05 100644 --- a/test/mitmproxy/test_protocol_http2.py +++ b/test/mitmproxy/test_protocol_http2.py @@ -126,7 +126,7 @@ class _Http2TestBase(object): client.wfile.flush() # read CONNECT response - while client.rfile.readline() != "\r\n": + while client.rfile.readline() != b"\r\n": pass client.convert_to_ssl(alpn_protos=[b'h2']) @@ -203,7 +203,7 @@ class TestSimple(_Http2TestBase, _Http2ServerBase): (':path', '/'), ('ClIeNt-FoO', 'client-bar-1'), ('ClIeNt-FoO', 'client-bar-2'), - ], body='my request body echoed back to me') + ], body=b'my request body echoed back to me') done = False while not done: @@ -275,7 +275,7 @@ class TestWithBodies(_Http2TestBase, _Http2ServerBase): (':scheme', 'https'), (':path', '/'), ], - body='foobar with request body', + body=b'foobar with request body', ) done = False -- cgit v1.2.3 From d962bd4e836856522c101b20e0167c3492d18965 Mon Sep 17 00:00:00 2001 From: Thomas Kriechbaumer Date: Thu, 7 Jul 2016 16:39:20 +0200 Subject: py3++ --- test/mitmproxy/test_protocol_http2.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'test') diff --git a/test/mitmproxy/test_protocol_http2.py b/test/mitmproxy/test_protocol_http2.py index 46d3dc05..58ffb787 100644 --- a/test/mitmproxy/test_protocol_http2.py +++ b/test/mitmproxy/test_protocol_http2.py @@ -169,8 +169,8 @@ class TestSimple(_Http2TestBase, _Http2ServerBase): if isinstance(event, h2.events.ConnectionTerminated): return False elif isinstance(event, h2.events.RequestReceived): - assert ('client-foo', 'client-bar-1') in event.headers - assert ('client-foo', 'client-bar-2') in event.headers + assert (b'client-foo', b'client-bar-1') in event.headers + assert (b'client-foo', b'client-bar-2') in event.headers import warnings with warnings.catch_warnings(): @@ -538,7 +538,7 @@ class TestMaxConcurrentStreams(_Http2TestBase, _Http2ServerBase): (':status', '200'), ('X-Stream-ID', str(event.stream_id)), ]) - h2_conn.send_data(event.stream_id, b'Stream-ID {}'.format(event.stream_id)) + h2_conn.send_data(event.stream_id, 'Stream-ID {}'.format(event.stream_id).encode()) h2_conn.end_stream(event.stream_id) wfile.write(h2_conn.data_to_send()) wfile.flush() @@ -579,7 +579,7 @@ class TestMaxConcurrentStreams(_Http2TestBase, _Http2ServerBase): assert len(self.master.state.flows) == len(new_streams) for flow in self.master.state.flows: assert flow.response.status_code == 200 - assert "Stream-ID" in flow.response.body + assert b"Stream-ID " in flow.response.body @requires_alpn @@ -598,7 +598,7 @@ class TestConnectionTerminated(_Http2TestBase, _Http2ServerBase): @classmethod def handle_server_event(self, event, h2_conn, rfile, wfile): if isinstance(event, h2.events.RequestReceived): - h2_conn.close_connection(error_code=5, last_stream_id=42, additional_data='foobar') + h2_conn.close_connection(error_code=5, last_stream_id=42, additional_data=b'foobar') wfile.write(h2_conn.data_to_send()) wfile.flush() return True @@ -630,4 +630,4 @@ class TestConnectionTerminated(_Http2TestBase, _Http2ServerBase): assert connection_terminated_event is not None assert connection_terminated_event.error_code == 5 assert connection_terminated_event.last_stream_id == 42 - assert connection_terminated_event.additional_data == 'foobar' + assert connection_terminated_event.additional_data == b'foobar' -- cgit v1.2.3 From f62e976e1e0245665aeeb08fa801661d6c766ba8 Mon Sep 17 00:00:00 2001 From: Maximilian Hils Date: Thu, 7 Jul 2016 17:29:22 -0700 Subject: py3++ --- test/mitmproxy/test_flow.py | 163 ++++++++++++++++++++------------------- test/netlib/http/test_request.py | 8 +- 2 files changed, 87 insertions(+), 84 deletions(-) (limited to 'test') diff --git a/test/mitmproxy/test_flow.py b/test/mitmproxy/test_flow.py index 9eaab9aa..bf7622f6 100644 --- a/test/mitmproxy/test_flow.py +++ b/test/mitmproxy/test_flow.py @@ -1,7 +1,7 @@ import os.path -from six.moves import cStringIO as StringIO import mock +import io import netlib.utils from netlib.http import Headers @@ -65,7 +65,7 @@ class TestStickyCookieState: assert s.jar.keys() s, f = self._response("SSID=mooo", "www.google.com") - assert s.jar.keys()[0] == ('www.google.com', 80, '/') + assert list(s.jar.keys())[0] == ('www.google.com', 80, '/') # Test setting of multiple cookies c1 = "somecookie=test; Path=/" @@ -73,7 +73,7 @@ class TestStickyCookieState: s, f = self._response(c1, "www.google.com") f.response.headers["Set-Cookie"] = c2 s.handle_response(f) - googlekey = s.jar.keys()[0] + googlekey = list(s.jar.keys())[0] assert len(s.jar[googlekey].keys()) == 2 # Test setting of weird cookie keys @@ -88,8 +88,8 @@ class TestStickyCookieState: for c in cs: f.response.headers["Set-Cookie"] = c s.handle_response(f) - googlekey = s.jar.keys()[0] - assert len(s.jar[googlekey].keys()) == len(cs) + googlekey = list(s.jar.keys())[0] + assert len(s.jar[googlekey]) == len(cs) # Test overwriting of a cookie value c1 = "somecookie=helloworld; Path=/" @@ -97,12 +97,12 @@ class TestStickyCookieState: s, f = self._response(c1, "www.google.com") f.response.headers["Set-Cookie"] = c2 s.handle_response(f) - googlekey = s.jar.keys()[0] - assert len(s.jar[googlekey].keys()) == 1 - assert s.jar[googlekey]["somecookie"].items()[0][1] == "newvalue" + googlekey = list(s.jar.keys())[0] + assert len(s.jar[googlekey]) == 1 + assert list(s.jar[googlekey]["somecookie"].values())[0] == "newvalue" def test_request(self): - s, f = self._response("SSID=mooo", "www.google.com") + s, f = self._response("SSID=mooo", b"www.google.com") assert "cookie" not in f.request.headers s.handle_request(f) assert "cookie" in f.request.headers @@ -264,26 +264,26 @@ class TestServerPlaybackState: "param1", "param2"], False) r = tutils.tflow(resp=True) r.request.headers["Content-Type"] = "application/x-www-form-urlencoded" - r.request.content = "paramx=x¶m1=1" + 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 = "paramx=x¶m1=1" + r2.request.content = b"paramx=x¶m1=1" # same parameters assert s._hash(r) == s._hash(r2) # ignored parameters != - r2.request.content = "paramx=x¶m1=2" + r2.request.content = b"paramx=x¶m1=2" assert s._hash(r) == s._hash(r2) # missing parameter - r2.request.content = "paramx=x" + r2.request.content = b"paramx=x" assert s._hash(r) == s._hash(r2) # ignorable parameter added - r2.request.content = "paramx=x¶m1=2" + r2.request.content = b"paramx=x¶m1=2" assert s._hash(r) == s._hash(r2) # not ignorable parameter changed - r2.request.content = "paramx=y¶m1=1" + r2.request.content = b"paramx=y¶m1=1" assert not s._hash(r) == s._hash(r2) # not ignorable parameter missing - r2.request.content = "param1=1" + r2.request.content = b"param1=1" assert not s._hash(r) == s._hash(r2) def test_ignore_payload_params_other_content_type(self): @@ -292,14 +292,14 @@ class TestServerPlaybackState: "param1", "param2"], False) r = tutils.tflow(resp=True) r.request.headers["Content-Type"] = "application/json" - r.request.content = '{"param1":"1"}' + r.request.content = b'{"param1":"1"}' r2 = tutils.tflow(resp=True) r2.request.headers["Content-Type"] = "application/json" - r2.request.content = '{"param1":"1"}' + 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 = '{"param1":"2"}' + r2.request.content = b'{"param1":"2"}' assert not s._hash(r) == s._hash(r2) def test_ignore_payload_wins_over_params(self): @@ -309,10 +309,10 @@ class TestServerPlaybackState: "param1", "param2"], False) r = tutils.tflow(resp=True) r.request.headers["Content-Type"] = "application/x-www-form-urlencoded" - r.request.content = "paramx=y" + r.request.content = b"paramx=y" r2 = tutils.tflow(resp=True) r2.request.headers["Content-Type"] = "application/x-www-form-urlencoded" - r2.request.content = "paramx=x" + r2.request.content = b"paramx=x" # same parameters assert s._hash(r) == s._hash(r2) @@ -329,10 +329,10 @@ class TestServerPlaybackState: r = tutils.tflow(resp=True) r2 = tutils.tflow(resp=True) - r.request.content = "foo" - r2.request.content = "foo" + r.request.content = b"foo" + r2.request.content = b"foo" assert s._hash(r) == s._hash(r2) - r2.request.content = "bar" + r2.request.content = b"bar" assert not s._hash(r) == s._hash(r2) # now ignoring content @@ -347,12 +347,12 @@ class TestServerPlaybackState: False) r = tutils.tflow(resp=True) r2 = tutils.tflow(resp=True) - r.request.content = "foo" - r2.request.content = "foo" + r.request.content = b"foo" + r2.request.content = b"foo" assert s._hash(r) == s._hash(r2) - r2.request.content = "bar" + r2.request.content = b"bar" assert s._hash(r) == s._hash(r2) - r2.request.content = "" + r2.request.content = b"" assert s._hash(r) == s._hash(r2) r2.request.content = None assert s._hash(r) == s._hash(r2) @@ -420,13 +420,13 @@ class TestFlow(object): def test_backup(self): f = tutils.tflow() f.response = HTTPResponse.wrap(netlib.tutils.tresp()) - f.request.content = "foo" + f.request.content = b"foo" assert not f.modified() f.backup() - f.request.content = "bar" + f.request.content = b"bar" assert f.modified() f.revert() - assert f.request.content == "foo" + assert f.request.content == b"foo" def test_backup_idempotence(self): f = tutils.tflow(resp=True) @@ -486,8 +486,8 @@ class TestFlow(object): def test_replace_unicode(self): f = tutils.tflow(resp=True) - f.response.content = "\xc2foo" - f.replace("foo", u"bar") + f.response.content = b"\xc2foo" + f.replace(b"foo", u"bar") def test_replace_no_content(self): f = tutils.tflow() @@ -497,34 +497,34 @@ class TestFlow(object): def test_replace(self): f = tutils.tflow(resp=True) f.request.headers["foo"] = "foo" - f.request.content = "afoob" + f.request.content = b"afoob" f.response.headers["foo"] = "foo" - f.response.content = "afoob" + f.response.content = b"afoob" assert f.replace("foo", "bar") == 6 assert f.request.headers["bar"] == "bar" - assert f.request.content == "abarb" + assert f.request.content == b"abarb" assert f.response.headers["bar"] == "bar" - assert f.response.content == "abarb" + assert f.response.content == b"abarb" def test_replace_encoded(self): f = tutils.tflow(resp=True) - f.request.content = "afoob" + f.request.content = b"afoob" f.request.encode("gzip") - f.response.content = "afoob" + f.response.content = b"afoob" f.response.encode("gzip") f.replace("foo", "bar") - assert f.request.content != "abarb" + assert f.request.content != b"abarb" f.request.decode() - assert f.request.content == "abarb" + assert f.request.content == b"abarb" - assert f.response.content != "abarb" + assert f.response.content != b"abarb" f.response.decode() - assert f.response.content == "abarb" + assert f.response.content == b"abarb" class TestState: @@ -667,7 +667,7 @@ class TestState: class TestSerialize: def _treader(self): - sio = StringIO() + sio = io.BytesIO() w = flow.FlowWriter(sio) for i in range(3): f = tutils.tflow(resp=True) @@ -684,9 +684,9 @@ class TestSerialize: return flow.FlowReader(sio) def test_roundtrip(self): - sio = StringIO() + sio = io.BytesIO() f = tutils.tflow() - f.request.content = "".join(chr(i) for i in range(255)) + f.request.content = bytes(bytearray(range(256))) w = flow.FlowWriter(sio) w.add(f) @@ -718,7 +718,7 @@ class TestSerialize: assert s.flows[0].request.host == "use-this-domain" def test_filter(self): - sio = StringIO() + sio = io.BytesIO() fl = filt.parse("~c 200") w = flow.FilteredFlowWriter(sio, fl) @@ -735,8 +735,8 @@ class TestSerialize: assert len(list(r.stream())) def test_error(self): - sio = StringIO() - sio.write("bogus") + sio = io.BytesIO() + sio.write(b"bogus") sio.seek(0) r = flow.FlowReader(sio) tutils.raises(FlowReadException, list, r.stream()) @@ -748,7 +748,7 @@ class TestSerialize: f = tutils.tflow() d = f.get_state() d["version"] = (0, 0) - sio = StringIO() + sio = io.BytesIO() tnetstring.dump(d, sio) sio.seek(0) @@ -938,7 +938,7 @@ class TestFlowMaster: None, False) r = tutils.tflow() - r.request.content = "gibble" + r.request.content = b"gibble" assert not fm.do_server_playback(r) assert fm.do_server_playback(tutils.tflow()) @@ -1017,27 +1017,30 @@ class TestFlowMaster: with tutils.tmpdir() as tdir: p = os.path.join(tdir, "foo") - def r(): - r = flow.FlowReader(open(p, "rb")) - return list(r.stream()) + def read(): + with open(p, "rb") as f: + r = flow.FlowReader(f) + return list(r.stream()) s = flow.State() fm = flow.FlowMaster(None, s) f = tutils.tflow(resp=True) - fm.start_stream(file(p, "ab"), None) - fm.request(f) - fm.response(f) - fm.stop_stream() + with open(p, "ab") as tmpfile: + fm.start_stream(tmpfile, None) + fm.request(f) + fm.response(f) + fm.stop_stream() - assert r()[0].response + assert read()[0].response - f = tutils.tflow() - fm.start_stream(file(p, "ab"), None) - fm.request(f) - fm.shutdown() + with open(p, "ab") as tmpfile: + f = tutils.tflow() + fm.start_stream(tmpfile, None) + fm.request(f) + fm.shutdown() - assert not r()[1].response + assert not read()[1].response class TestRequest: @@ -1086,10 +1089,10 @@ class TestRequest: r = HTTPRequest.wrap(netlib.tutils.treq()) r.path = "path/foo" r.headers["Foo"] = "fOo" - r.content = "afoob" + r.content = b"afoob" assert r.replace("foo(?i)", "boo") == 4 assert r.path == "path/boo" - assert "foo" not in r.content + assert b"foo" not in r.content assert r.headers["boo"] == "boo" def test_constrain_encoding(self): @@ -1108,9 +1111,9 @@ class TestRequest: r.headers["content-encoding"] = "identity" assert r.get_decoded_content() is None - r.content = "falafel" + r.content = b"falafel" r.encode("gzip") - assert r.get_decoded_content() == "falafel" + assert r.get_decoded_content() == b"falafel" def test_get_content_type(self): resp = HTTPResponse.wrap(netlib.tutils.tresp()) @@ -1129,9 +1132,9 @@ class TestResponse: def test_replace(self): r = HTTPResponse.wrap(netlib.tutils.tresp()) r.headers["Foo"] = "fOo" - r.content = "afoob" + r.content = b"afoob" assert r.replace("foo(?i)", "boo") == 3 - assert "foo" not in r.content + assert b"foo" not in r.content assert r.headers["boo"] == "boo" def test_get_content_type(self): @@ -1208,24 +1211,24 @@ def test_replacehooks(): assert h.count() == 0 f = tutils.tflow() - f.request.content = "foo" + f.request.content = b"foo" h.add("~s", "foo", "bar") h.run(f) - assert f.request.content == "foo" + assert f.request.content == b"foo" f = tutils.tflow(resp=True) - f.request.content = "foo" - f.response.content = "foo" + f.request.content = b"foo" + f.response.content = b"foo" h.run(f) - assert f.response.content == "bar" - assert f.request.content == "foo" + assert f.response.content == b"bar" + assert f.request.content == b"foo" f = tutils.tflow() h.clear() h.add("~q", "foo", "bar") - f.request.content = "foo" + f.request.content = b"foo" h.run(f) - assert f.request.content == "bar" + assert f.request.content == b"bar" assert not h.add("~", "foo", "bar") assert not h.add("foo", "*", "bar") @@ -1257,10 +1260,10 @@ def test_setheaders(): assert h.count() == 0 f = tutils.tflow() - f.request.content = "foo" + f.request.content = b"foo" h.add("~s", "foo", "bar") h.run(f) - assert f.request.content == "foo" + assert f.request.content == b"foo" h.clear() h.add("~s", "one", "two") diff --git a/test/netlib/http/test_request.py b/test/netlib/http/test_request.py index c03db339..f3cd8b71 100644 --- a/test/netlib/http/test_request.py +++ b/test/netlib/http/test_request.py @@ -248,20 +248,20 @@ class TestRequestUtils(object): assert "gzip" in request.headers["Accept-Encoding"] def test_get_urlencoded_form(self): - request = treq(content="foobar=baz") + request = treq(content=b"foobar=baz") assert not request.urlencoded_form request.headers["Content-Type"] = "application/x-www-form-urlencoded" - assert list(request.urlencoded_form.items()) == [("foobar", "baz")] + assert list(request.urlencoded_form.items()) == [(b"foobar", b"baz")] def test_set_urlencoded_form(self): request = treq() - request.urlencoded_form = [('foo', 'bar'), ('rab', 'oof')] + request.urlencoded_form = [(b'foo', b'bar'), (b'rab', b'oof')] assert request.headers["Content-Type"] == "application/x-www-form-urlencoded" assert request.content def test_get_multipart_form(self): - request = treq(content="foobar") + request = treq(content=b"foobar") assert not request.multipart_form request.headers["Content-Type"] = "multipart/form-data" -- cgit v1.2.3 From 76473d44e035306503a426ebcd55967798f243a1 Mon Sep 17 00:00:00 2001 From: Maximilian Hils Date: Thu, 7 Jul 2016 17:50:26 -0700 Subject: py3++ --- test/mitmproxy/test_examples.py | 14 +++++++------- test/mitmproxy/test_flow_export.py | 10 +++++----- test/netlib/http/http1/test_assemble.py | 2 +- test/netlib/http/test_message.py | 4 ++-- 4 files changed, 15 insertions(+), 15 deletions(-) (limited to 'test') diff --git a/test/mitmproxy/test_examples.py b/test/mitmproxy/test_examples.py index 206a0366..f30973e7 100644 --- a/test/mitmproxy/test_examples.py +++ b/test/mitmproxy/test_examples.py @@ -84,11 +84,11 @@ def test_iframe_injector(): with example("iframe_injector.py") as ex: pass - flow = tutils.tflow(resp=netutils.tresp(content="mitmproxy")) + flow = tutils.tflow(resp=netutils.tresp(content=b"mitmproxy")) with example("iframe_injector.py http://example.org/evil_iframe") as ex: ex.run("response", flow) content = flow.response.content - assert 'iframe' in content and 'evil_iframe' in content + assert b'iframe' in content and b'evil_iframe' in content def test_modify_form(): @@ -96,11 +96,11 @@ def test_modify_form(): flow = tutils.tflow(req=netutils.treq(headers=form_header)) with example("modify_form.py") as ex: ex.run("request", flow) - assert flow.request.urlencoded_form["mitmproxy"] == "rocks" + assert flow.request.urlencoded_form[b"mitmproxy"] == b"rocks" flow.request.headers["content-type"] = "" ex.run("request", flow) - assert list(flow.request.urlencoded_form.items()) == [("foo", "bar")] + assert list(flow.request.urlencoded_form.items()) == [(b"foo", b"bar")] def test_modify_querystring(): @@ -119,11 +119,11 @@ def test_modify_response_body(): with example("modify_response_body.py"): assert True - flow = tutils.tflow(resp=netutils.tresp(content="I <3 mitmproxy")) + flow = tutils.tflow(resp=netutils.tresp(content=b"I <3 mitmproxy")) with example("modify_response_body.py mitmproxy rocks") as ex: - assert ex.ctx.old == "mitmproxy" and ex.ctx.new == "rocks" + assert ex.ctx.old == b"mitmproxy" and ex.ctx.new == b"rocks" ex.run("response", flow) - assert flow.response.content == "I <3 rocks" + assert flow.response.content == b"I <3 rocks" def test_redirect_requests(): diff --git a/test/mitmproxy/test_flow_export.py b/test/mitmproxy/test_flow_export.py index 33c5137a..e6d65e40 100644 --- a/test/mitmproxy/test_flow_export.py +++ b/test/mitmproxy/test_flow_export.py @@ -60,7 +60,7 @@ class TestExportPythonCode(): def test_post_json(self): p = req_post() - p.content = '{"name": "example", "email": "example@example.com"}' + p.content = b'{"name": "example", "email": "example@example.com"}' p.headers = Headers(content_type="application/json") flow = tutils.tflow(req=p) python_equals("data/test_flow_export/python_post_json.py", export.python_code(flow)) @@ -112,7 +112,7 @@ class TestExportLocustCode(): def test_post(self): p = req_post() - p.content = '''content''' + p.content = b'content' p.headers = '' flow = tutils.tflow(req=p) python_equals("data/test_flow_export/locust_post.py", export.locust_code(flow)) @@ -142,14 +142,14 @@ class TestIsJson(): def test_json_type(self): headers = Headers(content_type="application/json") - assert export.is_json(headers, "foobar") is False + assert export.is_json(headers, b"foobar") is False def test_valid(self): headers = Headers(content_type="application/foobar") - j = export.is_json(headers, '{"name": "example", "email": "example@example.com"}') + j = export.is_json(headers, b'{"name": "example", "email": "example@example.com"}') assert j is False def test_valid2(self): headers = Headers(content_type="application/json") - j = export.is_json(headers, '{"name": "example", "email": "example@example.com"}') + j = export.is_json(headers, b'{"name": "example", "email": "example@example.com"}') assert isinstance(j, dict) diff --git a/test/netlib/http/http1/test_assemble.py b/test/netlib/http/http1/test_assemble.py index 50d29384..841ea58a 100644 --- a/test/netlib/http/http1/test_assemble.py +++ b/test/netlib/http/http1/test_assemble.py @@ -24,7 +24,7 @@ def test_assemble_request(): def test_assemble_request_head(): - c = assemble_request_head(treq(content="foo")) + c = assemble_request_head(treq(content=b"foo")) assert b"GET" in c assert b"qvalue" in c assert b"content-length" in c diff --git a/test/netlib/http/test_message.py b/test/netlib/http/test_message.py index f5bf7f0c..ab2ac628 100644 --- a/test/netlib/http/test_message.py +++ b/test/netlib/http/test_message.py @@ -7,8 +7,8 @@ from netlib.tutils import tresp def _test_passthrough_attr(message, attr): assert getattr(message, attr) == getattr(message.data, attr) - setattr(message, attr, "foo") - assert getattr(message.data, attr) == "foo" + setattr(message, attr, b"foo") + assert getattr(message.data, attr) == b"foo" def _test_decoded_attr(message, attr): -- cgit v1.2.3 From 00dce240150595e41719e512f1b156103c3c9c31 Mon Sep 17 00:00:00 2001 From: Maximilian Hils Date: Thu, 7 Jul 2016 18:02:59 -0700 Subject: tests++ --- test/netlib/test_strutils.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'test') diff --git a/test/netlib/test_strutils.py b/test/netlib/test_strutils.py index f88e33ed..68bfdb94 100644 --- a/test/netlib/test_strutils.py +++ b/test/netlib/test_strutils.py @@ -3,6 +3,13 @@ import six from netlib import strutils, tutils +def test_always_bytes(): + assert strutils.always_bytes(bytes(bytearray(range(256)))) == bytes(bytearray(range(256))) + assert strutils.always_bytes("foo") == b"foo" + with tutils.raises(ValueError): + strutils.always_bytes(u"\u2605", "ascii") + + def test_native(): with tutils.raises(TypeError): strutils.native(42) @@ -31,6 +38,9 @@ def test_escape_control_characters(): u'=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~.' ) + with tutils.raises(ValueError): + strutils.escape_control_characters(b"foo") + def test_bytes_to_escaped_str(): assert strutils.bytes_to_escaped_str(b"foo") == "foo" @@ -68,6 +78,11 @@ def test_escaped_str_to_bytes(): strutils.escaped_str_to_bytes(b"very byte") +def test_is_mostly_bin(): + assert not strutils.is_mostly_bin(b"foo\xFF") + assert strutils.is_mostly_bin(b"foo" + b"\xFF" * 10) + + def test_is_xml(): assert not strutils.is_xml(b"foo") assert strutils.is_xml(b" Date: Thu, 7 Jul 2016 18:37:33 -0700 Subject: remove context from all scripts --- test/mitmproxy/data/scripts/a.py | 4 +-- test/mitmproxy/data/scripts/all.py | 29 +++++++++++----------- .../mitmproxy/data/scripts/concurrent_decorator.py | 2 +- .../data/scripts/concurrent_decorator_err.py | 2 +- test/mitmproxy/data/scripts/duplicate_flow.py | 8 +++--- test/mitmproxy/data/scripts/reqerr.py | 4 +-- test/mitmproxy/data/scripts/starterr.py | 2 +- test/mitmproxy/data/scripts/stream_modify.py | 2 +- test/mitmproxy/data/scripts/tcp_stream_modify.py | 2 +- test/mitmproxy/data/scripts/unloaderr.py | 2 +- 10 files changed, 30 insertions(+), 27 deletions(-) (limited to 'test') diff --git a/test/mitmproxy/data/scripts/a.py b/test/mitmproxy/data/scripts/a.py index 33dbaa64..ab0dbf96 100644 --- a/test/mitmproxy/data/scripts/a.py +++ b/test/mitmproxy/data/scripts/a.py @@ -5,12 +5,12 @@ from a_helper import parser var = 0 -def start(ctx): +def start(): global var var = parser.parse_args(sys.argv[1:]).var -def here(ctx): +def here(): global var var += 1 return var diff --git a/test/mitmproxy/data/scripts/all.py b/test/mitmproxy/data/scripts/all.py index dad2aade..17ffe33f 100644 --- a/test/mitmproxy/data/scripts/all.py +++ b/test/mitmproxy/data/scripts/all.py @@ -1,36 +1,37 @@ +import mitmproxy log = [] -def clientconnect(ctx, cc): - ctx.log("XCLIENTCONNECT") +def clientconnect(cc): + mitmproxy.log("XCLIENTCONNECT") log.append("clientconnect") -def serverconnect(ctx, cc): - ctx.log("XSERVERCONNECT") +def serverconnect(cc): + mitmproxy.log("XSERVERCONNECT") log.append("serverconnect") -def request(ctx, f): - ctx.log("XREQUEST") +def request(f): + mitmproxy.log("XREQUEST") log.append("request") -def response(ctx, f): - ctx.log("XRESPONSE") +def response(f): + mitmproxy.log("XRESPONSE") log.append("response") -def responseheaders(ctx, f): - ctx.log("XRESPONSEHEADERS") +def responseheaders(f): + mitmproxy.log("XRESPONSEHEADERS") log.append("responseheaders") -def clientdisconnect(ctx, cc): - ctx.log("XCLIENTDISCONNECT") +def clientdisconnect(cc): + mitmproxy.log("XCLIENTDISCONNECT") log.append("clientdisconnect") -def error(ctx, cc): - ctx.log("XERROR") +def error(cc): + mitmproxy.log("XERROR") log.append("error") diff --git a/test/mitmproxy/data/scripts/concurrent_decorator.py b/test/mitmproxy/data/scripts/concurrent_decorator.py index e017f605..162c00f4 100644 --- a/test/mitmproxy/data/scripts/concurrent_decorator.py +++ b/test/mitmproxy/data/scripts/concurrent_decorator.py @@ -3,5 +3,5 @@ from mitmproxy.script import concurrent @concurrent -def request(context, flow): +def request(flow): time.sleep(0.1) diff --git a/test/mitmproxy/data/scripts/concurrent_decorator_err.py b/test/mitmproxy/data/scripts/concurrent_decorator_err.py index 349e5dd6..756869c8 100644 --- a/test/mitmproxy/data/scripts/concurrent_decorator_err.py +++ b/test/mitmproxy/data/scripts/concurrent_decorator_err.py @@ -2,5 +2,5 @@ from mitmproxy.script import concurrent @concurrent -def start(context): +def start(): pass diff --git a/test/mitmproxy/data/scripts/duplicate_flow.py b/test/mitmproxy/data/scripts/duplicate_flow.py index e13af786..a50d2cb5 100644 --- a/test/mitmproxy/data/scripts/duplicate_flow.py +++ b/test/mitmproxy/data/scripts/duplicate_flow.py @@ -1,4 +1,6 @@ +import mitmproxy -def request(ctx, f): - f = ctx.duplicate_flow(f) - ctx.replay_request(f) + +def request(f): + f = mitmproxy.master.duplicate_flow(f) + mitmproxy.master.replay_request(f, block=True, run_scripthooks=False) diff --git a/test/mitmproxy/data/scripts/reqerr.py b/test/mitmproxy/data/scripts/reqerr.py index e7c503a8..7b419361 100644 --- a/test/mitmproxy/data/scripts/reqerr.py +++ b/test/mitmproxy/data/scripts/reqerr.py @@ -1,2 +1,2 @@ -def request(ctx, r): - raise ValueError +def request(r): + raise ValueError() diff --git a/test/mitmproxy/data/scripts/starterr.py b/test/mitmproxy/data/scripts/starterr.py index 82d773bd..28ba2ff1 100644 --- a/test/mitmproxy/data/scripts/starterr.py +++ b/test/mitmproxy/data/scripts/starterr.py @@ -1,3 +1,3 @@ -def start(ctx): +def start(): raise ValueError() diff --git a/test/mitmproxy/data/scripts/stream_modify.py b/test/mitmproxy/data/scripts/stream_modify.py index 8221b0dd..4fbf45c2 100644 --- a/test/mitmproxy/data/scripts/stream_modify.py +++ b/test/mitmproxy/data/scripts/stream_modify.py @@ -3,5 +3,5 @@ def modify(chunks): yield chunk.replace(b"foo", b"bar") -def responseheaders(context, flow): +def responseheaders(flow): flow.response.stream = modify diff --git a/test/mitmproxy/data/scripts/tcp_stream_modify.py b/test/mitmproxy/data/scripts/tcp_stream_modify.py index 0965beba..2281e6e6 100644 --- a/test/mitmproxy/data/scripts/tcp_stream_modify.py +++ b/test/mitmproxy/data/scripts/tcp_stream_modify.py @@ -1,4 +1,4 @@ -def tcp_message(ctx, flow): +def tcp_message(flow): message = flow.messages[-1] if not message.from_client: message.content = message.content.replace(b"foo", b"bar") diff --git a/test/mitmproxy/data/scripts/unloaderr.py b/test/mitmproxy/data/scripts/unloaderr.py index fba02734..6a48ab43 100644 --- a/test/mitmproxy/data/scripts/unloaderr.py +++ b/test/mitmproxy/data/scripts/unloaderr.py @@ -1,2 +1,2 @@ -def done(ctx): +def done(): raise RuntimeError() -- cgit v1.2.3 From 7c67faa8da39f428d1860bccae806137943b66a6 Mon Sep 17 00:00:00 2001 From: Maximilian Hils Date: Thu, 7 Jul 2016 23:50:55 -0700 Subject: remove script contexts --- test/mitmproxy/script/test_concurrent.py | 4 +-- test/mitmproxy/script/test_reloader.py | 2 +- test/mitmproxy/script/test_script.py | 28 +++++++++--------- test/mitmproxy/test_examples.py | 49 +++++++++++++------------------- test/mitmproxy/test_server.py | 3 +- 5 files changed, 38 insertions(+), 48 deletions(-) (limited to 'test') diff --git a/test/mitmproxy/script/test_concurrent.py b/test/mitmproxy/script/test_concurrent.py index 62541f3f..57eeca19 100644 --- a/test/mitmproxy/script/test_concurrent.py +++ b/test/mitmproxy/script/test_concurrent.py @@ -11,7 +11,7 @@ class Thing: @tutils.skip_appveyor def test_concurrent(): - with Script(tutils.test_data.path("data/scripts/concurrent_decorator.py"), None) as s: + with Script(tutils.test_data.path("data/scripts/concurrent_decorator.py")) as s: f1, f2 = Thing(), Thing() s.run("request", f1) s.run("request", f2) @@ -23,6 +23,6 @@ def test_concurrent(): def test_concurrent_err(): - s = Script(tutils.test_data.path("data/scripts/concurrent_decorator_err.py"), None) + s = Script(tutils.test_data.path("data/scripts/concurrent_decorator_err.py")) with tutils.raises("Concurrent decorator not supported for 'start' method"): s.load() diff --git a/test/mitmproxy/script/test_reloader.py b/test/mitmproxy/script/test_reloader.py index 0345f6ed..e33903b9 100644 --- a/test/mitmproxy/script/test_reloader.py +++ b/test/mitmproxy/script/test_reloader.py @@ -10,7 +10,7 @@ def test_simple(): pass script = mock.Mock() - script.filename = "foo.py" + script.path = "foo.py" e = Event() diff --git a/test/mitmproxy/script/test_script.py b/test/mitmproxy/script/test_script.py index fe98fab5..48fe65c9 100644 --- a/test/mitmproxy/script/test_script.py +++ b/test/mitmproxy/script/test_script.py @@ -21,21 +21,21 @@ class TestParseCommand: def test_parse_args(self): with tutils.chdir(tutils.test_data.dirname): - assert Script.parse_command("data/scripts/a.py") == ["data/scripts/a.py"] - assert Script.parse_command("data/scripts/a.py foo bar") == ["data/scripts/a.py", "foo", "bar"] - assert Script.parse_command("data/scripts/a.py 'foo bar'") == ["data/scripts/a.py", "foo bar"] + assert Script.parse_command("data/scripts/a.py") == ("data/scripts/a.py", []) + assert Script.parse_command("data/scripts/a.py foo bar") == ("data/scripts/a.py", ["foo", "bar"]) + assert Script.parse_command("data/scripts/a.py 'foo bar'") == ("data/scripts/a.py", ["foo bar"]) @tutils.skip_not_windows def test_parse_windows(self): with tutils.chdir(tutils.test_data.dirname): - assert Script.parse_command("data\\scripts\\a.py") == ["data\\scripts\\a.py"] - assert Script.parse_command("data\\scripts\\a.py 'foo \\ bar'") == ["data\\scripts\\a.py", 'foo \\ bar'] + assert Script.parse_command("data\\scripts\\a.py") == ("data\\scripts\\a.py", []) + assert Script.parse_command("data\\scripts\\a.py 'foo \\ bar'") == ("data\\scripts\\a.py", ['foo \\ bar']) def test_simple(): with tutils.chdir(tutils.test_data.path("data/scripts")): - s = Script("a.py --var 42", None) - assert s.filename == "a.py" + s = Script("a.py --var 42") + assert s.path == "a.py" assert s.ns is None s.load() @@ -50,34 +50,34 @@ def test_simple(): with tutils.raises(ScriptException): s.run("here") - with Script("a.py --var 42", None) as s: + with Script("a.py --var 42") as s: s.run("here") def test_script_exception(): with tutils.chdir(tutils.test_data.path("data/scripts")): - s = Script("syntaxerr.py", None) + s = Script("syntaxerr.py") with tutils.raises(ScriptException): s.load() - s = Script("starterr.py", None) + s = Script("starterr.py") with tutils.raises(ScriptException): s.load() - s = Script("a.py", None) + s = Script("a.py") s.load() with tutils.raises(ScriptException): s.load() - s = Script("a.py", None) + s = Script("a.py") with tutils.raises(ScriptException): s.run("here") with tutils.raises(ScriptException): - with Script("reqerr.py", None) as s: + with Script("reqerr.py") as s: s.run("request", None) - s = Script("unloaderr.py", None) + s = Script("unloaderr.py") s.load() with tutils.raises(ScriptException): s.unload() diff --git a/test/mitmproxy/test_examples.py b/test/mitmproxy/test_examples.py index f30973e7..3b5ff2a2 100644 --- a/test/mitmproxy/test_examples.py +++ b/test/mitmproxy/test_examples.py @@ -1,47 +1,31 @@ import glob import json +import mock import os import sys from contextlib import contextmanager from mitmproxy import script -from mitmproxy.proxy import config import netlib.utils from netlib import tutils as netutils from netlib.http import Headers -from . import tservers, tutils +from . import tutils example_dir = netlib.utils.Data(__name__).path("../../examples") -class DummyContext(object): - """Emulate script.ScriptContext() functionality.""" - - contentview = None - - def log(self, *args, **kwargs): - pass - - def add_contentview(self, view_obj): - self.contentview = view_obj - - def remove_contentview(self, view_obj): - self.contentview = None - - @contextmanager def example(command): command = os.path.join(example_dir, command) - ctx = DummyContext() - with script.Script(command, ctx) as s: + with script.Script(command) as s: yield s -def test_load_scripts(): +@mock.patch("mitmproxy.master") +@mock.patch("mitmproxy.log") +def test_load_scripts(log, master): scripts = glob.glob("%s/*.py" % example_dir) - tmaster = tservers.TestMaster(config.ProxyConfig()) - for f in scripts: if "har_extractor" in f: continue @@ -54,7 +38,7 @@ def test_load_scripts(): if "modify_response_body" in f: f += " foo bar" # two arguments required - s = script.Script(f, script.ScriptContext(tmaster)) + s = script.Script(f) try: s.load() except Exception as v: @@ -71,17 +55,21 @@ def test_add_header(): assert flow.response.headers["newheader"] == "foo" -def test_custom_contentviews(): - with example("custom_contentviews.py") as ex: - pig = ex.ctx.contentview +@mock.patch("mitmproxy.contentviews.remove") +@mock.patch("mitmproxy.contentviews.add") +def test_custom_contentviews(add, remove): + with example("custom_contentviews.py"): + assert add.called + pig = add.call_args[0][0] _, fmt = pig(b"test!") assert any(b'esttay!' in val[0][1] for val in fmt) assert not pig(b"gobbledygook") + assert remove.called def test_iframe_injector(): with tutils.raises(script.ScriptException): - with example("iframe_injector.py") as ex: + with example("iframe_injector.py"): pass flow = tutils.tflow(resp=netutils.tresp(content=b"mitmproxy")) @@ -121,7 +109,7 @@ def test_modify_response_body(): flow = tutils.tflow(resp=netutils.tresp(content=b"I <3 mitmproxy")) with example("modify_response_body.py mitmproxy rocks") as ex: - assert ex.ctx.old == b"mitmproxy" and ex.ctx.new == b"rocks" + assert ex.ns["state"]["old"] == b"mitmproxy" and ex.ns["state"]["new"] == b"rocks" ex.run("response", flow) assert flow.response.content == b"I <3 rocks" @@ -133,7 +121,8 @@ def test_redirect_requests(): assert flow.request.host == "mitmproxy.org" -def test_har_extractor(): +@mock.patch("mitmproxy.log") +def test_har_extractor(log): if sys.version_info >= (3, 0): with tutils.raises("does not work on Python 3"): with example("har_extractor.py -"): @@ -159,4 +148,4 @@ def test_har_extractor(): with open(tutils.test_data.path("data/har_extractor.har")) as fp: test_data = json.load(fp) - assert json.loads(ex.ctx.HARLog.json()) == test_data["test_response"] + assert json.loads(ex.ns["context"].HARLog.json()) == test_data["test_response"] diff --git a/test/mitmproxy/test_server.py b/test/mitmproxy/test_server.py index 0ab7624e..9dd8b79c 100644 --- a/test/mitmproxy/test_server.py +++ b/test/mitmproxy/test_server.py @@ -1,6 +1,7 @@ import os import socket import time +import types from OpenSSL import SSL from netlib.exceptions import HttpReadDisconnect, HttpException from netlib.tcp import Address @@ -945,7 +946,7 @@ class TestProxyChainingSSLReconnect(tservers.HTTPUpstreamProxyTest): f.reply.kill() return _func(f) - setattr(master, attr, handler) + setattr(master, attr, types.MethodType(handler, master)) kill_requests( self.chain[1].tmaster, -- cgit v1.2.3 From 05ab9c1b376473265af1a779c59319cc99b5fcd3 Mon Sep 17 00:00:00 2001 From: jpkrause Date: Fri, 8 Jul 2016 15:03:36 -0700 Subject: Updated coding style and modified flow format compat test to use v0.11 and v0.10 dump files --- test/mitmproxy/data/dumpfile-010 | Bin 0 -> 2140 bytes test/mitmproxy/data/dumpfile-011 | Bin 0 -> 5465 bytes test/mitmproxy/data/dumpfile-012 | 35 ------------------------------ test/mitmproxy/data/dumpfile-013 | 35 ------------------------------ test/mitmproxy/test_flow_format_compat.py | 4 ++-- 5 files changed, 2 insertions(+), 72 deletions(-) create mode 100644 test/mitmproxy/data/dumpfile-010 create mode 100644 test/mitmproxy/data/dumpfile-011 delete mode 100644 test/mitmproxy/data/dumpfile-012 delete mode 100644 test/mitmproxy/data/dumpfile-013 (limited to 'test') diff --git a/test/mitmproxy/data/dumpfile-010 b/test/mitmproxy/data/dumpfile-010 new file mode 100644 index 00000000..435795bf Binary files /dev/null and b/test/mitmproxy/data/dumpfile-010 differ diff --git a/test/mitmproxy/data/dumpfile-011 b/test/mitmproxy/data/dumpfile-011 new file mode 100644 index 00000000..2534ad89 Binary files /dev/null and b/test/mitmproxy/data/dumpfile-011 differ diff --git a/test/mitmproxy/data/dumpfile-012 b/test/mitmproxy/data/dumpfile-012 deleted file mode 100644 index 49c2350d..00000000 --- a/test/mitmproxy/data/dumpfile-012 +++ /dev/null @@ -1,35 +0,0 @@ -4092:8:response,491:11:httpversion,8:1:1#1:1#]13:timestamp_end,14:1449080668.874^3:msg,12:Not Modified,15:timestamp_start,14:1449080668.863^7:headers,330:35:13:Cache-Control,14:max-age=604800,]40:4:Date,29:Wed, 02 Dec 2015 18:24:32 GMT,]32:4:Etag,21:"359670651+gzip+gzip",]43:7:Expires,29:Wed, 09 Dec 2015 18:24:32 GMT,]50:13:Last-Modified,29:Fri, 09 Aug 2013 23:54:35 GMT,]27:6:Server,14:ECS (lga/1312),]26:4:Vary,15:Accept-Encoding,]16:7:X-Cache,3:HIT,]25:17:x-ec-custom-error,1:1,]]7:content,0:,4:code,3:304#}4:type,4:http,2:id,36:d209a4fc-8e12-43cb-9250-b0b052d2caf8,5:error,0:~7:version,9:1:0#2:12#]11:client_conn,208:15:ssl_established,4:true!10:clientcert,0:~13:timestamp_end,0:~19:timestamp_ssl_setup,14:1449080668.754^7:address,53:7:address,20:9:127.0.0.1,5:58199#]8:use_ipv6,5:false!}15:timestamp_start,14:1449080666.523^}11:server_conn,2479:15:ssl_established,4:true!14:source_address,57:7:address,24:12:10.67.56.236,5:58201#]8:use_ipv6,5:false!}13:timestamp_end,0:~7:address,54:7:address,21:11:example.com,3:443#]8:use_ipv6,5:false!}15:timestamp_start,14:1449080668.046^3:sni,11:example.com,4:cert,2122:-----BEGIN CERTIFICATE----- -MIIF8jCCBNqgAwIBAgIQDmTF+8I2reFLFyrrQceMsDANBgkqhkiG9w0BAQsFADBw -MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 -d3cuZGlnaWNlcnQuY29tMS8wLQYDVQQDEyZEaWdpQ2VydCBTSEEyIEhpZ2ggQXNz -dXJhbmNlIFNlcnZlciBDQTAeFw0xNTExMDMwMDAwMDBaFw0xODExMjgxMjAwMDBa -MIGlMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEUMBIGA1UEBxML -TG9zIEFuZ2VsZXMxPDA6BgNVBAoTM0ludGVybmV0IENvcnBvcmF0aW9uIGZvciBB -c3NpZ25lZCBOYW1lcyBhbmQgTnVtYmVyczETMBEGA1UECxMKVGVjaG5vbG9neTEY -MBYGA1UEAxMPd3d3LmV4YW1wbGUub3JnMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A -MIIBCgKCAQEAs0CWL2FjPiXBl61lRfvvE0KzLJmG9LWAC3bcBjgsH6NiVVo2dt6u -Xfzi5bTm7F3K7srfUBYkLO78mraM9qizrHoIeyofrV/n+pZZJauQsPjCPxMEJnRo -D8Z4KpWKX0LyDu1SputoI4nlQ/htEhtiQnuoBfNZxF7WxcxGwEsZuS1KcXIkHl5V -RJOreKFHTaXcB1qcZ/QRaBIv0yhxvK1yBTwWddT4cli6GfHcCe3xGMaSL328Fgs3 -jYrvG29PueB6VJi/tbbPu6qTfwp/H1brqdjh29U52Bhb0fJkM9DWxCP/Cattcc7a -z8EXnCO+LK8vkhw/kAiJWPKx4RBvgy73nwIDAQABo4ICUDCCAkwwHwYDVR0jBBgw -FoAUUWj/kK8CB3U8zNllZGKiErhZcjswHQYDVR0OBBYEFKZPYB4fLdHn8SOgKpUW -5Oia6m5IMIGBBgNVHREEejB4gg93d3cuZXhhbXBsZS5vcmeCC2V4YW1wbGUuY29t -ggtleGFtcGxlLmVkdYILZXhhbXBsZS5uZXSCC2V4YW1wbGUub3Jngg93d3cuZXhh -bXBsZS5jb22CD3d3dy5leGFtcGxlLmVkdYIPd3d3LmV4YW1wbGUubmV0MA4GA1Ud -DwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwdQYDVR0f -BG4wbDA0oDKgMIYuaHR0cDovL2NybDMuZGlnaWNlcnQuY29tL3NoYTItaGEtc2Vy -dmVyLWc0LmNybDA0oDKgMIYuaHR0cDovL2NybDQuZGlnaWNlcnQuY29tL3NoYTIt -aGEtc2VydmVyLWc0LmNybDBMBgNVHSAERTBDMDcGCWCGSAGG/WwBATAqMCgGCCsG -AQUFBwIBFhxodHRwczovL3d3dy5kaWdpY2VydC5jb20vQ1BTMAgGBmeBDAECAjCB -gwYIKwYBBQUHAQEEdzB1MCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2Vy -dC5jb20wTQYIKwYBBQUHMAKGQWh0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNvbS9E -aWdpQ2VydFNIQTJIaWdoQXNzdXJhbmNlU2VydmVyQ0EuY3J0MAwGA1UdEwEB/wQC -MAAwDQYJKoZIhvcNAQELBQADggEBAISomhGn2L0LJn5SJHuyVZ3qMIlRCIdvqe0Q -6ls+C8ctRwRO3UU3x8q8OH+2ahxlQmpzdC5al4XQzJLiLjiJ2Q1p+hub8MFiMmVP -PZjb2tZm2ipWVuMRM+zgpRVM6nVJ9F3vFfUSHOb4/JsEIUvPY+d8/Krc+kPQwLvy -ieqRbcuFjmqfyPmUv1U9QoI4TQikpw7TZU0zYZANP4C/gj4Ry48/znmUaRvy2kvI -l7gRQ21qJTK5suoiYoYNo3J9T+pXPGU7Lydz/HwW+w0DpArtAaukI8aNX4ohFUKS -wDSiIIWIWJiJGbEeIO0TIFwEVWTOnbNl/faPXpk5IRXicapqiII= ------END CERTIFICATE----- -,19:timestamp_ssl_setup,14:1449080668.358^5:state,0:]19:timestamp_tcp_setup,14:1449080668.177^}11:intercepted,5:false!7:request,727:9:is_replay,5:false!4:port,3:443#6:scheme,5:https,6:method,3:GET,4:path,1:/,8:form_out,8:relative,11:httpversion,8:1:1#1:1#]4:host,11:example.com,7:headers,460:22:4:Host,11:example.com,]91:10:User-Agent,73:Mozilla/5.0 (Windows NT 10.0; WOW64; rv:41.0) Gecko/20100101 Firefox/41.0,]76:6:Accept,63:text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8,]46:15:Accept-Language,23:de,en-US;q=0.7,en;q=0.3,]36:15:Accept-Encoding,13:gzip, deflate,]28:10:Connection,10:keep-alive,]54:17:If-Modified-Since,29:Fri, 09 Aug 2013 23:54:35 GMT,]42:13:If-None-Match,21:"359670651+gzip+gzip",]29:13:Cache-Control,9:max-age=0,]]7:content,0:,7:form_in,8:relative,15:timestamp_start,14:1449080668.754^13:timestamp_end,14:1449080668.757^}} \ No newline at end of file diff --git a/test/mitmproxy/data/dumpfile-013 b/test/mitmproxy/data/dumpfile-013 deleted file mode 100644 index ede06f23..00000000 --- a/test/mitmproxy/data/dumpfile-013 +++ /dev/null @@ -1,35 +0,0 @@ -4092:8:response,491:11:httpversion,8:1:1#1:1#]13:timestamp_end,14:1449080668.874^3:msg,12:Not Modified,15:timestamp_start,14:1449080668.863^7:headers,330:35:13:Cache-Control,14:max-age=604800,]40:4:Date,29:Wed, 02 Dec 2015 18:24:32 GMT,]32:4:Etag,21:"359670651+gzip+gzip",]43:7:Expires,29:Wed, 09 Dec 2015 18:24:32 GMT,]50:13:Last-Modified,29:Fri, 09 Aug 2013 23:54:35 GMT,]27:6:Server,14:ECS (lga/1312),]26:4:Vary,15:Accept-Encoding,]16:7:X-Cache,3:HIT,]25:17:x-ec-custom-error,1:1,]]7:content,0:,4:code,3:304#}4:type,4:http,2:id,36:d209a4fc-8e12-43cb-9250-b0b052d2caf8,5:error,0:~7:version,9:1:0#2:13#]11:client_conn,208:15:ssl_established,4:true!10:clientcert,0:~13:timestamp_end,0:~19:timestamp_ssl_setup,14:1449080668.754^7:address,53:7:address,20:9:127.0.0.1,5:58199#]8:use_ipv6,5:false!}15:timestamp_start,14:1449080666.523^}11:server_conn,2479:15:ssl_established,4:true!14:source_address,57:7:address,24:12:10.67.56.236,5:58201#]8:use_ipv6,5:false!}13:timestamp_end,0:~7:address,54:7:address,21:11:example.com,3:443#]8:use_ipv6,5:false!}15:timestamp_start,14:1449080668.046^3:sni,11:example.com,4:cert,2122:-----BEGIN CERTIFICATE----- -MIIF8jCCBNqgAwIBAgIQDmTF+8I2reFLFyrrQceMsDANBgkqhkiG9w0BAQsFADBw -MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 -d3cuZGlnaWNlcnQuY29tMS8wLQYDVQQDEyZEaWdpQ2VydCBTSEEyIEhpZ2ggQXNz -dXJhbmNlIFNlcnZlciBDQTAeFw0xNTExMDMwMDAwMDBaFw0xODExMjgxMjAwMDBa -MIGlMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEUMBIGA1UEBxML -TG9zIEFuZ2VsZXMxPDA6BgNVBAoTM0ludGVybmV0IENvcnBvcmF0aW9uIGZvciBB -c3NpZ25lZCBOYW1lcyBhbmQgTnVtYmVyczETMBEGA1UECxMKVGVjaG5vbG9neTEY -MBYGA1UEAxMPd3d3LmV4YW1wbGUub3JnMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A -MIIBCgKCAQEAs0CWL2FjPiXBl61lRfvvE0KzLJmG9LWAC3bcBjgsH6NiVVo2dt6u -Xfzi5bTm7F3K7srfUBYkLO78mraM9qizrHoIeyofrV/n+pZZJauQsPjCPxMEJnRo -D8Z4KpWKX0LyDu1SputoI4nlQ/htEhtiQnuoBfNZxF7WxcxGwEsZuS1KcXIkHl5V -RJOreKFHTaXcB1qcZ/QRaBIv0yhxvK1yBTwWddT4cli6GfHcCe3xGMaSL328Fgs3 -jYrvG29PueB6VJi/tbbPu6qTfwp/H1brqdjh29U52Bhb0fJkM9DWxCP/Cattcc7a -z8EXnCO+LK8vkhw/kAiJWPKx4RBvgy73nwIDAQABo4ICUDCCAkwwHwYDVR0jBBgw -FoAUUWj/kK8CB3U8zNllZGKiErhZcjswHQYDVR0OBBYEFKZPYB4fLdHn8SOgKpUW -5Oia6m5IMIGBBgNVHREEejB4gg93d3cuZXhhbXBsZS5vcmeCC2V4YW1wbGUuY29t -ggtleGFtcGxlLmVkdYILZXhhbXBsZS5uZXSCC2V4YW1wbGUub3Jngg93d3cuZXhh -bXBsZS5jb22CD3d3dy5leGFtcGxlLmVkdYIPd3d3LmV4YW1wbGUubmV0MA4GA1Ud -DwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwdQYDVR0f -BG4wbDA0oDKgMIYuaHR0cDovL2NybDMuZGlnaWNlcnQuY29tL3NoYTItaGEtc2Vy -dmVyLWc0LmNybDA0oDKgMIYuaHR0cDovL2NybDQuZGlnaWNlcnQuY29tL3NoYTIt -aGEtc2VydmVyLWc0LmNybDBMBgNVHSAERTBDMDcGCWCGSAGG/WwBATAqMCgGCCsG -AQUFBwIBFhxodHRwczovL3d3dy5kaWdpY2VydC5jb20vQ1BTMAgGBmeBDAECAjCB -gwYIKwYBBQUHAQEEdzB1MCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2Vy -dC5jb20wTQYIKwYBBQUHMAKGQWh0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNvbS9E -aWdpQ2VydFNIQTJIaWdoQXNzdXJhbmNlU2VydmVyQ0EuY3J0MAwGA1UdEwEB/wQC -MAAwDQYJKoZIhvcNAQELBQADggEBAISomhGn2L0LJn5SJHuyVZ3qMIlRCIdvqe0Q -6ls+C8ctRwRO3UU3x8q8OH+2ahxlQmpzdC5al4XQzJLiLjiJ2Q1p+hub8MFiMmVP -PZjb2tZm2ipWVuMRM+zgpRVM6nVJ9F3vFfUSHOb4/JsEIUvPY+d8/Krc+kPQwLvy -ieqRbcuFjmqfyPmUv1U9QoI4TQikpw7TZU0zYZANP4C/gj4Ry48/znmUaRvy2kvI -l7gRQ21qJTK5suoiYoYNo3J9T+pXPGU7Lydz/HwW+w0DpArtAaukI8aNX4ohFUKS -wDSiIIWIWJiJGbEeIO0TIFwEVWTOnbNl/faPXpk5IRXicapqiII= ------END CERTIFICATE----- -,19:timestamp_ssl_setup,14:1449080668.358^5:state,0:]19:timestamp_tcp_setup,14:1449080668.177^}11:intercepted,5:false!7:request,727:9:is_replay,5:false!4:port,3:443#6:scheme,5:https,6:method,3:GET,4:path,1:/,8:form_out,8:relative,11:httpversion,8:1:1#1:1#]4:host,11:example.com,7:headers,460:22:4:Host,11:example.com,]91:10:User-Agent,73:Mozilla/5.0 (Windows NT 10.0; WOW64; rv:41.0) Gecko/20100101 Firefox/41.0,]76:6:Accept,63:text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8,]46:15:Accept-Language,23:de,en-US;q=0.7,en;q=0.3,]36:15:Accept-Encoding,13:gzip, deflate,]28:10:Connection,10:keep-alive,]54:17:If-Modified-Since,29:Fri, 09 Aug 2013 23:54:35 GMT,]42:13:If-None-Match,21:"359670651+gzip+gzip",]29:13:Cache-Control,9:max-age=0,]]7:content,0:,7:form_in,8:relative,15:timestamp_start,14:1449080668.754^13:timestamp_end,14:1449080668.757^}} \ No newline at end of file diff --git a/test/mitmproxy/test_flow_format_compat.py b/test/mitmproxy/test_flow_format_compat.py index b2cef88d..cc80db81 100644 --- a/test/mitmproxy/test_flow_format_compat.py +++ b/test/mitmproxy/test_flow_format_compat.py @@ -4,7 +4,7 @@ from . import tutils def test_load(): - with open(tutils.test_data.path("data/dumpfile-013"), "rb") as f: + with open(tutils.test_data.path("data/dumpfile-011"), "rb") as f: flow_reader = FlowReader(f) flows = list(flow_reader.stream()) assert len(flows) == 1 @@ -12,7 +12,7 @@ def test_load(): def test_cannot_convert(): - with open(tutils.test_data.path("data/dumpfile-012"), "rb") as f: + with open(tutils.test_data.path("data/dumpfile-010"), "rb") as f: flow_reader = FlowReader(f) with tutils.raises(FlowReadException): list(flow_reader.stream()) -- cgit v1.2.3 From f7639e077ab10dc8e7f180f44b531b9ad35c060b Mon Sep 17 00:00:00 2001 From: Maximilian Hils Date: Fri, 8 Jul 2016 15:58:12 -0700 Subject: py3++ --- test/mitmproxy/console/test_master.py | 4 +++- test/mitmproxy/test_dump.py | 2 ++ 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'test') diff --git a/test/mitmproxy/console/test_master.py b/test/mitmproxy/console/test_master.py index 33261c28..d42863b3 100644 --- a/test/mitmproxy/console/test_master.py +++ b/test/mitmproxy/console/test_master.py @@ -112,11 +112,13 @@ def test_options(): class TestMaster(mastertest.MasterTest): def mkmaster(self, filt, **options): + if "verbosity" not in options: + options["verbosity"] = 0 o = console.master.Options(filtstr=filt, **options) return console.master.ConsoleMaster(None, o) def test_basic(self): m = self.mkmaster(None) for i in (1, 2, 3): - self.dummy_cycle(m, 1, "") + self.dummy_cycle(m, 1, b"") assert len(m.state.flows) == i diff --git a/test/mitmproxy/test_dump.py b/test/mitmproxy/test_dump.py index 234490f8..18de09d5 100644 --- a/test/mitmproxy/test_dump.py +++ b/test/mitmproxy/test_dump.py @@ -63,6 +63,8 @@ class TestDumpMaster(mastertest.MasterTest): def mkmaster(self, filt, **options): cs = StringIO() + if "verbosity" not in options: + options["verbosity"] = 0 o = dump.Options(filtstr=filt, **options) return dump.DumpMaster(None, o, outfile=cs) -- cgit v1.2.3 From 5d2b7c52f9c33e84be5c4330b09b0f2a5ad869e2 Mon Sep 17 00:00:00 2001 From: Maximilian Hils Date: Fri, 8 Jul 2016 19:57:57 -0700 Subject: move script context to mitmproxy.ctx --- test/mitmproxy/data/scripts/all.py | 14 +++++++------- test/mitmproxy/data/scripts/duplicate_flow.py | 4 ++-- test/mitmproxy/test_examples.py | 6 +++--- 3 files changed, 12 insertions(+), 12 deletions(-) (limited to 'test') diff --git a/test/mitmproxy/data/scripts/all.py b/test/mitmproxy/data/scripts/all.py index 17ffe33f..bf8e93ec 100644 --- a/test/mitmproxy/data/scripts/all.py +++ b/test/mitmproxy/data/scripts/all.py @@ -3,35 +3,35 @@ log = [] def clientconnect(cc): - mitmproxy.log("XCLIENTCONNECT") + mitmproxy.ctx.log("XCLIENTCONNECT") log.append("clientconnect") def serverconnect(cc): - mitmproxy.log("XSERVERCONNECT") + mitmproxy.ctx.log("XSERVERCONNECT") log.append("serverconnect") def request(f): - mitmproxy.log("XREQUEST") + mitmproxy.ctx.log("XREQUEST") log.append("request") def response(f): - mitmproxy.log("XRESPONSE") + mitmproxy.ctx.log("XRESPONSE") log.append("response") def responseheaders(f): - mitmproxy.log("XRESPONSEHEADERS") + mitmproxy.ctx.log("XRESPONSEHEADERS") log.append("responseheaders") def clientdisconnect(cc): - mitmproxy.log("XCLIENTDISCONNECT") + mitmproxy.ctx.log("XCLIENTDISCONNECT") log.append("clientdisconnect") def error(cc): - mitmproxy.log("XERROR") + mitmproxy.ctx.log("XERROR") log.append("error") diff --git a/test/mitmproxy/data/scripts/duplicate_flow.py b/test/mitmproxy/data/scripts/duplicate_flow.py index a50d2cb5..565b1845 100644 --- a/test/mitmproxy/data/scripts/duplicate_flow.py +++ b/test/mitmproxy/data/scripts/duplicate_flow.py @@ -2,5 +2,5 @@ import mitmproxy def request(f): - f = mitmproxy.master.duplicate_flow(f) - mitmproxy.master.replay_request(f, block=True, run_scripthooks=False) + f = mitmproxy.ctx.master.duplicate_flow(f) + mitmproxy.ctx.master.replay_request(f, block=True, run_scripthooks=False) diff --git a/test/mitmproxy/test_examples.py b/test/mitmproxy/test_examples.py index 3b5ff2a2..bdadcd11 100644 --- a/test/mitmproxy/test_examples.py +++ b/test/mitmproxy/test_examples.py @@ -21,8 +21,8 @@ def example(command): yield s -@mock.patch("mitmproxy.master") -@mock.patch("mitmproxy.log") +@mock.patch("mitmproxy.ctx.master") +@mock.patch("mitmproxy.ctx.log") def test_load_scripts(log, master): scripts = glob.glob("%s/*.py" % example_dir) @@ -121,7 +121,7 @@ def test_redirect_requests(): assert flow.request.host == "mitmproxy.org" -@mock.patch("mitmproxy.log") +@mock.patch("mitmproxy.ctx.log") def test_har_extractor(log): if sys.version_info >= (3, 0): with tutils.raises("does not work on Python 3"): -- cgit v1.2.3 From 147f61fa62f3c2b29f46c6a033bea19c4c49a171 Mon Sep 17 00:00:00 2001 From: Shadab Zafar Date: Thu, 7 Jul 2016 19:37:33 +0530 Subject: py3++ --- test/mitmproxy/test_dump.py | 41 +++++++++++++++++++++++------------------ 1 file changed, 23 insertions(+), 18 deletions(-) (limited to 'test') diff --git a/test/mitmproxy/test_dump.py b/test/mitmproxy/test_dump.py index 18de09d5..263c8b3d 100644 --- a/test/mitmproxy/test_dump.py +++ b/test/mitmproxy/test_dump.py @@ -40,7 +40,7 @@ def test_strfuncs(): flow.response.status_code = 300 m.echo_flow(flow) - flow = tutils.tflow(resp=netlib.tutils.tresp(content="{")) + flow = tutils.tflow(resp=netlib.tutils.tresp(content=b"{")) flow.response.headers["content-type"] = "application/json" flow.response.status_code = 400 m.echo_flow(flow) @@ -70,15 +70,20 @@ class TestDumpMaster(mastertest.MasterTest): def test_basic(self): for i in (1, 2, 3): - assert "GET" in self.dummy_cycle(self.mkmaster("~s", flow_detail=i), 1, "") assert "GET" in self.dummy_cycle( self.mkmaster("~s", flow_detail=i), 1, - "\x00\x00\x00" + b"" ) assert "GET" in self.dummy_cycle( self.mkmaster("~s", flow_detail=i), - 1, "ascii" + 1, + b"\x00\x00\x00" + ) + assert "GET" in self.dummy_cycle( + self.mkmaster("~s", flow_detail=i), + 1, + b"ascii" ) def test_error(self): @@ -115,12 +120,12 @@ class TestDumpMaster(mastertest.MasterTest): o = dump.Options(server_replay=[p], kill=True) m = dump.DumpMaster(None, o, outfile=cs) - self.cycle(m, "content") - self.cycle(m, "content") + self.cycle(m, b"content") + self.cycle(m, b"content") o = dump.Options(server_replay=[p], kill=False) m = dump.DumpMaster(None, o, outfile=cs) - self.cycle(m, "nonexistent") + self.cycle(m, b"nonexistent") o = dump.Options(client_replay=[p], kill=False) m = dump.DumpMaster(None, o, outfile=cs) @@ -131,7 +136,7 @@ class TestDumpMaster(mastertest.MasterTest): self.flowfile(p) assert "GET" in self.dummy_cycle( self.mkmaster(None, flow_detail=1, rfile=p), - 0, "", + 0, b"", ) tutils.raises( @@ -149,7 +154,7 @@ class TestDumpMaster(mastertest.MasterTest): def test_filter(self): assert "GET" not in self.dummy_cycle( - self.mkmaster("~u foo", verbosity=1), 1, "" + self.mkmaster("~u foo", verbosity=1), 1, b"" ) def test_app(self): @@ -162,21 +167,21 @@ class TestDumpMaster(mastertest.MasterTest): cs = StringIO() o = dump.Options(replacements=[(".*", "content", "foo")]) m = dump.DumpMaster(None, o, outfile=cs) - f = self.cycle(m, "content") - assert f.request.content == "foo" + f = self.cycle(m, b"content") + assert f.request.content == b"foo" def test_setheader(self): cs = StringIO() o = dump.Options(setheaders=[(".*", "one", "two")]) m = dump.DumpMaster(None, o, outfile=cs) - f = self.cycle(m, "content") + f = self.cycle(m, b"content") assert f.request.headers["one"] == "two" def test_write(self): with tutils.tmpdir() as d: p = os.path.join(d, "a") self.dummy_cycle( - self.mkmaster(None, outfile=(p, "wb"), verbosity=0), 1, "" + self.mkmaster(None, outfile=(p, "wb"), verbosity=0), 1, b"" ) assert len(list(flow.FlowReader(open(p, "rb")).stream())) == 1 @@ -185,11 +190,11 @@ class TestDumpMaster(mastertest.MasterTest): p = os.path.join(d, "a.append") self.dummy_cycle( self.mkmaster(None, outfile=(p, "wb"), verbosity=0), - 1, "" + 1, b"" ) self.dummy_cycle( self.mkmaster(None, outfile=(p, "ab"), verbosity=0), - 1, "" + 1, b"" ) assert len(list(flow.FlowReader(open(p, "rb")).stream())) == 2 @@ -205,7 +210,7 @@ class TestDumpMaster(mastertest.MasterTest): None, scripts=[tutils.test_data.path("data/scripts/all.py")], verbosity=1 ), - 1, "", + 1, b"", ) assert "XCLIENTCONNECT" in ret assert "XSERVERCONNECT" in ret @@ -226,11 +231,11 @@ class TestDumpMaster(mastertest.MasterTest): def test_stickycookie(self): self.dummy_cycle( self.mkmaster(None, stickycookie = ".*"), - 1, "" + 1, b"" ) def test_stickyauth(self): self.dummy_cycle( self.mkmaster(None, stickyauth = ".*"), - 1, "" + 1, b"" ) -- cgit v1.2.3 From c7cbbf5f0de9bceccc37b73586ed3baf9421f63a Mon Sep 17 00:00:00 2001 From: Shadab Zafar Date: Sat, 9 Jul 2016 12:32:41 +0530 Subject: Set verbosity & flow_detail to 0 --- test/mitmproxy/test_dump.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'test') diff --git a/test/mitmproxy/test_dump.py b/test/mitmproxy/test_dump.py index 263c8b3d..aa73b5a4 100644 --- a/test/mitmproxy/test_dump.py +++ b/test/mitmproxy/test_dump.py @@ -65,6 +65,8 @@ class TestDumpMaster(mastertest.MasterTest): cs = StringIO() if "verbosity" not in options: options["verbosity"] = 0 + if "flow_detail" not in options: + options["flow_detail"] = 0 o = dump.Options(filtstr=filt, **options) return dump.DumpMaster(None, o, outfile=cs) @@ -118,16 +120,22 @@ class TestDumpMaster(mastertest.MasterTest): self.flowfile(p) o = dump.Options(server_replay=[p], kill=True) + o.verbosity = 0 + o.flow_detail = 0 m = dump.DumpMaster(None, o, outfile=cs) self.cycle(m, b"content") self.cycle(m, b"content") o = dump.Options(server_replay=[p], kill=False) + o.verbosity = 0 + o.flow_detail = 0 m = dump.DumpMaster(None, o, outfile=cs) self.cycle(m, b"nonexistent") o = dump.Options(client_replay=[p], kill=False) + o.verbosity = 0 + o.flow_detail = 0 m = dump.DumpMaster(None, o, outfile=cs) def test_read(self): @@ -166,6 +174,8 @@ class TestDumpMaster(mastertest.MasterTest): def test_replacements(self): cs = StringIO() o = dump.Options(replacements=[(".*", "content", "foo")]) + o.verbosity = 0 + o.flow_detail = 0 m = dump.DumpMaster(None, o, outfile=cs) f = self.cycle(m, b"content") assert f.request.content == b"foo" @@ -173,6 +183,8 @@ class TestDumpMaster(mastertest.MasterTest): def test_setheader(self): cs = StringIO() o = dump.Options(setheaders=[(".*", "one", "two")]) + o.verbosity = 0 + o.flow_detail = 0 m = dump.DumpMaster(None, o, outfile=cs) f = self.cycle(m, b"content") assert f.request.headers["one"] == "two" -- cgit v1.2.3 From 83a1cc5a9a62dbe22bd9e87f496928ae1664da2b Mon Sep 17 00:00:00 2001 From: Shadab Zafar Date: Sat, 9 Jul 2016 12:57:55 +0530 Subject: Make escape_control_characters handle strings on Py2 --- test/netlib/test_strutils.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'test') diff --git a/test/netlib/test_strutils.py b/test/netlib/test_strutils.py index 68bfdb94..7c3eacc6 100644 --- a/test/netlib/test_strutils.py +++ b/test/netlib/test_strutils.py @@ -38,8 +38,9 @@ def test_escape_control_characters(): u'=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~.' ) - with tutils.raises(ValueError): - strutils.escape_control_characters(b"foo") + if not six.PY2: + with tutils.raises(ValueError): + strutils.escape_control_characters(b"foo") def test_bytes_to_escaped_str(): -- cgit v1.2.3 From 6a746deff57d7283ee8440148b87ea16a672739a Mon Sep 17 00:00:00 2001 From: Shadab Zafar Date: Thu, 7 Jul 2016 23:26:52 +0530 Subject: Add tests for deletion of stickycookies --- test/mitmproxy/test_flow.py | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) (limited to 'test') diff --git a/test/mitmproxy/test_flow.py b/test/mitmproxy/test_flow.py index bf7622f6..c0d9155f 100644 --- a/test/mitmproxy/test_flow.py +++ b/test/mitmproxy/test_flow.py @@ -55,14 +55,16 @@ class TestStickyCookieState: assert s.domain_match("google.com", ".google.com") def test_response(self): - c = "SSID=mooo; domain=.google.com, FOO=bar; Domain=.google.com; Path=/; " \ + c = ( + "SSID=mooo; domain=.google.com, FOO=bar; Domain=.google.com; Path=/; " "Expires=Wed, 13-Jan-2021 22:23:01 GMT; Secure; " + ) s, f = self._response(c, "host") assert not s.jar.keys() s, f = self._response(c, "www.google.com") - assert s.jar.keys() + assert list(s.jar.keys())[0] == ('.google.com', 80, '/') s, f = self._response("SSID=mooo", "www.google.com") assert list(s.jar.keys())[0] == ('www.google.com', 80, '/') @@ -101,6 +103,28 @@ class TestStickyCookieState: assert len(s.jar[googlekey]) == 1 assert list(s.jar[googlekey]["somecookie"].values())[0] == "newvalue" + def test_response_delete(self): + c = "duffer=zafar; Path=/", "www.google.com" + + # Test that a cookie is be deleted + # by setting the expire time in the past + s, f = self._response(*c) + f.response.headers["Set-Cookie"] = "duffer=; Expires=Thu, 01-Jan-1970 00:00:00 GMT" + s.handle_response(f) + assert not s.jar.keys() + + # or by setting Max-Age to 0 + s, f = self._response(*c) + f.response.headers["Set-Cookie"] = "duffer=; Max-Age=0" + s.handle_response(f) + assert not s.jar.keys() + + # or both + s, f = self._response(*c) + f.response.headers["Set-Cookie"] = "duffer=; Expires=Thu, 01-Jan-1970 00:00:00 GMT; Max-Age=0" + s.handle_response(f) + assert not s.jar.keys() + def test_request(self): s, f = self._response("SSID=mooo", b"www.google.com") assert "cookie" not in f.request.headers -- cgit v1.2.3 From 39f51084003b93a2e9868f7a56acfc29c12ed79e Mon Sep 17 00:00:00 2001 From: Shadab Zafar Date: Sun, 10 Jul 2016 01:06:50 +0530 Subject: Test cookies.is_expired separately --- test/netlib/http/test_cookies.py | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'test') diff --git a/test/netlib/http/test_cookies.py b/test/netlib/http/test_cookies.py index 83b85656..17e21b94 100644 --- a/test/netlib/http/test_cookies.py +++ b/test/netlib/http/test_cookies.py @@ -245,3 +245,24 @@ def test_refresh_cookie(): assert cookies.refresh_set_cookie_header(c, 0) c = "foo/bar=bla" assert cookies.refresh_set_cookie_header(c, 0) + + +def test_is_expired(): + CA = cookies.CookieAttrs + + # A cookie can be expired + # by setting the expire time in the past + assert cookies.is_expired(CA([("Expires", "Thu, 01-Jan-1970 00:00:00 GMT")])) + + # or by setting Max-Age to 0 + assert cookies.is_expired(CA([("Max-Age", "0")])) + + # or both + assert cookies.is_expired(CA([("Expires", "Thu, 01-Jan-1970 00:00:00 GMT"), ("Max-Age", "0")])) + + assert not cookies.is_expired(CA([("Expires", "Thu, 24-Aug-2063 00:00:00 GMT")])) + assert not cookies.is_expired(CA([("Max-Age", "1")])) + assert not cookies.is_expired(CA([("Expires", "Thu, 15-Jul-2068 00:00:00 GMT"), ("Max-Age", "1")])) + + assert not cookies.is_expired(CA([("Max-Age", "nan")])) + assert not cookies.is_expired(CA([("Expires", "false")])) -- cgit v1.2.3 From 7eade1ef7c24b98567c1657973290aa5377b2719 Mon Sep 17 00:00:00 2001 From: Shadab Zafar Date: Sun, 10 Jul 2016 01:08:02 +0530 Subject: Remove redundant tests --- test/mitmproxy/test_flow.py | 12 ------------ 1 file changed, 12 deletions(-) (limited to 'test') diff --git a/test/mitmproxy/test_flow.py b/test/mitmproxy/test_flow.py index c0d9155f..74b3f599 100644 --- a/test/mitmproxy/test_flow.py +++ b/test/mitmproxy/test_flow.py @@ -113,18 +113,6 @@ class TestStickyCookieState: s.handle_response(f) assert not s.jar.keys() - # or by setting Max-Age to 0 - s, f = self._response(*c) - f.response.headers["Set-Cookie"] = "duffer=; Max-Age=0" - s.handle_response(f) - assert not s.jar.keys() - - # or both - s, f = self._response(*c) - f.response.headers["Set-Cookie"] = "duffer=; Expires=Thu, 01-Jan-1970 00:00:00 GMT; Max-Age=0" - s.handle_response(f) - assert not s.jar.keys() - def test_request(self): s, f = self._response("SSID=mooo", b"www.google.com") assert "cookie" not in f.request.headers -- cgit v1.2.3 From b611997619b126efdc371e725cbb742a6b02c410 Mon Sep 17 00:00:00 2001 From: Thomas Kriechbaumer Date: Sun, 10 Jul 2016 18:53:00 +0200 Subject: http2: simplify test class --- test/mitmproxy/test_protocol_http2.py | 87 +++++++++-------------------------- 1 file changed, 22 insertions(+), 65 deletions(-) (limited to 'test') diff --git a/test/mitmproxy/test_protocol_http2.py b/test/mitmproxy/test_protocol_http2.py index 58ffb787..a4f6b574 100644 --- a/test/mitmproxy/test_protocol_http2.py +++ b/test/mitmproxy/test_protocol_http2.py @@ -151,8 +151,7 @@ class _Http2TestBase(object): wfile.flush() -@requires_alpn -class TestSimple(_Http2TestBase, _Http2ServerBase): +class _Http2Test(_Http2TestBase, _Http2ServerBase): @classmethod def setup_class(self): @@ -164,6 +163,10 @@ class TestSimple(_Http2TestBase, _Http2ServerBase): _Http2TestBase.teardown_class() _Http2ServerBase.teardown_class() + +@requires_alpn +class TestSimple(_Http2Test): + @classmethod def handle_server_event(self, event, h2_conn, rfile, wfile): if isinstance(event, h2.events.ConnectionTerminated): @@ -196,14 +199,18 @@ class TestSimple(_Http2TestBase, _Http2ServerBase): def test_simple(self): 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), - (':method', 'GET'), - (':scheme', 'https'), - (':path', '/'), - ('ClIeNt-FoO', 'client-bar-1'), - ('ClIeNt-FoO', 'client-bar-2'), - ], body=b'my request body echoed back to me') + self._send_request( + client.wfile, + h2_conn, + headers=[ + (':authority', "127.0.0.1:%s" % self.server.server.address.port), + (':method', 'GET'), + (':scheme', 'https'), + (':path', '/'), + ('ClIeNt-FoO', 'client-bar-1'), + ('ClIeNt-FoO', 'client-bar-2'), + ], + body=b'my request body echoed back to me') done = False while not done: @@ -233,19 +240,9 @@ class TestSimple(_Http2TestBase, _Http2ServerBase): @requires_alpn -class TestWithBodies(_Http2TestBase, _Http2ServerBase): +class TestWithBodies(_Http2Test): tmp_data_buffer_foobar = b'' - @classmethod - def setup_class(self): - _Http2TestBase.setup_class() - _Http2ServerBase.setup_class() - - @classmethod - def teardown_class(self): - _Http2TestBase.teardown_class() - _Http2ServerBase.teardown_class() - @classmethod def handle_server_event(self, event, h2_conn, rfile, wfile): if isinstance(event, h2.events.ConnectionTerminated): @@ -302,17 +299,7 @@ class TestWithBodies(_Http2TestBase, _Http2ServerBase): @requires_alpn -class TestPushPromise(_Http2TestBase, _Http2ServerBase): - - @classmethod - def setup_class(self): - _Http2TestBase.setup_class() - _Http2ServerBase.setup_class() - - @classmethod - def teardown_class(self): - _Http2TestBase.teardown_class() - _Http2ServerBase.teardown_class() +class TestPushPromise(_Http2Test): @classmethod def handle_server_event(self, event, h2_conn, rfile, wfile): @@ -465,17 +452,7 @@ class TestPushPromise(_Http2TestBase, _Http2ServerBase): @requires_alpn -class TestConnectionLost(_Http2TestBase, _Http2ServerBase): - - @classmethod - def setup_class(self): - _Http2TestBase.setup_class() - _Http2ServerBase.setup_class() - - @classmethod - def teardown_class(self): - _Http2TestBase.teardown_class() - _Http2ServerBase.teardown_class() +class TestConnectionLost(_Http2Test): @classmethod def handle_server_event(self, event, h2_conn, rfile, wfile): @@ -517,17 +494,7 @@ class TestConnectionLost(_Http2TestBase, _Http2ServerBase): @requires_alpn -class TestMaxConcurrentStreams(_Http2TestBase, _Http2ServerBase): - - @classmethod - def setup_class(self): - _Http2TestBase.setup_class() - _Http2ServerBase.setup_class(h2_server_settings={h2.settings.MAX_CONCURRENT_STREAMS: 2}) - - @classmethod - def teardown_class(self): - _Http2TestBase.teardown_class() - _Http2ServerBase.teardown_class() +class TestMaxConcurrentStreams(_Http2Test): @classmethod def handle_server_event(self, event, h2_conn, rfile, wfile): @@ -583,17 +550,7 @@ class TestMaxConcurrentStreams(_Http2TestBase, _Http2ServerBase): @requires_alpn -class TestConnectionTerminated(_Http2TestBase, _Http2ServerBase): - - @classmethod - def setup_class(self): - _Http2TestBase.setup_class() - _Http2ServerBase.setup_class() - - @classmethod - def teardown_class(self): - _Http2TestBase.teardown_class() - _Http2ServerBase.teardown_class() +class TestConnectionTerminated(_Http2Test): @classmethod def handle_server_event(self, event, h2_conn, rfile, wfile): -- cgit v1.2.3 From 7c092552989a6f328bb5defad744cdd37a14e8ec Mon Sep 17 00:00:00 2001 From: Thomas Kriechbaumer Date: Sun, 10 Jul 2016 20:07:43 +0200 Subject: http2: more coverage --- test/mitmproxy/test_protocol_http2.py | 220 +++++++++++++++++++++++++++++++--- 1 file changed, 201 insertions(+), 19 deletions(-) (limited to 'test') diff --git a/test/mitmproxy/test_protocol_http2.py b/test/mitmproxy/test_protocol_http2.py index a4f6b574..cb7cebca 100644 --- a/test/mitmproxy/test_protocol_http2.py +++ b/test/mitmproxy/test_protocol_http2.py @@ -60,7 +60,10 @@ class _Http2ServerBase(netlib_tservers.ServerTestBase): except HttpException: print(traceback.format_exc()) assert False + except netlib.exceptions.TcpDisconnect: + break except: + print(traceback.format_exc()) break self.wfile.write(h2_conn.data_to_send()) self.wfile.flush() @@ -70,8 +73,11 @@ class _Http2ServerBase(netlib_tservers.ServerTestBase): if not self.server.handle_server_event(event, h2_conn, self.rfile, self.wfile): done = True break + except netlib.exceptions.TcpDisconnect: + done = True except: done = True + print(traceback.format_exc()) break def handle_server_event(self, h2_conn, rfile, wfile): @@ -138,11 +144,22 @@ class _Http2TestBase(object): return client, h2_conn - def _send_request(self, wfile, h2_conn, stream_id=1, headers=[], body=b''): + def _send_request(self, + wfile, + h2_conn, + stream_id=1, + headers=[], + body=b'', + priority_exclusive=None, + priority_depends_on=None, + priority_weight=None): h2_conn.send_headers( stream_id=stream_id, headers=headers, end_stream=(len(body) == 0), + priority_exclusive=priority_exclusive, + priority_depends_on=priority_depends_on, + priority_weight=priority_weight, ) if body: h2_conn.send_data(stream_id, body) @@ -166,6 +183,7 @@ class _Http2Test(_Http2TestBase, _Http2ServerBase): @requires_alpn class TestSimple(_Http2Test): + request_body_buffer = b'' @classmethod def handle_server_event(self, event, h2_conn, rfile, wfile): @@ -190,13 +208,16 @@ class TestSimple(_Http2Test): ('föo', 'bär'), ('X-Stream-ID', str(event.stream_id)), ]) - h2_conn.send_data(event.stream_id, b'foobar') + h2_conn.send_data(event.stream_id, b'response body') h2_conn.end_stream(event.stream_id) wfile.write(h2_conn.data_to_send()) wfile.flush() + elif isinstance(event, h2.events.DataReceived): + self.request_body_buffer += event.data return True def test_simple(self): + response_body_buffer = b'' client, h2_conn = self._setup_connection() self._send_request( @@ -210,7 +231,7 @@ class TestSimple(_Http2Test): ('ClIeNt-FoO', 'client-bar-1'), ('ClIeNt-FoO', 'client-bar-2'), ], - body=b'my request body echoed back to me') + body=b'request body') done = False while not done: @@ -225,7 +246,9 @@ class TestSimple(_Http2Test): client.wfile.flush() for event in events: - if isinstance(event, h2.events.StreamEnded): + if isinstance(event, h2.events.DataReceived): + response_body_buffer += event.data + elif isinstance(event, h2.events.StreamEnded): done = True h2_conn.close_connection() @@ -236,31 +259,41 @@ class TestSimple(_Http2Test): assert self.master.state.flows[0].response.status_code == 200 assert self.master.state.flows[0].response.headers['server-foo'] == 'server-bar' assert self.master.state.flows[0].response.headers['föo'] == 'bär' - assert self.master.state.flows[0].response.body == b'foobar' + assert self.master.state.flows[0].response.body == b'response body' + assert self.request_body_buffer == b'request body' + assert response_body_buffer == b'response body' @requires_alpn -class TestWithBodies(_Http2Test): - tmp_data_buffer_foobar = b'' +class TestRequestWithPriority(_Http2Test): @classmethod def handle_server_event(self, event, h2_conn, rfile, wfile): if isinstance(event, h2.events.ConnectionTerminated): return False - if isinstance(event, h2.events.DataReceived): - self.tmp_data_buffer_foobar += event.data - elif isinstance(event, h2.events.StreamEnded): - h2_conn.send_headers(1, [ - (':status', '200'), - ]) - h2_conn.send_data(1, self.tmp_data_buffer_foobar) - h2_conn.end_stream(1) + elif isinstance(event, h2.events.RequestReceived): + import warnings + with warnings.catch_warnings(): + # Ignore UnicodeWarning: + # h2/utilities.py:64: UnicodeWarning: Unicode equal comparison + # failed to convert both arguments to Unicode - interpreting + # them as being unequal. + # elif header[0] in (b'cookie', u'cookie') and len(header[1]) < 20: + + warnings.simplefilter("ignore") + + headers = [(':status', '200')] + if event.priority_updated: + headers.append(('priority_exclusive', event.priority_updated.exclusive)) + headers.append(('priority_depends_on', event.priority_updated.depends_on)) + headers.append(('priority_weight', event.priority_updated.weight)) + h2_conn.send_headers(event.stream_id, headers) + h2_conn.end_stream(event.stream_id) wfile.write(h2_conn.data_to_send()) wfile.flush() - return True - def test_with_bodies(self): + def test_request_with_priority(self): client, h2_conn = self._setup_connection() self._send_request( @@ -272,7 +305,9 @@ class TestWithBodies(_Http2Test): (':scheme', 'https'), (':path', '/'), ], - body=b'foobar with request body', + priority_exclusive = True, + priority_depends_on = 42424242, + priority_weight = 42, ) done = False @@ -295,7 +330,149 @@ class TestWithBodies(_Http2Test): client.wfile.write(h2_conn.data_to_send()) client.wfile.flush() - assert self.master.state.flows[0].response.body == b'foobar with request body' + assert len(self.master.state.flows) == 1 + assert self.master.state.flows[0].response.headers['priority_exclusive'] == 'True' + assert self.master.state.flows[0].response.headers['priority_depends_on'] == '42424242' + assert self.master.state.flows[0].response.headers['priority_weight'] == '42' + + def test_request_without_priority(self): + 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), + (':method', 'GET'), + (':scheme', 'https'), + (':path', '/'), + ], + ) + + done = False + while not done: + try: + raw = b''.join(framereader.http2_read_raw_frame(client.rfile)) + events = h2_conn.receive_data(raw) + except HttpException: + print(traceback.format_exc()) + assert False + + client.wfile.write(h2_conn.data_to_send()) + client.wfile.flush() + + for event in events: + if isinstance(event, h2.events.StreamEnded): + done = True + + h2_conn.close_connection() + client.wfile.write(h2_conn.data_to_send()) + client.wfile.flush() + + assert len(self.master.state.flows) == 1 + assert 'priority_exclusive' not in self.master.state.flows[0].response.headers + assert 'priority_depends_on' not in self.master.state.flows[0].response.headers + assert 'priority_weight' not in self.master.state.flows[0].response.headers + + +@requires_alpn +class TestStreamResetFromServer(_Http2Test): + + @classmethod + def handle_server_event(self, event, h2_conn, rfile, wfile): + if isinstance(event, h2.events.ConnectionTerminated): + return False + elif isinstance(event, h2.events.RequestReceived): + h2_conn.reset_stream(event.stream_id, 0x8) + wfile.write(h2_conn.data_to_send()) + wfile.flush() + return True + + def test_request_with_priority(self): + 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), + (':method', 'GET'), + (':scheme', 'https'), + (':path', '/'), + ], + ) + + done = False + while not done: + try: + raw = b''.join(framereader.http2_read_raw_frame(client.rfile)) + events = h2_conn.receive_data(raw) + except HttpException: + print(traceback.format_exc()) + assert False + + client.wfile.write(h2_conn.data_to_send()) + client.wfile.flush() + + for event in events: + if isinstance(event, h2.events.StreamReset): + done = True + + h2_conn.close_connection() + client.wfile.write(h2_conn.data_to_send()) + client.wfile.flush() + + assert len(self.master.state.flows) == 1 + assert self.master.state.flows[0].response is None + + +@requires_alpn +class TestBodySizeLimit(_Http2Test): + + @classmethod + def handle_server_event(self, event, h2_conn, rfile, wfile): + if isinstance(event, h2.events.ConnectionTerminated): + return False + return True + + def test_body_size_limit(self): + self.config.body_size_limit = 20 + + 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), + (':method', 'GET'), + (':scheme', 'https'), + (':path', '/'), + ], + body=b'very long body over 20 characters long', + ) + + done = False + while not done: + try: + raw = b''.join(framereader.http2_read_raw_frame(client.rfile)) + events = h2_conn.receive_data(raw) + except HttpException: + print(traceback.format_exc()) + assert False + + client.wfile.write(h2_conn.data_to_send()) + client.wfile.flush() + + for event in events: + if isinstance(event, h2.events.StreamReset): + done = True + + h2_conn.close_connection() + client.wfile.write(h2_conn.data_to_send()) + client.wfile.flush() + + assert len(self.master.state.flows) == 0 @requires_alpn @@ -496,6 +673,11 @@ class TestConnectionLost(_Http2Test): @requires_alpn class TestMaxConcurrentStreams(_Http2Test): + @classmethod + def setup_class(self): + _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): if isinstance(event, h2.events.ConnectionTerminated): -- cgit v1.2.3 From 3579c6dd43529595ce1a37d96f19a446419c6ee5 Mon Sep 17 00:00:00 2001 From: Thomas Kriechbaumer Date: Tue, 12 Jul 2016 19:55:28 +0200 Subject: http2: fix race-condition in tests --- test/mitmproxy/test_protocol_http2.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'test') diff --git a/test/mitmproxy/test_protocol_http2.py b/test/mitmproxy/test_protocol_http2.py index cb7cebca..a100ac2d 100644 --- a/test/mitmproxy/test_protocol_http2.py +++ b/test/mitmproxy/test_protocol_http2.py @@ -192,7 +192,7 @@ class TestSimple(_Http2Test): elif isinstance(event, h2.events.RequestReceived): assert (b'client-foo', b'client-bar-1') in event.headers assert (b'client-foo', b'client-bar-2') in event.headers - + elif isinstance(event, h2.events.StreamEnded): import warnings with warnings.catch_warnings(): # Ignore UnicodeWarning: -- cgit v1.2.3 From a20f8e9620c0cfcb40500113cbeb813a05a195bb Mon Sep 17 00:00:00 2001 From: Aldo Cortesi Date: Wed, 13 Jul 2016 18:45:50 +1200 Subject: More powerful Options scheme This prepares us for the addon configuration mechanism and gives us a more flexible way to handle options changes. This changeset should spell the end of the current anti-pattern in our codebase where we duplicate data out of options onto the master when mutability is needed. From now on, Options can be the one source of thruth. - Change notifications - Rollback on error --- test/mitmproxy/test_options.py | 67 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 test/mitmproxy/test_options.py (limited to 'test') diff --git a/test/mitmproxy/test_options.py b/test/mitmproxy/test_options.py new file mode 100644 index 00000000..5fdb7abe --- /dev/null +++ b/test/mitmproxy/test_options.py @@ -0,0 +1,67 @@ +from __future__ import absolute_import, print_function, division +import copy + +from mitmproxy import options +from mitmproxy import exceptions +from netlib.tutils import raises + + +class TO(options.Options): + attributes = [ + "one", + "two" + ] + + +def test_options(): + o = TO(two="three") + assert o.one is None + assert o.two == "three" + o.one = "one" + assert o.one == "one" + raises("no such option", setattr, o, "nonexistent", "value") + raises("no such option", o.update, nonexistent = "value") + + rec = [] + + def sub(opts): + rec.append(copy.copy(opts)) + + o.changed.connect(sub) + + o.one = "ninety" + assert len(rec) == 1 + assert rec[-1].one == "ninety" + + o.update(one="oink") + assert len(rec) == 2 + assert rec[-1].one == "oink" + + +def test_rollback(): + o = TO(one="two") + + rec = [] + + def sub(opts): + rec.append(copy.copy(opts)) + + recerr = [] + + def errsub(opts, **kwargs): + recerr.append(kwargs) + + def err(opts): + if opts.one == "ten": + raise exceptions.OptionsError + + o.changed.connect(sub) + o.changed.connect(err) + o.errored.connect(errsub) + + o.one = "ten" + assert isinstance(recerr[0]["exc"], exceptions.OptionsError) + assert o.one == "two" + assert len(rec) == 2 + assert rec[0].one == "ten" + assert rec[1].one == "two" -- cgit v1.2.3 From 7f8fd3cdffedb537f95773110d8ef2be60666133 Mon Sep 17 00:00:00 2001 From: Aldo Cortesi Date: Wed, 13 Jul 2016 23:26:04 +1200 Subject: Basic outline of addons Add addons.py, integrate with our event mechanism, and change the Master API so options is the first init argument. --- test/mitmproxy/test_addons.py | 20 ++++++++++++++++++++ test/mitmproxy/test_controller.py | 4 ++-- test/mitmproxy/test_flow.py | 38 +++++++++++++++++++------------------- test/mitmproxy/test_script.py | 2 +- test/mitmproxy/tservers.py | 2 +- 5 files changed, 43 insertions(+), 23 deletions(-) create mode 100644 test/mitmproxy/test_addons.py (limited to 'test') diff --git a/test/mitmproxy/test_addons.py b/test/mitmproxy/test_addons.py new file mode 100644 index 00000000..1861d4ac --- /dev/null +++ b/test/mitmproxy/test_addons.py @@ -0,0 +1,20 @@ +from __future__ import absolute_import, print_function, division +from mitmproxy import addons +from mitmproxy import controller +from mitmproxy import options + + +class TAddon: + def __init__(self, name): + self.name = name + + def __repr__(self): + return "Addon(%s)" % self.name + + +def test_simple(): + m = controller.Master(options.Options()) + a = addons.Addons(m) + a.add(TAddon("one")) + assert a.has_addon("one") + assert not a.has_addon("two") diff --git a/test/mitmproxy/test_controller.py b/test/mitmproxy/test_controller.py index 5a68e15b..6d4b8fe6 100644 --- a/test/mitmproxy/test_controller.py +++ b/test/mitmproxy/test_controller.py @@ -25,7 +25,7 @@ class TestMaster(object): # Speed up test super(DummyMaster, self).tick(0) - m = DummyMaster() + m = DummyMaster(None) assert not m.should_exit.is_set() msg = TMsg() msg.reply = controller.DummyReply() @@ -34,7 +34,7 @@ class TestMaster(object): assert m.should_exit.is_set() def test_server_simple(self): - m = controller.Master() + m = controller.Master(None) s = DummyServer(None) m.add_server(s) m.start() diff --git a/test/mitmproxy/test_flow.py b/test/mitmproxy/test_flow.py index 74b3f599..eda01ad9 100644 --- a/test/mitmproxy/test_flow.py +++ b/test/mitmproxy/test_flow.py @@ -139,7 +139,7 @@ class TestClientPlaybackState: def test_tick(self): first = tutils.tflow() s = flow.State() - fm = flow.FlowMaster(None, s) + fm = flow.FlowMaster(None, None, s) fm.start_client_playback([first, tutils.tflow()], True) c = fm.client_playback c.testing = True @@ -470,7 +470,7 @@ class TestFlow(object): def test_kill(self): s = flow.State() - fm = flow.FlowMaster(None, s) + fm = flow.FlowMaster(None, None, s) f = tutils.tflow() f.intercept(mock.Mock()) f.kill(fm) @@ -479,7 +479,7 @@ class TestFlow(object): def test_killall(self): s = flow.State() - fm = flow.FlowMaster(None, s) + fm = flow.FlowMaster(None, None, s) f = tutils.tflow() f.intercept(fm) @@ -714,7 +714,7 @@ class TestSerialize: def test_load_flows(self): r = self._treader() s = flow.State() - fm = flow.FlowMaster(None, s) + fm = flow.FlowMaster(None, None, s) fm.load_flows(r) assert len(s.flows) == 6 @@ -725,7 +725,7 @@ class TestSerialize: mode="reverse", upstream_server=("https", ("use-this-domain", 80)) ) - fm = flow.FlowMaster(DummyServer(conf), s) + fm = flow.FlowMaster(None, DummyServer(conf), s) fm.load_flows(r) assert s.flows[0].request.host == "use-this-domain" @@ -772,7 +772,7 @@ class TestFlowMaster: def test_load_script(self): s = flow.State() - fm = flow.FlowMaster(None, s) + fm = flow.FlowMaster(None, None, s) fm.load_script(tutils.test_data.path("data/scripts/a.py")) fm.load_script(tutils.test_data.path("data/scripts/a.py")) @@ -788,14 +788,14 @@ class TestFlowMaster: def test_getset_ignore(self): p = mock.Mock() p.config.check_ignore = HostMatcher() - fm = flow.FlowMaster(p, flow.State()) + fm = flow.FlowMaster(None, p, flow.State()) assert not fm.get_ignore_filter() fm.set_ignore_filter(["^apple\.com:", ":443$"]) assert fm.get_ignore_filter() def test_replay(self): s = flow.State() - fm = flow.FlowMaster(None, s) + fm = flow.FlowMaster(None, None, s) f = tutils.tflow(resp=True) f.request.content = None assert "missing" in fm.replay_request(f) @@ -808,7 +808,7 @@ class TestFlowMaster: def test_script_reqerr(self): s = flow.State() - fm = flow.FlowMaster(None, s) + fm = flow.FlowMaster(None, None, s) fm.load_script(tutils.test_data.path("data/scripts/reqerr.py")) f = tutils.tflow() fm.clientconnect(f.client_conn) @@ -816,7 +816,7 @@ class TestFlowMaster: def test_script(self): s = flow.State() - fm = flow.FlowMaster(None, s) + fm = flow.FlowMaster(None, None, s) fm.load_script(tutils.test_data.path("data/scripts/all.py")) f = tutils.tflow(resp=True) @@ -852,7 +852,7 @@ class TestFlowMaster: def test_duplicate_flow(self): s = flow.State() - fm = flow.FlowMaster(None, s) + fm = flow.FlowMaster(None, None, s) f = tutils.tflow(resp=True) fm.load_flow(f) assert s.flow_count() == 1 @@ -863,12 +863,12 @@ class TestFlowMaster: def test_create_flow(self): s = flow.State() - fm = flow.FlowMaster(None, s) + fm = flow.FlowMaster(None, None, s) assert fm.create_request("GET", "http", "example.com", 80, "/") def test_all(self): s = flow.State() - fm = flow.FlowMaster(None, s) + fm = flow.FlowMaster(None, None, s) fm.anticache = True fm.anticomp = True f = tutils.tflow(req=None) @@ -895,7 +895,7 @@ class TestFlowMaster: f = tutils.tflow(resp=True) pb = [tutils.tflow(resp=True), f] - fm = flow.FlowMaster(DummyServer(ProxyConfig()), s) + fm = flow.FlowMaster(None, DummyServer(ProxyConfig()), s) assert not fm.start_server_playback( pb, False, @@ -923,7 +923,7 @@ class TestFlowMaster: f.response = HTTPResponse.wrap(netlib.tutils.tresp(content=f.request)) pb = [f] - fm = flow.FlowMaster(None, s) + fm = flow.FlowMaster(None, None, s) fm.refresh_server_playback = True assert not fm.do_server_playback(tutils.tflow()) @@ -965,7 +965,7 @@ class TestFlowMaster: f = tutils.tflow() f.response = HTTPResponse.wrap(netlib.tutils.tresp(content=f.request)) pb = [f] - fm = flow.FlowMaster(None, s) + fm = flow.FlowMaster(None, None, s) fm.refresh_server_playback = True fm.start_server_playback( pb, @@ -985,7 +985,7 @@ class TestFlowMaster: def test_stickycookie(self): s = flow.State() - fm = flow.FlowMaster(None, s) + fm = flow.FlowMaster(None, None, s) assert "Invalid" in fm.set_stickycookie("~h") fm.set_stickycookie(".*") assert fm.stickycookie_state @@ -1007,7 +1007,7 @@ class TestFlowMaster: def test_stickyauth(self): s = flow.State() - fm = flow.FlowMaster(None, s) + fm = flow.FlowMaster(None, None, s) assert "Invalid" in fm.set_stickyauth("~h") fm.set_stickyauth(".*") assert fm.stickyauth_state @@ -1035,7 +1035,7 @@ class TestFlowMaster: return list(r.stream()) s = flow.State() - fm = flow.FlowMaster(None, s) + fm = flow.FlowMaster(None, None, s) f = tutils.tflow(resp=True) with open(p, "ab") as tmpfile: diff --git a/test/mitmproxy/test_script.py b/test/mitmproxy/test_script.py index 81994780..1e8220f1 100644 --- a/test/mitmproxy/test_script.py +++ b/test/mitmproxy/test_script.py @@ -4,7 +4,7 @@ from . import tutils def test_duplicate_flow(): s = flow.State() - fm = flow.FlowMaster(None, s) + fm = flow.FlowMaster(None, None, s) fm.load_script(tutils.test_data.path("data/scripts/duplicate_flow.py")) f = tutils.tflow() fm.request(f) diff --git a/test/mitmproxy/tservers.py b/test/mitmproxy/tservers.py index 0760cb53..69a50b9d 100644 --- a/test/mitmproxy/tservers.py +++ b/test/mitmproxy/tservers.py @@ -34,7 +34,7 @@ class TestMaster(flow.FlowMaster): config.port = 0 s = ProxyServer(config) state = flow.State() - flow.FlowMaster.__init__(self, s, state) + flow.FlowMaster.__init__(self, None, s, state) self.apps.add(testapp, "testapp", 80) self.apps.add(errapp, "errapp", 80) self.clear_log() -- cgit v1.2.3 From 255e1eb00b76f169305d7c4ae3bba91403f3f924 Mon Sep 17 00:00:00 2001 From: Aldo Cortesi Date: Wed, 13 Jul 2016 23:45:49 +1200 Subject: Add the addons mechanism Demonstrate how it works and interacts with Options by adding our first new builtin: anticomp. --- test/mitmproxy/builtins/__init__.py | 0 test/mitmproxy/builtins/test_anticomp.py | 22 ++++++++++++++++++++++ test/mitmproxy/mastertest.py | 8 +++++++- test/mitmproxy/test_flow.py | 1 - 4 files changed, 29 insertions(+), 2 deletions(-) create mode 100644 test/mitmproxy/builtins/__init__.py create mode 100644 test/mitmproxy/builtins/test_anticomp.py (limited to 'test') diff --git a/test/mitmproxy/builtins/__init__.py b/test/mitmproxy/builtins/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/test/mitmproxy/builtins/test_anticomp.py b/test/mitmproxy/builtins/test_anticomp.py new file mode 100644 index 00000000..6bfd54bb --- /dev/null +++ b/test/mitmproxy/builtins/test_anticomp.py @@ -0,0 +1,22 @@ +from .. import tutils, mastertest +from mitmproxy.builtins import anticomp +from mitmproxy.flow import master +from mitmproxy.flow import state +from mitmproxy import options + + +class TestAntiComp(mastertest.MasterTest): + def test_simple(self): + s = state.State() + m = master.FlowMaster(options.Options(anticomp = True), None, s) + sa = anticomp.AntiComp() + m.addons.add(sa) + + f = tutils.tflow(resp=True) + self.invoke(m, "request", f) + + f = tutils.tflow(resp=True) + + f.request.headers["Accept-Encoding"] = "foobar" + self.invoke(m, "request", f) + assert f.request.headers["Accept-Encoding"] == "identity" diff --git a/test/mitmproxy/mastertest.py b/test/mitmproxy/mastertest.py index 9e726a32..06854e25 100644 --- a/test/mitmproxy/mastertest.py +++ b/test/mitmproxy/mastertest.py @@ -3,10 +3,16 @@ import mock from . import tutils import netlib.tutils -from mitmproxy import flow, proxy, models +from mitmproxy import flow, proxy, models, controller class MasterTest: + def invoke(self, master, handler, message): + with master.handlecontext(): + func = getattr(master, handler) + func(message) + message.reply = controller.DummyReply() + def cycle(self, master, content): f = tutils.tflow(req=netlib.tutils.treq(content=content)) l = proxy.Log("connect") diff --git a/test/mitmproxy/test_flow.py b/test/mitmproxy/test_flow.py index eda01ad9..6b270872 100644 --- a/test/mitmproxy/test_flow.py +++ b/test/mitmproxy/test_flow.py @@ -870,7 +870,6 @@ class TestFlowMaster: s = flow.State() fm = flow.FlowMaster(None, None, s) fm.anticache = True - fm.anticomp = True f = tutils.tflow(req=None) fm.clientconnect(f.client_conn) f.request = HTTPRequest.wrap(netlib.tutils.treq()) -- cgit v1.2.3 From a8a083a10d09509be8f39fb4463a857e0d3e2eeb Mon Sep 17 00:00:00 2001 From: Aldo Cortesi Date: Thu, 14 Jul 2016 10:08:41 +1200 Subject: Move StickyAuth into addon This is the first addon that handles an OptionsError, so this commit also demos how this works in console. Handling of command-line erorrs is on its way. --- test/mitmproxy/builtins/test_stickyauth.py | 23 ++++++++++++++++++++ test/mitmproxy/test_flow.py | 34 ------------------------------ 2 files changed, 23 insertions(+), 34 deletions(-) create mode 100644 test/mitmproxy/builtins/test_stickyauth.py (limited to 'test') diff --git a/test/mitmproxy/builtins/test_stickyauth.py b/test/mitmproxy/builtins/test_stickyauth.py new file mode 100644 index 00000000..9233f435 --- /dev/null +++ b/test/mitmproxy/builtins/test_stickyauth.py @@ -0,0 +1,23 @@ +from .. import tutils, mastertest +from mitmproxy.builtins import stickyauth +from mitmproxy.flow import master +from mitmproxy.flow import state +from mitmproxy import options + + +class TestStickyAuth(mastertest.MasterTest): + def test_simple(self): + s = state.State() + m = master.FlowMaster(options.Options(stickyauth = ".*"), None, s) + sa = stickyauth.StickyAuth() + m.addons.add(sa) + + f = tutils.tflow(resp=True) + f.request.headers["authorization"] = "foo" + self.invoke(m, "request", f) + + assert "address" in sa.hosts + + f = tutils.tflow(resp=True) + self.invoke(m, "request", f) + assert f.request.headers["authorization"] == "foo" diff --git a/test/mitmproxy/test_flow.py b/test/mitmproxy/test_flow.py index 6b270872..a6a3038c 100644 --- a/test/mitmproxy/test_flow.py +++ b/test/mitmproxy/test_flow.py @@ -120,20 +120,6 @@ class TestStickyCookieState: assert "cookie" in f.request.headers -class TestStickyAuthState: - - def test_response(self): - s = flow.StickyAuthState(filt.parse(".*")) - f = tutils.tflow(resp=True) - f.request.headers["authorization"] = "foo" - s.handle_request(f) - assert "address" in s.hosts - - f = tutils.tflow(resp=True) - s.handle_request(f) - assert f.request.headers["authorization"] == "foo" - - class TestClientPlaybackState: def test_tick(self): @@ -1004,26 +990,6 @@ class TestFlowMaster: fm.request(f) assert f.request.headers["cookie"] == "foo=bar" - def test_stickyauth(self): - s = flow.State() - fm = flow.FlowMaster(None, None, s) - assert "Invalid" in fm.set_stickyauth("~h") - fm.set_stickyauth(".*") - assert fm.stickyauth_state - fm.set_stickyauth(None) - assert not fm.stickyauth_state - - fm.set_stickyauth(".*") - f = tutils.tflow(resp=True) - f.request.headers["authorization"] = "foo" - fm.request(f) - - f = tutils.tflow(resp=True) - assert fm.stickyauth_state.hosts - assert "authorization" not in f.request.headers - fm.request(f) - assert f.request.headers["authorization"] == "foo" - def test_stream(self): with tutils.tmpdir() as tdir: p = os.path.join(tdir, "foo") -- cgit v1.2.3 From 97b2e6d958a691060746b530219bf15a0bede1ae Mon Sep 17 00:00:00 2001 From: Aldo Cortesi Date: Thu, 14 Jul 2016 11:11:41 +1200 Subject: Add a .setter helper to Options This returns a function that sets a named attribute, and is handy for event-driven code like mitmproxy console. --- test/mitmproxy/test_options.py | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'test') diff --git a/test/mitmproxy/test_options.py b/test/mitmproxy/test_options.py index 5fdb7abe..97db9430 100644 --- a/test/mitmproxy/test_options.py +++ b/test/mitmproxy/test_options.py @@ -3,7 +3,7 @@ import copy from mitmproxy import options from mitmproxy import exceptions -from netlib.tutils import raises +from netlib import tutils class TO(options.Options): @@ -19,8 +19,8 @@ def test_options(): assert o.two == "three" o.one = "one" assert o.one == "one" - raises("no such option", setattr, o, "nonexistent", "value") - raises("no such option", o.update, nonexistent = "value") + tutils.raises("no such option", setattr, o, "nonexistent", "value") + tutils.raises("no such option", o.update, nonexistent = "value") rec = [] @@ -38,6 +38,14 @@ def test_options(): assert rec[-1].one == "oink" +def test_setter(): + o = TO(two="three") + f = o.setter("two") + f("xxx") + assert o.two == "xxx" + tutils.raises("no such option", o.setter, "nonexistent") + + def test_rollback(): o = TO(one="two") -- cgit v1.2.3 From 143bf0dfa9138a4340287d636bb68648665b3829 Mon Sep 17 00:00:00 2001 From: Aldo Cortesi Date: Thu, 14 Jul 2016 11:24:06 +1200 Subject: AntiCache to addon --- test/mitmproxy/builtins/test_anticache.py | 23 +++++++++++++++++++++++ test/mitmproxy/test_flow.py | 10 ---------- 2 files changed, 23 insertions(+), 10 deletions(-) create mode 100644 test/mitmproxy/builtins/test_anticache.py (limited to 'test') diff --git a/test/mitmproxy/builtins/test_anticache.py b/test/mitmproxy/builtins/test_anticache.py new file mode 100644 index 00000000..5a00af03 --- /dev/null +++ b/test/mitmproxy/builtins/test_anticache.py @@ -0,0 +1,23 @@ +from .. import tutils, mastertest +from mitmproxy.builtins import anticache +from mitmproxy.flow import master +from mitmproxy.flow import state +from mitmproxy import options + + +class TestAntiCache(mastertest.MasterTest): + def test_simple(self): + s = state.State() + m = master.FlowMaster(options.Options(anticache = True), None, s) + sa = anticache.AntiCache() + m.addons.add(sa) + + f = tutils.tflow(resp=True) + self.invoke(m, "request", f) + + f = tutils.tflow(resp=True) + f.request.headers["if-modified-since"] = "test" + f.request.headers["if-none-match"] = "test" + self.invoke(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/test_flow.py b/test/mitmproxy/test_flow.py index a6a3038c..585dbf93 100644 --- a/test/mitmproxy/test_flow.py +++ b/test/mitmproxy/test_flow.py @@ -855,7 +855,6 @@ class TestFlowMaster: def test_all(self): s = flow.State() fm = flow.FlowMaster(None, None, s) - fm.anticache = True f = tutils.tflow(req=None) fm.clientconnect(f.client_conn) f.request = HTTPRequest.wrap(netlib.tutils.treq()) @@ -1053,15 +1052,6 @@ class TestRequest: assert r.url == "https://address:22/path" assert r.pretty_url == "https://foo.com:22/path" - def test_anticache(self): - r = HTTPRequest.wrap(netlib.tutils.treq()) - r.headers = Headers() - r.headers["if-modified-since"] = "test" - r.headers["if-none-match"] = "test" - r.anticache() - assert "if-modified-since" not in r.headers - assert "if-none-match" not in r.headers - def test_replace(self): r = HTTPRequest.wrap(netlib.tutils.treq()) r.path = "path/foo" -- cgit v1.2.3 From 00509d86a8ee3057ab870ae54dd1baf3ea10946b Mon Sep 17 00:00:00 2001 From: Aldo Cortesi Date: Thu, 14 Jul 2016 12:10:46 +1200 Subject: StickyCookies to addon --- test/mitmproxy/builtins/test_stickycookie.py | 118 +++++++++++++++++++++++++++ test/mitmproxy/test_flow.py | 102 ----------------------- 2 files changed, 118 insertions(+), 102 deletions(-) create mode 100644 test/mitmproxy/builtins/test_stickycookie.py (limited to 'test') diff --git a/test/mitmproxy/builtins/test_stickycookie.py b/test/mitmproxy/builtins/test_stickycookie.py new file mode 100644 index 00000000..ddfaf5e0 --- /dev/null +++ b/test/mitmproxy/builtins/test_stickycookie.py @@ -0,0 +1,118 @@ +from .. import tutils, mastertest +from mitmproxy.builtins import stickycookie +from mitmproxy.flow import master +from mitmproxy.flow import state +from mitmproxy import options +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): + s = state.State() + m = master.FlowMaster(options.Options(stickycookie = ".*"), None, s) + sc = stickycookie.StickyCookie() + m.addons.add(sc) + return s, m, sc + + def test_config(self): + sc = stickycookie.StickyCookie() + tutils.raises( + "invalid filter", + sc.configure, + options.Options(stickycookie = "~b") + ) + + def test_simple(self): + s, m, sc = self.mk() + m.addons.add(sc) + + f = tutils.tflow(resp=True) + f.response.headers["set-cookie"] = "foo=bar" + self.invoke(m, "request", f) + + f.reply.acked = False + self.invoke(m, "response", f) + + assert sc.jar + assert "cookie" not in f.request.headers + + f = f.copy() + f.reply.acked = False + self.invoke(m, "request", f) + assert f.request.headers["cookie"] == "foo=bar" + + def _response(self, s, m, sc, cookie, host): + f = tutils.tflow(req=ntutils.treq(host=host, port=80), resp=True) + f.response.headers["Set-Cookie"] = cookie + self.invoke(m, "response", f) + return f + + def test_response(self): + s, 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(s, m, sc, c, "host") + assert not sc.jar.keys() + + self._response(s, m, sc, c, "www.google.com") + assert sc.jar.keys() + + self._response(s, m, sc, "SSID=mooo", "www.google.com") + assert sc.jar.keys()[0] == ('www.google.com', 80, '/') + + def test_response_multiple(self): + s, m, sc = self.mk() + + # Test setting of multiple cookies + c1 = "somecookie=test; Path=/" + c2 = "othercookie=helloworld; Path=/" + f = self._response(s, m, sc, c1, "www.google.com") + f.response.headers["Set-Cookie"] = c2 + self.invoke(m, "response", f) + googlekey = sc.jar.keys()[0] + assert len(sc.jar[googlekey].keys()) == 2 + + def test_response_weird(self): + s, 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", + "foo,bar=buzz", + ] + for c in cs: + f.response.headers["Set-Cookie"] = c + self.invoke(m, "response", f) + googlekey = sc.jar.keys()[0] + assert len(sc.jar[googlekey].keys()) == len(cs) + + def test_response_overwrite(self): + s, m, sc = self.mk() + + # Test overwriting of a cookie value + c1 = "somecookie=helloworld; Path=/" + c2 = "somecookie=newvalue; Path=/" + f = self._response(s, m, sc, c1, "www.google.com") + f.response.headers["Set-Cookie"] = c2 + self.invoke(m, "response", f) + googlekey = sc.jar.keys()[0] + assert len(sc.jar[googlekey].keys()) == 1 + assert sc.jar[googlekey]["somecookie"].items()[0][1] == "newvalue" + + def test_request(self): + s, m, sc = self.mk() + + f = self._response(s, m, sc, "SSID=mooo", "www.google.com") + assert "cookie" not in f.request.headers + self.invoke(m, "request", f) + assert "cookie" in f.request.headers diff --git a/test/mitmproxy/test_flow.py b/test/mitmproxy/test_flow.py index 585dbf93..91342e58 100644 --- a/test/mitmproxy/test_flow.py +++ b/test/mitmproxy/test_flow.py @@ -40,86 +40,6 @@ def test_app_registry(): assert ar.get(r) -class TestStickyCookieState: - - def _response(self, cookie, host): - s = flow.StickyCookieState(filt.parse(".*")) - f = tutils.tflow(req=netlib.tutils.treq(host=host, port=80), resp=True) - f.response.headers["Set-Cookie"] = cookie - s.handle_response(f) - return s, f - - def test_domain_match(self): - s = flow.StickyCookieState(filt.parse(".*")) - assert s.domain_match("www.google.com", ".google.com") - assert s.domain_match("google.com", ".google.com") - - def test_response(self): - c = ( - "SSID=mooo; domain=.google.com, FOO=bar; Domain=.google.com; Path=/; " - "Expires=Wed, 13-Jan-2021 22:23:01 GMT; Secure; " - ) - - s, f = self._response(c, "host") - assert not s.jar.keys() - - s, f = self._response(c, "www.google.com") - assert list(s.jar.keys())[0] == ('.google.com', 80, '/') - - s, f = self._response("SSID=mooo", "www.google.com") - assert list(s.jar.keys())[0] == ('www.google.com', 80, '/') - - # Test setting of multiple cookies - c1 = "somecookie=test; Path=/" - c2 = "othercookie=helloworld; Path=/" - s, f = self._response(c1, "www.google.com") - f.response.headers["Set-Cookie"] = c2 - s.handle_response(f) - googlekey = list(s.jar.keys())[0] - assert len(s.jar[googlekey].keys()) == 2 - - # Test setting of weird cookie keys - s = flow.StickyCookieState(filt.parse(".*")) - f = tutils.tflow(req=netlib.tutils.treq(host="www.google.com", port=80), resp=True) - cs = [ - "foo/bar=hello", - "foo:bar=world", - "foo@bar=fizz", - "foo,bar=buzz", - ] - for c in cs: - f.response.headers["Set-Cookie"] = c - s.handle_response(f) - googlekey = list(s.jar.keys())[0] - assert len(s.jar[googlekey]) == len(cs) - - # Test overwriting of a cookie value - c1 = "somecookie=helloworld; Path=/" - c2 = "somecookie=newvalue; Path=/" - s, f = self._response(c1, "www.google.com") - f.response.headers["Set-Cookie"] = c2 - s.handle_response(f) - googlekey = list(s.jar.keys())[0] - assert len(s.jar[googlekey]) == 1 - assert list(s.jar[googlekey]["somecookie"].values())[0] == "newvalue" - - def test_response_delete(self): - c = "duffer=zafar; Path=/", "www.google.com" - - # Test that a cookie is be deleted - # by setting the expire time in the past - s, f = self._response(*c) - f.response.headers["Set-Cookie"] = "duffer=; Expires=Thu, 01-Jan-1970 00:00:00 GMT" - s.handle_response(f) - assert not s.jar.keys() - - def test_request(self): - s, f = self._response("SSID=mooo", b"www.google.com") - assert "cookie" not in f.request.headers - s.handle_request(f) - assert "cookie" in f.request.headers - - class TestClientPlaybackState: def test_tick(self): @@ -967,28 +887,6 @@ class TestFlowMaster: fm.process_new_request(f) assert "killed" in f.error.msg - def test_stickycookie(self): - s = flow.State() - fm = flow.FlowMaster(None, None, s) - assert "Invalid" in fm.set_stickycookie("~h") - fm.set_stickycookie(".*") - assert fm.stickycookie_state - fm.set_stickycookie(None) - assert not fm.stickycookie_state - - fm.set_stickycookie(".*") - f = tutils.tflow(resp=True) - f.response.headers["set-cookie"] = "foo=bar" - fm.request(f) - f.reply.acked = False - fm.response(f) - assert fm.stickycookie_state.jar - assert "cookie" not in f.request.headers - f = f.copy() - f.reply.acked = False - fm.request(f) - assert f.request.headers["cookie"] == "foo=bar" - def test_stream(self): with tutils.tmpdir() as tdir: p = os.path.join(tdir, "foo") -- cgit v1.2.3 From 703c05066ec0bc05c680e24d368606791dd1c958 Mon Sep 17 00:00:00 2001 From: Aldo Cortesi Date: Thu, 14 Jul 2016 12:59:00 +1200 Subject: Fix indeterminacy in sticky cookie tests How has this not bitten us before? --- test/mitmproxy/builtins/test_stickycookie.py | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) (limited to 'test') diff --git a/test/mitmproxy/builtins/test_stickycookie.py b/test/mitmproxy/builtins/test_stickycookie.py index ddfaf5e0..e64ecb5b 100644 --- a/test/mitmproxy/builtins/test_stickycookie.py +++ b/test/mitmproxy/builtins/test_stickycookie.py @@ -64,8 +64,11 @@ class TestStickyCookie(mastertest.MasterTest): self._response(s, m, sc, c, "www.google.com") assert sc.jar.keys() - self._response(s, m, sc, "SSID=mooo", "www.google.com") - assert sc.jar.keys()[0] == ('www.google.com', 80, '/') + sc.jar.clear() + self._response( + s, m, sc, "SSID=mooo", "www.google.com" + ) + assert list(sc.jar.keys())[0] == ('www.google.com', 80, '/') def test_response_multiple(self): s, m, sc = self.mk() @@ -76,7 +79,7 @@ class TestStickyCookie(mastertest.MasterTest): f = self._response(s, m, sc, c1, "www.google.com") f.response.headers["Set-Cookie"] = c2 self.invoke(m, "response", f) - googlekey = sc.jar.keys()[0] + googlekey = list(sc.jar.keys())[0] assert len(sc.jar[googlekey].keys()) == 2 def test_response_weird(self): @@ -93,7 +96,7 @@ class TestStickyCookie(mastertest.MasterTest): for c in cs: f.response.headers["Set-Cookie"] = c self.invoke(m, "response", f) - googlekey = sc.jar.keys()[0] + googlekey = list(sc.jar.keys())[0] assert len(sc.jar[googlekey].keys()) == len(cs) def test_response_overwrite(self): @@ -105,9 +108,9 @@ class TestStickyCookie(mastertest.MasterTest): f = self._response(s, m, sc, c1, "www.google.com") f.response.headers["Set-Cookie"] = c2 self.invoke(m, "response", f) - googlekey = sc.jar.keys()[0] + googlekey = list(sc.jar.keys())[0] assert len(sc.jar[googlekey].keys()) == 1 - assert sc.jar[googlekey]["somecookie"].items()[0][1] == "newvalue" + assert list(sc.jar[googlekey]["somecookie"].items())[0][1] == "newvalue" def test_request(self): s, m, sc = self.mk() -- cgit v1.2.3 From b2c4f301cb834ecdf6e5b0063e86be877d3ece6d Mon Sep 17 00:00:00 2001 From: Aldo Cortesi Date: Thu, 14 Jul 2016 12:43:17 +1200 Subject: Stream to file -> addon This commit also clarifies a confusion about the "outfile" attribute and its use in testing in the mitmdump master. --- test/mitmproxy/builtins/test_stream.py | 46 ++++++++++++++++++ test/mitmproxy/mastertest.py | 13 +++-- test/mitmproxy/test_dump.py | 89 ++++++++++++++++++++-------------- test/mitmproxy/test_flow.py | 31 ------------ 4 files changed, 104 insertions(+), 75 deletions(-) create mode 100644 test/mitmproxy/builtins/test_stream.py (limited to 'test') diff --git a/test/mitmproxy/builtins/test_stream.py b/test/mitmproxy/builtins/test_stream.py new file mode 100644 index 00000000..54e4f7d9 --- /dev/null +++ b/test/mitmproxy/builtins/test_stream.py @@ -0,0 +1,46 @@ +from __future__ import absolute_import, print_function, division + +from .. import tutils, mastertest + +import os.path + +from mitmproxy.builtins import stream +from mitmproxy.flow import master, FlowReader +from mitmproxy.flow import state +from mitmproxy import options + + +class TestStream(mastertest.MasterTest): + def test_stream(self): + with tutils.tmpdir() as tdir: + p = os.path.join(tdir, "foo") + + def r(): + r = FlowReader(open(p, "rb")) + return list(r.stream()) + + s = state.State() + m = master.FlowMaster( + options.Options( + outfile = (p, "wb") + ), + None, + s + ) + sa = stream.Stream() + + m.addons.add(sa) + f = tutils.tflow(resp=True) + self.invoke(m, "request", f) + self.invoke(m, "response", f) + m.addons.remove(sa) + + assert r()[0].response + + m.options.outfile = (p, "ab") + + m.addons.add(sa) + f = tutils.tflow() + self.invoke(m, "request", f) + m.addons.remove(sa) + assert not r()[1].response diff --git a/test/mitmproxy/mastertest.py b/test/mitmproxy/mastertest.py index 06854e25..9754d3a9 100644 --- a/test/mitmproxy/mastertest.py +++ b/test/mitmproxy/mastertest.py @@ -18,15 +18,14 @@ class MasterTest: l = proxy.Log("connect") l.reply = mock.MagicMock() master.log(l) - master.clientconnect(f.client_conn) - master.serverconnect(f.server_conn) - master.request(f) + self.invoke(master, "clientconnect", f.client_conn) + self.invoke(master, "clientconnect", f.client_conn) + self.invoke(master, "serverconnect", f.server_conn) + self.invoke(master, "request", f) if not f.error: f.response = models.HTTPResponse.wrap(netlib.tutils.tresp(content=content)) - f.reply.acked = False - f = master.response(f) - f.client_conn.reply.acked = False - master.clientdisconnect(f.client_conn) + self.invoke(master, "response", f) + self.invoke(master, "clientdisconnect", f) return f def dummy_cycle(self, master, n, content): diff --git a/test/mitmproxy/test_dump.py b/test/mitmproxy/test_dump.py index aa73b5a4..9686be84 100644 --- a/test/mitmproxy/test_dump.py +++ b/test/mitmproxy/test_dump.py @@ -4,31 +4,33 @@ from mitmproxy.exceptions import ContentViewException import netlib.tutils -from mitmproxy import dump, flow, models +from mitmproxy import dump, flow, models, exceptions from . import tutils, mastertest import mock def test_strfuncs(): - o = dump.Options() + o = dump.Options( + tfile = StringIO(), + flow_detail = 0, + ) m = dump.DumpMaster(None, o) - m.outfile = StringIO() m.o.flow_detail = 0 m.echo_flow(tutils.tflow()) - assert not m.outfile.getvalue() + assert not o.tfile.getvalue() m.o.flow_detail = 4 m.echo_flow(tutils.tflow()) - assert m.outfile.getvalue() + assert o.tfile.getvalue() - m.outfile = StringIO() + o.tfile = StringIO() m.echo_flow(tutils.tflow(resp=True)) - assert "<<" in m.outfile.getvalue() + assert "<<" in o.tfile.getvalue() - m.outfile = StringIO() + o.tfile = StringIO() m.echo_flow(tutils.tflow(err=True)) - assert "<<" in m.outfile.getvalue() + assert "<<" in o.tfile.getvalue() flow = tutils.tflow() flow.request = netlib.tutils.treq() @@ -50,25 +52,32 @@ def test_strfuncs(): def test_contentview(get_content_view): get_content_view.side_effect = ContentViewException(""), ("x", iter([])) - o = dump.Options(flow_detail=4, verbosity=3) - m = dump.DumpMaster(None, o, StringIO()) + o = dump.Options( + flow_detail=4, + verbosity=3, + tfile=StringIO(), + ) + m = dump.DumpMaster(None, o) m.echo_flow(tutils.tflow()) - assert "Content viewer failed" in m.outfile.getvalue() + assert "Content viewer failed" in m.options.tfile.getvalue() class TestDumpMaster(mastertest.MasterTest): def dummy_cycle(self, master, n, content): mastertest.MasterTest.dummy_cycle(self, master, n, content) - return master.outfile.getvalue() + return master.options.tfile.getvalue() def mkmaster(self, filt, **options): - cs = StringIO() if "verbosity" not in options: options["verbosity"] = 0 if "flow_detail" not in options: options["flow_detail"] = 0 - o = dump.Options(filtstr=filt, **options) - return dump.DumpMaster(None, o, outfile=cs) + o = dump.Options( + filtstr=filt, + tfile=StringIO(), + **options + ) + return dump.DumpMaster(None, o) def test_basic(self): for i in (1, 2, 3): @@ -89,31 +98,33 @@ class TestDumpMaster(mastertest.MasterTest): ) def test_error(self): - cs = StringIO() - o = dump.Options(flow_detail=1) - m = dump.DumpMaster(None, o, outfile=cs) + o = dump.Options( + tfile=StringIO(), + flow_detail=1 + ) + m = dump.DumpMaster(None, o) f = tutils.tflow(err=True) m.request(f) assert m.error(f) - assert "error" in cs.getvalue() + assert "error" in o.tfile.getvalue() def test_missing_content(self): - cs = StringIO() - o = dump.Options(flow_detail=3) - m = dump.DumpMaster(None, o, outfile=cs) + o = dump.Options( + flow_detail=3, + tfile=StringIO(), + ) + m = dump.DumpMaster(None, o) f = tutils.tflow() f.request.content = None m.request(f) f.response = models.HTTPResponse.wrap(netlib.tutils.tresp()) f.response.content = None m.response(f) - assert "content missing" in cs.getvalue() + assert "content missing" in o.tfile.getvalue() def test_replay(self): - cs = StringIO() - o = dump.Options(server_replay=["nonexistent"], kill=True) - tutils.raises(dump.DumpError, dump.DumpMaster, None, o, outfile=cs) + tutils.raises(dump.DumpError, dump.DumpMaster, None, o) with tutils.tmpdir() as t: p = os.path.join(t, "rep") @@ -122,7 +133,7 @@ class TestDumpMaster(mastertest.MasterTest): o = dump.Options(server_replay=[p], kill=True) o.verbosity = 0 o.flow_detail = 0 - m = dump.DumpMaster(None, o, outfile=cs) + m = dump.DumpMaster(None, o) self.cycle(m, b"content") self.cycle(m, b"content") @@ -130,13 +141,13 @@ class TestDumpMaster(mastertest.MasterTest): o = dump.Options(server_replay=[p], kill=False) o.verbosity = 0 o.flow_detail = 0 - m = dump.DumpMaster(None, o, outfile=cs) + m = dump.DumpMaster(None, o) self.cycle(m, b"nonexistent") o = dump.Options(client_replay=[p], kill=False) o.verbosity = 0 o.flow_detail = 0 - m = dump.DumpMaster(None, o, outfile=cs) + m = dump.DumpMaster(None, o) def test_read(self): with tutils.tmpdir() as t: @@ -172,20 +183,24 @@ class TestDumpMaster(mastertest.MasterTest): assert len(m.apps.apps) == 1 def test_replacements(self): - cs = StringIO() - o = dump.Options(replacements=[(".*", "content", "foo")]) + o = dump.Options( + replacements=[(".*", "content", "foo")], + tfile = StringIO(), + ) o.verbosity = 0 o.flow_detail = 0 - m = dump.DumpMaster(None, o, outfile=cs) + m = dump.DumpMaster(None, o) f = self.cycle(m, b"content") assert f.request.content == b"foo" def test_setheader(self): - cs = StringIO() - o = dump.Options(setheaders=[(".*", "one", "two")]) + o = dump.Options( + setheaders=[(".*", "one", "two")], + tfile=StringIO() + ) o.verbosity = 0 o.flow_detail = 0 - m = dump.DumpMaster(None, o, outfile=cs) + m = dump.DumpMaster(None, o) f = self.cycle(m, b"content") assert f.request.headers["one"] == "two" @@ -212,7 +227,7 @@ class TestDumpMaster(mastertest.MasterTest): def test_write_err(self): tutils.raises( - dump.DumpError, + exceptions.OptionsError, self.mkmaster, None, outfile = ("nonexistentdir/foo", "wb") ) diff --git a/test/mitmproxy/test_flow.py b/test/mitmproxy/test_flow.py index 91342e58..1a07f74d 100644 --- a/test/mitmproxy/test_flow.py +++ b/test/mitmproxy/test_flow.py @@ -1,5 +1,3 @@ -import os.path - import mock import io @@ -887,35 +885,6 @@ class TestFlowMaster: fm.process_new_request(f) assert "killed" in f.error.msg - def test_stream(self): - with tutils.tmpdir() as tdir: - p = os.path.join(tdir, "foo") - - def read(): - with open(p, "rb") as f: - r = flow.FlowReader(f) - return list(r.stream()) - - s = flow.State() - fm = flow.FlowMaster(None, None, s) - f = tutils.tflow(resp=True) - - with open(p, "ab") as tmpfile: - fm.start_stream(tmpfile, None) - fm.request(f) - fm.response(f) - fm.stop_stream() - - assert read()[0].response - - with open(p, "ab") as tmpfile: - f = tutils.tflow() - fm.start_stream(tmpfile, None) - fm.request(f) - fm.shutdown() - - assert not read()[1].response - class TestRequest: -- cgit v1.2.3 From ec6fbe9eb684bbf70db796876751078865a0e50f Mon Sep 17 00:00:00 2001 From: Maximilian Hils Date: Wed, 13 Jul 2016 21:40:13 -0700 Subject: make options explicit --- test/mitmproxy/builtins/test_anticache.py | 2 +- test/mitmproxy/builtins/test_anticomp.py | 2 +- test/mitmproxy/builtins/test_stickyauth.py | 2 +- test/mitmproxy/builtins/test_stickycookie.py | 2 +- test/mitmproxy/console/test_master.py | 6 +++--- test/mitmproxy/test_options.py | 30 ++++++++++++++++++++-------- test/mitmproxy/test_web_master.py | 9 +++------ 7 files changed, 32 insertions(+), 21 deletions(-) (limited to 'test') diff --git a/test/mitmproxy/builtins/test_anticache.py b/test/mitmproxy/builtins/test_anticache.py index 5a00af03..127e1c1a 100644 --- a/test/mitmproxy/builtins/test_anticache.py +++ b/test/mitmproxy/builtins/test_anticache.py @@ -2,7 +2,7 @@ from .. import tutils, mastertest from mitmproxy.builtins import anticache from mitmproxy.flow import master from mitmproxy.flow import state -from mitmproxy import options +from mitmproxy.flow import options class TestAntiCache(mastertest.MasterTest): diff --git a/test/mitmproxy/builtins/test_anticomp.py b/test/mitmproxy/builtins/test_anticomp.py index 6bfd54bb..601e56c8 100644 --- a/test/mitmproxy/builtins/test_anticomp.py +++ b/test/mitmproxy/builtins/test_anticomp.py @@ -2,7 +2,7 @@ from .. import tutils, mastertest from mitmproxy.builtins import anticomp from mitmproxy.flow import master from mitmproxy.flow import state -from mitmproxy import options +from mitmproxy.flow import options class TestAntiComp(mastertest.MasterTest): diff --git a/test/mitmproxy/builtins/test_stickyauth.py b/test/mitmproxy/builtins/test_stickyauth.py index 9233f435..1e617402 100644 --- a/test/mitmproxy/builtins/test_stickyauth.py +++ b/test/mitmproxy/builtins/test_stickyauth.py @@ -2,7 +2,7 @@ from .. import tutils, mastertest from mitmproxy.builtins import stickyauth from mitmproxy.flow import master from mitmproxy.flow import state -from mitmproxy import options +from mitmproxy.flow import options class TestStickyAuth(mastertest.MasterTest): diff --git a/test/mitmproxy/builtins/test_stickycookie.py b/test/mitmproxy/builtins/test_stickycookie.py index e64ecb5b..9cf768df 100644 --- a/test/mitmproxy/builtins/test_stickycookie.py +++ b/test/mitmproxy/builtins/test_stickycookie.py @@ -2,7 +2,7 @@ from .. import tutils, mastertest from mitmproxy.builtins import stickycookie from mitmproxy.flow import master from mitmproxy.flow import state -from mitmproxy import options +from mitmproxy.flow import options from netlib import tutils as ntutils diff --git a/test/mitmproxy/console/test_master.py b/test/mitmproxy/console/test_master.py index d42863b3..b84e4c1c 100644 --- a/test/mitmproxy/console/test_master.py +++ b/test/mitmproxy/console/test_master.py @@ -111,14 +111,14 @@ def test_options(): class TestMaster(mastertest.MasterTest): - def mkmaster(self, filt, **options): + def mkmaster(self, **options): if "verbosity" not in options: options["verbosity"] = 0 - o = console.master.Options(filtstr=filt, **options) + o = console.master.Options(**options) return console.master.ConsoleMaster(None, o) def test_basic(self): - m = self.mkmaster(None) + m = self.mkmaster() for i in (1, 2, 3): self.dummy_cycle(m, 1, b"") assert len(m.state.flows) == i diff --git a/test/mitmproxy/test_options.py b/test/mitmproxy/test_options.py index 97db9430..cdb0d765 100644 --- a/test/mitmproxy/test_options.py +++ b/test/mitmproxy/test_options.py @@ -7,10 +7,10 @@ from netlib import tutils class TO(options.Options): - attributes = [ - "one", - "two" - ] + def __init__(self, one=None, two=None): + self.one = one + self.two = two + super(TO, self).__init__() def test_options(): @@ -19,8 +19,13 @@ def test_options(): assert o.two == "three" o.one = "one" assert o.one == "one" - tutils.raises("no such option", setattr, o, "nonexistent", "value") - tutils.raises("no such option", o.update, nonexistent = "value") + + with tutils.raises(TypeError): + TO(nonexistent = "value") + with tutils.raises("no such option"): + o.nonexistent = "value" + with tutils.raises("no such option"): + o.update(nonexistent = "value") rec = [] @@ -43,7 +48,8 @@ def test_setter(): f = o.setter("two") f("xxx") assert o.two == "xxx" - tutils.raises("no such option", o.setter, "nonexistent") + with tutils.raises("no such option"): + o.setter("nonexistent") def test_rollback(): @@ -61,7 +67,7 @@ def test_rollback(): def err(opts): if opts.one == "ten": - raise exceptions.OptionsError + raise exceptions.OptionsError() o.changed.connect(sub) o.changed.connect(err) @@ -73,3 +79,11 @@ def test_rollback(): assert len(rec) == 2 assert rec[0].one == "ten" assert rec[1].one == "two" + + +def test_repr(): + assert repr(TO()) == "test.mitmproxy.test_options.TO({'one': None, 'two': None})" + assert repr(TO(one='x' * 60)) == """test.mitmproxy.test_options.TO({ + 'one': 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', + 'two': None +})""" diff --git a/test/mitmproxy/test_web_master.py b/test/mitmproxy/test_web_master.py index f0fafe24..2ab440ce 100644 --- a/test/mitmproxy/test_web_master.py +++ b/test/mitmproxy/test_web_master.py @@ -3,15 +3,12 @@ from . import mastertest class TestWebMaster(mastertest.MasterTest): - def mkmaster(self, filt, **options): - o = master.Options( - filtstr=filt, - **options - ) + def mkmaster(self, **options): + o = master.Options(**options) return master.WebMaster(None, o) def test_basic(self): - m = self.mkmaster(None) + m = self.mkmaster() for i in (1, 2, 3): self.dummy_cycle(m, 1, b"") assert len(m.state.flows) == i -- cgit v1.2.3 From f84a23f11d869ca5132e0388345bd19937486628 Mon Sep 17 00:00:00 2001 From: Maximilian Hils Date: Wed, 13 Jul 2016 22:01:16 -0700 Subject: minor fixes --- test/mitmproxy/builtins/test_stream.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'test') diff --git a/test/mitmproxy/builtins/test_stream.py b/test/mitmproxy/builtins/test_stream.py index 54e4f7d9..edaa41d2 100644 --- a/test/mitmproxy/builtins/test_stream.py +++ b/test/mitmproxy/builtins/test_stream.py @@ -7,7 +7,7 @@ import os.path from mitmproxy.builtins import stream from mitmproxy.flow import master, FlowReader from mitmproxy.flow import state -from mitmproxy import options +from mitmproxy.flow import options class TestStream(mastertest.MasterTest): -- cgit v1.2.3 From 126625584251d6a246ba46943cfa71d5a57fbdda Mon Sep 17 00:00:00 2001 From: Shadab Zafar Date: Thu, 14 Jul 2016 13:07:27 +0530 Subject: Re-add deletion of stickycookies (#1355) This was originally added in #1324 (fixing issue #1096) but got lost during "the big refactor" (#1352) --- test/mitmproxy/builtins/test_stickycookie.py | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'test') diff --git a/test/mitmproxy/builtins/test_stickycookie.py b/test/mitmproxy/builtins/test_stickycookie.py index 9cf768df..b8d703bd 100644 --- a/test/mitmproxy/builtins/test_stickycookie.py +++ b/test/mitmproxy/builtins/test_stickycookie.py @@ -112,6 +112,16 @@ class TestStickyCookie(mastertest.MasterTest): assert len(sc.jar[googlekey].keys()) == 1 assert list(sc.jar[googlekey]["somecookie"].items())[0][1] == "newvalue" + def test_response_delete(self): + s, m, sc = self.mk() + + # Test that a cookie is be deleted + # by setting the expire time in the past + f = self._response(s, m, sc, "duffer=zafar; Path=/", "www.google.com") + f.response.headers["Set-Cookie"] = "duffer=; Expires=Thu, 01-Jan-1970 00:00:00 GMT" + self.invoke(m, "response", f) + assert not sc.jar.keys() + def test_request(self): s, m, sc = self.mk() -- cgit v1.2.3 From a3a22fba337fc4ac750b8c18663233920a0d646b Mon Sep 17 00:00:00 2001 From: Aldo Cortesi Date: Thu, 14 Jul 2016 13:51:00 +1200 Subject: First-order integration of scripts addon --- test/mitmproxy/builtins/test_script.py | 136 +++++++++++++++++++++ test/mitmproxy/data/addonscripts/duplicate_flow.py | 6 + test/mitmproxy/data/addonscripts/error.py | 7 ++ test/mitmproxy/data/addonscripts/recorder.py | 18 +++ test/mitmproxy/data/addonscripts/stream_modify.py | 8 ++ .../data/addonscripts/tcp_stream_modify.py | 5 + test/mitmproxy/test_dump.py | 4 +- test/mitmproxy/test_flow.py | 64 +--------- test/mitmproxy/test_script.py | 13 -- test/mitmproxy/test_server.py | 22 ++-- 10 files changed, 197 insertions(+), 86 deletions(-) create mode 100644 test/mitmproxy/builtins/test_script.py create mode 100644 test/mitmproxy/data/addonscripts/duplicate_flow.py create mode 100644 test/mitmproxy/data/addonscripts/error.py create mode 100644 test/mitmproxy/data/addonscripts/recorder.py create mode 100644 test/mitmproxy/data/addonscripts/stream_modify.py create mode 100644 test/mitmproxy/data/addonscripts/tcp_stream_modify.py delete mode 100644 test/mitmproxy/test_script.py (limited to 'test') diff --git a/test/mitmproxy/builtins/test_script.py b/test/mitmproxy/builtins/test_script.py new file mode 100644 index 00000000..d3366189 --- /dev/null +++ b/test/mitmproxy/builtins/test_script.py @@ -0,0 +1,136 @@ +import time + +from mitmproxy.builtins import script +from mitmproxy import exceptions +from mitmproxy.flow import master +from mitmproxy.flow import state +from mitmproxy import options + +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/scripts/a.py") == ("data/scripts/a.py", []) + assert script.parse_command("data/scripts/a.py foo bar") == ("data/scripts/a.py", ["foo", "bar"]) + assert script.parse_command("data/scripts/a.py 'foo bar'") == ("data/scripts/a.py", ["foo bar"]) + + @tutils.skip_not_windows + def test_parse_windows(self): + with tutils.chdir(tutils.test_data.dirname): + assert script.parse_command("data\\scripts\\a.py") == ("data\\scripts\\a.py", []) + assert script.parse_command("data\\scripts\\a.py 'foo \\ bar'") == ("data\\scripts\\a.py", 'foo \\ bar', []) + + +def test_load_script(): + ns = script.load_script( + tutils.test_data.path( + "data/addonscripts/recorder.py" + ), [] + ) + assert ns["configure"] + + +class RecordingMaster(master.FlowMaster): + def __init__(self, *args, **kwargs): + master.FlowMaster.__init__(self, *args, **kwargs) + self.event_log = [] + + def add_event(self, e, level): + self.event_log.append((level, e)) + + +class TestScript(mastertest.MasterTest): + def test_simple(self): + s = state.State() + m = master.FlowMaster(options.Options(), None, s) + sc = script.Script( + tutils.test_data.path( + "data/addonscripts/recorder.py" + ) + ) + m.addons.add(sc) + assert sc.ns["call_log"] == [("configure", (options.Options(),), {})] + + sc.ns["call_log"] = [] + f = tutils.tflow(resp=True) + self.invoke(m, "request", f) + + recf = sc.ns["call_log"][0] + assert recf[0] == "request" + + def test_reload(self): + s = state.State() + m = RecordingMaster(options.Options(), None, s) + 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(".") + time.sleep(0.1) + if m.event_log: + return + raise AssertionError("Change event not detected.") + + def test_exception(self): + s = state.State() + m = RecordingMaster(options.Options(), None, s) + sc = script.Script( + tutils.test_data.path("data/addonscripts/error.py") + ) + m.addons.add(sc) + f = tutils.tflow(resp=True) + self.invoke(m, "request", f) + assert m.event_log[0][0] == "warn" + + def test_duplicate_flow(self): + s = state.State() + fm = master.FlowMaster(None, None, s) + fm.addons.add( + script.Script( + tutils.test_data.path("data/addonscripts/duplicate_flow.py") + ) + ) + f = tutils.tflow() + fm.request(f) + assert fm.state.flow_count() == 2 + assert not fm.state.view[0].request.is_replay + assert fm.state.view[1].request.is_replay + + +class TestScriptLoader(mastertest.MasterTest): + def test_simple(self): + s = state.State() + o = options.Options(scripts=[]) + m = master.FlowMaster(o, None, s) + 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 diff --git a/test/mitmproxy/data/addonscripts/duplicate_flow.py b/test/mitmproxy/data/addonscripts/duplicate_flow.py new file mode 100644 index 00000000..b466423c --- /dev/null +++ b/test/mitmproxy/data/addonscripts/duplicate_flow.py @@ -0,0 +1,6 @@ +from mitmproxy import ctx + + +def request(flow): + f = ctx.master.duplicate_flow(flow) + ctx.master.replay_request(f, block=True) diff --git a/test/mitmproxy/data/addonscripts/error.py b/test/mitmproxy/data/addonscripts/error.py new file mode 100644 index 00000000..8ece9fce --- /dev/null +++ b/test/mitmproxy/data/addonscripts/error.py @@ -0,0 +1,7 @@ + +def mkerr(): + raise ValueError("Error!") + + +def request(flow): + mkerr() diff --git a/test/mitmproxy/data/addonscripts/recorder.py b/test/mitmproxy/data/addonscripts/recorder.py new file mode 100644 index 00000000..728203e3 --- /dev/null +++ b/test/mitmproxy/data/addonscripts/recorder.py @@ -0,0 +1,18 @@ +from mitmproxy import controller +from mitmproxy import ctx + +call_log = [] + +# Keep a log of all possible event calls +evts = list(controller.Events) + ["configure"] +for i in evts: + def mkprox(): + evt = i + + def prox(*args, **kwargs): + lg = (evt, args, kwargs) + if evt != "log": + ctx.log.info(str(lg)) + call_log.append(lg) + return prox + globals()[i] = mkprox() diff --git a/test/mitmproxy/data/addonscripts/stream_modify.py b/test/mitmproxy/data/addonscripts/stream_modify.py new file mode 100644 index 00000000..bc616342 --- /dev/null +++ b/test/mitmproxy/data/addonscripts/stream_modify.py @@ -0,0 +1,8 @@ + +def modify(chunks): + for chunk in chunks: + yield chunk.replace(b"foo", b"bar") + + +def responseheaders(flow): + flow.response.stream = modify diff --git a/test/mitmproxy/data/addonscripts/tcp_stream_modify.py b/test/mitmproxy/data/addonscripts/tcp_stream_modify.py new file mode 100644 index 00000000..af4ccf7e --- /dev/null +++ b/test/mitmproxy/data/addonscripts/tcp_stream_modify.py @@ -0,0 +1,5 @@ + +def tcp_message(flow): + message = flow.messages[-1] + if not message.from_client: + message.content = message.content.replace(b"foo", b"bar") diff --git a/test/mitmproxy/test_dump.py b/test/mitmproxy/test_dump.py index 9686be84..201386e3 100644 --- a/test/mitmproxy/test_dump.py +++ b/test/mitmproxy/test_dump.py @@ -245,12 +245,12 @@ class TestDumpMaster(mastertest.MasterTest): assert "XRESPONSE" in ret assert "XCLIENTDISCONNECT" in ret tutils.raises( - dump.DumpError, + exceptions.AddonError, self.mkmaster, None, scripts=["nonexistent"] ) tutils.raises( - dump.DumpError, + exceptions.AddonError, self.mkmaster, None, scripts=["starterr.py"] ) diff --git a/test/mitmproxy/test_flow.py b/test/mitmproxy/test_flow.py index 1a07f74d..c58a9703 100644 --- a/test/mitmproxy/test_flow.py +++ b/test/mitmproxy/test_flow.py @@ -5,7 +5,7 @@ import netlib.utils from netlib.http import Headers from mitmproxy import filt, controller, flow from mitmproxy.contrib import tnetstring -from mitmproxy.exceptions import FlowReadException, ScriptException +from mitmproxy.exceptions import FlowReadException from mitmproxy.models import Error from mitmproxy.models import Flow from mitmproxy.models import HTTPFlow @@ -674,21 +674,6 @@ class TestSerialize: class TestFlowMaster: - def test_load_script(self): - s = flow.State() - fm = flow.FlowMaster(None, None, s) - - fm.load_script(tutils.test_data.path("data/scripts/a.py")) - fm.load_script(tutils.test_data.path("data/scripts/a.py")) - fm.unload_scripts() - with tutils.raises(ScriptException): - fm.load_script("nonexistent") - try: - fm.load_script(tutils.test_data.path("data/scripts/starterr.py")) - except ScriptException as e: - assert "ValueError" in str(e) - assert len(fm.scripts) == 0 - def test_getset_ignore(self): p = mock.Mock() p.config.check_ignore = HostMatcher() @@ -708,51 +693,7 @@ class TestFlowMaster: assert "intercepting" in fm.replay_request(f) f.live = True - assert "live" in fm.replay_request(f, run_scripthooks=True) - - def test_script_reqerr(self): - s = flow.State() - fm = flow.FlowMaster(None, None, s) - fm.load_script(tutils.test_data.path("data/scripts/reqerr.py")) - f = tutils.tflow() - fm.clientconnect(f.client_conn) - assert fm.request(f) - - def test_script(self): - s = flow.State() - fm = flow.FlowMaster(None, None, s) - fm.load_script(tutils.test_data.path("data/scripts/all.py")) - f = tutils.tflow(resp=True) - - f.client_conn.acked = False - fm.clientconnect(f.client_conn) - assert fm.scripts[0].ns["log"][-1] == "clientconnect" - f.server_conn.acked = False - fm.serverconnect(f.server_conn) - assert fm.scripts[0].ns["log"][-1] == "serverconnect" - f.reply.acked = False - fm.request(f) - assert fm.scripts[0].ns["log"][-1] == "request" - f.reply.acked = False - fm.response(f) - assert fm.scripts[0].ns["log"][-1] == "response" - # load second script - fm.load_script(tutils.test_data.path("data/scripts/all.py")) - assert len(fm.scripts) == 2 - f.server_conn.reply.acked = False - fm.clientdisconnect(f.server_conn) - assert fm.scripts[0].ns["log"][-1] == "clientdisconnect" - assert fm.scripts[1].ns["log"][-1] == "clientdisconnect" - - # unload first script - fm.unload_scripts() - assert len(fm.scripts) == 0 - fm.load_script(tutils.test_data.path("data/scripts/all.py")) - - f.error = tutils.terr() - f.reply.acked = False - fm.error(f) - assert fm.scripts[0].ns["log"][-1] == "error" + assert "live" in fm.replay_request(f) def test_duplicate_flow(self): s = flow.State() @@ -789,7 +730,6 @@ class TestFlowMaster: f.error.reply = controller.DummyReply() fm.error(f) - fm.load_script(tutils.test_data.path("data/scripts/a.py")) fm.shutdown() def test_client_playback(self): diff --git a/test/mitmproxy/test_script.py b/test/mitmproxy/test_script.py deleted file mode 100644 index 1e8220f1..00000000 --- a/test/mitmproxy/test_script.py +++ /dev/null @@ -1,13 +0,0 @@ -from mitmproxy import flow -from . import tutils - - -def test_duplicate_flow(): - s = flow.State() - fm = flow.FlowMaster(None, None, s) - fm.load_script(tutils.test_data.path("data/scripts/duplicate_flow.py")) - f = tutils.tflow() - fm.request(f) - assert fm.state.flow_count() == 2 - assert not fm.state.view[0].request.is_replay - assert fm.state.view[1].request.is_replay diff --git a/test/mitmproxy/test_server.py b/test/mitmproxy/test_server.py index 9dd8b79c..b1ca6910 100644 --- a/test/mitmproxy/test_server.py +++ b/test/mitmproxy/test_server.py @@ -13,6 +13,7 @@ from netlib.http import authentication, http1 from netlib.tutils import raises from pathod import pathoc, pathod +from mitmproxy.builtins import script from mitmproxy import controller from mitmproxy.proxy.config import HostMatcher from mitmproxy.models import Error, HTTPResponse, HTTPFlow @@ -287,10 +288,13 @@ class TestHTTP(tservers.HTTPProxyTest, CommonMixin, AppMixin): self.master.set_stream_large_bodies(None) def test_stream_modify(self): - self.master.load_script(tutils.test_data.path("data/scripts/stream_modify.py")) + s = script.Script( + tutils.test_data.path("data/addonscripts/stream_modify.py") + ) + self.master.addons.add(s) d = self.pathod('200:b"foo"') - assert d.content == b"bar" - self.master.unload_scripts() + assert d.content == "bar" + self.master.addons.remove(s) class TestHTTPAuth(tservers.HTTPProxyTest): @@ -512,15 +516,15 @@ class TestTransparent(tservers.TransparentProxyTest, CommonMixin, TcpMixin): ssl = False def test_tcp_stream_modify(self): - self.master.load_script(tutils.test_data.path("data/scripts/tcp_stream_modify.py")) - + s = script.Script( + tutils.test_data.path("data/addonscripts/tcp_stream_modify.py") + ) + self.master.addons.add(s) self._tcpproxy_on() d = self.pathod('200:b"foo"') self._tcpproxy_off() - - assert d.content == b"bar" - - self.master.unload_scripts() + assert d.content == "bar" + self.master.addons.remove(s) class TestTransparentSSL(tservers.TransparentProxyTest, CommonMixin, TcpMixin): -- cgit v1.2.3 From a6821aad8e9296640c3efd4275e8922dd7c6e43b Mon Sep 17 00:00:00 2001 From: Aldo Cortesi Date: Thu, 14 Jul 2016 14:39:07 +1200 Subject: Zap old scripts infrastructure, fix concurrency tests --- test/mitmproxy/builtins/test_script.py | 13 +------ .../data/addonscripts/concurrent_decorator.py | 6 +++ .../data/addonscripts/concurrent_decorator_err.py | 6 +++ .../mitmproxy/data/scripts/concurrent_decorator.py | 7 ---- .../data/scripts/concurrent_decorator_err.py | 6 --- test/mitmproxy/mastertest.py | 10 +++++ test/mitmproxy/script/test_concurrent.py | 43 ++++++++++++++++------ 7 files changed, 55 insertions(+), 36 deletions(-) create mode 100644 test/mitmproxy/data/addonscripts/concurrent_decorator.py create mode 100644 test/mitmproxy/data/addonscripts/concurrent_decorator_err.py delete mode 100644 test/mitmproxy/data/scripts/concurrent_decorator.py delete mode 100644 test/mitmproxy/data/scripts/concurrent_decorator_err.py (limited to 'test') diff --git a/test/mitmproxy/builtins/test_script.py b/test/mitmproxy/builtins/test_script.py index d3366189..2447c8ea 100644 --- a/test/mitmproxy/builtins/test_script.py +++ b/test/mitmproxy/builtins/test_script.py @@ -47,15 +47,6 @@ def test_load_script(): assert ns["configure"] -class RecordingMaster(master.FlowMaster): - def __init__(self, *args, **kwargs): - master.FlowMaster.__init__(self, *args, **kwargs) - self.event_log = [] - - def add_event(self, e, level): - self.event_log.append((level, e)) - - class TestScript(mastertest.MasterTest): def test_simple(self): s = state.State() @@ -77,7 +68,7 @@ class TestScript(mastertest.MasterTest): def test_reload(self): s = state.State() - m = RecordingMaster(options.Options(), None, s) + m = mastertest.RecordingMaster(options.Options(), None, s) with tutils.tmpdir(): with open("foo.py", "w"): pass @@ -94,7 +85,7 @@ class TestScript(mastertest.MasterTest): def test_exception(self): s = state.State() - m = RecordingMaster(options.Options(), None, s) + m = mastertest.RecordingMaster(options.Options(), None, s) sc = script.Script( tutils.test_data.path("data/addonscripts/error.py") ) diff --git a/test/mitmproxy/data/addonscripts/concurrent_decorator.py b/test/mitmproxy/data/addonscripts/concurrent_decorator.py new file mode 100644 index 00000000..a56c2af1 --- /dev/null +++ b/test/mitmproxy/data/addonscripts/concurrent_decorator.py @@ -0,0 +1,6 @@ +import time +from mitmproxy.script import concurrent + +@concurrent +def request(flow): + time.sleep(0.1) diff --git a/test/mitmproxy/data/addonscripts/concurrent_decorator_err.py b/test/mitmproxy/data/addonscripts/concurrent_decorator_err.py new file mode 100644 index 00000000..756869c8 --- /dev/null +++ b/test/mitmproxy/data/addonscripts/concurrent_decorator_err.py @@ -0,0 +1,6 @@ +from mitmproxy.script import concurrent + + +@concurrent +def start(): + pass diff --git a/test/mitmproxy/data/scripts/concurrent_decorator.py b/test/mitmproxy/data/scripts/concurrent_decorator.py deleted file mode 100644 index 162c00f4..00000000 --- a/test/mitmproxy/data/scripts/concurrent_decorator.py +++ /dev/null @@ -1,7 +0,0 @@ -import time -from mitmproxy.script import concurrent - - -@concurrent -def request(flow): - time.sleep(0.1) diff --git a/test/mitmproxy/data/scripts/concurrent_decorator_err.py b/test/mitmproxy/data/scripts/concurrent_decorator_err.py deleted file mode 100644 index 756869c8..00000000 --- a/test/mitmproxy/data/scripts/concurrent_decorator_err.py +++ /dev/null @@ -1,6 +0,0 @@ -from mitmproxy.script import concurrent - - -@concurrent -def start(): - pass diff --git a/test/mitmproxy/mastertest.py b/test/mitmproxy/mastertest.py index 9754d3a9..240f6a73 100644 --- a/test/mitmproxy/mastertest.py +++ b/test/mitmproxy/mastertest.py @@ -3,6 +3,7 @@ import mock from . import tutils import netlib.tutils +from mitmproxy.flow import master from mitmproxy import flow, proxy, models, controller @@ -39,3 +40,12 @@ class MasterTest: t = tutils.tflow(resp=True) fw.add(t) f.close() + + +class RecordingMaster(master.FlowMaster): + def __init__(self, *args, **kwargs): + master.FlowMaster.__init__(self, *args, **kwargs) + self.event_log = [] + + def add_event(self, e, level): + self.event_log.append((level, e)) diff --git a/test/mitmproxy/script/test_concurrent.py b/test/mitmproxy/script/test_concurrent.py index 57eeca19..d5243bcb 100644 --- a/test/mitmproxy/script/test_concurrent.py +++ b/test/mitmproxy/script/test_concurrent.py @@ -1,28 +1,47 @@ -from mitmproxy.script import Script from test.mitmproxy import tutils from mitmproxy import controller +from mitmproxy.builtins import script +from mitmproxy import options +from mitmproxy.flow import master +from mitmproxy.flow import state import time +from .. import mastertest, tutils class Thing: def __init__(self): self.reply = controller.DummyReply() + self.live = True -@tutils.skip_appveyor -def test_concurrent(): - with Script(tutils.test_data.path("data/scripts/concurrent_decorator.py")) as s: - f1, f2 = Thing(), Thing() - s.run("request", f1) - s.run("request", f2) +class TestConcurrent(mastertest.MasterTest): + @tutils.skip_appveyor + def test_concurrent(self): + s = state.State() + m = master.FlowMaster(options.Options(), None, s) + sc = script.Script( + tutils.test_data.path( + "data/addonscripts/concurrent_decorator.py" + ) + ) + m.addons.add(sc) + f1, f2 = tutils.tflow(), tutils.tflow() + self.invoke(m, "request", f1) + self.invoke(m, "request", f2) start = time.time() while time.time() - start < 5: if f1.reply.acked and f2.reply.acked: return raise ValueError("Script never acked") - -def test_concurrent_err(): - s = Script(tutils.test_data.path("data/scripts/concurrent_decorator_err.py")) - with tutils.raises("Concurrent decorator not supported for 'start' method"): - s.load() + def test_concurrent_err(self): + s = state.State() + m = mastertest.RecordingMaster(options.Options(), None, s) + sc = script.Script( + tutils.test_data.path( + "data/addonscripts/concurrent_decorator_err.py" + ) + ) + with m.handlecontext(): + sc.configure(options.Options()) + assert "decorator not supported" in m.event_log[0][1] -- cgit v1.2.3 From b94f5fd361af6255ad4d3c7a88b9a21868736dea Mon Sep 17 00:00:00 2001 From: Aldo Cortesi Date: Thu, 14 Jul 2016 16:20:27 +1200 Subject: Convert examples and example tests for new-style scripts Remove the test that just loads all the example scripts for now - it's a very low-value test, and we need to think of something better. --- test/mitmproxy/script/test_reloader.py | 34 ----- test/mitmproxy/script/test_script.py | 83 ------------ test/mitmproxy/test_examples.py | 234 ++++++++++++++------------------- 3 files changed, 101 insertions(+), 250 deletions(-) delete mode 100644 test/mitmproxy/script/test_reloader.py delete mode 100644 test/mitmproxy/script/test_script.py (limited to 'test') diff --git a/test/mitmproxy/script/test_reloader.py b/test/mitmproxy/script/test_reloader.py deleted file mode 100644 index e33903b9..00000000 --- a/test/mitmproxy/script/test_reloader.py +++ /dev/null @@ -1,34 +0,0 @@ -import mock -from mitmproxy.script.reloader import watch, unwatch -from test.mitmproxy import tutils -from threading import Event - - -def test_simple(): - with tutils.tmpdir(): - with open("foo.py", "w"): - pass - - script = mock.Mock() - script.path = "foo.py" - - e = Event() - - def _onchange(): - e.set() - - watch(script, _onchange) - with tutils.raises("already observed"): - watch(script, _onchange) - - # Some reloaders don't register a change directly after watching, because they first need to initialize. - # To test if watching works at all, we do repeated writes every 100ms. - for _ in range(100): - with open("foo.py", "a") as f: - f.write(".") - if e.wait(0.1): - break - else: - raise AssertionError("No change detected.") - - unwatch(script) diff --git a/test/mitmproxy/script/test_script.py b/test/mitmproxy/script/test_script.py deleted file mode 100644 index 48fe65c9..00000000 --- a/test/mitmproxy/script/test_script.py +++ /dev/null @@ -1,83 +0,0 @@ -from mitmproxy.script import Script -from mitmproxy.exceptions import ScriptException -from test.mitmproxy import tutils - - -class TestParseCommand: - def test_empty_command(self): - with tutils.raises(ScriptException): - Script.parse_command("") - - with tutils.raises(ScriptException): - 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/scripts/a.py") == ("data/scripts/a.py", []) - assert Script.parse_command("data/scripts/a.py foo bar") == ("data/scripts/a.py", ["foo", "bar"]) - assert Script.parse_command("data/scripts/a.py 'foo bar'") == ("data/scripts/a.py", ["foo bar"]) - - @tutils.skip_not_windows - def test_parse_windows(self): - with tutils.chdir(tutils.test_data.dirname): - assert Script.parse_command("data\\scripts\\a.py") == ("data\\scripts\\a.py", []) - assert Script.parse_command("data\\scripts\\a.py 'foo \\ bar'") == ("data\\scripts\\a.py", ['foo \\ bar']) - - -def test_simple(): - with tutils.chdir(tutils.test_data.path("data/scripts")): - s = Script("a.py --var 42") - assert s.path == "a.py" - assert s.ns is None - - s.load() - assert s.ns["var"] == 42 - - s.run("here") - assert s.ns["var"] == 43 - - s.unload() - assert s.ns is None - - with tutils.raises(ScriptException): - s.run("here") - - with Script("a.py --var 42") as s: - s.run("here") - - -def test_script_exception(): - with tutils.chdir(tutils.test_data.path("data/scripts")): - s = Script("syntaxerr.py") - with tutils.raises(ScriptException): - s.load() - - s = Script("starterr.py") - with tutils.raises(ScriptException): - s.load() - - s = Script("a.py") - s.load() - with tutils.raises(ScriptException): - s.load() - - s = Script("a.py") - with tutils.raises(ScriptException): - s.run("here") - - with tutils.raises(ScriptException): - with Script("reqerr.py") as s: - s.run("request", None) - - s = Script("unloaderr.py") - s.load() - with tutils.raises(ScriptException): - s.unload() diff --git a/test/mitmproxy/test_examples.py b/test/mitmproxy/test_examples.py index bdadcd11..9c8edb29 100644 --- a/test/mitmproxy/test_examples.py +++ b/test/mitmproxy/test_examples.py @@ -1,151 +1,119 @@ -import glob import json -import mock -import os -import sys -from contextlib import contextmanager -from mitmproxy import script +import os.path +from mitmproxy.flow import master +from mitmproxy.flow import state +from mitmproxy import options +from mitmproxy import contentviews +from mitmproxy.builtins import script import netlib.utils from netlib import tutils as netutils from netlib.http import Headers -from . import tutils - -example_dir = netlib.utils.Data(__name__).path("../../examples") - - -@contextmanager -def example(command): - command = os.path.join(example_dir, command) - with script.Script(command) as s: - yield s - - -@mock.patch("mitmproxy.ctx.master") -@mock.patch("mitmproxy.ctx.log") -def test_load_scripts(log, master): - scripts = glob.glob("%s/*.py" % example_dir) - - for f in scripts: - if "har_extractor" in f: - continue - if "flowwriter" in f: - f += " -" - if "iframe_injector" in f: - f += " foo" # one argument required - if "filt" in f: - f += " ~a" - if "modify_response_body" in f: - f += " foo bar" # two arguments required - - s = script.Script(f) - try: - s.load() - except Exception as v: - if "ImportError" not in str(v): - raise - else: - s.unload() - - -def test_add_header(): - flow = tutils.tflow(resp=netutils.tresp()) - with example("add_header.py") as ex: - ex.run("response", flow) - assert flow.response.headers["newheader"] == "foo" - - -@mock.patch("mitmproxy.contentviews.remove") -@mock.patch("mitmproxy.contentviews.add") -def test_custom_contentviews(add, remove): - with example("custom_contentviews.py"): - assert add.called - pig = add.call_args[0][0] - _, fmt = pig(b"test!") - assert any(b'esttay!' in val[0][1] for val in fmt) - assert not pig(b"gobbledygook") - assert remove.called - - -def test_iframe_injector(): - with tutils.raises(script.ScriptException): - with example("iframe_injector.py"): - pass - - flow = tutils.tflow(resp=netutils.tresp(content=b"mitmproxy")) - with example("iframe_injector.py http://example.org/evil_iframe") as ex: - ex.run("response", flow) - content = flow.response.content - assert b'iframe' in content and b'evil_iframe' in content - - -def test_modify_form(): - form_header = Headers(content_type="application/x-www-form-urlencoded") - flow = tutils.tflow(req=netutils.treq(headers=form_header)) - with example("modify_form.py") as ex: - ex.run("request", flow) - assert flow.request.urlencoded_form[b"mitmproxy"] == b"rocks" - - flow.request.headers["content-type"] = "" - ex.run("request", flow) - assert list(flow.request.urlencoded_form.items()) == [(b"foo", b"bar")] +from . import tutils, mastertest +example_dir = netlib.utils.Data(__name__).push("../../examples") -def test_modify_querystring(): - flow = tutils.tflow(req=netutils.treq(path=b"/search?q=term")) - with example("modify_querystring.py") as ex: - ex.run("request", flow) - assert flow.request.query["mitmproxy"] == "rocks" - flow.request.path = "/" - ex.run("request", flow) - assert flow.request.query["mitmproxy"] == "rocks" +class ScriptError(Exception): + pass -def test_modify_response_body(): - with tutils.raises(script.ScriptException): - with example("modify_response_body.py"): - assert True +class RaiseMaster(master.FlowMaster): + def add_event(self, e, level): + if level in ("warn", "error"): + raise ScriptError(e) - flow = tutils.tflow(resp=netutils.tresp(content=b"I <3 mitmproxy")) - with example("modify_response_body.py mitmproxy rocks") as ex: - assert ex.ns["state"]["old"] == b"mitmproxy" and ex.ns["state"]["new"] == b"rocks" - ex.run("response", flow) - assert flow.response.content == b"I <3 rocks" +def tscript(cmd, args=""): + cmd = example_dir.path(cmd) + " " + args + m = RaiseMaster(options.Options(), None, state.State()) + sc = script.Script(cmd) + m.addons.add(sc) + return m, sc -def test_redirect_requests(): - flow = tutils.tflow(req=netutils.treq(host=b"example.org")) - with example("redirect_requests.py") as ex: - ex.run("request", flow) - assert flow.request.host == "mitmproxy.org" +class TestScripts(mastertest.MasterTest): + def test_add_header(self): + m, _ = tscript("add_header.py") + f = tutils.tflow(resp=netutils.tresp()) + self.invoke(m, "response", f) + assert f.response.headers["newheader"] == "foo" -@mock.patch("mitmproxy.ctx.log") -def test_har_extractor(log): - if sys.version_info >= (3, 0): - with tutils.raises("does not work on Python 3"): - with example("har_extractor.py -"): - pass - return + def test_custom_contentviews(self): + m, sc = tscript("custom_contentviews.py") + pig = contentviews.get("pig_latin_HTML") + _, fmt = pig("test!") + assert any('esttay!' in val[0][1] for val in fmt) + assert not pig("gobbledygook") - with tutils.raises(script.ScriptException): - with example("har_extractor.py"): - pass + def test_iframe_injector(self): + with tutils.raises(ScriptError): + tscript("iframe_injector.py") - times = dict( - timestamp_start=746203272, - timestamp_end=746203272, - ) - - flow = tutils.tflow( - req=netutils.treq(**times), - resp=netutils.tresp(**times) - ) - - with example("har_extractor.py -") as ex: - ex.run("response", flow) - - with open(tutils.test_data.path("data/har_extractor.har")) as fp: + m, sc = tscript("iframe_injector.py", "http://example.org/evil_iframe") + flow = tutils.tflow(resp=netutils.tresp(content="mitmproxy")) + self.invoke(m, "response", flow) + content = flow.response.content + assert 'iframe' in content and 'evil_iframe' in content + + def test_modify_form(self): + m, sc = tscript("modify_form.py") + + form_header = Headers(content_type="application/x-www-form-urlencoded") + f = tutils.tflow(req=netutils.treq(headers=form_header)) + self.invoke(m, "request", f) + + assert f.request.urlencoded_form["mitmproxy"] == "rocks" + + f.request.headers["content-type"] = "" + self.invoke(m, "request", f) + assert list(f.request.urlencoded_form.items()) == [("foo", "bar")] + + def test_modify_querystring(self): + m, sc = tscript("modify_querystring.py") + f = tutils.tflow(req=netutils.treq(path="/search?q=term")) + + self.invoke(m, "request", f) + assert f.request.query["mitmproxy"] == "rocks" + + f.request.path = "/" + self.invoke(m, "request", f) + assert f.request.query["mitmproxy"] == "rocks" + + def test_modify_response_body(self): + with tutils.raises(ScriptError): + tscript("modify_response_body.py") + + m, sc = tscript("modify_response_body.py", "mitmproxy rocks") + f = tutils.tflow(resp=netutils.tresp(content="I <3 mitmproxy")) + self.invoke(m, "response", f) + assert f.response.content == "I <3 rocks" + + def test_redirect_requests(self): + m, sc = tscript("redirect_requests.py") + f = tutils.tflow(req=netutils.treq(host="example.org")) + self.invoke(m, "request", f) + assert f.request.host == "mitmproxy.org" + + def test_har_extractor(self): + with tutils.raises(ScriptError): + tscript("har_extractor.py") + + with tutils.tmpdir() as tdir: + times = dict( + timestamp_start=746203272, + timestamp_end=746203272, + ) + + path = os.path.join(tdir, "file") + m, sc = tscript("har_extractor.py", path) + f = tutils.tflow( + req=netutils.treq(**times), + resp=netutils.tresp(**times) + ) + self.invoke(m, "response", f) + m.addons.remove(sc) + + fp = open(path, "rb") test_data = json.load(fp) - assert json.loads(ex.ns["context"].HARLog.json()) == test_data["test_response"] + assert len(test_data["log"]["pages"]) == 1 -- cgit v1.2.3 From deffed2196a8d595624998b9fcc8fa4016b41808 Mon Sep 17 00:00:00 2001 From: Aldo Cortesi Date: Thu, 14 Jul 2016 17:19:33 +1200 Subject: Script cleanup: editing in console, Python3 compatibility fixes --- test/mitmproxy/script/test_concurrent.py | 3 +-- test/mitmproxy/test_examples.py | 24 +++++++++++++++--------- test/mitmproxy/test_server.py | 4 ++-- 3 files changed, 18 insertions(+), 13 deletions(-) (limited to 'test') diff --git a/test/mitmproxy/script/test_concurrent.py b/test/mitmproxy/script/test_concurrent.py index d5243bcb..92d1153b 100644 --- a/test/mitmproxy/script/test_concurrent.py +++ b/test/mitmproxy/script/test_concurrent.py @@ -1,11 +1,10 @@ -from test.mitmproxy import tutils +from test.mitmproxy import tutils, mastertest from mitmproxy import controller from mitmproxy.builtins import script from mitmproxy import options from mitmproxy.flow import master from mitmproxy.flow import state import time -from .. import mastertest, tutils class Thing: diff --git a/test/mitmproxy/test_examples.py b/test/mitmproxy/test_examples.py index 9c8edb29..ef97219c 100644 --- a/test/mitmproxy/test_examples.py +++ b/test/mitmproxy/test_examples.py @@ -1,5 +1,6 @@ import json +import sys import os.path from mitmproxy.flow import master from mitmproxy.flow import state @@ -42,19 +43,19 @@ class TestScripts(mastertest.MasterTest): def test_custom_contentviews(self): m, sc = tscript("custom_contentviews.py") pig = contentviews.get("pig_latin_HTML") - _, fmt = pig("test!") - assert any('esttay!' in val[0][1] for val in fmt) - assert not pig("gobbledygook") + _, fmt = pig(b"test!") + assert any(b'esttay!' in val[0][1] for val in fmt) + assert not pig(b"gobbledygook") def test_iframe_injector(self): with tutils.raises(ScriptError): tscript("iframe_injector.py") m, sc = tscript("iframe_injector.py", "http://example.org/evil_iframe") - flow = tutils.tflow(resp=netutils.tresp(content="mitmproxy")) + flow = tutils.tflow(resp=netutils.tresp(content=b"mitmproxy")) self.invoke(m, "response", flow) content = flow.response.content - assert 'iframe' in content and 'evil_iframe' in content + assert b'iframe' in content and b'evil_iframe' in content def test_modify_form(self): m, sc = tscript("modify_form.py") @@ -63,11 +64,11 @@ class TestScripts(mastertest.MasterTest): f = tutils.tflow(req=netutils.treq(headers=form_header)) self.invoke(m, "request", f) - assert f.request.urlencoded_form["mitmproxy"] == "rocks" + assert f.request.urlencoded_form[b"mitmproxy"] == b"rocks" f.request.headers["content-type"] = "" self.invoke(m, "request", f) - assert list(f.request.urlencoded_form.items()) == [("foo", "bar")] + assert list(f.request.urlencoded_form.items()) == [(b"foo", b"bar")] def test_modify_querystring(self): m, sc = tscript("modify_querystring.py") @@ -85,9 +86,9 @@ class TestScripts(mastertest.MasterTest): tscript("modify_response_body.py") m, sc = tscript("modify_response_body.py", "mitmproxy rocks") - f = tutils.tflow(resp=netutils.tresp(content="I <3 mitmproxy")) + f = tutils.tflow(resp=netutils.tresp(content=b"I <3 mitmproxy")) self.invoke(m, "response", f) - assert f.response.content == "I <3 rocks" + assert f.response.content == b"I <3 rocks" def test_redirect_requests(self): m, sc = tscript("redirect_requests.py") @@ -96,6 +97,11 @@ class TestScripts(mastertest.MasterTest): assert f.request.host == "mitmproxy.org" def test_har_extractor(self): + if sys.version_info >= (3, 0): + with tutils.raises("does not work on Python 3"): + tscript("har_extractor.py") + return + with tutils.raises(ScriptError): tscript("har_extractor.py") diff --git a/test/mitmproxy/test_server.py b/test/mitmproxy/test_server.py index b1ca6910..a5196dae 100644 --- a/test/mitmproxy/test_server.py +++ b/test/mitmproxy/test_server.py @@ -293,7 +293,7 @@ class TestHTTP(tservers.HTTPProxyTest, CommonMixin, AppMixin): ) self.master.addons.add(s) d = self.pathod('200:b"foo"') - assert d.content == "bar" + assert d.content == b"bar" self.master.addons.remove(s) @@ -523,7 +523,7 @@ class TestTransparent(tservers.TransparentProxyTest, CommonMixin, TcpMixin): self._tcpproxy_on() d = self.pathod('200:b"foo"') self._tcpproxy_off() - assert d.content == "bar" + assert d.content == b"bar" self.master.addons.remove(s) -- cgit v1.2.3 From a4127fb6d5f026c015525bab7993bf6f33e16f93 Mon Sep 17 00:00:00 2001 From: Aldo Cortesi Date: Thu, 14 Jul 2016 18:46:07 +1200 Subject: Add a tick event for addons and scripts, and use it for race-free reload --- test/mitmproxy/builtins/test_script.py | 1 + 1 file changed, 1 insertion(+) (limited to 'test') diff --git a/test/mitmproxy/builtins/test_script.py b/test/mitmproxy/builtins/test_script.py index 2447c8ea..394c3f38 100644 --- a/test/mitmproxy/builtins/test_script.py +++ b/test/mitmproxy/builtins/test_script.py @@ -78,6 +78,7 @@ class TestScript(mastertest.MasterTest): 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 -- cgit v1.2.3 From 698af945a49ef34e909f1f5dc1f12552f9e3680b Mon Sep 17 00:00:00 2001 From: Aldo Cortesi Date: Thu, 14 Jul 2016 19:58:12 +1200 Subject: Adjust for new options scheme --- test/mitmproxy/builtins/test_script.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'test') diff --git a/test/mitmproxy/builtins/test_script.py b/test/mitmproxy/builtins/test_script.py index 394c3f38..7c9787f8 100644 --- a/test/mitmproxy/builtins/test_script.py +++ b/test/mitmproxy/builtins/test_script.py @@ -4,7 +4,7 @@ from mitmproxy.builtins import script from mitmproxy import exceptions from mitmproxy.flow import master from mitmproxy.flow import state -from mitmproxy import options +from mitmproxy.flow import options from .. import tutils, mastertest -- cgit v1.2.3 From fcc1416ffd82a3497bf17323b4bb467e7e4435f4 Mon Sep 17 00:00:00 2001 From: Aldo Cortesi Date: Fri, 15 Jul 2016 10:33:51 +1200 Subject: Fix windows parse_args test --- test/mitmproxy/builtins/test_script.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'test') diff --git a/test/mitmproxy/builtins/test_script.py b/test/mitmproxy/builtins/test_script.py index 7c9787f8..5747912d 100644 --- a/test/mitmproxy/builtins/test_script.py +++ b/test/mitmproxy/builtins/test_script.py @@ -35,7 +35,7 @@ class TestParseCommand: def test_parse_windows(self): with tutils.chdir(tutils.test_data.dirname): assert script.parse_command("data\\scripts\\a.py") == ("data\\scripts\\a.py", []) - assert script.parse_command("data\\scripts\\a.py 'foo \\ bar'") == ("data\\scripts\\a.py", 'foo \\ bar', []) + assert script.parse_command("data\\scripts\\a.py 'foo \\ bar'") == ("data\\scripts\\a.py", ['foo \\ bar']) def test_load_script(): -- cgit v1.2.3 From 4ba7ce50c6aa7b96325e201f65747a3a6ace1a7a Mon Sep 17 00:00:00 2001 From: Aldo Cortesi Date: Fri, 15 Jul 2016 13:22:20 +1200 Subject: Add .start for addons and scripts Also improve error messages, fix various unit tests --- test/mitmproxy/builtins/test_script.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'test') diff --git a/test/mitmproxy/builtins/test_script.py b/test/mitmproxy/builtins/test_script.py index 5747912d..2c2568ed 100644 --- a/test/mitmproxy/builtins/test_script.py +++ b/test/mitmproxy/builtins/test_script.py @@ -57,7 +57,10 @@ class TestScript(mastertest.MasterTest): ) ) m.addons.add(sc) - assert sc.ns["call_log"] == [("configure", (options.Options(),), {})] + assert sc.ns["call_log"] == [ + ("start", (), {}), + ("configure", (options.Options(),), {}) + ] sc.ns["call_log"] = [] f = tutils.tflow(resp=True) @@ -93,7 +96,7 @@ class TestScript(mastertest.MasterTest): m.addons.add(sc) f = tutils.tflow(resp=True) self.invoke(m, "request", f) - assert m.event_log[0][0] == "warn" + assert m.event_log[0][0] == "error" def test_duplicate_flow(self): s = state.State() -- cgit v1.2.3 From 92a5076bd01b71e8ed709901d63de9ee37385c3b Mon Sep 17 00:00:00 2001 From: Aldo Cortesi Date: Fri, 15 Jul 2016 14:59:48 +1200 Subject: Adjust concurrent tests for start method --- test/mitmproxy/script/test_concurrent.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'test') diff --git a/test/mitmproxy/script/test_concurrent.py b/test/mitmproxy/script/test_concurrent.py index 92d1153b..080746e8 100644 --- a/test/mitmproxy/script/test_concurrent.py +++ b/test/mitmproxy/script/test_concurrent.py @@ -42,5 +42,5 @@ class TestConcurrent(mastertest.MasterTest): ) ) with m.handlecontext(): - sc.configure(options.Options()) + sc.start() assert "decorator not supported" in m.event_log[0][1] -- cgit v1.2.3 From 917d51bd22ea75408bcf461b09b6cf78c44e1162 Mon Sep 17 00:00:00 2001 From: Aldo Cortesi Date: Fri, 15 Jul 2016 15:01:35 +1200 Subject: Fix HAR extractor Thanks to @mhils --- test/mitmproxy/test_examples.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'test') diff --git a/test/mitmproxy/test_examples.py b/test/mitmproxy/test_examples.py index ef97219c..f8646336 100644 --- a/test/mitmproxy/test_examples.py +++ b/test/mitmproxy/test_examples.py @@ -1,5 +1,6 @@ import json +import six import sys import os.path from mitmproxy.flow import master @@ -112,7 +113,7 @@ class TestScripts(mastertest.MasterTest): ) path = os.path.join(tdir, "file") - m, sc = tscript("har_extractor.py", path) + m, sc = tscript("har_extractor.py", six.moves.shlex_quote(path)) f = tutils.tflow( req=netutils.treq(**times), resp=netutils.tresp(**times) @@ -120,6 +121,6 @@ class TestScripts(mastertest.MasterTest): self.invoke(m, "response", f) m.addons.remove(sc) - fp = open(path, "rb") - test_data = json.load(fp) + with open(path, "rb") as f: + test_data = json.load(f) assert len(test_data["log"]["pages"]) == 1 -- cgit v1.2.3 From c7d0850d8f697915b183f4fafd5ede7df2245569 Mon Sep 17 00:00:00 2001 From: Aldo Cortesi Date: Fri, 15 Jul 2016 16:35:24 +1200 Subject: Script cleanups - Preserve script order on config change - Prohibit script duplicates (i.e. identical script + args) - Various cleanups and tweaks --- test/mitmproxy/builtins/test_script.py | 62 ++++++++++++++++++++++++++-- test/mitmproxy/data/addonscripts/recorder.py | 9 +++- 2 files changed, 67 insertions(+), 4 deletions(-) (limited to 'test') diff --git a/test/mitmproxy/builtins/test_script.py b/test/mitmproxy/builtins/test_script.py index 2c2568ed..da60b64c 100644 --- a/test/mitmproxy/builtins/test_script.py +++ b/test/mitmproxy/builtins/test_script.py @@ -58,8 +58,8 @@ class TestScript(mastertest.MasterTest): ) m.addons.add(sc) assert sc.ns["call_log"] == [ - ("start", (), {}), - ("configure", (options.Options(),), {}) + ("solo", "start", (), {}), + ("solo", "configure", (options.Options(),), {}) ] sc.ns["call_log"] = [] @@ -67,7 +67,7 @@ class TestScript(mastertest.MasterTest): self.invoke(m, "request", f) recf = sc.ns["call_log"][0] - assert recf[0] == "request" + assert recf[1] == "request" def test_reload(self): s = state.State() @@ -129,3 +129,59 @@ class TestScriptLoader(mastertest.MasterTest): assert len(m.addons) == 2 o.update(scripts = []) assert len(m.addons) == 1 + + def test_dupes(self): + s = state.State() + o = options.Options(scripts=["one", "one"]) + m = master.FlowMaster(o, None, s) + sc = script.ScriptLoader() + tutils.raises(exceptions.OptionsError, m.addons.add, sc) + + def test_order(self): + rec = tutils.test_data.path("data/addonscripts/recorder.py") + + s = state.State() + o = options.Options( + scripts = [ + "%s %s" % (rec, "a"), + "%s %s" % (rec, "b"), + "%s %s" % (rec, "c"), + ] + ) + m = mastertest.RecordingMaster(o, None, s) + 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"] + assert debug == [ + ('debug', 'c configure'), + ('debug', 'a configure'), + ('debug', 'b configure'), + ] + m.event_log[:] = [] + + 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/data/addonscripts/recorder.py b/test/mitmproxy/data/addonscripts/recorder.py index 728203e3..b6ac8d89 100644 --- a/test/mitmproxy/data/addonscripts/recorder.py +++ b/test/mitmproxy/data/addonscripts/recorder.py @@ -1,8 +1,14 @@ from mitmproxy import controller from mitmproxy import ctx +import sys call_log = [] +if len(sys.argv) > 1: + name = sys.argv[1] +else: + name = "solo" + # Keep a log of all possible event calls evts = list(controller.Events) + ["configure"] for i in evts: @@ -10,9 +16,10 @@ for i in evts: evt = i def prox(*args, **kwargs): - lg = (evt, 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() -- cgit v1.2.3 From c4fb489a96c58932609cced96d5b0d3c2687f15f Mon Sep 17 00:00:00 2001 From: Aldo Cortesi Date: Fri, 15 Jul 2016 22:35:03 +1200 Subject: Zap unused test scripts --- test/mitmproxy/builtins/test_script.py | 14 +++++++++----- test/mitmproxy/data/scripts/a.py | 20 -------------------- test/mitmproxy/data/scripts/a_helper.py | 4 ---- test/mitmproxy/data/scripts/duplicate_flow.py | 6 ------ test/mitmproxy/data/scripts/loaderr.py | 3 --- test/mitmproxy/data/scripts/reqerr.py | 2 -- test/mitmproxy/data/scripts/starterr.py | 3 --- test/mitmproxy/data/scripts/stream_modify.py | 7 ------- test/mitmproxy/data/scripts/syntaxerr.py | 3 --- test/mitmproxy/data/scripts/tcp_stream_modify.py | 4 ---- test/mitmproxy/data/scripts/unloaderr.py | 2 -- 11 files changed, 9 insertions(+), 59 deletions(-) delete mode 100644 test/mitmproxy/data/scripts/a.py delete mode 100644 test/mitmproxy/data/scripts/a_helper.py delete mode 100644 test/mitmproxy/data/scripts/duplicate_flow.py delete mode 100644 test/mitmproxy/data/scripts/loaderr.py delete mode 100644 test/mitmproxy/data/scripts/reqerr.py delete mode 100644 test/mitmproxy/data/scripts/starterr.py delete mode 100644 test/mitmproxy/data/scripts/stream_modify.py delete mode 100644 test/mitmproxy/data/scripts/syntaxerr.py delete mode 100644 test/mitmproxy/data/scripts/tcp_stream_modify.py delete mode 100644 test/mitmproxy/data/scripts/unloaderr.py (limited to 'test') diff --git a/test/mitmproxy/builtins/test_script.py b/test/mitmproxy/builtins/test_script.py index da60b64c..c9616249 100644 --- a/test/mitmproxy/builtins/test_script.py +++ b/test/mitmproxy/builtins/test_script.py @@ -27,15 +27,19 @@ class TestParseCommand: def test_parse_args(self): with tutils.chdir(tutils.test_data.dirname): - assert script.parse_command("data/scripts/a.py") == ("data/scripts/a.py", []) - assert script.parse_command("data/scripts/a.py foo bar") == ("data/scripts/a.py", ["foo", "bar"]) - assert script.parse_command("data/scripts/a.py 'foo bar'") == ("data/scripts/a.py", ["foo bar"]) + 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\\scripts\\a.py") == ("data\\scripts\\a.py", []) - assert script.parse_command("data\\scripts\\a.py 'foo \\ bar'") == ("data\\scripts\\a.py", ['foo \\ bar']) + 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(): diff --git a/test/mitmproxy/data/scripts/a.py b/test/mitmproxy/data/scripts/a.py deleted file mode 100644 index ab0dbf96..00000000 --- a/test/mitmproxy/data/scripts/a.py +++ /dev/null @@ -1,20 +0,0 @@ -import sys - -from a_helper import parser - -var = 0 - - -def start(): - global var - var = parser.parse_args(sys.argv[1:]).var - - -def here(): - global var - var += 1 - return var - - -def errargs(): - pass diff --git a/test/mitmproxy/data/scripts/a_helper.py b/test/mitmproxy/data/scripts/a_helper.py deleted file mode 100644 index e1f1c649..00000000 --- a/test/mitmproxy/data/scripts/a_helper.py +++ /dev/null @@ -1,4 +0,0 @@ -import argparse - -parser = argparse.ArgumentParser() -parser.add_argument('--var', type=int) diff --git a/test/mitmproxy/data/scripts/duplicate_flow.py b/test/mitmproxy/data/scripts/duplicate_flow.py deleted file mode 100644 index 565b1845..00000000 --- a/test/mitmproxy/data/scripts/duplicate_flow.py +++ /dev/null @@ -1,6 +0,0 @@ -import mitmproxy - - -def request(f): - f = mitmproxy.ctx.master.duplicate_flow(f) - mitmproxy.ctx.master.replay_request(f, block=True, run_scripthooks=False) diff --git a/test/mitmproxy/data/scripts/loaderr.py b/test/mitmproxy/data/scripts/loaderr.py deleted file mode 100644 index 8dc4d56d..00000000 --- a/test/mitmproxy/data/scripts/loaderr.py +++ /dev/null @@ -1,3 +0,0 @@ - - -a = x diff --git a/test/mitmproxy/data/scripts/reqerr.py b/test/mitmproxy/data/scripts/reqerr.py deleted file mode 100644 index 7b419361..00000000 --- a/test/mitmproxy/data/scripts/reqerr.py +++ /dev/null @@ -1,2 +0,0 @@ -def request(r): - raise ValueError() diff --git a/test/mitmproxy/data/scripts/starterr.py b/test/mitmproxy/data/scripts/starterr.py deleted file mode 100644 index 28ba2ff1..00000000 --- a/test/mitmproxy/data/scripts/starterr.py +++ /dev/null @@ -1,3 +0,0 @@ - -def start(): - raise ValueError() diff --git a/test/mitmproxy/data/scripts/stream_modify.py b/test/mitmproxy/data/scripts/stream_modify.py deleted file mode 100644 index 4fbf45c2..00000000 --- a/test/mitmproxy/data/scripts/stream_modify.py +++ /dev/null @@ -1,7 +0,0 @@ -def modify(chunks): - for chunk in chunks: - yield chunk.replace(b"foo", b"bar") - - -def responseheaders(flow): - flow.response.stream = modify diff --git a/test/mitmproxy/data/scripts/syntaxerr.py b/test/mitmproxy/data/scripts/syntaxerr.py deleted file mode 100644 index 219d6b84..00000000 --- a/test/mitmproxy/data/scripts/syntaxerr.py +++ /dev/null @@ -1,3 +0,0 @@ - - -a + diff --git a/test/mitmproxy/data/scripts/tcp_stream_modify.py b/test/mitmproxy/data/scripts/tcp_stream_modify.py deleted file mode 100644 index 2281e6e6..00000000 --- a/test/mitmproxy/data/scripts/tcp_stream_modify.py +++ /dev/null @@ -1,4 +0,0 @@ -def tcp_message(flow): - message = flow.messages[-1] - if not message.from_client: - message.content = message.content.replace(b"foo", b"bar") diff --git a/test/mitmproxy/data/scripts/unloaderr.py b/test/mitmproxy/data/scripts/unloaderr.py deleted file mode 100644 index 6a48ab43..00000000 --- a/test/mitmproxy/data/scripts/unloaderr.py +++ /dev/null @@ -1,2 +0,0 @@ -def done(): - raise RuntimeError() -- cgit v1.2.3 From 5f23d4f5ca49a3f6cfbcfd9f4e444150a25844b0 Mon Sep 17 00:00:00 2001 From: Aldo Cortesi Date: Sat, 16 Jul 2016 10:00:34 +1200 Subject: add_event -> add_log throughout project "Event" is terribly over-loaded in the project, and "log" is straight-forward and self-explanatory. --- test/mitmproxy/mastertest.py | 2 +- test/mitmproxy/test_dump.py | 3 ++- test/mitmproxy/test_examples.py | 2 +- test/mitmproxy/tservers.py | 2 +- 4 files changed, 5 insertions(+), 4 deletions(-) (limited to 'test') diff --git a/test/mitmproxy/mastertest.py b/test/mitmproxy/mastertest.py index 240f6a73..d1fe8cb4 100644 --- a/test/mitmproxy/mastertest.py +++ b/test/mitmproxy/mastertest.py @@ -47,5 +47,5 @@ class RecordingMaster(master.FlowMaster): master.FlowMaster.__init__(self, *args, **kwargs) self.event_log = [] - def add_event(self, e, level): + def add_log(self, e, level): self.event_log.append((level, e)) diff --git a/test/mitmproxy/test_dump.py b/test/mitmproxy/test_dump.py index 201386e3..c94630a9 100644 --- a/test/mitmproxy/test_dump.py +++ b/test/mitmproxy/test_dump.py @@ -235,7 +235,8 @@ class TestDumpMaster(mastertest.MasterTest): ret = self.dummy_cycle( self.mkmaster( None, - scripts=[tutils.test_data.path("data/scripts/all.py")], verbosity=1 + scripts=[tutils.test_data.path("data/scripts/all.py")], + verbosity=2 ), 1, b"", ) diff --git a/test/mitmproxy/test_examples.py b/test/mitmproxy/test_examples.py index f8646336..0ec85f52 100644 --- a/test/mitmproxy/test_examples.py +++ b/test/mitmproxy/test_examples.py @@ -21,7 +21,7 @@ class ScriptError(Exception): class RaiseMaster(master.FlowMaster): - def add_event(self, e, level): + def add_log(self, e, level): if level in ("warn", "error"): raise ScriptError(e) diff --git a/test/mitmproxy/tservers.py b/test/mitmproxy/tservers.py index 69a50b9d..9a66984b 100644 --- a/test/mitmproxy/tservers.py +++ b/test/mitmproxy/tservers.py @@ -42,7 +42,7 @@ class TestMaster(flow.FlowMaster): def clear_log(self): self.tlog = [] - def add_event(self, message, level=None): + def add_log(self, message, level=None): self.tlog.append(message) -- cgit v1.2.3