o
    Miz                     @   sx  d Z ddlZddlm  mZ ddlZddlZddl	m
Z
 ddlmZmZ dZde
dedefd	d
Zejjde
defddZejjde
defddZejjde
defddZejjde
defddZejjde
defddZejjde
defddZejjde
dedejfddZejjde
defddZejjde
defddZejjde
dedejfddZdS ) z-Tests for the VTON (Virtual Try-On) endpoint.    N)AsyncClient)_mock_analyzer	_mock_llmz$00000000-0000-0000-0000-000000000000clientsample_jpegreturnc                    s  | j ddd|dfidI dH }|j}d}||k}|sUtd|fd	||fd
t v s0t|r5t|nd
t|t|d }t|j	d d|i }t
t|d } }}| d d d }|  d| dI dH }|j}d}||k}|std|fd	||fd
t v st|rt|nd
t|t|d }t|j	d d|i }t
t|d } }}| d }	|	sddt|	i }
t
t|
d}	|S )zHHelper: run analyze (auto_save) then generate ghost. Returns garment_id./api/v1/garments/analyzeimagetest.jpg
image/jpegfilesN   ==z3%(py2)s
{%(py2)s = %(py0)s.status_code
} == %(py5)sresppy0py2py5
>assert %(py7)spy7garmentsr   idz/api/v1/garments/z/ghostghost_image_urlzassert %(py1)spy1)poststatus_code
@pytest_ar_call_reprcompare@py_builtinslocals_should_repr_global_name	_saferepr_format_assertmsgtextAssertionError_format_explanationjson)r   r   r   @py_assert1@py_assert4@py_assert3@py_format6@py_format8
garment_id@py_assert0@py_format2 r2   //home/ubuntu/ootd-poc-server/tests/test_vton.py_analyze_and_generate_ghost   s   4r4   c                    s<  t | |I dH }g tj_| jddd|dfid|gidI dH }|j}d}||k}|s_td	|fd
||fdt	 v s@t
|rEt|ndt|t|d }dd|i }tt|d } }}d}	| d }|	|v }
|
std|
fd|	|ft|	t|d }dd|i }tt|d }	 }
}dS )u-   Person image with no detectable face → 400.N/api/v1/vton/generater	   
person.jpgr   garment_idsr   data  r   r   r   r   assert %(py7)sr   u   얼굴detailinz%(py1)s in %(py4)sr   py4assert %(py6)spy6)r4   r   get_embeddingsreturn_valuer   r   r   r    r!   r"   r#   r$   r'   r(   r)   r   r   r/   r   r*   r+   r,   r-   r.   r0   @py_assert2@py_format5@py_format7r2   r2   r3   test_vton_no_face_returns_400   s   rrJ   c                    s0  t t }| jddd|dfid|gidI dH }|j}d}||k}|sYtd	|fd
||fdt v s:t	|r?t
|ndt
|t
|d }dd|i }tt|d } }}d}	| d }|	|v }
|
std|
fd|	|ft
|	t
|d }dd|i }tt|d }	 }
}dS )u   Unknown garment_id → 404.r5   r	   r6   r   r7   r8   Ni  r   r   r   r   r;   r   u   의류r<   r=   r?   r@   rB   rC   )struuiduuid4r   r   r   r    r!   r"   r#   r$   r'   r(   r)   )r   r   bogusr   r*   r+   r,   r-   r.   r0   rG   rH   rI   r2   r2   r3   'test_vton_garment_not_found_returns_404,   s   rrO   c                    s  | j ddd|dfidI dH }|j}d}||k}|sOtd|fd	||fd
t v s0t|r5t|nd
t|t|d }dd|i }tt	|d } }}|
 d d d }| j ddd|dfid|gidI dH }|j}d}||k}|std|fd	||fd
t v st|rt|nd
t|t|d }dd|i }tt	|d } }}d}	|
 d }|	|v }
