o
    j7$                     @   s  U 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 ddlmZ ddlZddlZddlZddlmZmZ ddlmZmZmZ ddlmZ dd	lmZ dd
lmZm Z m!Z!m"Z"m#Z# ddl$m%Z% ddl&m'Z' ddl(m)Z) ddl*m+Z+ ddl,m-Z- ddl.m/Z/m0Z0m1Z1m2Z2m3Z3 ddl4m5Z5 e6dZ7eej8dedZ9ee9ddZ:da;edB e<d< de
edf fddZ=dZ>G dd de/Z?e? Z@dd ZAdd  ZBd!d" ZCeC ZDd#d$ ZEe ZFd%d& eFjG_Hd'd( ZIejJde
edf fd)d*ZKejJdeLfd+d,ZMdS )-z?Shared fixtures for pytest: async DB, httpx test client, mocks.    N)AsyncGenerator)Path)	MagicMock)ASGITransportAsyncClient)AsyncSessionasync_sessionmakercreate_async_engine)NullPool)settings)get_dbget_face_serviceget_garment_serviceget_llm_providerget_vton_serviceapp)FaceEmbedding)Garment)FaceService)GarmentService)BaseLLMProviderGarmentAnalysisStyleAnalysisStyleAnalysisTempStyleCategoryScore)VtonServicez$00000000-0000-0000-0000-000000000000F)echo	poolclass)expire_on_commit_test_sessionreturnc                  C  s   d } t | u}|s9td|fdt | fdt v stt r#tt ndt| d }dd|i }tt|d  }} t V  d S )N)is not)z%(py0)s is not %(py3)sr    )py0py3zassert %(py5)spy5)	r    
@pytest_ar_call_reprcompare@py_builtinslocals_should_repr_global_name	_safereprAssertionError_format_explanation)@py_assert2@py_assert1@py_format4@py_format6 r2   ./home/ubuntu/ootd-poc-server/tests/conftest.py_override_get_db4   s   x
r4   sB   PNG

   IHDR         ĉ   
IDATxc    
    IENDB`c                   @   s   e Zd ZU dZdZedB ed< eZe	dB ed< de	de
e fdd	Z	dde	d
edededB de	dB f
ddZ	dde	de
e	 de
e dedB dee	dB edB f f
ddZde	defddZde	defddZdS )MockLLMProviderzJLLM provider that returns deterministic results without calling real APIs.Used all garments.N	vton_note
vton_imageimager!   c                    s*   t ddddgdddgdd	gd
ddgS )Ntopzt-shirtu   검정 반팔 티셔츠blacksolidcottoncasualregulardailyunknown)colorpatternmaterialstylefitoccasionbrand)category_maincategory_subdescriptiontags)r   selfr9   r2   r2   r3   analyze_garmentN   s   zMockLLMProvider.analyze_garmentitemmodeimage_modelc                    s   t S N)_ONE_PX_PNG)rN   r9   rP   rQ   rR   r2   r2   r3   generate_ghost_mannequin`   s   z(MockLLMProvider.generate_ghost_mannequinperson_imageghost_images
categoriesc                    s   | j | jfS rS   )r8   r7   )rN   rV   rW   rX   rR   r2   r2   r3   generate_vtoni   s   zMockLLMProvider.generate_vtonc                    s2   t tdddtdddtdddddd	d
gdS )N   u   색상 조합이 좋습니다.)scorecomment   u   핏이 적절합니다.u   디테일이 돋보입니다.g      @u.   전체적으로 균형 잡힌 코디입니다.r>   minimal)color_palette
silhouettedetailoverall_scoreoverall_comment
style_tags)r   r   rM   r2   r2   r3   analyze_styler   s   


