diff --git a/dashboard/modules/serve/tests/test_schema.py b/dashboard/modules/serve/tests/test_schema.py index 4af22a0bfcde..06bbc1bfa2f2 100644 --- a/dashboard/modules/serve/tests/test_schema.py +++ b/dashboard/modules/serve/tests/test_schema.py @@ -1,4 +1,7 @@ +import sys + from pydantic import ValidationError + import pytest import requests @@ -586,3 +589,7 @@ def f2(): assert len(deployment_names) == 0 serve.shutdown() + + +if __name__ == "__main__": + sys.exit(pytest.main(["-v", __file__])) diff --git a/dashboard/modules/serve/tests/test_serve_head.py b/dashboard/modules/serve/tests/test_serve_head.py index 31627be16868..e77b54f30f2c 100644 --- a/dashboard/modules/serve/tests/test_serve_head.py +++ b/dashboard/modules/serve/tests/test_serve_head.py @@ -1,8 +1,12 @@ -import pytest +import json import subprocess +import sys +import os +from typing import List, Dict, Set + +import pytest + import requests -import json -from typing import List, Dict GET_OR_PUT_URL = "http://localhost:8265/api/serve/deployments/" @@ -12,15 +16,17 @@ @pytest.fixture -def serve_start_stop(): +def ray_start_stop(): subprocess.check_output(["ray", "start", "--head"]) - subprocess.check_output(["serve", "start"]) yield subprocess.check_output(["ray", "stop", "--force"]) -def deployments_match(list1: List[Dict], list2: List[Dict]) -> bool: - # Helper that takes in 2 lists of deployment dictionaries and compares them +def deployments_match(list1: List[Dict], list2: List[Dict], properties: Set) -> bool: + """ + Helper that takes in 2 lists of deployment dictionaries and compares their + properties and ray_actor_options. + """ if len(list1) != len(list2): return False @@ -29,7 +35,10 @@ def deployments_match(list1: List[Dict], list2: List[Dict]) -> bool: matching_deployment = None for i in range(len(list2)): deployment2 = list2[i] - if deployment1 == deployment2: + for property in properties: + if deployment1[property] != deployment2[property]: + break + else: matching_deployment = i if matching_deployment is None: return False @@ -38,8 +47,14 @@ def deployments_match(list1: List[Dict], list2: List[Dict]) -> bool: return len(list2) == 0 -def test_put_get_success(serve_start_stop): - ray_actor_options = {"runtime_env": {"py_modules": [test_env_uri, test_module_uri]}} +@pytest.mark.skipif( + sys.platform == "win32", reason="File paths incompatible with Windows." +) +def test_put_get_success(ray_start_stop): + ray_actor_options = { + "runtime_env": {"py_modules": [test_env_uri, test_module_uri]}, + "num_cpus": 0.1, + } shallow = dict( name="shallow", @@ -64,45 +79,70 @@ def test_put_get_success(serve_start_stop): import_path="test_module.test.one", ) + three_deployments = os.path.join( + os.path.dirname(__file__), "three_deployments_response.json" + ) + + two_deployments = os.path.join( + os.path.dirname(__file__), "two_deployments_response.json" + ) + # Ensure the REST API is idempotent - for _ in range(3): + for _ in range(2): deployments = [shallow, deep, one] - put_response = requests.put(GET_OR_PUT_URL, json={"deployments": deployments}) + put_response = requests.put( + GET_OR_PUT_URL, json={"deployments": deployments}, timeout=30 + ) assert put_response.status_code == 200 assert ( - requests.get("http://localhost:8000/shallow").text == "Hello shallow world!" + requests.get("http://localhost:8000/shallow", timeout=30).text + == "Hello shallow world!" + ) + assert ( + requests.get("http://localhost:8000/deep", timeout=30).text + == "Hello deep world!" ) - assert requests.get("http://localhost:8000/deep").text == "Hello deep world!" - assert requests.get("http://localhost:8000/one").text == "2" + assert requests.get("http://localhost:8000/one", timeout=30).text == "2" - get_response = requests.get(GET_OR_PUT_URL) + get_response = requests.get(GET_OR_PUT_URL, timeout=30) assert get_response.status_code == 200 - with open("three_deployments_response.json", "r") as f: + with open(three_deployments, "r") as f: response_deployments = get_response.json()["deployments"] expected_deployments = json.load(f)["deployments"] - assert deployments_match(response_deployments, expected_deployments) + assert deployments_match( + response_deployments, + expected_deployments, + {"name", "import_path", "num_replicas", "route_prefix"}, + ) deployments = [shallow, one] - put_response = requests.put(GET_OR_PUT_URL, json={"deployments": deployments}) + put_response = requests.put( + GET_OR_PUT_URL, json={"deployments": deployments}, timeout=30 + ) assert put_response.status_code == 200 assert ( - requests.get("http://localhost:8000/shallow").text == "Hello shallow world!" + requests.get("http://localhost:8000/shallow", timeout=30).text + == "Hello shallow world!" ) - assert requests.get("http://localhost:8000/deep").status_code == 404 - assert requests.get("http://localhost:8000/one").text == "2" + assert requests.get("http://localhost:8000/deep", timeout=30).status_code == 404 + assert requests.get("http://localhost:8000/one", timeout=30).text == "2" - get_response = requests.get(GET_OR_PUT_URL) + get_response = requests.get(GET_OR_PUT_URL, timeout=30) assert get_response.status_code == 200 - with open("two_deployments_response.json", "r") as f: + with open(two_deployments, "r") as f: response_deployments = get_response.json()["deployments"] expected_deployments = json.load(f)["deployments"] - assert deployments_match(response_deployments, expected_deployments) + assert deployments_match( + response_deployments, + expected_deployments, + {"name", "import_path", "num_replicas", "route_prefix"}, + ) -def test_delete_success(serve_start_stop): +def test_delete_success(ray_start_stop): ray_actor_options = { "runtime_env": { "working_dir": ( @@ -121,22 +161,25 @@ def test_delete_success(serve_start_stop): ) # Ensure the REST API is idempotent - for _ in range(5): - put_response = requests.put(GET_OR_PUT_URL, json={"deployments": [shallow]}) + for _ in range(2): + put_response = requests.put( + GET_OR_PUT_URL, json={"deployments": [shallow]}, timeout=30 + ) assert put_response.status_code == 200 assert ( - requests.get("http://localhost:8000/shallow").text == "Hello shallow world!" + requests.get("http://localhost:8000/shallow", timeout=30).text + == "Hello shallow world!" ) - delete_response = requests.delete(GET_OR_PUT_URL) + delete_response = requests.delete(GET_OR_PUT_URL, timeout=30) assert delete_response.status_code == 200 # Make sure no deployments exist - get_response = requests.get(GET_OR_PUT_URL) + get_response = requests.get(GET_OR_PUT_URL, timeout=30) assert len(get_response.json()["deployments"]) == 0 -def test_get_status_info(serve_start_stop): +def test_get_status_info(ray_start_stop): ray_actor_options = {"runtime_env": {"py_modules": [test_env_uri, test_module_uri]}} shallow = dict( @@ -164,10 +207,12 @@ def test_get_status_info(serve_start_stop): deployments = [shallow, deep, one] - put_response = requests.put(GET_OR_PUT_URL, json={"deployments": deployments}) + put_response = requests.put( + GET_OR_PUT_URL, json={"deployments": deployments}, timeout=30 + ) assert put_response.status_code == 200 - status_response = requests.get(STATUS_URL) + status_response = requests.get(STATUS_URL, timeout=30) assert status_response.status_code == 200 statuses = status_response.json()["statuses"] @@ -181,3 +226,7 @@ def test_get_status_info(serve_start_stop): assert len(expected_deployment_names) == 0 print(statuses) + + +if __name__ == "__main__": + sys.exit(pytest.main(["-v", __file__])) diff --git a/dashboard/modules/serve/tests/three_deployments_response.json b/dashboard/modules/serve/tests/three_deployments_response.json index c44030df8720..cb3a3a185383 100644 --- a/dashboard/modules/serve/tests/three_deployments_response.json +++ b/dashboard/modules/serve/tests/three_deployments_response.json @@ -23,7 +23,7 @@ ], "working_dir": null }, - "num_cpus": 1.0, + "num_cpus": 0.1, "num_gpus": 0.0, "memory": 0.0, "object_store_memory": 0.0, @@ -54,7 +54,7 @@ ], "working_dir": null }, - "num_cpus": 1.0, + "num_cpus": 0.1, "num_gpus": 0.0, "memory": 0.0, "object_store_memory": 0.0, @@ -85,7 +85,7 @@ ], "working_dir": null }, - "num_cpus": 1.0, + "num_cpus": 0.1, "num_gpus": 0.0, "memory": 0.0, "object_store_memory": 0.0, diff --git a/dashboard/modules/serve/tests/two_deployments_response.json b/dashboard/modules/serve/tests/two_deployments_response.json index fb81945ec307..49701e79169c 100644 --- a/dashboard/modules/serve/tests/two_deployments_response.json +++ b/dashboard/modules/serve/tests/two_deployments_response.json @@ -23,7 +23,7 @@ ], "working_dir": null }, - "num_cpus": 1.0, + "num_cpus": 0.1, "num_gpus": 0.0, "memory": 0.0, "object_store_memory": 0.0, @@ -54,7 +54,7 @@ ], "working_dir": null }, - "num_cpus": 1.0, + "num_cpus": 0.1, "num_gpus": 0.0, "memory": 0.0, "object_store_memory": 0.0,