# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import pretend

from warehouse.events.tags import EventTag
from warehouse.malware.checks.package_turnover import check as c
from warehouse.malware.models import (
    MalwareCheckState,
    VerdictClassification,
    VerdictConfidence,
)

from .....common.db.accounts import UserFactory
from .....common.db.malware import MalwareCheckFactory
from .....common.db.packaging import ProjectFactory, ReleaseFactory, RoleFactory


def test_initializes(db_session):
    check_model = MalwareCheckFactory.create(
        name="PackageTurnoverCheck", state=MalwareCheckState.Enabled
    )
    check = c.PackageTurnoverCheck(db_session)

    assert check.id == check_model.id


def test_user_posture_verdicts(db_session):
    user = UserFactory.create()
    project = pretend.stub(users=[user], id=pretend.stub())

    MalwareCheckFactory.create(
        name="PackageTurnoverCheck", state=MalwareCheckState.Enabled
    )
    check = c.PackageTurnoverCheck(db_session)

    user.record_event(
        tag=EventTag.Account.TwoFactorMethodRemoved, ip_address="0.0.0.0", additional={}
    )

    check.user_posture_verdicts(project)
    assert len(check._verdicts) == 1
    assert check._verdicts[0].check_id == check.id
    assert check._verdicts[0].project_id == project.id
    assert check._verdicts[0].classification == VerdictClassification.Threat
    assert check._verdicts[0].confidence == VerdictConfidence.High
    assert (
        check._verdicts[0].message
        == "User with control over this package has disabled 2FA"
    )


def test_user_posture_verdicts_hasnt_removed_2fa(db_session):
    user = UserFactory.create()
    project = pretend.stub(users=[user], id=pretend.stub())

    MalwareCheckFactory.create(
        name="PackageTurnoverCheck", state=MalwareCheckState.Enabled
    )
    check = c.PackageTurnoverCheck(db_session)

    check.user_posture_verdicts(project)
    assert len(check._verdicts) == 0


def test_user_posture_verdicts_has_2fa(db_session):
    user = UserFactory.create(totp_secret=b"fake secret")
    project = pretend.stub(users=[user], id=pretend.stub())

    MalwareCheckFactory.create(
        name="PackageTurnoverCheck", state=MalwareCheckState.Enabled
    )
    check = c.PackageTurnoverCheck(db_session)

    user.record_event(
        tag=EventTag.Account.TwoFactorMethodRemoved, ip_address="0.0.0.0", additional={}
    )

    check.user_posture_verdicts(project)
    assert len(check._verdicts) == 0


def test_user_turnover_verdicts(db_session):
    user = UserFactory.create()
    project = ProjectFactory.create()
    RoleFactory.create(user=user, project=project, role_name="Owner")

    project.record_event(
        tag=EventTag.Project.RoleAdd,
        ip_address="0.0.0.0",
        additional={"target_user": user.username},
    )

    MalwareCheckFactory.create(
        name="PackageTurnoverCheck", state=MalwareCheckState.Enabled
    )
    check = c.PackageTurnoverCheck(db_session)

    check.user_turnover_verdicts(project)
    assert len(check._verdicts) == 1
    assert check._verdicts[0].check_id == check.id
    assert check._verdicts[0].project_id == project.id
    assert check._verdicts[0].classification == VerdictClassification.Threat
    assert check._verdicts[0].confidence == VerdictConfidence.High
    assert (
        check._verdicts[0].message
        == "Suspicious user turnover; all current maintainers are new"
    )


def test_user_turnover_verdicts_no_turnover(db_session):
    user = UserFactory.create()
    project = ProjectFactory.create()
    RoleFactory.create(user=user, project=project, role_name="Owner")

    MalwareCheckFactory.create(
        name="PackageTurnoverCheck", state=MalwareCheckState.Enabled
    )
    check = c.PackageTurnoverCheck(db_session)

    check.user_turnover_verdicts(project)
    assert len(check._verdicts) == 0


