<filename>server/tests/controllers/features/github/test_check_run_filter.py
from datetime import datetime, timedelta, timezone
from typing import List, Optional

import pandas as pd
import pytest

from athenian.api.controllers.features.github.check_run_filter import filter_check_runs
from athenian.api.controllers.miners.filters import JIRAFilter, LabelFilter
from athenian.api.controllers.miners.types import CodeCheckRunListItem, CodeCheckRunListStats
from athenian.api.defer import wait_deferred, with_defer


def td_list(items: List[Optional[int]]) -> List[timedelta]:
    return [(x if x is None else timedelta(seconds=x)) for x in items]


async def test_filter_check_runs_monthly_quantiles(mdb, logical_settings):
    timeline, items = await filter_check_runs(
        datetime(2015, 1, 1, tzinfo=timezone.utc),
        datetime(2020, 1, 1, tzinfo=timezone.utc),
        ["src-d/go-git"], [],
        LabelFilter.empty(), JIRAFilter.empty(), [0, 0.95],
        logical_settings, (6366825,), mdb, None)
    assert len(timeline) == len(set(timeline)) == 61
    assert len(items) == 9
    assert items[0] == CodeCheckRunListItem(
        title="DCO", repository="src-d/go-git",
        last_execution_time=pd.Timestamp("2019-12-30T09:41:10+00").to_pydatetime(),
        last_execution_url="https://github.com/src-d/go-git/runs/367607194",
        size_groups=[1, 3, 4, 5, 6],
        total_stats=CodeCheckRunListStats(
            count=383, successes=361, skips=0, critical=False, flaky_count=0,
            mean_execution_time=timedelta(seconds=0),
            stddev_execution_time=timedelta(seconds=1),
            median_execution_time=timedelta(seconds=1),
            count_timeline=[
                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 18, 17, 26, 49, 38, 42, 11, 5, 5, 15, 11,
                59, 17, 9, 18, 12, 0, 3, 6, 4],
            successes_timeline=[
                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 17, 16, 24, 48, 37, 34, 10, 5, 5, 15, 11,
                57, 17, 9, 17, 10, 0, 3, 5, 4],
            mean_execution_time_timeline=td_list([
                None, None, None, None, None, None, None, None, None, None,
                None, None, None, None, None, None, None, None, None, None, None,
                None, None, None, None, None, None, None, None, None, None, None,
                None, None, None, None, None, None, None, None, None, None, None,
                None, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, None, 1, 1, 1]),
            median_execution_time_timeline=td_list([
                None, None, None, None, None, None, None, None, None, None,
                None, None, None, None, None, None, None, None, None, None,
                None, None, None, None, None, None, None, None, None, None,
                None, None, None, None, None, None, None, None, None, None,
                None, None, None, None, 0., 0., 0., 0., 0., 1., 1., 1., 1., 2., 1., 1.,
                None, 2., 1., 2.]),
        ),
        prs_stats=CodeCheckRunListStats(
            count=319, successes=301, skips=0, critical=False, flaky_count=0,
            mean_execution_time=timedelta(seconds=0),
            stddev_execution_time=timedelta(seconds=1),
            median_execution_time=timedelta(seconds=1),
            count_timeline=[
                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 18, 13, 15, 39, 26, 37, 10, 5, 5, 14, 11,
                50, 15, 9, 17, 12, 0, 3, 6, 4],
            successes_timeline=[
                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 17, 12, 15, 38, 25, 30, 9, 5, 5, 14, 11,
                48, 15, 9, 17, 10, 0, 3, 5, 4],
            mean_execution_time_timeline=td_list([
                None, None, None, None, None, None, None, None, None, None,
                None, None, None, None, None, None, None, None, None, None, None,
                None, None, None, None, None, None, None, None, None, None, None,
                None, None, None, None, None, None, None, None, None, None, None,
                None, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, None, 1, 1, 1]),
            median_execution_time_timeline=td_list([
                None, None, None, None, None, None, None, None, None, None,
                None, None, None, None, None, None, None, None, None, None,
                None, None, None, None, None, None, None, None, None, None,
                None, None, None, None, None, None, None, None, None, None,
                None, None, None, None, 0., 0., 0., 0., 0., 1., 1., 1., 1., 2., 1., 1.,
                None, 2., 1., 2.]),
        ),
    )


async def test_filter_check_runs_daily(mdb, logical_settings):
    timeline, items = await filter_check_runs(
        datetime(2018, 2, 1, tzinfo=timezone.utc), datetime(2018, 2, 12, tzinfo=timezone.utc),
        ["src-d/go-git"], [],
        LabelFilter.empty(), JIRAFilter.empty(), [0, 1],
        logical_settings, (6366825,), mdb, None)
    assert len(timeline) == len(set(timeline)) == 12
    assert len(items) == 7