zMockLLMProvider.analyze_stylec                    s   t ddddddS )Nu-   출근룩으로는 무난한 조합입니다.u+   오늘 일정은 적절한 복장입니다.u.   오늘 날씨는 적합한 옷차림입니다.u*   전체적인 배색은 조화롭습니다.uB   더 완벽한 코디를 위해 액세서리를 추가해보세요.)time_contextoccasion_contextweather_contextcolor_harmonyimprovement_tips)r   rM   r2   r2   r3   analyze_style_temp|   s   z"MockLLMProvider.analyze_style_temprS   )__name__
__module____qualname____doc__r7   str__annotations__rT   r8   byteslistr   rO   rU   tuplerY   r   re   r   rk   r2   r2   r2   r3   r5   G   s>   
 

	
r5   c                   C   s   t S rS   )	_mock_llmr2   r2   r2   r3   _override_get_llm_provider   s   rv   c                   C   s   t ttdS )N)llm_providersegmentation_service)r   ru   _mock_segmentationr2   r2   r2   r3   _override_get_garment_service   s   rz   c                  C   sF   t  } tjddtj}|tj| }|| j	_
|g| j_
| S )z@Create a mock FaceAnalyzer that returns a fixed 512-d embedding.*   i   )r   nprandomdefault_rngstandard_normalastypefloat32linalgnormget_largest_face_embeddingreturn_valueget_embeddings)analyzerfixed_embeddingr2   r2   r3   _make_mock_face_analyzer   s   
r   c                   C   s
   t tdS )N)r   )r   _mock_analyzerr2   r2   r2   r3   _override_get_face_service   s   
r   c                 K   s   | S rS   r2   )image_bytes_r2   r2   r3   <lambda>   s    r   c                   C   s   t tttdS )N)rw   face_analyzerrx   )r   ru   r   ry   r2   r2   r2   r3   _override_get_vton_service   s
   r   c                  C  s  dt _tt _tjjgtj_tt	j
t< tt	j
t< tt	j
t< tt	j
t< tt	j
t< tj} t }|t_t 4 I dH c}| I dH }t|dda| I dH  tj tj!ddd }t"t	d}t#|d	d
4 I dH }|V  W d  I dH  n1 I dH s~w   Y  t$ I dH  |% I dH  daW d  I dH  n1 I dH sw   Y  | t_W d   n1 sw   Y  t	j
&  dS )zProvide an async test client with all dependencies overridden.

    Each test runs inside a DB transaction that is rolled back at the end,
    so test data never persists in the real database.
    r6   NF)bindr   after_transaction_endc                 S   s"   |j r|jj s|   d S d S d S rS   )nested_parentbegin_nested)sessiontransactionr2   r2   r3   restart_savepoint   s   z!client.<locals>.restart_savepointr   zhttp://test)	transportbase_url)'ru   r7   rT   r8   r   r   r   r   r4   r   dependency_overridesr   rv   r   rz   r   r   r   r   r   r   
UPLOAD_DIRtempfileTemporaryDirectoryTEST_ENGINEconnectbeginr   r    r   
sqlalchemyeventlistens_forsync_sessionr   r   closerollbackclear)original_upload_dirtmp_dirconntxnr   r   acr2   r2   r3   client   s<   








((r   c                  C   sB   ddl } ddlm} |jdddd}|  }|j|dd	 | S )
z0Return a minimal valid JPEG image (100x100 red).r   N)ImageRGB)d   r   )   r   r   )rB   JPEG)format)ioPILr   newBytesIOsavegetvalue)r   r   imgbufr2   r2   r3   sample_jpeg   s   r   )Nro   builtinsr(   _pytest.assertion.rewrite	assertionrewriter&   r   uuidcollections.abcr   pathlibr   unittest.mockr   numpyr|   pytestr   httpxr   r   sqlalchemy.ext.asyncior   r   r	   sqlalchemy.poolr
   
app.configr   app.dependenciesr   r   r   r   r   app.mainr   app.models.facer   app.models.garmentr   app.services.face_servicer   app.services.garment_servicer   app.services.llm.baser   r   r   r   r   app.services.vton_servicer   UUIDGLOBAL_USER_IDDATABASE_URLr   TestSessionFactoryr    rq   r4   rT   r5   ru   rv   rz   r   r   r   ry   remove_backgroundside_effectr   fixturer   rr   r   r2   r2   r2   r3   <module>   sT    "
?
=