Beispiel #1
0
def test_handle_payload(event_list, tmpdir):
    db_mock = mock.MagicMock()
    event_handler = event.EventHandler("VEN_ID", db_path=TEST_DB_ADDR % tmpdir)
    event_handler.db.add_event = db_mock

    reply = event_handler.handle_payload(generate_payload(event_list))
    assert reply.findtext(responseCode, namespaces=NS_A) == "200"
    assert reply.findtext(requestID, namespaces=NS_A) == "OadrDisReq092520_152645_178"
    assert reply.findtext(optType, namespaces=NS_A) == "optIn"
    assert reply.findtext(venID, namespaces=NS_A) == "VEN_ID"

    db_mock.assert_called_once()

    for index, evt in enumerate(event_list):
        parsed_event = db_mock.call_args[0][index]
        expected_event = evt.to_obj()

        assert parsed_event.id == expected_event.id
        assert parsed_event.start == expected_event.start
        assert parsed_event.original_start == expected_event.original_start
        assert parsed_event.cancellation_offset == expected_event.cancellation_offset
        assert parsed_event.signals == expected_event.signals
        assert parsed_event.mod_number == expected_event.mod_number
        assert parsed_event.status == expected_event.status
        if expected_event.status != AdrEventStatus.CANCELLED.value:
            assert parsed_event.end == expected_event.end
def test_36_cancellation_acknowledgement(tmpdir):
    """
    VEN, EiEvent Service, oadrCreatedEvent Payload
    An event cancellation received by the VEN must be acknowledged with an
    oadrCreatedEvent with the optType element set as follows, unless the
    oadrResponseRequired is set to ‘never”:
    optIn = Confirm to cancellation
    optOut = Cannot cancel
    Note: Once an event cancellation is acknowledged by the VEN, the event
    shall not be included in subsequent oadrCreatedEvent payloads unless the
    VTN includes this event in a subsequent oadrDistributeEvent payload.
    """
    test_event = AdrEvent(
        id="FooEvent",
        start=datetime.utcnow() + timedelta(minutes=10),
        signals=[dict(index=0, duration=timedelta(minutes=10), level=1.0)],
        status=AdrEventStatus.CANCELLED
    )
    db_mock = mock.MagicMock()
    event_handler = event.EventHandler("VEN_ID", db_path=TEST_DB_ADDR % tmpdir)
    event_handler.db.update_event = db_mock

    reply = event_handler.handle_payload(generate_payload([test_event]))

    assert reply.findtext(responseCode, namespaces=NS_A) == "200"
    assert reply.findtext(requestID, namespaces=NS_A) == "OadrDisReq092520_152645_178"
    assert reply.findtext(optType, namespaces=NS_A) == "optIn"
    assert reply.findtext(venID, namespaces=NS_A) == "VEN_ID"

    db_mock.assert_not_called()
Beispiel #3
0
    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_42_request_id(tmpdir):
    """
    VEN, EiEvent Service, oadrCreatedEvent Payload
    A VEN receiving an oadrDistributeEvent eiEvent must use the received requestID
    value in the EiCreatedEvent eventResponse when responding to the event. This
    includes any and all subsequent EiCreatedEvent messages that may be sent to
    change the opt status of the VEN.
    The eiResponse:requestID in oadrCreatedEvent shall be left empty if the
    payload contains eventResponses. The VTN shall
    look inside each
    eventResponse for the relevant requestID
    """
    test_event = AdrEvent(
        id="FooEvent",
        start=datetime.utcnow() + timedelta(minutes=10),
        signals=[dict(index=0, duration=timedelta(minutes=10), level=1.0)],
        status=AdrEventStatus.PENDING, start_after=timedelta(minutes=2)
    )
    db_mock = mock.MagicMock()
    event_handler = event.EventHandler("VEN_ID", db_path=TEST_DB_ADDR % tmpdir)
    event_handler.db.update_event = db_mock

    reply = event_handler.handle_payload(generate_payload([test_event]))
    assert reply.findtext(
        'pyld:eiCreatedEvent/ei:eventResponses/ei:eventResponse/pyld:requestID',
        namespaces=NS_A
    ) == "OadrDisReq092520_152645_178"