|
std|
fd|	|ft|	t|d }dd|i }tt	|d }	 }
}dS )u1   Garment that has no ghost_image_path yet → 400.r   r	   r
   r   r   Nr   r   r   r   r   r;   r   r   r   r   r5   r6   r7   r8   r:   u	   고스트r<   r=   r?   r@   rB   rC   )r   r   r   r    r!   r"   r#   r$   r'   r(   r)   )r   r   r   r*   r+   r,   r-   r.   r/   r0   rG   rH   rI   r2   r2   r3   +test_vton_garment_without_ghost_returns_4009   s   rrP   c                    s  t | |I dH }| jddd|dfid|gidI dH }|j}d}||k}|satd	|fd
||fdt v s<t|rAt|ndt|t|d }t	|j
d d|i }tt|d } }}| }	|	d }
|
j}d}||}|sdt|
t|t|t|d }tt|d }
 } }}|	d }
|
j}d}||}|sdt|
t|t|t|d }tt|d }
 } }}|	d }
|g}|
|k}|std	|fd|
|ft|
t|d }dd|i }tt|d }
 }}|	d }
g }|
|k}|s8td	|fd|
|ft|
t|d }dd|i }tt|d }
 }}|	d }
d}|
|k}|sntd	|fd|
|ft|
t|d }dd|i }tt|d }
 }}dS )u=   Single garment with ghost → 200 with result URL + all used.Nr5   r	   r6   r   r7   r8   r   r   r   r   r   r   r   result_image_url/storage/vton/Lassert %(py7)s
{%(py7)s = %(py3)s
{%(py3)s = %(py1)s.startswith
}(%(py5)s)
}r   py3r   r   result_image_pathzvton/used_garment_idsz%(py1)s == %(py4)sr@   rB   rC   skipped_garment_idsllm_notezUsed all garments.)r4   r   r   r   r    r!   r"   r#   r$   r%   r&   r'   r(   r)   
startswith)r   r   r/   r   r*   r+   r,   r-   r.   r9   r0   rG   @py_assert6rH   rI   r2   r2   r3   test_vton_happy_pathO   s   ffnlpr]   c                    s6  t | |I dH }t | |I dH }dt_| jddd|dfid||gidI dH }|j}d	}||k}|smtd
|fd||fdt v sHt	|rMt
|ndt
|t
|d }t|jd d|i }	tt|	d } }}| }
|
d }|g}||k}|std
|fd||ft
|t
|d }dd|i }tt|d } }}|
d }|g}||k}|std
|fd||ft
|t
|d }dd|i }tt|d } }}d}|
d }||v }|std|fd||ft
|t
|d }dd|i }tt|d } }}dS )zIWhen the LLM note says "Skipped #2", the second garment moves to skipped.Nz>Skipped #2 because the person's legs are not visible in frame.r5   r	   r6   r   r7   r8   r   r   r   r   r   r   r   rW   rX   r@   rB   rC   rY   z#2rZ   r=   r?   )r4   r   	vton_noter   r   r   r    r!   r"   r#   r$   r%   r&   r'   r(   r)   )r   r   g1g2r   r*   r+   r,   r-   r.   r9   r0   rG   rH   rI   r2   r2   r3   test_vton_llm_note_parses_skipb   s   
llpra   c                    s   | j ddd|dfidI dH }|j}d}||k}|sOtd|fd	||fd
t v s0t|r5t|nd
t|t|d }dd|i }tt	|d } }}dS )u5   Missing garment_ids field → FastAPI validation 422.r5   r	   r6   r   r   Ni  r   r   r   r   r;   r   )
r   r   r   r    r!   r"   r#   r$   r'   r(   )r   r   r   r*   r+   r,   r-   r.   r2   r2   r3   )test_vton_missing_garment_ids_returns_422v   s   rb   monkeypatchc                    s  t |  I dH }ddtdtdtf fdd}|d| | jd	d
|gddI dH }|j}d}||k}|sptd|fd||fdt	
 v sKt|rPt|ndt|t|d }	t|jd d|	i }
