def __init__(self, event_config, control_opts={}, client_id=None): ''' base class initializer, creates an `event.EventHandler` as `self.event_handler` and a `control.EventController` as `self.event_controller event_config -- A dictionary containing keyword arugments for the EventHandler control_opts -- a dict of opts for `control.EventController` init ''' # Get an EventHandler and an EventController self.event_handler = event.EventHandler(**event_config) self.event_controller = controller.EventController( self.event_handler, **control_opts) # Add an exit thread for the module self._exit = threading.Event() self._exit.clear() logger.addFilter(IdFilter(client_id=client_id)) logger.info('Created base handler.') pass
def test_60_new_cancelled_event(tmpdir): """ VEN, EiEvent Service, oadrDistributeEvent, oadrCreatedEvent Payload If the VTN sends an oadrEvent with the eventStatus set to cancelled and has an eventID that the VEN is not aware of then the VEN should ignore the event since it is not currently in its list of known events, but still must respond with the createdEvent if required to do so by oadrResponseRequired """ test_event = AdrEvent( id="FooEvent", start=datetime.utcnow() - timedelta(seconds=60), signals=[dict(index=0, duration=timedelta(minutes=10), level=1.0)], status=AdrEventStatus.CANCELLED, mod_number=1 ) event_handler = event.EventHandler("VEN_ID", db_path=TEST_DB_ADDR % tmpdir) event_controller = controller.EventController(event_handler) reply = event_handler.handle_payload(generate_payload([test_event])) assert reply.findtext( responseCode, namespaces=NS_A ) == "200" assert reply.findtext( optType, namespaces=NS_A ) == "optIn" active_event = event_handler.get_active_events()[0] signal_level, evt_id, remove_events = event_controller._calculate_current_event_status([active_event]) assert (signal_level, evt_id, remove_events) == (0, None, ["FooEvent"])
def test_65_cancellation_time_randomization(tmpdir): """ VEN, EiEvent Service, oadrDistributeEvent, oadrCreatedEvent Payload When an event containing a randomization value in the startafter element is cancelled, either explicitly or implicitly, the VEN MUST randomize its termination of the event. The randomization window should be between 0 and a duration equal to the value specified in startafter. """ test_event = AdrEvent( id="FooEvent", start=datetime.utcnow() - timedelta(minutes=5), signals=[dict(index=0, duration=timedelta(minutes=10), level=1.0)], status=AdrEventStatus.ACTIVE, start_after=timedelta(minutes=2) ) event_handler = event.EventHandler("VEN_ID", db_path=TEST_DB_ADDR % tmpdir) event_controller = controller.EventController(event_handler) event_handler.handle_payload(generate_payload([test_event])) with freeze_time(): test_event.mod_number += 1 test_event.status = AdrEventStatus.CANCELLED event_handler.handle_payload(generate_payload([test_event])) active_event = event_handler.get_active_events()[0] assert active_event.end != datetime.utcnow() assert (active_event.start - datetime.utcnow()) < timedelta(minutes=2)
def test_59_event_cancellation(tmpdir): """ VEN, EiEvent Service, oadrDistributeEvent Payload If the VTN sends an oadrEvent with the eventStatus set to cancelled and has an eventID that the VEN is aware of then the VEN should cancel the existing event and delete it from its list of known events. """ test_event = AdrEvent( id="FooEvent", start=datetime.utcnow() + timedelta(seconds=60), signals=[dict(index=0, duration=timedelta(minutes=10), level=1.0)], status=AdrEventStatus.PENDING, mod_number=1 ) event_handler = event.EventHandler("VEN_ID", db_path=TEST_DB_ADDR % tmpdir) event_controller = controller.EventController(event_handler) event_handler.handle_payload(generate_payload([test_event])) active_event = event_handler.get_active_events()[0] assert active_event == test_event.to_obj() with freeze_time(): test_event.status = AdrEventStatus.CANCELLED test_event.mod_number += 1 test_event.end = datetime.utcnow() event_handler.handle_payload(generate_payload([test_event])) active_event = event_handler.get_active_events()[0] assert active_event == test_event.to_obj() signal_level, evt_id, remove_events = event_controller._calculate_current_event_status([test_event.to_obj()]) assert (signal_level, evt_id, remove_events) == (0, None, ["FooEvent"])
def test_56_new_event(tmpdir): """ VEN, EiEvent Service, oadrDistributeEvent Payload If the VTN sends an oadrEvent with an eventID that the VEN is not aware then it should process the event and add it to its list of known events """ test_event = AdrEvent( id="FooEvent", start=datetime.utcnow()+timedelta(seconds=60), signals=[dict(index=0, duration=timedelta(minutes=10), level=1.0)], status=AdrEventStatus.PENDING ) event_handler = event.EventHandler("VEN_ID", db_path=TEST_DB_ADDR % tmpdir) event_controller = controller.EventController(event_handler) event_handler.handle_payload(generate_payload([test_event])) signal_level, evt_id, remove_events = event_controller._calculate_current_event_status([test_event.to_obj()]) assert (signal_level, evt_id, remove_events) == (0, None, []) active_event = event_handler.get_active_events()[0] expected_event = test_event.to_obj() assert active_event == expected_event with freeze_time(datetime.utcnow()+timedelta(seconds=70)): signal_level, evt_id, remove_events = event_controller._calculate_current_event_status([test_event.to_obj()]) assert (signal_level, evt_id, remove_events) == (1.0, "FooEvent", [])
def test_calculate_current_event_status(event_list, expected, tmpdir): event_handler = event.EventHandler("VEN_ID", db_path=TEST_DB_ADDR % tmpdir) event_controller = controller.EventController(event_handler) signal_level, evt_id, remove_events = event_controller._calculate_current_event_status([evt.to_obj() for evt in event_list]) assert (signal_level, evt_id, remove_events) == expected
def test_18_overlaping_events(tmpdir): """ VEN/VTN, EiEvent Service The VEN/VTN must honor the following rules with regards to overlapping active periods... DR events with overlapping active periods may be issued, but only if they are from different marketContexts and only if the programs have a priority associated with them. DR events for programs with higher priorities supersede the events of programs with lower priorities. If two programs with overlapping events have the same priority then the program whose event was activated first takes priority. The behavior of a VEN is undefined with respect to the receipt on an overlapping event in the same market context. The VTN shall not send overlapping events in the same market context, including events that could potentially overlap a randomized event cancellation. Nothing in this rule should preclude a VEN from opting into overlapping events in different market contexts. """ expected_events = [ AdrEvent( id="FooEvent1", start=datetime.utcnow() - timedelta(seconds=60), signals=[dict(index=0, duration=timedelta(minutes=10), level=1.0)], status=AdrEventStatus.ACTIVE, market_context="context1", priority=1 ), AdrEvent( id="FooEvent2", start=datetime.utcnow() - timedelta(seconds=60), signals=[dict(index=0, duration=timedelta(minutes=10), level=2.0)], status=AdrEventStatus.ACTIVE, market_context="context2", priority=2 ), ] event_handler = event.EventHandler( "VEN_ID", db_path=TEST_DB_ADDR % tmpdir, vtn_ids="TH_VTN", market_contexts="context1,context2" ) event_controller = controller.EventController(event_handler) event_handler.handle_payload(generate_payload(expected_events)) active_events = event_handler.get_active_events() signal_level, evt_id, remove_events = event_controller._calculate_current_event_status(active_events) assert (signal_level, evt_id, remove_events) == (2.0, "FooEvent2", [])
def test_calculate_update_control(event_list, expected_level, expected_removed, tmpdir): db_mock = mock.MagicMock() event_handler = event.EventHandler("VEN_ID", db_path=TEST_DB_ADDR % tmpdir) event_handler.db.remove_events = db_mock event_controller = controller.EventController(event_handler) signal_level = event_controller._update_control([evt.to_obj() for evt in event_list]) assert signal_level == expected_level if expected_removed: parsed_events = db_mock.call_args[0][0] for evt in expected_removed: assert evt in parsed_events parsed_events.remove(evt) assert parsed_events == [] else: db_mock.assert_not_called()
def test_47_unending_event(tmpdir): """ VEN/VTN, EiEvent Service, oadrDistributeEvent Payload An event with an overall duration of 0 indicates an event with no defined end time and will remain active until explicitly cancelled. """ test_event = AdrEvent( id="FooEvent", start=datetime.utcnow() + timedelta(seconds=60), signals=[dict(index=0, duration=timedelta(minutes=0), level=1.0)], status=AdrEventStatus.ACTIVE ) event_handler = event.EventHandler("VEN_ID", db_path=TEST_DB_ADDR % tmpdir) event_controller = controller.EventController(event_handler) event_handler.handle_payload(generate_payload([test_event])) active_event = event_handler.get_active_events()[0] signal_level, evt_id, remove_events = event_controller._calculate_current_event_status([active_event]) assert (signal_level, evt_id, remove_events) == (0, None, []) with freeze_time(datetime.utcnow() + timedelta(seconds=70)): signal_level, evt_id, remove_events = event_controller._calculate_current_event_status([active_event]) assert (signal_level, evt_id, remove_events) == (1.0, "FooEvent", []) with freeze_time(datetime.utcnow() + timedelta(minutes=70)): signal_level, evt_id, remove_events = event_controller._calculate_current_event_status([active_event]) assert (signal_level, evt_id, remove_events) == (1.0, "FooEvent", []) with freeze_time(datetime.utcnow() + timedelta(hours=70)): signal_level, evt_id, remove_events = event_controller._calculate_current_event_status([active_event]) assert (signal_level, evt_id, remove_events) == (1.0, "FooEvent", []) test_event.status = AdrEventStatus.CANCELLED test_event.mod_number += 1 event_handler.handle_payload(generate_payload([test_event])) active_event = event_handler.get_active_events()[0] signal_level, evt_id, remove_events = event_controller._calculate_current_event_status([active_event]) assert (signal_level, evt_id, remove_events) == (0, None, ["FooEvent"])
def test_6_test_event(tmpdir): """ VEN, EiEvent Service, oadrDistributeEvent Payload The presence of any string except “false” in the oadrDisributeEvent testEvent element is treated as a trigger for a test event. """ test_event = AdrEvent( id="FooEvent", start=datetime.utcnow()-timedelta(seconds=60), signals=[dict(index=0, duration=timedelta(minutes=10), level=1.0)], status=AdrEventStatus.ACTIVE, test_event=True ) event_handler = event.EventHandler("VEN_ID", db_path=TEST_DB_ADDR % tmpdir) event_controller = controller.EventController(event_handler) event_handler.handle_payload(generate_payload([test_event])) signal_level, evt_id, remove_events = event_controller._calculate_current_event_status([test_event.to_obj()]) assert (signal_level, evt_id, remove_events) == (0, None, []) active_event = event_handler.get_active_events()[0] expected_event = test_event.to_obj() assert active_event == expected_event