def test_scan(db_session, monkeypatch):
    user = UserFactory.create()
    project = ProjectFactory.create()
    RoleFactory.create(user=user, project=project, role_name="Owner")

    for _ in range(3):
        ReleaseFactory.create(project=project)

    MalwareCheckFactory.create(
        name="PackageTurnoverCheck", state=MalwareCheckState.Enabled
    )
    check = c.PackageTurnoverCheck(db_session)

    monkeypatch.setattr(
        check, "user_posture_verdicts", pretend.call_recorder(lambda project: None)
    )
    monkeypatch.setattr(
        check, "user_turnover_verdicts", pretend.call_recorder(lambda project: None)
    )

    check.scan()

    # Each verdict rendering method is only called once per project,
    # thanks to deduplication.
    assert check.user_posture_verdicts.calls == [pretend.call(project)]
    assert check.user_turnover_verdicts.calls == [pretend.call(project)]


def test_scan_too_few_releases(db_session, monkeypatch):
    user = UserFactory.create()
    project = ProjectFactory.create()
    RoleFactory.create(user=user, project=project, role_name="Owner")
    ReleaseFactory.create(project=project)

    MalwareCheckFactory.create(
        name="PackageTurnoverCheck", state=MalwareCheckState.Enabled
    )
    check = c.PackageTurnoverCheck(db_session)

    monkeypatch.setattr(
        check, "user_posture_verdicts", pretend.call_recorder(lambda project: None)
    )
    monkeypatch.setattr(
        check, "user_turnover_verdicts", pretend.call_recorder(lambda project: None)
    )

    check.scan()
    assert check.user_posture_verdicts.calls == []
    assert check.user_turnover_verdicts.calls == []

a743e0e1357b66a0cd980c149a4b8555013c3075
<mask token>


def test_initializes(db_session):
    check_model = MalwareCheckFactory.create(name='PackageTurnoverCheck',
        state=MalwareCheckState.Enabled)
    check = c.PackageTurnoverCheck(db_session)
    assert check.id == check_model.id


<mask token>


def test_user_posture_verdicts_has_2fa(db_session):
    user = UserFactory.create(totp_secret=b'fake secret')
    project = pretend.stub(users=[user], id=pretend.stub())
    MalwareCheckFactory.create(name='PackageTurnoverCheck', state=
        MalwareCheckState.Enabled)
    check = c.PackageTurnoverCheck(db_session)
    user.record_event(tag=EventTag.Account.TwoFactorMethodRemoved,
        ip_address='0.0.0.0', additional={})
    check.user_posture_verdicts(project)
    assert len(check._verdicts) == 0


<mask token>


def test_user_turnover_verdicts_no_turnover(db_session):
    user = UserFactory.create()
    project = ProjectFactory.create()
    RoleFactory.create(user=user, project=project, role_name='Owner')
    MalwareCheckFactory.create(name='PackageTurnoverCheck', state=
        MalwareCheckState.Enabled)
    check = c.PackageTurnoverCheck(db_session)
    check.user_turnover_verdicts(project)
    assert len(check._verdicts) == 0


def test_scan(db_session, monkeypatch):
    user = UserFactory.create()
    project = ProjectFactory.create()
    RoleFactory.create(user=user, project=project, role_name='Owner')
    for _ in range(3):
        ReleaseFactory.create(project=project)
    MalwareCheckFactory.create(name='PackageTurnoverCheck', state=
        MalwareCheckState.Enabled)
    check = c.PackageTurnoverCheck(db_session)
    monkeypatch.setattr(check, 'user_posture_verdicts', pretend.
        call_recorder(lambda project: None))
    monkeypatch.setattr(check, 'user_turnover_verdicts', pretend.
        call_recorder(lambda project: None))
    check.scan()
    assert check.user_posture_verdicts.calls == [pretend.call(project)]
    assert check.user_turnover_verdicts.calls == [pretend.call(project)]


<mask token>

<mask token>


