|
2 | 2 | from collections.abc import Sequence |
3 | 3 | from copy import deepcopy |
4 | 4 | from datetime import datetime, timedelta |
5 | | -from typing import cast |
| 5 | +from typing import DefaultDict, cast |
6 | 6 | from unittest.mock import Mock, patch |
7 | 7 | from uuid import uuid4 |
8 | 8 |
|
9 | 9 | import pytest |
10 | 10 |
|
11 | 11 | from sentry import buffer |
12 | 12 | from sentry.eventstore.models import GroupEvent |
| 13 | +from sentry.models.group import Group |
13 | 14 | from sentry.models.project import Project |
| 15 | +from sentry.models.rule import Rule |
14 | 16 | from sentry.models.rulefirehistory import RuleFireHistory |
15 | 17 | from sentry.rules.conditions.event_frequency import ( |
16 | 18 | ComparisonType, |
|
26 | 28 | get_condition_group_results, |
27 | 29 | get_condition_query_groups, |
28 | 30 | get_group_to_groupevent, |
| 31 | + get_rules_to_fire, |
29 | 32 | get_rules_to_groups, |
30 | 33 | get_rules_to_slow_conditions, |
31 | 34 | get_slow_conditions, |
|
43 | 46 | pytestmark = pytest.mark.sentry_metrics |
44 | 47 |
|
45 | 48 | FROZEN_TIME = before_now(days=1).replace(hour=1, minute=30, second=0, microsecond=0) |
46 | | -TEST_RULE_SLOW_CONDITION = {"id": "sentry.rules.conditions.event_frequency.EventFrequencyCondition"} |
47 | | -TEST_RULE_FAST_CONDITION = {"id": "sentry.rules.conditions.every_event.EveryEventCondition"} |
| 49 | +TEST_RULE_SLOW_CONDITION: EventFrequencyConditionData = { |
| 50 | + "id": "sentry.rules.conditions.event_frequency.EventFrequencyCondition", |
| 51 | + "value": 1, |
| 52 | + "interval": "1h", |
| 53 | +} |
| 54 | + |
| 55 | +TEST_RULE_FAST_CONDITION: EventFrequencyConditionData = { |
| 56 | + "id": "sentry.rules.conditions.every_event.EveryEventCondition", |
| 57 | + "value": 1, |
| 58 | + "interval": "1h", |
| 59 | +} |
48 | 60 |
|
49 | 61 |
|
50 | 62 | def test_bucket_num_groups(): |
@@ -366,8 +378,117 @@ def test_invalid_group_ids(self): |
366 | 378 |
|
367 | 379 |
|
368 | 380 | class GetRulesToFireTest(TestCase): |
369 | | - def test_get_rules_to_fire(self): |
370 | | - pass |
| 381 | + def setUp(self): |
| 382 | + self.organization = self.create_organization() |
| 383 | + self.project = self.create_project() |
| 384 | + self.environment = self.create_environment() |
| 385 | + |
| 386 | + self.rule1: Rule = self.create_project_rule( |
| 387 | + project=self.project, |
| 388 | + condition_match=[TEST_RULE_SLOW_CONDITION], |
| 389 | + environment_id=self.environment.id, |
| 390 | + ) |
| 391 | + self.group1: Group = self.create_group(self.project) |
| 392 | + self.group2: Group = self.create_group(self.project) |
| 393 | + |
| 394 | + self.condition_group_results: dict[UniqueConditionQuery, dict[int, int]] = { |
| 395 | + UniqueConditionQuery( |
| 396 | + cls_id=TEST_RULE_SLOW_CONDITION["id"], |
| 397 | + interval=TEST_RULE_SLOW_CONDITION["interval"], |
| 398 | + environment_id=self.environment.id, |
| 399 | + ): {self.group1.id: 2, self.group2.id: 1} |
| 400 | + } |
| 401 | + |
| 402 | + self.rules_to_slow_conditions: DefaultDict[ |
| 403 | + Rule, list[EventFrequencyConditionData] |
| 404 | + ] = defaultdict(list) |
| 405 | + self.rules_to_slow_conditions[self.rule1].append(TEST_RULE_SLOW_CONDITION) |
| 406 | + |
| 407 | + self.rules_to_groups: DefaultDict[int, set[int]] = defaultdict(set) |
| 408 | + self.rules_to_groups[self.rule1.id].add(self.group1.id) |
| 409 | + self.rules_to_groups[self.rule1.id].add(self.group2.id) |
| 410 | + |
| 411 | + # Mock _passes_comparison function |
| 412 | + self.patcher = patch("sentry.rules.processing.delayed_processing._passes_comparison") |
| 413 | + self.mock_passes_comparison = self.patcher.start() |
| 414 | + |
| 415 | + def tearDown(self): |
| 416 | + self.patcher.stop() |
| 417 | + |
| 418 | + def test_comparison(self): |
| 419 | + self.mock_passes_comparison.return_value = True |
| 420 | + |
| 421 | + result = get_rules_to_fire( |
| 422 | + self.condition_group_results, |
| 423 | + self.rules_to_slow_conditions, |
| 424 | + self.rules_to_groups, |
| 425 | + self.project.id, |
| 426 | + ) |
| 427 | + |
| 428 | + assert result[self.rule1] == {self.group1.id, self.group2.id} |
| 429 | + |
| 430 | + def test_comparison_fail_all(self): |
| 431 | + self.mock_passes_comparison.return_value = False |
| 432 | + |
| 433 | + result = get_rules_to_fire( |
| 434 | + self.condition_group_results, |
| 435 | + self.rules_to_slow_conditions, |
| 436 | + self.rules_to_groups, |
| 437 | + self.project.id, |
| 438 | + ) |
| 439 | + |
| 440 | + assert self.rule1 not in result |
| 441 | + |
| 442 | + def test_comparison_any(self): |
| 443 | + self.rule1.data["action_match"] = "any" |
| 444 | + self.mock_passes_comparison.return_value = True |
| 445 | + |
| 446 | + result = get_rules_to_fire( |
| 447 | + self.condition_group_results, |
| 448 | + self.rules_to_slow_conditions, |
| 449 | + self.rules_to_groups, |
| 450 | + self.project.id, |
| 451 | + ) |
| 452 | + |
| 453 | + assert result[self.rule1] == {self.group1.id, self.group2.id} |
| 454 | + |
| 455 | + def test_comparison_any_fail(self): |
| 456 | + self.rule1.data["action_match"] = "any" |
| 457 | + self.mock_passes_comparison.return_value = False |
| 458 | + |
| 459 | + result = get_rules_to_fire( |
| 460 | + self.condition_group_results, |
| 461 | + self.rules_to_slow_conditions, |
| 462 | + self.rules_to_groups, |
| 463 | + self.project.id, |
| 464 | + ) |
| 465 | + |
| 466 | + assert self.rule1 not in result |
| 467 | + |
| 468 | + def test_empty_input(self): |
| 469 | + result = get_rules_to_fire({}, defaultdict(list), defaultdict(set), self.project.id) |
| 470 | + assert len(result) == 0 |
| 471 | + |
| 472 | + @patch("sentry.rules.processing.delayed_processing._passes_comparison", return_value=True) |
| 473 | + def test_multiple_rules_and_groups(self, mock_passes): |
| 474 | + rule2 = self.create_project_rule( |
| 475 | + project=self.project, |
| 476 | + condition_match=[TEST_RULE_SLOW_CONDITION], |
| 477 | + environment_id=self.environment.id, |
| 478 | + ) |
| 479 | + self.rules_to_slow_conditions[rule2].append(TEST_RULE_SLOW_CONDITION) |
| 480 | + self.rules_to_groups[rule2.id].add(self.group2.id) |
| 481 | + |
| 482 | + result = get_rules_to_fire( |
| 483 | + self.condition_group_results, |
| 484 | + self.rules_to_slow_conditions, |
| 485 | + self.rules_to_groups, |
| 486 | + self.project.id, |
| 487 | + ) |
| 488 | + |
| 489 | + assert len(result) == 2 |
| 490 | + assert result[self.rule1] == {self.group1.id, self.group2.id} |
| 491 | + assert result[rule2] == {self.group2.id} |
371 | 492 |
|
372 | 493 |
|
373 | 494 | class GetRulesToGroupsTest(TestCase): |
|
0 commit comments