mirror of
https://github.com/bugsink/bugsink.git
synced 2026-05-01 20:39:37 -05:00
WIP: tests for registry
This commit is contained in:
@@ -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
@@ -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
@@ -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())
|
||||
|
||||
@@ -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__
|
||||
|
||||
Reference in New Issue
Block a user