def test_initializes(db_session):
    check_model = MalwareCheckFactory.create(name='PackageTurnoverCheck',
        state=MalwareCheckState.Enabled)
    check = c.PackageTurnoverCheck(db_session)
    assert check.id == check_model.id


<mask token>


def test_user_posture_verdicts_has_2fa(db_session):
    user = UserFactory.create(totp_secret=b'fake secret')
    project = pretend.stub(users=[user], id=pretend.stub())
    MalwareCheckFactory.create(name='PackageTurnoverCheck', state=
        MalwareCheckState.Enabled)
    check = c.PackageTurnoverCheck(db_session)
    user.record_event(tag=EventTag.Account.TwoFactorMethodRemoved,
        ip_address='0.0.0.0', additional={})
    check.user_posture_verdicts(project)
    assert len(check._verdicts) == 0


def test_user_turnover_verdicts(db_session):
    user = UserFactory.create()
    project = ProjectFactory.create()
    RoleFactory.create(user=user, project=project, role_name='Owner')
    project.record_event(tag=EventTag.Project.RoleAdd, ip_address='0.0.0.0',
        additional={'target_user': user.username})
    MalwareCheckFactory.create(name='PackageTurnoverCheck', state=
        MalwareCheckState.Enabled)
    check = c.PackageTurnoverCheck(db_session)
    check.user_turnover_verdicts(project)
    assert len(check._verdicts) == 1
    assert check._verdicts[0].check_id == check.id
    assert check._verdicts[0].project_id == project.id
    assert check._verdicts[0].classification == VerdictClassification.Threat
    assert check._verdicts[0].confidence == VerdictConfidence.High
    assert check._verdicts[0
        ].message == 'Suspicious user turnover; all current maintainers are new'


def test_user_turnover_verdicts_no_turnover(db_session):
    user = UserFactory.create()
    project = ProjectFactory.create()
    RoleFactory.create(user=user, project=project, role_name='Owner')
    MalwareCheckFactory.create(name='PackageTurnoverCheck', state=
        MalwareCheckState.Enabled)
    check = c.PackageTurnoverCheck(db_session)
    check.user_turnover_verdicts(project)
    assert len(check._verdicts) == 0


def test_scan(db_session, monkeypatch):
    user = UserFactory.create()
    project = ProjectFactory.create()
    RoleFactory.create(user=user, project=project, role_name='Owner')
    for _ in range(3):
        ReleaseFactory.create(project=project)
    MalwareCheckFactory.create(name='PackageTurnoverCheck', state=
        MalwareCheckState.Enabled)
    check = c.PackageTurnoverCheck(db_session)
    monkeypatch.setattr(check, 'user_posture_verdicts', pretend.
        call_recorder(lambda project: None))
    monkeypatch.setattr(check, 'user_turnover_verdicts', pretend.
        call_recorder(lambda project: None))
    check.scan()
    assert check.user_posture_verdicts.calls == [pretend.call(project)]
    assert check.user_turnover_verdicts.calls == [pretend.call(project)]


def test_scan_too_few_releases(db_session, monkeypatch):
    user = UserFactory.create()
    project = ProjectFactory.create()
    RoleFactory.create(user=user, project=project, role_name='Owner')
    ReleaseFactory.create(project=project)
    MalwareCheckFactory.create(name='PackageTurnoverCheck', state=
        MalwareCheckState.Enabled)
    check = c.PackageTurnoverCheck(db_session)
    monkeypatch.setattr(check, 'user_posture_verdicts', pretend.
        call_recorder(lambda project: None))
    monkeypatch.setattr(check, 'user_turnover_verdicts', pretend.
        call_recorder(lambda project: None))
    check.scan()
    assert check.user_posture_verdicts.calls == []
    assert check.user_turnover_verdicts.calls == []

<mask token>


def test_initializes(db_session):
    check_model = MalwareCheckFactory.create(name='PackageTurnoverCheck',
        state=MalwareCheckState.Enabled)
    check = c.PackageTurnoverCheck(db_session)
    assert check.id == check_model.id


