import copy from unittest import mock import pytest from csaxs_bec.devices.npoint import NPointAxis, NPointController # pylint: disable=protected-access # pylint: disable=redefined-outer-name @pytest.fixture def controller(): """ Fixture to create a NPointController object. """ with mock.patch("ophyd_devices.utils.socket.SocketIO") as socket_cls: controller = NPointController( socket_cls=socket_cls, socket_host="localhost", socket_port=1234, device_manager=mock.MagicMock(), ) controller.on() controller.sock.reset_mock() yield controller controller.off() @pytest.fixture def npointx(dm_with_devices): """ Fixture to create a NPointAxis object. """ controller = mock.MagicMock() npointx = NPointAxis( axis_Id="A", name="npointx", host="localhost", port=1234, socket_cls=controller, device_manager=dm_with_devices, ) npointx.controller.on() npointx.controller.sock.reset_mock() npointx.controller.sock.receive.reset_mock() yield npointx npointx.controller.off() @pytest.mark.parametrize( "pos,msg", [ (5, b"\xa2\x18\x12\x83\x11\xcd\xcc\x00\x00U"), (0, b"\xa2\x18\x12\x83\x11\x00\x00\x00\x00U"), (-5, b"\xa2\x18\x12\x83\x1133\xff\xffU"), ], ) def test_axis_put(npointx, pos, msg): """ Test that the set target position sends the correct message to the controller. """ npointx.controller.set_target_pos(npointx.axis_Id_numeric, pos) npointx.controller.sock.put.assert_called_with(msg) def test_npoint_axis_move(npointx): """ Test that the move method sends the correct messages to the controller. It should send the set target position, followed by 2 get current position messages. """ npointx.controller.sock.receive.side_effect = [ b"\xa0\x34\x13\x83\x11\x00\x00\x00\x00U", # pos 0 b"\xa0\x34\x13\x83\x11\xcd\xcc\x00\x00U", # pos 5 ] npointx.move(5) assert ( mock.call(b"\xa2\x18\x12\x83\x11\xcd\xcc\x00\x00U") in npointx.controller.sock.put.mock_calls ) assert len(npointx.controller.sock.put.mock_calls) == 3 @pytest.mark.parametrize( "pos, msg_in, msg_out", [ (5.0, b"\xa04\x13\x83\x11U", b"\xa0\x34\x13\x83\x11\xcd\xcc\x00\x00U"), (0, b"\xa04\x13\x83\x11U", b"\xa0\x34\x13\x83\x11\x00\x00\x00\x00U"), (-5, b"\xa04\x13\x83\x11U", b"\xa0\x34\x13\x83\x1133\xff\xffU"), ], ) def test_axis_get_out(npointx, pos, msg_in, msg_out): """ Test that the readback value is correctly read from the controller. """ npointx.controller.sock.receive.side_effect = [msg_out] assert pytest.approx(npointx.readback.get(), rel=0.01) == pos @pytest.mark.parametrize( "axis, msg_in, msg_out", [ (0, b"\xa04\x13\x83\x11U", b"\xa0\x34\x13\x83\x11\xcd\xcc\x00\x00U"), (1, b"\xa04#\x83\x11U", b"\xa0\x34\x13\x83\x11\x00\x00\x00\x00U"), (2, b"\xa043\x83\x11U", b"\xa0\x34\x13\x83\x1133\xff\xffU"), ], ) def test_axis_get_in(npointx, axis, msg_in, msg_out): """ Test that the readback value is correctly read from the controller by directly calling the controller's method. """ npointx.controller.sock.receive.side_effect = [msg_out] npointx.controller.get_current_pos(axis) npointx.controller.sock.put.assert_called_once_with(msg_in) def test_axis_out_of_range(dm_with_devices): """ Test that an error is raised when trying to create an NPointAxis object with an invalid axis ID. """ with pytest.raises(ValueError): npointx = NPointAxis( axis_Id="G", name="npointx", host="localhost", port=1234, socket_cls=mock.MagicMock(), device_manager=dm_with_devices, ) def test_get_axis_out_of_range(controller): """ Test that an error is raised when trying to get the current position of an invalid axis. """ with pytest.raises(ValueError): controller.get_current_pos(3) def test_set_axis_out_of_range(controller): """ Test that an error is raised when trying to set the target position of an invalid axis. """ with pytest.raises(ValueError): controller.set_target_pos(3, 5) @pytest.mark.parametrize( "in_buffer, byteorder, signed, val", [ (["0x0", "0x0", "0xcc", "0xcd"], "big", True, 52429), (["0xcd", "0xcc", "0x0", "0x0"], "little", True, 52429), (["cd", "cc", "00", "00"], "little", True, 52429), ], ) def test_hex_list_to_int(in_buffer, byteorder, signed, val): """ Test that the hex list is correctly converted to an integer """ assert ( NPointController._hex_list_to_int( copy.deepcopy(in_buffer), byteorder=byteorder, signed=signed ) == val ) @pytest.mark.parametrize( "axis, msg_in, msg_out", [ (0, b"\xa0x\x10\x83\x11U", b"\xa0\x78\x13\x83\x11\x64\x00\x00\x00U"), (1, b"\xa0x \x83\x11U", b"\xa0\x78\x13\x83\x11\x64\x00\x00\x00U"), (2, b"\xa0x0\x83\x11U", b"\xa0\x78\x13\x83\x11\x64\x00\x00\x00U"), ], ) def test_get_range(npointx, axis, msg_in, msg_out): """ Test that the range is correctly read from the controller by directly calling the controller's method. """ npointx.controller.sock.receive.side_effect = [msg_out] val = npointx.controller._get_range(axis) npointx.controller.sock.put.assert_called_once_with(msg_in) assert val == 100