Coverage for src/tests/test_activeness_probes.py: 100%
96 statements
« prev ^ index » next coverage.py v7.6.10, created at 2025-03-24 14:08 +0000
« prev ^ index » next coverage.py v7.6.10, created at 2025-03-24 14:08 +0000
1from datetime import timedelta
2from unittest.mock import patch
4import grpc
5import pytest
6from google.protobuf import empty_pb2
8from couchers import errors
9from couchers.config import config
10from couchers.db import session_scope
11from couchers.jobs.enqueue import queue_job
12from couchers.models import ActivenessProbe, ActivenessProbeStatus, HostingStatus, MeetupStatus
13from couchers.sql import couchers_select as select
14from couchers.utils import now
15from proto import api_pb2, jail_pb2
16from tests.test_fixtures import ( # noqa # noqa
17 api_session,
18 db,
19 email_fields,
20 generate_user,
21 process_jobs,
22 push_collector,
23 real_jail_session,
24 testconfig,
25)
28@pytest.fixture(autouse=True)
29def _(testconfig):
30 pass
33def test_activeness_probes_happy_path_inactive(db, push_collector):
34 user, token = generate_user(
35 hosting_status=HostingStatus.can_host,
36 meetup_status=MeetupStatus.wants_to_meetup,
37 last_active=now() - timedelta(days=335),
38 )
40 with session_scope() as session:
41 queue_job(session, "send_activeness_probes", empty_pb2.Empty())
43 process_jobs()
45 with real_jail_session(token) as jail:
46 res = jail.JailInfo(empty_pb2.Empty())
47 assert res.has_pending_activeness_probe
48 assert res.jailed
50 res = jail.RespondToActivenessProbe(
51 jail_pb2.RespondToActivenessProbeReq(response=jail_pb2.ACTIVENESS_PROBE_RESPONSE_NO_LONGER_ACTIVE)
52 )
53 assert not res.has_pending_activeness_probe
54 assert not res.jailed
56 with api_session(token) as api:
57 res = api.GetUser(api_pb2.GetUserReq(user=user.username))
58 assert res.hosting_status == api_pb2.HOSTING_STATUS_CANT_HOST
59 assert res.meetup_status == api_pb2.MEETUP_STATUS_WANTS_TO_MEETUP
61 push_collector.assert_user_has_single_matching(
62 user.id,
63 title="Are you still open to hosting on Couchers.org?",
64 body="Please log in to confirm your hosting status.",
65 )
68def test_activeness_probes_happy_path_active(db, push_collector):
69 user, token = generate_user(
70 hosting_status=HostingStatus.can_host,
71 meetup_status=MeetupStatus.wants_to_meetup,
72 last_active=now() - timedelta(days=335),
73 )
75 with session_scope() as session:
76 queue_job(session, "send_activeness_probes", empty_pb2.Empty())
78 process_jobs()
80 with real_jail_session(token) as jail:
81 res = jail.JailInfo(empty_pb2.Empty())
82 assert res.has_pending_activeness_probe
83 assert res.jailed
85 res = jail.RespondToActivenessProbe(
86 jail_pb2.RespondToActivenessProbeReq(response=jail_pb2.ACTIVENESS_PROBE_RESPONSE_STILL_ACTIVE)
87 )
88 assert not res.has_pending_activeness_probe
89 assert not res.jailed
91 with api_session(token) as api:
92 res = api.GetUser(api_pb2.GetUserReq(user=user.username))
93 assert res.hosting_status == api_pb2.HOSTING_STATUS_CAN_HOST
94 assert res.meetup_status == api_pb2.MEETUP_STATUS_WANTS_TO_MEETUP
96 push_collector.assert_user_has_single_matching(
97 user.id,
98 title="Are you still open to hosting on Couchers.org?",
99 body="Please log in to confirm your hosting status.",
100 )
103def test_activeness_probes_disabled(db, push_collector):
104 new_config = config.copy()
105 new_config["ACTIVENESS_PROBES_ENABLED"] = False
107 with patch("couchers.jobs.handlers.config", new_config):
108 user, token = generate_user(
109 hosting_status=HostingStatus.can_host,
110 meetup_status=MeetupStatus.wants_to_meetup,
111 last_active=now() - timedelta(days=335),
112 )
114 with session_scope() as session:
115 queue_job(session, "send_activeness_probes", empty_pb2.Empty())
117 process_jobs()
119 with real_jail_session(token) as jail:
120 res = jail.JailInfo(empty_pb2.Empty())
121 assert not res.has_pending_activeness_probe
122 assert not res.jailed
124 with session_scope() as session:
125 assert not session.execute(select(ActivenessProbe)).scalar_one_or_none()
128def test_activeness_probes_expiry(db, push_collector):
129 user, token = generate_user(
130 hosting_status=HostingStatus.can_host,
131 meetup_status=MeetupStatus.wants_to_meetup,
132 last_active=now() - timedelta(days=335),
133 )
135 with session_scope() as session:
136 queue_job(session, "send_activeness_probes", empty_pb2.Empty())
138 process_jobs()
140 with real_jail_session(token) as jail:
141 res = jail.JailInfo(empty_pb2.Empty())
142 assert res.has_pending_activeness_probe
143 assert res.jailed
145 with session_scope() as session:
146 probe = session.execute(select(ActivenessProbe)).scalar_one()
147 probe.probe_initiated = now() - timedelta(days=15)
148 assert probe.notifications_sent == 1
149 probe.notifications_sent = 2
151 queue_job(session, "send_activeness_probes", empty_pb2.Empty())
153 process_jobs()
155 with session_scope() as session:
156 probe = session.execute(select(ActivenessProbe)).scalar_one()
157 assert probe.response == ActivenessProbeStatus.expired
159 with real_jail_session(token) as jail:
160 # no such probe
161 with pytest.raises(grpc.RpcError) as e:
162 jail.RespondToActivenessProbe(
163 jail_pb2.RespondToActivenessProbeReq(response=jail_pb2.ACTIVENESS_PROBE_RESPONSE_STILL_ACTIVE)
164 )
165 assert e.value.code() == grpc.StatusCode.FAILED_PRECONDITION
166 assert e.value.details() == errors.PROBE_NOT_FOUND
168 res = jail.JailInfo(empty_pb2.Empty())
169 assert not res.has_pending_activeness_probe
170 assert not res.jailed
172 with api_session(token) as api:
173 res = api.GetUser(api_pb2.GetUserReq(user=user.username))
174 assert res.hosting_status == api_pb2.HOSTING_STATUS_CANT_HOST
175 assert res.meetup_status == api_pb2.MEETUP_STATUS_OPEN_TO_MEETUP