Beispiel #5
0
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_57_modified_event(tmpdir):
    """
    VEN/VTN, EiEvent Service, oadrDistributeEvent Payload
    If the VTN sends an oadrEvent with an eventID that the VEN is already
    aware of, but with a higher modification number then the VEN should
    replace the previous event with the new one In 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_handler.handle_payload(generate_payload([test_event]))

    active_event = event_handler.get_active_events()[0]
    expected_event = test_event.to_obj()
    assert active_event == expected_event

    test_event.mod_number = 1
    test_event.status = AdrEventStatus.ACTIVE

    event_handler.handle_payload(generate_payload([test_event]))

    active_event = event_handler.get_active_events()[0]
    expected_event = test_event.to_obj()
    assert active_event == expected_event
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_22_target_validation(expected_event, tmpdir):
    """
    VEN, EiEvent Service, oadrDistributeEvent Payload
    If no sub elements are present in oadrDistributeEvent eiTarget, the
    presumption is that the recipient is the intended target of the event. If
    multiple criteria are present in eiTarget subelements, the values are OR’d
    togther to determine whether the VEN is a target for the event. However,
    the VENs behavior with respect to responding to an event when it matches
    one of the eiTarget criteria is implementation dependent.
    """
    db_mock = mock.MagicMock()
    event_handler = event.EventHandler(
        "VEN_ID",
        db_path=TEST_DB_ADDR % tmpdir,
        resource_id="resource_id",
        party_id="party_id",
        group_id="group_id"
    )
    event_handler.db.update_event = db_mock

    reply = event_handler.handle_payload(generate_payload([expected_event]))
    assert reply.findtext(responseCode, namespaces=NS_A) == "200"
    assert reply.findtext(requestID, namespaces=NS_A) == "OadrDisReq092520_152645_178"
    assert reply.findtext(optType, namespaces=NS_A) == "optIn"
    assert reply.findtext(venID, namespaces=NS_A) == "VEN_ID"
def test_58_modified_event_error(tmpdir):
    """
    VEN, EiEvent Service, oadrDistributeEvent Payload
    If the VTN sends an oadrEvent with an eventID that the VEN is already
    aware of, but which has a lower modification number than one in which the
    VEN is already aware then this is an ERROR and the VEN should respond
    with the appropriate error code. Note that this is true regardless of the
    event state including cancelled.
    """
    test_event1 = 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=5
    )
    test_event2 = 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=3
    )

    event_handler = event.EventHandler("VEN_ID", db_path=TEST_DB_ADDR % tmpdir)

    event_handler.handle_payload(generate_payload([test_event1]))

    active_event = event_handler.get_active_events()[0]
    expected_event = test_event1.to_obj()
    assert active_event == expected_event

    event_handler.handle_payload(generate_payload([test_event2]))

    active_event = event_handler.get_active_events()[0]
    assert active_event == expected_event
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_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_21a_ven_id_validation(tmpdir):
    """
    VEN/VTN, EiEvent Service, oadrDistributeEvent Payload
    If venID, vtnID, or EventID is included in payloads, the receiving entity must
    validate the ID values are as expected and generate an error if no ID is
    present or an unexpected value is received.
    Exception: A VEN shall not generate an error upon receipt of a cancelled
    event whose eventID is not previously known.
    """
    expected_event = AdrEvent(
        id="FooEvent",
        start=datetime.utcnow() + timedelta(seconds=60),
        signals=[dict(index=0, duration=timedelta(seconds=10), level=1.0)],
        status=AdrEventStatus.PENDING, ven_ids=["Wrong_Ven"]
    )
    db_mock = mock.MagicMock()
    event_handler = event.EventHandler(
        "VEN_ID",
        db_path=TEST_DB_ADDR % tmpdir,
        vtn_ids="TH_VTN"
    )
    event_handler.db.update_event = db_mock

    reply = event_handler.handle_payload(generate_payload([expected_event]))
    assert reply.findtext(responseCode, namespaces=NS_A) == "200"
    assert reply.findtext(requestID, namespaces=NS_A) == "OadrDisReq092520_152645_178"
    assert reply.findtext(optType, namespaces=NS_A) == "optOut"
    assert reply.findtext(venID, namespaces=NS_A) == "VEN_ID"
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)
Beispiel #14
0
def test_implied_cancellation(tmpdir):
    event1 = AdrEvent(
        id="FooEvent1",
        start=datetime.utcnow()-timedelta(seconds=60),
        signals=[dict(index=0, duration=timedelta(minutes=10), level=1.0)],
        status=AdrEventStatus.ACTIVE,
    )
    event2 = AdrEvent(
        id="FooEvent2",
        start=datetime.utcnow()-timedelta(seconds=50),
        signals=[dict(index=0, duration=timedelta(minutes=10), level=2.0)],
        status=AdrEventStatus.ACTIVE,
    )

    event_handler = event.EventHandler("VEN_ID", db_path=TEST_DB_ADDR % tmpdir)

    event_handler.handle_payload(generate_payload([event1]))

    active_events = event_handler.get_active_events()

    assert [event1.to_obj()] == active_events

    with freeze_time():
        event_handler.handle_payload(generate_payload([event2]))
        active_events = event_handler.get_active_events()

        cancelled_evt = event1.to_obj()
        cancelled_evt.cancel()
        assert [cancelled_evt, event2.to_obj()] == active_events
def test_48_payload_error_indication(expected_event, tmpdir):
    """
    When a VTN or VEN receives schema compliant oadr payload that has
    logical errors, the receiving device must provide an application layer error
    indication of 4xx. The detailed error message number is informational and
    not a requirement for response to a specific scenario. If the error is in an
    event contained in an oadrDistributeEvent payload, it should be reported in
    the eventResponse element of oadrCreatedEvent. The following logical
    errors must be detected by implementations:
        VEN receives non-matching market context
        VEN receives non-matching eiTarget
        VEN receives unsupported signalName
        VTN receives non-matching eventID in oadrCreatedEvent Response
        VTN receives mismatched modificationNumber in oadrCreatedEvent
    """
    db_mock = mock.MagicMock()
    event_handler = event.EventHandler(
        "VEN_ID",
        market_contexts="http://market.context",
        db_path=TEST_DB_ADDR % tmpdir,
        resource_id="resource_id",
        party_id="party_id",
        group_id="group_id"
    )
    event_handler.db.update_event = db_mock

    reply = event_handler.handle_payload(generate_payload([expected_event]))
    assert reply.findtext(responseCode, namespaces=NS_A) == "200"
    assert reply.findtext(requestID, namespaces=NS_A) == "OadrDisReq092520_152645_178"
    assert reply.findtext(optType, namespaces=NS_A) == "optOut"
    assert reply.findtext(venID, namespaces=NS_A) == "VEN_ID"
Beispiel #16
0
def test_handle_payload_with_db(event_list, tmpdir):
    event_handler = event.EventHandler("VEN_ID", db_path=TEST_DB_ADDR % tmpdir)

    reply = event_handler.handle_payload(generate_payload(event_list))

    active_events = event_handler.get_active_events()
    for evt in event_list:
        assert evt.to_obj() in active_events
Beispiel #17
0
def test_handle_cancelled_payload_with_db(event_list, tmpdir):
    event_handler = event.EventHandler("VEN_ID", db_path=TEST_DB_ADDR % tmpdir)

    event_handler.handle_payload(generate_payload(event_list))

    active_event = event_handler.get_active_events()[0]
    expected_event = event_list[0].to_obj()

    assert active_event.end != expected_event.end
    active_event.end = expected_event.end = None
    assert active_event == expected_event
Beispiel #18
0
def test_handle_payload_with_wrong_target_info(expected_event, handler_param, tmpdir):
    db_mock = mock.MagicMock()
    event_handler = event.EventHandler("VEN_ID", db_path=TEST_DB_ADDR % tmpdir, **handler_param)
    event_handler.db.update_event = db_mock

    reply = event_handler.handle_payload(generate_payload([expected_event]))
    assert reply.findtext(responseCode, namespaces=NS_A) == "200"
    assert reply.findtext(requestID, namespaces=NS_A) == "OadrDisReq092520_152645_178"
    assert reply.findtext(optType, namespaces=NS_A) == "optOut"
    assert reply.findtext(venID, namespaces=NS_A) == "VEN_ID"

    db_mock.assert_not_called()
Beispiel #19
0
    def setUp(self):
        self.start_thread = False

        # Some configureation variables, by default, this is for the a handler
        self.config = {'vtn_ids': 'vtn_1,vtn_2,vtn_3,TH_VTN', 'ven_id': VEN_ID}
        oadr_schema_file = open(os.path.join(SCHEMA_DIR,
                                             'oadr_20a.xsd'))  # OpenADR
        oadr_schema_doc = etree.parse(oadr_schema_file)
        self.oadr_schema = etree.XMLSchema(oadr_schema_doc)
        self.event_handler = event.EventHandler(**self.config)

        # Make things a little nicer for us to see
        print('')
        print(40 * '=')
def test_19_valid_invalid_events(tmpdir):
    """
    VEN, EiEvent Service, oadrDistributeEvent Payload
    If an oadrDistributeEvent payload has as mix of valid and invalid events,
    the implementation shall only respond to the relevant valid events and not
    reject the entire message.
    """
    expected_events = [
        AdrEvent(
            id="FooEvent",
            start=datetime.utcnow() + timedelta(seconds=60),
            signals=[dict(index=0, duration=timedelta(seconds=10), level=1.0)],
            status=AdrEventStatus.PENDING
        ),
        AdrEvent(
            id="FooFailed",
            start=datetime.utcnow() + timedelta(seconds=160),
            signals=[dict(index=0, duration=timedelta(seconds=10), level=1.0)],
            status=AdrEventStatus.PENDING, ven_ids=["Wrong_Ven"]
        ),
        AdrEvent(
            id="AnotherFooEvent",
            start=datetime.utcnow() + timedelta(seconds=260),
            signals=[dict(index=0, duration=timedelta(seconds=10), level=1.0)],
            status=AdrEventStatus.PENDING
        )
    ]
    db_mock = mock.MagicMock()
    event_handler = event.EventHandler(
        "VEN_ID",
        db_path=TEST_DB_ADDR % tmpdir,
        vtn_ids="TH_VTN"
    )
    event_handler.db.update_event = db_mock

    reply = event_handler.handle_payload(generate_payload(expected_events))

    assert reply.findtext(venID, namespaces=NS_A) == "VEN_ID"
    assert reply.findtext(responseCode, namespaces=NS_A) == "200"
    for event_reply in reply.iterfind(eventResponse, namespaces=NS_A):
        event_id = event_reply.findtext("ei:qualifiedEventID/ei:eventID", namespaces=NS_A)

        assert reply.findtext(requestID, namespaces=NS_A) == "OadrDisReq092520_152645_178"
        if event_id == "FooFailed":
            assert event_reply.findtext("ei:responseCode", namespaces=NS_A) == "403"
            assert event_reply.findtext("ei:optType", namespaces=NS_A) == "optOut"
        else:
            assert event_reply.findtext("ei:responseCode", namespaces=NS_A) == "200"
            assert event_reply.findtext("ei:optType", namespaces=NS_A) == "optIn"
Beispiel #21
0
def test_update_with_db(test_event, tmpdir):
    event_handler = event.EventHandler("VEN_ID", db_path=TEST_DB_ADDR % tmpdir)

    event_handler.handle_payload(generate_payload([test_event]))

    active_events = event_handler.get_active_events()
    assert test_event.to_obj() in active_events

    test_event.mod_number += 1
    test_event.status = AdrEventStatus.ACTIVE

    event_handler.handle_payload(generate_payload([test_event]))

    active_events = event_handler.get_active_events()
    assert test_event.to_obj() in active_events
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_35_response_created_event(tmpdir):
    """
    VEN, EiEvent Service, oadrCreatedEvent Payload
    The eiResponses element in oadrCreatedEvent is mandatory, except when
    an error condition is reported in eiResponse.
    """
    test_event = AdrEvent(
        id="FooEvent",
        start=datetime.utcnow() + timedelta(minutes=10),
        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)

    reply = event_handler.handle_payload(generate_payload([test_event]))

    assert bool(reply.find("pyld:eiCreatedEvent/ei:eventResponses", namespaces=NS_A))
    def setUp(self):
        self.start_thread = False

        # Some configureation variables, by default, this is for the a handler
        self.config = {
            'vtn_ids': 'vtn_1,vtn_2,vtn_3,TH_VTN,VTN_543',
            'ven_id': VEN_ID,
            'oadr_profile_level': event.OADR_PROFILE_20B
        }
        with open(os.path.join(SCHEMA_DIR,
                               'oadr_20b.xsd')) as oadr_schema_file:
            oadr_schema_doc = etree.parse(oadr_schema_file)
        self.oadr_schema = etree.XMLSchema(oadr_schema_doc)
        self.event_handler = event.EventHandler(**self.config)

        # Make things a little nicer for us to see
        print('')
        print(40 * '=')
def test_21b_vtn_id_validation(tmpdir):
    expected_event = AdrEvent(
        id="FooEvent",
        start=datetime.utcnow() + timedelta(seconds=60),
        signals=[dict(index=0, duration=timedelta(seconds=10), level=1.0)],
        status=AdrEventStatus.PENDING
    )
    db_mock = mock.MagicMock()
    event_handler = event.EventHandler(
        "VEN_ID",
        db_path=TEST_DB_ADDR % tmpdir,
        vtn_ids="Wrong_Vtn"
    )
    event_handler.db.update_event = db_mock

    reply = event_handler.handle_payload(generate_payload([expected_event]))
    assert reply.findtext(responseCode, namespaces=NS_A) == "400"
    assert reply.findtext('pyld:eiCreatedEvent/ei:eiResponse/pyld:requestID', namespaces=NS_A) == "OadrDisReq092520_152645_178"
    assert reply.findtext(venID, namespaces=NS_A) == "VEN_ID"
Beispiel #26
0
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
def test_30_start_time_randomization(tmpdir):
    """
    VEN, EiEvent Service, oadrDistributeEvent Payload
    The VEN must randomize the dtstart time of the event if a value is present
    in the startafter element. Event completion times are determined by adding
    the event duration to the randomized dtstart time. Modifications to an event
    should maintain the same random offset, unless the startafter element itself
    is modified.
    """
    test_event = AdrEvent(
        id="FooEvent",
        start=datetime.utcnow() + timedelta(minutes=10),
        signals=[dict(index=0, duration=timedelta(minutes=10), level=1.0)],
        status=AdrEventStatus.PENDING, start_after=timedelta(minutes=2)
    )
    event_handler = event.EventHandler("VEN_ID", db_path=TEST_DB_ADDR % tmpdir)

    event_handler.handle_payload(generate_payload([test_event]))

    active_event = event_handler.get_active_events()[0]
    expected_event = test_event.to_obj()
    assert active_event.start != expected_event.start
    assert (active_event.start - expected_event.start) < timedelta(minutes=2)
def test_12_response_required(response_required, tmpdir):
    """
    VEN, EiEvent Service, oadrCreatedEvent Payload
    The VEN must respond to an event in oadrDistributeEvent based upon the
    value in each event’s oadrResponseRequired element as follows:
    Always – The VEN shall respond to the event with an oadrCreatedEvent
    eventResponse . This includes unchanged, new, changed, and cancelled
    events
    Never – The VEN shall not respond to the event with a oadrCreatedEvent
    eventResponse
    Note that oadrCreatedEvent event responses SHOULD be returned in one
    message, but CAN be returned in separate messages.
    """
    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, response_required=response_required
    )
    event_handler = event.EventHandler("VEN_ID", db_path=TEST_DB_ADDR % tmpdir)
    reply = event_handler.handle_payload(generate_payload([test_event]))

    assert bool(reply) == response_required