Beispiel #1
0
def test_only_print_queries(model_name, config, monkeypatch, caplog):
    """
    Test that if --only-print-queries is passed, the SQL query is printed but no deletions or
    simulation occurs.
    """
    caplog.set_level('INFO')
    delete_mock = mock.Mock()
    monkeypatch.setattr(QuerySet, 'delete', delete_mock)

    command = delete_old_records.Command()
    model = apps.get_model(model_name)
    mapping = MAPPING[model_name]
    model_factory = mapping['factory']

    for _ in range(3):
        _create_model_obj(model_factory,
                          **mapping['expired_objects_kwargs'][0])

    management.call_command(command, model_name, only_print_queries=True)

    assert not delete_mock.called

    log_text = caplog.text.lower()
    assert f'{model._meta.verbose_name_plural} to delete:' in log_text

    for relation in get_relations_to_delete(model):
        related_meta = relation.related_model._meta
        expected_related_log = (
            f'{related_meta.verbose_name_plural} to delete '
            f'(via {related_meta.model_name}.{relation.remote_field.name}): '
        ).lower()
        assert expected_related_log in log_text
        assert f'from "{related_meta.db_table}"' in log_text
def test_simulate(
    model_name,
    config,
    track_return_values,
    es_with_signals,
    es_collector_context_manager,
):
    """
    Test that if --simulate is passed in, the command only simulates the action
    without making any actual changes.
    """
    # Set up the state before running the command
    delete_return_value_tracker = track_return_values(QuerySet, 'delete')
    command = delete_old_records.Command()

    mapping = MAPPING[model_name]
    model_factory = mapping['factory']
    has_search_app = not mapping.get('has_no_search_app')

    with es_collector_context_manager as collector:
        for _ in range(3):
            _create_model_obj(model_factory,
                              **mapping['expired_objects_kwargs'][0])

        collector.flush_and_refresh()

    model = apps.get_model(model_name)

    if has_search_app:
        search_app = get_search_app_by_model(model)
        read_alias = search_app.es_model.get_read_alias()
        assert es_with_signals.count(read_alias,
                                     doc_type=search_app.name)['count'] == 3

    assert model.objects.count() == 3

    # Run the command
    management.call_command(command, model_name, simulate=True)
    es_with_signals.indices.refresh()

    # Check which models were deleted prior to the rollback
    return_values = delete_return_value_tracker.return_values
    assert len(return_values) == 1
    _, deletions_by_model = return_values[0]
    actual_deleted_models = {  # only include models actually deleted
        deleted_model
        for deleted_model, deleted_count in deletions_by_model.items()
        if deleted_count
    }
    assert model._meta.label in {model._meta.label}
    assert actual_deleted_models - {model._meta.label
                                    } <= mapping['implicitly_deletable_models']
    assert deletions_by_model[model._meta.label] == 3

    # Check that nothing has actually been deleted
    assert model.objects.count() == 3

    if has_search_app:
        assert es_with_signals.count(read_alias,
                                     doc_type=search_app.name)['count'] == 3
Beispiel #3
0
def test_with_opensearch_exception(mocked_bulk):
    """
    Test that if OpenSearch returns a 5xx error, the command completes but it also
    raises a DataHubError with details of the error.
    """
    mocked_bulk.return_value = (None, [{'delete': {'status': 500}}])

    command = delete_old_records.Command()
    model_name = next(iter(delete_old_records.Command.CONFIGS))
    mapping = MAPPING[model_name]
    model_factory = MAPPING[model_name]['factory']

    _create_model_obj(model_factory, **mapping['expired_objects_kwargs'][0])

    with pytest.raises(DataHubError):
        management.call_command(command, model_name)

    model = apps.get_model(model_name)
    assert model.objects.count() == 0
