def test_forwarder_sends_pv_updates_single_pv_string(docker_compose): """ Test the forwarder pushes new PV value when the value is updated. :param docker_compose: Test fixture :return: None """ data_topic = "TEST_forwarderData_string_pv_update" pvs = [PVSTR] prod = ProducerWrapper("localhost:9092", CONFIG_TOPIC, data_topic) prod.add_config(pvs) # Wait for config to be pushed sleep(2) cons = create_consumer() # Update value change_pv_value(PVSTR, "stop") # Wait for PV to be updated sleep(5) cons.subscribe([data_topic]) # Poll for empty update - initial value of PVSTR is nothing poll_for_valid_message(cons) # Poll for message which should contain forwarded PV update data_msg = poll_for_valid_message(cons) check_expected_values(data_msg, Value.String, PVSTR, b'stop') cons.close()
def test_forwarder_sends_pv_updates_single_pv_double(docker_compose): """ Test the forwarder pushes new PV value when the value is updated. :param docker_compose: Test fixture :return: None """ data_topic = "TEST_forwarderData_double_pv_update" pvs = [PVDOUBLE] prod = ProducerWrapper("localhost:9092", CONFIG_TOPIC, data_topic) prod.add_config(pvs) # Wait for config to be pushed sleep(2) cons = create_consumer() cons.subscribe([data_topic]) # Update value change_pv_value(PVDOUBLE, 5) # Wait for PV to be updated sleep(5) first_msg = poll_for_valid_message(cons) check_expected_values(first_msg, Value.Double, PVDOUBLE, 0.0) second_msg = poll_for_valid_message(cons) check_expected_values(second_msg, Value.Double, PVDOUBLE, 5.0) cons.close()
def test_forwarder_sends_pv_updates_single_pv_enum(docker_compose): """ Test the forwarder pushes new PV value when the value is updated. NOTE: Enums are converted to Ints in the forwarder. :param docker_compose: Test fixture :return: None """ data_topic = "TEST_forwarderData_enum_pv_update" pvs = [PVENUM] prod = ProducerWrapper("localhost:9092", CONFIG_TOPIC, data_topic) prod.add_config(pvs) # Wait for config to be pushed sleep(5) cons = create_consumer() # Update value change_pv_value(PVENUM, "START") # Wait for PV to be updated sleep(5) cons.subscribe([data_topic]) first_msg = poll_for_valid_message(cons) check_expected_values(first_msg, Value.Int, PVENUM, 0) second_msg = poll_for_valid_message(cons) check_expected_values(second_msg, Value.Int, PVENUM, 1) cons.close()
def test_forwarder_sends_pv_updates_single_pv_long(docker_compose): """ Test the forwarder pushes new PV value when the value is updated. NOTE: longs are converted to ints in the forwarder as they will fit in a 32 bit integer :param docker_compose: Test fixture :return: None """ data_topic = "TEST_forwarderData_long_pv_update" pvs = [PVLONG] prod = ProducerWrapper("localhost:9092", CONFIG_TOPIC, data_topic) prod.add_config(pvs) # Wait for config to be pushed sleep(2) cons = create_consumer() # Set initial PV value change_pv_value(PVLONG, 0) sleep(2) # Update value change_pv_value(PVLONG, 5) # Wait for PV to be updated sleep(2) cons.subscribe([data_topic]) first_msg = poll_for_valid_message(cons) check_expected_values(first_msg, Value.Int, PVLONG, 0) second_msg = poll_for_valid_message(cons) check_expected_values(second_msg, Value.Int, PVLONG, 5) cons.close()
def test_forwarder_sends_pv_updates_single_pv_enum(docker_compose_no_command, start_ioc): """ GIVEN PV of enum type is configured to be forwarded WHEN PV value is updated THEN Forwarder publishes the update to Kafka NOTE: Enums are converted to Ints in the forwarder. """ data_topic = "TEST_forwarderData_enum_pv_update" pvs = [PVENUM] prod = ProducerWrapper("localhost:9092", CONFIG_TOPIC, data_topic) prod.add_config(pvs) # Wait for config to be pushed sleep(5) cons = create_consumer() # Update value change_pv_value(PVENUM, "START") # Wait for PV to be updated cons.subscribe([data_topic]) sleep(5) first_msg, _ = poll_for_valid_message(cons) check_expected_values(first_msg, Value.Int, PVENUM, 0) second_msg, _ = poll_for_valid_message(cons) check_expected_values(second_msg, Value.Int, PVENUM, 1) cons.close()
def test_forwarder_sends_fake_pv_updates(docker_compose_fake_epics): # A fake PV is defined in the config json file with channel name "FakePV" consumer = create_consumer() data_topic = "TEST_forward_fake_generated_pvs" consumer.subscribe([data_topic]) sleep(5) msg = poll_for_valid_message(consumer) # We should see PV updates in Kafka despite there being no IOC running check_expected_values(msg, Value.Value.Double, "FakePV")
def test_forwarder_sends_idle_pv_updates(docker_compose_idle_updates): consumer = create_consumer() data_topic = "TEST_forwarderData_idle_updates" consumer.subscribe([data_topic]) sleep(10) for i in range(3): msg = poll_for_valid_message(consumer) check_expected_values(msg, Value.Value.Double, PVDOUBLE, 0) consumer.close()
def test_forwarder_does_not_send_pv_update_more_than_once_when_periodic_update_is_used( docker_compose_idle_updates_long_period): consumer = create_consumer() data_topic = "TEST_forwarderData_long_idle_updates" consumer.subscribe([data_topic]) sleep(3) msg = poll_for_valid_message(consumer) check_expected_values(msg, Value.Value.Double, PVDOUBLE, 0) with raises(MsgErrorException): # AssertionError because there are no more messages to poll poll_for_valid_message(consumer)
def test_long_run(docker_compose_lr, start_ioc): """ Test that the channel defined in the config file is created. :param docker_compose: Test fixture :return: None """ # Set up consumer now and subscribe from earliest offset on data topic cons = create_consumer("earliest") cons.subscribe(["TEST_forwarderDataLR"]) with open(os.path.join("logs", "forwarder_lr_stats.log"), "w+") as stats_file: with open(os.path.join("logs", "forwarder_lr_missedupdates.log"), "w+") as file: for i in range(5150): # minimum 12 hours with 4 second sleep time # Change pv value now change_pv_value(PVDOUBLE, i) # Wait for the forwarder to push the update sleep(3) try: msg, _ = poll_for_valid_message(cons) except MsgErrorException: sleep(3) msg, _ = poll_for_valid_message(cons) try: check_expected_values(msg, Value.Double, PVDOUBLE, float(i)) except AssertionError: # Message is either incorrect or empty - log expected value to file file.write(str(i) + "\n") container = False # Report stats every 10th iteration if i % 10 == 0: client = docker.from_env() for item in client.containers.list(): if "forwarder" in item.name: container = item break if container: stats_file.write("{}\t{}\n".format( datetime.now(), container.stats( stream=False)["memory_stats"]["usage"], ))
def test_config_file_channel_created_correctly(docker_compose): """ Test that the channel defined in the config file is created. :param docker_compose: Test fixture :return: None """ cons = create_consumer() cons.subscribe(['TEST_forwarderData_pv_from_config']) sleep(5) # Change the PV value, so something is forwarded change_pv_value(PVDOUBLE, 10) # Wait for PV to be updated sleep(5) # Check the initial value is forwarded first_msg = poll_for_valid_message(cons) check_expected_values(first_msg, Value.Double, PVDOUBLE, 0.0) # Check the new value is forwarded second_msg = poll_for_valid_message(cons) check_expected_values(second_msg, Value.Double, PVDOUBLE, 10.0) cons.close()