diff --git a/tests/conftest.py b/tests/conftest.py index b04109dd..782448b9 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -111,6 +111,23 @@ def pytest_runtest_call(item): TEST_PASSWORD = "test12345" # nosec B105 +def free_port(): + """A free local TCP port, for a server's ``http_port``. + + The server's default is the fixed port 2480, so a test that starts a server + without choosing a port fails with "Unable to listen to a HTTP port in the + configured port range 2480 - 2480" whenever anything else on the machine + holds 2480. Every test that starts a server passes + ``config={"http_port": free_port()}``. For several distinct ports at once, + see ``_free_ports`` in test_server_wire_protocols.py. + """ + import socket + + with socket.socket() as s: + s.bind(("127.0.0.1", 0)) + return s.getsockname()[1] + + @pytest.fixture def temp_server_root(): """Create a temporary server root directory.""" diff --git a/tests/test_server.py b/tests/test_server.py index f050fbba..0c2d5f5e 100644 --- a/tests/test_server.py +++ b/tests/test_server.py @@ -17,16 +17,17 @@ import pytest from arcadedb_embedded import ArcadeDBServer -from tests.conftest import TEST_PASSWORD +from tests.conftest import TEST_PASSWORD, free_port @pytest.mark.server def test_server_creation(temp_server_root): """Test creating and starting a server.""" + port = free_port() server = ArcadeDBServer( root_path=temp_server_root, root_password=TEST_PASSWORD, - config={"http_port": 2480}, + config={"http_port": port}, ) assert not server.is_started() @@ -36,10 +37,10 @@ def test_server_creation(temp_server_root): # Give server a moment to start time.sleep(1) - assert server.get_http_port() == 2480 + assert server.get_http_port() == port studio_url = server.get_studio_url() assert "http://" in studio_url - assert "2480" in studio_url + assert str(port) in studio_url server.stop() assert not server.is_started() @@ -56,7 +57,9 @@ def test_server_database_operations(temp_server_root): - Operations within same Python process (embedded access) """ with ArcadeDBServer( - root_path=temp_server_root, root_password=TEST_PASSWORD + root_path=temp_server_root, + root_password=TEST_PASSWORD, + config={"http_port": free_port()}, ) as server: # Server auto-starts in context manager time.sleep(1) @@ -85,7 +88,8 @@ def test_server_database_operations(temp_server_root): @pytest.mark.server def test_server_custom_config(temp_server_root): """Test server with custom configuration.""" - config = {"http_port": 8080, "host": "127.0.0.1", "mode": "production"} + port = free_port() + config = {"http_port": port, "host": "127.0.0.1", "mode": "production"} server = ArcadeDBServer( root_path=temp_server_root, root_password=TEST_PASSWORD, config=config @@ -93,7 +97,7 @@ def test_server_custom_config(temp_server_root): server.start() time.sleep(1) - assert server.get_http_port() == 8080 + assert server.get_http_port() == port server.stop() @@ -102,7 +106,9 @@ def test_server_custom_config(temp_server_root): def test_server_context_manager(temp_server_root): """Test server context manager.""" with ArcadeDBServer( - root_path=temp_server_root, root_password=TEST_PASSWORD + root_path=temp_server_root, + root_password=TEST_PASSWORD, + config={"http_port": free_port()}, ) as server: # Server auto-starts in context manager time.sleep(1) diff --git a/tests/test_server_http_endpoints.py b/tests/test_server_http_endpoints.py index 8f7ef3dd..45f43374 100644 --- a/tests/test_server_http_endpoints.py +++ b/tests/test_server_http_endpoints.py @@ -12,14 +12,16 @@ import pytest import arcadedb_embedded as arcadedb -from tests.conftest import TEST_PASSWORD +from tests.conftest import TEST_PASSWORD, free_port @pytest.fixture def http_server(tmp_path): requests = pytest.importorskip("requests") server = arcadedb.create_server( - root_path=str(tmp_path / "srv"), root_password=TEST_PASSWORD + root_path=str(tmp_path / "srv"), + root_password=TEST_PASSWORD, + config={"http_port": free_port()}, ) server.start() time.sleep(1) diff --git a/tests/test_server_packaging.py b/tests/test_server_packaging.py index d1e0dabe..471d6829 100644 --- a/tests/test_server_packaging.py +++ b/tests/test_server_packaging.py @@ -109,10 +109,12 @@ def test_server_starts_and_serves_http(temp_server_root): """ requests = pytest.importorskip("requests") from arcadedb_embedded import create_server - from tests.conftest import TEST_PASSWORD + from tests.conftest import TEST_PASSWORD, free_port with create_server( - root_path=temp_server_root, root_password=TEST_PASSWORD + root_path=temp_server_root, + root_password=TEST_PASSWORD, + config={"http_port": free_port()}, ) as server: assert server.is_started() port = server.get_http_port() diff --git a/tests/test_server_patterns.py b/tests/test_server_patterns.py index b5876832..ce342158 100644 --- a/tests/test_server_patterns.py +++ b/tests/test_server_patterns.py @@ -21,7 +21,7 @@ import pytest import arcadedb_embedded as arcadedb -from tests.conftest import TEST_PASSWORD +from tests.conftest import TEST_PASSWORD, free_port def _http_query(server, db_name, sql): @@ -95,7 +95,11 @@ def test_server_pattern_recommended(cleanup_test_dirs): # Step 1: Start server first print("\n1. Starting ArcadeDB server...") - server = arcadedb.create_server(root_path=root_path, root_password=TEST_PASSWORD) + server = arcadedb.create_server( + root_path=root_path, + root_password=TEST_PASSWORD, + config={"http_port": free_port()}, + ) register_server(server) server.start() assert server.is_started() @@ -154,7 +158,11 @@ def test_server_thread_safety(cleanup_test_dirs): # Start server and create database print("\n1. Setting up server and database...") - server = arcadedb.create_server(root_path=root_path, root_password=TEST_PASSWORD) + server = arcadedb.create_server( + root_path=root_path, + root_password=TEST_PASSWORD, + config={"http_port": free_port()}, + ) register_server(server) server.start() @@ -230,7 +238,9 @@ def test_server_context_manager(cleanup_test_dirs): # Server automatically starts and stops with arcadedb.create_server( - root_path=root_path, root_password=TEST_PASSWORD + root_path=root_path, + root_password=TEST_PASSWORD, + config={"http_port": free_port()}, ) as server: print(" ✅ Server started (automatic)") @@ -307,7 +317,11 @@ def test_pattern1_embedded_first_requires_close(cleanup_test_dirs): # Step 4: Start server print("\n4. Starting ArcadeDB server...") - server = arcadedb.create_server(root_path=root_path, root_password=TEST_PASSWORD) + server = arcadedb.create_server( + root_path=root_path, + root_password=TEST_PASSWORD, + config={"http_port": free_port()}, + ) register_server(server) server.start() print(f" ✅ Server started on port {server.get_http_port()}") @@ -443,7 +457,11 @@ def test_embedded_performance_comparison(cleanup_test_dirs): print("\n2. Server-Managed Embedded Mode (same process)...") server_path = create_temp_dir("server_perf_") - server = arcadedb.create_server(root_path=server_path, root_password=TEST_PASSWORD) + server = arcadedb.create_server( + root_path=server_path, + root_password=TEST_PASSWORD, + config={"http_port": free_port()}, + ) register_server(server) server.start() @@ -539,7 +557,11 @@ def test_http_api_access_pattern(cleanup_test_dirs): # Step 1: Start server (required for HTTP API) print("\n1. Starting ArcadeDB server...") - server = arcadedb.create_server(root_path=root_path, root_password=TEST_PASSWORD) + server = arcadedb.create_server( + root_path=root_path, + root_password=TEST_PASSWORD, + config={"http_port": free_port()}, + ) register_server(server) server.start() time.sleep(1) # Give server time to fully start