def test_get_messages_correctly_return_a_list_of_message_to_send_that_represent_the_current_image( ): # Given new_image = np.array(4 * [4 * 4 * [[0, 0, 0]]]) im = ImageManager(max_packet_size=64) im.refresh_image(new_image) nb_packet = 3 total_bytes = 192 height = 4 length = 16 pixel_size = 3 expected_topic = 10 encoding = 0 expected_header = nb_packet.to_bytes( ImageManager.NB_PACKET_SIZE, 'little') + total_bytes.to_bytes( ImageManager.TOTAL_BYTES_SIZE, 'little') + height.to_bytes( ImageManager.HEIGHT_SIZE, 'little') + length.to_bytes( ImageManager.LENGTH_SIZE, 'little') + pixel_size.to_bytes( ImageManager.SIZE_PIXEL_SIZE, 'little') + encoding.to_bytes( ImageManager.ENCODING_SIZE, 'little') # When result = list(im.get_messages(expected_topic)) # Then assert collections.Counter(UDPMessage.from_bytes( result[0]).payload) == collections.Counter(list(expected_header)) for i in range(1, len(result)): msg = UDPMessage.from_bytes(result[i]) assert int.from_bytes(msg.message_nb, 'little') == i assert int.from_bytes(msg.topic, 'little') == expected_topic assert msg.payload == bytes(64 * [0])
def test_refresh_image_raise_an_error_if_shape_length_is_2_and_pixels_does_not_contains_3_values( ): # Given new_image = np.array([[[0, 0], [1, 1], [2, 2]]]) im = ImageManager() # When # Then with pytest.raises(ValueError): im.refresh_image(new_image)
def test_refresh_image_correctly_change_current_image(): # Given new_image = np.array([[[0, 0, 0], [1, 1, 1], [2, 2, 2]], [[0, 0, 0], [1, 1, 1], [2, 2, 2]]]) im = ImageManager() # When im.refresh_image(new_image) # Then assert np.array_equiv(im.current_image, new_image)
def test_refresh_image_raise_an_error_if_shape_length_is_greater_than_3(): # Given new_image = np.array([[[[1, 1, 1], [1, 1, 1], [1, 1, 1]], [[1, 1, 1], [1, 1, 1], [1, 1, 1]], [[1, 1, 1], [1, 1, 1], [1, 1, 1]]]]) im = ImageManager() # When # Then with pytest.raises(ValueError): im.refresh_image(new_image)
def test_get_pixel_size_correctly_return_1_for_pixel_size_1(): # Given new_image = np.array(4 * [4 * [0]]) im = ImageManager() im.refresh_image(new_image) expected_pixel_size = 1 # When result = im.get_pixel_size() # Then assert result == expected_pixel_size
def test_split_image_correctly_returns_a_list_of_bytes_with_many_elements_for_big_image_of_pixels( ): # Given new_image = np.array(4 * 4 * [[0, 0, 0]]) expected_result = 4 * [bytes(12 * [0])] im = ImageManager(max_packet_size=12) im.refresh_image(new_image) # When result = im.split_image() # Then assert collections.Counter(result) == collections.Counter(expected_result)
def test_split_image_correctly_returns_a_list_of_bytes_with_one_element_for_small_image_of_pixels( ): # Given new_image = np.array([[0, 0, 0], [1, 1, 1], [2, 2, 2]]) expected_result = [bytes([0, 0, 0, 1, 1, 1, 2, 2, 2])] im = ImageManager(max_packet_size=100) im.refresh_image(new_image) # When result = im.split_image() # Then assert collections.Counter(result) == collections.Counter(expected_result)
def test_get_header_msg_correctly_return_an_array_of_bytes_with_correct_metadata( ): # Given nb_packet = 2 total_bytes = 50 height = 2 length = 25 pixel_size = 3 encoding = 0 expected_payload = nb_packet.to_bytes( ImageManager.NB_PACKET_SIZE, 'little') + total_bytes.to_bytes( ImageManager.TOTAL_BYTES_SIZE, 'little') + height.to_bytes( ImageManager.HEIGHT_SIZE, 'little') + length.to_bytes( ImageManager.LENGTH_SIZE, 'little') + pixel_size.to_bytes( ImageManager.SIZE_PIXEL_SIZE, 'little') + encoding.to_bytes( ImageManager.ENCODING_SIZE, 'little') expected_topic = 10 # When result = ImageManager.get_header_msg(expected_topic, nb_packet, total_bytes, height, length, pixel_size) result_message = UDPMessage.from_bytes(result) # Then assert result_message.payload == expected_payload assert int.from_bytes(result_message.topic, 'little') == expected_topic
def test_from_message_correctly_create_a_new_video_topic(): # Given nb_packet = 3 total_bytes = 90 height = 10 length = 3 pixel_size = 3 expected_payload = nb_packet.to_bytes(ImageManager.NB_PACKET_SIZE, 'little') + total_bytes.to_bytes( ImageManager.TOTAL_BYTES_SIZE, 'little') + height.to_bytes(ImageManager.HEIGHT_SIZE, 'little') + length.to_bytes( ImageManager.LENGTH_SIZE, 'little') + pixel_size.to_bytes(ImageManager.SIZE_PIXEL_SIZE, 'little') expected_topic = 10 # When header = ImageManager.get_header_msg(expected_topic, nb_packet, total_bytes, height, length, pixel_size) header_message = UDPMessage.from_bytes(header) result = VideoTopic.from_message(header_message) # Then assert result.nb_packet == nb_packet assert result.total_bytes == total_bytes assert result.height == height assert result.length == length assert result.pixel_size == pixel_size assert result.time_creation == int.from_bytes(header_message.time_creation, 'little')
def __init__(self, role: Optional[str] = EMITTER, max_packet_size: Optional[int] = 60000, socket_ip: Optional[str] = "127.0.0.1", socket_port: Optional[int] = 50000, encryption_in_transit: Optional[bool] = False, max_queue_size: Optional[int] = 100, buffer_size: Optional[int] = 65543, key: Optional[Union[None, bytes]] = None, enable_multicast: Optional[bool] = False, multicast_ttl: Optional[int] = 2, use_rcv_img_buffer: Optional[bool] = False, from_source: Optional[Union[int, str]] = None, run_new_process: Optional[bool] = True, async_msg_generation: Optional[bool] = False, encoding: Optional[int] = 0, encoding_param: Optional[Union[dict, None]] = None): """Create a new VideoStream object with given parameter. :param role: Tell if the VideoStream is emitter or consumer. :param max_packet_size: The max size of a packet (in byte). :param socket_ip: The ip used to bind the socket. :param socket_port: The port used to bind the socket. :param encryption_in_transit: Define if the messages must be encrypted. :param max_queue_size: The max size of message queue. :param buffer_size: The max size of the received message buffer. :param key: The encryption key used to encrypt message. If no value is provided it will generate a new one. :param enable_multicast: Specify if the socket can use multicast. :param multicast_ttl: A list of tuples containing ip address and port of subscribers. :param use_rcv_img_buffer: A bool that tell if received image are stored in a buffer or in a single variable. :param from_source: Make the VideoStream stream from a source. :param run_new_process: Specify if the Eye object must be run in a new process. :param async_msg_generation: Specify if the messages representing the image must be generated asynchronously. :param encoding: Define the encoding used to send images. :param encoding_param: Parameters used to encode image. See cv2.imencode for more details. """ self.internal_pipe, self.external_pipe = mp.Pipe() if role != VideoStream.EMITTER and role != VideoStream.CONSUMER: raise ValueError self.role = role self.im: ImageManager = ImageManager(max_packet_size=max_packet_size, async_msg_generation=async_msg_generation, encoding=encoding, encoding_param=encoding_param) self.opened_topics: List[VideoTopic] = [] self.udp_socket: Union[UDPSocket, None] = None self.socket_ip = socket_ip self.socket_port = socket_port self.encryption_in_transit: bool = encryption_in_transit self.max_queue_size: int = max_queue_size self.buffer_size: int = buffer_size self.is_running: bool = False self.enable_multicast: bool = enable_multicast self.multicast_ttl: int = multicast_ttl if self.enable_multicast: raise NotImplementedError self.key: bytes = key self.subs_list: List[Tuple[str, int]] = [] self.tm = TopicManager() self.use_rcv_img_buffer = use_rcv_img_buffer self.rcv_img_buffer: List[np.array] = [] if use_rcv_img_buffer is False: self.rcv_img_buffer.append(None) self.from_source = from_source self.eye: Union[None, Eye] = None self.run_new_process = run_new_process self.async_msg_generation = async_msg_generation self.encoding = encoding self.encoding_param = encoding_param if encoding_param is not None else {}
def test_new_image_manager_correctly_setup_an_empty_numpy_array_for_image(): # Given expected_current_image_size = 0 # When im = ImageManager() # Then assert im.current_image.size == 0
def test_new_image_manager_correctly_setup_max_packet_size(): # Given max_packet_size = 1000 # When im = ImageManager(max_packet_size=max_packet_size) # Then assert im.current_image.size == 0
def test_check_topic_remove_old_opened_topic_when_a_topic_is_completed(get_msg_sample): # Given messages = get_msg_sample tm = TopicManager() tm.add_message(UDPMessage.from_bytes(messages[0])) time.sleep(.01) new_image = np.array(4 * [4 * 4 * [[0, 0, 0]]]) im = ImageManager(max_packet_size=64) im.refresh_image(new_image) new_messages = list(im.get_messages(2)) tm.add_message(UDPMessage.from_bytes(new_messages[0])) # When for i in new_messages[1:]: tm.add_message(UDPMessage.from_bytes(i)) # Then assert len(tm.open_topic.keys()) == 0
def test_process_dlq_correctly_remove_outdated_messages_from_dlq(get_msg_sample): # Given messages = get_msg_sample tm = TopicManager() tm.add_message(UDPMessage.from_bytes(messages[1])) time.sleep(.01) new_image = np.array(4 * [4 * 4 * [[0, 0, 0]]]) im = ImageManager(max_packet_size=64) im.refresh_image(new_image) new_messages = list(im.get_messages(2)) tm.add_message(UDPMessage.from_bytes(new_messages[1])) # When tm.add_message(UDPMessage.from_bytes(new_messages[0])) # Then assert len(tm.dead_letter_queue) == 0
def get_msg_sample(): new_image = np.array(4 * [4 * 4 * [[0, 0, 0]]]) im = ImageManager(max_packet_size=64) im.refresh_image(new_image) return list(im.get_messages(1))