Example #1
0
def test_simple_function_node_json_serde(serve_instance):
    """
    Test the following behavior
        1) Ray DAG node can go through full JSON serde cycle
        2) Ray DAG node and deserialized DAG node produces same output
        3) Ray DAG node can go through multiple rounds of JSON serde and still
            provides the same value as if it's only JSON serde once
    Against following test cases
        - Simple function with no args
        - Simple function with only args, all primitive types
        - Simple function with args + kwargs, all primitive types
    """
    original_dag_node = combine.bind(1, 2)
    _test_deployment_json_serde_helper(
        original_dag_node,
        expected_num_deployments=1,
    )

    original_dag_node = combine.bind(1, 2, kwargs_output=3)
    _test_deployment_json_serde_helper(
        original_dag_node,
        expected_num_deployments=1,
    )

    original_dag_node = fn_hello.bind()
    _test_deployment_json_serde_helper(
        original_dag_node,
        expected_num_deployments=1,
    )
Example #2
0
def test_get_pipeline_input_node():
    # 1) No InputNode found
    ray_dag = combine.bind(1, 2)
    with _DAGNodeNameGenerator() as node_name_generator:
        serve_dag = ray_dag.apply_recursive(
            lambda node: transform_ray_dag_to_serve_dag(node, node_name_generator)
        )
    with pytest.raises(
        AssertionError, match="There should be one and only one InputNode"
    ):
        get_pipeline_input_node(serve_dag)

    # 2) More than one InputNode found
    with InputNode() as dag_input:
        a = combine.bind(dag_input[0], dag_input[1])
    with InputNode() as dag_input_2:
        b = combine.bind(dag_input_2[0], dag_input_2[1])
        ray_dag = combine.bind(a, b)
    with pytest.raises(
        AssertionError, match="Each DAG should only have one unique InputNode"
    ):
        with _DAGNodeNameGenerator() as node_name_generator:
            serve_dag = ray_dag.apply_recursive(
                lambda node: transform_ray_dag_to_serve_dag(node, node_name_generator)
            )
        get_pipeline_input_node(serve_dag)
Example #3
0
def test_simple_function_node_json_serde(serve_instance):
    """
    Test the following behavior
        1) Ray DAG node can go through full JSON serde cycle
        2) Ray DAG node and deserialized DAG node produces same output
        3) Ray DAG node can go through multiple rounds of JSON serde and still
            provides the same value as if it's only JSON serde once
    Against following test cases
        - Simple function with no args
        - Simple function with only args, all primitive types
        - Simple function with args + kwargs, all primitive types
    """
    original_dag_node = combine.bind(1, 2)
    _test_json_serde_helper(
        original_dag_node,
        executor_fn=_test_execution_function_node,
        expected_json_dict={
            DAGNODE_TYPE_KEY: "FunctionNode",
            "import_path": "ray.serve.tests.resources.test_modules.combine",
            "args": [1, 2],
            "kwargs": {},
            "options": {},
            "other_args_to_resolve": {},
            "uuid": original_dag_node.get_stable_uuid(),
        },
    )

    original_dag_node = combine.bind(1, 2, kwargs_output=3)
    _test_json_serde_helper(
        original_dag_node,
        executor_fn=_test_execution_function_node,
        expected_json_dict={
            DAGNODE_TYPE_KEY: "FunctionNode",
            "import_path": "ray.serve.tests.resources.test_modules.combine",
            "args": [1, 2],
            "kwargs": {
                "kwargs_output": 3
            },
            "options": {},
            "other_args_to_resolve": {},
            "uuid": original_dag_node.get_stable_uuid(),
        },
    )

    original_dag_node = fn_hello.bind()
    _test_json_serde_helper(
        original_dag_node,
        executor_fn=_test_execution_function_node,
        expected_json_dict={
            DAGNODE_TYPE_KEY: "FunctionNode",
            "import_path": "ray.serve.tests.resources.test_modules.fn_hello",
            "args": [],
            "kwargs": {},
            "options": {},
            "other_args_to_resolve": {},
            "uuid": original_dag_node.get_stable_uuid(),
        },
    )
Example #4
0
def get_func_class_with_class_method_dag():
    with InputNode() as dag_input:
        m1 = Model.bind(1)
        m2 = Model.bind(2)
        m1_output = m1.forward.bind(dag_input[0])
        m2_output = m2.forward.bind(dag_input[1])
        ray_dag = combine.bind(m1_output,
                               m2_output,
                               kwargs_output=dag_input[2])

    return ray_dag, dag_input
Example #5
0
def test_non_json_serializable_args():
    """Use non-JSON serializable object in Ray DAG and ensure we throw exception
    with reasonable error messages.
    """
    class MyNonJSONClass:
        def __init__(self, val):
            self.val = val

    ray_dag = combine.bind(MyNonJSONClass(1), MyNonJSONClass(2))
    # General context
    with pytest.raises(
            TypeError,
            match=r"Object of type .* is not JSON serializable",
    ):
        _ = json.dumps(ray_dag, cls=DAGNodeEncoder)
Example #6
0
def test_nested_deployment_node_json_serde(serve_instance):
    with InputNode() as dag_input:
        m1 = Model.bind(2)
        m2 = Model.bind(3)

        m1_output = m1.forward.bind(dag_input)
        m2_output = m2.forward.bind(dag_input)

        ray_dag = combine.bind(m1_output, m2_output)
    (
        serve_root_dag,
        deserialized_serve_root_dag_node,
    ) = _test_deployment_json_serde_helper(ray_dag,
                                           input=1,
                                           expected_num_deployments=2)
    assert ray.get(serve_root_dag.execute(1)) == ray.get(
        deserialized_serve_root_dag_node.execute(1))
Example #7
0
def get_simple_func_dag():
    with InputNode() as dag_input:
        ray_dag = combine.bind(dag_input[0], dag_input[1], kwargs_output=1)

    return ray_dag, dag_input