mirror of
https://github.com/Grasscutters/mitmproxy.git
synced 2024-11-25 09:37:37 +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)
|
||||
)
|
||||
)
|
||||
else:
|
||||
else: # pragma: no cover
|
||||
# this should not happen, but we're defensive here.
|
||||
client = ""
|
||||
|
||||
pushed = ' PUSH_PROMISE' if 'h2-pushed-stream' in flow.metadata else ''
|
||||
|
@ -224,22 +224,26 @@ async def test_load(tmpdir):
|
||||
def test_resolve():
|
||||
v = view.View()
|
||||
with taddons.context() as tctx:
|
||||
f = tft(method="get")
|
||||
assert tctx.command(v.resolve, "@all") == []
|
||||
assert tctx.command(v.resolve, "@focus") == []
|
||||
assert tctx.command(v.resolve, "@shown") == []
|
||||
assert tctx.command(v.resolve, "@hidden") == []
|
||||
assert tctx.command(v.resolve, "@marked") == []
|
||||
assert tctx.command(v.resolve, "@unmarked") == []
|
||||
assert tctx.command(v.resolve, f"@{f.id}") == []
|
||||
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, "@focus")) == 1
|
||||
assert len(tctx.command(v.resolve, "@all")) == 1
|
||||
assert len(tctx.command(v.resolve, "@shown")) == 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, "@marked") == []
|
||||
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, "@shown")) == 2
|
||||
assert len(tctx.command(v.resolve, "@all")) == 2
|
||||
@ -624,4 +628,4 @@ def test_configure():
|
||||
[":not valid:", SYMBOL_MARK], [":weird", SYMBOL_MARK]
|
||||
])
|
||||
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 websocket
|
||||
|
||||
from mitmproxy import options, optmanager
|
||||
from mitmproxy import certs, options, optmanager
|
||||
from mitmproxy.test import tflow
|
||||
from mitmproxy.tools.web import app
|
||||
from mitmproxy.tools.web import master as webmaster
|
||||
@ -39,7 +39,81 @@ def get_json(resp: httpclient.HTTPResponse):
|
||||
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):
|
||||
def get_new_ioloop(self):
|
||||
io_loop = tornado.platform.asyncio.AsyncIOLoop()
|
||||
@ -51,6 +125,7 @@ class TestApp(tornado.testing.AsyncHTTPTestCase):
|
||||
m = webmaster.WebMaster(o, with_termlog=False)
|
||||
f = tflow.tflow(resp=True)
|
||||
f.id = "42"
|
||||
f.request.content = b"foo\nbar"
|
||||
m.view.add([f])
|
||||
m.view.add([tflow.tflow(err=True)])
|
||||
m.log.info("test log")
|
||||
@ -153,7 +228,8 @@ class TestApp(tornado.testing.AsyncHTTPTestCase):
|
||||
"code": 404,
|
||||
"headers": [("bar", "baz")],
|
||||
"content": "resp",
|
||||
}
|
||||
},
|
||||
"marked": ":red_circle:",
|
||||
}
|
||||
assert self.put_json("/flows/42", upd).code == 200
|
||||
assert f.request.method == "PATCH"
|
||||
@ -252,10 +328,17 @@ class TestApp(tornado.testing.AsyncHTTPTestCase):
|
||||
assert f.modified()
|
||||
f.revert()
|
||||
|
||||
def test_flow_content_view(self):
|
||||
def test_flow_contentview(self):
|
||||
assert get_json(self.fetch("/flows/42/request/content/raw")) == {
|
||||
"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"
|
||||
}
|
||||
@ -322,70 +405,3 @@ class TestApp(tornado.testing.AsyncHTTPTestCase):
|
||||
# trigger on_close by opening a second connection.
|
||||
ws_client2 = yield websocket.websocket_connect(ws_url)
|
||||
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",
|
||||
"coveragePathIgnorePatterns": [
|
||||
"<rootDir>/src/js/filt/filt.js"
|
||||
"<rootDir>/src/js/filt/filt.js",
|
||||
"<rootDir>/src/js/filt/command.js"
|
||||
],
|
||||
"collectCoverageFrom": [
|
||||
"src/js/**/*.{js,jsx,ts,tsx}"
|
||||
|
@ -1,9 +1,6 @@
|
||||
{
|
||||
"name": "mitmproxy",
|
||||
"private": true,
|
||||
"jest": {
|
||||
"verbose": true
|
||||
},
|
||||
"scripts": {
|
||||
"test": "tsc --noEmit && jest --coverage",
|
||||
"build": "gulp prod",
|
||||
|
@ -611,6 +611,121 @@ exports[`FlowView 4`] = `
|
||||
</tr>
|
||||
</tbody>
|
||||
</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>
|
||||
</div>
|
||||
</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';
|
||||
export default function(): Required<HTTPFlow> {
|
||||
return {
|
||||
@ -90,7 +90,47 @@ export default function(): Required<HTTPFlow> {
|
||||
22
|
||||
],
|
||||
"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,
|
||||
"id": "f087e7b2-6d0a-41a8-a8f0-e1a4761395f8",
|
||||
"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 {
|
||||
add_upstream_certs_to_client_chain: boolean
|
||||
allow_hosts: string[]
|
||||
|
Loading…
Reference in New Issue
Block a user