diff options
Diffstat (limited to 'test')
-rw-r--r-- | test/conftest.py | 124 | ||||
-rw-r--r-- | test/filename_matching.py | 57 | ||||
-rw-r--r-- | test/full_coverage_plugin.py | 121 | ||||
-rw-r--r-- | test/helper_tools/1024example (renamed from test/mitmproxy/tools/1024example) | 0 | ||||
-rw-r--r-- | test/helper_tools/ab.exe (renamed from test/mitmproxy/tools/ab.exe) | bin | 82944 -> 82944 bytes | |||
-rw-r--r-- | test/helper_tools/bench.py (renamed from test/mitmproxy/tools/bench.py) | 0 | ||||
-rw-r--r-- | test/helper_tools/benchtool.py (renamed from test/mitmproxy/tools/benchtool.py) | 0 | ||||
-rwxr-xr-x | test/helper_tools/dumperview.py (renamed from test/mitmproxy/addons/dumperview.py) | 0 | ||||
-rw-r--r-- | test/helper_tools/getcert (renamed from test/mitmproxy/tools/getcert) | 0 | ||||
-rw-r--r-- | test/helper_tools/inspect_dumpfile.py (renamed from test/mitmproxy/tools/inspect_dumpfile.py) | 0 | ||||
-rw-r--r-- | test/helper_tools/memoryleak.py (renamed from test/mitmproxy/tools/memoryleak.py) | 0 | ||||
-rw-r--r-- | test/helper_tools/passive_close.py (renamed from test/mitmproxy/tools/passive_close.py) | 0 | ||||
-rw-r--r-- | test/helper_tools/testpatt (renamed from test/mitmproxy/tools/testpatt) | 0 | ||||
-rw-r--r-- | test/individual_coverage.py | 82 | ||||
-rw-r--r-- | test/mitmproxy/__init__.py | 1 | ||||
-rw-r--r-- | test/mitmproxy/addons/onboardingapp/test_app.py | 1 | ||||
-rw-r--r-- | test/mitmproxy/addons/test_eventstore.py (renamed from test/mitmproxy/addons/test_evenstore.py) | 0 | ||||
-rw-r--r-- | test/mitmproxy/addons/test_proxyauth.py | 50 | ||||
-rw-r--r-- | test/mitmproxy/contentviews/image/__init__.py (renamed from test/mitmproxy/console/__init__.py) | 0 | ||||
-rw-r--r-- | test/mitmproxy/contentviews/image/test_image_parser.py (renamed from test/mitmproxy/contentviews/test_image_parser.py) | 6 | ||||
-rw-r--r-- | test/mitmproxy/contentviews/image/test_view.py (renamed from test/mitmproxy/contentviews/test_image.py) | 10 | ||||
-rw-r--r-- | test/mitmproxy/contentviews/test_auto.py | 12 | ||||
-rw-r--r-- | test/mitmproxy/contentviews/test_base.py | 1 | ||||
-rw-r--r-- | test/mitmproxy/contentviews/test_protobuf.py | 52 | ||||
-rw-r--r-- | test/mitmproxy/contentviews/test_wbxml.py | 1 | ||||
-rw-r--r-- | test/mitmproxy/contrib/test_tnetstring.py (renamed from test/mitmproxy/test_contrib_tnetstring.py) | 0 | ||||
-rw-r--r-- | test/mitmproxy/mock_urwid.py | 11 | ||||
-rw-r--r-- | test/mitmproxy/net/http/test_request.py | 47 | ||||
-rw-r--r-- | test/mitmproxy/net/http/test_url.py | 20 | ||||
-rw-r--r-- | test/mitmproxy/platform/test_pf.py (renamed from test/mitmproxy/test_platform_pf.py) | 0 | ||||
-rw-r--r-- | test/mitmproxy/proxy/__init__.py (renamed from test/mitmproxy/protocol/__init__.py) | 0 | ||||
-rw-r--r-- | test/mitmproxy/proxy/modes/test_http_proxy.py | 1 | ||||
-rw-r--r-- | test/mitmproxy/proxy/modes/test_reverse_proxy.py | 1 | ||||
-rw-r--r-- | test/mitmproxy/proxy/modes/test_socks_proxy.py | 1 | ||||
-rw-r--r-- | test/mitmproxy/proxy/modes/test_transparent_proxy.py | 1 | ||||
-rw-r--r-- | test/mitmproxy/proxy/protocol/__init__.py | 0 | ||||
-rw-r--r-- | test/mitmproxy/proxy/protocol/test_base.py | 1 | ||||
-rw-r--r-- | test/mitmproxy/proxy/protocol/test_http.py | 1 | ||||
-rw-r--r-- | test/mitmproxy/proxy/protocol/test_http1.py (renamed from test/mitmproxy/protocol/test_http1.py) | 2 | ||||
-rw-r--r-- | test/mitmproxy/proxy/protocol/test_http2.py (renamed from test/mitmproxy/protocol/test_http2.py) | 150 | ||||
-rw-r--r-- | test/mitmproxy/proxy/protocol/test_http_replay.py | 1 | ||||
-rw-r--r-- | test/mitmproxy/proxy/protocol/test_rawtcp.py | 1 | ||||
-rw-r--r-- | test/mitmproxy/proxy/protocol/test_tls.py (renamed from test/mitmproxy/protocol/test_tls.py) | 0 | ||||
-rw-r--r-- | test/mitmproxy/proxy/protocol/test_websocket.py (renamed from test/mitmproxy/protocol/test_websocket.py) | 10 | ||||
-rw-r--r-- | test/mitmproxy/proxy/test_config.py (renamed from test/mitmproxy/test_proxy_config.py) | 0 | ||||
-rw-r--r-- | test/mitmproxy/proxy/test_root_context.py | 1 | ||||
-rw-r--r-- | test/mitmproxy/proxy/test_server.py (renamed from test/mitmproxy/test_server.py) | 4 | ||||
-rw-r--r-- | test/mitmproxy/test_connections.py | 1 | ||||
-rw-r--r-- | test/mitmproxy/test_ctx.py | 1 | ||||
-rw-r--r-- | test/mitmproxy/test_exceptions.py | 1 | ||||
-rw-r--r-- | test/mitmproxy/test_export.py (renamed from test/mitmproxy/test_flow_export.py) | 0 | ||||
-rw-r--r-- | test/mitmproxy/test_flow.py | 112 | ||||
-rw-r--r-- | test/mitmproxy/test_http.py | 1 | ||||
-rw-r--r-- | test/mitmproxy/test_io.py | 1 | ||||
-rw-r--r-- | test/mitmproxy/test_io_compat.py (renamed from test/mitmproxy/test_flow_format_compat.py) | 0 | ||||
-rw-r--r-- | test/mitmproxy/test_log.py | 1 | ||||
-rw-r--r-- | test/mitmproxy/test_master.py | 1 | ||||
-rw-r--r-- | test/mitmproxy/test_options.py | 1 | ||||
-rw-r--r-- | test/mitmproxy/test_tcp.py | 59 | ||||
-rw-r--r-- | test/mitmproxy/test_websocket.py | 62 | ||||
-rw-r--r-- | test/mitmproxy/tools/__init__.py | 0 | ||||
-rw-r--r-- | test/mitmproxy/tools/console/__init__.py | 0 | ||||
-rw-r--r-- | test/mitmproxy/tools/console/test_common.py (renamed from test/mitmproxy/console/test_common.py) | 2 | ||||
-rw-r--r-- | test/mitmproxy/tools/console/test_help.py (renamed from test/mitmproxy/console/test_help.py) | 2 | ||||
-rw-r--r-- | test/mitmproxy/tools/console/test_master.py (renamed from test/mitmproxy/console/test_master.py) | 10 | ||||
-rw-r--r-- | test/mitmproxy/tools/console/test_palettes.py (renamed from test/mitmproxy/console/test_palettes.py) | 2 | ||||
-rw-r--r-- | test/mitmproxy/tools/console/test_pathedit.py (renamed from test/mitmproxy/console/test_pathedit.py) | 0 | ||||
-rw-r--r-- | test/mitmproxy/tools/test_cmdline.py (renamed from test/mitmproxy/test_cmdline.py) | 0 | ||||
-rw-r--r-- | test/mitmproxy/tools/test_dump.py (renamed from test/mitmproxy/test_tools_dump.py) | 2 | ||||
-rw-r--r-- | test/mitmproxy/tools/web/__init__.py | 0 | ||||
-rw-r--r-- | test/mitmproxy/tools/web/test_app.py (renamed from test/mitmproxy/test_web_app.py) | 0 | ||||
-rw-r--r-- | test/mitmproxy/tools/web/test_master.py (renamed from test/mitmproxy/test_web_master.py) | 2 | ||||
-rw-r--r-- | test/mitmproxy/utils/test_bits.py | 1 | ||||
-rw-r--r-- | test/mitmproxy/utils/test_debug.py | 11 | ||||
-rw-r--r-- | test/pathod/language/__init__.py | 0 | ||||
-rw-r--r-- | test/pathod/language/test_actions.py (renamed from test/pathod/test_language_actions.py) | 0 | ||||
-rw-r--r-- | test/pathod/language/test_base.py (renamed from test/pathod/test_language_base.py) | 0 | ||||
-rw-r--r-- | test/pathod/language/test_exceptions.py | 1 | ||||
-rw-r--r-- | test/pathod/language/test_generators.py (renamed from test/pathod/test_language_generators.py) | 0 | ||||
-rw-r--r-- | test/pathod/language/test_http.py (renamed from test/pathod/test_language_http.py) | 2 | ||||
-rw-r--r-- | test/pathod/language/test_http2.py (renamed from test/pathod/test_language_http2.py) | 0 | ||||
-rw-r--r-- | test/pathod/language/test_message.py | 1 | ||||
-rw-r--r-- | test/pathod/language/test_websockets.py (renamed from test/pathod/test_language_websocket.py) | 2 | ||||
-rw-r--r-- | test/pathod/language/test_writer.py (renamed from test/pathod/test_language_writer.py) | 0 | ||||
-rw-r--r-- | test/pathod/protocols/__init__.py | 0 | ||||
-rw-r--r-- | test/pathod/protocols/test_http.py | 1 | ||||
-rw-r--r-- | test/pathod/protocols/test_http2.py (renamed from test/pathod/test_protocols_http2.py) | 4 | ||||
-rw-r--r-- | test/pathod/protocols/test_websockets.py | 1 |
88 files changed, 677 insertions, 379 deletions
diff --git a/test/conftest.py b/test/conftest.py index 83823a19..b4e1da93 100644 --- a/test/conftest.py +++ b/test/conftest.py @@ -6,6 +6,7 @@ from contextlib import contextmanager import mitmproxy.net.tcp +pytest_plugins = ('test.full_coverage_plugin',) requires_alpn = pytest.mark.skipif( not mitmproxy.net.tcp.HAS_ALPN, @@ -27,10 +28,17 @@ skip_appveyor = pytest.mark.skipif( ) -original_pytest_raises = pytest.raises +@pytest.fixture() +def disable_alpn(monkeypatch): + monkeypatch.setattr(mitmproxy.net.tcp, 'HAS_ALPN', False) + monkeypatch.setattr(OpenSSL.SSL._lib, 'Cryptography_HAS_ALPN', False) +################################################################################ # TODO: remove this wrapper when pytest 3.1.0 is released +original_pytest_raises = pytest.raises + + @contextmanager @functools.wraps(original_pytest_raises) def raises(exc, *args, **kwargs): @@ -41,116 +49,4 @@ def raises(exc, *args, **kwargs): pytest.raises = raises - - -@pytest.fixture() -def disable_alpn(monkeypatch): - monkeypatch.setattr(mitmproxy.net.tcp, 'HAS_ALPN', False) - monkeypatch.setattr(OpenSSL.SSL._lib, 'Cryptography_HAS_ALPN', False) - - -enable_coverage = False -coverage_values = [] -coverage_passed = False - - -def pytest_addoption(parser): - parser.addoption('--full-cov', - action='append', - dest='full_cov', - default=[], - help="Require full test coverage of 100%% for this module/path/filename (multi-allowed). Default: none") - - parser.addoption('--no-full-cov', - action='append', - dest='no_full_cov', - default=[], - help="Exclude file from a parent 100%% coverage requirement (multi-allowed). Default: none") - - -def pytest_configure(config): - global enable_coverage - enable_coverage = ( - len(config.getoption('file_or_dir')) == 0 and - len(config.getoption('full_cov')) > 0 and - config.pluginmanager.getplugin("_cov") is not None and - config.pluginmanager.getplugin("_cov").cov_controller is not None and - config.pluginmanager.getplugin("_cov").cov_controller.cov is not None - ) - - -@pytest.hookimpl(hookwrapper=True) -def pytest_runtestloop(session): - global enable_coverage - global coverage_values - global coverage_passed - - if not enable_coverage: - yield - return - - cov = pytest.config.pluginmanager.getplugin("_cov").cov_controller.cov - - if os.name == 'nt': - cov.exclude('pragma: windows no cover') - - yield - - coverage_values = dict([(name, 0) for name in pytest.config.option.full_cov]) - - prefix = os.getcwd() - excluded_files = [os.path.normpath(f) for f in pytest.config.option.no_full_cov] - measured_files = [os.path.normpath(os.path.relpath(f, prefix)) for f in cov.get_data().measured_files()] - measured_files = [f for f in measured_files if not any(f.startswith(excluded_f) for excluded_f in excluded_files)] - - for name in coverage_values.keys(): - files = [f for f in measured_files if f.startswith(os.path.normpath(name))] - try: - with open(os.devnull, 'w') as null: - overall = cov.report(files, ignore_errors=True, file=null) - singles = [(s, cov.report(s, ignore_errors=True, file=null)) for s in files] - coverage_values[name] = (overall, singles) - except: - pass - - if any(v < 100 for v, _ in coverage_values.values()): - # make sure we get the EXIT_TESTSFAILED exit code - session.testsfailed += 1 - else: - coverage_passed = True - - -def pytest_terminal_summary(terminalreporter, exitstatus): - global enable_coverage - global coverage_values - global coverage_passed - - if not enable_coverage: - return - - terminalreporter.write('\n') - if not coverage_passed: - markup = {'red': True, 'bold': True} - msg = "FAIL: Full test coverage not reached!\n" - terminalreporter.write(msg, **markup) - - for name in sorted(coverage_values.keys()): - msg = 'Coverage for {}: {:.2f}%\n'.format(name, coverage_values[name][0]) - if coverage_values[name][0] < 100: - markup = {'red': True, 'bold': True} - for s, v in sorted(coverage_values[name][1]): - if v < 100: - msg += ' {}: {:.2f}%\n'.format(s, v) - else: - markup = {'green': True} - terminalreporter.write(msg, **markup) - else: - markup = {'green': True} - msg = 'SUCCESS: Full test coverage reached in modules and files:\n' - msg += '{}\n\n'.format('\n'.join(pytest.config.option.full_cov)) - terminalreporter.write(msg, **markup) - - msg = '\nExcluded files:\n' - for s in sorted(pytest.config.option.no_full_cov): - msg += " {}\n".format(s) - terminalreporter.write(msg) +################################################################################ diff --git a/test/filename_matching.py b/test/filename_matching.py new file mode 100644 index 00000000..51cedf03 --- /dev/null +++ b/test/filename_matching.py @@ -0,0 +1,57 @@ +import os +import re +import glob +import sys + + +def check_src_files_have_test(): + missing_test_files = [] + + excluded = ['mitmproxy/contrib/', 'mitmproxy/test/', 'mitmproxy/tools/', 'mitmproxy/platform/'] + src_files = glob.glob('mitmproxy/**/*.py', recursive=True) + glob.glob('pathod/**/*.py', recursive=True) + src_files = [f for f in src_files if os.path.basename(f) != '__init__.py'] + src_files = [f for f in src_files if not any(os.path.normpath(p) in f for p in excluded)] + for f in src_files: + p = os.path.join("test", os.path.dirname(f), "test_" + os.path.basename(f)) + if not os.path.isfile(p): + missing_test_files.append((f, p)) + + return missing_test_files + + +def check_test_files_have_src(): + unknown_test_files = [] + + excluded = ['test/mitmproxy/data/', 'test/mitmproxy/net/data/', '/tservers.py'] + test_files = glob.glob('test/mitmproxy/**/*.py', recursive=True) + glob.glob('test/pathod/**/*.py', recursive=True) + test_files = [f for f in test_files if os.path.basename(f) != '__init__.py'] + test_files = [f for f in test_files if not any(os.path.normpath(p) in f for p in excluded)] + for f in test_files: + p = os.path.join(re.sub('^test/', '', os.path.dirname(f)), re.sub('^test_', '', os.path.basename(f))) + if not os.path.isfile(p): + unknown_test_files.append((f, p)) + + return unknown_test_files + + +def main(): + exitcode = 0 + + missing_test_files = check_src_files_have_test() + if missing_test_files: + exitcode += 1 + for f, p in sorted(missing_test_files): + print("{} MUST have a matching test file: {}".format(f, p)) + + unknown_test_files = check_test_files_have_src() + if unknown_test_files: + # TODO: enable this in the future + # exitcode += 1 + for f, p in sorted(unknown_test_files): + print("{} DOES NOT MATCH a source file! Expected to find: {}".format(f, p)) + + sys.exit(exitcode) + + +if __name__ == '__main__': + main() diff --git a/test/full_coverage_plugin.py b/test/full_coverage_plugin.py new file mode 100644 index 00000000..d98c29d6 --- /dev/null +++ b/test/full_coverage_plugin.py @@ -0,0 +1,121 @@ +import os +import configparser +import pytest + +here = os.path.abspath(os.path.dirname(__file__)) + + +enable_coverage = False +coverage_values = [] +coverage_passed = True +no_full_cov = [] + + +def pytest_addoption(parser): + parser.addoption('--full-cov', + action='append', + dest='full_cov', + default=[], + help="Require full test coverage of 100%% for this module/path/filename (multi-allowed). Default: none") + + parser.addoption('--no-full-cov', + action='append', + dest='no_full_cov', + default=[], + help="Exclude file from a parent 100%% coverage requirement (multi-allowed). Default: none") + + +def pytest_configure(config): + global enable_coverage + global no_full_cov + + enable_coverage = ( + len(config.getoption('file_or_dir')) == 0 and + len(config.getoption('full_cov')) > 0 and + config.pluginmanager.getplugin("_cov") is not None and + config.pluginmanager.getplugin("_cov").cov_controller is not None and + config.pluginmanager.getplugin("_cov").cov_controller.cov is not None + ) + + c = configparser.ConfigParser() + c.read(os.path.join(here, "..", "setup.cfg")) + fs = c['tool:full_coverage']['exclude'].split('\n') + no_full_cov = config.option.no_full_cov + [f.strip() for f in fs] + + +@pytest.hookimpl(hookwrapper=True) +def pytest_runtestloop(session): + global enable_coverage + global coverage_values + global coverage_passed + global no_full_cov + + if not enable_coverage: + yield + return + + cov = pytest.config.pluginmanager.getplugin("_cov").cov_controller.cov + + if os.name == 'nt': + cov.exclude('pragma: windows no cover') + + yield + + coverage_values = dict([(name, 0) for name in pytest.config.option.full_cov]) + + prefix = os.getcwd() + + excluded_files = [os.path.normpath(f) for f in no_full_cov] + measured_files = [os.path.normpath(os.path.relpath(f, prefix)) for f in cov.get_data().measured_files()] + measured_files = [f for f in measured_files if not any(f.startswith(excluded_f) for excluded_f in excluded_files)] + + for name in coverage_values.keys(): + files = [f for f in measured_files if f.startswith(os.path.normpath(name))] + try: + with open(os.devnull, 'w') as null: + overall = cov.report(files, ignore_errors=True, file=null) + singles = [(s, cov.report(s, ignore_errors=True, file=null)) for s in files] + coverage_values[name] = (overall, singles) + except: + pass + + if any(v < 100 for v, _ in coverage_values.values()): + # make sure we get the EXIT_TESTSFAILED exit code + session.testsfailed += 1 + coverage_passed = False + + +def pytest_terminal_summary(terminalreporter, exitstatus): + global enable_coverage + global coverage_values + global coverage_passed + global no_full_cov + + if not enable_coverage: + return + + terminalreporter.write('\n') + if not coverage_passed: + markup = {'red': True, 'bold': True} + msg = "FAIL: Full test coverage not reached!\n" + terminalreporter.write(msg, **markup) + + for name in sorted(coverage_values.keys()): + msg = 'Coverage for {}: {:.2f}%\n'.format(name, coverage_values[name][0]) + if coverage_values[name][0] < 100: + markup = {'red': True, 'bold': True} + for s, v in sorted(coverage_values[name][1]): + if v < 100: + msg += ' {}: {:.2f}%\n'.format(s, v) + else: + markup = {'green': True} + terminalreporter.write(msg, **markup) + else: + msg = 'SUCCESS: Full test coverage reached in modules and files:\n' + msg += '{}\n\n'.format('\n'.join(pytest.config.option.full_cov)) + terminalreporter.write(msg, green=True) + + msg = '\nExcluded files:\n' + for s in sorted(no_full_cov): + msg += " {}\n".format(s) + terminalreporter.write(msg) diff --git a/test/mitmproxy/tools/1024example b/test/helper_tools/1024example index 78af7ed0..78af7ed0 100644 --- a/test/mitmproxy/tools/1024example +++ b/test/helper_tools/1024example diff --git a/test/mitmproxy/tools/ab.exe b/test/helper_tools/ab.exe Binary files differindex d68ed0f3..d68ed0f3 100644 --- a/test/mitmproxy/tools/ab.exe +++ b/test/helper_tools/ab.exe diff --git a/test/mitmproxy/tools/bench.py b/test/helper_tools/bench.py index fb75ef46..fb75ef46 100644 --- a/test/mitmproxy/tools/bench.py +++ b/test/helper_tools/bench.py diff --git a/test/mitmproxy/tools/benchtool.py b/test/helper_tools/benchtool.py index b9078d0e..b9078d0e 100644 --- a/test/mitmproxy/tools/benchtool.py +++ b/test/helper_tools/benchtool.py diff --git a/test/mitmproxy/addons/dumperview.py b/test/helper_tools/dumperview.py index be56fe14..be56fe14 100755 --- a/test/mitmproxy/addons/dumperview.py +++ b/test/helper_tools/dumperview.py diff --git a/test/mitmproxy/tools/getcert b/test/helper_tools/getcert index 43ebf11d..43ebf11d 100644 --- a/test/mitmproxy/tools/getcert +++ b/test/helper_tools/getcert diff --git a/test/mitmproxy/tools/inspect_dumpfile.py b/test/helper_tools/inspect_dumpfile.py index b2201f40..b2201f40 100644 --- a/test/mitmproxy/tools/inspect_dumpfile.py +++ b/test/helper_tools/inspect_dumpfile.py diff --git a/test/mitmproxy/tools/memoryleak.py b/test/helper_tools/memoryleak.py index c03230da..c03230da 100644 --- a/test/mitmproxy/tools/memoryleak.py +++ b/test/helper_tools/memoryleak.py diff --git a/test/mitmproxy/tools/passive_close.py b/test/helper_tools/passive_close.py index 6f97ea4f..6f97ea4f 100644 --- a/test/mitmproxy/tools/passive_close.py +++ b/test/helper_tools/passive_close.py diff --git a/test/mitmproxy/tools/testpatt b/test/helper_tools/testpatt index b41011c0..b41011c0 100644 --- a/test/mitmproxy/tools/testpatt +++ b/test/helper_tools/testpatt diff --git a/test/individual_coverage.py b/test/individual_coverage.py new file mode 100644 index 00000000..35bcd27f --- /dev/null +++ b/test/individual_coverage.py @@ -0,0 +1,82 @@ +import io +import contextlib +import os +import sys +import glob +import multiprocessing +import configparser +import itertools +import pytest + + +def run_tests(src, test, fail): + stderr = io.StringIO() + stdout = io.StringIO() + with contextlib.redirect_stderr(stderr): + with contextlib.redirect_stdout(stdout): + e = pytest.main([ + '-qq', + '--disable-pytest-warnings', + '--no-faulthandler', + '--cov', src.replace('.py', '').replace('/', '.'), + '--cov-fail-under', '100', + '--cov-report', 'term-missing:skip-covered', + test + ]) + + if e == 0: + if fail: + print("SUCCESS but should have FAILED:", src, "Please remove this file from setup.cfg tool:individual_coverage/exclude.") + e = 42 + else: + print("SUCCESS:", src) + else: + if fail: + print("Ignoring fail:", src) + e = 0 + else: + cov = [l for l in stdout.getvalue().split("\n") if (src in l) or ("was never imported" in l)] + if len(cov) == 1: + print("FAIL:", cov[0]) + else: + print("FAIL:", src, test, stdout.getvalue(), stdout.getvalue()) + print(stderr.getvalue()) + print(stdout.getvalue()) + + sys.exit(e) + + +def start_pytest(src, test, fail): + # run pytest in a new process, otherwise imports and modules might conflict + proc = multiprocessing.Process(target=run_tests, args=(src, test, fail)) + proc.start() + proc.join() + return (src, test, proc.exitcode) + + +def main(): + c = configparser.ConfigParser() + c.read('setup.cfg') + fs = c['tool:individual_coverage']['exclude'].strip().split('\n') + no_individual_cov = [f.strip() for f in fs] + + excluded = ['mitmproxy/contrib/', 'mitmproxy/test/', 'mitmproxy/tools/', 'mitmproxy/platform/'] + src_files = glob.glob('mitmproxy/**/*.py', recursive=True) + glob.glob('pathod/**/*.py', recursive=True) + src_files = [f for f in src_files if os.path.basename(f) != '__init__.py'] + src_files = [f for f in src_files if not any(os.path.normpath(p) in f for p in excluded)] + + ps = [] + for src in sorted(src_files): + test = os.path.join("test", os.path.dirname(src), "test_" + os.path.basename(src)) + if os.path.isfile(test): + ps.append((src, test, src in no_individual_cov)) + + result = list(itertools.starmap(start_pytest, ps)) + + if any(e != 0 for _, _, e in result): + sys.exit(1) + pass + + +if __name__ == '__main__': + main() diff --git a/test/mitmproxy/__init__.py b/test/mitmproxy/__init__.py index 28dc133f..6f114e18 100644 --- a/test/mitmproxy/__init__.py +++ b/test/mitmproxy/__init__.py @@ -3,5 +3,4 @@ import logging logging.getLogger("hyper").setLevel(logging.WARNING) logging.getLogger("requests").setLevel(logging.WARNING) logging.getLogger("passlib").setLevel(logging.WARNING) -logging.getLogger("PIL").setLevel(logging.WARNING) logging.getLogger("tornado").setLevel(logging.WARNING) diff --git a/test/mitmproxy/addons/onboardingapp/test_app.py b/test/mitmproxy/addons/onboardingapp/test_app.py new file mode 100644 index 00000000..777ab4dd --- /dev/null +++ b/test/mitmproxy/addons/onboardingapp/test_app.py @@ -0,0 +1 @@ +# TODO: write tests diff --git a/test/mitmproxy/addons/test_evenstore.py b/test/mitmproxy/addons/test_eventstore.py index f54b9980..f54b9980 100644 --- a/test/mitmproxy/addons/test_evenstore.py +++ b/test/mitmproxy/addons/test_eventstore.py diff --git a/test/mitmproxy/addons/test_proxyauth.py b/test/mitmproxy/addons/test_proxyauth.py index b59b87c1..dd5829ab 100644 --- a/test/mitmproxy/addons/test_proxyauth.py +++ b/test/mitmproxy/addons/test_proxyauth.py @@ -1,21 +1,27 @@ import binascii + import pytest from mitmproxy import exceptions +from mitmproxy.addons import proxyauth from mitmproxy.test import taddons from mitmproxy.test import tflow from mitmproxy.test import tutils -from mitmproxy.addons import proxyauth def test_parse_http_basic_auth(): assert proxyauth.parse_http_basic_auth( proxyauth.mkauth("test", "test") ) == ("basic", "test", "test") - assert not proxyauth.parse_http_basic_auth("") - assert not proxyauth.parse_http_basic_auth("foo bar") - v = "basic " + binascii.b2a_base64(b"foo").decode("ascii") - assert not proxyauth.parse_http_basic_auth(v) + with pytest.raises(ValueError): + proxyauth.parse_http_basic_auth("") + with pytest.raises(ValueError): + proxyauth.parse_http_basic_auth("foo bar") + with pytest.raises(ValueError): + proxyauth.parse_http_basic_auth("basic abc") + with pytest.raises(ValueError): + v = "basic " + binascii.b2a_base64(b"foo").decode("ascii") + proxyauth.parse_http_basic_auth(v) def test_configure(): @@ -42,14 +48,14 @@ def test_configure(): ctx.configure( up, - auth_htpasswd = tutils.test_data.path( + auth_htpasswd=tutils.test_data.path( "mitmproxy/net/data/htpasswd" ) ) assert up.htpasswd assert up.htpasswd.check_password("test", "test") assert not up.htpasswd.check_password("test", "foo") - ctx.configure(up, auth_htpasswd = None) + ctx.configure(up, auth_htpasswd=None) assert not up.htpasswd with pytest.raises(exceptions.OptionsError): @@ -57,11 +63,14 @@ def test_configure(): with pytest.raises(exceptions.OptionsError): ctx.configure(up, auth_nonanonymous=True, mode="socks5") + ctx.configure(up, mode="regular") + assert up.mode == "regular" + def test_check(): up = proxyauth.ProxyAuth() with taddons.context() as ctx: - ctx.configure(up, auth_nonanonymous=True) + ctx.configure(up, auth_nonanonymous=True, mode="regular") f = tflow.tflow() assert not up.check(f) f.request.headers["Proxy-Authorization"] = proxyauth.mkauth( @@ -73,7 +82,7 @@ def test_check(): assert not up.check(f) f.request.headers["Proxy-Authorization"] = proxyauth.mkauth( - "test", "test", scheme = "unknown" + "test", "test", scheme="unknown" ) assert not up.check(f) @@ -87,8 +96,8 @@ def test_check(): ctx.configure( up, - auth_singleuser = None, - auth_htpasswd = tutils.test_data.path( + auth_singleuser=None, + auth_htpasswd=tutils.test_data.path( "mitmproxy/net/data/htpasswd" ) ) @@ -105,7 +114,7 @@ def test_check(): def test_authenticate(): up = proxyauth.ProxyAuth() with taddons.context() as ctx: - ctx.configure(up, auth_nonanonymous=True) + ctx.configure(up, auth_nonanonymous=True, mode="regular") f = tflow.tflow() assert not f.response @@ -121,13 +130,12 @@ def test_authenticate(): assert not f.request.headers.get("Proxy-Authorization") f = tflow.tflow() - f.mode = "transparent" + ctx.configure(up, mode="reverse") assert not f.response up.authenticate(f) assert f.response.status_code == 401 f = tflow.tflow() - f.mode = "transparent" f.request.headers["Authorization"] = proxyauth.mkauth( "test", "test" ) @@ -139,7 +147,7 @@ def test_authenticate(): def test_handlers(): up = proxyauth.ProxyAuth() with taddons.context() as ctx: - ctx.configure(up, auth_nonanonymous=True) + ctx.configure(up, auth_nonanonymous=True, mode="regular") f = tflow.tflow() assert not f.response @@ -151,3 +159,15 @@ def test_handlers(): assert not f.response up.http_connect(f) assert f.response.status_code == 407 + + f = tflow.tflow() + f.request.method = "CONNECT" + f.request.headers["Proxy-Authorization"] = proxyauth.mkauth( + "test", "test" + ) + up.http_connect(f) + assert not f.response + + f2 = tflow.tflow(client_conn=f.client_conn) + up.requestheaders(f2) + assert not f2.response diff --git a/test/mitmproxy/console/__init__.py b/test/mitmproxy/contentviews/image/__init__.py index e69de29b..e69de29b 100644 --- a/test/mitmproxy/console/__init__.py +++ b/test/mitmproxy/contentviews/image/__init__.py diff --git a/test/mitmproxy/contentviews/test_image_parser.py b/test/mitmproxy/contentviews/image/test_image_parser.py index 3c8bfdf7..3cb44ca6 100644 --- a/test/mitmproxy/contentviews/test_image_parser.py +++ b/test/mitmproxy/contentviews/image/test_image_parser.py @@ -80,7 +80,7 @@ def test_parse_png(filename, metadata): # check comment "mitmproxy/data/image_parser/hopper.gif": [ ('Format', 'Compuserve GIF'), - ('version', 'GIF89a'), + ('Version', 'GIF89a'), ('Size', '128 x 128 px'), ('background', '0'), ('comment', "b'File written by Adobe Photoshop\\xa8 4.0'") @@ -88,7 +88,7 @@ def test_parse_png(filename, metadata): # check background "mitmproxy/data/image_parser/chi.gif": [ ('Format', 'Compuserve GIF'), - ('version', 'GIF89a'), + ('Version', 'GIF89a'), ('Size', '320 x 240 px'), ('background', '248'), ('comment', "b'Created with GIMP'") @@ -96,7 +96,7 @@ def test_parse_png(filename, metadata): # check working with color table "mitmproxy/data/image_parser/iss634.gif": [ ('Format', 'Compuserve GIF'), - ('version', 'GIF89a'), + ('Version', 'GIF89a'), ('Size', '245 x 245 px'), ('background', '0') ], diff --git a/test/mitmproxy/contentviews/test_image.py b/test/mitmproxy/contentviews/image/test_view.py index e3dfb714..34f655a1 100644 --- a/test/mitmproxy/contentviews/test_image.py +++ b/test/mitmproxy/contentviews/image/test_view.py @@ -1,6 +1,6 @@ from mitmproxy.contentviews import image from mitmproxy.test import tutils -from . import full_eval +from .. import full_eval def test_view_image(): @@ -9,9 +9,11 @@ def test_view_image(): "mitmproxy/data/image.png", "mitmproxy/data/image.gif", "mitmproxy/data/all.jpeg", - "mitmproxy/data/image.ico" + # https://bugs.python.org/issue21574 + # "mitmproxy/data/image.ico", ]: with open(tutils.test_data.path(img), "rb") as f: - assert v(f.read()) + viewname, lines = v(f.read()) + assert img.split(".")[-1].upper() in viewname - assert not v(b"flibble") + assert v(b"flibble") == ('Unknown Image', [[('header', 'Image Format: '), ('text', 'unknown')]]) diff --git a/test/mitmproxy/contentviews/test_auto.py b/test/mitmproxy/contentviews/test_auto.py index a077affa..2ff43139 100644 --- a/test/mitmproxy/contentviews/test_auto.py +++ b/test/mitmproxy/contentviews/test_auto.py @@ -30,6 +30,18 @@ def test_view_auto(): ) assert f[0].startswith("XML") + f = v( + b"<svg></svg>", + headers=http.Headers(content_type="image/svg+xml") + ) + assert f[0].startswith("XML") + + f = v( + b"verybinary", + headers=http.Headers(content_type="image/new-magic-image-format") + ) + assert f[0] == "Unknown Image" + f = v(b"\xFF" * 30) assert f[0] == "Hex" diff --git a/test/mitmproxy/contentviews/test_base.py b/test/mitmproxy/contentviews/test_base.py new file mode 100644 index 00000000..777ab4dd --- /dev/null +++ b/test/mitmproxy/contentviews/test_base.py @@ -0,0 +1 @@ +# TODO: write tests diff --git a/test/mitmproxy/contentviews/test_protobuf.py b/test/mitmproxy/contentviews/test_protobuf.py index 1224b8db..31e382ec 100644 --- a/test/mitmproxy/contentviews/test_protobuf.py +++ b/test/mitmproxy/contentviews/test_protobuf.py @@ -1,12 +1,50 @@ +from unittest import mock +import pytest + from mitmproxy.contentviews import protobuf from mitmproxy.test import tutils from . import full_eval -if protobuf.ViewProtobuf.is_available(): - def test_view_protobuf_request(): - v = full_eval(protobuf.ViewProtobuf()) - p = tutils.test_data.path("mitmproxy/data/protobuf01") - content_type, output = v(open(p, "rb").read()) - assert content_type == "Protobuf" - assert output.next()[0][1] == '1: "3bbc333c-e61c-433b-819a-0b9a8cc103b8"' +def test_view_protobuf_request(): + v = full_eval(protobuf.ViewProtobuf()) + p = tutils.test_data.path("mitmproxy/data/protobuf01") + + with mock.patch('mitmproxy.contentviews.protobuf.ViewProtobuf.is_available'): + with mock.patch('subprocess.Popen') as n: + m = mock.Mock() + attrs = {'communicate.return_value': (b'1: "3bbc333c-e61c-433b-819a-0b9a8cc103b8"', True)} + m.configure_mock(**attrs) + n.return_value = m + + content_type, output = v(open(p, "rb").read()) + assert content_type == "Protobuf" + assert output[0] == [('text', b'1: "3bbc333c-e61c-433b-819a-0b9a8cc103b8"')] + + m.communicate = mock.MagicMock() + m.communicate.return_value = (None, None) + with pytest.raises(ValueError, matches="Failed to parse input."): + v(b'foobar') + + +def test_view_protobuf_availability(): + with mock.patch('subprocess.Popen') as n: + m = mock.Mock() + attrs = {'communicate.return_value': (b'libprotoc fake version', True)} + m.configure_mock(**attrs) + n.return_value = m + assert protobuf.ViewProtobuf().is_available() + + m = mock.Mock() + attrs = {'communicate.return_value': (b'command not found', True)} + m.configure_mock(**attrs) + n.return_value = m + assert not protobuf.ViewProtobuf().is_available() + + +def test_view_protobuf_fallback(): + with mock.patch('subprocess.Popen.communicate') as m: + m.side_effect = OSError() + v = full_eval(protobuf.ViewProtobuf()) + with pytest.raises(NotImplementedError, matches='protoc not found'): + v(b'foobar') diff --git a/test/mitmproxy/contentviews/test_wbxml.py b/test/mitmproxy/contentviews/test_wbxml.py new file mode 100644 index 00000000..777ab4dd --- /dev/null +++ b/test/mitmproxy/contentviews/test_wbxml.py @@ -0,0 +1 @@ +# TODO: write tests diff --git a/test/mitmproxy/test_contrib_tnetstring.py b/test/mitmproxy/contrib/test_tnetstring.py index 05c4a7c9..05c4a7c9 100644 --- a/test/mitmproxy/test_contrib_tnetstring.py +++ b/test/mitmproxy/contrib/test_tnetstring.py diff --git a/test/mitmproxy/mock_urwid.py b/test/mitmproxy/mock_urwid.py deleted file mode 100644 index 9cc41abc..00000000 --- a/test/mitmproxy/mock_urwid.py +++ /dev/null @@ -1,11 +0,0 @@ -import os -import sys -from unittest import mock - -if os.name == "nt": - m = mock.Mock() - m.__version__ = "1.1.1" - m.Widget = mock.Mock - m.WidgetWrap = mock.Mock - sys.modules['urwid'] = m - sys.modules['urwid.util'] = mock.Mock() diff --git a/test/mitmproxy/net/http/test_request.py b/test/mitmproxy/net/http/test_request.py index 6fe57010..90ec31fe 100644 --- a/test/mitmproxy/net/http/test_request.py +++ b/test/mitmproxy/net/http/test_request.py @@ -97,7 +97,7 @@ class TestRequestCore: request.host = d assert request.data.host == b"foo\xFF\x00bar" - def test_host_header_update(self): + def test_host_update_also_updates_header(self): request = treq() assert "host" not in request.headers request.host = "example.com" @@ -107,6 +107,51 @@ class TestRequestCore: request.host = "example.org" assert request.headers["Host"] == "example.org" + def test_get_host_header(self): + no_hdr = treq() + assert no_hdr.host_header is None + + h1 = treq(headers=( + (b"host", b"example.com"), + )) + assert h1.host_header == "example.com" + + h2 = treq(headers=( + (b":authority", b"example.org"), + )) + assert h2.host_header == "example.org" + + both_hdrs = treq(headers=( + (b"host", b"example.org"), + (b":authority", b"example.com"), + )) + assert both_hdrs.host_header == "example.com" + + def test_modify_host_header(self): + h1 = treq() + assert "host" not in h1.headers + assert ":authority" not in h1.headers + h1.host_header = "example.com" + assert "host" in h1.headers + assert ":authority" not in h1.headers + h1.host_header = None + assert "host" not in h1.headers + + h2 = treq(http_version=b"HTTP/2.0") + h2.host_header = "example.org" + assert "host" not in h2.headers + assert ":authority" in h2.headers + del h2.host_header + assert ":authority" not in h2.headers + + both_hdrs = treq(headers=( + (b":authority", b"example.com"), + (b"host", b"example.org"), + )) + both_hdrs.host_header = "foo.example.com" + assert both_hdrs.headers["Host"] == "foo.example.com" + assert both_hdrs.headers[":authority"] == "foo.example.com" + class TestRequestUtils: """ diff --git a/test/mitmproxy/net/http/test_url.py b/test/mitmproxy/net/http/test_url.py index 11ab1b81..2064aab8 100644 --- a/test/mitmproxy/net/http/test_url.py +++ b/test/mitmproxy/net/http/test_url.py @@ -85,6 +85,26 @@ surrogates_quoted = ( ) +def test_empty_key_trailing_equal_sign(): + """ + Some HTTP clients don't send trailing equal signs for parameters without assigned value, e.g. they send + foo=bar&baz&qux=quux + instead of + foo=bar&baz=&qux=quux + The respective behavior of encode() should be driven by a reference string given in similar_to parameter + """ + reference_without_equal = "key1=val1&key2&key3=val3" + reference_with_equal = "key1=val1&key2=&key3=val3" + + post_data_empty_key_middle = [('one', 'two'), ('emptykey', ''), ('three', 'four')] + post_data_empty_key_end = [('one', 'two'), ('three', 'four'), ('emptykey', '')] + + assert url.encode(post_data_empty_key_middle, similar_to = reference_with_equal) == "one=two&emptykey=&three=four" + assert url.encode(post_data_empty_key_end, similar_to = reference_with_equal) == "one=two&three=four&emptykey=" + assert url.encode(post_data_empty_key_middle, similar_to = reference_without_equal) == "one=two&emptykey&three=four" + assert url.encode(post_data_empty_key_end, similar_to = reference_without_equal) == "one=two&three=four&emptykey" + + def test_encode(): assert url.encode([('foo', 'bar')]) assert url.encode([('foo', surrogates)]) diff --git a/test/mitmproxy/test_platform_pf.py b/test/mitmproxy/platform/test_pf.py index f644bcc5..f644bcc5 100644 --- a/test/mitmproxy/test_platform_pf.py +++ b/test/mitmproxy/platform/test_pf.py diff --git a/test/mitmproxy/protocol/__init__.py b/test/mitmproxy/proxy/__init__.py index e69de29b..e69de29b 100644 --- a/test/mitmproxy/protocol/__init__.py +++ b/test/mitmproxy/proxy/__init__.py diff --git a/test/mitmproxy/proxy/modes/test_http_proxy.py b/test/mitmproxy/proxy/modes/test_http_proxy.py new file mode 100644 index 00000000..777ab4dd --- /dev/null +++ b/test/mitmproxy/proxy/modes/test_http_proxy.py @@ -0,0 +1 @@ +# TODO: write tests diff --git a/test/mitmproxy/proxy/modes/test_reverse_proxy.py b/test/mitmproxy/proxy/modes/test_reverse_proxy.py new file mode 100644 index 00000000..777ab4dd --- /dev/null +++ b/test/mitmproxy/proxy/modes/test_reverse_proxy.py @@ -0,0 +1 @@ +# TODO: write tests diff --git a/test/mitmproxy/proxy/modes/test_socks_proxy.py b/test/mitmproxy/proxy/modes/test_socks_proxy.py new file mode 100644 index 00000000..777ab4dd --- /dev/null +++ b/test/mitmproxy/proxy/modes/test_socks_proxy.py @@ -0,0 +1 @@ +# TODO: write tests diff --git a/test/mitmproxy/proxy/modes/test_transparent_proxy.py b/test/mitmproxy/proxy/modes/test_transparent_proxy.py new file mode 100644 index 00000000..777ab4dd --- /dev/null +++ b/test/mitmproxy/proxy/modes/test_transparent_proxy.py @@ -0,0 +1 @@ +# TODO: write tests diff --git a/test/mitmproxy/proxy/protocol/__init__.py b/test/mitmproxy/proxy/protocol/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/test/mitmproxy/proxy/protocol/__init__.py diff --git a/test/mitmproxy/proxy/protocol/test_base.py b/test/mitmproxy/proxy/protocol/test_base.py new file mode 100644 index 00000000..777ab4dd --- /dev/null +++ b/test/mitmproxy/proxy/protocol/test_base.py @@ -0,0 +1 @@ +# TODO: write tests diff --git a/test/mitmproxy/proxy/protocol/test_http.py b/test/mitmproxy/proxy/protocol/test_http.py new file mode 100644 index 00000000..777ab4dd --- /dev/null +++ b/test/mitmproxy/proxy/protocol/test_http.py @@ -0,0 +1 @@ +# TODO: write tests diff --git a/test/mitmproxy/protocol/test_http1.py b/test/mitmproxy/proxy/protocol/test_http1.py index 44a9effa..07cd7dcc 100644 --- a/test/mitmproxy/protocol/test_http1.py +++ b/test/mitmproxy/proxy/protocol/test_http1.py @@ -2,7 +2,7 @@ from mitmproxy.test import tflow from mitmproxy.net.http import http1 from mitmproxy.net.tcp import TCPClient from mitmproxy.test.tutils import treq -from .. import tservers +from ... import tservers class TestHTTPFlow: diff --git a/test/mitmproxy/protocol/test_http2.py b/test/mitmproxy/proxy/protocol/test_http2.py index 8e8ba644..cb9c0474 100644 --- a/test/mitmproxy/protocol/test_http2.py +++ b/test/mitmproxy/proxy/protocol/test_http2.py @@ -4,27 +4,25 @@ import os import tempfile import traceback - +import pytest import h2 from mitmproxy import options from mitmproxy.proxy.config import ProxyConfig import mitmproxy.net -from ...mitmproxy.net import tservers as net_tservers +from ....mitmproxy.net import tservers as net_tservers from mitmproxy import exceptions from mitmproxy.net.http import http1, http2 -from .. import tservers -from ...conftest import requires_alpn +from ... import tservers +from ....conftest import requires_alpn import logging logging.getLogger("hyper.packages.hpack.hpack").setLevel(logging.WARNING) logging.getLogger("requests.packages.urllib3.connectionpool").setLevel(logging.WARNING) logging.getLogger("passlib.utils.compat").setLevel(logging.WARNING) logging.getLogger("passlib.registry").setLevel(logging.WARNING) -logging.getLogger("PIL.Image").setLevel(logging.WARNING) -logging.getLogger("PIL.PngImagePlugin").setLevel(logging.WARNING) # inspect the log: @@ -274,13 +272,13 @@ class TestSimple(_Http2Test): @requires_alpn -class TestRequestWithPriority(_Http2Test): +class TestForbiddenHeaders(_Http2Test): @classmethod def handle_server_event(cls, event, h2_conn, rfile, wfile): if isinstance(event, h2.events.ConnectionTerminated): return False - elif isinstance(event, h2.events.RequestReceived): + elif isinstance(event, h2.events.StreamEnded): import warnings with warnings.catch_warnings(): # Ignore UnicodeWarning: @@ -291,60 +289,18 @@ class TestRequestWithPriority(_Http2Test): warnings.simplefilter("ignore") - headers = [(':status', '200')] - if event.priority_updated: - headers.append(('priority_exclusive', str(event.priority_updated.exclusive).encode())) - headers.append(('priority_depends_on', str(event.priority_updated.depends_on).encode())) - headers.append(('priority_weight', str(event.priority_updated.weight).encode())) - h2_conn.send_headers(event.stream_id, headers) + h2_conn.config.validate_outbound_headers = False + h2_conn.send_headers(event.stream_id, [ + (':status', '200'), + ('keep-alive', '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() 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:{}".format(self.server.server.address.port)), - (':method', 'GET'), - (':scheme', 'https'), - (':path', '/'), - ], - priority_exclusive=True, - priority_depends_on=42424242, - priority_weight=42, - ) - - done = False - while not done: - try: - raw = b''.join(http2.read_raw_frame(client.rfile)) - events = h2_conn.receive_data(raw) - except exceptions.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 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): + def test_forbidden_headers(self): client, h2_conn = self._setup_connection() self._send_request( @@ -355,8 +311,7 @@ class TestRequestWithPriority(_Http2Test): (':method', 'GET'), (':scheme', 'https'), (':path', '/'), - ], - ) + ]) done = False while not done: @@ -371,7 +326,9 @@ class TestRequestWithPriority(_Http2Test): client.wfile.flush() for event in events: - if isinstance(event, h2.events.StreamEnded): + if isinstance(event, h2.events.ResponseReceived): + assert 'keep-alive' not in event.headers + elif isinstance(event, h2.events.StreamEnded): done = True h2_conn.close_connection() @@ -379,21 +336,17 @@ class TestRequestWithPriority(_Http2Test): 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 + assert self.master.state.flows[0].response.status_code == 200 + assert self.master.state.flows[0].response.headers['keep-alive'] == 'foobar' @requires_alpn -class TestPriority(_Http2Test): - priority_data = None +class TestRequestWithPriority(_Http2Test): @classmethod def handle_server_event(cls, event, h2_conn, rfile, wfile): if isinstance(event, h2.events.ConnectionTerminated): return False - elif isinstance(event, h2.events.PriorityUpdated): - cls.priority_data = (event.exclusive, event.depends_on, event.weight) elif isinstance(event, h2.events.RequestReceived): import warnings with warnings.catch_warnings(): @@ -406,18 +359,26 @@ class TestPriority(_Http2Test): warnings.simplefilter("ignore") headers = [(':status', '200')] + if event.priority_updated: + headers.append(('priority_exclusive', str(event.priority_updated.exclusive).encode())) + headers.append(('priority_depends_on', str(event.priority_updated.depends_on).encode())) + headers.append(('priority_weight', str(event.priority_updated.weight).encode())) 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_priority(self): - client, h2_conn = self._setup_connection() + @pytest.mark.parametrize("http2_priority_enabled, priority, expected_priority", [ + (True, (True, 42424242, 42), ('True', '42424242', '42')), + (False, (True, 42424242, 42), (None, None, None)), + (True, (None, None, None), (None, None, None)), + (False, (None, None, None), (None, None, None)), + ]) + def test_request_with_priority(self, http2_priority_enabled, priority, expected_priority): + self.config.options.http2_priority = http2_priority_enabled - h2_conn.prioritize(1, exclusive=True, depends_on=0, weight=42) - client.wfile.write(h2_conn.data_to_send()) - client.wfile.flush() + client, h2_conn = self._setup_connection() self._send_request( client.wfile, @@ -428,6 +389,9 @@ class TestPriority(_Http2Test): (':scheme', 'https'), (':path', '/'), ], + priority_exclusive=priority[0], + priority_depends_on=priority[1], + priority_weight=priority[2], ) done = False @@ -451,12 +415,15 @@ class TestPriority(_Http2Test): client.wfile.flush() assert len(self.master.state.flows) == 1 - assert self.priority_data == (True, 0, 42) + + resp = self.master.state.flows[0].response + assert resp.headers.get('priority_exclusive', None) == expected_priority[0] + assert resp.headers.get('priority_depends_on', None) == expected_priority[1] + assert resp.headers.get('priority_weight', None) == expected_priority[2] @requires_alpn -class TestPriorityWithExistingStream(_Http2Test): - priority_data = [] +class TestPriority(_Http2Test): @classmethod def handle_server_event(cls, event, h2_conn, rfile, wfile): @@ -465,8 +432,6 @@ class TestPriorityWithExistingStream(_Http2Test): elif isinstance(event, h2.events.PriorityUpdated): cls.priority_data.append((event.exclusive, event.depends_on, event.weight)) elif isinstance(event, h2.events.RequestReceived): - assert not event.priority_updated - import warnings with warnings.catch_warnings(): # Ignore UnicodeWarning: @@ -479,17 +444,27 @@ class TestPriorityWithExistingStream(_Http2Test): headers = [(':status', '200')] h2_conn.send_headers(event.stream_id, headers) - wfile.write(h2_conn.data_to_send()) - wfile.flush() - elif isinstance(event, h2.events.StreamEnded): h2_conn.end_stream(event.stream_id) wfile.write(h2_conn.data_to_send()) wfile.flush() return True - def test_priority_with_existing_stream(self): + @pytest.mark.parametrize("prioritize_before", [True, False]) + @pytest.mark.parametrize("http2_priority_enabled, priority, expected_priority", [ + (True, (True, 42424242, 42), [(True, 42424242, 42)]), + (False, (True, 42424242, 42), []), + ]) + def test_priority(self, prioritize_before, http2_priority_enabled, priority, expected_priority): + self.config.options.http2_priority = http2_priority_enabled + self.__class__.priority_data = [] + client, h2_conn = self._setup_connection() + if prioritize_before: + h2_conn.prioritize(1, exclusive=priority[0], depends_on=priority[1], weight=priority[2]) + client.wfile.write(h2_conn.data_to_send()) + client.wfile.flush() + self._send_request( client.wfile, h2_conn, @@ -499,13 +474,14 @@ class TestPriorityWithExistingStream(_Http2Test): (':scheme', 'https'), (':path', '/'), ], - end_stream=False, + end_stream=prioritize_before, ) - h2_conn.prioritize(1, exclusive=True, depends_on=0, weight=42) - h2_conn.end_stream(1) - client.wfile.write(h2_conn.data_to_send()) - client.wfile.flush() + if not prioritize_before: + h2_conn.prioritize(1, exclusive=priority[0], depends_on=priority[1], weight=priority[2]) + h2_conn.end_stream(1) + client.wfile.write(h2_conn.data_to_send()) + client.wfile.flush() done = False while not done: @@ -528,7 +504,7 @@ class TestPriorityWithExistingStream(_Http2Test): client.wfile.flush() assert len(self.master.state.flows) == 1 - assert self.priority_data == [(True, 0, 42)] + assert self.priority_data == expected_priority @requires_alpn diff --git a/test/mitmproxy/proxy/protocol/test_http_replay.py b/test/mitmproxy/proxy/protocol/test_http_replay.py new file mode 100644 index 00000000..777ab4dd --- /dev/null +++ b/test/mitmproxy/proxy/protocol/test_http_replay.py @@ -0,0 +1 @@ +# TODO: write tests diff --git a/test/mitmproxy/proxy/protocol/test_rawtcp.py b/test/mitmproxy/proxy/protocol/test_rawtcp.py new file mode 100644 index 00000000..777ab4dd --- /dev/null +++ b/test/mitmproxy/proxy/protocol/test_rawtcp.py @@ -0,0 +1 @@ +# TODO: write tests diff --git a/test/mitmproxy/protocol/test_tls.py b/test/mitmproxy/proxy/protocol/test_tls.py index e17ee46f..e17ee46f 100644 --- a/test/mitmproxy/protocol/test_tls.py +++ b/test/mitmproxy/proxy/protocol/test_tls.py diff --git a/test/mitmproxy/protocol/test_websocket.py b/test/mitmproxy/proxy/protocol/test_websocket.py index 73ee8b35..4ea01d34 100644 --- a/test/mitmproxy/protocol/test_websocket.py +++ b/test/mitmproxy/proxy/protocol/test_websocket.py @@ -9,17 +9,17 @@ from mitmproxy.http import HTTPFlow from mitmproxy.websocket import WebSocketFlow from mitmproxy.proxy.config import ProxyConfig -import mitmproxy.net +from mitmproxy.net import tcp from mitmproxy.net import http -from ...mitmproxy.net import tservers as net_tservers -from .. import tservers +from ....mitmproxy.net import tservers as net_tservers +from ... import tservers from mitmproxy.net import websockets class _WebSocketServerBase(net_tservers.ServerTestBase): - class handler(mitmproxy.net.tcp.BaseHandler): + class handler(tcp.BaseHandler): def handle(self): try: @@ -80,7 +80,7 @@ class _WebSocketTestBase: self.server.server.handle_websockets = self.handle_websockets def _setup_connection(self): - client = mitmproxy.net.tcp.TCPClient(("127.0.0.1", self.proxy.port)) + client = tcp.TCPClient(("127.0.0.1", self.proxy.port)) client.connect() request = http.Request( diff --git a/test/mitmproxy/test_proxy_config.py b/test/mitmproxy/proxy/test_config.py index 4272d952..4272d952 100644 --- a/test/mitmproxy/test_proxy_config.py +++ b/test/mitmproxy/proxy/test_config.py diff --git a/test/mitmproxy/proxy/test_root_context.py b/test/mitmproxy/proxy/test_root_context.py new file mode 100644 index 00000000..777ab4dd --- /dev/null +++ b/test/mitmproxy/proxy/test_root_context.py @@ -0,0 +1 @@ +# TODO: write tests diff --git a/test/mitmproxy/test_server.py b/test/mitmproxy/proxy/test_server.py index 9cd47cea..0be772a4 100644 --- a/test/mitmproxy/test_server.py +++ b/test/mitmproxy/proxy/test_server.py @@ -21,8 +21,8 @@ from mitmproxy.net.tcp import Address from pathod import pathoc from pathod import pathod -from . import tservers -from ..conftest import skip_appveyor +from .. import tservers +from ...conftest import skip_appveyor """ diff --git a/test/mitmproxy/test_connections.py b/test/mitmproxy/test_connections.py new file mode 100644 index 00000000..777ab4dd --- /dev/null +++ b/test/mitmproxy/test_connections.py @@ -0,0 +1 @@ +# TODO: write tests diff --git a/test/mitmproxy/test_ctx.py b/test/mitmproxy/test_ctx.py new file mode 100644 index 00000000..777ab4dd --- /dev/null +++ b/test/mitmproxy/test_ctx.py @@ -0,0 +1 @@ +# TODO: write tests diff --git a/test/mitmproxy/test_exceptions.py b/test/mitmproxy/test_exceptions.py new file mode 100644 index 00000000..777ab4dd --- /dev/null +++ b/test/mitmproxy/test_exceptions.py @@ -0,0 +1 @@ +# TODO: write tests diff --git a/test/mitmproxy/test_flow_export.py b/test/mitmproxy/test_export.py index 457d8836..457d8836 100644 --- a/test/mitmproxy/test_flow_export.py +++ b/test/mitmproxy/test_export.py diff --git a/test/mitmproxy/test_flow.py b/test/mitmproxy/test_flow.py index 65e6845f..a78e5f80 100644 --- a/test/mitmproxy/test_flow.py +++ b/test/mitmproxy/test_flow.py @@ -10,7 +10,6 @@ from mitmproxy.exceptions import FlowReadException, Kill from mitmproxy import flow from mitmproxy import http from mitmproxy import connections -from mitmproxy import tcp from mitmproxy.proxy import ProxyConfig from mitmproxy.proxy.server import DummyServer from mitmproxy import master @@ -157,117 +156,6 @@ class TestHTTPFlow: assert f.response.raw_content == b"abarb" -class TestWebSocketFlow: - - def test_copy(self): - f = tflow.twebsocketflow() - f.get_state() - f2 = f.copy() - a = f.get_state() - b = f2.get_state() - del a["id"] - del b["id"] - del a["handshake_flow"]["id"] - del b["handshake_flow"]["id"] - assert a == b - assert not f == f2 - assert f is not f2 - - assert f.client_key == f2.client_key - assert f.client_protocol == f2.client_protocol - assert f.client_extensions == f2.client_extensions - assert f.server_accept == f2.server_accept - assert f.server_protocol == f2.server_protocol - assert f.server_extensions == f2.server_extensions - assert f.messages is not f2.messages - assert f.handshake_flow is not f2.handshake_flow - - for m in f.messages: - m2 = m.copy() - m2.set_state(m2.get_state()) - assert m is not m2 - assert m.get_state() == m2.get_state() - - f = tflow.twebsocketflow(err=True) - f2 = f.copy() - assert f is not f2 - assert f.handshake_flow is not f2.handshake_flow - assert f.error.get_state() == f2.error.get_state() - assert f.error is not f2.error - - def test_match(self): - f = tflow.twebsocketflow() - assert not flowfilter.match("~b nonexistent", f) - assert flowfilter.match(None, f) - assert not flowfilter.match("~b nonexistent", f) - - f = tflow.twebsocketflow(err=True) - assert flowfilter.match("~e", f) - - with pytest.raises(ValueError): - flowfilter.match("~", f) - - def test_repr(self): - f = tflow.twebsocketflow() - assert 'WebSocketFlow' in repr(f) - assert 'binary message: ' in repr(f.messages[0]) - assert 'text message: ' in repr(f.messages[1]) - - -class TestTCPFlow: - - def test_copy(self): - f = tflow.ttcpflow() - f.get_state() - f2 = f.copy() - a = f.get_state() - b = f2.get_state() - del a["id"] - del b["id"] - assert a == b - assert not f == f2 - assert f is not f2 - - assert f.messages is not f2.messages - - for m in f.messages: - assert m.get_state() - m2 = m.copy() - assert not m == m2 - assert m is not m2 - - a = m.get_state() - b = m2.get_state() - assert a == b - - m = tcp.TCPMessage(False, 'foo') - m.set_state(f.messages[0].get_state()) - assert m.timestamp == f.messages[0].timestamp - - f = tflow.ttcpflow(err=True) - f2 = f.copy() - assert f is not f2 - assert f.error.get_state() == f2.error.get_state() - assert f.error is not f2.error - - def test_match(self): - f = tflow.ttcpflow() - assert not flowfilter.match("~b nonexistent", f) - assert flowfilter.match(None, f) - assert not flowfilter.match("~b nonexistent", f) - - f = tflow.ttcpflow(err=True) - assert flowfilter.match("~e", f) - - with pytest.raises(ValueError): - flowfilter.match("~", f) - - def test_repr(self): - f = tflow.ttcpflow() - assert 'TCPFlow' in repr(f) - assert '-> ' in repr(f.messages[0]) - - class TestSerialize: def _treader(self): diff --git a/test/mitmproxy/test_http.py b/test/mitmproxy/test_http.py new file mode 100644 index 00000000..777ab4dd --- /dev/null +++ b/test/mitmproxy/test_http.py @@ -0,0 +1 @@ +# TODO: write tests diff --git a/test/mitmproxy/test_io.py b/test/mitmproxy/test_io.py new file mode 100644 index 00000000..777ab4dd --- /dev/null +++ b/test/mitmproxy/test_io.py @@ -0,0 +1 @@ +# TODO: write tests diff --git a/test/mitmproxy/test_flow_format_compat.py b/test/mitmproxy/test_io_compat.py index 288de4fc..288de4fc 100644 --- a/test/mitmproxy/test_flow_format_compat.py +++ b/test/mitmproxy/test_io_compat.py diff --git a/test/mitmproxy/test_log.py b/test/mitmproxy/test_log.py new file mode 100644 index 00000000..777ab4dd --- /dev/null +++ b/test/mitmproxy/test_log.py @@ -0,0 +1 @@ +# TODO: write tests diff --git a/test/mitmproxy/test_master.py b/test/mitmproxy/test_master.py new file mode 100644 index 00000000..777ab4dd --- /dev/null +++ b/test/mitmproxy/test_master.py @@ -0,0 +1 @@ +# TODO: write tests diff --git a/test/mitmproxy/test_options.py b/test/mitmproxy/test_options.py new file mode 100644 index 00000000..777ab4dd --- /dev/null +++ b/test/mitmproxy/test_options.py @@ -0,0 +1 @@ +# TODO: write tests diff --git a/test/mitmproxy/test_tcp.py b/test/mitmproxy/test_tcp.py new file mode 100644 index 00000000..dce6493c --- /dev/null +++ b/test/mitmproxy/test_tcp.py @@ -0,0 +1,59 @@ +import pytest + +from mitmproxy import tcp +from mitmproxy import flowfilter +from mitmproxy.test import tflow + + +class TestTCPFlow: + + def test_copy(self): + f = tflow.ttcpflow() + f.get_state() + f2 = f.copy() + a = f.get_state() + b = f2.get_state() + del a["id"] + del b["id"] + assert a == b + assert not f == f2 + assert f is not f2 + + assert f.messages is not f2.messages + + for m in f.messages: + assert m.get_state() + m2 = m.copy() + assert not m == m2 + assert m is not m2 + + a = m.get_state() + b = m2.get_state() + assert a == b + + m = tcp.TCPMessage(False, 'foo') + m.set_state(f.messages[0].get_state()) + assert m.timestamp == f.messages[0].timestamp + + f = tflow.ttcpflow(err=True) + f2 = f.copy() + assert f is not f2 + assert f.error.get_state() == f2.error.get_state() + assert f.error is not f2.error + + def test_match(self): + f = tflow.ttcpflow() + assert not flowfilter.match("~b nonexistent", f) + assert flowfilter.match(None, f) + assert not flowfilter.match("~b nonexistent", f) + + f = tflow.ttcpflow(err=True) + assert flowfilter.match("~e", f) + + with pytest.raises(ValueError): + flowfilter.match("~", f) + + def test_repr(self): + f = tflow.ttcpflow() + assert 'TCPFlow' in repr(f) + assert '-> ' in repr(f.messages[0]) diff --git a/test/mitmproxy/test_websocket.py b/test/mitmproxy/test_websocket.py new file mode 100644 index 00000000..f2963390 --- /dev/null +++ b/test/mitmproxy/test_websocket.py @@ -0,0 +1,62 @@ +import pytest + +from mitmproxy import flowfilter +from mitmproxy.test import tflow + + +class TestWebSocketFlow: + + def test_copy(self): + f = tflow.twebsocketflow() + f.get_state() + f2 = f.copy() + a = f.get_state() + b = f2.get_state() + del a["id"] + del b["id"] + del a["handshake_flow"]["id"] + del b["handshake_flow"]["id"] + assert a == b + assert not f == f2 + assert f is not f2 + + assert f.client_key == f2.client_key + assert f.client_protocol == f2.client_protocol + assert f.client_extensions == f2.client_extensions + assert f.server_accept == f2.server_accept + assert f.server_protocol == f2.server_protocol + assert f.server_extensions == f2.server_extensions + assert f.messages is not f2.messages + assert f.handshake_flow is not f2.handshake_flow + + for m in f.messages: + m2 = m.copy() + m2.set_state(m2.get_state()) + assert m is not m2 + assert m.get_state() == m2.get_state() + + f = tflow.twebsocketflow(err=True) + f2 = f.copy() + assert f is not f2 + assert f.handshake_flow is not f2.handshake_flow + assert f.error.get_state() == f2.error.get_state() + assert f.error is not f2.error + + def test_match(self): + f = tflow.twebsocketflow() + assert not flowfilter.match("~b nonexistent", f) + assert flowfilter.match(None, f) + assert not flowfilter.match("~b nonexistent", f) + + f = tflow.twebsocketflow(err=True) + assert flowfilter.match("~e", f) + + with pytest.raises(ValueError): + flowfilter.match("~", f) + + def test_repr(self): + f = tflow.twebsocketflow() + assert f.message_info(f.messages[0]) + assert 'WebSocketFlow' in repr(f) + assert 'binary message: ' in repr(f.messages[0]) + assert 'text message: ' in repr(f.messages[1]) diff --git a/test/mitmproxy/tools/__init__.py b/test/mitmproxy/tools/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/test/mitmproxy/tools/__init__.py diff --git a/test/mitmproxy/tools/console/__init__.py b/test/mitmproxy/tools/console/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/test/mitmproxy/tools/console/__init__.py diff --git a/test/mitmproxy/console/test_common.py b/test/mitmproxy/tools/console/test_common.py index 236ebb41..3ab4fd67 100644 --- a/test/mitmproxy/console/test_common.py +++ b/test/mitmproxy/tools/console/test_common.py @@ -1,7 +1,7 @@ from mitmproxy.test import tflow from mitmproxy.tools.console import common -from ...conftest import skip_appveyor +from ....conftest import skip_appveyor @skip_appveyor diff --git a/test/mitmproxy/console/test_help.py b/test/mitmproxy/tools/console/test_help.py index 86b842d8..ac3011e6 100644 --- a/test/mitmproxy/console/test_help.py +++ b/test/mitmproxy/tools/console/test_help.py @@ -1,6 +1,6 @@ import mitmproxy.tools.console.help as help -from ...conftest import skip_appveyor +from ....conftest import skip_appveyor @skip_appveyor diff --git a/test/mitmproxy/console/test_master.py b/test/mitmproxy/tools/console/test_master.py index 1c89467c..0bf3734b 100644 --- a/test/mitmproxy/console/test_master.py +++ b/test/mitmproxy/tools/console/test_master.py @@ -1,10 +1,10 @@ from mitmproxy.test import tflow -import mitmproxy.test.tutils +from mitmproxy.test import tutils from mitmproxy.tools import console from mitmproxy import proxy from mitmproxy import options from mitmproxy.tools.console import common -from .. import tservers +from ... import tservers def test_format_keyvals(): @@ -45,12 +45,12 @@ class TestMaster(tservers.MasterTest): def test_intercept(self): """regression test for https://github.com/mitmproxy/mitmproxy/issues/1605""" m = self.mkmaster(intercept="~b bar") - f = tflow.tflow(req=mitmproxy.test.tutils.treq(content=b"foo")) + f = tflow.tflow(req=tutils.treq(content=b"foo")) m.request(f) assert not m.view[0].intercepted - f = tflow.tflow(req=mitmproxy.test.tutils.treq(content=b"bar")) + f = tflow.tflow(req=tutils.treq(content=b"bar")) m.request(f) assert m.view[1].intercepted - f = tflow.tflow(resp=mitmproxy.test.tutils.tresp(content=b"bar")) + f = tflow.tflow(resp=tutils.tresp(content=b"bar")) m.request(f) assert m.view[2].intercepted diff --git a/test/mitmproxy/console/test_palettes.py b/test/mitmproxy/tools/console/test_palettes.py index 3892797d..1c7e1df1 100644 --- a/test/mitmproxy/console/test_palettes.py +++ b/test/mitmproxy/tools/console/test_palettes.py @@ -1,6 +1,6 @@ import mitmproxy.tools.console.palettes as palettes -from ...conftest import skip_appveyor +from ....conftest import skip_appveyor @skip_appveyor diff --git a/test/mitmproxy/console/test_pathedit.py b/test/mitmproxy/tools/console/test_pathedit.py index bd064e5f..bd064e5f 100644 --- a/test/mitmproxy/console/test_pathedit.py +++ b/test/mitmproxy/tools/console/test_pathedit.py diff --git a/test/mitmproxy/test_cmdline.py b/test/mitmproxy/tools/test_cmdline.py index 96d5ae31..96d5ae31 100644 --- a/test/mitmproxy/test_cmdline.py +++ b/test/mitmproxy/tools/test_cmdline.py diff --git a/test/mitmproxy/test_tools_dump.py b/test/mitmproxy/tools/test_dump.py index f8a88871..b4183725 100644 --- a/test/mitmproxy/test_tools_dump.py +++ b/test/mitmproxy/tools/test_dump.py @@ -8,7 +8,7 @@ from mitmproxy import controller from mitmproxy.tools import dump from mitmproxy.test import tutils -from . import tservers +from .. import tservers class TestDumpMaster(tservers.MasterTest): diff --git a/test/mitmproxy/tools/web/__init__.py b/test/mitmproxy/tools/web/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/test/mitmproxy/tools/web/__init__.py diff --git a/test/mitmproxy/test_web_app.py b/test/mitmproxy/tools/web/test_app.py index 00dc2c7c..00dc2c7c 100644 --- a/test/mitmproxy/test_web_app.py +++ b/test/mitmproxy/tools/web/test_app.py diff --git a/test/mitmproxy/test_web_master.py b/test/mitmproxy/tools/web/test_master.py index d4190ffb..27f99a18 100644 --- a/test/mitmproxy/test_web_master.py +++ b/test/mitmproxy/tools/web/test_master.py @@ -3,7 +3,7 @@ from mitmproxy import proxy from mitmproxy import options from mitmproxy.proxy.config import ProxyConfig -from . import tservers +from ... import tservers class TestWebMaster(tservers.MasterTest): diff --git a/test/mitmproxy/utils/test_bits.py b/test/mitmproxy/utils/test_bits.py new file mode 100644 index 00000000..777ab4dd --- /dev/null +++ b/test/mitmproxy/utils/test_bits.py @@ -0,0 +1 @@ +# TODO: write tests diff --git a/test/mitmproxy/utils/test_debug.py b/test/mitmproxy/utils/test_debug.py index 22f8dc66..4371ef70 100644 --- a/test/mitmproxy/utils/test_debug.py +++ b/test/mitmproxy/utils/test_debug.py @@ -1,13 +1,20 @@ import io import subprocess +import sys from unittest import mock +import pytest from mitmproxy.utils import debug -def test_dump_system_info(): - assert debug.dump_system_info() +@pytest.mark.parametrize("precompiled", [True, False]) +def test_dump_system_info_precompiled(precompiled): + sys.frozen = None + with mock.patch.object(sys, 'frozen', precompiled): + assert ("Precompiled Binary" in debug.dump_system_info()) == precompiled + +def test_dump_system_info_version(): with mock.patch('subprocess.check_output') as m: m.side_effect = subprocess.CalledProcessError(-1, 'git describe --tags --long') assert 'release version' in debug.dump_system_info() diff --git a/test/pathod/language/__init__.py b/test/pathod/language/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/test/pathod/language/__init__.py diff --git a/test/pathod/test_language_actions.py b/test/pathod/language/test_actions.py index 9740e5c7..9740e5c7 100644 --- a/test/pathod/test_language_actions.py +++ b/test/pathod/language/test_actions.py diff --git a/test/pathod/test_language_base.py b/test/pathod/language/test_base.py index 85e9e53b..85e9e53b 100644 --- a/test/pathod/test_language_base.py +++ b/test/pathod/language/test_base.py diff --git a/test/pathod/language/test_exceptions.py b/test/pathod/language/test_exceptions.py new file mode 100644 index 00000000..777ab4dd --- /dev/null +++ b/test/pathod/language/test_exceptions.py @@ -0,0 +1 @@ +# TODO: write tests diff --git a/test/pathod/test_language_generators.py b/test/pathod/language/test_generators.py index b3ce0335..b3ce0335 100644 --- a/test/pathod/test_language_generators.py +++ b/test/pathod/language/test_generators.py diff --git a/test/pathod/test_language_http.py b/test/pathod/language/test_http.py index 6ab43fe0..a5b35c05 100644 --- a/test/pathod/test_language_http.py +++ b/test/pathod/language/test_http.py @@ -4,7 +4,7 @@ import pytest from pathod import language from pathod.language import http, base -from . import tservers +from .. import tservers def parse_request(s): diff --git a/test/pathod/test_language_http2.py b/test/pathod/language/test_http2.py index 4f89adb8..4f89adb8 100644 --- a/test/pathod/test_language_http2.py +++ b/test/pathod/language/test_http2.py diff --git a/test/pathod/language/test_message.py b/test/pathod/language/test_message.py new file mode 100644 index 00000000..777ab4dd --- /dev/null +++ b/test/pathod/language/test_message.py @@ -0,0 +1 @@ +# TODO: write tests diff --git a/test/pathod/test_language_websocket.py b/test/pathod/language/test_websockets.py index e5046591..ed766bca 100644 --- a/test/pathod/test_language_websocket.py +++ b/test/pathod/language/test_websockets.py @@ -4,7 +4,7 @@ from pathod import language from pathod.language import websockets import mitmproxy.net.websockets -from . import tservers +from .. import tservers def parse_request(s): diff --git a/test/pathod/test_language_writer.py b/test/pathod/language/test_writer.py index 7feb985d..7feb985d 100644 --- a/test/pathod/test_language_writer.py +++ b/test/pathod/language/test_writer.py diff --git a/test/pathod/protocols/__init__.py b/test/pathod/protocols/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/test/pathod/protocols/__init__.py diff --git a/test/pathod/protocols/test_http.py b/test/pathod/protocols/test_http.py new file mode 100644 index 00000000..777ab4dd --- /dev/null +++ b/test/pathod/protocols/test_http.py @@ -0,0 +1 @@ +# TODO: write tests diff --git a/test/pathod/test_protocols_http2.py b/test/pathod/protocols/test_http2.py index 5bb31031..1c074197 100644 --- a/test/pathod/test_protocols_http2.py +++ b/test/pathod/protocols/test_http2.py @@ -7,11 +7,11 @@ from mitmproxy.net import tcp, http from mitmproxy.net.http import http2 from mitmproxy import exceptions -from ..mitmproxy.net import tservers as net_tservers +from ...mitmproxy.net import tservers as net_tservers from pathod.protocols.http2 import HTTP2StateProtocol, TCPHandler -from ..conftest import requires_alpn +from ...conftest import requires_alpn class TestTCPHandlerWrapper: diff --git a/test/pathod/protocols/test_websockets.py b/test/pathod/protocols/test_websockets.py new file mode 100644 index 00000000..777ab4dd --- /dev/null +++ b/test/pathod/protocols/test_websockets.py @@ -0,0 +1 @@ +# TODO: write tests |