o
    پi-                     @   s  d dl Z d dlZd dlZd dlZd dlZd dlmZ d dlZd dlm	Z	 d dl
mZ d dlmZ d dlmZmZ eeZdeeB dB defd	d
ZdOdefddZdefddZdefddZdedefddZdedefddZdd ZdedefddZ		dPdedB dedB defdd ZdQd#d$Z d%d& Z!defd'd(Z"d)edefd*d+Z#d)edefd,d-Z$de%eef fd.d/Z&d0ede'e fd1d2Z(	3dRd4ed0ed5e)dedB fd6d7Z*d8eddfd9d:Z+d8eddfd;d<Z,d=eddfd>d?Z-				dSd@edAedBedB dCedB dedB dedB ddfdDdEZ.dFej/de%eef dB fdGdHZ0dFej/de%eef fdIdJZ1d@ede%eef fdKdLZ2		dPd@edAedBedB dCedB ddf
dMdNZ3dS )T    N)Path)Imageget_bool_env_var)init_logger)RequestPerfRecordget_diffusion_perf_log_dir
image_pathreturnc                 C   s*   | du rdS t | to| dp| dS )zCheck if image_path is a URL.NFzhttp://zhttps://)
isinstancestr
startswith)r	    r   Y/home/ubuntu/.local/lib/python3.10/site-packages/sglang/multimodal_gen/test/test_utils.pyis_image_url   s
   
r   	127.0.0.1:u         @c              	   C   sr   t  t jt j'}|| z|| |f W W d    dS  ty.   Y W d    dS w 1 s2w   Y  d S )NTF)socketAF_INETSOCK_STREAM
settimeoutconnectOSError)hostporttimeoutsr   r   r   
probe_port   s   
r   c                   C   s   t dS )NSGLANG_IS_IN_CIr   r   r   r   r   is_in_ci)   s   r    c               	   C   s~   t jdd} | sd} zt| dd  d }W n ttfy'   d}Y nw t r5d|d  }|d S d|d  }|d S )	NCUDA_VISIBLE_DEVICES0,r   i'  i  i N  i  )	osenvirongetintsplitstrip
ValueError
IndexErrorr    )cuda_devicesfirst_device_id	base_portr   r   r   get_dynamic_server_port-   s   r/   datac                 C   s    t | dk rdS | dd dkS )z9Check if data represents a valid MP4 file by magic bytes.   F   s   ftyp)lenr0   r   r   r   is_mp4>   s   r5   c                 C   
   |  dS )Ns   r   r4   r   r   r   is_jpegE      
r8   c                 C   r6   )Ns   PNG

r7   r4   r   r   r   is_pngJ   r9   r:   c                 C   s    | d d dko| dd dkS )Nr2   s   RIFFr1      s   WEBPr   r4   r   r   r   is_webpO   s    r<   output_format
backgroundc                 C   s<   | pd  }|dv r|dkrdS |S |pd  dkrdS dS )a=  Infer expected image format based on request parameters.
    Args:
        output_format: The output_format parameter from the request (png/jpeg/webp/jpg)
        background: The background parameter from the request (transparent/opaque/auto)
    Returns:
        Expected file extension: "jpg", "png", or "webp"
     >   jpgpngjpegwebprB   r@   autotransparentrA   )lower)r=   r>   fmtr   r   r   get_expected_image_formatT   s   rH        r@      ?c                 C   s^   t   | }d }t   |k r"t| ||drdS t | t   |k std|  d| d| )N)r   TzPort :z not ready. Last error: )timer   sleepTimeoutError)r   r   deadlineintervalendlast_errr   r   r   wait_for_portg   s   
rS   c                 C   s   |  |j||f d S )N)assertEqualsize)utimagewidthheightr   r   r   check_image_sizeq   s   rZ   c                  C   s   t  } | s	tdt| S )zGGets the performance log directory from the centralized sglang utility.zmPerformance logging is disabled (SGLANG_PERF_LOG_DIR is empty), but a test tried to access the log directory.)r   RuntimeErrorr   )log_dir_strr   r   r   get_perf_log_dirv   s   r]   log_dirc                 C   s   | j ddd | d S )NT)parentsexist_okzperformance.log)mkdir)r^   r   r   r   _ensure_log_path   s   rb   c                 C   s,   t | }| r|  td|  |S )z>Delete the perf log file so tests can watch for fresh entries.z'[server-test] Monitoring perf log at %s)rb   existsunlinkloggerinfoas_posixr^   log_pathr   r   r   clear_perf_log   s
   rj   c                  C   s   t  } t| }| |fS )zAConvenience helper to resolve and clear the perf log in one call.)r]   rj   rh   r   r   r   prepare_perf_log   s   rk   ri   c              
   C   s   |   sg S g }| jddd0}|D ]$}| }|sqzt|}|tdi | W q tjy6   Y qw W d    |S 1 sBw   Y  |S )Nrzutf-8)encodingr   )rc   openr)   jsonloadsappendr   JSONDecodeError)ri   recordsfhlinerecord_dictr   r   r   read_perf_logs   s&   