async def test_filter_check_runs_empty(mdb, logical_settings):
    timeline, items = await filter_check_runs(
        datetime(2018, 2, 1, tzinfo=timezone.utc), datetime(2018, 2, 12, tzinfo=timezone.utc),
        ["src-d/go-git"], ["xxx"],
        LabelFilter.empty(), JIRAFilter.empty(), [0, 1],
        logical_settings, (6366825,), mdb, None)
    assert len(timeline) == len(set(timeline)) == 12
    assert len(items) == 0


@with_defer
async def test_filter_check_runs_cache(mdb, cache, logical_settings):
    timeline1, items1 = await filter_check_runs(
        datetime(2015, 1, 1, tzinfo=timezone.utc), datetime(2020, 1, 1, tzinfo=timezone.utc),
        ["src-d/go-git"], [],
        LabelFilter.empty(), JIRAFilter.empty(), [0, 0.95],
        logical_settings, (6366825,), mdb, cache)
    await wait_deferred()
    timeline2, items2 = await filter_check_runs(
        datetime(2015, 1, 1, tzinfo=timezone.utc), datetime(2020, 1, 1, tzinfo=timezone.utc),
        ["src-d/go-git"], [],
        LabelFilter.empty(), JIRAFilter.empty(), [0, 0.95],
        logical_settings, (6366825,), None, cache)
    assert timeline1 == timeline2
    assert items1 == items2
    timeline2, items2 = await filter_check_runs(
        datetime(2015, 1, 1, tzinfo=timezone.utc), datetime(2020, 1, 1, tzinfo=timezone.utc),
        ["src-d/go-git"], [],
        LabelFilter.empty(), JIRAFilter.empty(), [0, 0.05],
        logical_settings, (6366825,), None, cache)
    assert items1 != items2
    with pytest.raises(Exception):
        await filter_check_runs(
            datetime(2015, 1, 1, tzinfo=timezone.utc), datetime(2020, 1, 2, tzinfo=timezone.utc),
            ["src-d/go-git"], [],
            LabelFilter.empty(), JIRAFilter.empty(), [0, 0.95],
            logical_settings, (6366825,), None, cache)


async def test_filter_check_runs_logical_repos(mdb, logical_settings):
    timeline, items = await filter_check_runs(
        datetime(2016, 2, 1, tzinfo=timezone.utc), datetime(2018, 2, 12, tzinfo=timezone.utc),
        ["src-d/go-git/alpha"], [],
        LabelFilter.empty(), JIRAFilter.empty(), [0, 1],
        logical_settings, (6366825,), mdb, None)
    assert len(timeline) == len(set(timeline)) == 26
    assert len(items) == 8

<filename>server/tests/controllers/features/github/test_check_run_filter.py
from datetime import datetime, timedelta, timezone
from typing import List, Optional

import pandas as pd
import pytest

from athenian.api.controllers.features.github.check_run_filter import filter_check_runs
from athenian.api.controllers.miners.filters import JIRAFilter, LabelFilter
from athenian.api.controllers.miners.types import CodeCheckRunListItem, CodeCheckRunListStats
from athenian.api.defer import wait_deferred, with_defer


def td_list(items: List[Optional[int]]) -> List[timedelta]:
    return [(x if x is None else timedelta(seconds=x)) for x in items]


async def test_filter_check_runs_monthly_quantiles(mdb, logical_settings):
    timeline, items = await filter_check_runs(
        datetime(2015, 1, 1, tzinfo=timezone.utc),
        datetime(2020, 1, 1, tzinfo=timezone.utc),
        ["src-d/go-git"], [],
        LabelFilter.empty(), JIRAFilter.empty(), [0, 0.95],
        logical_settings, (6366825,), mdb, None)
    assert len(timeline) == len(set(timeline)) == 61
    assert len(items) == 9
    assert items[0] == CodeCheckRunListItem(
        title="DCO", repository="src-d/go-git",
        last_execution_time=pd.Timestamp("2019-12-30T09:41:10+00").to_pydatetime(),
        last_execution_url="https://github.com/src-d/go-git/runs/367607194",
        size_groups=[1, 3, 4, 5, 6],
        total_stats=CodeCheckRunListStats(
            count=383, successes=361, skips=0, critical=False, flaky_count=0,
            mean_execution_time=timedelta(seconds=0),
            stddev_execution_time=timedelta(seconds=1),
            median_execution_time=timedelta(seconds=1),
            count_timeline=[
                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 18, 17, 26, 49, 38, 42, 11, 5, 5, 15, 11,
                59, 17, 9, 18, 12, 0, 3, 6, 4],
            successes_timeline=[
                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 17, 16, 24, 48, 37, 34, 10, 5, 5, 15, 11,
                57, 17, 9, 17, 10, 0, 3, 5, 4],
            mean_execution_time_timeline=td_list([
                None, None, None, None, None, None, None, None, None, None,
                None, None, None, None, None, None, None, None, None, None, None,
                None, None, None, None, None, None, None, None, None, None, None,
                None, None, None, None, None, None, None, None, None, None, None,
                None, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, None, 1, 1, 1]),
            median_execution_time_timeline=td_list([
                None, None, None, None, None, None, None, None, None, None,
                None, None, None, None, None, None, None, None, None, None,
                None, None, None, None, None, None, None, None, None, None,
                None, None, None, None, None, None, None, None, None, None,
                None, None, None, None, 0., 0., 0., 0., 0., 1., 1., 1., 1., 2., 1., 1.,
                None, 2., 1., 2.]),
        ),
        prs_stats=CodeCheckRunListStats(
            count=319, successes=301, skips=0, critical=False, flaky_count=0,
            mean_execution_time=timedelta(seconds=0),
            stddev_execution_time=timedelta(seconds=1),
            median_execution_time=timedelta(seconds=1),
            count_timeline=[
                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 18, 13, 15, 39, 26, 37, 10, 5, 5, 14, 11,
                50, 15, 9, 17, 12, 0, 3, 6, 4],
            successes_timeline=[
                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 17, 12, 15, 38, 25, 30, 9, 5, 5, 14, 11,
                48, 15, 9, 17, 10, 0, 3, 5, 4],
            mean_execution_time_timeline=td_list([
                None, None, None, None, None, None, None, None, None, None,
                None, None, None, None, None, None, None, None, None, None, None,
                None, None, None, None, None, None, None, None, None, None, None,
                None, None, None, None, None, None, None, None, None, None, None,
                None, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, None, 1, 1, 1]),
            median_execution_time_timeline=td_list([
                None, None, None, None, None, None, None, None, None, None,
                None, None, None, None, None, None, None, None, None, None,
                None, None, None, None, None, None, None, None, None, None,
                None, None, None, None, None, None, None, None, None, None,
                None, None, None, None, 0., 0., 0., 0., 0., 1., 1., 1., 1., 2., 1., 1.,
                None, 2., 1., 2.]),
        ),
    )