def test_user_posture_verdicts(db_session):
    user = UserFactory.create()
    project = pretend.stub(users=[user], id=pretend.stub())
    MalwareCheckFactory.create(name='PackageTurnoverCheck', state=
        MalwareCheckState.Enabled)
    check = c.PackageTurnoverCheck(db_session)
    user.record_event(tag=EventTag.Account.TwoFactorMethodRemoved,
        ip_address='0.0.0.0', additional={})
    check.user_posture_verdicts(project)
    assert len(check._verdicts) == 1
    assert check._verdicts[0].check_id == check.id
    assert check._verdicts[0].project_id == project.id
    assert check._verdicts[0].classification == VerdictClassification.Threat
    assert check._verdicts[0].confidence == VerdictConfidence.High
    assert check._verdicts[0
        ].message == 'User with control over this package has disabled 2FA'


def test_user_posture_verdicts_hasnt_removed_2fa(db_session):
    user = UserFactory.create()
    project = pretend.stub(users=[user], id=pretend.stub())
    MalwareCheckFactory.create(name='PackageTurnoverCheck', state=
        MalwareCheckState.Enabled)
    check = c.PackageTurnoverCheck(db_session)
    check.user_posture_verdicts(project)
    assert len(check._verdicts) == 0


def test_user_posture_verdicts_has_2fa(db_session):
    user = UserFactory.create(totp_secret=b'fake secret')
    project = pretend.stub(users=[user], id=pretend.stub())
    MalwareCheckFactory.create(name='PackageTurnoverCheck', state=
        MalwareCheckState.Enabled)
    check = c.PackageTurnoverCheck(db_session)
    user.record_event(tag=EventTag.Account.TwoFactorMethodRemoved,
        ip_address='0.0.0.0', additional={})
    check.user_posture_verdicts(project)
    assert len(check._verdicts) == 0


def test_user_turnover_verdicts(db_session):
    user = UserFactory.create()
    project = ProjectFactory.create()
    RoleFactory.create(user=user, project=project, role_name='Owner')
    project.record_event(tag=EventTag.Project.RoleAdd, ip_address='0.0.0.0',
        additional={'target_user': user.username})
    MalwareCheckFactory.create(name='PackageTurnoverCheck', state=
        MalwareCheckState.Enabled)
    check = c.PackageTurnoverCheck(db_session)
    check.user_turnover_verdicts(project)
    assert len(check._verdicts) == 1
    assert check._verdicts[0].check_id == check.id
    assert check._verdicts[0].project_id == project.id
    assert check._verdicts[0].classification == VerdictClassification.Threat
    assert check._verdicts[0].confidence == VerdictConfidence.High
    assert check._verdicts[0
        ].message == 'Suspicious user turnover; all current maintainers are new'


def test_user_turnover_verdicts_no_turnover(db_session):
    user = UserFactory.create()
    project = ProjectFactory.create()
    RoleFactory.create(user=user, project=project, role_name='Owner')
    MalwareCheckFactory.create(name='PackageTurnoverCheck', state=
        MalwareCheckState.Enabled)
    check = c.PackageTurnoverCheck(db_session)
    check.user_turnover_verdicts(project)
    assert len(check._verdicts) == 0


def test_scan(db_session, monkeypatch):
    user = UserFactory.create()
    project = ProjectFactory.create()
    RoleFactory.create(user=user, project=project, role_name='Owner')
    for _ in range(3):
        ReleaseFactory.create(project=project)
    MalwareCheckFactory.create(name='PackageTurnoverCheck', state=
        MalwareCheckState.Enabled)
    check = c.PackageTurnoverCheck(db_session)
    monkeypatch.setattr(check, 'user_posture_verdicts', pretend.
        call_recorder(lambda project: None))
    monkeypatch.setattr(check, 'user_turnover_verdicts', pretend.
        call_recorder(lambda project: None))
    check.scan()
    assert check.user_posture_verdicts.calls == [pretend.call(project)]
    assert check.user_turnover_verdicts.calls == [pretend.call(project)]


