WIP: tests for registry

This commit is contained in:
Klaas van Schelven
2024-01-05 22:29:26 +01:00
parent e3433e8ddb
commit 164ed8dfd5
4 changed files with 64 additions and 15 deletions
+1 -1
View File
@@ -131,7 +131,7 @@ class PeriodCounter(object):
tl = self._tl_for_period(period_name)
if initial_event_state is None:
initial_event_state = self._get_event_state(tup, tl, nr_of_periods, gte_threshold)
initial_event_state = self._get_event_state(tup[:tl], tl, nr_of_periods, gte_threshold)
self.event_listeners[tl][(nr_of_periods, gte_threshold)] = \
(when_becomes_true, when_becomes_false, auto_remove, initial_event_state)
+9 -3
View File
@@ -20,7 +20,8 @@ def create_unmute_issue_handler(issue_id):
class PeriodCounterRegistry(object):
def load_from_scratch(self, projects, issues, ordered_events, now_tup):
def load_from_scratch(self, projects, issues, ordered_events, now):
# create period counters for all projects and issues
by_project = {}
by_issue = {}
@@ -30,6 +31,7 @@ class PeriodCounterRegistry(object):
for issue in issues:
by_issue[issue.id] = PeriodCounter()
# load all events (one by one, let's measure the slowness of the naive implementation before making it faster)
for event in ordered_events:
project_pc = by_project[event.project_id]
project_pc.inc(event.timestamp)
@@ -37,6 +39,10 @@ class PeriodCounterRegistry(object):
issue_pc = by_issue[event.issue_id]
issue_pc.inc(event.timestamp)
# connect all volume-based conditions to their respective period counters' event listeners
# this is done after the events are loaded because:
# 1. we don't actually want to trigger anything on-load and
# 2. this is much faster.
for issue in issues.filter(is_muted=True):
issue_pc = by_issue[issue.id]
@@ -47,11 +53,11 @@ class PeriodCounterRegistry(object):
for vbc in unmute_vbcs:
issue_pc.add_event_listener(
period_name=vbc.period_name,
period_name=vbc.period,
nr_of_periods=vbc.nr_of_periods,
gte_threshold=vbc.volume,
when_becomes_true=create_unmute_issue_handler(issue.id),
tup=now_tup,
tup=now.timetuple(),
auto_remove=True, # unmuting is needed only once; hence auto_remove to avoid recurring unmute calls
)
+51 -4
View File
@@ -1,9 +1,16 @@
import uuid
from datetime import datetime, timezone
from unittest import TestCase
from django.test import TestCase as DjangoTestCase
from .period_counter import PeriodCounter, _prev_tup, TL_YEAR
from projects.models import Project
from issues.models import Issue
from events.models import Event
from .period_counter import PeriodCounter, _prev_tup, TL_DAY, TL_YEAR
from .volume_based_condition import VolumeBasedCondition
from .registry import PeriodCounterRegistry
def apply_n(f, n, v):
@@ -139,8 +146,48 @@ class VolumeBasedConditionTestCase(TestCase):
def test_serialization(self):
vbc = VolumeBasedCondition("day", 1, 100)
json_str = vbc.to_json_str()
self.assertEquals('{"period": "day", "nr_of_periods": 1, "volume": 100}', json_str)
self.assertEquals({"period": "day", "nr_of_periods": 1, "volume": 100}, vbc.to_dict())
vbc2 = VolumeBasedCondition.from_json_str(json_str)
vbc2 = VolumeBasedCondition.from_dict(vbc.to_dict())
self.assertEquals(vbc, vbc2)
class PCRegistryTestCase(DjangoTestCase):
def test_empty(self):
result = PeriodCounterRegistry().load_from_scratch(
Project.objects.all(),
Issue.objects.all(),
Event.objects.all(),
datetime.now(timezone.utc),
)
self.assertEquals(({}, {}), result)
def test_with_muted_issue_and_event(self):
project = Project.objects.create(name="project")
issue = Issue.objects.create(
project=project,
is_muted=True,
unmute_on_volume_based_conditions='[{"period": "day", "nr_of_periods": 1, "volume": 100}]',
)
Event.objects.create(
project=project,
issue=issue,
timestamp=datetime.now(timezone.utc),
server_side_timestamp=datetime.now(timezone.utc),
event_id=uuid.uuid4().hex,
has_exception=True,
has_logentry=True,
data="{}",
)
by_project, by_issue = PeriodCounterRegistry().load_from_scratch(
Project.objects.all(),
Issue.objects.all(),
Event.objects.all(),
datetime.now(timezone.utc),
)
self.assertEquals({project.id}, by_project.keys())
self.assertEquals({issue.id}, by_issue.keys())
self.assertEquals({(1, 100)}, by_issue[issue.id].event_listeners[TL_DAY].keys())
+3 -7
View File
@@ -1,6 +1,3 @@
import json
class VolumeBasedCondition(object):
def __init__(self, period, nr_of_periods, volume):
@@ -9,16 +6,15 @@ class VolumeBasedCondition(object):
self.volume = volume
@classmethod
def from_json_str(cls, json_str): # TODO had toch gewoon dict moeten wezen
json_dict = json.loads(json_str)
def from_dict(cls, json_dict):
return VolumeBasedCondition(
json_dict['period'],
json_dict['nr_of_periods'],
json_dict['volume'],
)
def to_json_str(obj):
return json.dumps(obj.__dict__)
def to_dict(obj):
return obj.__dict__
def __eq__(self, other):
return self.__dict__ == other.__dict__