tt|
d } }}| }|d }|j}d}||}|sdt|t|t|t|d }
tt|
d } } }}|d }|g}||k}|std|fd||ft|t|d }dd|i }tt|d } }}dS )zFimage_url path: server fetches the URL, then pipeline runs end-to-end.N      .@urltimeoutr   c                    s~   d}| |k}|s9t d|fd| |fdt v st | r#t | ndt |d }dd|i }tt |d  }} S )Nhttps://example.com/person.jpgr   )z%(py0)s == %(py3)sre   )r   rU   zassert %(py5)sr   )r   r    r!   r"   r#   r$   r'   r(   )re   rf   rG   r*   @py_format4r-   r   r2   r3   
fake_fetch   s   xz7test_vton_with_image_url_happy_path.<locals>.fake_fetch"app.routers.vton.fetch_image_bytesr5   rg   	image_urlr7   r9   r   r   r   r   r   r   r   rQ   rR   rS   rT   rW   rX   r@   rB   rC   rd   )r4   rK   floatbytessetattrr   r   r   r    r!   r"   r#   r$   r%   r&   r'   r(   r)   r[   )r   r   rc   r/   rj   r   r*   r+   r,   r-   r.   r9   r0   rG   r\   rH   rI   r2   ri   r3   #test_vton_with_image_url_happy_path   s   fprs   c                    s6  t | |I dH }| jddd|dfid|gddI dH }|j}d	}||k}|s\td
|fd||fdt v s=t|rBt|ndt|t|d }dd|i }t	t
|d } }}d}	| d }|	|v }
|
std|
fd|	|ft|	t|d }dd|i }t	t
|d }	 }
}dS )u6   Providing both image file and image_url → 400 (XOR).Nr5   r	   r6   r   rg   rl   r8   r:   r   r   r   r   r;   r   r<   r=   r?   r@   rB   rC   r4   r   r   r   r    r!   r"   r#   r$   r'   r(   r)   rF   r2   r2   r3   (test_vton_both_image_and_url_returns_400   s   rru   c                    s(  t | |I dH }| jdd|gidI dH }|j}d}||k}|sUtd|fd||fdt v s6t|r;t|ndt|t|d	 }d
d|i }t	t
|d } }}d}	| d }|	|v }
|
std|
fd|	|ft|	t|d }dd|i }t	t
|d }	 }
}dS )u9   Providing neither image file nor image_url → 400 (XOR).Nr5   r7   rn   r:   r   r   r   r   r;   r   r	   r<   r=   r?   r@   rB   rC   rt   rF   r2   r2   r3   +test_vton_neither_image_nor_url_returns_400   s   rrv   c                    sN  t | |I dH }ddtdtdtfdd}|d| | jd	d
|gddI dH }|j}d}||k}|shtd|fd||fdt	
 v sIt|rNt|ndt|t|d }	dd|	i }
tt|
d } }}d}| d }||v }|std|fd||ft|t|d }dd|i }tt|d } }}dS )uF   Server-side URL fetch raising ValueError → 400 propagated to client.Nrd   re   rf   r   c                    s
   t d)Nu3   이미지를 가져오지 못했습니다: HTTP 404)
ValueError)re   rf   r2   r2   r3   failing_fetch   s   zDtest_vton_image_url_fetch_failure_returns_400.<locals>.failing_fetchrk   r5   zhttps://example.com/missing.jpgrl   rn   r:   r   r   r   r   r;   r   zHTTP 404r<   r=   r?   r@   rB   rC   ro   )r4   rK   rp   rq   rr   r   r   r   r    r!   r"   r#   r$   r'   r(   r)   )r   r   rc   r/   rx   r   r*   r+   r,   r-   r.   r0   rG   rH   rI   r2   r2   r3   -test_vton_image_url_fetch_failure_returns_400   s   rry   )__doc__builtinsr!   _pytest.assertion.rewrite	assertionrewriter   rL   pytesthttpxr   tests.conftestr   r   GLOBAL_USER_IDrq   rK   r4   markasynciorJ   rO   rP   r]   ra   rb   MonkeyPatchrs   ru   rv   ry   r2   r2   r2   r3   <module>   sn    "