def test_scan_too_few_releases(db_session, monkeypatch):
    user = UserFactory.create()
    project = ProjectFactory.create()
    RoleFactory.create(user=user, project=project, role_name='Owner')
    ReleaseFactory.create(project=project)
    MalwareCheckFactory.create(name='PackageTurnoverCheck', state=
        MalwareCheckState.Enabled)
    check = c.PackageTurnoverCheck(db_session)
    monkeypatch.setattr(check, 'user_posture_verdicts', pretend.
        call_recorder(lambda project: None))
    monkeypatch.setattr(check, 'user_turnover_verdicts', pretend.
        call_recorder(lambda project: None))
    check.scan()
    assert check.user_posture_verdicts.calls == []
    assert check.user_turnover_verdicts.calls == []

import pretend
from warehouse.events.tags import EventTag
from warehouse.malware.checks.package_turnover import check as c
from warehouse.malware.models import MalwareCheckState, VerdictClassification, VerdictConfidence
from .....common.db.accounts import UserFactory
from .....common.db.malware import MalwareCheckFactory
from .....common.db.packaging import ProjectFactory, ReleaseFactory, RoleFactory


def test_initializes(db_session):
    check_model = MalwareCheckFactory.create(name='PackageTurnoverCheck',
        state=MalwareCheckState.Enabled)
    check = c.PackageTurnoverCheck(db_session)
    assert check.id == check_model.id


def test_user_posture_verdicts(db_session):
    user = UserFactory.create()
    project = pretend.stub(users=[user], id=pretend.stub())
    MalwareCheckFactory.create(name='PackageTurnoverCheck', state=
        MalwareCheckState.Enabled)
    check = c.PackageTurnoverCheck(db_session)
    user.record_event(tag=EventTag.Account.TwoFactorMethodRemoved,
        ip_address='0.0.0.0', additional={})
    check.user_posture_verdicts(project)
    assert len(check._verdicts) == 1
    assert check._verdicts[0].check_id == check.id
    assert check._verdicts[0].project_id == project.id
    assert check._verdicts[0].classification == VerdictClassification.Threat
    assert check._verdicts[0].confidence == VerdictConfidence.High
    assert check._verdicts[0
        ].message == 'User with control over this package has disabled 2FA'


def test_user_posture_verdicts_hasnt_removed_2fa(db_session):
    user = UserFactory.create()
    project = pretend.stub(users=[user], id=pretend.stub())
    MalwareCheckFactory.create(name='PackageTurnoverCheck', state=
        MalwareCheckState.Enabled)
    check = c.PackageTurnoverCheck(db_session)
    check.user_posture_verdicts(project)
    assert len(check._verdicts) == 0


def test_user_posture_verdicts_has_2fa(db_session):
    user = UserFactory.create(totp_secret=b'fake secret')
    project = pretend.stub(users=[user], id=pretend.stub())
    MalwareCheckFactory.create(name='PackageTurnoverCheck', state=
        MalwareCheckState.Enabled)
    check = c.PackageTurnoverCheck(db_session)
    user.record_event(tag=EventTag.Account.TwoFactorMethodRemoved,
        ip_address='0.0.0.0', additional={})
    check.user_posture_verdicts(project)
    assert len(check._verdicts) == 0


def test_user_turnover_verdicts(db_session):
    user = UserFactory.create()
    project = ProjectFactory.create()
    RoleFactory.create(user=user, project=project, role_name='Owner')
    project.record_event(tag=EventTag.Project.RoleAdd, ip_address='0.0.0.0',
        additional={'target_user': user.username})
    MalwareCheckFactory.create(name='PackageTurnoverCheck', state=
        MalwareCheckState.Enabled)
    check = c.PackageTurnoverCheck(db_session)
    check.user_turnover_verdicts(project)
    assert len(check._verdicts) == 1
    assert check._verdicts[0].check_id == check.id
    assert check._verdicts[0].project_id == project.id
    assert check._verdicts[0].classification == VerdictClassification.Threat
    assert check._verdicts[0].confidence == VerdictConfidence.High
    assert check._verdicts[0
        ].message == 'Suspicious user turnover; all current maintainers are new'


