From b132e1ac89d0d685a29ac31ce42417f566a3b327 Mon Sep 17 00:00:00 2001 From: ali ugur Date: Wed, 27 Nov 2024 13:27:52 +0300 Subject: [PATCH] Chore(): Add Django test, simplify Django async test app --- .../django_async_app/django_async_app/urls.py | 6 +- .../django_async_app/testing/views.py | 29 +-------- tests/integration/django/test_workers.py | 64 +++++++------------ tests/integration/flask/test_workers.py | 3 +- 4 files changed, 25 insertions(+), 77 deletions(-) diff --git a/examples/django/django_async_app/django_async_app/django_async_app/urls.py b/examples/django/django_async_app/django_async_app/django_async_app/urls.py index deb38d8..ba482f2 100644 --- a/examples/django/django_async_app/django_async_app/django_async_app/urls.py +++ b/examples/django/django_async_app/django_async_app/django_async_app/urls.py @@ -20,13 +20,9 @@ from django.contrib import admin from django.urls import path -from testing.views import environ, get_settings, login, sleep, user_count +from testing.views import sleep urlpatterns = [ path("admin/", admin.site.urls), - path("settings/", get_settings, name="get_settings"), - path("len/users", user_count, name="user_count"), - path("environ", environ, name="environ"), path("sleep", sleep, name="sleep"), - path("login", login, name="login"), ] diff --git a/examples/django/django_async_app/django_async_app/testing/views.py b/examples/django/django_async_app/django_async_app/testing/views.py index 07b39f7..149129c 100644 --- a/examples/django/django_async_app/django_async_app/testing/views.py +++ b/examples/django/django_async_app/django_async_app/testing/views.py @@ -1,39 +1,12 @@ # Copyright 2024 Canonical Ltd. # See LICENSE file for licensing details. -import os import time -from django.conf import settings -from django.contrib.auth import authenticate -from django.contrib.auth.models import User -from django.http import HttpResponse, JsonResponse - - -def environ(request): - return JsonResponse(dict(os.environ)) - - -def user_count(request): - return JsonResponse(User.objects.count(), safe=False) - - -def get_settings(request, name): - if hasattr(settings, name): - return JsonResponse(getattr(settings, name), safe=False) - else: - return JsonResponse({"error": f"settings {name!r} not found"}, status=404) +from django.http import HttpResponse def sleep(request): duration = request.GET.get("duration") time.sleep(int(duration)) return HttpResponse() - - -def login(request): - user = authenticate(username=request.GET.get("username"), password=request.GET.get("password")) - if user is not None: - return HttpResponse(status=200) - else: - return HttpResponse(status=403) diff --git a/tests/integration/django/test_workers.py b/tests/integration/django/test_workers.py index f65ce27..5f82bb3 100644 --- a/tests/integration/django/test_workers.py +++ b/tests/integration/django/test_workers.py @@ -7,7 +7,9 @@ import logging import time import typing +from datetime import datetime +import aiohttp import pytest import requests from juju.application import Application @@ -18,55 +20,33 @@ logger = logging.getLogger(__name__) -@pytest.mark.parametrize( - "worker_class, expected_result", - [ - ("eventlet", "blocked"), - ("gevent", "active"), - ("sync", "active"), - ], -) @pytest.mark.usefixtures("django_async_app") -async def test_async_workers_config( +async def test_async_workers( ops_test: OpsTest, model: Model, django_async_app: Application, get_unit_ips, - worker_class: str, - expected_result: bool, ): """ - arrange: Django is deployed with async enabled rock. - act: Change gunicorn worker class. - assert: Charm should only let the class to be 'sync' or 'gevent'. - If it is something other than these, then the unit should be blocked. + arrange: Django is deployed with async enabled rock. Change gunicorn worker class. + act: Do 15 requests that would take 2 seconds each. + assert: All 15 requests should be served in under 3 seconds. """ - await django_async_app.set_config({"webserver-worker-class": worker_class}) - await model.wait_for_idle(apps=[django_async_app.name], status=expected_result, timeout=60) + await django_async_app.set_config({"webserver-worker-class": "gevent"}) + await model.wait_for_idle(apps=[django_async_app.name], status="active", timeout=60) + # the django unit is not important. Take the first one + django_unit_ip = (await get_unit_ips(django_async_app.name))[0] -@pytest.mark.parametrize( - "worker_class, expected_result", - [ - ("gevent", "blocked"), - ("eventlet", "blocked"), - ("sync", "active"), - ], -) -@pytest.mark.usefixtures("django_app") -async def test_async_workers_config_fail( - ops_test: OpsTest, - model: Model, - django_app: Application, - get_unit_ips, - worker_class: str, - expected_result: str, -): - """ - arrange: Django is deployed with async not enabled rock. - act: Change gunicorn worker class. - assert: Charm should only let the class to be 'sync'. - If it is 'gevent' or something else, then the unit should be blocked. - """ - await django_app.set_config({"webserver-worker-class": worker_class}) - await model.wait_for_idle(apps=[django_app.name], status=expected_result, timeout=60) + async def _fetch_page(session): + params = {"duration": 2} + async with session.get(f"http://{django_unit_ip}:8000/sleep", params=params) as response: + return await response.text() + + start_time = datetime.now() + async with aiohttp.ClientSession() as session: + pages = [_fetch_page(session) for _ in range(15)] + await asyncio.gather(*pages) + assert ( + datetime.now() - start_time + ).seconds < 3, "Async workers for Django are not working!" diff --git a/tests/integration/flask/test_workers.py b/tests/integration/flask/test_workers.py index a208db8..323992c 100644 --- a/tests/integration/flask/test_workers.py +++ b/tests/integration/flask/test_workers.py @@ -99,7 +99,6 @@ async def _fetch_page(session): async with aiohttp.ClientSession() as session: pages = [_fetch_page(session) for _ in range(15)] await asyncio.gather(*pages) - print(f"TIMME: {(datetime.now() - start_time).seconds}") assert ( datetime.now() - start_time - ).seconds < 3, "The page took more than 2 seconds to load" + ).seconds < 3, "Async workers for Flask are not working!"