Skip to content

Commit

Permalink
Add more tests
Browse files Browse the repository at this point in the history
  • Loading branch information
sihanwang41 committed Jul 12, 2022
1 parent da106cc commit dae9fe0
Showing 1 changed file with 38 additions and 42 deletions.
80 changes: 38 additions & 42 deletions python/ray/serve/tests/test_deploy.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
from ray import serve
from ray.serve.exceptions import RayServeException
from ray.serve.utils import get_random_letters
from pydantic import ValidationError


@pytest.mark.parametrize("use_handle", [True, False])
Expand All @@ -28,18 +29,18 @@ def call():

return ret.split("|")[0], ret.split("|")[1]

d.deploy()
serve.run(d.bind())
val1, pid1 = call()
assert val1 == "1"

# Redeploying with the same version and code should do nothing.
d.deploy()
serve.run(d.bind())
val2, pid2 = call()
assert val2 == "1"
assert pid2 == pid1

# Redeploying with a new version should start a new actor.
d.options(version="2").deploy()
serve.run(d.options(version="2").bind())
val3, pid3 = call()
assert val3 == "1"
assert pid3 != pid2
Expand All @@ -49,14 +50,14 @@ def d(*args):
return f"2|{os.getpid()}"

# Redeploying with the same version and new code should do nothing.
d.deploy()
serve.run(d.bind())
val4, pid4 = call()
assert val4 == "1"
assert pid4 == pid3

# Redeploying with new code and a new version should start a new actor
# running the new code.
d.options(version="3").deploy()
serve.run(d.options(version="3").bind())
val5, pid5 = call()
assert val5 == "2"
assert pid5 != pid4
Expand All @@ -74,11 +75,11 @@ def ping(self, *args):

assert func.name == "func"
assert Class.name == "Class"
func.deploy()
Class.deploy()
func_handle = serve.run(func.bind())
assert ray.get(func_handle.remote()) == "hi"

assert ray.get(func.get_handle().remote()) == "hi"
assert ray.get(Class.get_handle().ping.remote()) == "pong"
class_handle = serve.run(Class.bind())
assert ray.get(class_handle.ping.remote()) == "pong"


@pytest.mark.parametrize("use_handle", [True, False])
Expand All @@ -97,7 +98,7 @@ def call():

return ret.split("|")[0], ret.split("|")[1]

v1.deploy()
serve.run(v1.bind())
val1, pid1 = call()
assert val1 == "1"

Expand All @@ -106,23 +107,23 @@ def v2(*args):
return f"2|{os.getpid()}"

# Not specifying a version tag should cause it to always be updated.
v2.deploy()
serve.run(v2.bind())
val2, pid2 = call()
assert val2 == "2"
assert pid2 != pid1

v2.deploy()
serve.run(v2.bind())
val3, pid3 = call()
assert val3 == "2"
assert pid3 != pid2

# Specifying the version should stop updates from happening.
v2.options(version="1").deploy()
serve.run(v2.options(version="1").bind())
val4, pid4 = call()
assert val4 == "2"
assert pid4 != pid3

v2.options(version="1").deploy()
serve.run(v2.options(version="1").bind())
val5, pid5 = call()
assert val5 == "2"
assert pid5 == pid4
Expand Down Expand Up @@ -150,31 +151,31 @@ def call():
return ret.split("|")[0], ret.split("|")[1]

# First deploy with no user config set.
D.deploy()
serve.run(D.bind())
val1, pid1 = call()
assert val1 == "1"

# Now update the user config without changing versions. Actor should stay
# alive but return value should change.
D.options(user_config={"ret": "2"}).deploy()
serve.run(D.options(user_config={"ret": "2"}).bind())
val2, pid2 = call()
assert pid2 == pid1
assert val2 == "2"

# Update the user config without changing the version again.
D.options(user_config={"ret": "3"}).deploy()
serve.run(D.options(user_config={"ret": "3"}).bind())
val3, pid3 = call()
assert pid3 == pid2
assert val3 == "3"

# Update the version without changing the user config.
D.options(version="2", user_config={"ret": "3"}).deploy()
serve.run(D.options(version="2", user_config={"ret": "3"}).bind())
val4, pid4 = call()
assert pid4 != pid3
assert val4 == "3"

# Update the version and the user config.
D.options(version="3", user_config={"ret": "4"}).deploy()
serve.run(D.options(version="3", user_config={"ret": "4"}).bind())
val5, pid5 = call()
assert pid5 != pid4
assert val5 == "4"
Expand All @@ -195,12 +196,8 @@ def reconfigure(self, config):
def __call__(self, *args):
return self.config

A.options(user_config="not_hi").deploy()
config = ray.get(A.get_handle().remote())
assert config == "not_hi"

with pytest.raises(RuntimeError):
A.options(user_config="hi").deploy()
with pytest.raises(ValidationError):
serve.run(A.options(user_config="hi").bind())


