blob: f28a09fa22bf0532e48aa6b35875c5642f1245d7 [file]
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
"""
Test configuration and fixtures for the Python SDK test suite.
This module provides pytest fixtures for setting up test environments
and connecting to Iggy servers in various configurations.
"""
import asyncio
import os
import socket
import time
from typing import Generator, Optional
import pytest
from iggy_py import IggyClient
def get_server_config() -> tuple[str, int]:
"""
Get server configuration from environment variables or defaults.
Returns:
tuple: (host, port) for the Iggy server
"""
host = os.environ.get("IGGY_SERVER_HOST", "127.0.0.1")
port = int(os.environ.get("IGGY_SERVER_TCP_PORT", "8090"))
# Convert hostname to IP address for the Rust client
if host not in ("127.0.0.1", "localhost"):
try:
# Resolve hostname to IP address
host_ip = socket.gethostbyname(host)
host = host_ip
except socket.gaierror:
# If resolution fails, keep the original host
pass
elif host == "localhost":
host = "127.0.0.1"
return host, port
def wait_for_server(host: str, port: int, timeout: int = 60, interval: int = 2) -> None:
"""
Wait for the server to become available.
Args:
host: Server hostname or IP
port: Server port
timeout: Maximum time to wait in seconds
interval: Time between connection attempts in seconds
Raises:
TimeoutError: If server doesn't become available within timeout
"""
start_time = time.time()
while True:
try:
with socket.create_connection((host, port), timeout=interval):
return
except (socket.timeout, ConnectionRefusedError, OSError):
elapsed_time = time.time() - start_time
if elapsed_time >= timeout:
raise TimeoutError(
f"Server not available at {host}:{port} after {timeout}s"
)
time.sleep(interval)
async def wait_for_ping(client: IggyClient, timeout: int = 30, interval: int = 2) -> None:
"""
Wait for the server to respond to ping requests.
Args:
client: Iggy client instance
timeout: Maximum time to wait in seconds
interval: Time between ping attempts in seconds
Raises:
TimeoutError: If server doesn't respond to ping within timeout
"""
start_time = time.time()
while True:
try:
await client.ping()
return
except Exception:
elapsed_time = time.time() - start_time
if elapsed_time >= timeout:
raise TimeoutError(
f"Server not responding to ping after {timeout}s"
)
await asyncio.sleep(interval)
@pytest.fixture(scope="session")
async def iggy_client() -> IggyClient:
"""
Create and configure an Iggy client for testing.
This fixture:
1. Gets server configuration from environment
2. Waits for server to be available
3. Creates and connects the client
4. Authenticates with default credentials
5. Verifies connectivity with ping
Returns:
IggyClient: Authenticated client ready for testing
"""
host, port = get_server_config()
# Wait for server to be ready
wait_for_server(host, port)
# Create and connect client
client = IggyClient(f"{host}:{port}")
await client.connect()
# Wait for server to be fully ready
await wait_for_ping(client)
# Authenticate
await client.login_user("iggy", "iggy")
return client
@pytest.fixture(scope="session", autouse=True)
def configure_asyncio():
"""Configure asyncio settings for tests."""
# Set event loop policy if needed
if os.name == 'nt': # Windows
asyncio.set_event_loop_policy(asyncio.WindowsProactorEventLoopPolicy())
# Pytest configuration
def pytest_configure(config):
"""Configure pytest with custom markers."""
config.addinivalue_line(
"markers",
"integration: marks tests as integration tests (may be slow)"
)
config.addinivalue_line(
"markers",
"unit: marks tests as unit tests (fast)"
)
def pytest_collection_modifyitems(config, items):
"""Modify test collection to add markers automatically."""
for item in items:
# Mark all tests in test_iggy_sdk.py as integration tests
if "test_iggy_sdk" in item.nodeid:
item.add_marker(pytest.mark.integration)