def test_OkCommunicationProcess_run__processes_get_num_words_fifo_debug_console_command_with_one_data_frame( four_board_comm_process, ): ok_process = four_board_comm_process["ok_process"] board_queues = four_board_comm_process["board_queues"] expected_num_words = DATA_FRAME_SIZE_WORDS * DATA_FRAMES_PER_ROUND_ROBIN input_queue = board_queues[0][0] response_queue = board_queues[0][1] test_bytearray = bytearray(expected_num_words * 4) fifo = TestingQueue() put_object_into_queue_and_raise_error_if_eventually_still_empty( test_bytearray, fifo) queues = {"pipe_outs": {PIPE_OUT_FIFO: fifo}} simulator = FrontPanelSimulator(queues) simulator.initialize_board() ok_process.set_board_connection(0, simulator) expected_returned_communication = { "communication_type": "debug_console", "command": "get_num_words_fifo", } put_object_into_queue_and_raise_error_if_eventually_still_empty( copy.deepcopy(expected_returned_communication), input_queue) invoke_process_run_and_check_errors(ok_process) expected_returned_communication["response"] = expected_num_words expected_returned_communication["hex_converted_response"] = hex( expected_num_words) actual = response_queue.get(timeout=QUEUE_CHECK_TIMEOUT_SECONDS) assert actual == expected_returned_communication
def test_OkCommunicationProcess_run__processes_read_wire_out_debug_console_command( test_address, test_response, test_description, four_board_comm_process, ): ok_process = four_board_comm_process["ok_process"] board_queues = four_board_comm_process["board_queues"] input_queue = board_queues[0][0] response_queue = board_queues[0][1] wire_queue = TestingQueue() put_object_into_queue_and_raise_error_if_eventually_still_empty( test_response, wire_queue) simulator = FrontPanelSimulator({"wire_outs": {test_address: wire_queue}}) simulator.initialize_board() ok_process.set_board_connection(0, simulator) expected_returned_communication = { "communication_type": "debug_console", "command": "read_wire_out", "ep_addr": test_address, } put_object_into_queue_and_raise_error_if_eventually_still_empty( copy.deepcopy(expected_returned_communication), input_queue) invoke_process_run_and_check_errors(ok_process) expected_returned_communication["response"] = test_response expected_returned_communication["hex_converted_response"] = hex( test_response) actual = response_queue.get(timeout=QUEUE_CHECK_TIMEOUT_SECONDS) assert actual == expected_returned_communication
def test_OkCommunicationProcess_run__processes_activate_trigger_in_debug_console_command( four_board_comm_process, ): ok_process = four_board_comm_process["ok_process"] board_queues = four_board_comm_process["board_queues"] input_queue = board_queues[0][0] response_queue = board_queues[0][1] simulator = FrontPanelSimulator({}) simulator.initialize_board() ok_process.set_board_connection(0, simulator) expected_returned_communication = { "communication_type": "debug_console", "command": "activate_trigger_in", "ep_addr": 32, "bit": 0x01, } put_object_into_queue_and_raise_error_if_eventually_still_empty( copy.deepcopy(expected_returned_communication), input_queue) invoke_process_run_and_check_errors(ok_process) actual = response_queue.get(timeout=QUEUE_CHECK_TIMEOUT_SECONDS) assert actual["command"] == expected_returned_communication["command"] assert actual["ep_addr"] == expected_returned_communication["ep_addr"] assert actual["bit"] == expected_returned_communication["bit"]
def test_OkCommunicationProcess_run__processes_start_managed_acquisition_command( four_board_comm_process, ): ok_process = four_board_comm_process["ok_process"] board_queues = four_board_comm_process["board_queues"] simulator = FrontPanelSimulator({}) simulator.initialize_board() ok_process.set_board_connection(0, simulator) input_queue = board_queues[0][0] ok_comm_to_main = board_queues[0][1] expected_returned_communication: Dict[ str, Any] = get_mutable_copy_of_START_MANAGED_ACQUISITION_COMMUNICATION() input_queue.put_nowait(copy.deepcopy(expected_returned_communication)) confirm_queue_is_eventually_of_size(input_queue, 1) invoke_process_run_and_check_errors(ok_process) expected_returned_communication["timestamp"] = datetime.datetime.utcnow() actual = ok_comm_to_main.get(timeout=QUEUE_CHECK_TIMEOUT_SECONDS) assert actual == expected_returned_communication assert ok_process._is_managed_acquisition_running[0] is True # pylint:disable=protected-access board_connections = ok_process.get_board_connections_list() assert board_connections[0].is_spi_running() is True assert ok_process._is_first_managed_read[0] is True # pylint:disable=protected-access
def test_OkCommunicationProcess_run__processes_init_board_debug_console_command_when_reinitializing( four_board_comm_process, patched_firmware_folder): ok_process = four_board_comm_process["ok_process"] board_queues = four_board_comm_process["board_queues"] input_queue = board_queues[0][0] response_queue = board_queues[0][1] test_bit_file_name = patched_firmware_folder simulator = FrontPanelSimulator({}) simulator.initialize_board() ok_process.set_board_connection(0, simulator) init_command = { "communication_type": "debug_console", "command": "initialize_board", "bit_file_name": test_bit_file_name, "allow_board_reinitialization": True, } put_object_into_queue_and_raise_error_if_eventually_still_empty( copy.deepcopy(init_command), input_queue) invoke_process_run_and_check_errors(ok_process) init_response = response_queue.get(timeout=QUEUE_CHECK_TIMEOUT_SECONDS) assert init_response["command"] == "initialize_board" assert init_response["bit_file_name"] == test_bit_file_name # Tanner (5/26/20): Asserting response is None is the simplest way to assert no error was returned assert init_response["response"] is None
def test_OkCommunicationProcess__raises_and_logs_error_if_first_managed_read_does_not_contain_at_least_one_round_robin( four_board_comm_process, mocker): mocker.patch( "builtins.print", autospec=True) # don't print all the error messages to console test_bytearray = bytearray(0) ok_process = four_board_comm_process["ok_process"] board_queues = four_board_comm_process["board_queues"] ok_process._logging_level = logging.DEBUG # pylint:disable=protected-access board_queues[0][0].put_nowait( get_mutable_copy_of_START_MANAGED_ACQUISITION_COMMUNICATION()) fifo = TestingQueue() fifo.put_nowait(test_bytearray) assert is_queue_eventually_of_size( fifo, 1, timeout_seconds=QUEUE_CHECK_TIMEOUT_SECONDS) is True queues = {"pipe_outs": {PIPE_OUT_FIFO: fifo}} simulator = FrontPanelSimulator(queues) simulator.initialize_board() ok_process.set_board_connection(0, simulator) comm_to_main = board_queues[0][1] invoke_process_run_and_check_errors(ok_process) comm_to_main.get( timeout=QUEUE_CHECK_TIMEOUT_SECONDS) # pop out init log message assert is_queue_eventually_empty( comm_to_main, timeout_seconds=QUEUE_CHECK_TIMEOUT_SECONDS) is True ok_process._time_of_last_fifo_read[0] = datetime.datetime( # pylint: disable=protected-access year=2000, month=12, day=2) ok_process._timepoint_of_last_fifo_read[0] = time.perf_counter() # pylint: disable=protected-access with pytest.raises(FirstManagedReadLessThanOneRoundRobinError): invoke_process_run_and_check_errors(ok_process) assert is_queue_eventually_not_empty( comm_to_main, timeout_seconds=QUEUE_CHECK_TIMEOUT_SECONDS) is True for _ in range(4): comm_to_main.get(timeout=QUEUE_CHECK_TIMEOUT_SECONDS ) # pop out expected log messages assert (is_queue_eventually_not_empty( comm_to_main, timeout_seconds=QUEUE_CHECK_TIMEOUT_SECONDS) is True) fifo_read_msg = comm_to_main.get(timeout=QUEUE_CHECK_TIMEOUT_SECONDS) assert f"{len(test_bytearray)} bytes" in fifo_read_msg["message"] assert r"b''" in fifo_read_msg["message"] assert is_queue_eventually_not_empty( comm_to_main, timeout_seconds=QUEUE_CHECK_TIMEOUT_SECONDS) is True error_msg = comm_to_main.get(timeout=QUEUE_CHECK_TIMEOUT_SECONDS) assert "FirstManagedReadLessThanOneRoundRobinError" in error_msg["message"] assert is_queue_eventually_empty( comm_to_main, timeout_seconds=QUEUE_CHECK_TIMEOUT_SECONDS) is True
def test_OkCommunicationProcess_managed_acquisition__handles_ignoring_first_data_cycle( four_board_comm_process, ): ok_process = four_board_comm_process["ok_process"] board_queues = four_board_comm_process["board_queues"] ok_process._logging_level = logging.DEBUG # pylint:disable=protected-access board_queues[0][0].put_nowait( get_mutable_copy_of_START_MANAGED_ACQUISITION_COMMUNICATION()) fifo = TestingQueue() fifo.put_nowait(produce_data(2, 0)) assert is_queue_eventually_of_size( fifo, 1, timeout_seconds=QUEUE_CHECK_TIMEOUT_SECONDS) is True queues = {"pipe_outs": {PIPE_OUT_FIFO: fifo}} simulator = FrontPanelSimulator(queues) simulator.initialize_board() ok_process.set_board_connection(0, simulator) to_file_writer_queue = board_queues[0][2] invoke_process_run_and_check_errors(ok_process) ok_process._time_of_last_fifo_read[0] = datetime.datetime( # pylint: disable=protected-access year=2000, month=12, day=2) ok_process._timepoint_of_last_fifo_read[0] = time.perf_counter() # pylint: disable=protected-access invoke_process_run_and_check_errors(ok_process) assert ok_process._is_first_managed_read[0] is False # pylint: disable=protected-access expected_well_idx = 0 test_value_1 = (FIFO_READ_PRODUCER_DATA_OFFSET + FIFO_READ_PRODUCER_WELL_AMPLITUDE * (expected_well_idx + 1) * signal.sawtooth( (ROUND_ROBIN_PERIOD // TIMESTEP_CONVERSION_FACTOR) / FIFO_READ_PRODUCER_SAWTOOTH_PERIOD, width=0.5, ) * -1) expected_first_dict_sent = { "is_reference_sensor": False, "well_index": expected_well_idx, "data": np.array( [ [ROUND_ROBIN_PERIOD], [int(test_value_1) - RAW_TO_SIGNED_CONVERSION_VALUE], ], dtype=np.int32, ), } actual = to_file_writer_queue.get(timeout=QUEUE_CHECK_TIMEOUT_SECONDS) assert actual["is_reference_sensor"] == expected_first_dict_sent[ "is_reference_sensor"] assert actual["well_index"] == expected_first_dict_sent["well_index"] np.testing.assert_equal(actual["data"], expected_first_dict_sent["data"])
def test_execute_debug_console_command__initializes_board( patched_firmware_folder): dummy_panel = FrontPanelSimulator({}) execute_debug_console_command( dummy_panel, { "command": "initialize_board", "bit_file_name": patched_firmware_folder }, ) assert dummy_panel.is_board_initialized() is True
def test_OkCommunicationProcess_commands_for_each_run_iteration__removes_default_time_since_last_fifo_read_while_spi_not_running( ): board_queues, error_queue = generate_board_and_error_queues(num_boards=4) p = OkCommunicationProcess(board_queues, error_queue) simulator = FrontPanelSimulator({}) simulator.initialize_board() p.set_board_connection(0, simulator) p._time_of_last_fifo_read[0] = datetime.datetime.utcnow() # pylint:disable=protected-access p._timepoint_of_last_fifo_read[0] = time.perf_counter() # pylint: disable=protected-access invoke_process_run_and_check_errors(p) assert p._time_of_last_fifo_read[0] is None # pylint:disable=protected-access assert p._timepoint_of_last_fifo_read[0] is None # pylint: disable=protected-access
def test_OkCommunicationProcess_run__processes_get_status_debug_console_command_with_default_values( four_board_comm_process, ): ok_process = four_board_comm_process["ok_process"] board_queues = four_board_comm_process["board_queues"] input_queue = board_queues[0][0] response_queue = board_queues[0][1] simulator = FrontPanelSimulator({}) ok_process.set_board_connection(0, simulator) expected_returned_communication = { "communication_type": "debug_console", "command": "get_status", } put_object_into_queue_and_raise_error_if_eventually_still_empty( copy.deepcopy(expected_returned_communication), input_queue) invoke_process_run_and_check_errors(ok_process) expected_response = {} expected_response["is_spi_running"] = False expected_response["is_board_initialized"] = False expected_response["bit_file_name"] = None expected_returned_communication["response"] = expected_response actual = response_queue.get(timeout=QUEUE_CHECK_TIMEOUT_SECONDS) assert actual == expected_returned_communication
def test_OkCommunicationProcess_run__processes_set_device_id_debug_console_command( four_board_comm_process, ): ok_process = four_board_comm_process["ok_process"] board_queues = four_board_comm_process["board_queues"] input_queue = board_queues[0][0] response_queue = board_queues[0][1] expected_id = "Mantarray XEM" simulator = FrontPanelSimulator({}) ok_process.set_board_connection(0, simulator) expected_returned_communication = { "communication_type": "debug_console", "command": "set_device_id", "new_id": expected_id, } put_object_into_queue_and_raise_error_if_eventually_still_empty( copy.deepcopy(expected_returned_communication), input_queue) invoke_process_run_and_check_errors(ok_process) expected_get_communication = { "communication_type": "debug_console", "command": "get_device_id", } put_object_into_queue_and_raise_error_if_eventually_still_empty( copy.deepcopy(expected_get_communication), input_queue) invoke_process_run_and_check_errors(ok_process) actual = response_queue.get(timeout=QUEUE_CHECK_TIMEOUT_SECONDS) assert actual["command"] == expected_returned_communication["command"] assert actual["new_id"] == expected_returned_communication["new_id"] get_response = response_queue.get(timeout=QUEUE_CHECK_TIMEOUT_SECONDS) actual_id = get_response["response"] assert actual_id == expected_id
def test_OkCommunicationProcess_run__processes_comm_delay_debug_console_command( four_board_comm_process, ): ok_process = four_board_comm_process["ok_process"] board_queues = four_board_comm_process["board_queues"] input_queue = board_queues[0][0] response_queue = board_queues[0][1] simulator = FrontPanelSimulator({}) ok_process.set_board_connection(0, simulator) expected_num_millis = 20 expected_returned_communication = { "communication_type": "debug_console", "command": "comm_delay", "num_milliseconds": expected_num_millis, } put_object_into_queue_and_raise_error_if_eventually_still_empty( copy.deepcopy(expected_returned_communication), input_queue) invoke_process_run_and_check_errors(ok_process) actual = response_queue.get(timeout=QUEUE_CHECK_TIMEOUT_SECONDS) assert actual["command"] == expected_returned_communication["command"] assert actual["num_milliseconds"] == expected_returned_communication[ "num_milliseconds"] assert actual[ "response"] == f"Delayed for {expected_num_millis} milliseconds"
def test_OkCommunicationProcess_managed_acquisition__does_not_log_when_non_parsing_error_raised_with_first_round_robin( four_board_comm_process, mocker): mocker.patch( "builtins.print", autospec=True) # don't print all the error messages to console ok_process = four_board_comm_process["ok_process"] board_queues = four_board_comm_process["board_queues"] ok_process._logging_level = logging.DEBUG # pylint:disable=protected-access ok_process._data_frame_format = "fake_format" # pylint:disable=protected-access board_queues[0][0].put_nowait( get_mutable_copy_of_START_MANAGED_ACQUISITION_COMMUNICATION()) assert (is_queue_eventually_of_size( board_queues[0][0], 1, timeout_seconds=QUEUE_CHECK_TIMEOUT_SECONDS) is True) fifo = TestingQueue() fifo.put_nowait(produce_data(1, 0)) assert is_queue_eventually_of_size( fifo, 1, timeout_seconds=QUEUE_CHECK_TIMEOUT_SECONDS) is True queues = {"pipe_outs": {PIPE_OUT_FIFO: fifo}} simulator = FrontPanelSimulator(queues) simulator.initialize_board() ok_process.set_board_connection(0, simulator) comm_to_main = board_queues[0][1] invoke_process_run_and_check_errors(ok_process) comm_to_main.get( timeout=QUEUE_CHECK_TIMEOUT_SECONDS) # pop out init message assert is_queue_eventually_empty( comm_to_main, timeout_seconds=QUEUE_CHECK_TIMEOUT_SECONDS) is True ok_process._time_of_last_fifo_read[0] = datetime.datetime( # pylint: disable=protected-access year=2000, month=12, day=2) ok_process._timepoint_of_last_fifo_read[0] = time.perf_counter() # pylint: disable=protected-access with pytest.raises(UnrecognizedDataFrameFormatNameError): invoke_process_run_and_check_errors(ok_process) for _ in range(6): assert (is_queue_eventually_not_empty( comm_to_main, timeout_seconds=QUEUE_CHECK_TIMEOUT_SECONDS) is True) comm_to_main.get(timeout=QUEUE_CHECK_TIMEOUT_SECONDS ) # pop out expected log messages assert is_queue_eventually_empty( comm_to_main, timeout_seconds=QUEUE_CHECK_TIMEOUT_SECONDS) is True
def test_OkCommunicationProcess__hard_stop__hard_stops_the_RunningFIFOSimulator__for_board_0( four_board_comm_process, mocker): ok_process = four_board_comm_process["ok_process"] simulator = FrontPanelSimulator({}) # simulator.set_device_id('bob') ok_process.set_board_connection(0, simulator) spied_simulator_hard_stop = mocker.spy(simulator, "hard_stop") ok_process.hard_stop() assert spied_simulator_hard_stop.call_count == 1
def test_OkCommunicationProcess_run__raises_error_if_communication_type_is_invalid( four_board_comm_process, mocker): mocker.patch( "builtins.print", autospec=True) # don't print all the error messages to console ok_process = four_board_comm_process["ok_process"] board_queues = four_board_comm_process["board_queues"] simulator = FrontPanelSimulator({}) simulator.initialize_board() ok_process.set_board_connection(0, simulator) input_queue = board_queues[0][0] expected_returned_communication = { "communication_type": "fake_comm_type", } input_queue.put_nowait(copy.deepcopy(expected_returned_communication)) assert is_queue_eventually_not_empty(input_queue) is True with pytest.raises(UnrecognizedCommandFromMainToOkCommError, match="fake_comm_type"): invoke_process_run_and_check_errors(ok_process)
def test_OkCommunicationProcess_run__processes_stop_acquisition_debug_console_command( four_board_comm_process, ): ok_process = four_board_comm_process["ok_process"] board_queues = four_board_comm_process["board_queues"] input_queue = board_queues[0][0] response_queue = board_queues[0][1] simulator = FrontPanelSimulator({}) simulator.initialize_board() ok_process.set_board_connection(0, simulator) simulator.start_acquisition() expected_returned_communication = { "communication_type": "debug_console", "command": "stop_acquisition", } put_object_into_queue_and_raise_error_if_eventually_still_empty( copy.deepcopy(expected_returned_communication), input_queue) invoke_process_run_and_check_errors(ok_process) expected_spi_communication = { "communication_type": "debug_console", "command": "is_spi_running", } put_object_into_queue_and_raise_error_if_eventually_still_empty( copy.deepcopy(expected_spi_communication), input_queue) invoke_process_run_and_check_errors(ok_process) actual = response_queue.get(timeout=QUEUE_CHECK_TIMEOUT_SECONDS) assert actual["communication_type"] == expected_returned_communication[ "communication_type"] assert actual["command"] == expected_returned_communication["command"] expected_spi_communication["response"] = False actual_spi_response = response_queue.get( timeout=QUEUE_CHECK_TIMEOUT_SECONDS) assert actual_spi_response == expected_spi_communication
def test_OkCommunicationProcess_managed_acquisition__does_not_log_percent_use_metrics_in_first_logging_cycle( four_board_comm_process, mocker): mocker.patch.object(OkCommunicationProcess, "_is_ready_to_read_from_fifo", return_value=True) ok_process = four_board_comm_process["ok_process"] board_queues = four_board_comm_process["board_queues"] ok_process._time_of_last_fifo_read[0] = datetime.datetime( # pylint: disable=protected-access 2020, 7, 3, 9, 25, 0, 0) ok_process._timepoint_of_last_fifo_read[0] = 10 # pylint: disable=protected-access ok_process._minimum_iteration_duration_seconds = 0 # pylint: disable=protected-access fifo = TestingQueue() for _ in range(INSTRUMENT_COMM_PERFOMANCE_LOGGING_NUM_CYCLES): fifo.put_nowait(produce_data(2, 0)) confirm_queue_is_eventually_of_size( fifo, INSTRUMENT_COMM_PERFOMANCE_LOGGING_NUM_CYCLES) queues = {"pipe_outs": {PIPE_OUT_FIFO: fifo}} simulator = FrontPanelSimulator(queues) simulator.initialize_board() ok_process.set_board_connection(0, simulator) board_queues[0][0].put_nowait( get_mutable_copy_of_START_MANAGED_ACQUISITION_COMMUNICATION()) confirm_queue_is_eventually_of_size(board_queues[0][0], 1) invoke_process_run_and_check_errors( ok_process, num_iterations=INSTRUMENT_COMM_PERFOMANCE_LOGGING_NUM_CYCLES, perform_setup_before_loop=True, ) assert_queue_is_eventually_not_empty(board_queues[0][1]) queue_items = drain_queue(board_queues[0][1]) actual = queue_items[-1] assert "message" in actual assert "percent_use_metrics" not in actual["message"] # Tanner (5/29/20): Closing a queue while it is not empty (especially when very full) causes BrokePipeErrors, so flushing it before the test ends prevents this drain_queue(board_queues[0][2])
def test_OkCommunicationProcess_commands_for_each_run_iteration__does_not_send_fifo_read_to_file_writer_if_not_ready_to_read( ): board_queues, error_queue = generate_board_and_error_queues(num_boards=4) test_bytearray = bytearray(DATA_FRAME_SIZE_WORDS * 4 * DATA_FRAMES_PER_ROUND_ROBIN) test_bytearray[:8] = build_header_magic_number_bytes(HEADER_MAGIC_NUMBER) fifo = TestingQueue() fifo.put_nowait(test_bytearray) assert is_queue_eventually_of_size( fifo, 1, timeout_seconds=QUEUE_CHECK_TIMEOUT_SECONDS) is True queues = {"pipe_outs": {PIPE_OUT_FIFO: fifo}} simulator = FrontPanelSimulator(queues) simulator.initialize_board() simulator.start_acquisition() p = OkCommunicationProcess(board_queues, error_queue) p.set_board_connection(0, simulator) p._is_managed_acquisition_running[0] = True # pylint:disable=protected-access p._time_of_last_fifo_read[0] = datetime.datetime( # pylint:disable=protected-access 2020, 2, 13, 11, 43, 10, 123456) p._timepoint_of_last_fifo_read[0] = time.perf_counter() # pylint: disable=protected-access invoke_process_run_and_check_errors(p) assert (is_queue_eventually_not_empty( board_queues[0][2], timeout_seconds=QUEUE_CHECK_TIMEOUT_SECONDS) is False)
def test_OkCommunicationProcess_run__correctly_sets_mantarray_nickname_without_serial_number_present( test_device_id, test_description, four_board_comm_process): ok_process = four_board_comm_process["ok_process"] board_queues = four_board_comm_process["board_queues"] expected_nickname = "New Nickname" simulator = FrontPanelSimulator({}) simulator.set_device_id("Not a serial number") ok_process.set_board_connection(0, simulator) input_queue = board_queues[0][0] expected_returned_communication = { "communication_type": "mantarray_naming", "command": "set_mantarray_nickname", "mantarray_nickname": expected_nickname, } input_queue.put_nowait(copy.deepcopy(expected_returned_communication)) assert is_queue_eventually_not_empty(input_queue) is True invoke_process_run_and_check_errors(ok_process) actual = simulator.get_device_id() assert actual == expected_nickname
def test_OkCommunicationProcess_run__correctly_sets_mantarray_serial_number( four_board_comm_process, ): ok_process = four_board_comm_process["ok_process"] board_queues = four_board_comm_process["board_queues"] expected_serial_number = RunningFIFOSimulator.default_mantarray_serial_number simulator = FrontPanelSimulator({}) simulator.set_device_id("Existing Device ID") ok_process.set_board_connection(0, simulator) input_queue = board_queues[0][0] expected_returned_communication = { "communication_type": "mantarray_naming", "command": "set_mantarray_serial_number", "mantarray_serial_number": expected_serial_number, } input_queue.put_nowait(copy.deepcopy(expected_returned_communication)) assert is_queue_eventually_not_empty(input_queue) is True invoke_process_run_and_check_errors(ok_process) actual = simulator.get_device_id() assert actual == expected_serial_number
def test_OkCommunicationProcess_managed_acquisition__reads_at_least_one_prepopulated_simulated_fifo_read( four_board_comm_process, # mocker ): ok_process = four_board_comm_process["ok_process"] board_queues = four_board_comm_process["board_queues"] ok_process._logging_level = logging.DEBUG # pylint:disable=protected-access board_queues[0][0].put_nowait( get_mutable_copy_of_START_MANAGED_ACQUISITION_COMMUNICATION()) fifo = TestingQueue() fifo.put_nowait(produce_data(2, 0)) assert is_queue_eventually_of_size( fifo, 1, timeout_seconds=QUEUE_CHECK_TIMEOUT_SECONDS) is True queues = {"pipe_outs": {PIPE_OUT_FIFO: fifo}} simulator = FrontPanelSimulator(queues) simulator.initialize_board() ok_process.set_board_connection(0, simulator) to_main_queue = board_queues[0][1] invoke_process_run_and_check_errors(ok_process) to_main_queue.get(timeout=QUEUE_CHECK_TIMEOUT_SECONDS ) # pop out the receipt of the command assert to_main_queue.empty() ok_process._time_of_last_fifo_read[0] = datetime.datetime( # pylint: disable=protected-access year=2000, month=12, day=2) ok_process._timepoint_of_last_fifo_read[0] = time.perf_counter() # pylint: disable=protected-access invoke_process_run_and_check_errors(ok_process) words_msg = to_main_queue.get(timeout=QUEUE_CHECK_TIMEOUT_SECONDS) assert "words in the FIFO" in words_msg["message"] about_to_read_msg = to_main_queue.get(timeout=QUEUE_CHECK_TIMEOUT_SECONDS) assert "About to read from FIFO" in about_to_read_msg["message"] after_read_msg = to_main_queue.get(timeout=QUEUE_CHECK_TIMEOUT_SECONDS) assert "After reading from FIFO" in after_read_msg["message"] size_msg = to_main_queue.get(timeout=QUEUE_CHECK_TIMEOUT_SECONDS) assert "576 bytes" in size_msg["message"]
def test_execute_debug_console_command__lets_error_propagate_up_with_default_suppress_error_value( mocker, ): dummy_panel = FrontPanelSimulator({}) mocker.patch.object(dummy_panel, "initialize_board", side_effect=KeyError("side_effect_error")) with pytest.raises(KeyError, match="side_effect_error"): execute_debug_console_command( dummy_panel, { "command": "initialize_board", "bit_file_name": "main.bit" }, )
def test_execute_debug_console_command__returns_stack_trace_of_error_raised_when_attempting_to_run_command_with_suppress_error_key_True( mocker, ): dummy_panel = FrontPanelSimulator({}) mocker.patch.object(dummy_panel, "initialize_board", side_effect=KeyError("side_effect_error")) return_value = execute_debug_console_command( dummy_panel, { "command": "initialize_board", "bit_file_name": "main.bit", "suppress_error": True, }, ) assert ", in execute_debug_console_command" in return_value assert "side_effect_error" in str(return_value)
def test_OkCommunicationProcess_soft_stop_not_allowed_if_communication_from_main_still_in_queue( four_board_comm_process, patched_firmware_folder): ok_process = four_board_comm_process["ok_process"] board_queues = four_board_comm_process["board_queues"] dummy_communication = { "communication_type": "debug_console", "command": "initialize_board", "bit_file_name": patched_firmware_folder, } # The first communication will be processed, but if there is a second one in the queue then the soft stop should be disabled board_queues[0][0].put_nowait(dummy_communication) board_queues[0][0].put_nowait(dummy_communication) confirm_queue_is_eventually_of_size(board_queues[0][0], 2) simulator = FrontPanelSimulator({}) ok_process.set_board_connection(0, simulator) ok_process.soft_stop() invoke_process_run_and_check_errors(ok_process) assert ok_process.is_stopped() is False
def test_OkCommunicationProcess__hard_stop__passes_timeout_arg_to_super_hard_stop__and_front_panel_hard_stop__and_returns_value_from_super( four_board_comm_process, mocker): ok_process = four_board_comm_process["ok_process"] simulator = FrontPanelSimulator({}) ok_process.set_board_connection(0, simulator) expected_return = {"someinfo": ["list"]} mocked_parent_hard_stop = mocker.patch.object(InfiniteProcess, "hard_stop", autospec=True, return_value=expected_return) mocked_front_panel_hard_stop = mocker.patch.object(simulator, "hard_stop", autospec=True) expected_timeout = 1.1 actual_return = ok_process.hard_stop(timeout=expected_timeout) assert actual_return == expected_return mocked_parent_hard_stop.assert_called_once_with(ok_process, timeout=expected_timeout) mocked_front_panel_hard_stop.assert_called_once_with( timeout=expected_timeout)
def test_OkCommunicationProcess_run__processes_init_board_debug_console_command( running_process_with_simulated_board, patched_firmware_folder): # Tanner (8/20/21): leave running_process_with_simulated_board in this test so there is at least one test where a command from main is processed in a running instance of OkComm test_bit_file_name = patched_firmware_folder simulator = FrontPanelSimulator({}) ok_process, board_queues, error_queue = running_process_with_simulated_board( simulator).values() input_queue = board_queues[0][0] response_queue = board_queues[0][1] init_command = { "communication_type": "debug_console", "command": "initialize_board", "bit_file_name": test_bit_file_name, } input_queue.put_nowait(copy.deepcopy(init_command)) ok_process.soft_stop() ok_process.join() assert error_queue.empty() is True init_response = response_queue.get(timeout=QUEUE_CHECK_TIMEOUT_SECONDS) assert init_response["command"] == "initialize_board" assert init_response["bit_file_name"] == test_bit_file_name
def test_OkCommunicationProcess_commands_for_each_run_iteration__sets_default_time_since_last_fifo_read_if_none_while_spi_running( mocker, ): board_queues, error_queue = generate_board_and_error_queues(num_boards=4) p = OkCommunicationProcess(board_queues, error_queue) expected_timepoint = 9876 mocker.patch.object(time, "perf_counter", return_value=expected_timepoint) simulator = FrontPanelSimulator({}) simulator.initialize_board() simulator.start_acquisition() p.set_board_connection(0, simulator) p._is_managed_acquisition_running[0] = True # pylint:disable=protected-access invoke_process_run_and_check_errors(p) assert p._time_of_last_fifo_read[0] == datetime.datetime.utcnow() # pylint:disable=protected-access assert p._timepoint_of_last_fifo_read[0] == expected_timepoint # pylint:disable=protected-access
def test_OkCommunicationProcess_run__processes_read_from_fifo_debug_console_command( test_num_words_to_log, test_num_cycles_to_read, test_description, four_board_comm_process, ): ok_process = four_board_comm_process["ok_process"] board_queues = four_board_comm_process["board_queues"] input_queue = board_queues[0][0] response_queue = board_queues[0][1] test_bytearray = produce_data(test_num_cycles_to_read, 0) fifo = TestingQueue() put_object_into_queue_and_raise_error_if_eventually_still_empty( test_bytearray, fifo) queues = {"pipe_outs": {PIPE_OUT_FIFO: fifo}} simulator = FrontPanelSimulator(queues) simulator.initialize_board() ok_process.set_board_connection(0, simulator) simulator.start_acquisition() expected_returned_communication = { "communication_type": "debug_console", "command": "read_from_fifo", "num_words_to_log": test_num_words_to_log, } put_object_into_queue_and_raise_error_if_eventually_still_empty( copy.deepcopy(expected_returned_communication), input_queue) invoke_process_run_and_check_errors(ok_process) total_num_words = len(test_bytearray) // 4 test_words = struct.unpack(f"<{total_num_words}L", test_bytearray) formatted_test_words = list() num_words_to_log = min(total_num_words, test_num_words_to_log) for i in range(num_words_to_log): formatted_test_words.append(hex(test_words[i])) expected_returned_communication["response"] = formatted_test_words actual = response_queue.get(timeout=QUEUE_CHECK_TIMEOUT_SECONDS) assert actual == expected_returned_communication
def test_OkCommunicationProcess_commands_for_each_run_iteration__sends_fifo_read_to_file_writer_if_ready_to_read( ): board_queues, error_queue = generate_board_and_error_queues(num_boards=4) p = OkCommunicationProcess(board_queues, error_queue) test_bytearray = produce_data(1, 0) fifo = TestingQueue() fifo.put_nowait(test_bytearray) assert is_queue_eventually_of_size(fifo, 1) is True queues = {"pipe_outs": {PIPE_OUT_FIFO: fifo}} simulator = FrontPanelSimulator(queues) simulator.initialize_board() simulator.start_acquisition() p.set_board_connection(0, simulator) p._is_managed_acquisition_running[0] = True # pylint:disable=protected-access p._time_of_last_fifo_read[0] = datetime.datetime( # pylint:disable=protected-access 2020, 2, 13, 11, 43, 10, 123455) p._timepoint_of_last_fifo_read[0] = time.perf_counter() # pylint: disable=protected-access invoke_process_run_and_check_errors(p) expected_well_idx = 0 test_value_1 = ( FIFO_READ_PRODUCER_DATA_OFFSET + FIFO_READ_PRODUCER_WELL_AMPLITUDE * (expected_well_idx + 1) * signal.sawtooth( 0 / FIFO_READ_PRODUCER_SAWTOOTH_PERIOD, width=0.5) * -1) expected_first_dict_sent = { "is_reference_sensor": False, "well_index": expected_well_idx, "data": np.array([[0], [int(test_value_1) - RAW_TO_SIGNED_CONVERSION_VALUE]], dtype=np.int32), } actual = board_queues[0][2].get(timeout=QUEUE_CHECK_TIMEOUT_SECONDS) assert actual["is_reference_sensor"] == expected_first_dict_sent[ "is_reference_sensor"] assert actual["well_index"] == expected_first_dict_sent["well_index"] np.testing.assert_equal(actual["data"], expected_first_dict_sent["data"])
def test_OkCommunicationProcess_managed_acquisition__logs_performance_metrics_after_appropriate_number_of_read_cycles( four_board_comm_process, mocker): expected_idle_time = 1 expected_start_timepoint = 7 expected_stop_timepoint = 11 expected_latest_percent_use = 100 * ( 1 - expected_idle_time / (expected_stop_timepoint - expected_start_timepoint)) expected_percent_use_values = [40.1, 67.8, expected_latest_percent_use] expected_longest_iterations = list( range(INSTRUMENT_COMM_PERFOMANCE_LOGGING_NUM_CYCLES - 1)) test_data_parse_dur_values = [ 0 for _ in range(INSTRUMENT_COMM_PERFOMANCE_LOGGING_NUM_CYCLES * 2) ] test_read_dur_values = [ 0 for _ in range(INSTRUMENT_COMM_PERFOMANCE_LOGGING_NUM_CYCLES * 2) ] for i in range(1, INSTRUMENT_COMM_PERFOMANCE_LOGGING_NUM_CYCLES * 2, 2): test_data_parse_dur_values[i] = i test_read_dur_values[i] = i // 2 + 1 test_acquisition_values = [ 20 for _ in range(INSTRUMENT_COMM_PERFOMANCE_LOGGING_NUM_CYCLES) ] for i in range(1, INSTRUMENT_COMM_PERFOMANCE_LOGGING_NUM_CYCLES): test_acquisition_values[i] = test_acquisition_values[i - 1] + 10 * (i + 1) perf_counter_vals = list() for i in range(0, INSTRUMENT_COMM_PERFOMANCE_LOGGING_NUM_CYCLES * 2, 2): perf_counter_vals.append(test_read_dur_values[i]) perf_counter_vals.append(test_read_dur_values[i + 1]) perf_counter_vals.append(test_data_parse_dur_values[i]) perf_counter_vals.append(test_data_parse_dur_values[i + 1]) perf_counter_vals.append(test_acquisition_values[i // 2]) mocker.patch.object(time, "perf_counter", side_effect=perf_counter_vals) mocker.patch.object(time, "perf_counter_ns", return_value=expected_stop_timepoint) mocker.patch.object(OkCommunicationProcess, "_is_ready_to_read_from_fifo", return_value=True) mocker.patch.object( parallelism_framework, "calculate_iteration_time_ns", autospec=True, side_effect=expected_longest_iterations, ) ok_process = four_board_comm_process["ok_process"] board_queues = four_board_comm_process["board_queues"] ok_process._time_of_last_fifo_read[0] = datetime.datetime( # pylint: disable=protected-access 2020, 5, 28, 12, 58, 0, 0) ok_process._timepoint_of_last_fifo_read[0] = 10 # pylint: disable=protected-access ok_process._idle_iteration_time_ns = expected_idle_time # pylint: disable=protected-access ok_process._minimum_iteration_duration_seconds = 0 # pylint: disable=protected-access ok_process._start_timepoint_of_last_performance_measurement = ( # pylint: disable=protected-access expected_start_timepoint) ok_process._percent_use_values = expected_percent_use_values[:-1] # pylint: disable=protected-access test_fifo_reads = [ produce_data(i + 2, 0) for i in range(INSTRUMENT_COMM_PERFOMANCE_LOGGING_NUM_CYCLES) ] fifo = TestingQueue() for read in test_fifo_reads: fifo.put_nowait(read) confirm_queue_is_eventually_of_size( fifo, INSTRUMENT_COMM_PERFOMANCE_LOGGING_NUM_CYCLES) queues = {"pipe_outs": {PIPE_OUT_FIFO: fifo}} simulator = FrontPanelSimulator(queues) simulator.initialize_board() ok_process.set_board_connection(0, simulator) board_queues[0][0].put_nowait( get_mutable_copy_of_START_MANAGED_ACQUISITION_COMMUNICATION()) confirm_queue_is_eventually_of_size(board_queues[0][0], 1) invoke_process_run_and_check_errors( ok_process, num_iterations=INSTRUMENT_COMM_PERFOMANCE_LOGGING_NUM_CYCLES) assert_queue_is_eventually_not_empty(board_queues[0][1]) queue_items = drain_queue(board_queues[0][1]) actual = queue_items[-1] assert "message" in actual actual = actual["message"] expected_num_bytes = [len(read) for read in test_fifo_reads] expected_parsing_dur_values = [ i * 2 + 1 for i in range(INSTRUMENT_COMM_PERFOMANCE_LOGGING_NUM_CYCLES) ] expected_read_dur_values = [ i + 1 for i in range(INSTRUMENT_COMM_PERFOMANCE_LOGGING_NUM_CYCLES) ] expected_acquisition_values = [ 10 * (i + 1) for i in range(INSTRUMENT_COMM_PERFOMANCE_LOGGING_NUM_CYCLES) ] assert actual["communication_type"] == "performance_metrics" assert "idle_iteration_time_ns" not in actual assert "start_timepoint_of_measurements" not in actual assert actual["fifo_read_num_bytes"] == { "max": max(expected_num_bytes), "min": min(expected_num_bytes), "stdev": round(stdev(expected_num_bytes), 6), "mean": round(sum(expected_num_bytes) / len(expected_num_bytes), 6), } assert actual["fifo_read_duration"] == { "max": max(expected_read_dur_values), "min": min(expected_read_dur_values), "stdev": round(stdev(expected_read_dur_values), 6), "mean": round( sum(expected_read_dur_values) / len(expected_read_dur_values), 6), } assert actual["duration_between_acquisition"] == { "max": max(expected_acquisition_values), "min": min(expected_acquisition_values), "stdev": round(stdev(expected_acquisition_values), 6), "mean": round( sum(expected_acquisition_values) / len(expected_acquisition_values), 6), } assert actual["data_parsing_duration"] == { "max": max(expected_parsing_dur_values), "min": min(expected_parsing_dur_values), "stdev": round(stdev(expected_parsing_dur_values), 6), "mean": round( sum(expected_parsing_dur_values) / len(expected_parsing_dur_values), 6), } assert actual["percent_use"] == expected_latest_percent_use assert actual["percent_use_metrics"] == { "max": max(expected_percent_use_values), "min": min(expected_percent_use_values), "stdev": round(stdev(expected_percent_use_values), 6), "mean": round( sum(expected_percent_use_values) / len(expected_percent_use_values), 6), } num_longest_iterations = ok_process.num_longest_iterations assert actual["longest_iterations"] == expected_longest_iterations[ -num_longest_iterations:] # Tanner (5/29/20): Closing a queue while it is not empty (especially when very full) causes BrokePipeErrors, so flushing it before the test ends prevents this drain_queue(board_queues[0][2])