Skip to content

Commit ff73432

Browse files
committed
Replace fixed test ports with free port helper
1 parent 0401859 commit ff73432

14 files changed

Lines changed: 77 additions & 24 deletions

tests/durabletask/_port_utils.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# Copyright (c) Microsoft Corporation.
2+
# Licensed under the MIT License.
3+
4+
"""Shared test helpers for picking network ports.
5+
6+
Tests start an in-memory backend that binds a TCP port. Hard-coding
7+
fixed ports causes intermittent failures on Windows because Hyper-V (and
8+
other components) reserve large, dynamic ranges of TCP ports. Asking the
9+
OS for a free port avoids those collisions.
10+
"""
11+
12+
from __future__ import annotations
13+
14+
import socket
15+
16+
17+
def find_free_port() -> int:
18+
"""Return a TCP port number that is currently free.
19+
20+
Binds a socket to port 0 so the OS assigns an available port, then
21+
releases it and returns the chosen number. There is an inherent race
22+
between releasing the socket and the caller binding the port, but in
23+
practice it is reliable for tests and far safer than fixed ports.
24+
"""
25+
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
26+
s.bind(("localhost", 0))
27+
return s.getsockname()[1]

tests/durabletask/entities/test_class_based_entities_e2e.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,16 @@
1212
from durabletask import client, entities, task, worker
1313
from durabletask.testing import create_test_backend
1414

15-
HOST = "localhost:50059"
15+
from _port_utils import find_free_port
16+
17+
PORT = find_free_port()
18+
HOST = f"localhost:{PORT}"
1619

1720

1821
@pytest.fixture(autouse=True)
1922
def backend():
2023
"""Create an in-memory backend for entity testing."""
21-
b = create_test_backend(port=50059)
24+
b = create_test_backend(port=PORT)
2225
yield b
2326
b.stop()
2427
b.reset()

tests/durabletask/entities/test_entity_failure_handling.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,16 @@
1212
from durabletask import client, entities, task, worker
1313
from durabletask.testing import create_test_backend
1414

15-
HOST = "localhost:50057"
15+
from _port_utils import find_free_port
16+
17+
PORT = find_free_port()
18+
HOST = f"localhost:{PORT}"
1619

1720

1821
@pytest.fixture(autouse=True)
1922
def backend():
2023
"""Create an in-memory backend for entity testing."""
21-
b = create_test_backend(port=50057)
24+
b = create_test_backend(port=PORT)
2225
yield b
2326
b.stop()
2427
b.reset()

tests/durabletask/entities/test_function_based_entities_e2e.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,16 @@
1212
from durabletask import client, entities, task, worker
1313
from durabletask.testing import create_test_backend
1414

15-
HOST = "localhost:50056"
15+
from _port_utils import find_free_port
16+
17+
PORT = find_free_port()
18+
HOST = f"localhost:{PORT}"
1619

1720

1821
@pytest.fixture(autouse=True)
1922
def backend():
2023
"""Create an in-memory backend for entity testing."""
21-
b = create_test_backend(port=50056)
24+
b = create_test_backend(port=PORT)
2225
yield b
2326
b.stop()
2427
b.reset()

tests/durabletask/extensions/history_export/test_activities.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,9 @@
3636
)
3737
from durabletask.testing import create_test_backend
3838

39+
from _port_utils import find_free_port
3940

40-
PORT = 50261
41+
PORT = find_free_port()
4142
HOST = f"localhost:{PORT}"
4243

4344

tests/durabletask/extensions/history_export/test_client.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,9 @@
3535
from durabletask.testing import create_test_backend
3636

3737
from ._test_helpers import wait_until
38+
from _port_utils import find_free_port
3839

39-
40-
PORT = 50263
40+
PORT = find_free_port()
4141
HOST = f"localhost:{PORT}"
4242

4343

tests/durabletask/extensions/history_export/test_entity.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,9 @@
3131
from durabletask.testing import create_test_backend
3232

3333
from ._test_helpers import wait_until
34+
from _port_utils import find_free_port
3435

35-
36-
PORT = 50260
36+
PORT = find_free_port()
3737
HOST = f"localhost:{PORT}"
3838

3939
_WINDOW_START = datetime(2025, 1, 1, tzinfo=timezone.utc)

tests/durabletask/extensions/history_export/test_orchestrator.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,9 @@
3333
from durabletask.testing import create_test_backend
3434

3535
from ._test_helpers import wait_until
36+
from _port_utils import find_free_port
3637

37-
38-
PORT = 50262
38+
PORT = find_free_port()
3939
HOST = f"localhost:{PORT}"
4040

4141

tests/durabletask/test_batch_actions.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,9 @@
1515
from durabletask.testing import create_test_backend
1616
from durabletask.worker import TaskHubGrpcWorker
1717

18-
BATCH_TEST_PORT = 50058
18+
from _port_utils import find_free_port
19+
20+
BATCH_TEST_PORT = find_free_port()
1921
HOST = f"localhost:{BATCH_TEST_PORT}"
2022

2123

tests/durabletask/test_large_payload_e2e.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
from durabletask import client, task, worker
2323
from durabletask.testing import create_test_backend
2424

25+
from _port_utils import find_free_port
26+
2527
# Skip the entire module if azure-storage-blob is not installed.
2628
azure_blob = pytest.importorskip("azure.storage.blob")
2729

@@ -30,8 +32,8 @@
3032
# Azurite well-known connection string
3133
AZURITE_CONN_STR = "UseDevelopmentStorage=true"
3234

33-
HOST = "localhost:50070"
34-
BACKEND_PORT = 50070
35+
BACKEND_PORT = find_free_port()
36+
HOST = f"localhost:{BACKEND_PORT}"
3537

3638
# Use a unique container per test run to avoid collisions.
3739
TEST_CONTAINER = f"e2e-payloads-{uuid.uuid4().hex[:8]}"

0 commit comments

Comments
 (0)