def test_update_handlers_can_be_removed_by_name_and_schema(update_handlers, ): status_reporter = StubStatusReporter() producer = FakeProducer() schema_1 = "f142" schema_2 = "tdct" channel_name_1 = "channel_1" channel_name_2 = "channel_2" test_channel_3 = Channel(channel_name_2, EpicsProtocol.NONE, None, schema_1) update_handlers[Channel(channel_name_1, EpicsProtocol.NONE, None, schema_1)] = StubUpdateHandler() # type: ignore update_handlers[Channel(channel_name_2, EpicsProtocol.NONE, None, schema_2)] = StubUpdateHandler() # type: ignore update_handlers[test_channel_3] = StubUpdateHandler() # type: ignore # Only the handler with the channel matching provided name AND schema should be removed config_update = ConfigUpdate( CommandType.REMOVE, (test_channel_3, ), ) handle_configuration_change(config_update, 20000, None, update_handlers, producer, None, None, _logger, status_reporter) # type: ignore assert len(update_handlers) == 2 assert test_channel_3 not in update_handlers.keys()
def test_update_handlers_can_be_removed_by_topic(update_handlers, ): status_reporter = StubStatusReporter() producer = FakeProducer() topic_name_1 = "topic_1" topic_name_2 = "topic_2" update_handlers[Channel("", EpicsProtocol.NONE, topic_name_1, None)] = StubUpdateHandler() # type: ignore update_handlers[Channel("", EpicsProtocol.NONE, topic_name_2, None)] = StubUpdateHandler() # type: ignore update_handlers[Channel("", EpicsProtocol.NONE, topic_name_1, None)] = StubUpdateHandler() # type: ignore config_update = ConfigUpdate( CommandType.REMOVE, (Channel(None, EpicsProtocol.NONE, topic_name_1, None), ), ) handle_configuration_change(config_update, 20000, None, update_handlers, producer, None, None, _logger, status_reporter) # type: ignore assert len(update_handlers) == 1 assert ( list(update_handlers.keys())[0].output_topic == topic_name_2 ), "Expected handlers for topic_1 to have been removed, leaving only one for topic_2"
def test_update_handlers_can_be_removed_by_schema(update_handlers, ): status_reporter = StubStatusReporter() producer = FakeProducer() schema_1 = "f142" schema_2 = "tdct" update_handlers[Channel("", EpicsProtocol.NONE, "", schema_1)] = StubUpdateHandler() # type: ignore update_handlers[Channel("", EpicsProtocol.NONE, "", schema_2)] = StubUpdateHandler() # type: ignore update_handlers[Channel("", EpicsProtocol.NONE, "", schema_1)] = StubUpdateHandler() # type: ignore config_update = ConfigUpdate( CommandType.REMOVE, (Channel(None, EpicsProtocol.NONE, None, schema_1), ), ) handle_configuration_change(config_update, 20000, None, update_handlers, producer, None, None, _logger, status_reporter) # type: ignore assert len(update_handlers) == 1 assert ( list(update_handlers.keys())[0].schema == schema_2 ), "Expected handlers for schema_1 to have been removed, leaving only one for schema_2"
def test_when_update_handlers_exist_their_channel_names_are_reported_in_status( ): test_channel_name_1 = "test_channel_name_1" test_channel_name_2 = "test_channel_name_2" # Normally the values in this dictionary are the update handler objects # but the StatusReporter only uses the keys update_handlers = { Channel(test_channel_name_1, EpicsProtocol.NONE, None, None): 1, Channel(test_channel_name_2, EpicsProtocol.NONE, None, None): 2, } fake_producer = FakeProducer() status_reporter = StatusReporter(update_handlers, fake_producer, "status_topic", "", "version", logger) # type: ignore status_reporter.report_status() if fake_producer.published_payload is not None: deserialised_payload = deserialise_x5f2( fake_producer.published_payload) produced_status_message = json.loads(deserialised_payload.status_json) # Using set comprehension as order is unimportant assert { stream["channel_name"] for stream in produced_status_message["streams"] } == { test_channel_name_1, test_channel_name_2, }, "Expected channel names for existing update handlers to be reported in the status message"
def test_identical_configurations_are_not_added(update_handlers, ): status_reporter = StubStatusReporter() producer = FakeProducer() channel_name = "test_channel" test_channel_1 = Channel(channel_name, EpicsProtocol.FAKE, "output_topic", "f142") test_channel_2 = Channel(channel_name, EpicsProtocol.FAKE, "output_topic", "f142") test_channel_3 = Channel(channel_name, EpicsProtocol.FAKE, "output_topic", "f142") config_update = ConfigUpdate( CommandType.ADD, ( test_channel_1, test_channel_2, test_channel_3, ), ) handle_configuration_change(config_update, 20000, None, update_handlers, producer, None, None, _logger, status_reporter) # type: ignore assert ( len(update_handlers) == 1 ), "Only expect one channel to be added as others requested were identical" assert test_channel_1 in update_handlers.keys()
def test_configuration_stored_when_channels_added(update_handlers, ): status_reporter = StubStatusReporter() producer = FakeProducer() channel_name = "test_channel" test_channel_1 = Channel(channel_name, EpicsProtocol.FAKE, "output_topic", "f142") test_channel_2 = Channel(channel_name, EpicsProtocol.FAKE, "output_topic", "f142") test_channel_3 = Channel(channel_name, EpicsProtocol.FAKE, "output_topic", "f142") config_update = ConfigUpdate( CommandType.ADD, ( test_channel_1, test_channel_2, test_channel_3, ), ) config_store = mock.create_autospec(ConfigurationStore) handle_configuration_change(config_update, 20000, None, update_handlers, producer, None, None, _logger, status_reporter, config_store) # type: ignore config_store.save_configuration.assert_called_once()
def test_can_add_multiple_channels_with_same_name_if_protocol_topic_or_schema_are_different( update_handlers, ): status_reporter = StubStatusReporter() producer = FakeProducer() channel_name = "test_channel" test_channel_1 = Channel(channel_name, EpicsProtocol.FAKE, "output_topic", "f142") test_channel_2 = Channel(channel_name, EpicsProtocol.FAKE, "output_topic_2", "f142") test_channel_3 = Channel(channel_name, EpicsProtocol.FAKE, "output_topic", "tdct") config_update = ConfigUpdate( CommandType.ADD, ( test_channel_1, test_channel_2, test_channel_3, ), ) handle_configuration_change(config_update, 20000, None, update_handlers, producer, None, None, _logger, status_reporter) # type: ignore assert len(update_handlers) == 3 assert test_channel_1 in update_handlers.keys() assert test_channel_2 in update_handlers.keys() assert test_channel_3 in update_handlers.keys()
def test_wildcard_cannot_be_used_to_remove_channels_by_schema( update_handlers, ): # No wildcard matching on schemas because ? and * are allowed characters in schema identifiers status_reporter = StubStatusReporter() producer = FakeProducer() test_channel_3 = Channel("channel_3", EpicsProtocol.NONE, "topic_3", "f142") update_handlers[Channel("channel_1", EpicsProtocol.NONE, "topic_1", "f142")] = StubUpdateHandler() # type: ignore update_handlers[Channel("channel_2", EpicsProtocol.NONE, "topic_2", "f142")] = StubUpdateHandler() # type: ignore update_handlers[test_channel_3] = StubUpdateHandler() # type: ignore config_update = ConfigUpdate( CommandType.REMOVE, (Channel(None, EpicsProtocol.NONE, None, "f?42"), ), ) handle_configuration_change(config_update, 20000, None, update_handlers, producer, None, None, _logger, status_reporter) # type: ignore assert ( len(update_handlers) == 3 ), "Expected no channels to be removed as ? is not treated as a wildcard when matching schemas"
def test_create_update_handler_throws_if_channel_has_no_schema(): producer = FakeProducer() channel_with_no_topic = Channel("name", EpicsProtocol.PVA, "output_topic", None) with pytest.raises(RuntimeError): create_update_handler(producer, None, None, channel_with_no_topic, 20000) # type: ignore channel_with_empty_topic = Channel("name", EpicsProtocol.PVA, "output_topic", "") with pytest.raises(RuntimeError): create_update_handler(producer, None, None, channel_with_empty_topic, 20000) # type: ignore
def test_all_update_handlers_are_removed_when_removeall_config_update_is_handled( update_handlers, ): status_reporter = StubStatusReporter() producer = FakeProducer() config_update = ConfigUpdate(CommandType.REMOVE_ALL, None) update_handlers[Channel("test_channel_1", EpicsProtocol.NONE, None, None)] = StubUpdateHandler() # type: ignore update_handlers[Channel("test_channel_2", EpicsProtocol.NONE, None, None)] = StubUpdateHandler() # type: ignore handle_configuration_change(config_update, 20000, None, update_handlers, producer, None, None, _logger, status_reporter) # type: ignore assert not update_handlers
def test_create_update_handler_throws_if_protocol_not_specified(): producer = FakeProducer() channel_with_no_protocol = Channel( "name", EpicsProtocol.NONE, "output_topic", "f142" ) with pytest.raises(RuntimeError): create_update_handler(producer, None, None, channel_with_no_protocol, 20000) # type: ignore
def test_pva_handler_created_when_pva_protocol_specified(): producer = FakeProducer() context = FakePVAContext() channel_with_pva_protocol = Channel( "name", EpicsProtocol.PVA, "output_topic", "f142" ) handler = create_update_handler(producer, None, context, channel_with_pva_protocol, 20000) # type: ignore assert isinstance(handler, PVAUpdateHandler)
def test_update_handlers_are_removed_when_remove_config_update_is_handled( update_handlers, ): status_reporter = StubStatusReporter() producer = FakeProducer() channel_name_1 = "test_channel_1" channel_name_2 = "test_channel_2" config_update = ConfigUpdate( CommandType.REMOVE, (Channel(channel_name_1, EpicsProtocol.NONE, None, None), ), ) update_handlers[Channel(channel_name_1, EpicsProtocol.NONE, None, None)] = StubUpdateHandler() # type: ignore update_handlers[Channel(channel_name_2, EpicsProtocol.NONE, None, None)] = StubUpdateHandler() # type: ignore handle_configuration_change(config_update, 20000, None, update_handlers, producer, None, None, _logger, status_reporter) # type: ignore assert len(update_handlers) == 1 assert channel_name_2 in _get_channel_names( update_handlers ), "Expected handler for channel_name_1 to have been removed, leaving only channel_name_2"
def test_multicharacter_wildcard_can_be_used_to_remove_channels_by_name( update_handlers, ): status_reporter = StubStatusReporter() producer = FakeProducer() test_channel_3 = Channel("channel_3", EpicsProtocol.NONE, "topic_3", None) update_handlers[Channel("first_channel", EpicsProtocol.NONE, "topic2", None)] = StubUpdateHandler() # type: ignore update_handlers[Channel("second_channel", EpicsProtocol.NONE, "topic 1", None)] = StubUpdateHandler() # type: ignore update_handlers[test_channel_3] = StubUpdateHandler() # type: ignore config_update = ConfigUpdate( CommandType.REMOVE, (Channel("*_channel", EpicsProtocol.NONE, None, None), ), ) handle_configuration_change(config_update, 20000, None, update_handlers, producer, None, None, _logger, status_reporter) # type: ignore assert len(update_handlers) == 1 assert test_channel_3 in update_handlers.keys()
def test_update_handlers_are_added_when_add_config_update_is_handled( update_handlers): status_reporter = StubStatusReporter() producer = FakeProducer() channel_name_1 = "test_channel_1" channel_name_2 = "test_channel_2" config_update = ConfigUpdate( CommandType.ADD, ( Channel(channel_name_1, EpicsProtocol.FAKE, "output_topic", "f142"), Channel(channel_name_2, EpicsProtocol.FAKE, "output_topic", "f142"), ), ) handle_configuration_change(config_update, 20000, None, update_handlers, producer, None, None, _logger, status_reporter) # type: ignore assert len(update_handlers) == 2 assert channel_name_1 in _get_channel_names(update_handlers) assert channel_name_2 in _get_channel_names(update_handlers)
def test_no_change_to_update_handlers_when_malformed_config_update_handled( update_handlers, ): status_reporter = StubStatusReporter() producer = FakeProducer() config_update = ConfigUpdate(CommandType.MALFORMED, None) existing_channel_name = "test_channel" update_handlers[Channel(existing_channel_name, EpicsProtocol.NONE, None, None)] = StubUpdateHandler() # type: ignore handle_configuration_change(config_update, 20000, None, update_handlers, producer, None, None, _logger, status_reporter) # type: ignore assert len(update_handlers) == 1 assert existing_channel_name in _get_channel_names(update_handlers)
def test_configuration_not_stored_when_command_is_malformed(update_handlers, ): status_reporter = StubStatusReporter() producer = FakeProducer() test_channel_1 = Channel("test_channel", EpicsProtocol.FAKE, "output_topic", "f142") update_handlers[test_channel_1] = StubUpdateHandler() # type: ignore config_update = ConfigUpdate( CommandType.MALFORMED, None, ) config_store = mock.create_autospec(ConfigurationStore) handle_configuration_change(config_update, 20000, None, update_handlers, producer, None, None, _logger, status_reporter, config_store) # type: ignore config_store.save_configuration.assert_not_called()
) from streaming_data_types.fbschemas.forwarder_config_update_rf5k.UpdateType import ( UpdateType, ) from forwarder.parse_config_update import ( parse_config_update, config_change_to_command_type, ) from forwarder.configuration_store import ConfigurationStore from forwarder.parse_config_update import Channel, EpicsProtocol from tests.kafka.fake_producer import FakeProducer DUMMY_UPDATE_HANDLER = None CHANNELS_TO_STORE = { Channel("channel1", EpicsProtocol.PVA, "topic1", "f142"): DUMMY_UPDATE_HANDLER, Channel("channel2", EpicsProtocol.CA, "topic2", "tdct"): DUMMY_UPDATE_HANDLER, } STREAMS_TO_RETRIEVE = [ StreamInfo( channel.name, channel.schema, channel.output_topic, Protocol.Protocol.PVA if channel.protocol == EpicsProtocol.PVA else Protocol.Protocol.CA, ) for channel in CHANNELS_TO_STORE.keys() ]