Example #1
0
async def test_websocket_disconnected_after_logout(
    client: TestClient,
    logged_user: Dict[str, Any],
    socketio_client_factory: Callable,
    client_session_id_factory: Callable[[], str],
    expected,
    mocker: MockerFixture,
):
    app = client.server.app
    socket_registry = get_registry(app)

    # connect first socket
    cur_client_session_id1 = client_session_id_factory()
    sio = await socketio_client_factory(cur_client_session_id1)
    socket_logout_mock_callable = mocker.Mock()
    sio.on("logout", handler=socket_logout_mock_callable)

    # connect second socket
    cur_client_session_id2 = client_session_id_factory()
    sio2 = await socketio_client_factory(cur_client_session_id2)
    socket_logout_mock_callable2 = mocker.Mock()
    sio2.on("logout", handler=socket_logout_mock_callable2)

    # connect third socket
    cur_client_session_id3 = client_session_id_factory()
    sio3 = await socketio_client_factory(cur_client_session_id3)
    socket_logout_mock_callable3 = mocker.Mock()
    sio3.on("logout", handler=socket_logout_mock_callable3)

    # logout client with socket 2
    logout_url = client.app.router["auth_logout"].url_for()
    r = await client.post(f"{logout_url}",
                          json={"client_session_id": cur_client_session_id2})
    assert r.url_obj.path == logout_url.path
    await assert_status(r, expected)

    # the socket2 should be gone
    await asyncio.sleep(1)
    assert not sio2.sid
    socket_logout_mock_callable2.assert_not_called()

    # the others should receive a logout message through their respective sockets
    await asyncio.sleep(3)
    socket_logout_mock_callable.assert_called_once()
    socket_logout_mock_callable2.assert_not_called(
    )  # note 2 should be not called ever
    socket_logout_mock_callable3.assert_called_once()

    await asyncio.sleep(3)
    # first socket should be closed now
    assert not sio.sid
    # second socket also closed
    assert not sio3.sid
Example #2
0
async def test_disconnected_backend_send_computation_task(
    dask_spec_local_cluster: SpecCluster,
    dask_client: DaskClient,
    user_id: UserID,
    project_id: ProjectID,
    node_id: NodeID,
    cluster_id: ClusterID,
    cluster_id_resource: str,
    image: Image,
    expected_annotations: Dict[str, Any],
    mocker: MockerFixture,
):
    # INIT
    expected_annotations["resources"].update(
        {cluster_id_resource: CLUSTER_RESOURCE_MOCK_USAGE})

    fake_task = {node_id: image}
    mocked_done_callback_fct = mocker.Mock()

    # DISCONNECT THE CLUSTER
    await dask_spec_local_cluster.close()
    #
    with pytest.raises(ComputationalBackendNotConnectedError):
        await dask_client.send_computation_tasks(
            user_id=user_id,
            project_id=project_id,
            cluster_id=cluster_id,
            tasks=fake_task,
            callback=mocked_done_callback_fct,
            remote_fct=None,
        )
    assert (len(dask_client._taskid_to_future_map) == 0
            ), "dask client should not store any future here"
Example #3
0
async def test_too_many_resource_send_computation_task(
    dask_client: DaskClient,
    user_id: UserID,
    project_id: ProjectID,
    node_id: NodeID,
    cluster_id: ClusterID,
    cluster_id_resource: str,
    image: Image,
    expected_annotations: Dict[str, Any],
    mocker: MockerFixture,
):
    # INIT
    expected_annotations["resources"].update(
        {cluster_id_resource: CLUSTER_RESOURCE_MOCK_USAGE})

    fake_task = {node_id: image}
    mocked_done_callback_fct = mocker.Mock()

    # let's have a big number of CPUs
    with pytest.raises(InsuficientComputationalResourcesError):
        await dask_client.send_computation_tasks(
            user_id=user_id,
            project_id=project_id,
            cluster_id=cluster_id,
            tasks=fake_task,
            callback=mocked_done_callback_fct,
            remote_fct=None,
        )
    assert (len(dask_client._taskid_to_future_map) == 0
            ), "dask client should not store any future here"
Example #4
0
    def test_unknown_completion_mode_returns_default(
            self, mocker: MockerFixture) -> None:
        mock_config = mocker.Mock()
        mock_config.completion.mode = "unknown"

        config = GalaxyToolsConfiguration(mock_config)

        assert config.completion_mode == CompletionMode.AUTO
Example #5
0
    def test_init_sets_properties(self, mocker: MockerFixture) -> None:
        mock_config = mocker.Mock()
        mock_config.completion.mode = "invoke"
        mock_config.completion.autoCloseTags = "false"

        config = GalaxyToolsConfiguration(mock_config)

        assert config.completion_mode
        assert not config.auto_close_tags
