|
5 | 5 |
|
6 | 6 | from pathlib import Path |
7 | 7 |
|
| 8 | +import aiopg.sa |
| 9 | +import asyncpg |
| 10 | +import pytest |
| 11 | +import sqlalchemy as sa |
8 | 12 | import yaml |
| 13 | +from aiohttp import web |
9 | 14 | from aiohttp.test_utils import TestServer |
| 15 | +from pytest_mock import MockFixture, MockType |
| 16 | +from simcore_service_webserver.application_settings import ( |
| 17 | + ApplicationSettings, |
| 18 | + get_application_settings, |
| 19 | +) |
| 20 | +from simcore_service_webserver.db import _aiopg, _asyncpg |
10 | 21 | from simcore_service_webserver.db.plugin import ( |
11 | 22 | is_service_enabled, |
12 | 23 | is_service_responsive, |
| 24 | + setup_db, |
13 | 25 | ) |
| 26 | +from simcore_service_webserver.login.storage import AsyncpgStorage, get_plugin_storage |
| 27 | +from sqlalchemy.ext.asyncio import AsyncEngine |
| 28 | + |
| 29 | + |
| 30 | +@pytest.fixture |
| 31 | +def mock_asyncpg_in_setup_db(mocker: MockFixture) -> MockType: |
| 32 | + original_setup = setup_db |
| 33 | + |
| 34 | + mock_setup_db = mocker.patch( |
| 35 | + "simcore_service_webserver.application.setup_db", autospec=True |
| 36 | + ) |
| 37 | + |
| 38 | + def _wrapper_setup_db(app: web.Application): |
| 39 | + original_setup(app) |
| 40 | + |
| 41 | + # NEW engine ! |
| 42 | + app.cleanup_ctx.append(_asyncpg.postgres_cleanup_ctx) |
| 43 | + |
| 44 | + mock_setup_db.side_effect = _wrapper_setup_db |
| 45 | + return mock_setup_db |
| 46 | + |
| 47 | + |
| 48 | +async def test_all_pg_engines_in_app( |
| 49 | + mock_asyncpg_in_setup_db: MockType, web_server: TestServer |
| 50 | +): |
| 51 | + assert mock_asyncpg_in_setup_db.called |
| 52 | + |
| 53 | + app = web_server.app |
| 54 | + assert app |
| 55 | + |
| 56 | + settings: ApplicationSettings = get_application_settings(app) |
| 57 | + assert settings.WEBSERVER_DB |
| 58 | + assert settings.WEBSERVER_DB.POSTGRES_CLIENT_NAME |
| 59 | + |
| 60 | + # (1) aiopg engine (deprecated) |
| 61 | + aiopg_engine = _aiopg.get_database_engine(app) |
| 62 | + assert aiopg_engine |
| 63 | + assert isinstance(aiopg_engine, aiopg.sa.Engine) |
| 64 | + |
| 65 | + # (2) asyncpg engine via sqlalchemy.ext.asyncio (new) |
| 66 | + asyncpg_engine: AsyncEngine = _asyncpg.get_async_engine(app) |
| 67 | + assert asyncpg_engine |
| 68 | + assert isinstance(asyncpg_engine, AsyncEngine) |
| 69 | + |
| 70 | + # (3) low-level asyncpg Pool (deprecated) |
| 71 | + # Will be replaced by (2) |
| 72 | + login_storage: AsyncpgStorage = get_plugin_storage(app) |
| 73 | + assert login_storage.pool |
| 74 | + assert isinstance(login_storage.pool, asyncpg.Pool) |
| 75 | + |
| 76 | + # they ALL point to the SAME database |
| 77 | + assert aiopg_engine.dsn |
| 78 | + assert asyncpg_engine.url |
| 79 | + |
| 80 | + query = sa.text('SELECT "version_num" FROM "alembic_version"') |
| 81 | + async with login_storage.pool.acquire() as conn: |
| 82 | + result_pool = await conn.fetchval(str(query)) |
| 83 | + |
| 84 | + async with asyncpg_engine.connect() as conn: |
| 85 | + result_asyncpg = (await conn.execute(query)).scalar_one_or_none() |
| 86 | + |
| 87 | + async with aiopg_engine.acquire() as conn: |
| 88 | + result_aiopg = await (await conn.execute(query)).scalar() |
| 89 | + |
| 90 | + assert result_pool == result_asyncpg |
| 91 | + assert result_pool == result_aiopg |
14 | 92 |
|
15 | 93 |
|
16 | 94 | def test_uses_same_postgres_version( |
17 | 95 | docker_compose_file: Path, osparc_simcore_root_dir: Path |
18 | 96 | ): |
19 | | - with open(docker_compose_file) as fh: |
| 97 | + with Path.open(docker_compose_file) as fh: |
20 | 98 | fixture = yaml.safe_load(fh) |
21 | 99 |
|
22 | | - with open(osparc_simcore_root_dir / "services" / "docker-compose.yml") as fh: |
| 100 | + with Path.open(osparc_simcore_root_dir / "services" / "docker-compose.yml") as fh: |
23 | 101 | expected = yaml.safe_load(fh) |
24 | 102 |
|
25 | 103 | assert ( |
|
0 commit comments