def test_user_turnover_verdicts_no_turnover(db_session):
    user = UserFactory.create()
    project = ProjectFactory.create()
    RoleFactory.create(user=user, project=project, role_name='Owner')
    MalwareCheckFactory.create(name='PackageTurnoverCheck', state=
        MalwareCheckState.Enabled)
    check = c.PackageTurnoverCheck(db_session)
    check.user_turnover_verdicts(project)
    assert len(check._verdicts) == 0


def test_scan(db_session, monkeypatch):
    user = UserFactory.create()
    project = ProjectFactory.create()
    RoleFactory.create(user=user, project=project, role_name='Owner')
    for _ in range(3):
        ReleaseFactory.create(project=project)
    MalwareCheckFactory.create(name='PackageTurnoverCheck', state=
        MalwareCheckState.Enabled)
    check = c.PackageTurnoverCheck(db_session)
    monkeypatch.setattr(check, 'user_posture_verdicts', pretend.
        call_recorder(lambda project: None))
    monkeypatch.setattr(check, 'user_turnover_verdicts', pretend.
        call_recorder(lambda project: None))
    check.scan()
    assert check.user_posture_verdicts.calls == [pretend.call(project)]
    assert check.user_turnover_verdicts.calls == [pretend.call(project)]


def test_scan_too_few_releases(db_session, monkeypatch):
    user = UserFactory.create()
    project = ProjectFactory.create()
    RoleFactory.create(user=user, project=project, role_name='Owner')
    ReleaseFactory.create(project=project)
    MalwareCheckFactory.create(name='PackageTurnoverCheck', state=
        MalwareCheckState.Enabled)
    check = c.PackageTurnoverCheck(db_session)
    monkeypatch.setattr(check, 'user_posture_verdicts', pretend.
        call_recorder(lambda project: None))
    monkeypatch.setattr(check, 'user_turnover_verdicts', pretend.
        call_recorder(lambda project: None))
    check.scan()
    assert check.user_posture_verdicts.calls == []
    assert check.user_turnover_verdicts.calls == []

# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import pretend

from warehouse.events.tags import EventTag
from warehouse.malware.checks.package_turnover import check as c
from warehouse.malware.models import (
    MalwareCheckState,
    VerdictClassification,
    VerdictConfidence,
)

from .....common.db.accounts import UserFactory
from .....common.db.malware import MalwareCheckFactory
from .....common.db.packaging import ProjectFactory, ReleaseFactory, RoleFactory


def test_initializes(db_session):
    check_model = MalwareCheckFactory.create(
        name="PackageTurnoverCheck", state=MalwareCheckState.Enabled
    )
    check = c.PackageTurnoverCheck(db_session)

    assert check.id == check_model.id


def test_user_posture_verdicts(db_session):
    user = UserFactory.create()
    project = pretend.stub(users=[user], id=pretend.stub())

    MalwareCheckFactory.create(
        name="PackageTurnoverCheck", state=MalwareCheckState.Enabled
    )
    check = c.PackageTurnoverCheck(db_session)

    user.record_event(
        tag=EventTag.Account.TwoFactorMethodRemoved, ip_address="0.0.0.0", additional={}
    )

    check.user_posture_verdicts(project)
    assert len(check._verdicts) == 1
    assert check._verdicts[0].check_id == check.id
    assert check._verdicts[0].project_id == project.id
    assert check._verdicts[0].classification == VerdictClassification.Threat
    assert check._verdicts[0].confidence == VerdictConfidence.High
    assert (
        check._verdicts[0].message
        == "User with control over this package has disabled 2FA"
    )


