Ejemplo n.º 1
0
async def test_blueprint_stop_failure(bootsteps_graph,
                                      mock_execution_order_strategy_class,
                                      logger):
    mock_step1 = create_mock_step("step1")
    mock_step2 = create_start_stop_mock_step("step2")
    mock_step3 = create_mock_step("step3")
    mock_step4 = create_start_stop_mock_step("step4",
                                             mock_class=TrioCoroutineMock)
    mock_step4.stop.side_effect = expected_exception = RuntimeError(
        "Expected Failure")
    mock_step5 = create_mock_step("step5")
    mock_step6 = create_mock_step("step6",
                                  spec=AsyncStep,
                                  mock_class=TrioCoroutineMock)

    # We're using a parent mock simply to record the order of calls to different
    # steps
    m = Mock()
    m.attach_mock(mock_step1, "mock_step1")
    m.attach_mock(mock_step2, "mock_step2")
    m.attach_mock(mock_step3, "mock_step3")
    m.attach_mock(mock_step4, "mock_step4")
    m.attach_mock(mock_step5, "mock_step5")
    m.attach_mock(mock_step6, "mock_step6")

    expected_execution_order = [
        [m.mock_step1, m.mock_step2],
        [m.mock_step3, m.mock_step4, m.mock_step5],
        [m.mock_step6],
    ]
    mock_iterator = MagicMock()
    mock_iterator.__iter__.return_value = expected_execution_order
    reversed_func = Mock(return_value=reversed(expected_execution_order))
    mock_iterator.__reversed__ = reversed_func
    mock_execution_order_strategy_class.return_value = mock_iterator

    blueprint = Blueprint(
        bootsteps_graph,
        name="Test",
        execution_order_strategy_class=mock_execution_order_strategy_class,
    )

    with pytest.raises(RuntimeError):
        async with trio.open_nursery() as nursery:
            nursery.start_soon(blueprint.stop)

    with trio.fail_after(1):
        assert (await blueprint.state_changes_receive_channel.receive() ==
                BlueprintState.TERMINATING)

    with trio.fail_after(1):
        assert await blueprint.state_changes_receive_channel.receive() == (
            BlueprintState.FAILED,
            expected_exception,
        )

    mock_execution_order_strategy_class.assert_called_once_with(
        blueprint._steps)

    assert_parallelized_steps_are_in_order(m.method_calls,
                                           [[call.mock_step4.stop()]])

    mock_step1.assert_not_called()
    mock_step2.stop.assert_not_called()
    mock_step3.assert_not_called()
    mock_step5.assert_not_called()
    mock_step6.assert_not_called()

    logged_actions = LoggedAction.of_type(logger.messages,
                                          "bootsteps:blueprint:stop")
    assert len(logged_actions) == 1
    logged_action = logged_actions[0]
    assert_log_message_field_equals(logged_action.start_message, "name",
                                    blueprint.name)
    assert_logged_action_failed(logged_action)

    messages = LoggedMessage.of_type(logger.messages,
                                     "bootsteps:blueprint:next_bootsteps")
    assert len(messages) == 1, messages

    assert_log_message_field_equals(messages[0].message, "name",
                                    blueprint.name)
    assert_log_message_field_equals(messages[0].message, "next_bootsteps",
                                    [m.mock_step4])

    logged_actions = LoggedAction.of_type(
        logger.messages, "bootsteps:blueprint:executing_bootstep")
    assert len(logged_actions) == 1

    start_messages = [
        logged_action.start_message for logged_action in logged_actions
    ]

    assert_field_equals_in_any_message(start_messages, "bootstep",
                                       m.mock_step4.stop)

    assert_logged_action_failed(logged_actions[0])