Beispiel #1
0
async def test_muliple_sessions():
    """
    Create two application instances and test then out of order to verify that
    separate scopes are used.
    """
    async def inner(scope, receive, send):
        send(scope["path"])

    class SimpleHttpApp(AsyncConsumer):
        async def http_request(self, event):
            await database_sync_to_async(self.scope["session"].save)()
            assert self.scope["method"] == "GET"
            await self.send({
                "type": "http.response.start",
                "status": 200,
                "headers": []
            })
            await self.send({
                "type": "http.response.body",
                "body": self.scope["path"].encode()
            })

    app = SessionMiddlewareStack(SimpleHttpApp.as_asgi())

    first_communicator = HttpCommunicator(app, "GET", "/first/")
    second_communicator = HttpCommunicator(app, "GET", "/second/")

    second_response = await second_communicator.get_response()
    assert second_response["body"] == b"/second/"

    first_response = await first_communicator.get_response()
    assert first_response["body"] == b"/first/"
async def test_per_scope_consumers():
    """
    Tests that a distinct consumer is used per scope, with AsyncHttpConsumer as
    the example consumer class.
    """
    class TestConsumer(AsyncHttpConsumer):
        def __init__(self):
            super().__init__()
            self.time = time.time()

        async def handle(self, body):
            body = f"{self.__class__.__name__} {id(self)} {self.time}"

            await self.send_response(
                200,
                body.encode("utf-8"),
                headers={b"Content-Type": b"text/plain"},
            )

    app = TestConsumer.as_asgi()

    # Open a connection
    communicator = HttpCommunicator(app, method="GET", path="/test/")
    response = await communicator.get_response()
    assert response["status"] == 200

    # And another one.
    communicator = HttpCommunicator(app, method="GET", path="/test2/")
    second_response = await communicator.get_response()
    assert second_response["status"] == 200

    assert response["body"] != second_response["body"]
        async def test_body():
            user, order = await database_sync_to_async(init_db)()

            awaitable_requestor = asyncio.coroutine(
                MagicMock(return_value=b"SHIPPED"))

            with patch.object(consumers.OrderTrackerConsumer,
                              "query_remote_server") as mock_requestor:
                mock_requestor.side_effect = awaitable_requestor
                communicator = HttpCommunicator(
                    consumers.OrderTrackerConsumer,
                    "GET",
                    "/mobile-api/my-orders/%d/tracker/" % order.id,
                )
                communicator.scope["user"] = user
                communicator.scope["url_route"] = {
                    "kwargs": {
                        "order_id": order.id
                    }
                }

                response = await communicator.get_response()
                data = response["body"].decode("utf8")

                mock_requestor.assert_called_once()
                self.assertEquals(data, "SHIPPED")
        async def test_body():
            user, order, notify_user = await database_sync_to_async(init_db)()

            communicator = WebsocketCommunicator(
                consumers.ChatConsumer,
                "/ws/customer-service/%d/" % order.id,
            )
            communicator.scope["user"] = user
            communicator.scope["url_route"] = {
                "kwargs": {
                    "order_id": order.id
                }
            }
            connected, _ = await communicator.connect()
            self.assertTrue(connected)

            await communicator.send_json_to({"type": "heartbeat"})
            await communicator.disconnect()

            communicator = HttpCommunicator(
                consumers.ChatNotifyConsumer,
                "GET",
                "/customer-service/notify/",
            )
            communicator.scope["user"] = notify_user
            communicator.scope["query_string"] = "nopoll"

            response = await communicator.get_response()
            self.assertTrue(response["body"].startswith(b"data: "))
            payload = response["body"][6:]
            data = json.loads(payload.decode("utf8"))
            self.assertEquals(
                data,
                [{
                    "link": "/customer-service/%d/" % order.id,
                    "text": "%d ([email protected])" % order.id,
                }],
                "expecting someone in the room but noone found",
            )

            await asyncio.sleep(10)

            communicator = HttpCommunicator(
                consumers.ChatNotifyConsumer,
                "GET",
                "/customer-service/notify/",
            )
            communicator.scope["user"] = notify_user
            communicator.scope["query_string"] = "nopoll"
            response = await communicator.get_response()
            self.assertTrue(response["body"].startswith(b"data: "))
            payload = response["body"][6:]
            data = json.loads(payload.decode("utf8"))
            self.assertEquals(
                data,
                [],
                "expecting noone in the room but someone found",
            )