Example #6
0
async def test_send_computation_task(
    dask_client: DaskClient,
    user_id: UserID,
    project_id: ProjectID,
    node_id: NodeID,
    cluster_id: ClusterID,
    cluster_id_resource: str,
    image: Image,
    expected_annotations: Dict[str, Any],
    mocker: MockerFixture,
):
    # INIT
    expected_annotations["resources"].update(
        {cluster_id_resource: CLUSTER_RESOURCE_MOCK_USAGE})
    fake_task = {node_id: image}
    mocked_done_callback_fct = mocker.Mock()

    # NOTE: We pass another fct so it can run in our localy created dask cluster
    def fake_sidecar_fct(job_id: str, u_id: str, prj_id: str,
                         n_id: str) -> int:
        from dask.distributed import get_worker

        worker = get_worker()
        task: TaskState = worker.tasks.get(worker.get_current_task())
        assert task is not None
        assert task.annotations == expected_annotations
        assert u_id == user_id
        assert prj_id == project_id
        assert n_id == node_id
        return 123

    # TEST COMPUTATION RUNS THROUGH
    await dask_client.send_computation_tasks(
        user_id=user_id,
        project_id=project_id,
        cluster_id=cluster_id,
        tasks=fake_task,
        callback=mocked_done_callback_fct,
        remote_fct=fake_sidecar_fct,
    )
    assert (len(dask_client._taskid_to_future_map) == 1
            ), "dask client did not store the future of the task sent"

    job_id, future = list(dask_client._taskid_to_future_map.items())[0]
    # this waits for the computation to run
    task_result = await future.result(timeout=2)
    assert task_result == 123
    assert future.key == job_id
    await _wait_for_call(mocked_done_callback_fct)
    mocked_done_callback_fct.assert_called_once()
    mocked_done_callback_fct.reset_mock()
    assert (len(dask_client._taskid_to_future_map) == 0
            ), "the list of futures was not cleaned correctly"
Example #7
0
async def test_interactive_services_remain_after_websocket_reconnection_from_2_tabs(
    client,
    logged_user,
    empty_user_project,
    mocked_director_v2_api,
    create_dynamic_service_mock,
    socketio_client_factory: Callable,
    client_session_id_factory: Callable[[], str],
    storage_subsystem_mock,  # when guest user logs out garbage is collected
    expected_save_state: bool,
    mocker: MockerFixture,
):

    # login - logged_user fixture
    # create empty study - empty_user_project fixture
    # create dynamic service - create_dynamic_service_mock fixture
    service = await create_dynamic_service_mock(logged_user["id"],
                                                empty_user_project["uuid"])
    # create first websocket
    client_session_id1 = client_session_id_factory()
    sio = await socketio_client_factory(client_session_id1)
    # open project in client 1
    await open_project(client, empty_user_project["uuid"], client_session_id1)

    # create second websocket
    client_session_id2 = client_session_id_factory()
    sio2 = await socketio_client_factory(client_session_id2)
    assert sio.sid != sio2.sid
    socket_project_state_update_mock_callable = mocker.Mock()
    sio2.on(
        SOCKET_IO_PROJECT_UPDATED_EVENT,
        handler=socket_project_state_update_mock_callable,
    )
    # disconnect first websocket
    # NOTE: since the service deletion delay is set to 1 second for the test, we should not sleep as long here, or the user will be deleted
    # We have no mock-up for the heatbeat...
    await sio.disconnect()
    assert not sio.sid
    await asyncio.sleep(0.5)  # let the thread call the method
    socket_project_state_update_mock_callable.assert_called_with(
        json.dumps({
            "project_uuid": empty_user_project["uuid"],
            "data": {
                "locked": {
                    "value": False,
                    "owner": {
                        "user_id": logged_user["id"],
                        "first_name": logged_user["name"],
                        "last_name": "",
                    },
                    "status": "OPENED",
                },
                "state": {
                    "value": "NOT_STARTED"
                },
            },
        }))
    # open project in second client
    await open_project(client, empty_user_project["uuid"], client_session_id2)
    # ensure sufficient time is wasted here
    await asyncio.sleep(SERVICE_DELETION_DELAY + 1)
    await garbage_collector_core.collect_garbage(client.app)

    # assert dynamic service is still around
    mocked_director_v2_api["director_v2_api.stop_service"].assert_not_called()
    # disconnect second websocket
    await sio2.disconnect()
    assert not sio2.sid
    # assert dynamic service is still around for now
    mocked_director_v2_api["director_v2_api.stop_service"].assert_not_called()
    # reconnect websocket
    sio2 = await socketio_client_factory(client_session_id2)
    # it should still be there even after waiting for auto deletion from garbage collector
    await asyncio.sleep(SERVICE_DELETION_DELAY + 1)
    await garbage_collector_core.collect_garbage(client.app)

    mocked_director_v2_api["director_v2_api.stop_service"].assert_not_called()
    # now really disconnect
    await sio2.disconnect()
    assert not sio2.sid
    # run the garbage collector
    # event after waiting some time
    await asyncio.sleep(SERVICE_DELETION_DELAY + 1)
    await garbage_collector_core.collect_garbage(client.app)

    await asyncio.sleep(1)
    # assert dynamic service is gone
    calls = [
        call(
            app=client.server.app,
            save_state=expected_save_state,
            service_uuid=service["service_uuid"],
        )
    ]
    mocked_director_v2_api["director_v2_core.stop_service"].assert_has_calls(
        calls)
Example #8
0
def create_run_mock(run_api_mock, mocker: MockerFixture):
    run_api_mock.create_run = mocker.Mock()
    return run_api_mock.create_run