rw         >@
request_idr   c                 C   s   t d|   t | }t |k r1t|}|D ]}|j| kr%|  S qtd t |k stjdddkr<dS t 	d|  t
d|  d	)
zc
    the stage metrics of this request should be in the performance_log file with {request-id}
    z-Waiting for req perf record with request id: rJ   SGLANG_GEN_BASELINEr"   1Nzrecord: z.Timeout waiting for stage metrics for request  )re   rf   rL   rw   ry   rM   r$   r%   r&   errorAssertionError)ry   ri   r   rO   rs   recordr   r   r   wait_for_req_perf_record   s   

r   b64_jsonc                 C   s*   t | }t|st|sJ ddS dS )z.Decode and validate that image is PNG or JPEG.zImage must be PNG or JPEGN)base64	b64decoder:   r8   )r   image_bytesr   r   r   validate_image   s   
 r   c                 C   s6   t | }|dd dk}t|s|sJ ddS dS )z1Decode and validate that video is a valid format.Nr2      EߣVideo must be MP4 or WebM)r   r   r5   )r   video_bytesis_webmr   r   r   validate_video   s   
r   r   c                 C   s&   |  d}t| s|sJ ddS dS )z2Validate that video is MP4 or WebM by magic bytes.r   r   N)r   r5   )r   r   r   r   r   validate_openai_video   s   
r   	file_pathexpected_filenameexpected_widthexpected_heightc                 C   s  t ||}tj| sJ d|  | d| s$J d| d|  tj| }|dks5J d|  tj| }||ksJJ d| d| d	t| d
<}	|	d}
|dkret	|
sdJ d|  n|dkrut
|
stJ d|  n|dkrt|
sJ d|  W d   n1 sw   Y  |dur|durt| *}|j\}}||ksJ d| d| ||ksJ d| d| W d   dS 1 sw   Y  dS dS dS )zUValidate image output file: existence, extension, size, filename, format, dimensions.zImage file does not exist: .z
Expected .z extension, got: r   zImage file is empty: Filename mismatch: expected '', got ''rbr;   rA   zFile is not a valid PNG: r@   zFile is not a valid JPEG: rC   zFile is not a valid WebP: NzWidth mismatch: expected , got zHeight mismatch: expected )rH   r$   pathrc   endswithgetsizebasenamern   readr:   r8   r<   r   rU   )r   r   r   r   r=   r>   expected_ext	file_sizeactual_filenamefheaderimgrX   rY   r   r   r   validate_image_file   sD   







"r   capc                 C   s<   |  tj}|  tj}|dks|dkrdS t|t|fS )zGet video dimensions from metadata properties.

    Args:
        cap: OpenCV VideoCapture object

    Returns:
        Tuple of (width, height) if successful, None if metadata is invalid
    r   N)r&   cv2CAP_PROP_FRAME_WIDTHCAP_PROP_FRAME_HEIGHTr'   )r   rX   rY   r   r   r   #_get_video_dimensions_from_metadata  s
   r   c                 C   sB   |   \}}|r|du rtd|jdd \}}t|t|fS )zGet video dimensions by reading the first frame.

    Args:
        cap: OpenCV VideoCapture object

    Returns:
        Tuple of (width, height)

    Nz,Unable to read video frame to get dimensions   )r   r*   shaper'   )r   retframerY   rX   r   r   r    _get_video_dimensions_from_frame  s
   
r   c                 C   sF   t | }zt|}|dur|W |  S t|W |  S |  w )zGet video dimensions (width, height) from a video file.

    Tries to get dimensions from metadata first, falls back to reading first frame.

    Returns:
        Tuple of (width, height)

    N)r   VideoCapturer   releaser   )r   r   
dimensionsr   r   r   get_video_dimensions.  s   
	
r   c           
      C   s(  t j| sJ d|  | dsJ d|  t j| }|dks*J d|  t j| }||ks?J d| d| dt| d	}|d
}t|sUJ d|  W d   n1 s_w   Y  |dur|durt	| \}}	||ksJ d| d| |	|ksJ d| d|	 dS dS dS )zUValidate video output file: existence, extension, size, filename, format, dimensions.zVideo file does not exist: z.mp4zExpected .mp4 extension, got: r   zVideo file is empty: r   r   r   r       zFile is not a valid MP4: NzVideo width mismatch: expected r   z Video height mismatch: expected )
r$   r   rc   r   r   r   rn   r   r5   r   )
r   r   r   r   r   r   r   r   actual_widthactual_heightr   r   r   validate_video_fileD  s,   



r   )r   r   r   )NN)r   r   rI   rJ   )rx   )NNNN)4r   ro   r$   r   rL   pathlibr   r   PILr   *sglang.multimodal_gen.runtime.utils.commonr   1sglang.multimodal_gen.runtime.utils.logging_utilsr   /sglang.multimodal_gen.runtime.utils.perf_loggerr   r   __name__re   r   boolr   r   r    r'   r/   bytesr5   r8   r:   r<   rH   rS   rZ   r]   rb   rj   tuplerk   listrw   floatr   r   r   r   r   r   r   r   r   r   r   r   r   r   <module>   s   	



	
	
4