Beispiel #5
0
async def test_sessions():
    app = SimpleHttpApp()

    communicator = HttpCommunicator(SessionMiddlewareStack(app), "GET",
                                    "/test/")
    response = await communicator.get_response()
    headers = response.get("headers", [])

    assert len(headers) == 1
    name, value = headers[0]

    assert name == b"Set-Cookie"
    value = value.decode("utf-8")

    assert re.compile(r"sessionid=").search(value) is not None

    assert re.compile(r"expires=").search(value) is not None

    assert re.compile(r"HttpOnly").search(value) is not None

    assert re.compile(r"Max-Age").search(value) is not None

    assert re.compile(r"Path").search(value) is not None

    samesite = re.compile(r"SameSite=(\w+)").search(value)
    assert samesite is not None
    assert samesite.group(1) == "Lax"
Beispiel #6
0
async def test_basic(sentry_init, capture_events, application):
    sentry_init(integrations=[DjangoIntegration()], send_default_pii=True)
    events = capture_events()

    comm = HttpCommunicator(application, "GET", "/view-exc?test=query")
    response = await comm.get_response()
    assert response["status"] == 500

    event, = events

    exception, = event["exception"]["values"]
    assert exception["type"] == "ZeroDivisionError"

    # Test that the ASGI middleware got set up correctly. Right now this needs
    # to be installed manually (see myapp/asgi.py)
    assert event["transaction"] == "/view-exc"
    assert event["request"] == {
        "cookies": {},
        "headers": {},
        "method": "GET",
        "query_string": "test=query",
        "url": "/view-exc",
    }

    capture_message("hi")
    event = events[-1]
    assert "request" not in event
Beispiel #7
0
async def test_async_middleware_spans(sentry_init, render_span_tree,
                                      capture_events, settings):
    settings.MIDDLEWARE = [
        "django.contrib.sessions.middleware.SessionMiddleware",
        "django.contrib.auth.middleware.AuthenticationMiddleware",
        "django.middleware.csrf.CsrfViewMiddleware",
        "tests.integrations.django.myapp.settings.TestMiddleware",
    ]
    asgi_application.load_middleware(is_async=True)

    sentry_init(
        integrations=[DjangoIntegration(middleware_spans=True)],
        traces_sample_rate=1.0,
        _experiments={"record_sql_params": True},
    )

    events = capture_events()

    comm = HttpCommunicator(asgi_application, "GET", "/async_message")
    response = await comm.get_response()
    assert response["status"] == 200

    await comm.wait()

    message, transaction = events

    assert (render_span_tree(transaction) == """\
- op="http.server": description=null
  - op="django.middleware": description="django.contrib.sessions.middleware.SessionMiddleware.__acall__"
    - op="django.middleware": description="django.contrib.auth.middleware.AuthenticationMiddleware.__acall__"
      - op="django.middleware": description="django.middleware.csrf.CsrfViewMiddleware.__acall__"
        - op="django.middleware": description="tests.integrations.django.myapp.settings.TestMiddleware.__acall__"
          - op="django.middleware": description="django.middleware.csrf.CsrfViewMiddleware.process_view"
          - op="django.view": description="async_message\"""")
async def test_async_http_consumer():
    """
    Tests that AsyncHttpConsumer is implemented correctly.
    """
    class TestConsumer(AsyncHttpConsumer):
        async def handle(self, body):
            data = json.loads(body.decode("utf-8"))
            await self.send_response(
                200,
                json.dumps({
                    "value": data["value"]
                }).encode("utf-8"),
                headers={b"Content-Type": b"application/json"},
            )

    app = TestConsumer()

    # Open a connection
    communicator = HttpCommunicator(
        app,
        method="POST",
        path="/test/",
        body=json.dumps({
            "value": 42,
            "anything": False
        }).encode("utf-8"),
    )
    response = await communicator.get_response()
    assert response["body"] == b'{"value": 42}'
    assert response["status"] == 200
    assert response["headers"] == [(b"Content-Type", b"application/json")]
