mirror of
https://github.com/Grasscutters/mitmproxy.git
synced 2024-11-22 07:08:10 +00:00
please the coverage gods
This commit is contained in:
parent
8561a620c8
commit
2945ba925b
@ -137,7 +137,8 @@ class Dumper:
|
|||||||
human.format_address(flow.client_conn.peername)
|
human.format_address(flow.client_conn.peername)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
else:
|
else: # pragma: no cover
|
||||||
|
# this should not happen, but we're defensive here.
|
||||||
client = ""
|
client = ""
|
||||||
|
|
||||||
pushed = ' PUSH_PROMISE' if 'h2-pushed-stream' in flow.metadata else ''
|
pushed = ' PUSH_PROMISE' if 'h2-pushed-stream' in flow.metadata else ''
|
||||||
|
@ -224,22 +224,26 @@ async def test_load(tmpdir):
|
|||||||
def test_resolve():
|
def test_resolve():
|
||||||
v = view.View()
|
v = view.View()
|
||||||
with taddons.context() as tctx:
|
with taddons.context() as tctx:
|
||||||
|
f = tft(method="get")
|
||||||
assert tctx.command(v.resolve, "@all") == []
|
assert tctx.command(v.resolve, "@all") == []
|
||||||
assert tctx.command(v.resolve, "@focus") == []
|
assert tctx.command(v.resolve, "@focus") == []
|
||||||
assert tctx.command(v.resolve, "@shown") == []
|
assert tctx.command(v.resolve, "@shown") == []
|
||||||
assert tctx.command(v.resolve, "@hidden") == []
|
assert tctx.command(v.resolve, "@hidden") == []
|
||||||
assert tctx.command(v.resolve, "@marked") == []
|
assert tctx.command(v.resolve, "@marked") == []
|
||||||
assert tctx.command(v.resolve, "@unmarked") == []
|
assert tctx.command(v.resolve, "@unmarked") == []
|
||||||
|
assert tctx.command(v.resolve, f"@{f.id}") == []
|
||||||
assert tctx.command(v.resolve, "~m get") == []
|
assert tctx.command(v.resolve, "~m get") == []
|
||||||
v.request(tft(method="get"))
|
v.request(f)
|
||||||
assert len(tctx.command(v.resolve, "~m get")) == 1
|
assert len(tctx.command(v.resolve, "~m get")) == 1
|
||||||
assert len(tctx.command(v.resolve, "@focus")) == 1
|
assert len(tctx.command(v.resolve, "@focus")) == 1
|
||||||
assert len(tctx.command(v.resolve, "@all")) == 1
|
assert len(tctx.command(v.resolve, "@all")) == 1
|
||||||
assert len(tctx.command(v.resolve, "@shown")) == 1
|
assert len(tctx.command(v.resolve, "@shown")) == 1
|
||||||
assert len(tctx.command(v.resolve, "@unmarked")) == 1
|
assert len(tctx.command(v.resolve, "@unmarked")) == 1
|
||||||
|
assert len(tctx.command(v.resolve, f"@{f.id}")) == 1
|
||||||
assert tctx.command(v.resolve, "@hidden") == []
|
assert tctx.command(v.resolve, "@hidden") == []
|
||||||
assert tctx.command(v.resolve, "@marked") == []
|
assert tctx.command(v.resolve, "@marked") == []
|
||||||
v.request(tft(method="put"))
|
v.request(tft(method="put"))
|
||||||
|
assert len(tctx.command(v.resolve, f"@{f.id}")) == 1
|
||||||
assert len(tctx.command(v.resolve, "@focus")) == 1
|
assert len(tctx.command(v.resolve, "@focus")) == 1
|
||||||
assert len(tctx.command(v.resolve, "@shown")) == 2
|
assert len(tctx.command(v.resolve, "@shown")) == 2
|
||||||
assert len(tctx.command(v.resolve, "@all")) == 2
|
assert len(tctx.command(v.resolve, "@all")) == 2
|
||||||
@ -624,4 +628,4 @@ def test_configure():
|
|||||||
[":not valid:", SYMBOL_MARK], [":weird", SYMBOL_MARK]
|
[":not valid:", SYMBOL_MARK], [":weird", SYMBOL_MARK]
|
||||||
])
|
])
|
||||||
def test_marker(marker, expected):
|
def test_marker(marker, expected):
|
||||||
assert render_marker(marker) == expected
|
assert render_marker(marker) == expected
|
||||||
|
@ -18,7 +18,7 @@ import tornado.testing
|
|||||||
from tornado import httpclient
|
from tornado import httpclient
|
||||||
from tornado import websocket
|
from tornado import websocket
|
||||||
|
|
||||||
from mitmproxy import options, optmanager
|
from mitmproxy import certs, options, optmanager
|
||||||
from mitmproxy.test import tflow
|
from mitmproxy.test import tflow
|
||||||
from mitmproxy.tools.web import app
|
from mitmproxy.tools.web import app
|
||||||
from mitmproxy.tools.web import master as webmaster
|
from mitmproxy.tools.web import master as webmaster
|
||||||
@ -39,7 +39,81 @@ def get_json(resp: httpclient.HTTPResponse):
|
|||||||
return _json.loads(resp.body.decode())
|
return _json.loads(resp.body.decode())
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.usefixtures("no_tornado_logging")
|
def test_generate_tflow_js(tdata):
|
||||||
|
tf = tflow.tflow(resp=True, err=True, ws=True)
|
||||||
|
tf.server_conn.certificate_list = [
|
||||||
|
certs.Cert.from_pem(
|
||||||
|
Path(tdata.path("mitmproxy/net/data/verificationcerts/self-signed.pem")).read_bytes()
|
||||||
|
)
|
||||||
|
]
|
||||||
|
tf.request.trailers = Headers(trailer="qvalue")
|
||||||
|
tf.response.trailers = Headers(trailer="qvalue")
|
||||||
|
|
||||||
|
_tflow = app.flow_to_json(tf)
|
||||||
|
# Set some value as constant, so that _tflow.js would not change every time.
|
||||||
|
_tflow['id'] = "d91165be-ca1f-4612-88a9-c0f8696f3e29"
|
||||||
|
_tflow['client_conn']['id'] = "4a18d1a0-50a1-48dd-9aa6-d45d74282939"
|
||||||
|
_tflow['server_conn']['id'] = "f087e7b2-6d0a-41a8-a8f0-e1a4761395f8"
|
||||||
|
tflow_json = _json.dumps(_tflow, indent=4, sort_keys=True)
|
||||||
|
|
||||||
|
tflow_json = re.sub(
|
||||||
|
r'( {8}"(address|is_replay|alpn_proto_negotiated)":)',
|
||||||
|
r" //@ts-ignore\n\1",
|
||||||
|
tflow_json
|
||||||
|
).replace(": null", ": undefined")
|
||||||
|
|
||||||
|
content = (
|
||||||
|
"/** Auto-generated by test_app.py:test_generate_tflow_js */\n"
|
||||||
|
"import {HTTPFlow} from '../../flow';\n"
|
||||||
|
"export default function(): Required<HTTPFlow> {\n"
|
||||||
|
f" return {tflow_json}\n"
|
||||||
|
"}"
|
||||||
|
)
|
||||||
|
(Path(__file__).parent / "../../../../web/src/js/__tests__/ducks/_tflow.ts").write_bytes(
|
||||||
|
content.encode()
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_generate_options_js():
|
||||||
|
o = options.Options()
|
||||||
|
m = webmaster.WebMaster(o)
|
||||||
|
opt: optmanager._Option
|
||||||
|
|
||||||
|
def ts_type(t):
|
||||||
|
if t == bool:
|
||||||
|
return "boolean"
|
||||||
|
if t == str:
|
||||||
|
return "string"
|
||||||
|
if t == int:
|
||||||
|
return "number"
|
||||||
|
if t == typing.Sequence[str]:
|
||||||
|
return "string[]"
|
||||||
|
if t == typing.Optional[str]:
|
||||||
|
return "string | undefined"
|
||||||
|
raise RuntimeError(t)
|
||||||
|
|
||||||
|
with redirect_stdout(io.StringIO()) as s:
|
||||||
|
|
||||||
|
print("/** Auto-generated by test_app.py:test_generate_options_js */")
|
||||||
|
|
||||||
|
print("export interface OptionsState {")
|
||||||
|
for _, opt in sorted(m.options.items()):
|
||||||
|
print(f" {opt.name}: {ts_type(opt.typespec)}")
|
||||||
|
print("}")
|
||||||
|
print("")
|
||||||
|
print("export type Option = keyof OptionsState")
|
||||||
|
print("")
|
||||||
|
print("export const defaultState: OptionsState = {")
|
||||||
|
for _, opt in sorted(m.options.items()):
|
||||||
|
print(f" {opt.name}: {json.dumps(opt.default)},".replace(": null", ": undefined"))
|
||||||
|
print("}")
|
||||||
|
|
||||||
|
(Path(__file__).parent / "../../../../web/src/js/ducks/_options_gen.ts").write_bytes(
|
||||||
|
s.getvalue().encode()
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.usefixtures("no_tornado_logging", "tdata")
|
||||||
class TestApp(tornado.testing.AsyncHTTPTestCase):
|
class TestApp(tornado.testing.AsyncHTTPTestCase):
|
||||||
def get_new_ioloop(self):
|
def get_new_ioloop(self):
|
||||||
io_loop = tornado.platform.asyncio.AsyncIOLoop()
|
io_loop = tornado.platform.asyncio.AsyncIOLoop()
|
||||||
@ -51,6 +125,7 @@ class TestApp(tornado.testing.AsyncHTTPTestCase):
|
|||||||
m = webmaster.WebMaster(o, with_termlog=False)
|
m = webmaster.WebMaster(o, with_termlog=False)
|
||||||
f = tflow.tflow(resp=True)
|
f = tflow.tflow(resp=True)
|
||||||
f.id = "42"
|
f.id = "42"
|
||||||
|
f.request.content = b"foo\nbar"
|
||||||
m.view.add([f])
|
m.view.add([f])
|
||||||
m.view.add([tflow.tflow(err=True)])
|
m.view.add([tflow.tflow(err=True)])
|
||||||
m.log.info("test log")
|
m.log.info("test log")
|
||||||
@ -153,7 +228,8 @@ class TestApp(tornado.testing.AsyncHTTPTestCase):
|
|||||||
"code": 404,
|
"code": 404,
|
||||||
"headers": [("bar", "baz")],
|
"headers": [("bar", "baz")],
|
||||||
"content": "resp",
|
"content": "resp",
|
||||||
}
|
},
|
||||||
|
"marked": ":red_circle:",
|
||||||
}
|
}
|
||||||
assert self.put_json("/flows/42", upd).code == 200
|
assert self.put_json("/flows/42", upd).code == 200
|
||||||
assert f.request.method == "PATCH"
|
assert f.request.method == "PATCH"
|
||||||
@ -252,10 +328,17 @@ class TestApp(tornado.testing.AsyncHTTPTestCase):
|
|||||||
assert f.modified()
|
assert f.modified()
|
||||||
f.revert()
|
f.revert()
|
||||||
|
|
||||||
def test_flow_content_view(self):
|
def test_flow_contentview(self):
|
||||||
assert get_json(self.fetch("/flows/42/request/content/raw")) == {
|
assert get_json(self.fetch("/flows/42/request/content/raw")) == {
|
||||||
"lines": [
|
"lines": [
|
||||||
[["text", "content"]]
|
[["text", "foo"]],
|
||||||
|
[["text", "bar"]]
|
||||||
|
],
|
||||||
|
"description": "Raw"
|
||||||
|
}
|
||||||
|
assert get_json(self.fetch("/flows/42/request/content/raw?lines=1")) == {
|
||||||
|
"lines": [
|
||||||
|
[["text", "foo"]]
|
||||||
],
|
],
|
||||||
"description": "Raw"
|
"description": "Raw"
|
||||||
}
|
}
|
||||||
@ -322,70 +405,3 @@ class TestApp(tornado.testing.AsyncHTTPTestCase):
|
|||||||
# trigger on_close by opening a second connection.
|
# trigger on_close by opening a second connection.
|
||||||
ws_client2 = yield websocket.websocket_connect(ws_url)
|
ws_client2 = yield websocket.websocket_connect(ws_url)
|
||||||
ws_client2.close()
|
ws_client2.close()
|
||||||
|
|
||||||
def test_generate_tflow_js(self):
|
|
||||||
tf = tflow.tflow(resp=True, err=True, ws=True)
|
|
||||||
tf.request.trailers = Headers(trailer="qvalue")
|
|
||||||
tf.response.trailers = Headers(trailer="qvalue")
|
|
||||||
|
|
||||||
_tflow = app.flow_to_json(tf)
|
|
||||||
# Set some value as constant, so that _tflow.js would not change every time.
|
|
||||||
_tflow['id'] = "d91165be-ca1f-4612-88a9-c0f8696f3e29"
|
|
||||||
_tflow['client_conn']['id'] = "4a18d1a0-50a1-48dd-9aa6-d45d74282939"
|
|
||||||
_tflow['server_conn']['id'] = "f087e7b2-6d0a-41a8-a8f0-e1a4761395f8"
|
|
||||||
tflow_json = _json.dumps(_tflow, indent=4, sort_keys=True)
|
|
||||||
|
|
||||||
tflow_json = re.sub(
|
|
||||||
r'( {8}"(address|is_replay|alpn_proto_negotiated)":)',
|
|
||||||
r" //@ts-ignore\n\1",
|
|
||||||
tflow_json
|
|
||||||
).replace(": null", ": undefined")
|
|
||||||
|
|
||||||
content = (
|
|
||||||
"/** Auto-generated by test_app.py:TestApp.test_generate_tflow_js */\n"
|
|
||||||
"import {HTTPFlow} from '../../flow';\n"
|
|
||||||
"export default function(): Required<HTTPFlow> {\n"
|
|
||||||
f" return {tflow_json}\n"
|
|
||||||
"}"
|
|
||||||
)
|
|
||||||
(Path(__file__).parent / "../../../../web/src/js/__tests__/ducks/_tflow.ts").write_bytes(
|
|
||||||
content.encode()
|
|
||||||
)
|
|
||||||
|
|
||||||
def test_generate_options_js(self):
|
|
||||||
o = options.Options()
|
|
||||||
m = webmaster.WebMaster(o)
|
|
||||||
opt: optmanager._Option
|
|
||||||
|
|
||||||
def ts_type(t):
|
|
||||||
if t == bool:
|
|
||||||
return "boolean"
|
|
||||||
if t == str:
|
|
||||||
return "string"
|
|
||||||
if t == int:
|
|
||||||
return "number"
|
|
||||||
if t == typing.Sequence[str]:
|
|
||||||
return "string[]"
|
|
||||||
if t == typing.Optional[str]:
|
|
||||||
return "string | undefined"
|
|
||||||
raise RuntimeError(t)
|
|
||||||
|
|
||||||
with redirect_stdout(io.StringIO()) as s:
|
|
||||||
|
|
||||||
print("/** Auto-generated by test_app.py:TestApp.test_generate_options_js */")
|
|
||||||
|
|
||||||
print("export interface OptionsState {")
|
|
||||||
for _, opt in sorted(m.options.items()):
|
|
||||||
print(f" {opt.name}: {ts_type(opt.typespec)}")
|
|
||||||
print("}")
|
|
||||||
print("")
|
|
||||||
print("export type Option = keyof OptionsState")
|
|
||||||
print("")
|
|
||||||
print("export const defaultState: OptionsState = {")
|
|
||||||
for _, opt in sorted(m.options.items()):
|
|
||||||
print(f" {opt.name}: {json.dumps(opt.default)},".replace(": null", ": undefined"))
|
|
||||||
print("}")
|
|
||||||
|
|
||||||
(Path(__file__).parent / "../../../../web/src/js/ducks/_options_gen.ts").write_bytes(
|
|
||||||
s.getvalue().encode()
|
|
||||||
)
|
|
||||||
|
@ -13,7 +13,8 @@ module.exports = async () => {
|
|||||||
],
|
],
|
||||||
"coverageDirectory": "./coverage",
|
"coverageDirectory": "./coverage",
|
||||||
"coveragePathIgnorePatterns": [
|
"coveragePathIgnorePatterns": [
|
||||||
"<rootDir>/src/js/filt/filt.js"
|
"<rootDir>/src/js/filt/filt.js",
|
||||||
|
"<rootDir>/src/js/filt/command.js"
|
||||||
],
|
],
|
||||||
"collectCoverageFrom": [
|
"collectCoverageFrom": [
|
||||||
"src/js/**/*.{js,jsx,ts,tsx}"
|
"src/js/**/*.{js,jsx,ts,tsx}"
|
||||||
|
@ -1,9 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "mitmproxy",
|
"name": "mitmproxy",
|
||||||
"private": true,
|
"private": true,
|
||||||
"jest": {
|
|
||||||
"verbose": true
|
|
||||||
},
|
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "tsc --noEmit && jest --coverage",
|
"test": "tsc --noEmit && jest --coverage",
|
||||||
"build": "gulp prod",
|
"build": "gulp prod",
|
||||||
|
@ -611,6 +611,121 @@ exports[`FlowView 4`] = `
|
|||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
<h4>
|
||||||
|
Server Certificate
|
||||||
|
</h4>
|
||||||
|
<table
|
||||||
|
class="certificate-table"
|
||||||
|
>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
Type
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
RSA, 2048 bits
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
SHA256 digest
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
e5f62a1175031b6feb959bc8e6dd0f8e2546dbbf7c32da39534309d8aa92967c
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
Valid from
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
2020-11-03 06:03:27
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
Valid to
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
2040-10-29 06:03:27
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
Subject Alternative Names
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
example.mitmproxy.org
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
Subject
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<dl
|
||||||
|
class="cert-attributes"
|
||||||
|
>
|
||||||
|
<dt>
|
||||||
|
C
|
||||||
|
</dt>
|
||||||
|
<dd>
|
||||||
|
AU
|
||||||
|
</dd>
|
||||||
|
<dt>
|
||||||
|
ST
|
||||||
|
</dt>
|
||||||
|
<dd>
|
||||||
|
Some-State
|
||||||
|
</dd>
|
||||||
|
<dt>
|
||||||
|
O
|
||||||
|
</dt>
|
||||||
|
<dd>
|
||||||
|
Internet Widgits Pty Ltd
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
Issuer
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<dl
|
||||||
|
class="cert-attributes"
|
||||||
|
>
|
||||||
|
<dt>
|
||||||
|
C
|
||||||
|
</dt>
|
||||||
|
<dd>
|
||||||
|
AU
|
||||||
|
</dd>
|
||||||
|
<dt>
|
||||||
|
ST
|
||||||
|
</dt>
|
||||||
|
<dd>
|
||||||
|
Some-State
|
||||||
|
</dd>
|
||||||
|
<dt>
|
||||||
|
O
|
||||||
|
</dt>
|
||||||
|
<dd>
|
||||||
|
Internet Widgits Pty Ltd
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
Serial
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
247170098335718583458667965517443538258472437317
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
</DocumentFragment>
|
</DocumentFragment>
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/** Auto-generated by test_app.py:TestApp.test_generate_tflow_js */
|
/** Auto-generated by test_app.py:test_generate_tflow_js */
|
||||||
import {HTTPFlow} from '../../flow';
|
import {HTTPFlow} from '../../flow';
|
||||||
export default function(): Required<HTTPFlow> {
|
export default function(): Required<HTTPFlow> {
|
||||||
return {
|
return {
|
||||||
@ -90,7 +90,47 @@ export default function(): Required<HTTPFlow> {
|
|||||||
22
|
22
|
||||||
],
|
],
|
||||||
"alpn": undefined,
|
"alpn": undefined,
|
||||||
"cert": undefined,
|
"cert": {
|
||||||
|
"altnames": [
|
||||||
|
"example.mitmproxy.org"
|
||||||
|
],
|
||||||
|
"issuer": [
|
||||||
|
[
|
||||||
|
"C",
|
||||||
|
"AU"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"ST",
|
||||||
|
"Some-State"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"O",
|
||||||
|
"Internet Widgits Pty Ltd"
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"keyinfo": [
|
||||||
|
"RSA",
|
||||||
|
2048
|
||||||
|
],
|
||||||
|
"notafter": 2235103407,
|
||||||
|
"notbefore": 1604383407,
|
||||||
|
"serial": "247170098335718583458667965517443538258472437317",
|
||||||
|
"sha256": "e5f62a1175031b6feb959bc8e6dd0f8e2546dbbf7c32da39534309d8aa92967c",
|
||||||
|
"subject": [
|
||||||
|
[
|
||||||
|
"C",
|
||||||
|
"AU"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"ST",
|
||||||
|
"Some-State"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"O",
|
||||||
|
"Internet Widgits Pty Ltd"
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
"cipher": undefined,
|
"cipher": undefined,
|
||||||
"id": "f087e7b2-6d0a-41a8-a8f0-e1a4761395f8",
|
"id": "f087e7b2-6d0a-41a8-a8f0-e1a4761395f8",
|
||||||
"peername": [
|
"peername": [
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/** Auto-generated by test_app.py:TestApp.test_generate_options_js */
|
/** Auto-generated by test_app.py:test_generate_options_js */
|
||||||
export interface OptionsState {
|
export interface OptionsState {
|
||||||
add_upstream_certs_to_client_chain: boolean
|
add_upstream_certs_to_client_chain: boolean
|
||||||
allow_hosts: string[]
|
allow_hosts: string[]
|
||||||
|
Loading…
Reference in New Issue
Block a user