コード例 #1
0
def test_simulate(
    cleanup_configs,
    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')
    model_name, config = cleanup_configs
    filter_config = config.filters[0]
    command = delete_orphans.Command()
    mapping = MAPPINGS[model_name]
    model_factory = mapping['factory']
    datetime_older_than_threshold = filter_config.cut_off_date - relativedelta(
        days=1)

    with es_collector_context_manager as collector:
        for _ in range(3):
            create_orphanable_model(model_factory, filter_config,
                                    datetime_older_than_threshold)

        collector.flush_and_refresh()

    model = apps.get_model(model_name)
    search_app = get_search_app_by_model(model)
    read_alias = search_app.es_model.get_read_alias()

    assert model.objects.count() == 3
    assert es_with_signals.count(read_alias,
                                 doc_type=search_app.name)['count'] == 3

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

    # 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]
    expected_deleted_models = {model._meta.label} | set(
        mapping['implicit_related_models'])
    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 == expected_deleted_models
    assert deletions_by_model[model._meta.label] == 3

    # Check that nothing has actually been deleted
    assert model.objects.count() == 3
    assert es_with_signals.count(read_alias,
                                 doc_type=search_app.name)['count'] == 3
コード例 #2
0
def test_only_print_queries(cleanup_configs, 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)

    model_name, config = cleanup_configs
    filter_config = config.filters[0]
    command = delete_orphans.Command()

    model = apps.get_model(model_name)
    mapping = MAPPINGS[model_name]
    model_factory = mapping['factory']
    datetime_older_than_threshold = filter_config.cut_off_date - relativedelta(
        days=1)

    for _ in range(3):
        create_orphanable_model(model_factory, filter_config,
                                datetime_older_than_threshold)

    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
コード例 #3
0
def test_with_es_exception(mocked_bulk):
    """
    Test that if ES returns a 5xx error, the command completes but it also
    raises a DataHubException with details of the error.
    """
    mocked_bulk.return_value = (None, [{'delete': {'status': 500}}])

    command = delete_orphans.Command()
    model_name = next(iter(delete_orphans.Command.CONFIGS))
    model_factory = MAPPINGS[model_name]['factory']
    filter_config = delete_orphans.Command.CONFIGS[model_name].filters[0]

    datetime_older_than_threshold = (FROZEN_TIME -
                                     filter_config.age_threshold -
                                     relativedelta(days=1))
    create_orphanable_model(model_factory, filter_config,
                            datetime_older_than_threshold)

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

    model = apps.get_model(model_name)
    assert model.objects.count() == 0
コード例 #4
0
ファイル: test_common.py プロジェクト: reupen/data-hub-api
def test_run(cleanup_mapping, track_return_values, setup_es):
    """
    Test that:
        - a record without any objects referencing it but not old enough
            doesn't get deleted
        - a record without any objects referencing it and old gets deleted
        - a record with another object referencing it doesn't get deleted
    """
    command, model_name, config, mapping, dep_factory, dep_field_name = cleanup_mapping
    model_factory = mapping['factory']

    delete_return_value_tracker = track_return_values(QuerySet, 'delete')

    datetime_within_threshold = FROZEN_TIME - config.age_threshold
    datetime_older_than_threshold = datetime_within_threshold - relativedelta(
        days=1)

    # this orphan should NOT get deleted because not old enough
    create_orphanable_model(model_factory, config, datetime_within_threshold)

    # this orphan should get deleted because old
    create_orphanable_model(model_factory, config,
                            datetime_older_than_threshold)

    # this object should NOT get deleted because it has another object referencing it
    non_orphan = create_orphanable_model(model_factory, config,
                                         datetime_older_than_threshold)
    is_m2m = dep_factory._meta.model._meta.get_field(
        dep_field_name).many_to_many
    dep_factory(**{dep_field_name: [non_orphan] if is_m2m else non_orphan}, )

    # 3 + 1 in case of self-references
    total_model_records = 3 + (1 if dep_factory == model_factory else 0)

    setup_es.indices.refresh()

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

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

    management.call_command(delete_orphans.Command(), model_name)
    setup_es.indices.refresh()

    # Check that the records have been deleted
    assert model.objects.count() == total_model_records - 1
    assert setup_es.count(
        read_alias, doc_type=doc_type)['count'] == total_model_records - 1

    # 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]
    assert deletions_by_model[model._meta.label] == 1
    expected_deleted_models = {model._meta.label} | set(
        mapping['implicit_related_models'])
    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 == expected_deleted_models
コード例 #5
0
def test_run(
    model_name,
    config,
    mapping,
    dep_factory,
    dep_field_name,
    track_return_values,
    opensearch_with_signals,
    opensearch_collector_context_manager,
):
    """
    Test that:
        - a record without any objects referencing it but not old enough
            doesn't get deleted
        - a record without any objects referencing it and old gets deleted
        - a record with another object referencing it doesn't get deleted
    """
    # Set up the state before running the command
    command = delete_orphans.Command()
    model_factory = mapping['factory']
    filter_config = config.filters[0]

    delete_return_value_tracker = track_return_values(QuerySet, 'delete')

    datetime_within_threshold = filter_config.cut_off_date
    datetime_older_than_threshold = filter_config.cut_off_date - relativedelta(days=1)

    with opensearch_collector_context_manager as collector:
        # this orphan should NOT get deleted because not old enough
        create_orphanable_model(model_factory, filter_config, datetime_within_threshold)

        # this orphan should get deleted because old
        create_orphanable_model(model_factory, filter_config, datetime_older_than_threshold)

        # this object should NOT get deleted because it has another object referencing it
        non_orphan = create_orphanable_model(
            model_factory,
            filter_config,
            datetime_older_than_threshold,
        )
        is_m2m = dep_factory._meta.model._meta.get_field(dep_field_name).many_to_many
        dep_factory(
            **{dep_field_name: [non_orphan] if is_m2m else non_orphan},
        )

        collector.flush_and_refresh()

    # 3 + 1 in case of self-references
    total_model_records = 3 + (1 if dep_factory == model_factory else 0)

    model = apps.get_model(model_name)
    search_app = get_search_app_by_model(model)
    read_alias = search_app.search_model.get_read_alias()

    assert model.objects.count() == total_model_records
    assert opensearch_with_signals.count(index=read_alias)['count'] == total_model_records

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

    # Check that the records have been deleted
    assert model.objects.count() == total_model_records - 1
    assert opensearch_with_signals.count(index=read_alias)['count'] == total_model_records - 1

    # 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]
    assert deletions_by_model[model._meta.label] == 1
    expected_deleted_models = {model._meta.label} | set(mapping['implicit_related_models'])
    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 == expected_deleted_models