<commit_before>import asyncio
import json
import sys
from unittest import mock

import flask
import pytest
from flask import request

from .. import tservers
from mitmproxy.addons import asgiapp
from mitmproxy.test import tflow

tapp = flask.Flask(__name__)


@tapp.route("/")
def hello():
    return "testapp"


@tapp.route("/parameters")
def request_check():
    args = {}
    for k in request.args.keys():
        args[k] = request.args[k]
    return json.dumps(args)


@tapp.route("/error")
def error():
    raise ValueError("An exception...")


async def errapp(scope, receive, send):
    raise ValueError("errapp")


async def noresponseapp(scope, receive, send):
    return


class TestApp(tservers.HTTPProxyTest):
    def addons(self):
        return [
            asgiapp.WSGIApp(tapp, "testapp", 80),
            asgiapp.ASGIApp(errapp, "errapp", 80),
            asgiapp.ASGIApp(noresponseapp, "noresponseapp", 80),
        ]

    def test_simple(self):
        p = self.pathoc()
        with p.connect():
            ret = p.request("get:'http://testapp/'")
        assert b"testapp" in ret.content

    def test_parameters(self):
        p = self.pathoc()
        with p.connect():
            ret = p.request("get:'http://testapp/parameters?param1=1&param2=2'")
        assert b'{"param1": "1", "param2": "2"}' == ret.data.content

    def test_app_err(self):
        p = self.pathoc()
        with p.connect():
            ret = p.request("get:'http://errapp/?foo=bar'")
        assert ret.status_code == 500
        assert b"ASGI Error" in ret.content

    def test_app_no_response(self):
        p = self.pathoc()
        with p.connect():
            ret = p.request("get:'http://noresponseapp/'")
        assert ret.status_code == 500
        assert b"ASGI Error" in ret.content

    @pytest.mark.skipif(sys.version_info < (3, 8), reason='requires Python 3.8 or higher')
    def test_app_not_serve_loading_flows(self):
        with mock.patch('mitmproxy.addons.asgiapp.serve') as mck:
            flow = tflow.tflow()
            flow.request.host = "testapp"
            flow.request.port = 80
            asyncio.run_coroutine_threadsafe(self.master.load_flow(flow), self.master.channel.loop).result()
            mck.assert_not_awaited()<commit_msg>asgi: refactor tests to new proxy core<commit_after>import asyncio
import json

import pytest

import flask
from flask import request

from mitmproxy.addons import asgiapp
from mitmproxy.addons.proxyserver import Proxyserver
from mitmproxy.addons import next_layer
from mitmproxy.test import taddons

tapp = flask.Flask(__name__)


@tapp.route("/")
def hello():
    print("CALLED")
    return "testapp"


@tapp.route("/parameters")
def request_check():
    args = {}
    for k in request.args.keys():
        args[k] = request.args[k]
    return json.dumps(args)


@tapp.route("/error")
def error():
    raise ValueError("An exception...")


async def errapp(scope, receive, send):
    raise ValueError("errapp")


async def noresponseapp(scope, receive, send):
    return


@pytest.mark.asyncio
async def test_asgi_full():
    ps = Proxyserver()
    addons = [
        asgiapp.WSGIApp(tapp, "testapp", 80),
        asgiapp.ASGIApp(errapp, "errapp", 80),
        asgiapp.ASGIApp(noresponseapp, "noresponseapp", 80),
    ]
    with taddons.context(ps, *addons) as tctx:
        tctx.master.addons.add(next_layer.NextLayer())
        tctx.configure(ps, listen_host="127.0.0.1", listen_port=0)
        ps.running()
        assert await tctx.master.await_log("Proxy server listening", level="info")
        proxy_addr = ps.server.sockets[0].getsockname()[:2]

        reader, writer = await asyncio.open_connection(*proxy_addr)
        req = f"GET http://testapp:80/ HTTP/1.1\r\n\r\n"
        writer.write(req.encode())
        header = await reader.readuntil(b"\r\n\r\n")
        assert header.startswith(b"HTTP/1.1 200 OK")
        body = await reader.readuntil(b"testapp")
        assert body == b"testapp"

        reader, writer = await asyncio.open_connection(*proxy_addr)
        req = f"GET http://testapp:80/parameters?param1=1&param2=2 HTTP/1.1\r\n\r\n"
        writer.write(req.encode())
        header = await reader.readuntil(b"\r\n\r\n")
        assert header.startswith(b"HTTP/1.1 200 OK")
        body = await reader.readuntil(b"}")
        assert body == b'{"param1": "1", "param2": "2"}'

        reader, writer = await asyncio.open_connection(*proxy_addr)
        req = f"GET http://errapp:80/?foo=bar HTTP/1.1\r\n\r\n"
        writer.write(req.encode())
        header = await reader.readuntil(b"\r\n\r\n")
        assert header.startswith(b"HTTP/1.1 500")
        body = await reader.readuntil(b"ASGI Error")
        assert body == b"ASGI Error"

        reader, writer = await asyncio.open_connection(*proxy_addr)
        req = f"GET http://noresponseapp:80/ HTTP/1.1\r\n\r\n"
        writer.write(req.encode())
        header = await reader.readuntil(b"\r\n\r\n")
        assert header.startswith(b"HTTP/1.1 500")
        body = await reader.readuntil(b"ASGI Error")
        assert body == b"ASGI Error"
{'fraction_non_alphanumeric': 0.1396033771843707, 'fraction_numerical': 0.01668957392499509, 'mean_word_length': 2.8100224382946895, 'pattern_counts': {'":': 4, '<': 4, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 1, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6944604', 'n_tokens_mistral': 1754, 'n_tokens_neox': 1699, 'n_words': 361}