Skip to content

Commit 42d9477

Browse files
committed
webserver tests
1 parent 13543c3 commit 42d9477

File tree

3 files changed

+51
-242
lines changed

3 files changed

+51
-242
lines changed

services/web/server/tests/unit/with_dbs/01/test_storage.py renamed to services/web/server/tests/unit/with_dbs/01/storage/conftest.py

Lines changed: 51 additions & 240 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,16 @@
66
import logging
77
import random
88
from collections.abc import Iterator
9+
from pathlib import Path
910
from threading import Thread
10-
from typing import Any
11-
from urllib.parse import quote
11+
from typing import Annotated
1212

1313
import pytest
1414
import uvicorn
15-
from aiohttp.test_utils import TestClient
1615
from faker import Faker
17-
from fastapi import APIRouter, FastAPI, Request
16+
from fastapi import APIRouter, Depends, FastAPI, Request, status
17+
from fastapi_pagination import add_pagination, create_page
18+
from fastapi_pagination.cursor import CursorPage, CursorParams
1819
from models_library.api_schemas_storage.storage_schemas import (
1920
DatasetMetaDataGet,
2021
FileLocation,
@@ -24,30 +25,29 @@
2425
FileUploadCompletionBody,
2526
FileUploadSchema,
2627
LinkType,
28+
PathMetaDataGet,
2729
)
2830
from models_library.generics import Envelope
2931
from models_library.projects import ProjectID
3032
from models_library.projects_nodes_io import LocationID, StorageFileID
3133
from models_library.users import UserID
3234
from pydantic import AnyUrl, TypeAdapter
33-
from pytest_simcore.helpers.assert_checks import assert_status
3435
from pytest_simcore.helpers.logging_tools import log_context
35-
from servicelib.aiohttp import status
36+
from pytest_simcore.helpers.monkeypatch_envs import setenvs_from_dict
3637
from servicelib.utils import unused_port
37-
from simcore_postgres_database.models.users import UserRole
3838
from yarl import URL
3939

40-
API_VERSION = "v0"
41-
4240

4341
@pytest.fixture(scope="session")
4442
def storage_vtag() -> str:
4543
return "v9"
4644

4745

4846
@pytest.fixture(scope="module")
49-
def fake_storage_app(storage_vtag: str) -> FastAPI:
47+
def fake_storage_app(storage_vtag: str) -> FastAPI: # noqa: C901
5048
app = FastAPI(debug=True)
49+
add_pagination(app)
50+
5151
router = APIRouter(
5252
prefix=f"/{storage_vtag}",
5353
)
@@ -75,6 +75,37 @@ async def _list_storage_locations(user_id: UserID, request: Request):
7575
]
7676
)
7777