Beispiel #4
0
def test_run(
    model_label,
    factory_kwargs,
    relation_mapping,
    relation_factory_kwargs,
    is_expired,
    track_return_values,
    opensearch_with_signals,
    opensearch_collector_context_manager,
):
    """Tests the delete_old_records commands for various cases specified by MAPPING above."""
    # Set up the state before running the command
    mapping = MAPPING[model_label]
    model_factory = mapping['factory']
    command = delete_old_records.Command()
    model = apps.get_model(model_label)
    has_search_app = not mapping.get('has_no_search_app')

    delete_return_value_tracker = track_return_values(QuerySet, 'delete')

    with opensearch_collector_context_manager as collector:
        obj = _create_model_obj(model_factory, **factory_kwargs)
        total_model_records = 1

        if relation_mapping:
            relation_model = relation_mapping['factory']._meta.get_model_class(
            )
            relation_field = relation_model._meta.get_field(
                relation_mapping['field'])
            relation_factory_arg = [obj
                                    ] if relation_field.many_to_many else obj

            _create_model_obj(
                relation_mapping['factory'],
                **relation_factory_kwargs,
                **{relation_mapping['field']: relation_factory_arg},
            )
            if relation_mapping['factory']._meta.get_model_class() is model:
                total_model_records += 1

        collector.flush_and_refresh()

    num_expired_records = 1 if is_expired else 0

    if has_search_app:
        search_app = get_search_app_by_model(model)
        read_alias = search_app.search_model.get_read_alias()
        assert opensearch_with_signals.count(
            index=read_alias)['count'] == total_model_records

    assert model.objects.count() == total_model_records

    # Run the command
    management.call_command(command, model_label)
    opensearch_with_signals.indices.refresh()

    # Check if the object has been deleted
    assert model.objects.count() == total_model_records - num_expired_records

    if has_search_app:
        assert opensearch_with_signals.count(
            index=read_alias)['count'] == (total_model_records -
                                           num_expired_records)

    # Check which models were actually deleted
    return_values = delete_return_value_tracker.return_values
    assert len(return_values) == 1
    _, deletions_by_model = return_values[0]

    if is_expired:
        assert deletions_by_model[model._meta.label] == num_expired_records
        assert model._meta.label in {model._meta.label}

    actual_deleted_models = {  # only include models actually deleted
        deleted_model
        for deleted_model, deleted_count in deletions_by_model.items()
        if deleted_count
    }
    assert actual_deleted_models - {model._meta.label
                                    } <= mapping['implicitly_deletable_models']
def test_run(
    model_label,
    factory_kwargs,
    relation_mapping,
    relation_factory_kwargs,
    is_expired,
    track_return_values,
    setup_es,
):
    """Tests the delete_old_records commands for various cases specified by MAPPING above."""
    mapping = MAPPING[model_label]
    model_factory = mapping['factory']
    command = delete_old_records.Command()
    model = apps.get_model(model_label)

    delete_return_value_tracker = track_return_values(QuerySet, 'delete')

    obj = _create_model_obj(model_factory, **factory_kwargs)
    total_model_records = 1

    if relation_mapping:
        relation_model = relation_mapping['factory']._meta.get_model_class()
        relation_field = relation_model._meta.get_field(
            relation_mapping['field'])
        relation_factory_arg = [obj] if relation_field.many_to_many else obj

        _create_model_obj(
            relation_mapping['factory'],
            **relation_factory_kwargs,
            **{relation_mapping['field']: relation_factory_arg},
        )
        if relation_mapping['factory']._meta.get_model_class() is model:
            total_model_records += 1

    num_expired_records = 1 if is_expired else 0

    search_app = get_search_app_by_model(model)
    doc_type = search_app.name
    read_alias = search_app.es_model.get_read_alias()

    setup_es.indices.refresh()
    assert model.objects.count() == total_model_records
    assert setup_es.count(read_alias,
                          doc_type=doc_type)['count'] == total_model_records

    management.call_command(command, model_label)
    setup_es.indices.refresh()

    # Check if the object has been deleted
    assert model.objects.count() == total_model_records - num_expired_records
    assert setup_es.count(read_alias,
                          doc_type=doc_type)['count'] == (total_model_records -
                                                          num_expired_records)

    # Check which models were actually deleted
    return_values = delete_return_value_tracker.return_values
    assert len(return_values) == 1
    _, deletions_by_model = return_values[0]

    if is_expired:
        assert deletions_by_model[model._meta.label] == num_expired_records
        assert model._meta.label in {model._meta.label}

    actual_deleted_models = {  # only include models actually deleted
        deleted_model
        for deleted_model, deleted_count in deletions_by_model.items()
        if deleted_count
    }
    assert actual_deleted_models - {model._meta.label
                                    } <= mapping['implicitly_deletable_models']