async def test_filter_check_runs_daily(mdb, logical_settings):
    timeline, items = await filter_check_runs(
        datetime(2018, 2, 1, tzinfo=timezone.utc), datetime(2018, 2, 12, tzinfo=timezone.utc),
        ["src-d/go-git"], [],
        LabelFilter.empty(), JIRAFilter.empty(), [0, 1],
        logical_settings, (6366825,), mdb, None)
    assert len(timeline) == len(set(timeline)) == 12
    assert len(items) == 7


async def test_filter_check_runs_empty(mdb, logical_settings):
    timeline, items = await filter_check_runs(
        datetime(2018, 2, 1, tzinfo=timezone.utc), datetime(2018, 2, 12, tzinfo=timezone.utc),
        ["src-d/go-git"], ["xxx"],
        LabelFilter.empty(), JIRAFilter.empty(), [0, 1],
        logical_settings, (6366825,), mdb, None)
    assert len(timeline) == len(set(timeline)) == 12
    assert len(items) == 0


@with_defer
async def test_filter_check_runs_cache(mdb, cache, logical_settings):
    timeline1, items1 = await filter_check_runs(
        datetime(2015, 1, 1, tzinfo=timezone.utc), datetime(2020, 1, 1, tzinfo=timezone.utc),
        ["src-d/go-git"], [],
        LabelFilter.empty(), JIRAFilter.empty(), [0, 0.95],
        logical_settings, (6366825,), mdb, cache)
    await wait_deferred()
    timeline2, items2 = await filter_check_runs(
        datetime(2015, 1, 1, tzinfo=timezone.utc), datetime(2020, 1, 1, tzinfo=timezone.utc),
        ["src-d/go-git"], [],
        LabelFilter.empty(), JIRAFilter.empty(), [0, 0.95],
        logical_settings, (6366825,), None, cache)
    assert timeline1 == timeline2
    assert items1 == items2
    timeline2, items2 = await filter_check_runs(
        datetime(2015, 1, 1, tzinfo=timezone.utc), datetime(2020, 1, 1, tzinfo=timezone.utc),
        ["src-d/go-git"], [],
        LabelFilter.empty(), JIRAFilter.empty(), [0, 0.05],
        logical_settings, (6366825,), None, cache)
    assert items1 != items2
    with pytest.raises(Exception):
        await filter_check_runs(
            datetime(2015, 1, 1, tzinfo=timezone.utc), datetime(2020, 1, 2, tzinfo=timezone.utc),
            ["src-d/go-git"], [],
            LabelFilter.empty(), JIRAFilter.empty(), [0, 0.95],
            logical_settings, (6366825,), None, cache)


async def test_filter_check_runs_logical_repos(mdb, logical_settings):
    timeline, items = await filter_check_runs(
        datetime(2016, 2, 1, tzinfo=timezone.utc), datetime(2018, 2, 12, tzinfo=timezone.utc),
        ["src-d/go-git/alpha"], [],
        LabelFilter.empty(), JIRAFilter.empty(), [0, 1],
        logical_settings, (6366825,), mdb, None)
    assert len(timeline) == len(set(timeline)) == 26
    assert len(items) == 8