def test_user_posture_verdicts_hasnt_removed_2fa(db_session):
    user = UserFactory.create()
    project = pretend.stub(users=[user], id=pretend.stub())

    MalwareCheckFactory.create(
        name="PackageTurnoverCheck", state=MalwareCheckState.Enabled
    )
    check = c.PackageTurnoverCheck(db_session)

    check.user_posture_verdicts(project)
    assert len(check._verdicts) == 0


def test_user_posture_verdicts_has_2fa(db_session):
    user = UserFactory.create(totp_secret=b"fake secret")
    project = pretend.stub(users=[user], id=pretend.stub())

    MalwareCheckFactory.create(
        name="PackageTurnoverCheck", state=MalwareCheckState.Enabled
    )
    check = c.PackageTurnoverCheck(db_session)

    user.record_event(
        tag=EventTag.Account.TwoFactorMethodRemoved, ip_address="0.0.0.0", additional={}
    )

    check.user_posture_verdicts(project)
    assert len(check._verdicts) == 0


def test_user_turnover_verdicts(db_session):
    user = UserFactory.create()
    project = ProjectFactory.create()
    RoleFactory.create(user=user, project=project, role_name="Owner")

    project.record_event(
        tag=EventTag.Project.RoleAdd,
        ip_address="0.0.0.0",
        additional={"target_user": user.username},
    )

    MalwareCheckFactory.create(
        name="PackageTurnoverCheck", state=MalwareCheckState.Enabled
    )
    check = c.PackageTurnoverCheck(db_session)

    check.user_turnover_verdicts(project)
    assert len(check._verdicts) == 1
    assert check._verdicts[0].check_id == check.id
    assert check._verdicts[0].project_id == project.id
    assert check._verdicts[0].classification == VerdictClassification.Threat
    assert check._verdicts[0].confidence == VerdictConfidence.High
    assert (
        check._verdicts[0].message
        == "Suspicious user turnover; all current maintainers are new"
    )


def test_user_turnover_verdicts_no_turnover(db_session):
    user = UserFactory.create()
    project = ProjectFactory.create()
    RoleFactory.create(user=user, project=project, role_name="Owner")

    MalwareCheckFactory.create(
        name="PackageTurnoverCheck", state=MalwareCheckState.Enabled
    )
    check = c.PackageTurnoverCheck(db_session)

    check.user_turnover_verdicts(project)
    assert len(check._verdicts) == 0


def test_scan(db_session, monkeypatch):
    user = UserFactory.create()
    project = ProjectFactory.create()
    RoleFactory.create(user=user, project=project, role_name="Owner")

    for _ in range(3):
        ReleaseFactory.create(project=project)

    MalwareCheckFactory.create(
        name="PackageTurnoverCheck", state=MalwareCheckState.Enabled
    )
    check = c.PackageTurnoverCheck(db_session)

    monkeypatch.setattr(
        check, "user_posture_verdicts", pretend.call_recorder(lambda project: None)
    )
    monkeypatch.setattr(
        check, "user_turnover_verdicts", pretend.call_recorder(lambda project: None)
    )

    check.scan()

    # Each verdict rendering method is only called once per project,
    # thanks to deduplication.
    assert check.user_posture_verdicts.calls == [pretend.call(project)]
    assert check.user_turnover_verdicts.calls == [pretend.call(project)]


def test_scan_too_few_releases(db_session, monkeypatch):
    user = UserFactory.create()
    project = ProjectFactory.create()
    RoleFactory.create(user=user, project=project, role_name="Owner")
    ReleaseFactory.create(project=project)

    MalwareCheckFactory.create(
        name="PackageTurnoverCheck", state=MalwareCheckState.Enabled
    )
    check = c.PackageTurnoverCheck(db_session)

    monkeypatch.setattr(
        check, "user_posture_verdicts", pretend.call_recorder(lambda project: None)
    )
    monkeypatch.setattr(
        check, "user_turnover_verdicts", pretend.call_recorder(lambda project: None)
    )

    check.scan()
    assert check.user_posture_verdicts.calls == []
    assert check.user_turnover_verdicts.calls == []
