|
3 | 3 | from asyncio import AbstractEventLoop |
4 | 4 | from collections.abc import AsyncGenerator |
5 | 5 | from collections.abc import Generator |
6 | | -from concurrent.futures import TimeoutError |
7 | | -from typing import Any |
8 | | -from typing import Callable |
9 | 6 |
|
10 | 7 | import pytest |
11 | 8 | import ydb |
12 | | -from testcontainers.core.generic import DbContainer |
13 | | -from testcontainers.core.generic import wait_container_is_ready |
14 | | -from testcontainers.core.utils import setup_logger |
15 | | -from typing_extensions import Self |
16 | | - |
17 | | -logger = setup_logger(__name__) |
18 | | - |
19 | | - |
20 | | -class YDBContainer(DbContainer): |
21 | | - def __init__( |
22 | | - self, |
23 | | - name: str | None = None, |
24 | | - port: str = "2136", |
25 | | - image: str = "ydbplatform/local-ydb:trunk", |
26 | | - **kwargs: Any, |
27 | | - ) -> None: |
28 | | - docker_client_kw: dict[str, Any] = kwargs.pop("docker_client_kw", {}) |
29 | | - docker_client_kw["timeout"] = docker_client_kw.get("timeout") or 300 |
30 | | - super().__init__( |
31 | | - image=image, |
32 | | - hostname="localhost", |
33 | | - docker_client_kw=docker_client_kw, |
34 | | - **kwargs, |
35 | | - ) |
36 | | - self.port_to_expose = port |
37 | | - self._name = name |
38 | | - self._database_name = "local" |
39 | | - |
40 | | - def start(self) -> Self: |
41 | | - self._maybe_stop_old_container() |
42 | | - super().start() |
43 | | - return self |
44 | | - |
45 | | - def get_connection_url(self, driver: str = "ydb") -> str: |
46 | | - host = self.get_container_host_ip() |
47 | | - port = self.get_exposed_port(self.port_to_expose) |
48 | | - return f"yql+{driver}://{host}:{port}/local" |
49 | | - |
50 | | - def get_connection_string(self) -> str: |
51 | | - host = self.get_container_host_ip() |
52 | | - port = self.get_exposed_port(self.port_to_expose) |
53 | | - return f"grpc://{host}:{port}/?database=/local" |
54 | | - |
55 | | - def get_ydb_database_name(self) -> str: |
56 | | - return self._database_name |
57 | | - |
58 | | - def get_ydb_host(self) -> str: |
59 | | - return self.get_container_host_ip() |
60 | | - |
61 | | - def get_ydb_port(self) -> str: |
62 | | - return self.get_exposed_port(self.port_to_expose) |
63 | | - |
64 | | - @wait_container_is_ready(ydb.ConnectionError, TimeoutError) |
65 | | - def _connect(self) -> None: |
66 | | - with ydb.Driver( |
67 | | - connection_string=self.get_connection_string() |
68 | | - ) as driver: |
69 | | - driver.wait(fail_fast=True) |
70 | | - try: |
71 | | - driver.scheme_client.describe_path("/local/.sys_health/test") |
72 | | - except ydb.SchemeError as e: |
73 | | - msg = "Database is not ready" |
74 | | - raise ydb.ConnectionError(msg) from e |
75 | | - |
76 | | - def _configure(self) -> None: |
77 | | - self.with_bind_ports(self.port_to_expose, self.port_to_expose) |
78 | | - if self._name: |
79 | | - self.with_name(self._name) |
80 | | - self.with_env("YDB_USE_IN_MEMORY_PDISKS", "true") |
81 | | - self.with_env("YDB_DEFAULT_LOG_LEVEL", "DEBUG") |
82 | | - self.with_env("GRPC_PORT", self.port_to_expose) |
83 | | - self.with_env("GRPC_TLS_PORT", self.port_to_expose) |
84 | | - |
85 | | - def _maybe_stop_old_container(self) -> None: |
86 | | - if not self._name: |
87 | | - return |
88 | | - docker_client = self.get_docker_client() |
89 | | - running_container = docker_client.client.api.containers( |
90 | | - filters={"name": self._name} |
91 | | - ) |
92 | | - if running_container: |
93 | | - logger.info("Stop existing container") |
94 | | - docker_client.client.api.remove_container( |
95 | | - running_container[0], force=True, v=True |
96 | | - ) |
97 | | - |
98 | | - |
99 | | -@pytest.fixture(scope="session") |
100 | | -def ydb_container( |
101 | | - unused_tcp_port_factory: Callable[[], int], |
102 | | -) -> Generator[YDBContainer, None, None]: |
103 | | - with YDBContainer(port=str(unused_tcp_port_factory())) as ydb_container: |
104 | | - yield ydb_container |
105 | 9 |
|
106 | 10 |
|
107 | | -@pytest.fixture(scope="session") |
108 | | -def connection_string(ydb_container: YDBContainer) -> str: |
109 | | - return ydb_container.get_connection_string() |
| 11 | +@pytest.fixture |
| 12 | +def connection_string() -> str: |
| 13 | + return "grpc://localhost:2136/?database=/local" |
110 | 14 |
|
111 | 15 |
|
112 | | -@pytest.fixture(scope="session") |
113 | | -def connection_kwargs(ydb_container: YDBContainer) -> dict: |
| 16 | +@pytest.fixture |
| 17 | +def connection_kwargs() -> dict: |
114 | 18 | return { |
115 | | - "host": ydb_container.get_ydb_host(), |
116 | | - "port": ydb_container.get_ydb_port(), |
117 | | - "database": ydb_container.get_ydb_database_name(), |
| 19 | + "host": "localhost", |
| 20 | + "port": "2136", |
| 21 | + "database": "/local", |
118 | 22 | } |
119 | 23 |
|
120 | 24 |
|
@@ -176,6 +80,13 @@ async def session_pool( |
176 | 80 |
|
177 | 81 | yield session_pool |
178 | 82 |
|
| 83 | + for name in ["table", "table1", "table2"]: |
| 84 | + await session_pool.execute_with_retries( |
| 85 | + f""" |
| 86 | + DROP TABLE {name}; |
| 87 | + """ |
| 88 | + ) |
| 89 | + |
179 | 90 |
|
180 | 91 | @pytest.fixture |
181 | 92 | def session_pool_sync( |
@@ -207,3 +118,10 @@ def session_pool_sync( |
207 | 118 | ) |
208 | 119 |
|
209 | 120 | yield session_pool |
| 121 | + |
| 122 | + for name in ["table", "table1", "table2"]: |
| 123 | + session_pool.execute_with_retries( |
| 124 | + f""" |
| 125 | + DROP TABLE {name}; |
| 126 | + """ |
| 127 | + ) |
0 commit comments