<commit_before>import asyncio
import logging
import os
from unittest import IsolatedAsyncioTestCase as TestCase

import asyncpg
from asyncpg.pool import Pool

from abrechnung.application.users import UserService
from abrechnung.database import revisions

lock = asyncio.Lock()


def get_test_db_config() -> dict:
    return {
        "user": os.environ.get("TEST_DB_USER", "abrechnung-test"),
        "password": os.environ.get("TEST_DB_PASSWORD", "<PASSWORD>"),
        "host": os.environ.get("TEST_DB_HOST", "localhost"),
        "dbname": os.environ.get("TEST_DB_DATABASE", "abrechnung-test"),
        "port": int(os.environ.get("TEST_DB_PORT", 5432)),
    }


async def get_test_db() -> Pool:
    """
    get a connection pool to the test database
    """
    cfg = get_test_db_config()
    pool = await asyncpg.create_pool(
        user=cfg["user"],
        password=cfg["password"],
        database=cfg["dbname"],
        host=cfg["host"],
        port=cfg["port"],
        min_size=5,
        max_size=5
    )

    await revisions.reset_schema(pool)
    await revisions.apply_revisions(pool)

    return pool


class AsyncTestCase(TestCase):
    def __init__(self, *args, log_level=logging.DEBUG, **kwargs):
        super().__init__(*args, **kwargs)
        logging.basicConfig(level=log_level)

    async def _create_test_user(self, username: str, email: str) -> tuple[int, str]:
        """returns the user id and password"""
        # pylint: disable=protected-access
        async with self.db_pool.acquire() as conn:
            password = "<PASSWORD>"
            hashed_password = UserService._hash_password(password)
            user_id = await conn.fetchval(
                "insert into usr (username, email, hashed_password, pending) values ($1, $2, $3, false) returning id",
                username,
                email,
                hashed_password,
            )

            return user_id, password

    def setUp(self) -> None:
        try:
            self.loop = asyncio.get_running_loop()
        except (AttributeError, RuntimeError):  # AttributeError->py36
            self.loop = asyncio.get_event_loop_policy().get_event_loop()

        self.loop.run_until_complete(self._setup_db())
        self.loop.run_until_complete(self.setUpAsync())

    async def _setup_db(self):
        await lock.acquire()

        self.db_pool = await get_test_db()
        self.db_conn: asyncpg.Connection = await self.db_pool.acquire()

    async def _teardown_db(self):
        await self.db_conn.close()

        lock.release()

    async def setUpAsync(self) -> None:
        pass

    def tearDown(self) -> None:
        self.loop.run_until_complete(self.tearDownAsync())
        self.loop.run_until_complete(self._teardown_db())

    async def tearDownAsync(self) -> None:
        pass<commit_msg>Close db pool during tests<commit_after>import asyncio
import logging
import os
from unittest import IsolatedAsyncioTestCase as TestCase

import asyncpg
from asyncpg.pool import Pool

from abrechnung.application.users import UserService
from abrechnung.database import revisions

lock = asyncio.Lock()


def get_test_db_config() -> dict:
    return {
        "user": os.environ.get("TEST_DB_USER", "abrechnung-test"),
        "password": os.environ.get("TEST_DB_PASSWORD", "<PASSWORD>"),
        "host": os.environ.get("TEST_DB_HOST", "localhost"),
        "dbname": os.environ.get("TEST_DB_DATABASE", "abrechnung-test"),
        "port": int(os.environ.get("TEST_DB_PORT", 5432)),
    }


async def get_test_db() -> Pool:
    """
    get a connection pool to the test database
    """
    cfg = get_test_db_config()
    pool = await asyncpg.create_pool(
        user=cfg["user"],
        password=cfg["password"],
        database=cfg["dbname"],
        host=cfg["host"],
        port=cfg["port"],
        min_size=5,
        max_size=5
    )

    await revisions.reset_schema(pool)
    await revisions.apply_revisions(pool)

    return pool


class AsyncTestCase(TestCase):
    def __init__(self, *args, log_level=logging.DEBUG, **kwargs):
        super().__init__(*args, **kwargs)
        logging.basicConfig(level=log_level)

    async def _create_test_user(self, username: str, email: str) -> tuple[int, str]:
        """returns the user id and password"""
        # pylint: disable=protected-access
        async with self.db_pool.acquire() as conn:
            password = "<PASSWORD>"
            hashed_password = UserService._<PASSWORD>_password(password)
            user_id = await conn.fetchval(
                "insert into usr (username, email, hashed_password, pending) values ($1, $2, $3, false) returning id",
                username,
                email,
                hashed_password,
            )

            return user_id, password

    def setUp(self) -> None:
        try:
            self.loop = asyncio.get_running_loop()
        except (AttributeError, RuntimeError):  # AttributeError->py36
            self.loop = asyncio.get_event_loop_policy().get_event_loop()

        self.loop.run_until_complete(self._setup_db())
        self.loop.run_until_complete(self.setUpAsync())

    async def _setup_db(self):
        await lock.acquire()

        self.db_pool = await get_test_db()
        self.db_conn: asyncpg.Connection = await self.db_pool.acquire()

    async def _teardown_db(self):
        await self.db_conn.close()
        await self.db_pool.close()

        lock.release()

    async def setUpAsync(self) -> None:
        pass

    def tearDown(self) -> None:
        self.loop.run_until_complete(self.tearDownAsync())
        self.loop.run_until_complete(self._teardown_db())

    async def tearDownAsync(self) -> None:
        pass
{'fraction_non_alphanumeric': 0.11618111618111618, 'fraction_numerical': 0.003861003861003861, 'mean_word_length': 2.727272727272727, 'pattern_counts': {'":': 10, '<': 8, '<?xml version=': 0, '>': 24, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1257406', 'n_tokens_mistral': 1777, 'n_tokens_neox': 1729, 'n_words': 371}