Beispiel #9
0
async def test_async_http_consumer():
    """
    Tests that AsyncHttpConsumer is implemented correctly.
    """
    class TestConsumer(AsyncHttpConsumer):
        async def handle(self, body):
            self.is_streaming = True
            await self.send_headers(headers=[
                (b"Cache-Control", b"no-cache"),
                (b"Content-Type", b"text/event-stream"),
                (b"Transfer-Encoding", b"chunked"),
            ])
            asyncio.get_event_loop().create_task(self.stream())

        async def stream(self):
            for n in range(0, 3):
                if not self.is_streaming:
                    break
                payload = "data: %d\n\n" % (n + 1)
                await self.send_body(payload.encode("utf-8"), more_body=True)
                await asyncio.sleep(0.2)
            await self.send_body(b"")

        async def disconnect(self):
            self.is_streaming = False

    # Open a connection
    communicator = HttpCommunicator(TestConsumer,
                                    method="GET",
                                    path="/test/",
                                    body=b"")
    response = await communicator.get_response()
    assert response["body"] == b"data: 1\n\ndata: 2\n\ndata: 3\n\n"
    assert response["status"] == 200
Beispiel #10
0
        async def test_body():
            user, order, cs_user = await database_sync_to_async(init_db)()
            communicator = WebsocketCommunicator(
                consumers.ChatConsumer,
                "/ws/me2ushop/customer-service/%d/" % order.id,
            )
            communicator.scope['user'] = user
            communicator.scope['url_route'] = {
                'kwargs': {
                    'order_id': order.id
                }
            }
            connected, _ = await communicator.connect()
            self.assertTrue(connected)

            await communicator.send_json_to({'type': 'heartbeat'})
            await communicator.disconnect()

            communicator = HttpCommunicator(
                consumers.ChatNotifyConsumer, 'GET',
                'me2ushop/customer-service/notify/')
            communicator.scope['user'] = cs_user
            communicator.scope['query_string'] = 'nopoll'

            response = await communicator.get_response()
            self.assertTrue(response["body"].startswith(b"data: "))
            payload = response['body'][6:]
            data = json.loads(payload.decode('utf8'))
            self.assertEquals(
                data, [{
                    "link": "/me2ushop/customer-service/%d/" % order.id,
                    "text": "%d ([email protected])" % order.id,
                }], 'expecting someone in the room but on one found')
            await asyncio.sleep(10)
            communicator = HttpCommunicator(
                consumers.ChatNotifyConsumer, 'GET',
                'me2ushop/customer-service/notify/')
            communicator.scope['user'] = cs_user
            communicator.scope['query_string'] = 'nopoll'

            response = await communicator.get_response()
            self.assertTrue(response["body"].startswith(b"data: "))
            payload = response['body'][6:]
            data = json.loads(payload.decode('utf8'))
            self.assertEquals(
                data, [], 'expecting on one in the room but someone found')
Beispiel #11
0
async def test_http_communicator():
    """
    Tests that the HTTP communicator class works at a basic level.
    """
    communicator = HttpCommunicator(SimpleHttpApp, "GET", "/test/?foo=bar")
    response = await communicator.get_response()
    assert response["body"] == b"test response"
    assert response["status"] == 200
Beispiel #12
0
async def test_session_samesite_invalid(samesite_invalid):
    app = SimpleHttpApp()

    communicator = HttpCommunicator(SessionMiddlewareStack(app), "GET",
                                    "/test/")

    with pytest.raises(AssertionError):
        await communicator.get_response()
Beispiel #13
0
 async def get(self, path, headers=None, user=None):
     if user:
         headers = await self._login(headers, user)
     communicator = HttpCommunicator(self.app,
                                     method='GET',
                                     path=path,
                                     headers=headers)
     r = await communicator.get_response()
     return Response(**r)
Beispiel #14
0
async def test_async_views_concurrent_execution(sentry_init, capture_events,
                                                settings):
    import asyncio
    import time

    settings.MIDDLEWARE = []
    asgi_application.load_middleware(is_async=True)

    sentry_init(integrations=[DjangoIntegration()], send_default_pii=True)

    comm = HttpCommunicator(asgi_application, "GET", "/my_async_view")
    comm2 = HttpCommunicator(asgi_application, "GET", "/my_async_view")

    loop = asyncio.get_event_loop()

    start = time.time()

    r1 = loop.create_task(comm.get_response(timeout=5))
    r2 = loop.create_task(comm2.get_response(timeout=5))

    (resp1, resp2), _ = await asyncio.wait({r1, r2})

    end = time.time()

    assert resp1.result()["status"] == 200
    assert resp2.result()["status"] == 200

    assert end - start < 1.5
