[Dashboard ]Action Implementation. (#7826)

This commit is contained in:
SangBin Cho
2020-04-02 18:02:37 -07:00
committed by GitHub
parent a3181816b3
commit 1d532d1cb8
6 changed files with 228 additions and 46 deletions
+95 -10
View File
@@ -3,10 +3,11 @@ import requests
from unittest.mock import patch
from ray.dashboard.metrics_exporter.actions import ActionHandler
from ray.dashboard.metrics_exporter.client import MetricsExportClient
from ray.dashboard.metrics_exporter.client import Exporter
from ray.dashboard.metrics_exporter.schema import (AuthResponse, BaseModel,
ValidationError)
ValidationError, Field)
MOCK_DASHBOARD_ID = "1234"
MOCK_DASHBOARD_ADDRESS = "127.0.0.1:9081"
@@ -20,6 +21,11 @@ def _setup_client_and_exporter(controller):
return exporter, client
"""
Test Exporter
"""
@patch("ray.dashboard.dashboard.DashboardController")
def test_verify_exporter_cannot_run_without_access_token(mock_controller):
exporter, client = _setup_client_and_exporter(mock_controller)
@@ -28,6 +34,11 @@ def test_verify_exporter_cannot_run_without_access_token(mock_controller):
exporter.run()
"""
Test Client
"""
@patch("ray.dashboard.dashboard.DashboardController")
@patch(
"ray.dashboard.metrics_exporter.api.authentication_request",
@@ -129,8 +140,13 @@ BaseModel Test
def test_base_model():
DEFAULT_VALUE = "default"
class A(BaseModel):
__slots__ = ["a", "b"]
__schema__ = {
"a": Field(required=True, default=None, type=str),
"b": Field(required=False, default=DEFAULT_VALUE, type=str)
}
# Test the correct case.
obj = {"a": "1", "b": "1"}
@@ -152,20 +168,89 @@ def test_base_model():
with pytest.raises(AssertionError):
a = A.parse_obj(obj)
# Test when fields are not sufficient.
obj = {"a": "1"}
# Test when required fields are not provided.
obj = {"b": "1"}
with pytest.raises(ValidationError):
a = A.parse_obj(obj)
# Test when fields are more than expected.
obj = {"a": "1", "b": "1", "c": "1"}
# Test optional fields are set to default when fields are not given.
obj = {"a": "1"}
a = A.parse_obj(obj)
assert a.b == DEFAULT_VALUE
# Test when fields that are not defined in the schema is given.
# It should be ignoered
obj = {"a": "a", "b": "b", "c": "c"}
a = A.parse_obj(obj)
assert a.a == "a"
assert a.b == "b"
assert a.c == "c"
"""
Test Action Handler
"""
def _get_mock_kill_action():
return {
"type": "KILL_ACTOR",
"actor_id": "1234",
"ip_address": "1234",
"port": 30
}
@patch("ray.dashboard.dashboard.DashboardController")
def test_handle_kill_action(mock_controller):
action_handler = ActionHandler(mock_controller)
kill_action = _get_mock_kill_action()
action_handler.handle_kill_action(kill_action)
assert mock_controller.kill_actor.call_count == 1
@patch("ray.dashboard.dashboard.DashboardController")
def test_handle_kill_action_invalid_dict(mock_controller):
action_handler = ActionHandler(mock_controller)
kill_action = {"type": "KILL_ACTOR", "ip_address": "1234", "port": 30}
with pytest.raises(ValidationError):
a = A.parse_obj(obj)
action_handler.handle_kill_action(kill_action)
@patch("ray.dashboard.dashboard.DashboardController")
def test_handle_actions_many_kill_actor(mock_controller):
action_handler = ActionHandler(mock_controller)
# 10 actions required.
actions = [_get_mock_kill_action() for _ in range(10)]
action_handler.handle_actions(actions)
assert mock_controller.kill_actor.call_count == 10
@patch("ray.dashboard.dashboard.DashboardController")
def test_handle_actions_kill_actor_and_mixed_type(mock_controller):
action_handler = ActionHandler(mock_controller)
wrong_type_action = {"type": "NON_EXIST"}
actions = [
_get_mock_kill_action(), wrong_type_action,
_get_mock_kill_action()
]
action_handler.handle_actions(actions)
assert mock_controller.kill_actor.call_count == 2
@patch("ray.dashboard.dashboard.DashboardController")
def test_handle_actions_only_wrong_type(mock_controller):
action_handler = ActionHandler(mock_controller)
wrong_type_action = {"type": "NON_EXIST"}
actions = [wrong_type_action for _ in range(10)]
action_handler.handle_actions(actions)
assert mock_controller.kill_actor.call_count == 0
if __name__ == "__main__":
import sys
import os
os.environ["LC_ALL"] = "en_US.UTF-8"
os.environ["LANG"] = "en_US.UTF-8"
sys.exit(pytest.main(["-v", __file__]))
+13 -1
View File
@@ -25,8 +25,20 @@ def test_get_webui(shutdown_only):
break
except requests.exceptions.ConnectionError:
if time.time() > start_time + 30:
error_log = None
out_log = None
with open(
"{}/logs/dashboard.out".format(
addresses["session_dir"]), "r") as f:
out_log = f.read()
with open(
"{}/logs/dashboard.err".format(
addresses["session_dir"]), "r") as f:
error_log = f.read()
raise Exception(
"Timed out while waiting for dashboard to start.")
"Timed out while waiting for dashboard to start. "
"Dashboard output log: {}\n"
"Dashboard error log: {}\n".format(out_log, error_log))
assert node_info["error"] is None
assert node_info["result"] is not None
assert isinstance(node_info["timestamp"], float)