/
test_outcomes.py
162 lines (130 loc) · 4.84 KB
/
test_outcomes.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
import types
from unittest import mock
import pytest
from sentry.conf.types.kafka_definition import Topic
from sentry.utils import json, kafka_config, outcomes
from sentry.utils.outcomes import Outcome, track_outcome
@pytest.fixture(autouse=True)
def setup():
# Rely on the fact that the publisher is initialized lazily
with mock.patch.object(kafka_config, "get_kafka_producer_cluster_options") as mck_get_options:
with mock.patch.object(outcomes, "KafkaPublisher") as mck_publisher:
# Reset internals of the outcomes module
with mock.patch.object(outcomes, "outcomes_publisher", None):
with mock.patch.object(outcomes, "billing_publisher", None):
yield types.SimpleNamespace(
mock_get_kafka_producer_cluster_options=mck_get_options,
mock_publisher=mck_publisher,
)
@pytest.mark.parametrize(
"outcome, is_billing",
[
(Outcome.ACCEPTED, True),
(Outcome.FILTERED, False),
(Outcome.RATE_LIMITED, True),
(Outcome.INVALID, False),
(Outcome.ABUSE, False),
(Outcome.CLIENT_DISCARD, False),
],
)
def test_outcome_is_billing(outcome: Outcome, is_billing: bool):
"""
Tests the complete behavior of ``is_billing``, used for routing outcomes to
different Kafka topics. This is more of a sanity check to prevent
unintentional changes.
"""
assert outcome.is_billing() is is_billing
@pytest.mark.parametrize(
"name, outcome",
[
("rate_limited", Outcome.RATE_LIMITED),
("RATE_LIMITED", Outcome.RATE_LIMITED),
],
)
def test_parse_outcome(name, outcome):
"""
Asserts *case insensitive* parsing of outcomes from their canonical names,
as used in the API and queries.
"""
assert Outcome.parse(name) == outcome
def test_track_outcome_default(setup):
"""
Asserts an outcomes serialization roundtrip with defaults.
"""
track_outcome(
org_id=1,
project_id=2,
key_id=3,
outcome=Outcome.INVALID,
reason="project_id",
)
cluster_args, _ = setup.mock_get_kafka_producer_cluster_options.call_args
assert cluster_args == (kafka_config.get_topic_definition(Topic.OUTCOMES)["cluster"],)
assert outcomes.outcomes_publisher
(topic_name, payload), _ = setup.mock_publisher.return_value.publish.call_args
# not billing because it's not accepted/rate limited
assert topic_name == "outcomes"
data = json.loads(payload)
del data["timestamp"]
assert data == {
"org_id": 1,
"project_id": 2,
"key_id": 3,
"outcome": Outcome.INVALID.value,
"reason": "project_id",
"event_id": None,
"category": None,
"quantity": 1,
}
assert outcomes.billing_publisher is None
def test_track_outcome_billing(setup):
"""
Checks that outcomes are routed to the DEDICATED topic within the same cluster
in default configuration.
"""
track_outcome(
org_id=1,
project_id=1,
key_id=1,
outcome=Outcome.ACCEPTED,
)
cluster_args, _ = setup.mock_get_kafka_producer_cluster_options.call_args
assert cluster_args == (kafka_config.get_topic_definition(Topic.OUTCOMES)["cluster"],)
assert outcomes.outcomes_publisher
(topic_name, _), _ = setup.mock_publisher.return_value.publish.call_args
assert topic_name == "outcomes-billing"
assert outcomes.billing_publisher is None
def test_track_outcome_billing_topic(setup):
"""
Checks that outcomes are routed to the DEDICATED billing topic within the
same cluster in default configuration.
"""
track_outcome(
org_id=1,
project_id=1,
key_id=1,
outcome=Outcome.ACCEPTED,
)
cluster_args, _ = setup.mock_get_kafka_producer_cluster_options.call_args
assert cluster_args == (kafka_config.get_topic_definition(Topic.OUTCOMES)["cluster"],)
assert outcomes.outcomes_publisher
(topic_name, _), _ = setup.mock_publisher.return_value.publish.call_args
assert topic_name == "outcomes-billing"
assert outcomes.billing_publisher is None
def test_track_outcome_billing_cluster(settings, setup):
"""
Checks that outcomes are routed to the dedicated cluster and topic.
"""
with mock.patch.dict(settings.KAFKA_TOPIC_TO_CLUSTER, {"outcomes-billing": "different"}):
track_outcome(
org_id=1,
project_id=1,
key_id=1,
outcome=Outcome.ACCEPTED,
)
cluster_args, _ = setup.mock_get_kafka_producer_cluster_options.call_args
assert cluster_args == ("different",)
assert outcomes.billing_publisher
(topic_name, _), _ = setup.mock_publisher.return_value.publish.call_args
assert topic_name == "outcomes-billing"
assert outcomes.outcomes_publisher is None