예제 #1
0
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
예제 #2
0
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
예제 #3
0
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"]
예제 #4
0
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",
    }
예제 #5
0
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)
예제 #6
0
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()
예제 #7
0
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()
예제 #8
0
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,
    }
예제 #9
0
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
예제 #10
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"]
예제 #11
0
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)
예제 #12
0
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)
예제 #13
0
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
예제 #14
0
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])
예제 #15
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
예제 #16
0
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
예제 #17
0
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])
예제 #18
0
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
예제 #19
0
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)
예제 #20
0
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)
예제 #21
0
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])
예제 #22
0
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"])
예제 #23
0
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
예제 #24
0
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)
예제 #25
0
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
예제 #26
0
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
예제 #27
0
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)
예제 #28
0
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
예제 #29
0
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()
예제 #30
0
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"]