def test_McCommunicationProcess__handles_barcode_found( test_barcode, expected_valid_flag, four_board_mc_comm_process_no_handshake, mantarray_mc_simulator_no_beacon, ): mc_process = four_board_mc_comm_process_no_handshake["mc_process"] simulator = mantarray_mc_simulator_no_beacon["simulator"] testing_queue = mantarray_mc_simulator_no_beacon["testing_queue"] set_connection_and_register_simulator( four_board_mc_comm_process_no_handshake, mantarray_mc_simulator_no_beacon) to_main_queue = four_board_mc_comm_process_no_handshake["board_queues"][0][ 1] # send plate event packet from simulator plate_event_packet = create_data_packet( randint(0, SERIAL_COMM_MAX_TIMESTAMP_VALUE), SERIAL_COMM_MAIN_MODULE_ID, SERIAL_COMM_BARCODE_FOUND_PACKET_TYPE, bytes(test_barcode, encoding="ascii"), ) put_object_into_queue_and_raise_error_if_eventually_still_empty( { "command": "add_read_bytes", "read_bytes": plate_event_packet }, testing_queue, ) invoke_process_run_and_check_errors(simulator) # process plate event packet and send barcode comm to main invoke_process_run_and_check_errors(mc_process) confirm_queue_is_eventually_of_size(to_main_queue, 1) # check that comm was sent correctly expected_barcode_comm = { "communication_type": "barcode_comm", "board_idx": 0, "barcode": test_barcode, "valid": expected_valid_flag, } actual = to_main_queue.get(timeout=QUEUE_CHECK_TIMEOUT_SECONDS) assert actual == expected_barcode_comm
def test_OkCommunicationProcess_boot_up_instrument__with_real_board__does_not_raise_error_if_firmware_version_matches_file_name( four_board_comm_process, patched_firmware_folder, mocker, ): ok_process = four_board_comm_process["ok_process"] board_queues = four_board_comm_process["board_queues"] dummy_xem = okCFrontPanel() mocker.patch.object(dummy_xem, "ConfigureFPGA", autospec=True, return_value=0) mocker.patch.object(dummy_xem, "IsFrontPanelEnabled", autospec=True, return_value=True) fp_board = MantarrayFrontPanel(dummy_xem) expected_wire_out_version = "2.3.4" mocker.patch.object( fp_board, "get_firmware_version", autospec=True, return_value=expected_wire_out_version, ) ok_process.set_board_connection(0, fp_board) boot_up_comm = { "communication_type": "boot_up_instrument", "command": "initialize_board", "bit_file_name": patched_firmware_folder, "suppress_error": False, "allow_board_reinitialization": False, } board_queues[0][0].put_nowait(boot_up_comm) assert is_queue_eventually_not_empty(board_queues[0][0]) is True invoke_process_run_and_check_errors(ok_process) assert is_queue_eventually_not_empty(board_queues[0][1]) is True response_comm = board_queues[0][1].get(timeout=QUEUE_CHECK_TIMEOUT_SECONDS) assert response_comm["main_firmware_version"] == expected_wire_out_version
def test_McCommunicationProcess_setup_before_loop__does_not_send_message_to_main_when_setup_comm_is_suppressed( mocker, ): # mock this so the process priority isn't changed during unit tests mocker.patch.object(mc_comm, "set_this_process_high_priority", autospec=True) board_queues, error_queue = generate_board_and_error_queues(num_boards=4) mc_process = McCommunicationProcess(board_queues, error_queue, suppress_setup_communication_to_main=True) mocked_create_connections = mocker.patch.object( mc_process, "create_connections_to_all_available_boards", autospec=True ) invoke_process_run_and_check_errors(mc_process, perform_setup_before_loop=True) mocked_create_connections.assert_called_once() # Other parts of the process after setup may or may not send messages to main, so drain queue and make sure none of the items (if present) have a setup message to_main_queue_items = drain_queue(board_queues[0][1]) for item in to_main_queue_items: if "message" in item: assert "Microcontroller Communication Process initiated" not in item["message"]
def test_FileWriterProcess__updates_customer_settings_and_responds_to_main_queue( four_board_file_writer_process, mocker): file_writer_process = four_board_file_writer_process["fw_process"] from_main_queue = four_board_file_writer_process["from_main_queue"] to_main_queue = four_board_file_writer_process["to_main_queue"] this_command = copy.deepcopy(GENERIC_UPDATE_CUSTOMER_SETTINGS) put_object_into_queue_and_raise_error_if_eventually_still_empty( this_command, from_main_queue) confirm_queue_is_eventually_of_size(from_main_queue, 1) invoke_process_run_and_check_errors(file_writer_process) assert file_writer_process.get_customer_settings( ) == GENERIC_UPDATE_CUSTOMER_SETTINGS["config_settings"] command_response = to_main_queue.get(timeout=QUEUE_CHECK_TIMEOUT_SECONDS) assert command_response == { "communication_type": "command_receipt", "command": "update_customer_settings", }
def test_MantarrayProcessesMonitor__check_and_handle_server_to_main_queue__raises_error_if_unrecognized_command( test_comm_type, test_description, test_process_manager_creator, test_monitor, mocker, patch_print): test_process_manager = test_process_manager_creator( use_testing_queues=True) monitor_thread, *_ = test_monitor(test_process_manager) server_to_main_queue = (test_process_manager.queue_container(). get_communication_queue_from_server_to_main()) expected_command = "bad_command" expected_comm = { "communication_type": test_comm_type, "command": expected_command, } put_object_into_queue_and_raise_error_if_eventually_still_empty( expected_comm, server_to_main_queue) with pytest.raises(UnrecognizedCommandFromServerToMainError, match=expected_command): invoke_process_run_and_check_errors(monitor_thread)
def test_FIFOReadProducer__increments_sample_idx_by_correct_number_of_round_robin_periods_each_iteration( mocker, ): data_out_queue = queue.Queue() error_queue = queue.Queue() producer_thread = FIFOReadProducer(data_out_queue, error_queue, threading.Lock()) assert producer_thread._sample_index == 0 # pylint: disable=protected-access expected_num_cycles = 21 expected_cms_of_data = expected_num_cycles * ROUND_ROBIN_PERIOD mocker.patch.object(fifo_read_producer, "_get_cms_since_last_data_packet", side_effect=[expected_cms_of_data]) invoke_process_run_and_check_errors(producer_thread) assert (producer_thread._sample_index * TIMESTEP_CONVERSION_FACTOR # pylint: disable=protected-access == expected_cms_of_data) # clean up the queues to avoid BrokenPipe errors producer_thread.hard_stop()
def test_OkCommunicationProcess__sends_message_to_main_if_valid_barcode_received_after_first_attempt__and_stops_scan_process( test_barcode, expected_barcode, test_description, four_board_comm_process, mocker, test_barcode_simulator, ): mocker.patch.object( ok_comm, "_get_dur_since_barcode_clear", autospec=True, return_value=BARCODE_GET_SCAN_WAIT_SECONDS, ) ok_process = four_board_comm_process["ok_process"] board_queues = four_board_comm_process["board_queues"] input_queue = board_queues[0][0] to_main_queue = board_queues[0][1] simulator, mocked_get = test_barcode_simulator(test_barcode) ok_process.set_board_connection(0, simulator) put_object_into_queue_and_raise_error_if_eventually_still_empty( RUN_BARCODE_SCAN_COMMUNICATION, input_queue) invoke_process_run_and_check_errors(ok_process) mocked_get.assert_called_once() confirm_queue_is_eventually_of_size(to_main_queue, 1) expected_barcode_comm = { "communication_type": "barcode_comm", "barcode": expected_barcode, "board_idx": 0, "valid": True, } actual = to_main_queue.get(timeout=QUEUE_CHECK_TIMEOUT_SECONDS) assert actual == expected_barcode_comm invoke_process_run_and_check_errors(ok_process) mocked_get.assert_called_once()
def test_MantarrayProcessesMonitor__check_and_handle_server_to_main_queue__handles_update_shared_values_by_updating_shared_values_dictionary__and_overriding_existing_value( test_process_manager_creator, test_monitor): test_process_manager = test_process_manager_creator( use_testing_queues=True) monitor_thread, shared_values_dict, *_ = test_monitor(test_process_manager) server_to_main_queue = (test_process_manager.queue_container(). get_communication_queue_from_server_to_main()) new_id = UUID("e7744225-c41c-4bd5-9e32-e79716cc8f40") new_account_id = "new_ai" new_pass_key = "new_pw" shared_values_dict["config_settings"] = { "user_account_id": UUID("e623b13c-05a5-41f2-8526-c2eba8e78e7f") } shared_values_dict["customer_creds"] = { "customer_account_id": "old_ai", "customer_pass_key": "old_pw" } communication = { "communication_type": "update_customer_settings", "content": { "config_settings": { "user_account_id": new_id, "customer_account_id": new_account_id, "customer_pass_key": new_pass_key, } }, } put_object_into_queue_and_raise_error_if_eventually_still_empty( communication, server_to_main_queue) invoke_process_run_and_check_errors(monitor_thread) confirm_queue_is_eventually_empty(server_to_main_queue) assert shared_values_dict["config_settings"]["user_account_id"] == new_id assert shared_values_dict["customer_creds"] == { "customer_account_id": new_account_id, "customer_pass_key": new_pass_key, }
def test_FileWriterProcess__exits_status_function_correctly_when_newly_failed_files_passes_and_auto_delete_is_true_or_false( four_board_file_writer_process, auto_delete, mocker): file_writer_process = four_board_file_writer_process["fw_process"] from_main_queue = four_board_file_writer_process["from_main_queue"] this_command = copy.deepcopy(GENERIC_UPDATE_CUSTOMER_SETTINGS) put_object_into_queue_and_raise_error_if_eventually_still_empty( this_command, from_main_queue) invoke_process_run_and_check_errors(file_writer_process) mocked_rmdir = mocker.patch.object(os, "rmdir", autospec=True) mocker.patch.object(os, "listdir", autospec=True) mocked_thread = mocker.patch.object(worker_thread, "ErrorCatchingThread", autospec=True) mocker.patch.object(mocked_thread.name, "is_alive", autospec=True, return_value=False) mocker.patch.object(mocked_thread.name, "errors", autospec=True, return_value=False) mocker.patch.object(mocked_thread.name, "join", autospec=True) thread_dict = { "failed_upload": False, "customer_account_id": "test_customer_id", "user_account_id": "test_user", "thread": mocked_thread.name, "auto_delete": auto_delete, "file_name": "test_filename", } file_writer_process.get_upload_threads_container().append(thread_dict) file_writer_process._check_upload_statuses() # pylint: disable=protected-access assert mocked_rmdir.call_count == int(auto_delete) assert len(file_writer_process.get_upload_threads_container()) == 0
def test_McCommunicationProcess__logs_status_codes_from_handshake_responses( four_board_mc_comm_process, mantarray_mc_simulator_no_beacon, ): mc_process = four_board_mc_comm_process["mc_process"] output_queue = four_board_mc_comm_process["board_queues"][0][1] simulator = mantarray_mc_simulator_no_beacon["simulator"] testing_queue = mantarray_mc_simulator_no_beacon["testing_queue"] set_connection_and_register_simulator(four_board_mc_comm_process, mantarray_mc_simulator_no_beacon) expected_status_code = 1234 put_object_into_queue_and_raise_error_if_eventually_still_empty( {"command": "set_status_code", "status_code": expected_status_code}, testing_queue, ) invoke_process_run_and_check_errors(simulator) invoke_process_run_and_check_errors(mc_process) confirm_queue_is_eventually_of_size(output_queue, 1) actual = output_queue.get(timeout=QUEUE_CHECK_TIMEOUT_SECONDS) assert str(expected_status_code) in actual["message"]
def test_OkCommunicationProcess_run__raises_error_if_mantarray_naming_command_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({}) ok_process.set_board_connection(0, simulator) input_queue = board_queues[0][0] expected_returned_communication = { "communication_type": "mantarray_naming", "command": "fake_command", } input_queue.put_nowait(copy.deepcopy(expected_returned_communication)) assert is_queue_eventually_not_empty(input_queue) is True with pytest.raises(UnrecognizedMantarrayNamingCommandError, match="fake_command"): invoke_process_run_and_check_errors(ok_process)
def test_McCommunicationProcess__raises_error_if_status_beacon_not_received_in_allowed_period_of_time( four_board_mc_comm_process_no_handshake, mantarray_mc_simulator_no_beacon, mocker, patch_print, ): mc_process = four_board_mc_comm_process_no_handshake["mc_process"] set_connection_and_register_simulator( four_board_mc_comm_process_no_handshake, mantarray_mc_simulator_no_beacon) # patch so next iteration of mc_process will hit beacon timeout mocker.patch.object( mc_comm, "_get_secs_since_last_beacon", autospec=True, return_value=SERIAL_COMM_STATUS_BEACON_TIMEOUT_SECONDS, ) with pytest.raises(SerialCommStatusBeaconTimeoutError): invoke_process_run_and_check_errors(mc_process)
def test_FileWriterProcess__close_all_files( test_start_recording_command, test_description, four_board_file_writer_process, mocker ): file_writer_process = four_board_file_writer_process["fw_process"] from_main_queue = four_board_file_writer_process["from_main_queue"] if test_start_recording_command == GENERIC_BETA_2_START_RECORDING_COMMAND: file_writer_process.set_beta_2_mode() populate_calibration_folder(file_writer_process) this_command = copy.deepcopy(test_start_recording_command) this_command["active_well_indices"] = [3, 18] put_object_into_queue_and_raise_error_if_eventually_still_empty(this_command, from_main_queue) invoke_process_run_and_check_errors(file_writer_process) open_files = file_writer_process._open_files # pylint: disable=protected-access spied_file_3 = mocker.spy(open_files[0][3], "close") spied_file_18 = mocker.spy(open_files[0][18], "close") file_writer_process.close_all_files() assert spied_file_3.call_count == 1 assert spied_file_18.call_count == 1
def test_FileWriterProcess_soft_stop_not_allowed_if_incoming_data_still_in_queue_for_board_0( four_board_file_writer_process, ): file_writer_process = four_board_file_writer_process["fw_process"] board_queues = four_board_file_writer_process["board_queues"] # 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(SIMPLE_BETA_1_CONSTRUCT_DATA_FROM_WELL_0) put_object_into_queue_and_raise_error_if_eventually_still_empty( SIMPLE_BETA_1_CONSTRUCT_DATA_FROM_WELL_0, board_queues[0][0], ) confirm_queue_is_eventually_of_size(board_queues[0][0], 2) file_writer_process.soft_stop() invoke_process_run_and_check_errors(file_writer_process) assert file_writer_process.is_stopped() is False # Tanner (3/8/21): Prevent BrokenPipeErrors drain_queue(board_queues[0][0])
def test_InfiniteLoopingParallelismMixIn__correctly_stores_time_since_initialized__in_setup_before_loop( mocker, ): p = generic_infinite_looper() expected_init_time = 15796649135715 expected_poll_time = 15880317595302 mocker.patch.object( parallelism_framework.time, "perf_counter_ns", autospec=True, side_effect=[0, expected_init_time, 0, expected_poll_time], ) # before setup assert p.get_cms_since_init() == 0 invoke_process_run_and_check_errors(p, perform_setup_before_loop=True) # after setup expected_dur_since_init = (expected_poll_time - expected_init_time ) // NANOSECONDS_PER_CENTIMILLISECOND assert p.get_cms_since_init() == expected_dur_since_init
def test_MantarrayProcessesMonitor__processes_firmware_update_confirmation_command( update_accepted, test_process_manager_creator, test_monitor): test_process_manager = test_process_manager_creator( use_testing_queues=True) monitor_thread, shared_values_dict, *_ = test_monitor(test_process_manager) shared_values_dict["system_status"] = UPDATES_NEEDED_STATE server_to_main_queue = (test_process_manager.queue_container(). get_communication_queue_from_server_to_main()) put_object_into_queue_and_raise_error_if_eventually_still_empty( { "communication_type": "firmware_update_confirmation", "update_accepted": update_accepted }, server_to_main_queue, ) invoke_process_run_and_check_errors(monitor_thread) assert shared_values_dict["firmware_update_accepted"] is update_accepted # make sure system status was not updated assert shared_values_dict["system_status"] == UPDATES_NEEDED_STATE
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_McCommunicationProcess__processes_get_metadata_command( four_board_mc_comm_process_no_handshake, mantarray_mc_simulator_no_beacon ): mc_process = four_board_mc_comm_process_no_handshake["mc_process"] board_queues = four_board_mc_comm_process_no_handshake["board_queues"] simulator = mantarray_mc_simulator_no_beacon["simulator"] input_queue = board_queues[0][0] output_queue = board_queues[0][1] set_connection_and_register_simulator( four_board_mc_comm_process_no_handshake, mantarray_mc_simulator_no_beacon ) expected_response = { "communication_type": "metadata_comm", "command": "get_metadata", } put_object_into_queue_and_raise_error_if_eventually_still_empty( copy.deepcopy(expected_response), input_queue ) # run mc_process one iteration to send the command invoke_process_run_and_check_errors(mc_process) # run simulator one iteration to process the command invoke_process_run_and_check_errors(simulator) # run mc_process one iteration to get metadata from simulator and send back to main invoke_process_run_and_check_errors(mc_process) confirm_queue_is_eventually_of_size(output_queue, 1) expected_response["metadata"] = MantarrayMcSimulator.default_metadata_values expected_response["board_index"] = 0 command_response = output_queue.get(timeout=QUEUE_CHECK_TIMEOUT_SECONDS) assert command_response == expected_response
def test_McCommunicationProcess_register_magic_word__registers_magic_word_in_serial_comm_from_board__when_first_packet_is_truncated_to_more_than_8_bytes( four_board_mc_comm_process, mantarray_mc_simulator_no_beacon, mocker): mc_process = four_board_mc_comm_process["mc_process"] testing_queue = mantarray_mc_simulator_no_beacon["testing_queue"] simulator = mantarray_mc_simulator_no_beacon["simulator"] board_idx = 0 mc_process.set_board_connection(board_idx, simulator) assert mc_process.is_registered_with_serial_comm(board_idx) is False test_bytes = SERIAL_COMM_MAGIC_WORD_BYTES[3:] + bytes(8) dummy_timestamp = 0 test_bytes += create_data_packet( dummy_timestamp, SERIAL_COMM_MAIN_MODULE_ID, SERIAL_COMM_STATUS_BEACON_PACKET_TYPE, DEFAULT_SIMULATOR_STATUS_CODE, ) test_item = {"command": "add_read_bytes", "read_bytes": test_bytes} put_object_into_queue_and_raise_error_if_eventually_still_empty( test_item, testing_queue) invoke_process_run_and_check_errors(simulator) invoke_process_run_and_check_errors(mc_process) assert mc_process.is_registered_with_serial_comm(board_idx) is True # make sure no errors in next iteration invoke_process_run_and_check_errors(mc_process)
def test_McCommunicationProcess__raises_error_if_reboot_takes_longer_than_maximum_reboot_period( four_board_mc_comm_process_no_handshake, mantarray_mc_simulator, mocker, patch_print, ): mc_process = four_board_mc_comm_process_no_handshake["mc_process"] board_queues = four_board_mc_comm_process_no_handshake["board_queues"] simulator = mantarray_mc_simulator["simulator"] input_queue = board_queues[0][0] set_connection_and_register_simulator( four_board_mc_comm_process_no_handshake, mantarray_mc_simulator) mocker.patch.object( mc_comm, "_get_secs_since_reboot_start", autospec=True, side_effect=[MAX_MC_REBOOT_DURATION_SECONDS], ) reboot_command = { "communication_type": "to_instrument", "command": "reboot", } put_object_into_queue_and_raise_error_if_eventually_still_empty( copy.deepcopy(reboot_command), input_queue) # run mc_process to sent reboot command and simulator to start reboot invoke_process_run_and_check_errors(mc_process) invoke_process_run_and_check_errors(simulator) # run mc_process to raise error after reboot period has elapsed and confirm error is raised with pytest.raises(InstrumentRebootTimeoutError): invoke_process_run_and_check_errors(mc_process)
def test_FileWriterProcess__passes_stim_data_packet_through_to_output_queue_correctly( four_board_file_writer_process, ): fw_process = four_board_file_writer_process["fw_process"] fw_process.set_beta_2_mode() board_idx = 0 board_queues = four_board_file_writer_process["board_queues"][board_idx] from_main_queue = four_board_file_writer_process["from_main_queue"] # send stim packet and make sure it is passed through put_object_into_queue_and_raise_error_if_eventually_still_empty( copy.deepcopy(SIMPLE_STIM_DATA_PACKET_FROM_ALL_WELLS), board_queues[0]) invoke_process_run_and_check_errors(fw_process) confirm_queue_is_eventually_of_size(board_queues[1], 1) assert board_queues[1].get( timeout=QUEUE_CHECK_TIMEOUT_SECONDS)["data_type"] == "stimulation" # stop data stream put_object_into_queue_and_raise_error_if_eventually_still_empty( dict(STOP_MANAGED_ACQUISITION_COMMUNICATION), from_main_queue) invoke_process_run_and_check_errors(fw_process) # send stim packet and make sure it is not passed through put_object_into_queue_and_raise_error_if_eventually_still_empty( copy.deepcopy(SIMPLE_STIM_DATA_PACKET_FROM_ALL_WELLS), board_queues[0]) invoke_process_run_and_check_errors(fw_process) confirm_queue_is_eventually_empty(board_queues[1])
def test_MantarrayProcessesMonitor__check_and_handle_server_to_main_queue__handles_start_recording__in_hardware_test_mode__by_passing_command_to_file_writer__and_setting_status_to_recording__and_updating_adc_offsets( test_process_manager_creator, test_monitor): test_process_manager = test_process_manager_creator( use_testing_queues=True) monitor_thread, *_ = test_monitor(test_process_manager) server_to_main_queue = (test_process_manager.queue_container(). get_communication_queue_from_server_to_main()) # expected_timepoint = 55432 adc_offsets = dict() for well_idx in range(24): adc_offsets[well_idx] = { "construct": 0, "ref": 0, } communication = { "communication_type": "recording", "command": "start_recording", "is_hardware_test_recording": True, "metadata_to_copy_onto_main_file_attributes": { "adc_offsets": adc_offsets }, } put_object_into_queue_and_raise_error_if_eventually_still_empty( communication, server_to_main_queue) invoke_process_run_and_check_errors(monitor_thread) confirm_queue_is_eventually_empty(server_to_main_queue) main_to_fw_queue = (test_process_manager.queue_container(). get_communication_queue_from_main_to_file_writer()) confirm_queue_is_eventually_of_size(main_to_fw_queue, 1) actual = main_to_fw_queue.get(timeout=QUEUE_CHECK_TIMEOUT_SECONDS) assert actual == communication shared_values_dict = test_process_manager.get_values_to_share_to_server() assert shared_values_dict["is_hardware_test_recording"] is True assert shared_values_dict["system_status"] == RECORDING_STATE assert (shared_values_dict["adc_offsets"] == communication[ "metadata_to_copy_onto_main_file_attributes"]["adc_offsets"])
def test_OkCommunicationProcess__restarts_scan_process_if_valid_barcode_not_detected_on_first_scan( four_board_comm_process, mocker, test_barcode_simulator): mocker.patch.object( ok_comm, "_get_dur_since_barcode_clear", autospec=True, side_effect=[ BARCODE_CONFIRM_CLEAR_WAIT_SECONDS, BARCODE_GET_SCAN_WAIT_SECONDS, BARCODE_CONFIRM_CLEAR_WAIT_SECONDS, ], ) ok_process = four_board_comm_process["ok_process"] board_queues = four_board_comm_process["board_queues"] input_queue = board_queues[0][0] simulator, mocked_get = test_barcode_simulator( [CLEARED_BARCODE_VALUE, INVALID_BARCODE, CLEARED_BARCODE_VALUE]) spied_start_scan = mocker.spy(simulator, "start_barcode_scan") ok_process.set_board_connection(0, simulator) put_object_into_queue_and_raise_error_if_eventually_still_empty( RUN_BARCODE_SCAN_COMMUNICATION, input_queue) invoke_process_run_and_check_errors(ok_process) mocked_get.assert_called_once() spied_start_scan.assert_called_once() invoke_process_run_and_check_errors(ok_process) assert mocked_get.call_count == 2 spied_start_scan.assert_called_once() invoke_process_run_and_check_errors(ok_process) assert mocked_get.call_count == 3 assert spied_start_scan.call_count == 2
def set_connection_and_register_simulator( mc_process_fixture, simulator_fixture, ): """Send a single status beacon in order to register magic word. Sets connection on board index 0. """ mc_process = mc_process_fixture["mc_process"] output_queue = mc_process_fixture["board_queues"][0][1] simulator = simulator_fixture["simulator"] testing_queue = simulator_fixture["testing_queue"] num_iterations = 1 if not isinstance(simulator, MantarrayMcSimulatorNoBeacons): # first iteration to send possibly truncated beacon invoke_process_run_and_check_errors(simulator) num_iterations += 1 # Tanner (4/6/21): May need to run two iterations in case the first beacon is not truncated. Not doing this will cause issues with output_queue later on # send single non-truncated beacon and then register with mc_process put_object_into_queue_and_raise_error_if_eventually_still_empty( {"command": "send_single_beacon"}, testing_queue) invoke_process_run_and_check_errors(simulator) mc_process.set_board_connection(0, simulator) invoke_process_run_and_check_errors(mc_process, num_iterations=num_iterations) # remove status code log message(s) drain_queue(output_queue)
def test_DataAnalyzerProcess_beta_1_performance__first_second_of_data_with_analysis( runnable_four_board_analyzer_process, ): # Fill data analysis buffer with 10 seconds of data to start metric analysis, # Then record duration of sending 1 additional second of data # # start: 0.547285524 # initial pulse3D import: 0.535316489 # pulse3D 0.23.3: 0.535428579 p, board_queues, comm_from_main_queue, comm_to_main_queue, _ = runnable_four_board_analyzer_process put_object_into_queue_and_raise_error_if_eventually_still_empty( get_mutable_copy_of_START_MANAGED_ACQUISITION_COMMUNICATION(), comm_from_main_queue, ) invoke_process_run_and_check_errors(p, perform_setup_before_loop=True) # load data num_seconds = MIN_NUM_SECONDS_NEEDED_FOR_ANALYSIS + 1 fill_da_input_data_queue(board_queues[0][0], num_seconds) invoke_process_run_and_check_errors( p, num_iterations=MIN_NUM_SECONDS_NEEDED_FOR_ANALYSIS * (24 + 6)) # send additional data and time analysis start = time.perf_counter_ns() invoke_process_run_and_check_errors(p, num_iterations=(24 + 6)) dur_seconds = (time.perf_counter_ns() - start) / 10**9 # prevent BrokenPipeErrors drain_queue(board_queues[0][1]) drain_queue(comm_to_main_queue) # print(f"Duration (seconds): {dur_seconds}") # Eli (4/8/21): this is commented code that is deliberately kept in the codebase since it is often toggled on/off during optimization assert dur_seconds < 2
def test_DataAnalyzerProcess__does_not_include_performance_metrics_in_first_logging_cycle__with_beta_1_data( four_board_analyzer_process, mocker): # TODO Tanner (8/30/21): change this test to work with Beta 2 data once beta 1 is phased out mocker.patch.object(data_analyzer, "get_force_signal", autospec=True, return_value=np.zeros((2, 2))) da_process, _, _, to_main_queue, _ = four_board_analyzer_process da_process._minimum_iteration_duration_seconds = 0 # pylint: disable=protected-access data_buffer = da_process._data_buffer # pylint: disable=protected-access for i in range(24): data_buffer[i]["construct_data"] = np.zeros((2, 2)) data_buffer[i]["ref_data"] = np.zeros((2, 2)) invoke_process_run_and_check_errors(da_process, perform_setup_before_loop=True) confirm_queue_is_eventually_of_size(to_main_queue, 2) actual = to_main_queue.get(timeout=QUEUE_CHECK_TIMEOUT_SECONDS) actual = actual["message"] assert "percent_use_metrics" not in actual assert "data_creation_duration_metrics" not in actual
def test_OkCommunicationProcess_run__raises_error_if_acquisition_manager_command_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": "acquisition_manager", "command": "fake_command", } input_queue.put_nowait(copy.deepcopy(expected_returned_communication)) confirm_queue_is_eventually_of_size(input_queue, 1) with pytest.raises(UnrecognizedCommandFromMainToOkCommError, match="fake_command"): invoke_process_run_and_check_errors(ok_process)
def test_MantarrayProcessesMonitor__check_and_handle_server_to_main_queue__handles_nickname_update_by_updating_shared_values_dictionary( test_process_manager_creator, test_monitor): test_process_manager = test_process_manager_creator( use_testing_queues=True) monitor_thread, shared_values_dict, *_ = test_monitor(test_process_manager) server_to_main_queue = (test_process_manager.queue_container(). get_communication_queue_from_server_to_main()) shared_values_dict["mantarray_nickname"] = {0: "The Nautilus 1"} expected_nickname = "The Nautilus 2" expected_comm = { "communication_type": "mantarray_naming", "command": "set_mantarray_nickname", "mantarray_nickname": expected_nickname, } put_object_into_queue_and_raise_error_if_eventually_still_empty( expected_comm, server_to_main_queue) invoke_process_run_and_check_errors(monitor_thread) confirm_queue_is_eventually_empty(server_to_main_queue) assert test_process_manager.get_values_to_share_to_server( )["mantarray_nickname"][0] == expected_nickname
def test_MantarrayProcessesMonitor__check_and_handle_server_to_main_queue__handles_shutdown_hard_stop_by_hard_stop_and_join_all_processes( test_process_manager_creator, test_monitor, mocker): test_process_manager = test_process_manager_creator( use_testing_queues=True) monitor_thread, *_ = test_monitor(test_process_manager) mocked_hard_stop_and_join = mocker.patch.object( test_process_manager, "hard_stop_and_join_processes", autospec=True ) # Eli (11/17/20): mocking instead of spying because processes can't be joined unless they were actually started, and we're just doing a create_processes here server_to_main_queue = (test_process_manager.queue_container(). get_communication_queue_from_server_to_main()) communication = { "communication_type": "shutdown", "command": "hard_stop", } put_object_into_queue_and_raise_error_if_eventually_still_empty( communication, server_to_main_queue) invoke_process_run_and_check_errors(monitor_thread) confirm_queue_is_eventually_empty(server_to_main_queue) mocked_hard_stop_and_join.assert_called_once()
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"]