78+
@router.get(
79+
"/locations/{location_id}/paths",
80+
response_model=CursorPage[PathMetaDataGet],
81+
)
82+
async def _list_paths(
83+
page_params: Annotated[CursorParams, Depends()],
84+
# dsm: Annotated[BaseDataManager, Depends(get_data_manager)],
85+
user_id: UserID,
86+
file_filter: Path | None = None,
87+
):
88+
assert user_id
89+
assert "json_schema_extra" in PathMetaDataGet.model_config
90+
assert isinstance(PathMetaDataGet.model_config["json_schema_extra"], dict)
91+
assert isinstance(
92+
PathMetaDataGet.model_config["json_schema_extra"]["examples"], list
93+
)
94+
95+
example_index = len(file_filter.parts) if file_filter else 0
96+
assert example_index < len(
97+
PathMetaDataGet.model_config["json_schema_extra"]["examples"]
98+
), "fake server unable to server this example"
99+
chosen_example = PathMetaDataGet.model_config["json_schema_extra"]["examples"][
100+
example_index
101+
]
102+
103+
return create_page(
104+
random.randint(3, 15) * [PathMetaDataGet.model_validate(chosen_example)],
105+
params=page_params,
106+
next_=None,
107+
)
108+
78109
@router.get(
79110
"/locations/{location_id}/files/metadata",
80111
response_model=Envelope[list[FileMetaDataGet]],
@@ -296,238 +327,18 @@ def app_environment(
296327
monkeypatch: pytest.MonkeyPatch,
297328
) -> dict[str, str]:
298329
# NOTE: overrides app_environment
299-
monkeypatch.setenv("STORAGE_PORT", f"{fake_storage_server.port}")
300-
monkeypatch.setenv("STORAGE_VTAG", storage_vtag)
301-
monkeypatch.setenv("WEBSERVER_GARBAGE_COLLECTOR", "null")
302-
return app_environment | {"WEBSERVER_GARBAGE_COLLECTOR": "null"}
303-
304-
305-
# --------------------------------------------------------------------------
306-
PREFIX = "/" + API_VERSION + "/storage"
307330

308-
309-
@pytest.mark.parametrize(
310-
"user_role,expected",
311-
[
312-
(UserRole.ANONYMOUS, status.HTTP_401_UNAUTHORIZED),
313-
(UserRole.GUEST, status.HTTP_200_OK),
314-
(UserRole.USER, status.HTTP_200_OK),
315-
(UserRole.TESTER, status.HTTP_200_OK),
316-
],
317-
)
318-
async def test_list_storage_locations(
319-
client: TestClient,
320-
logged_user: dict[str, Any],
321-
expected: int,
322-
):
323-
url = "/v0/storage/locations"
324-
assert url.startswith(PREFIX)
325-
326-
resp = await client.get(url, params={"user_id": logged_user["id"]})
327-
data, error = await assert_status(resp, expected)
328-
329-
if not error:
330-
assert "json_schema_extra" in FileLocation.model_config
331-
assert isinstance(FileLocation.model_config["json_schema_extra"], dict)
332-
assert isinstance(
333-
FileLocation.model_config["json_schema_extra"]["examples"], list
334-
)
335-
assert len(data) == len(
336-
FileLocation.model_config["json_schema_extra"]["examples"]
337-
)
338-
assert data == FileLocation.model_config["json_schema_extra"]["examples"]
339-
340-
341-
@pytest.mark.parametrize(
342-
"user_role,expected",
343-
[
344-
(UserRole.ANONYMOUS, status.HTTP_401_UNAUTHORIZED),
345-
(UserRole.GUEST, status.HTTP_200_OK),
346-
(UserRole.USER, status.HTTP_200_OK),
347-
(UserRole.TESTER, status.HTTP_200_OK),
348-
],
349-
)
350-
async def test_list_datasets_metadata(
351-
client: TestClient,
352-
logged_user: dict[str, Any],
353-
expected: int,
354-
):
355-
url = "/v0/storage/locations/0/datasets"
356-
assert url.startswith(PREFIX)
357-
assert client.app
358-
_url = client.app.router["list_datasets_metadata"].url_for(location_id="0")
359-
360-
assert url == str(_url)
361-
362-
resp = await client.get(url, params={"user_id": logged_user["id"]})
363-
data, error = await assert_status(resp, expected)
364-
365-
if not error:
366-
assert "json_schema_extra" in DatasetMetaDataGet.model_config
367-
assert isinstance(DatasetMetaDataGet.model_config["json_schema_extra"], dict)
368-
assert isinstance(
369-
DatasetMetaDataGet.model_config["json_schema_extra"]["examples"], list
370-
)
371-
372-
assert len(data) == len(
373-
DatasetMetaDataGet.model_config["json_schema_extra"]["examples"]
374-
)
375-
assert data == DatasetMetaDataGet.model_config["json_schema_extra"]["examples"]
376-
377-
378-
@pytest.mark.parametrize(
379-
"user_role,expected",
380-
[
381-
(UserRole.ANONYMOUS, status.HTTP_401_UNAUTHORIZED),
382-
(UserRole.GUEST, status.HTTP_200_OK),
383-
(UserRole.USER, status.HTTP_200_OK),
384-
(UserRole.TESTER, status.HTTP_200_OK),
385-
],
386-
)
387-
async def test_list_dataset_files_metadata(
388-
client: TestClient,
389-
logged_user: dict[str, Any],
390-
expected: int,
391-
):
392-
url = "/v0/storage/locations/0/datasets/N:asdfsdf/metadata"
393-
assert url.startswith(PREFIX)
394-
assert client.app
395-
_url = client.app.router["list_dataset_files_metadata"].url_for(
396-
location_id="0", dataset_id="N:asdfsdf"
331+
return app_environment | setenvs_from_dict(
332+
monkeypatch,
333+
{
334+
"STORAGE_PORT": f"{fake_storage_server.port}",
335+
"STORAGE_VTAG": storage_vtag,
336+
"WEBSERVER_DB_LISTENER": "0",
337+
"WEBSERVER_GARBAGE_COLLECTOR": "null",
338+
},
397339
)
398340

399-
assert url == str(_url)
400-
401-
resp = await client.get(url, params={"user_id": logged_user["id"]})
402-
data, error = await assert_status(resp, expected)
403-
404-
if not error:
405-
assert "json_schema_extra" in FileMetaDataGet.model_config
406-
assert isinstance(FileMetaDataGet.model_config["json_schema_extra"], dict)
407-
assert isinstance(
408-
FileMetaDataGet.model_config["json_schema_extra"]["examples"], list
409-
)
410-
assert len(data) == len(
411-
FileMetaDataGet.model_config["json_schema_extra"]["examples"]
412-
)
413-
assert data == [
414-
FileMetaDataGet.model_validate(e).model_dump(mode="json")
415-
for e in FileMetaDataGet.model_config["json_schema_extra"]["examples"]
416-
]
417-
418-
419-
@pytest.mark.parametrize(
420-
"user_role,expected",
421-
[
422-
(UserRole.ANONYMOUS, status.HTTP_401_UNAUTHORIZED),
423-
(UserRole.GUEST, status.HTTP_200_OK),
424-
(UserRole.USER, status.HTTP_200_OK),
425-
(UserRole.TESTER, status.HTTP_200_OK),
426-
],
427-
)
428-
async def test_storage_file_meta(
429-
client: TestClient,
430-
logged_user: dict[str, Any],
431-
expected: int,
432-
faker: Faker,
433-
):
434-
# tests redirect of path with quotes in path
435-
file_id = f"{faker.uuid4()}/{faker.uuid4()}/a/b/c/d/e/dat"
436-
quoted_file_id = quote(file_id, safe="")
437-
url = f"/v0/storage/locations/0/files/{quoted_file_id}/metadata"
438-
439-
assert url.startswith(PREFIX)
440-
441-
resp = await client.get(url, params={"user_id": logged_user["id"]})
442-
data, error = await assert_status(resp, expected)
443-
444-
if not error:
445-
assert "json_schema_extra" in FileMetaDataGet.model_config
446-
assert isinstance(FileMetaDataGet.model_config["json_schema_extra"], dict)
447-
assert isinstance(
448-
FileMetaDataGet.model_config["json_schema_extra"]["examples"], list
449-
)
450-
451-
assert data
452-
model = FileMetaDataGet.model_validate(data)
453-
assert model
454-
455-
456-
@pytest.mark.parametrize(
457-
"user_role,expected",
458-
[
459-
(UserRole.ANONYMOUS, status.HTTP_401_UNAUTHORIZED),
460-
(UserRole.GUEST, status.HTTP_200_OK),
461-
(UserRole.USER, status.HTTP_200_OK),
462-
(UserRole.TESTER, status.HTTP_200_OK),
463-
],
464-
)
465-
async def test_storage_list_filter(
466-
client: TestClient,
467-
logged_user: dict[str, Any],
468-
expected: int,
469-
):
470-
# tests composition of 2 queries
471-
file_id = "a/b/c/d/e/dat"
472-
url = "/v0/storage/locations/0/files/metadata?uuid_filter={}".format(
473-
quote(file_id, safe="")
474-
)
475-
476-
assert url.startswith(PREFIX)
477-
478-
resp = await client.get(url, params={"user_id": logged_user["id"]})
479-
data, error = await assert_status(resp, expected)
480-
481-
if not error:
482-
assert "json_schema_extra" in FileMetaDataGet.model_config
483-
assert isinstance(FileMetaDataGet.model_config["json_schema_extra"], dict)
484-
assert isinstance(
485-
FileMetaDataGet.model_config["json_schema_extra"]["examples"], list
486-
)
487-
488-
assert len(data) == 2
489-
for item in data:
490-
model = FileMetaDataGet.model_validate(item)
491-
assert model
492-
493341

494342
@pytest.fixture
495-
def file_id(faker: Faker) -> StorageFileID:
496-
return TypeAdapter(StorageFileID).validate_python(
497-
f"{faker.uuid4()}/{faker.uuid4()}/{faker.file_name()} with spaces.dat"
498-
)
499-
500-
501-
@pytest.mark.parametrize(
502-
"user_role,expected",
503-
[
504-
# (UserRole.ANONYMOUS, status.HTTP_401_UNAUTHORIZED),
505-
# (UserRole.GUEST, status.HTTP_200_OK),
506-
(UserRole.USER, status.HTTP_200_OK),
507-
# (UserRole.TESTER, status.HTTP_200_OK),
508-
],
509-
)
510-
async def test_upload_file(
511-
client: TestClient,
512-
logged_user: dict[str, Any],
513-
expected: int,
514-
file_id: StorageFileID,
515-
):
516-
url = f"/v0/storage/locations/0/files/{quote(file_id, safe='')}"
517-
518-
assert url.startswith(PREFIX)
519-
520-
resp = await client.put(url, params={"user_id": logged_user["id"]})
521-
data, error = await assert_status(resp, expected)
522-
assert not error
523-
assert data
524-
file_upload_schema = FileUploadSchema.model_validate(data)
525-
526-
# let's abort
527-
resp = await client.post(
528-
f"{file_upload_schema.links.abort_upload.path}",
529-
params={"user_id": logged_user["id"]},
530-
)
531-
data, error = await assert_status(resp, status.HTTP_204_NO_CONTENT)
532-
assert not error
533-
assert not data
343+
def location_id(faker: Faker) -> LocationID:
344+
return TypeAdapter(LocationID).validate_python(faker.pyint(min_value=0))

services/web/server/tests/unit/with_dbs/03/test_storage_handlers.py renamed to services/web/server/tests/unit/with_dbs/01/storage/test_storage_handlers.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,6 @@ def app_environment(
3030
return app_environment | setenvs_from_dict(
3131
monkeypatch,
3232
{
33-
"WEBSERVER_DB_LISTENER": "0",
34-
"WEBSERVER_GARBAGE_COLLECTOR": "null",
3533
"STORAGE_HOST": "fake-storage",
3634
},
3735
)

0 commit comments

Comments
 (0)