chore: import upstream snapshot with attribution

This commit is contained in:
wehub-resource-sync
2026-07-13 13:17:40 +08:00
commit f1825c8ceb
10096 changed files with 2364182 additions and 0 deletions
+458
View File
@@ -0,0 +1,458 @@
import os
import random
import socket
import subprocess
import tempfile
from contextlib import contextmanager
from copy import deepcopy
from typing import Any, Dict, Generator
import httpx
import pytest
import pytest_asyncio
import ray
from ray import serve
from ray._common.test_utils import SignalActor, wait_for_condition
from ray._common.usage import usage_lib
from ray._common.utils import reset_ray_address
from ray.cluster_utils import AutoscalingCluster, Cluster
from ray.serve._private.test_utils import (
TELEMETRY_ROUTE_PREFIX,
TEST_METRICS_EXPORT_PORT,
check_ray_started,
check_ray_stopped,
start_telemetry_app,
)
from ray.serve.config import HTTPOptions, ProxyLocation, gRPCOptions
from ray.serve.context import _get_global_client
from ray.tests.conftest import ( # noqa
external_redis,
propagate_logs,
pytest_runtest_makereport,
)
# https://tools.ietf.org/html/rfc6335#section-6
MIN_DYNAMIC_PORT = 49152
MAX_DYNAMIC_PORT = 65535
TEST_GRPC_SERVICER_FUNCTIONS = [
"ray.serve.generated.serve_pb2_grpc.add_UserDefinedServiceServicer_to_server",
"ray.serve.generated.serve_pb2_grpc.add_FruitServiceServicer_to_server",
]
if os.environ.get("RAY_SERVE_INTENTIONALLY_CRASH", False) == 1:
serve.controller._CRASH_AFTER_CHECKPOINT_PROBABILITY = 0.5
@pytest.fixture(autouse=True)
def _clear_stale_ray_address():
# Serve CI runs several test targets per container sharing /tmp/ray; a target
# killed mid-run can leave a ray_current_cluster pointing at a dead cluster.
# Drop it before each test so an address-less ray.init() starts fresh.
reset_ray_address()
yield
@pytest.fixture
def ray_shutdown():
serve.shutdown()
if ray.is_initialized():
ray.shutdown()
yield
serve.shutdown()
if ray.is_initialized():
ray.shutdown()
@pytest.fixture
def ray_cluster():
cluster = Cluster()
yield cluster
serve.shutdown()
ray.shutdown()
cluster.shutdown()
@pytest.fixture
def ray_autoscaling_cluster(request):
# NOTE(zcin): We have to make a deepcopy here because AutoscalingCluster
# modifies the dictionary that's passed in.
params = deepcopy(request.param)
cluster = AutoscalingCluster(**params)
cluster.start()
yield
serve.shutdown()
ray.shutdown()
cluster.shutdown()
@pytest.fixture
def ray_start(scope="module"):
port = random.randint(MIN_DYNAMIC_PORT, MAX_DYNAMIC_PORT)
subprocess.check_output(
[
"ray",
"start",
"--head",
"--num-cpus",
"16",
"--ray-client-server-port",
f"{port}",
]
)
try:
yield f"localhost:{port}"
finally:
subprocess.check_output(["ray", "stop", "--force"])
def _check_ray_stop():
try:
httpx.get("http://localhost:8265/api/ray/version")
return False
except Exception:
return True
@contextmanager
def start_and_shutdown_ray_cli():
subprocess.check_output(["ray", "stop", "--force"])
wait_for_condition(_check_ray_stop, timeout=15)
subprocess.check_output(["ray", "start", "--head"])
yield
subprocess.check_output(["ray", "stop", "--force"])
wait_for_condition(_check_ray_stop, timeout=15)
@pytest.fixture(scope="module")
def start_and_shutdown_ray_cli_module():
with start_and_shutdown_ray_cli():
yield
@pytest.fixture
def tmp_dir():
with tempfile.TemporaryDirectory() as tmp_dir:
old_dir = os.getcwd()
os.chdir(tmp_dir)
yield tmp_dir
os.chdir(old_dir)
@pytest.fixture(scope="session")
def _shared_serve_instance():
# Note(simon):
# This line should be not turned on on master because it leads to very
# spammy and not useful log in case of a failure in CI.
# To run locally, please use this instead.
# SERVE_DEBUG_LOG=1 pytest -v -s test_api.py
# os.environ["SERVE_DEBUG_LOG"] = "1" <- Do not uncomment this.
# Overriding task_retry_delay_ms to relaunch actors more quickly
ray.init(
address="local",
num_cpus=36,
namespace="default_test_namespace",
_metrics_export_port=9999,
_system_config={"metrics_report_interval_ms": 1000, "task_retry_delay_ms": 50},
)
serve.start(
proxy_location=ProxyLocation.HeadOnly,
http_options={"host": "0.0.0.0"},
grpc_options={
"port": 9000,
"grpc_servicer_functions": TEST_GRPC_SERVICER_FUNCTIONS,
},
)
yield _get_global_client()
# Shutdown Serve and Ray when the session ends so that proxy actors
# (e.g. HAProxyManager) run their shutdown logic and stop subprocesses.
serve.shutdown()
@pytest_asyncio.fixture
async def serve_instance_async(_shared_serve_instance):
yield _shared_serve_instance
# Clear all state for 2.x applications and deployments.
_shared_serve_instance.delete_all_apps()
# Clear the ServeHandle cache between tests to avoid them piling up.
await _shared_serve_instance.shutdown_cached_handles_async()
@pytest.fixture
def serve_instance(_shared_serve_instance):
yield _shared_serve_instance
# Clear all state for 2.x applications and deployments.
_shared_serve_instance.delete_all_apps()
# Clear the ServeHandle cache between tests to avoid them piling up.
_shared_serve_instance.shutdown_cached_handles()
@pytest.fixture
def serve_instance_with_signal(serve_instance):
client = serve_instance
signal = SignalActor.options(name="signal123").remote()
yield client, signal
# Delete signal actor so there is no conflict between tests
ray.kill(signal)
def check_ray_stop():
try:
httpx.get("http://localhost:8265/api/ray/version")
return False
except Exception:
return True
@pytest.fixture(scope="function")
def ray_start_stop():
subprocess.check_output(["ray", "stop", "--force"])
ray.shutdown()
wait_for_condition(
check_ray_stop,
timeout=15,
)
subprocess.check_output(["ray", "start", "--head"])
wait_for_condition(
lambda: httpx.get("http://localhost:8265/api/ray/version").status_code == 200,
timeout=15,
)
ray.init("auto")
yield
serve.shutdown()
ray.shutdown()
subprocess.check_output(["ray", "stop", "--force"])
wait_for_condition(
check_ray_stop,
timeout=15,
)
@pytest.fixture(scope="function")
def ray_start_stop_in_specific_directory(request):
original_working_dir = os.getcwd()
# Change working directory so Ray will start in the requested directory.
new_working_dir = request.param
os.chdir(new_working_dir)
print(f"\nChanged working directory to {new_working_dir}\n")
subprocess.check_output(["ray", "start", "--head"])
wait_for_condition(
lambda: httpx.get("http://localhost:8265/api/ray/version").status_code == 200,
timeout=15,
)
try:
yield
finally:
# Change the directory back to the original one.
os.chdir(original_working_dir)
print(f"\nChanged working directory back to {original_working_dir}\n")
subprocess.check_output(["ray", "stop", "--force"])
wait_for_condition(
check_ray_stop,
timeout=15,
)
@pytest.fixture
def ray_instance(
request: pytest.FixtureRequest,
) -> Generator[Dict[str, Any], None, None]:
"""Starts and stops a Ray instance for this test.
Args:
request: request.param should contain a dictionary of env vars and
their values. The Ray instance will be started with these env vars.
Yields:
Dict[str, Any]: The dict returned by ``ray.init`` for the started cluster.
"""
original_env_vars = os.environ.copy()
try:
requested_env_vars = request.param
except AttributeError:
requested_env_vars = {}
os.environ.update(requested_env_vars)
yield ray.init(
address="local",
_metrics_export_port=9999,
_system_config={
"metrics_report_interval_ms": 1000,
"task_retry_delay_ms": 50,
},
)
serve.shutdown()
ray.shutdown()
os.environ.clear()
os.environ.update(original_env_vars)
@pytest.fixture
def manage_ray_with_telemetry(monkeypatch):
with monkeypatch.context() as m:
m.setenv("RAY_USAGE_STATS_ENABLED", "1")
m.setenv(
"RAY_USAGE_STATS_REPORT_URL",
f"http://127.0.0.1:8000{TELEMETRY_ROUTE_PREFIX}",
)
m.setenv("RAY_USAGE_STATS_REPORT_INTERVAL_S", "1")
subprocess.check_output(["ray", "stop", "--force"])
wait_for_condition(check_ray_stopped, timeout=5)
subprocess.check_output(["ray", "start", "--head"])
wait_for_condition(check_ray_started, timeout=5)
storage = start_telemetry_app()
wait_for_condition(
lambda: ray.get(storage.get_reports_received.remote()) > 1, timeout=15
)
yield storage
# Call Python API shutdown() methods to clear global variable state
serve.shutdown()
ray.shutdown()
# Reset global state (any keys that may have been set and cached while the
# workload was running).
usage_lib.reset_global_state()
# Shut down Ray cluster with CLI
subprocess.check_output(["ray", "stop", "--force"])
wait_for_condition(check_ray_stopped, timeout=5)
def wait_for_metrics_port_free(port=TEST_METRICS_EXPORT_PORT, timeout=30):
"""
Ensures the metrics export port is freed.
"""
def port_free():
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
try:
s.bind(("", port))
return True
except OSError:
return False
finally:
s.close()
wait_for_condition(port_free, timeout=timeout, retry_interval_ms=200)
def wait_for_metrics_endpoint(session_name, port=TEST_METRICS_EXPORT_PORT, timeout=30):
"""
Ensures the current dashboard agent is serving the metrics endpoint. A
timeout indicates another agent is still running and holding the port.
"""
def ready():
try:
resp = httpx.get(f"http://localhost:{port}/metrics", timeout=1.0)
except Exception:
return False
return resp.status_code == 200 and f'SessionName="{session_name}"' in resp.text
wait_for_condition(ready, timeout=timeout, retry_interval_ms=500)
@pytest.fixture
def metrics_start_shutdown(request):
param = request.param if hasattr(request, "param") else None
request_timeout_s = param if param else None
"""Fixture provides a fresh Ray cluster to prevent metrics state sharing."""
wait_for_metrics_port_free()
ray.init(
address="local",
_metrics_export_port=TEST_METRICS_EXPORT_PORT,
_system_config={
"metrics_report_interval_ms": 100,
"task_retry_delay_ms": 50,
},
)
try:
session_name = ray._private.worker._global_node.session_name
wait_for_metrics_endpoint(session_name)
grpc_port = 9000
grpc_servicer_functions = [
"ray.serve.generated.serve_pb2_grpc.add_UserDefinedServiceServicer_to_server",
"ray.serve.generated.serve_pb2_grpc.add_FruitServiceServicer_to_server",
]
yield serve.start(
grpc_options=gRPCOptions(
port=grpc_port,
grpc_servicer_functions=grpc_servicer_functions,
request_timeout_s=request_timeout_s,
),
http_options=HTTPOptions(
host="0.0.0.0",
request_timeout_s=request_timeout_s,
),
)
finally:
serve.shutdown()
ray.shutdown()
reset_ray_address()
# Helper function to return the node ID of a remote worker.
@ray.remote(num_cpus=0)
def _get_node_id():
return ray.get_runtime_context().get_node_id()
# Test fixture to start a Serve instance in a RayCluster with two labeled nodes
@pytest.fixture(scope="module")
def serve_instance_with_labeled_nodes():
cluster = Cluster()
# Unlabeled default node.
cluster.add_node(num_cpus=3, resources={"worker0": 1})
# Node 1 - labeled A100 node in us-west.
cluster.add_node(
num_cpus=3,
resources={"worker1": 1},
labels={"region": "us-west", "gpu-type": "A100"},
)
# Node 2 - labeled H100 node in us-east.
cluster.add_node(
num_cpus=3,
resources={"worker2": 1},
labels={"region": "us-east", "gpu-type": "H100"},
)
cluster.wait_for_nodes()
if ray.is_initialized():
ray.shutdown()
ray.init(address=cluster.address)
node_1_id = ray.get(_get_node_id.options(resources={"worker1": 1}).remote())
node_2_id = ray.get(_get_node_id.options(resources={"worker2": 1}).remote())
serve.start()
yield _get_global_client(), node_1_id, node_2_id, cluster
serve.shutdown()
ray.shutdown()
cluster.shutdown()