Skip to content
This repository was archived by the owner on Dec 20, 2023. It is now read-only.

Query test #69

Merged
merged 12 commits into from
Nov 7, 2023
Merged
39 changes: 38 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
name: CI

permissions:
packages: read

on:
pull_request:
push:
Expand Down Expand Up @@ -28,7 +31,7 @@ jobs:
cache-dependency-path: ${{ github.workspace }}/authpage/package-lock.json
- name: Cache authpage
id: cached-authpage
uses: actions/cache@v2
uses: actions/cache@v3
with:
key: authpage-${{ hashFiles('${{ github.workspace }}/authpage') }}
path: ${{ github.workspace }}/src/apiserver/resources/static/credentials
Expand All @@ -46,3 +49,37 @@ jobs:
run: poetry run mypy
- name: Pytest
run: poetry run pytest
env:
QUERY_TEST: true
services:
postgres:
image: ghcr.io/dsav-dodeka/postgres:localdev
credentials:
username: ${{ secrets.GH_DODEKACOMCOM_USER }}
password: ${{ secrets.GH_DODEKACOMCOM_TOKEN }}
# These values must align with the config used by the tests in the repo
# The port is set in the image
env:
POSTGRES_PASSWORD: postpost
POSTGRES_USER: dodeka
options: >-
--health-cmd "pg_isready -p 3141"
--health-interval 10s
--health-timeout 5s
--health-retries 5
ports:
- 3141:3141
redis:
image: ghcr.io/dsav-dodeka/redis:localdev
credentials:
username: ${{ secrets.GH_DODEKACOMCOM_USER }}
password: ${{ secrets.GH_DODEKACOMCOM_TOKEN }}
# These values must align with the config used by the tests in the repo
# The port is set in the image
options: >-
--health-cmd "redis-cli ping"
--health-interval 10s
--health-timeout 5s
--health-retries 5
ports:
- 6379:6379
1 change: 0 additions & 1 deletion src/apiserver/app/ops/startup.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,6 @@ async def waiting_lock(dsrc: Source) -> bool:


def drop_create_database(config: Config) -> None:
# runtime_key = aes_from_symmetric(config.KEY_PASS)
db_cluster = f"{config.DB_USER}:{config.DB_PASS}@{config.DB_HOST}:{config.DB_PORT}"
db_url = f"{db_cluster}/{config.DB_NAME}"
admin_db_url = f"{db_cluster}/{config.DB_NAME_ADMIN}"
Expand Down
Empty file added tests/query_test/data_test.py
Empty file.
91 changes: 91 additions & 0 deletions tests/query_test/store_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
import asyncio
import os
from random import randint
from typing import LiteralString

import pytest
import pytest_asyncio
from sqlalchemy import text
from apiserver.app.ops.startup import drop_create_database


from apiserver.env import Config, load_config
from test_util import Fixture, AsyncFixture
from store.conn import get_conn
from store.store import Store
from store.db import LiteralDict, insert
from test_resources import res_path


if not os.environ.get("QUERY_TEST"):
pytest.skip(
"Skipping store_test as QUERY_TEST is not set.", allow_module_level=True
)


@pytest.fixture(scope="session", autouse=True)
def event_loop():
"""Necessary for async tests with module-scoped fixtures"""
loop = asyncio.get_event_loop()
yield loop
loop.close()


@pytest.fixture(scope="module")
def api_config() -> Fixture[Config]:
test_config_path = res_path.joinpath("querytestenv.toml")
yield load_config(test_config_path)


@pytest_asyncio.fixture(scope="module")
async def local_store(api_config: Config):
# each module makes its own database
api_config.DB_NAME = f"testdb_{randint(0, 100000)}"
drop_create_database(api_config)
store = Store()
store.init_objects(api_config)
await store.startup()
yield store


@pytest_asyncio.fixture
async def setup_table(local_store: Store) -> AsyncFixture[str]:
table_name = f"table_{randint(0, 100000)}"
async with get_conn(local_store) as conn:
query = text(f"""
CREATE TABLE {table_name} (
first integer,
second text,
third text
);
""")

await conn.execute(query)

yield table_name

async with get_conn(local_store) as conn:
query = text(f"""
DROP TABLE {table_name};
""")

await conn.execute(query)


@pytest.mark.asyncio
async def test_insert(local_store: Store, setup_table: LiteralString):
row: LiteralDict = {"first": 3, "second": "some", "third": "other"}
async with get_conn(local_store) as conn:
cnt = await insert(conn, setup_table, row)
assert cnt == 1

query = text(f"""
SELECT * FROM {setup_table};
""")

res = await conn.execute(query)

res_item = res.mappings().first()

assert res_item is not None
assert dict(res_item) == row
19 changes: 19 additions & 0 deletions tests/resources/querytestenv.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
APISERVER_ENV="localdev"

DB_USER="dodeka"
DB_PASS="postpost"
DB_HOST="localhost"
DB_PORT=3141
DB_NAME="dodeka"
DB_NAME_ADMIN="postgres"

KV_HOST="localhost"
KV_PORT=6379
KV_PASS="redisredis"

MAIL_ENABLED=false
MAIL_PASS="abcpass"
KEY_PASS="abcpass"

SMTP_SERVER = "abcmail"
SMTP_PORT = 587
2 changes: 1 addition & 1 deletion tests/router_test/authorize_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
from apiserver.env import load_config
from auth.core.model import AuthRequest
from auth.data.context import AuthorizeContext
from router_test.test_util import make_test_user, mock_auth_request
from test_util import make_test_user, mock_auth_request
from store import Store
from store.error import NoDataError
from test_resources import res_path
Expand Down
2 changes: 1 addition & 1 deletion tests/router_test/login_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
from auth.core.model import SavedState, FlowUser
from auth.data.context import LoginContext
from auth.data.relational.user import UserOps
from router_test.test_util import GenUser, OpaqueValues, make_test_user
from test_util import GenUser, OpaqueValues, make_test_user
from store import Store
from test_resources import res_path

Expand Down
2 changes: 1 addition & 1 deletion tests/router_test/register_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
)
from auth.core.util import utc_timestamp
from auth.data.context import RegisterContext
from router_test.test_util import (
from test_util import (
make_test_user,
GenUser,
OpaqueValues,
Expand Down
2 changes: 1 addition & 1 deletion tests/router_test/token_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
from auth.define import refresh_exp, id_exp, access_exp
from auth.hazmat.key_decode import aes_from_symmetric
from auth.hazmat.structs import PEMPrivateKey
from router_test.test_util import (
from test_util import (
Fixture,
make_test_user,
mock_auth_request,
Expand Down
2 changes: 1 addition & 1 deletion tests/router_test/update_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
from apiserver.data.context import Code, UpdateContext
from apiserver.env import load_config
from apiserver.lib.model.entities import UserData, User
from router_test.test_util import (
from test_util import (
make_test_user,
make_base_ud,
)
Expand Down
3 changes: 2 additions & 1 deletion tests/router_test/test_util.py → tests/test_util.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from dataclasses import dataclass
from typing import Generator, TypeVar
from typing import AsyncGenerator, Generator, TypeVar

from faker import Faker
from pydantic import BaseModel
Expand All @@ -10,6 +10,7 @@

T = TypeVar("T")
Fixture = Generator[T, None, None]
AsyncFixture = AsyncGenerator[T, None]


def cr_user_id(id_int: int, g_id_name: str):
Expand Down