@pytest.mark.parametrize("use_handle", [True, False])
Expand Down Expand Up @@ -245,7 +242,7 @@ async def handler(self, *args):
async def __call__(self, request):
return await self.handler()

V1.deploy()
serve.run(V1.bind())
ref1 = call.remote(block=False)
val1, pid1 = ray.get(ref1)
assert val1 == "1"
Expand All @@ -257,7 +254,7 @@ async def __call__(self, request):
# Redeploy new version. This should not go through until the old version
# replica completely stops.
V2 = V1.options(func_or_class=V2, version="2")
V2.deploy(_blocking=False)
serve.run(V2.bind(), _blocking=False)
with pytest.raises(TimeoutError):
client._wait_for_deployment_healthy(V2.name, timeout_s=0.1)

Expand Down Expand Up @@ -359,7 +356,7 @@ def make_nonblocking_calls(expected, expect_blocking=False):

return responses, blocking

V1.deploy()
serve.run(V1.bind())
responses1, _ = make_nonblocking_calls({"1": 2})
pids1 = responses1["1"]

Expand All @@ -372,7 +369,7 @@ def make_nonblocking_calls(expected, expect_blocking=False):
# Redeploy new version. Since there is one replica blocking, only one new
# replica should be started up.
V2 = V1.options(func_or_class=V2, version="2")
V2.deploy(_blocking=False)
serve.run(V2.bind(), _blocking=False)
with pytest.raises(TimeoutError):
client._wait_for_deployment_healthy(V2.name, timeout_s=0.1)
responses3, blocking3 = make_nonblocking_calls({"1": 1}, expect_blocking=True)
Expand Down Expand Up @@ -424,7 +421,8 @@ async def reconfigure(self, config):
self.config = config

async def handler(self):
return f"{self.config}|{os.getpid()}"
val = self.config["test"]
return f"{val}|{os.getpid()}"

async def __call__(self, request):
return await self.handler()
Expand Down Expand Up @@ -452,13 +450,13 @@ def make_nonblocking_calls(expected, expect_blocking=False):

return responses, blocking

V1.options(user_config="1").deploy()
V1.options(user_config={"test": "1"}).deploy()
responses1, _ = make_nonblocking_calls({"1": 2})
pids1 = responses1["1"]

# Reconfigure should block one replica until the signal is sent. Check that
# some requests are now blocking.
V1.options(user_config="2").deploy(_blocking=False)
V1.options(user_config={"test": "2"}).deploy(_blocking=False)
responses2, blocking2 = make_nonblocking_calls({"1": 1}, expect_blocking=True)
assert list(responses2["1"])[0] in pids1

Expand All @@ -484,15 +482,14 @@ async def __call__(self):
await signal.wait.remote()
return self.state["a"]

A.options(version="1", user_config={"a": 1}).deploy()
handle = A.get_handle()
handle = serve.run(A.options(version="1", user_config={"a": 1}).bind())
refs = []
for _ in range(30):
refs.append(handle.remote())

@ray.remote(num_cpus=0)
def reconfigure():
A.options(version="1", user_config={"a": 2}).deploy()
serve.run(A.options(version="1", user_config={"a": 2}).bind())

reconfigure_ref = reconfigure.remote()
signal.send.remote()
Expand Down Expand Up @@ -540,15 +537,15 @@ def make_calls(expected):

return responses

v1.deploy()
serve.run(v1.bind())
responses1 = make_calls({"1": 4})
pids1 = responses1["1"]

@serve.deployment(name=name, version="2", num_replicas=2)
def v2(*args):
return f"2|{os.getpid()}"

v2.deploy()
serve.run(v2.bind())
responses2 = make_calls({"2": 2})
assert all(pid not in pids1 for pid in responses2["2"])

Expand Down Expand Up @@ -591,15 +588,15 @@ def make_calls(expected):

return responses

v1.deploy()
serve.run(v1.bind())
responses1 = make_calls({"1": 2})
pids1 = responses1["1"]

@serve.deployment(name=name, version="2", num_replicas=4)
def v2(*args):
return f"2|{os.getpid()}"

v2.deploy()
serve.run(v2.bind())
responses2 = make_calls({"2": 4})
assert all(pid not in pids1 for pid in responses2["2"])

Expand All @@ -610,7 +607,7 @@ class A:
def b(self, *args):
return "hello"

A.deploy()
serve.run(A.bind())
handle = A.get_handle()

# Legacy code path
Expand Down Expand Up @@ -729,8 +726,7 @@ def __init__(self, func):
def __call__(self, inp):
return self.func(inp)

Evaluator.deploy(lambda a: a + 1)
handle = Evaluator.get_handle()
handle = serve.run(Evaluator.bind(lambda a: a + 1))
assert ray.get(handle.remote(41)) == 42


Expand Down

0 comments on commit dae9fe0

Please sign in to comment.