Beispiel #15
0
 async def post(self, path, body=None, headers=None, user=None):
     if not isinstance(body, bytes):
         data = body or {}
         body = dumps(data).encode('utf-8')
     if user:
         headers = await self._login(headers, user)
     communicator = HttpCommunicator(self.app,
                                     method='POST',
                                     path=path,
                                     body=body,
                                     headers=headers)
     r = await communicator.get_response()
     return Response(**r)
Beispiel #16
0
        async def test_body():
            user, order = await database_sync_to_async(init_db)()
            awaitable_reqestor = asyncio.coroutine(
                MagicMock(return_value=b"SHIPPED"))
            with patch.object(consumers.OrderTrackerConsumer,
                              'query_remote_server') as mock_requestor:
                mock_requestor.side_effect = awaitable_reqestor
                communicator = HttpCommunicator(
                    consumers.OrderTrackerConsumer,
                    'GET',
                    '/mobile-api/my-orders/%d/tracker/' % order.id,
                )
                communicator.scope['user'] = user
                communicator.scope['url_route'] = {
                    'kwargs': {
                        'order_id': order.id
                    }
                }
                response = await communicator.get_response()
                data = response['body'].decode('utf8')

                mock_requestor.assert_called_once()
                self.assertEquals(data, 'SHIPPED')
Beispiel #17
0
async def test_session_samesite(samesite, settings):
    app = SimpleHttpApp()

    communicator = HttpCommunicator(SessionMiddlewareStack(app), "GET",
                                    "/test/")
    response = await communicator.get_response()
    headers = response.get("headers", [])

    assert len(headers) == 1
    name, value = headers[0]

    assert name == b"Set-Cookie"
    value = value.decode("utf-8")

    samesite = re.compile(r"SameSite=(\w+)").search(value)
    assert samesite is not None
    assert samesite.group(1) == settings.SESSION_COOKIE_SAMESITE
Beispiel #18
0
async def test_async_views(sentry_init, capture_events, application):
    sentry_init(integrations=[DjangoIntegration()], send_default_pii=True)

    events = capture_events()

    comm = HttpCommunicator(application, "GET", "/async_message")
    response = await comm.get_response()
    assert response["status"] == 200

    (event, ) = events

    assert event["transaction"] == "/async_message"
    assert event["request"] == {
        "cookies": {},
        "headers": {},
        "method": "GET",
        "query_string": None,
        "url": "/async_message",
    }
Beispiel #19
0
async def test_sessions():
    class SimpleHttpApp(AsyncConsumer):
        """
        Barebones HTTP ASGI app for testing.
        """
        async def http_request(self, event):
            await database_sync_to_async(self.scope["session"].save)()
            assert self.scope["path"] == "/test/"
            assert self.scope["method"] == "GET"
            await self.send({
                "type": "http.response.start",
                "status": 200,
                "headers": []
            })
            await self.send({
                "type": "http.response.body",
                "body": b"test response"
            })

    app = SimpleHttpApp()

    communicator = HttpCommunicator(SessionMiddlewareStack(app), "GET",
                                    "/test/")
    response = await communicator.get_response()
    headers = response.get("headers", [])

    assert len(headers) == 1
    name, value = headers[0]

    assert name == b"Set-Cookie"
    value = value.decode("utf-8")

    assert re.compile(r"sessionid=").search(value) is not None

    assert re.compile(r"expires=").search(value) is not None

    assert re.compile(r"HttpOnly").search(value) is not None

    assert re.compile(r"Max-Age").search(value) is not None

    assert re.compile(r"Path").search(value) is not None
async def test_my_consumer():
    communicator = HttpCommunicator(NotificationConsumer, "GET", "/test/")
    response = await communicator.get_response()
    assert response["body"] == b"test response"
    assert response["status"] == 200
    connected, _ = await communicator.connect()
    assert connected

    await communicator.send_json_to({
        "model": "as.Appropriate",
        "id": str(Foo.id),
    })
    assert await communicator.receive_nothing()

    await update_foo()
    response = await communicator.receive_json_from()
    assert response == {
        # ... whatever you expect
    }

    await communicator.disconnect()
