Exemple #1
0
def test_lifespan_scope_default_version():
    app = App()

    resource = testing.SimpleTestResourceAsync()

    app.add_route('/', resource)

    shutting_down = asyncio.Condition()
    req_event_emitter = testing.ASGILifespanEventEmitter(shutting_down)
    resp_event_collector = testing.ASGIResponseEventCollector()

    scope = {'type': 'lifespan'}

    async def t():
        t = asyncio.get_event_loop().create_task(
            app(scope, req_event_emitter, resp_event_collector))

        # NOTE(kgriffs): Yield to the lifespan task above
        await asyncio.sleep(0.001)

        async with shutting_down:
            shutting_down.notify()

        await t

    falcon.invoke_coroutine_sync(t)

    assert not resource.called
Exemple #2
0
def test_lifespan_scope_version(spec_version, supported):
    app = App()

    shutting_down = asyncio.Condition()
    req_event_emitter = testing.ASGILifespanEventEmitter(shutting_down)
    resp_event_collector = testing.ASGIResponseEventCollector()

    scope = {
        'type': 'lifespan',
        'asgi': {'spec_version': spec_version, 'version': '3.0'}
    }

    if not supported:
        with pytest.raises(UnsupportedScopeError):
            falcon.async_to_sync(
                app.__call__, scope, req_event_emitter, resp_event_collector
            )

        return

    async def t():
        t = asyncio.get_event_loop().create_task(
            app(scope, req_event_emitter, resp_event_collector)
        )

        # NOTE(kgriffs): Yield to the lifespan task above
        await asyncio.sleep(0.001)

        async with shutting_down:
            shutting_down.notify()

        await t

    falcon.async_to_sync(t)
Exemple #3
0
async def test_ignore_extra_asgi_events():
    collect = testing.ASGIResponseEventCollector()

    await collect({'type': 'http.response.start', 'status': 200})
    await collect({'type': 'http.response.body', 'more_body': False})

    # NOTE(kgriffs): Events after more_body is False are ignored to conform
    #   to the ASGI spec.
    await collect({'type': 'http.response.body'})
    assert len(collect.events) == 2
Exemple #4
0
def _call_with_scope(scope):
    app = App()

    resource = testing.SimpleTestResourceAsync()

    app.add_route('/', resource)

    req_event_emitter = testing.ASGIRequestEventEmitter()
    resp_event_collector = testing.ASGIResponseEventCollector()

    falcon.invoke_coroutine_sync(app.__call__, scope, req_event_emitter,
                                 resp_event_collector)

    assert resource.called
    return resource
Exemple #5
0
async def test_invalid_asgi_events():
    collect = testing.ASGIResponseEventCollector()

    def make_event(headers=None, status=200):
        return {
            'type': 'http.response.start',
            'headers': headers or [],
            'status': status
        }

    with pytest.raises(TypeError):
        await collect({'type': 123})

    with pytest.raises(TypeError):
        headers = [
            ('notbytes', b'bytes')
        ]
        await collect(make_event(headers))

    with pytest.raises(TypeError):
        headers = [
            (b'bytes', 'notbytes')
        ]
        await collect(make_event(headers))

    with pytest.raises(ValueError):
        headers = [
            # NOTE(kgriffs): Name must be lowercase
            (b'Content-Type', b'application/json')
        ]
        await collect(make_event(headers))

    with pytest.raises(TypeError):
        await collect(make_event(status='200'))

    with pytest.raises(TypeError):
        await collect(make_event(status=200.1))

    with pytest.raises(TypeError):
        await collect({'type': 'http.response.body', 'body': 'notbytes'})

    with pytest.raises(TypeError):
        await collect({'type': 'http.response.body', 'more_body': ''})

    with pytest.raises(ValueError):
        # NOTE(kgriffs): Invalid type
        await collect({'type': 'http.response.bod'})
Exemple #6
0
def test_supported_asgi_version(version, supported):
    scope = {
        'type': 'lifespan',
        'asgi': {
            'spec_version': '2.0',
            'version': version
        },
    }
    if version is None:
        del scope['asgi']['version']

    app = App()

    resource = testing.SimpleTestResourceAsync()
    app.add_route('/', resource)

    shutting_down = asyncio.Condition()
    req_event_emitter = testing.ASGILifespanEventEmitter(shutting_down)
    resp_event_collector = testing.ASGIResponseEventCollector()

    async def task():
        coro = asyncio.get_event_loop().create_task(
            app(scope, req_event_emitter, resp_event_collector))

        # NOTE(vytas): Yield to the lifespan task above.
        await asyncio.sleep(0)

        assert len(resp_event_collector.events) == 1
        event = resp_event_collector.events[0]
        if supported:
            assert event['type'] == 'lifespan.startup.complete'
        else:
            assert event['type'] == 'lifespan.startup.failed'
            assert event['message'].startswith(
                'Falcon requires ASGI version 3.x')

        async with shutting_down:
            shutting_down.notify()

        await coro

    falcon.async_to_sync(task)