aboutsummaryrefslogtreecommitdiffstats
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/mitmproxy/addons/test_export.py141
-rw-r--r--test/mitmproxy/addons/test_serverplayback.py34
-rw-r--r--test/mitmproxy/contentviews/test_protobuf.py6
-rw-r--r--test/mitmproxy/contentviews/test_protobuf_data/protobuf01.bin (renamed from test/mitmproxy/contentviews/test_protobuf_data/protobuf01)0
-rw-r--r--test/mitmproxy/contentviews/test_protobuf_data/protobuf02-decoded.bin (renamed from test/mitmproxy/contentviews/test_protobuf_data/protobuf02-decoded)0
-rw-r--r--test/mitmproxy/contentviews/test_protobuf_data/protobuf02.bin (renamed from test/mitmproxy/contentviews/test_protobuf_data/protobuf02)bin213 -> 213 bytes
-rw-r--r--test/mitmproxy/contentviews/test_protobuf_data/protobuf03-decoded.bin (renamed from test/mitmproxy/contentviews/test_protobuf_data/protobuf03-decoded)0
-rw-r--r--test/mitmproxy/contentviews/test_protobuf_data/protobuf03.bin (renamed from test/mitmproxy/contentviews/test_protobuf_data/protobuf03)0
-rw-r--r--test/mitmproxy/data/dumpfile-010.bin (renamed from test/mitmproxy/data/dumpfile-010)bin2140 -> 2140 bytes
-rw-r--r--test/mitmproxy/data/dumpfile-011.bin (renamed from test/mitmproxy/data/dumpfile-011)0
-rw-r--r--test/mitmproxy/data/dumpfile-018.bin (renamed from test/mitmproxy/data/dumpfile-018)0
-rw-r--r--test/mitmproxy/io/test_compat.py6
-rw-r--r--test/mitmproxy/proxy/test_config.py2
-rw-r--r--test/mitmproxy/test_proxy.py15
-rw-r--r--test/release/test_cibuild.py64
15 files changed, 220 insertions, 48 deletions
diff --git a/test/mitmproxy/addons/test_export.py b/test/mitmproxy/addons/test_export.py
index c86e0c7d..b0e5e47e 100644
--- a/test/mitmproxy/addons/test_export.py
+++ b/test/mitmproxy/addons/test_export.py
@@ -1,4 +1,5 @@
import os
+import shlex
import pytest
import pyperclip
@@ -18,6 +19,19 @@ def get_request():
@pytest.fixture
+def get_response():
+ return tflow.tflow(
+ resp=tutils.tresp(status_code=404, content=b"Test Response Body"))
+
+
+@pytest.fixture
+def get_flow():
+ return tflow.tflow(
+ req=tutils.treq(method=b'GET', content=b'', path=b"/path?a=foo&a=bar&b=baz"),
+ resp=tutils.tresp(status_code=404, content=b"Test Response Body"))
+
+
+@pytest.fixture
def post_request():
return tflow.tflow(
req=tutils.treq(method=b'POST', headers=(), content=bytes(range(256))))
@@ -41,51 +55,136 @@ def tcp_flow():
class TestExportCurlCommand:
def test_get(self, get_request):
- result = """curl -H 'header:qvalue' 'http://address:22/path?a=foo&a=bar&b=baz'"""
+ result = """curl -H 'header: qvalue' 'http://address:22/path?a=foo&a=bar&b=baz'"""
assert export.curl_command(get_request) == result
def test_post(self, post_request):
- result = "curl -H 'content-length:256' -X POST 'http://address:22/path' --data-binary '{}'".format(
- str(bytes(range(256)))[2:-1]
- )
+ post_request.request.content = b'nobinarysupport'
+ result = "curl -X POST http://address:22/path -d nobinarysupport"
assert export.curl_command(post_request) == result
+ def test_fails_with_binary_data(self, post_request):
+ # shlex.quote doesn't support a bytes object
+ # see https://github.com/python/cpython/pull/10871
+ post_request.request.headers["Content-Type"] = "application/json; charset=utf-8"
+ with pytest.raises(exceptions.CommandError):
+ export.curl_command(post_request)
+
def test_patch(self, patch_request):
- result = """curl -H 'header:qvalue' -H 'content-length:7' -X PATCH 'http://address:22/path?query=param' --data-binary 'content'"""
+ result = """curl -H 'header: qvalue' -X PATCH 'http://address:22/path?query=param' -d content"""
assert export.curl_command(patch_request) == result
def test_tcp(self, tcp_flow):
with pytest.raises(exceptions.CommandError):
export.curl_command(tcp_flow)
+ def test_escape_single_quotes_in_body(self):
+ request = tflow.tflow(
+ req=tutils.treq(
+ method=b'POST',
+ headers=(),
+ content=b"'&#"
+ )
+ )
+ command = export.curl_command(request)
+ assert shlex.split(command)[-2] == '-d'
+ assert shlex.split(command)[-1] == "'&#"
+
+ def test_strip_unnecessary(self, get_request):
+ get_request.request.headers.clear()
+ get_request.request.headers["host"] = "address"
+ get_request.request.headers[":authority"] = "address"
+ get_request.request.headers["accept-encoding"] = "br"
+ result = """curl --compressed 'http://address:22/path?a=foo&a=bar&b=baz'"""
+ assert export.curl_command(get_request) == result
+
class TestExportHttpieCommand:
def test_get(self, get_request):
- result = """http GET http://address:22/path?a=foo&a=bar&b=baz 'header:qvalue'"""
+ result = """http GET 'http://address:22/path?a=foo&a=bar&b=baz' 'header: qvalue'"""
assert export.httpie_command(get_request) == result
def test_post(self, post_request):
- result = "http POST http://address:22/path 'content-length:256' <<< '{}'".format(
- str(bytes(range(256)))[2:-1]
- )
+ post_request.request.content = b'nobinarysupport'
+ result = "http POST http://address:22/path <<< nobinarysupport"
assert export.httpie_command(post_request) == result
+ def test_fails_with_binary_data(self, post_request):
+ # shlex.quote doesn't support a bytes object
+ # see https://github.com/python/cpython/pull/10871
+ post_request.request.headers["Content-Type"] = "application/json; charset=utf-8"
+ with pytest.raises(exceptions.CommandError):
+ export.httpie_command(post_request)
+
def test_patch(self, patch_request):
- result = """http PATCH http://address:22/path?query=param 'header:qvalue' 'content-length:7' <<< 'content'"""
+ result = """http PATCH 'http://address:22/path?query=param' 'header: qvalue' <<< content"""
assert export.httpie_command(patch_request) == result
def test_tcp(self, tcp_flow):
with pytest.raises(exceptions.CommandError):
export.httpie_command(tcp_flow)
+ def test_escape_single_quotes_in_body(self):
+ request = tflow.tflow(
+ req=tutils.treq(
+ method=b'POST',
+ headers=(),
+ content=b"'&#"
+ )
+ )
+ command = export.httpie_command(request)
+ assert shlex.split(command)[-2] == '<<<'
+ assert shlex.split(command)[-1] == "'&#"
+
class TestRaw:
- def test_get(self, get_request):
+ def test_req_and_resp_present(self, get_flow):
+ assert b"header: qvalue" in export.raw(get_flow)
+ assert b"header-response: svalue" in export.raw(get_flow)
+
+ def test_get_request_present(self, get_request):
assert b"header: qvalue" in export.raw(get_request)
+ def test_get_response_present(self, get_response):
+ delattr(get_response, 'request')
+ assert b"header-response: svalue" in export.raw(get_response)
+
+ def test_missing_both(self, get_request):
+ delattr(get_request, 'request')
+ delattr(get_request, 'response')
+ with pytest.raises(exceptions.CommandError):
+ export.raw(get_request)
+
+ def test_tcp(self, tcp_flow):
+ with pytest.raises(exceptions.CommandError):
+ export.raw_request(tcp_flow)
+
+
+class TestRawRequest:
+ def test_get(self, get_request):
+ assert b"header: qvalue" in export.raw_request(get_request)
+
+ def test_no_request(self, get_response):
+ delattr(get_response, 'request')
+ with pytest.raises(exceptions.CommandError):
+ export.raw_request(get_response)
+
+ def test_tcp(self, tcp_flow):
+ with pytest.raises(exceptions.CommandError):
+ export.raw_request(tcp_flow)
+
+
+class TestRawResponse:
+ def test_get(self, get_response):
+ assert b"header-response: svalue" in export.raw_response(get_response)
+
+ def test_no_response(self, get_request):
+ with pytest.raises(exceptions.CommandError):
+ export.raw_response(get_request)
+
def test_tcp(self, tcp_flow):
with pytest.raises(exceptions.CommandError):
- export.raw(tcp_flow)
+ export.raw_response(tcp_flow)
def qr(f):
@@ -97,11 +196,15 @@ def test_export(tmpdir):
f = str(tmpdir.join("path"))
e = export.Export()
with taddons.context():
- assert e.formats() == ["curl", "httpie", "raw"]
+ assert e.formats() == ["curl", "httpie", "raw", "raw_request", "raw_response"]
with pytest.raises(exceptions.CommandError):
e.file("nonexistent", tflow.tflow(resp=True), f)
- e.file("raw", tflow.tflow(resp=True), f)
+ e.file("raw_request", tflow.tflow(resp=True), f)
+ assert qr(f)
+ os.unlink(f)
+
+ e.file("raw_response", tflow.tflow(resp=True), f)
assert qr(f)
os.unlink(f)
@@ -126,7 +229,7 @@ async def test_export_open(exception, log_message, tmpdir):
with taddons.context() as tctx:
with mock.patch("mitmproxy.addons.export.open") as m:
m.side_effect = exception(log_message)
- e.file("raw", tflow.tflow(resp=True), f)
+ e.file("raw_request", tflow.tflow(resp=True), f)
assert await tctx.master.await_log(log_message, level="error")
@@ -138,7 +241,11 @@ async def test_clip(tmpdir):
e.clip("nonexistent", tflow.tflow(resp=True))
with mock.patch('pyperclip.copy') as pc:
- e.clip("raw", tflow.tflow(resp=True))
+ e.clip("raw_request", tflow.tflow(resp=True))
+ assert pc.called
+
+ with mock.patch('pyperclip.copy') as pc:
+ e.clip("raw_response", tflow.tflow(resp=True))
assert pc.called
with mock.patch('pyperclip.copy') as pc:
@@ -153,5 +260,5 @@ async def test_clip(tmpdir):
log_message = "Pyperclip could not find a " \
"copy/paste mechanism for your system."
pc.side_effect = pyperclip.PyperclipException(log_message)
- e.clip("raw", tflow.tflow(resp=True))
+ e.clip("raw_request", tflow.tflow(resp=True))
assert await tctx.master.await_log(log_message, level="error")
diff --git a/test/mitmproxy/addons/test_serverplayback.py b/test/mitmproxy/addons/test_serverplayback.py
index c6a0c1f4..2e42fa03 100644
--- a/test/mitmproxy/addons/test_serverplayback.py
+++ b/test/mitmproxy/addons/test_serverplayback.py
@@ -1,13 +1,13 @@
import urllib
-import pytest
-from mitmproxy.test import taddons
-from mitmproxy.test import tflow
+import pytest
import mitmproxy.test.tutils
-from mitmproxy.addons import serverplayback
from mitmproxy import exceptions
from mitmproxy import io
+from mitmproxy.addons import serverplayback
+from mitmproxy.test import taddons
+from mitmproxy.test import tflow
def tdump(path, flows):
@@ -321,7 +321,7 @@ def test_server_playback_full():
with taddons.context(s) as tctx:
tctx.configure(
s,
- server_replay_refresh = True,
+ server_replay_refresh=True,
)
f = tflow.tflow()
@@ -345,7 +345,7 @@ def test_server_playback_kill():
with taddons.context(s) as tctx:
tctx.configure(
s,
- server_replay_refresh = True,
+ server_replay_refresh=True,
server_replay_kill_extra=True
)
@@ -357,3 +357,25 @@ def test_server_playback_kill():
f.request.host = "nonexistent"
tctx.cycle(s, f)
assert f.reply.value == exceptions.Kill
+
+
+def test_server_playback_response_deleted():
+ """
+ The server playback addon holds references to flows that can be modified by the user in the meantime.
+ One thing that can happen is that users remove the response object. This happens for example when doing a client
+ replay at the same time.
+ """
+ sp = serverplayback.ServerPlayback()
+ with taddons.context(sp) as tctx:
+ tctx.configure(sp)
+ f1 = tflow.tflow(resp=True)
+ f2 = tflow.tflow(resp=True)
+
+ assert not sp.flowmap
+
+ sp.load_flows([f1, f2])
+ assert sp.flowmap
+
+ f1.response = f2.response = None
+ assert not sp.next_flow(f1)
+ assert not sp.flowmap
diff --git a/test/mitmproxy/contentviews/test_protobuf.py b/test/mitmproxy/contentviews/test_protobuf.py
index 791045e7..f0a91fd1 100644
--- a/test/mitmproxy/contentviews/test_protobuf.py
+++ b/test/mitmproxy/contentviews/test_protobuf.py
@@ -8,7 +8,7 @@ datadir = "mitmproxy/contentviews/test_protobuf_data/"
def test_view_protobuf_request(tdata):
v = full_eval(protobuf.ViewProtobuf())
- p = tdata.path(datadir + "protobuf01")
+ p = tdata.path(datadir + "protobuf01.bin")
with open(p, "rb") as f:
raw = f.read()
@@ -19,12 +19,12 @@ def test_view_protobuf_request(tdata):
v(b'foobar')
-@pytest.mark.parametrize("filename", ["protobuf02", "protobuf03"])
+@pytest.mark.parametrize("filename", ["protobuf02.bin", "protobuf03.bin"])
def test_format_pbuf(filename, tdata):
path = tdata.path(datadir + filename)
with open(path, "rb") as f:
input = f.read()
- with open(path + "-decoded") as f:
+ with open(path.replace(".bin", "-decoded.bin")) as f:
expected = f.read()
assert protobuf.format_pbuf(input) == expected
diff --git a/test/mitmproxy/contentviews/test_protobuf_data/protobuf01 b/test/mitmproxy/contentviews/test_protobuf_data/protobuf01.bin
index fbfdbff3..fbfdbff3 100644
--- a/test/mitmproxy/contentviews/test_protobuf_data/protobuf01
+++ b/test/mitmproxy/contentviews/test_protobuf_data/protobuf01.bin
diff --git a/test/mitmproxy/contentviews/test_protobuf_data/protobuf02-decoded b/test/mitmproxy/contentviews/test_protobuf_data/protobuf02-decoded.bin
index 9be61e28..9be61e28 100644
--- a/test/mitmproxy/contentviews/test_protobuf_data/protobuf02-decoded
+++ b/test/mitmproxy/contentviews/test_protobuf_data/protobuf02-decoded.bin
diff --git a/test/mitmproxy/contentviews/test_protobuf_data/protobuf02 b/test/mitmproxy/contentviews/test_protobuf_data/protobuf02.bin
index a47c45d5..a47c45d5 100644
--- a/test/mitmproxy/contentviews/test_protobuf_data/protobuf02
+++ b/test/mitmproxy/contentviews/test_protobuf_data/protobuf02.bin
Binary files differ
diff --git a/test/mitmproxy/contentviews/test_protobuf_data/protobuf03-decoded b/test/mitmproxy/contentviews/test_protobuf_data/protobuf03-decoded.bin
index 3d3392e1..3d3392e1 100644
--- a/test/mitmproxy/contentviews/test_protobuf_data/protobuf03-decoded
+++ b/test/mitmproxy/contentviews/test_protobuf_data/protobuf03-decoded.bin
diff --git a/test/mitmproxy/contentviews/test_protobuf_data/protobuf03 b/test/mitmproxy/contentviews/test_protobuf_data/protobuf03.bin
index 9fb230b3..9fb230b3 100644
--- a/test/mitmproxy/contentviews/test_protobuf_data/protobuf03
+++ b/test/mitmproxy/contentviews/test_protobuf_data/protobuf03.bin
diff --git a/test/mitmproxy/data/dumpfile-010 b/test/mitmproxy/data/dumpfile-010.bin
index 435795bf..435795bf 100644
--- a/test/mitmproxy/data/dumpfile-010
+++ b/test/mitmproxy/data/dumpfile-010.bin
Binary files differ
diff --git a/test/mitmproxy/data/dumpfile-011 b/test/mitmproxy/data/dumpfile-011.bin
index 936ac0cc..936ac0cc 100644
--- a/test/mitmproxy/data/dumpfile-011
+++ b/test/mitmproxy/data/dumpfile-011.bin
diff --git a/test/mitmproxy/data/dumpfile-018 b/test/mitmproxy/data/dumpfile-018.bin
index 6a27b5a6..6a27b5a6 100644
--- a/test/mitmproxy/data/dumpfile-018
+++ b/test/mitmproxy/data/dumpfile-018.bin
diff --git a/test/mitmproxy/io/test_compat.py b/test/mitmproxy/io/test_compat.py
index 4c31e363..341906ca 100644
--- a/test/mitmproxy/io/test_compat.py
+++ b/test/mitmproxy/io/test_compat.py
@@ -5,7 +5,7 @@ from mitmproxy import exceptions
def test_load(tdata):
- with open(tdata.path("mitmproxy/data/dumpfile-011"), "rb") as f:
+ with open(tdata.path("mitmproxy/data/dumpfile-011.bin"), "rb") as f:
flow_reader = io.FlowReader(f)
flows = list(flow_reader.stream())
assert len(flows) == 1
@@ -13,7 +13,7 @@ def test_load(tdata):
def test_load_018(tdata):
- with open(tdata.path("mitmproxy/data/dumpfile-018"), "rb") as f:
+ with open(tdata.path("mitmproxy/data/dumpfile-018.bin"), "rb") as f:
flow_reader = io.FlowReader(f)
flows = list(flow_reader.stream())
assert len(flows) == 1
@@ -21,7 +21,7 @@ def test_load_018(tdata):
def test_cannot_convert(tdata):
- with open(tdata.path("mitmproxy/data/dumpfile-010"), "rb") as f:
+ with open(tdata.path("mitmproxy/data/dumpfile-010.bin"), "rb") as f:
flow_reader = io.FlowReader(f)
with pytest.raises(exceptions.FlowReadException):
list(flow_reader.stream())
diff --git a/test/mitmproxy/proxy/test_config.py b/test/mitmproxy/proxy/test_config.py
index 1319d1a9..38a6e1ad 100644
--- a/test/mitmproxy/proxy/test_config.py
+++ b/test/mitmproxy/proxy/test_config.py
@@ -14,7 +14,7 @@ class TestProxyConfig:
def test_invalid_certificate(self, tdata):
opts = options.Options()
- opts.certs = [tdata.path("mitmproxy/data/dumpfile-011")]
+ opts.certs = [tdata.path("mitmproxy/data/dumpfile-011.bin")]
with pytest.raises(exceptions.OptionsError, match="Invalid certificate format"):
ProxyConfig(opts)
diff --git a/test/mitmproxy/test_proxy.py b/test/mitmproxy/test_proxy.py
index c8cf6c33..f455b0ff 100644
--- a/test/mitmproxy/test_proxy.py
+++ b/test/mitmproxy/test_proxy.py
@@ -1,20 +1,19 @@
import argparse
import platform
from unittest import mock
+
import pytest
-from mitmproxy.tools import cmdline
-from mitmproxy.tools import main
from mitmproxy import options
from mitmproxy.proxy import ProxyConfig
-from mitmproxy.proxy.server import DummyServer, ProxyServer, ConnectionHandler
from mitmproxy.proxy import config
-
+from mitmproxy.proxy.server import ConnectionHandler, DummyServer, ProxyServer
+from mitmproxy.tools import cmdline
+from mitmproxy.tools import main
from ..conftest import skip_windows
class MockParser(argparse.ArgumentParser):
-
"""
argparse.ArgumentParser sys.exits() by default.
Make it more testable by throwing an exception instead.
@@ -53,11 +52,9 @@ class TestProcessProxyOptions:
class TestProxyServer:
@skip_windows
- @pytest.mark.skipif(platform.mac_ver()[0].split('.')[:2] == ['10', '14'],
- reason='Skipping due to macOS Mojave')
+ @pytest.mark.skipif(platform.system() != "Linux", reason="Linux-only")
def test_err(self):
- # binding to 0.0.0.0:1 works without special permissions on Windows and
- # macOS Mojave
+ # binding to 0.0.0.0:1 works without special permissions on Windows and macOS Mojave+
conf = ProxyConfig(options.Options(listen_port=1))
with pytest.raises(Exception, match="Error starting proxy server"):
ProxyServer(conf)
diff --git a/test/release/test_cibuild.py b/test/release/test_cibuild.py
index cfa24e63..d4ed32b0 100644
--- a/test/release/test_cibuild.py
+++ b/test/release/test_cibuild.py
@@ -58,31 +58,60 @@ def test_buildenviron_pr():
)
assert be.is_pull_request
- # Mini test for appveyor
- be = cibuild.BuildEnviron(
- appveyor_pull_request_number="xxxx",
+
+def test_ci_systems():
+ appveyor = cibuild.BuildEnviron(
+ appveyor_pull_request_number="1234",
+ appveyor_repo_branch="foo",
+ appveyor_repo_tag_name="qux",
)
- assert be.is_pull_request
- assert not be.is_prod_release
- assert not be.is_maintenance_branch
+ assert appveyor.is_pull_request
+ assert appveyor.branch == "foo"
+ assert appveyor.tag == "qux"
+
+ travis = cibuild.BuildEnviron(
+ travis_pull_request="1234",
+ travis_branch="foo",
+ travis_tag="foo",
+ )
+ assert travis.is_pull_request
+ assert travis.branch == "foo"
+ assert travis.tag == "foo"
+
+ github = cibuild.BuildEnviron(
+ github_event_name="pull_request",
+ github_ref="refs/heads/master"
+ )
+ assert github.is_pull_request
+ assert github.branch == "master"
+ assert github.tag == ""
+
+ github2 = cibuild.BuildEnviron(
+ github_event_name="pull_request",
+ github_ref="refs/tags/qux"
+ )
+ assert github2.is_pull_request
+ assert github2.branch == ""
+ assert github2.tag == "qux"
def test_buildenviron_commit():
# Simulates an ordinary commit on the master branch.
be = cibuild.BuildEnviron(
- travis_tag="",
- travis_branch="master",
- travis_pull_request="false",
+ github_ref="refs/heads/master",
+ github_event_name="push",
should_build_wheel=True,
should_build_pyinstaller=True,
should_build_docker=True,
docker_username="foo",
docker_password="bar",
+ has_aws_creds=True,
)
assert be.docker_tag == "mitmproxy/mitmproxy:dev"
assert be.should_upload_docker
assert not be.should_upload_pypi
assert be.should_upload_docker
+ assert be.should_upload_aws
assert not be.is_prod_release
assert not be.is_maintenance_branch
@@ -244,3 +273,20 @@ def test_buildenviron_check_version(version, tag, ok, tmpdir):
else:
with pytest.raises(ValueError):
be.check_version()
+
+
+def test_bool_from_env(monkeypatch):
+ monkeypatch.setenv("FOO", "1")
+ assert cibuild.bool_from_env("FOO")
+
+ monkeypatch.setenv("FOO", "0")
+ assert not cibuild.bool_from_env("FOO")
+
+ monkeypatch.setenv("FOO", "false")
+ assert not cibuild.bool_from_env("FOO")
+
+ monkeypatch.setenv("FOO", "")
+ assert not cibuild.bool_from_env("FOO")
+
+ monkeypatch.delenv("FOO")
+ assert not cibuild.bool_from_env("FOO")