Beispiel #21
0
async def test_file_uploading():
    body = (
        b"--BOUNDARY\r\n" +
        b'Content-Disposition: form-data; name="title"\r\n\r\n' +
        b"My First Book\r\n" + b"--BOUNDARY\r\n" +
        b'Content-Disposition: form-data; name="pdf"; filename="book.pdf"\r\n\r\n'
        + b"FAKEPDFBYTESGOHERE" + b"--BOUNDARY--")
    headers = {
        "content-type": b"multipart/form-data; boundary=BOUNDARY",
        "content-length": str(len(body)).encode("ascii"),
    }

    class SimpleHttpApp(AsyncConsumer):
        """
        Barebones HTTP ASGI app for testing.
        """
        async def http_request(self, event):
            # self.scope["session"].save()
            assert self.scope["path"] == "/test_upload/"
            assert self.scope["method"] == "POST"
            await self.send({
                "type": "http.response.start",
                "status": 201,
                "headers": [],
            })
            await self.send({
                "type": "http.response.body",
                "body": b'{"result": "great success!"}',
            })

    communicator = HttpCommunicator(SimpleHttpApp,
                                    "POST",
                                    "/test_upload/",
                                    body=body,
                                    headers=headers)
    response = await communicator.get_response()
    assert response["body"] == b'{"result": "great success!"}'
    assert response["status"] == 201
Beispiel #22
0
async def test_async_http_consumer_with_channel_layer():
    """
    Tests that AsyncHttpConsumer is implemented correctly.
    """
    class TestConsumer(AsyncHttpConsumer):
        """
        Abstract consumer that provides a method that handles running a command and getting a response on a
        device.
        """

        channel_layer_alias = "testlayer"

        async def handle(self, body):
            # Add consumer to a known test group that we will use to send events to.
            await self.channel_layer.group_add("test_group", self.channel_name)
            await self.send_headers(status=200,
                                    headers=[(b"Content-Type",
                                              b"application/json")])

        async def send_to_long_poll(self, event):
            received_data = str(event["data"]).encode("utf8")
            # We just echo what we receive, and close the response.
            await self.send_body(received_data, more_body=False)

    channel_layers_setting = {
        "testlayer": {
            "BACKEND": "channels.layers.InMemoryChannelLayer"
        }
    }

    with override_settings(CHANNEL_LAYERS=channel_layers_setting):
        # Open a connection
        communicator = HttpCommunicator(
            TestConsumer,
            method="POST",
            path="/test/",
            body=json.dumps({
                "value": 42,
                "anything": False
            }).encode("utf-8"),
        )

        # We issue the HTTP request
        await communicator.send_request()

        # Gets the response start (status and headers)
        response_start = await communicator.get_response_start(timeout=1)

        # Make sure that the start of the response looks good so far.
        assert response_start["status"] == 200
        assert response_start["headers"] == [(b"Content-Type",
                                              b"application/json")]

        # Send now a message to the consumer through the channel layer. Using the known test_group.
        channel_layer = get_channel_layer("testlayer")
        await channel_layer.group_send(
            "test_group",
            {
                "type": "send.to.long.poll",
                "data": "hello from channel layer"
            },
        )

        # Now we should be able to get the message back on the remaining chunk of body.
        body = await communicator.get_body_chunk(timeout=1)
        assert body == b"hello from channel layer"
Beispiel #23
0
async def test_my_consumer():
    communicator = HttpCommunicator(ChatConsumer, "GET", "/test/")
    response = await communicator.get_response()
    assert response["body"] == b"test response"
    assert response["status"] == 200
Beispiel #24
0
async def test_my_consumer():
    communicator = HttpCommunicator(TickerConsumer, "GET", "/test/")
    response = await communicator.get_response()
    self.assertEqual(response["body"], b"test response")
    self.assertEqual(response["status"], 200)
Beispiel #25
0
async def test_news_collector_consumer():
    communicator = HttpCommunicator(NewsCollectorAsyncConsumer, "GET",
                                    "/collector/collect_news_async/")
    response = await communicator.get_response()
    assert response["status"] == 200
Beispiel #26
0
 async def test_0090_test_consumer(self):
     communicator = HttpCommunicator(WSConsumer, 'GET',
                                     '/communication/websocket')
     response = await communicator.get_response()
     self.assertTrue(response['status'] == 200)