
    Ti*                       d Z ddlmZ ddlZddlmc mZ ddl	Z	ddl
Z
ddlmZ ddlmZmZ ddlZe
j"                  j%                  d e ee      j*                  j*                  j*                               ddlmZmZmZmZ ddZ G d d	      Z G d
 d      Z G d d      Z G d d      Z G d d      Z  G d d      Z! G d d      Z"y)u@   utils/event_hooks.py 테스트 스위트 (TDD — RED → GREEN)    )annotationsN)Path)	MagicMockpatch)EventHookRegistryemitget_registryc                     t               S )u+   싱글턴 우회용 독립 레지스트리.)r        3/home/jay/workspace/utils/tests/test_event_hooks.py_fresh_registryr      s
    >r   c                  .    e Zd ZdZd Zd Zd Zd Zd Zy)TestHandlerRegistrationu   핸들러 등록 기본 동작c                $   t               }g fd}|j                  t        j                  |       t	        j
                  |j                  t        j                  ddi             ddig}|k(  }|st        j                  d|fd|f      dt        j                         v st        j                        rt        j                        ndt        j                  |      dz  }dd	|iz  }t        t        j                  |            d
x}}y
)u=   동기 핸들러를 이벤트 타입에 등록할 수 있다.c                (    j                  |        y Nappendctxcalleds    r   handlerzCTestHandlerRegistration.test_register_sync_handler.<locals>.handler(   s    MM#r   x   ==z%(py0)s == %(py3)sr   py0py3assert %(py5)spy5N)r   registerr   DISPATCH_STARTasynciorunr	   
@pytest_ar_call_reprcompare@py_builtinslocals_should_repr_global_name	_safereprAssertionError_format_explanationselfregr   @py_assert2@py_assert1@py_format4@py_format6r   s          @r   test_register_sync_handlerz2TestHandlerRegistration.test_register_sync_handler#   s    	 	U))73CHHU11C8<=(#v####v######v###v##########r   c                   t               }g fd}|j                  t        j                  |       t	        j
                  |j                  t        j                  d             dg}|k(  }|st        j                  d|fd|f      dt        j                         v st        j                        rt        j                        ndt        j                  |      dz  }dd|iz  }t        t        j                  |            d	x}}y	)
u@   비동기 핸들러를 이벤트 타입에 등록할 수 있다.c                0   K   j                  |        y wr   r   r   s    r   r   zDTestHandlerRegistration.test_register_async_handler.<locals>.handler4   s     MM#   hellor   r   r   r    r#   r$   N)r   r%   r   SESSION_STARTr'   r(   r	   r)   r*   r+   r,   r-   r.   r/   r0   r1   s          @r   test_register_async_handlerz3TestHandlerRegistration.test_register_async_handler/   s    	 	U(('2CHHU00':;!"v""""v""""""v"""v""""""""""r   c                *   t               }d }|j                  t        j                  |d       |j                  j                  t        j                  g       D cg c]  }|d   	 }}d}||v }|st        j                  d|fd||f      t        j                  |      dt        j                         v st        j                  |      rt        j                  |      nddz  }d	d
|iz  }t        t        j                  |            dx}}yc c}w )u@   name 파라미터로 핸들러에 이름 부여가 가능하다.c                     y r   r   r   s    r   r   zDTestHandlerRegistration.test_register_named_handler.<locals>.handler?   s    r   
my_handler)namerC   inz%(py1)s in %(py3)snamespy1r"   r#   r$   N)r   r%   r   
AGENT_STEP	_handlersgetr)   r*   r.   r+   r,   r-   r/   r0   )	r2   r3   r   inforG   @py_assert0r4   r6   r7   s	            r   test_register_named_handlerz3TestHandlerRegistration.test_register_named_handler;   s    	 	U%%w\B*---*;*;E<L<Lb*QR$fRR$|u$$$$|u$$$|$$$$$$u$$$u$$$$$$$ Ss   Dc                   t               }g |j                  t        j                  fd       |j                  t        j                  fd       t	        j
                  |j                  t        j                  d             g }d}|v }|}|rd}|v }|}|sXt        j                  d|fd|f      t        j                  |      dt        j                         v st        j                        rt        j                        ndd	z  }d
d|iz  }	|j                  |	       |rt        j                  dfdf      t        j                  |      dt        j                         v st        j                        rt        j                        nddz  }
dd|
iz  }|j                  |       t        j                  |d      i z  }dd|iz  }t        t        j                   |            dx}x}x}x}x}}y)u=   같은 이벤트에 여러 핸들러를 등록할 수 있다.c                &    j                  d      S )NAr   r   resultss    r   <lambda>zOTestHandlerRegistration.test_multiple_handlers_for_same_event.<locals>.<lambda>K       W^^C5H r   c                &    j                  d      S )NBr   rS   s    r   rU   zOTestHandlerRegistration.test_multiple_handlers_for_same_event.<locals>.<lambda>L   rV   r   NrR   rX   rD   z%(py3)s in %(py5)srT   r"   r$   %(py7)spy7z%(py10)s in %(py12)spy10py12%(py14)spy14r   assert %(py17)spy17)r   r%   r   DISPATCH_ENDr'   r(   r	   r)   r*   r.   r+   r,   r-   r   _format_boolopr/   r0   )r2   r3   r5   r4   @py_assert4rN   @py_assert9@py_assert11r7   @py_format8@py_format13@py_format15@py_format16@py_format18rT   s                 @r   %test_multiple_handlers_for_same_eventz=TestHandlerRegistration.test_multiple_handlers_for_same_eventF   s   U'')HIU'')HICHHU//670s0sg~0#0#.0000sg000s000000g000g0000000#000#00000000000000000000000r   c                b    t               }t        j                  |j                  di              y)uM   핸들러가 없는 이벤트에 emit해도 예외가 발생하지 않는다.znonexistent:eventN)r   r'   r(   r	   )r2   r3   s     r   test_no_handlers_emit_is_noopz5TestHandlerRegistration.test_no_handlers_emit_is_noopP   s"    CHH0"56r   N)	__name__
__module____qualname____doc__r8   r>   rO   ro   rq   r   r   r   r   r       s    (
$
#	%17r   r   c                  (    e Zd ZdZd Zd Zd Zd Zy)TestWildcardMatchingu+   dispatch:* 스타일 와일드카드 매칭c                   t               }g |j                  dfd       t        j                  |j	                  t
        j                  d             d}|v }|st        j                  d|fd|f      t        j                  |      dt        j                         v st        j                        rt        j                        nddz  }dd	|iz  }t        t        j                  |            d
x}}y
)u8   dispatch:* 핸들러가 dispatch:start 에 호출된다.
dispatch:*c                &    j                  |       S r   r   r   callss    r   rU   zLTestWildcardMatching.test_wildcard_matches_prefixed_events.<locals>.<lambda>c       u||C/@ r   srD   rF   r|   rH   r#   r$   N)r   r%   r'   r(   r	   r   r&   r)   r*   r.   r+   r,   r-   r/   r0   )r2   r3   rN   r4   r6   r7   r|   s         @r   %test_wildcard_matches_prefixed_eventsz:TestWildcardMatching.test_wildcard_matches_prefixed_events^   s    \#@ACHHU11378se|seseer   c                d   t               }g |j                  dfd       t        j                  |j	                  t
        j                  d             t        j                  |j	                  t
        j                  d             ddg}|k(  }|st        j                  d|fd|f      dt        j                         v st        j                        rt        j                        ndt        j                  |      dz  }d	d
|iz  }t        t        j                  |            dx}}y)u9   dispatch:* 핸들러가 dispatch:end 에도 호출된다.ry   c                &    j                  |       S r   r   r{   s    r   rU   zLTestWildcardMatching.test_wildcard_matches_multiple_events.<locals>.<lambda>l   r}   r   r      r   r   r|   r    r#   r$   N)r   r%   r'   r(   r	   r   r&   re   r)   r*   r+   r,   r-   r.   r/   r0   r2   r3   r4   r5   r6   r7   r|   s         @r   %test_wildcard_matches_multiple_eventsz:TestWildcardMatching.test_wildcard_matches_multiple_eventsg   s    \#@ACHHU11156CHHU//34Auuuur   c                   t               }g |j                  dfd       t        j                  |j	                  t
        j                  d             g }|k(  }|st        j                  d|fd|f      dt        j                         v st        j                        rt        j                        ndt        j                  |      dz  }dd	|iz  }t        t        j                  |            d
x}}y
)uA   session:* 핸들러가 dispatch:start 에 호출되지 않는다.z	session:*c                &    j                  |       S r   r   r{   s    r   rU   zTTestWildcardMatching.test_wildcard_does_not_match_different_prefix.<locals>.<lambda>v   s    ell3.? r   r   r   r   r|   r    r#   r$   N)r   r%   r'   r(   r	   r   r&   r)   r*   r+   r,   r-   r.   r/   r0   r   s         @r   -test_wildcard_does_not_match_different_prefixzBTestWildcardMatching.test_wildcard_does_not_match_different_prefixq   s    ["?@CHHU11378u{uuur   c                   t               }g |j                  t        j                  fd       |j                  dfd       t	        j
                  |j                  t        j                  d             g }d}|v }|}|rd}|v }|}|sXt        j                  d|fd|f      t        j                  |      d	t        j                         v st        j                        rt        j                        nd	d
z  }dd|iz  }	|j                  |	       |rt        j                  dfdf      t        j                  |      d	t        j                         v st        j                        rt        j                        nd	dz  }
dd|
iz  }|j                  |       t        j                  |d      i z  }dd|iz  }t        t        j                   |            dx}x}x}x}x}}y)uR   정확한 이벤트 핸들러와 와일드카드 핸들러가 함께 호출된다.c                &    j                  d      S )Nexactr   r{   s    r   rU   zHTestWildcardMatching.test_exact_and_wildcard_both_fire.<locals>.<lambda>   s    u||G7L r   ry   c                &    j                  d      S )Nwildr   r{   s    r   rU   zHTestWildcardMatching.test_exact_and_wildcard_both_fire.<locals>.<lambda>   s    u||F/C r   Nr   r   rD   rY   r|   rZ   r[   r\   r]   r^   ra   rb   r   rc   rd   )r   r%   r   r&   r'   r(   r	   r)   r*   r.   r+   r,   r-   r   rf   r/   r0   )r2   r3   r5   r4   rg   rN   rh   ri   r7   rj   rk   rl   rm   rn   r|   s                 @r   !test_exact_and_wildcard_both_firez6TestWildcardMatching.test_exact_and_wildcard_both_firez   s   U))+LM\#CDCHHU114893w3w%3F3FeO3333w%333w333333%333%3333333Fe333F333333e333e33333333333333r   N)rr   rs   rt   ru   r   r   r   r   r   r   r   rw   rw   [   s    54r   rw   c                  "    e Zd ZdZd Zd Zd Zy)TestErrorIsolationuA   핸들러 예외가 메인 파이프라인을 블록하지 않음c                b   t               }g d }fd}|j                  t        j                  |       |j                  t        j                  |       t	        j
                  |j                  t        j                  i              dg}|k(  }|st        j                  d|fd|f      dt        j                         v st        j                        rt        j                        ndt        j                  |      dz  }dd	|iz  }t        t        j                  |            d
x}}y
)uI   동기 핸들러 예외가 catch 되어 다음 핸들러가 실행된다.c                    t        d      )Nboom)RuntimeErrorrA   s    r   bad_handlerzMTestErrorIsolation.test_sync_handler_exception_is_caught.<locals>.bad_handler   s    v&&r   c                (    j                  d       y NTr   r   second_calleds    r   good_handlerzNTestErrorIsolation.test_sync_handler_exception_is_caught.<locals>.good_handler         &r   Tr   r   r   r    r#   r$   N)r   r%   r   DISPATCH_ERRORr'   r(   r	   r)   r*   r+   r,   r-   r.   r/   r0   	r2   r3   r   r   r4   r5   r6   r7   r   s	           @r   %test_sync_handler_exception_is_caughtz8TestErrorIsolation.test_sync_handler_exception_is_caught   s    	'	' 	U));7U))<8CHHU11267!%&}&&&&}&&&&&&}&&&}&&&&&&&&&&r   c                b   t               }g d }fd}|j                  t        j                  |       |j                  t        j                  |       t	        j
                  |j                  t        j                  i              dg}|k(  }|st        j                  d|fd|f      dt        j                         v st        j                        rt        j                        ndt        j                  |      dz  }dd	|iz  }t        t        j                  |            d
x}}y
)uL   비동기 핸들러 예외도 catch 되어 다음 핸들러가 실행된다.c                    K   t        d      w)Nz
async boom)
ValueErrorrA   s    r   r   zNTestErrorIsolation.test_async_handler_exception_is_caught.<locals>.bad_handler   s     \**s   c                (    j                  d       y r   r   r   s    r   r   zOTestErrorIsolation.test_async_handler_exception_is_caught.<locals>.good_handler   r   r   Tr   r   r   r    r#   r$   N)r   r%   r   SESSION_ENDr'   r(   r	   r)   r*   r+   r,   r-   r.   r/   r0   r   s	           @r   &test_async_handler_exception_is_caughtz9TestErrorIsolation.test_async_handler_exception_is_caught   s    	+	' 	U&&4U&&5CHHU..34!%&}&&&&}&&&&&&}&&&}&&&&&&&&&&r   c                    t               }d }|j                  t        j                  |       t	        j
                  |j                  t        j                  i              y)u<   emit()을 호출한 쪽에 예외가 전파되지 않는다.c                    t        d      )Nzshould not propagate)	ExceptionrA   s    r   	explodingzQTestErrorIsolation.test_exception_does_not_propagate_to_caller.<locals>.exploding   s    233r   N)r   r%   r   SECURITY_BLOCKr'   r(   r	   )r2   r3   r   s      r   +test_exception_does_not_propagate_to_callerz>TestErrorIsolation.test_exception_does_not_propagate_to_caller   sB    	4 	U))95CHHU11267r   N)rr   rs   rt   ru   r   r   r   r   r   r   r   r      s    K' ' 	8r   r   c                      e Zd ZdZd Zd Zy)TestEmitSyncu    동기 컨텍스트용 emit_syncc                   t               }g |j                  t        j                  fd       |j	                  t        j                  d       dg}|k(  }|st        j                  d|fd|f      dt        j                         v st        j                        rt        j                        ndt        j                  |      dz  }dd|iz  }t        t        j                  |            d	x}}y	)
u)   emit_sync()가 핸들러를 호출한다.c                &    j                  |       S r   r   rS   s    r   rU   z;TestEmitSync.test_emit_sync_calls_handler.<locals>.<lambda>   s    gnnS6I r   pkgr   r   rT   r    r#   r$   Nr   r%   r   SKILL_INSTALL	emit_syncr)   r*   r+   r,   r-   r.   r/   r0   )r2   r3   r4   r5   r6   r7   rT   s         @r   test_emit_sync_calls_handlerz)TestEmitSync.test_emit_sync_calls_handler   s    U((*IJe))51 '!w'!!!!w'!!!!!!w!!!w!!!'!!!!!!!r   c                   t               }g fd}|j                  t        j                  |       |j	                  t        j                  d       dg}|k(  }|st        j                  d|fd|f      dt        j                         v st        j                        rt        j                        ndt        j                  |      dz  }dd|iz  }t        t        j                  |            d	x}}y	)
u3   emit_sync()가 비동기 핸들러도 실행한다.c                0   K   j                  |        y wr   r   rS   s    r   ahandlerz@TestEmitSync.test_emit_sync_runs_async_handler.<locals>.ahandler   s     NN3r;   	async_pkgr   r   rT   r    r#   r$   Nr   )r2   r3   r   r4   r5   r6   r7   rT   s          @r   !test_emit_sync_runs_async_handlerz.TestEmitSync.test_emit_sync_runs_async_handler   s    	  	U(((3e));7&-'w-''''w-''''''w'''w'''-'''''''r   N)rr   rs   rt   ru   r   r   r   r   r   r   r      s    *"
(r   r   c                      e Zd ZdZd Zd Zy)TestSingletonu%   get_registry()가 싱글턴을 반환c                   t               }t               }||u }|st        j                  d|fd||f      dt        j                         v st        j
                  |      rt        j                  |      nddt        j                         v st        j
                  |      rt        j                  |      nddz  }dd|iz  }t        t        j                  |            d}y)	uE   get_registry()를 두 번 호출하면 같은 객체를 반환한다.)is)z%(py0)s is %(py2)sr1r2r!   py2zassert %(py4)spy4N)	r
   r)   r*   r+   r,   r-   r.   r/   r0   )r2   r   r   r5   @py_format3@py_format5s         r   'test_get_registry_returns_same_instancez5TestSingleton.test_get_registry_returns_same_instance   s[    ^^RxrRrrRRr   c                   t               }g d}|j                  |fd       t        j                  t	        |d             d}|v }|st        j                  d|fd|f      t        j                  |      dt        j                         v st        j                        rt        j                        nddz  }dd	|iz  }t        t        j                  |            d
x}}y
)uR   전역 emit()이 싱글턴 레지스트리에 등록된 핸들러를 호출한다.ztest:singleton_emit_checkc                &    j                  |       S r   r   rS   s    r   rU   z?TestSingleton.test_global_emit_uses_singleton.<locals>.<lambda>   s    w~~c/B r   pingrD   rF   rT   rH   r#   r$   N)r
   r%   r'   r(   r	   r)   r*   r.   r+   r,   r-   r/   r0   )r2   r3   unique_eventrN   r4   r6   r7   rT   s          @r   test_global_emit_uses_singletonz-TestSingleton.test_global_emit_uses_singleton   s    n2\#BCDv./ v    v   v                r   N)rr   rs   rt   ru   r   r   r   r   r   r   r      s    /!r   r   c                  (    e Zd ZdZd Zd Zd Zd Zy)TestDiscoverAndLoadu8   HOOK.yaml + handler.py 디렉토리 기반 동적 로드c                |   |dz  }|j                          |dz  j                  dd       |dz  j                  dd       t               }|j                  t	        |             |j
                  j                  t        j                  g       |j
                  j                  dg       z   }t        |      }d	}||k\  }|st        j                  d
|fd||f      dt        j                         v st        j                  t              rt        j                  t              nddt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      dz  }dd|iz  }	t!        t        j"                  |	            dx}x}}y)uC   HOOK.yaml과 handler.py가 있는 훅이 자동으로 등록된다.myhook	HOOK.yamlz&event: dispatch:start
name: test_hook
utf-8encoding
handler.pyzdef handle(ctx):
    pass
zdispatch:startr   )>=)z0%(py3)s
{%(py3)s = %(py0)s(%(py1)s)
} >= %(py6)slenhandlers)r!   rI   r"   py6zassert %(py8)spy8N)mkdir
write_textr   discover_and_loadstrrK   rL   r   r&   r   r)   r*   r+   r,   r-   r.   r/   r0   )
r2   tmp_pathhook_dirr3   r   r4   @py_assert5rg   @py_format7@py_format9s
             r   .test_discover_registers_handler_from_directoryzBTestDiscoverAndLoad.test_discover_registers_handler_from_directory   s*   h&	K	++,Vah+i	L	 ,,* 	- 	

 c(m,==$$U%9%92>ARARScegAhh8}!!}!!!!}!!!!!!s!!!s!!!!!!8!!!8!!!}!!!!!!!!!!r   c                   |dz  }|j                          |dz  j                  dd       t               }|j                  t	        |             d}|s8ddt        j                  |      iz  }t        t        j                  |            d	}y	)
u1   HOOK.yaml이 없는 디렉토리는 무시된다.badhookr   zdef handle(ctx): pass
r   r   Tassert %(py1)srI   N	r   r   r   r   r   r)   r.   r/   r0   r2   r   r   r3   rN   @py_format2s         r    test_discover_skips_missing_yamlz4TestDiscoverAndLoad.test_discover_skips_missing_yaml	  se    i'	L	 ,,-FQX,Yc(m,ttr   c                   |dz  }|j                          |dz  j                  dd       t               }|j                  t	        |             d}|s8ddt        j                  |      iz  }t        t        j                  |            d	}y	)
u2   handler.py가 없는 디렉토리는 무시된다.nohookr   z!event: dispatch:start
name: test
r   r   Tr   rI   Nr   r   s         r   #test_discover_skips_missing_handlerz7TestDiscoverAndLoad.test_discover_skips_missing_handler  se    h&	K	++,Q\c+dc(m,ttr   c                    t               }|j                  d       d}|s8ddt        j                  |      iz  }t	        t        j
                  |            d}y)uM   존재하지 않는 디렉토리에 discover_and_load해도 예외가 없다.z!/tmp/nonexistent_hooks_dir_xyz123Tr   rI   N)r   r   r)   r.   r/   r0   )r2   r3   rN   r   s       r   %test_discover_nonexistent_dir_is_noopz9TestDiscoverAndLoad.test_discover_nonexistent_dir_is_noop  s4    ABttr   N)rr   rs   rt   ru   r   r   r   r   r   r   r   r   r      s    B""	r   r   c                      e Zd ZdZd Zy)TestEventConstantsu$   Event 클래스 상수 존재 확인c                ~
   t         j                  }|sddt        j                         v st	        j
                  t               rt	        j                  t               ndt	        j                  |      dz  }t        t	        j                  |            d}t         j                  }|sddt        j                         v st	        j
                  t               rt	        j                  t               ndt	        j                  |      dz  }t        t	        j                  |            d}t         j                  }|sddt        j                         v st	        j
                  t               rt	        j                  t               ndt	        j                  |      dz  }t        t	        j                  |            d}t         j                  }|sddt        j                         v st	        j
                  t               rt	        j                  t               ndt	        j                  |      dz  }t        t	        j                  |            d}t         j                  }|sddt        j                         v st	        j
                  t               rt	        j                  t               ndt	        j                  |      dz  }t        t	        j                  |            d}t         j                  }|sd	dt        j                         v st	        j
                  t               rt	        j                  t               ndt	        j                  |      dz  }t        t	        j                  |            d}t         j                  }|sd
dt        j                         v st	        j
                  t               rt	        j                  t               ndt	        j                  |      dz  }t        t	        j                  |            d}t         j                  }|sddt        j                         v st	        j
                  t               rt	        j                  t               ndt	        j                  |      dz  }t        t	        j                  |            d}t         j                   }|sddt        j                         v st	        j
                  t               rt	        j                  t               ndt	        j                  |      dz  }t        t	        j                  |            d}y)u+   모든 Event 상수가 정의되어 있다.z2assert %(py2)s
{%(py2)s = %(py0)s.DISPATCH_START
}r   r   Nz0assert %(py2)s
{%(py2)s = %(py0)s.DISPATCH_END
}z2assert %(py2)s
{%(py2)s = %(py0)s.DISPATCH_ERROR
}z1assert %(py2)s
{%(py2)s = %(py0)s.SESSION_START
}z/assert %(py2)s
{%(py2)s = %(py0)s.SESSION_END
}z.assert %(py2)s
{%(py2)s = %(py0)s.AGENT_STEP
}z2assert %(py2)s
{%(py2)s = %(py0)s.SECURITY_BLOCK
}z1assert %(py2)s
{%(py2)s = %(py0)s.SECURITY_WARN
}z1assert %(py2)s
{%(py2)s = %(py0)s.SKILL_INSTALL
})r   r&   r+   r,   r)   r-   r.   r/   r0   re   r   r=   r   rJ   r   SECURITY_WARNr   )r2   r5   r   s      r   test_event_constants_definedz/TestEventConstants.test_event_constants_defined-  s   #########u###u##########!!!!!!!!!u!!!u!!!!!!!!!!#########u###u##########"""""""""u"""u""""""""""         u   u          uu#########u###u##########"""""""""u"""u"""""""""""""""""""u"""u""""""""""r   N)rr   rs   rt   ru   r   r   r   r   r   r   *  s
    .
#r   r   )returnr   )#ru   
__future__r   builtinsr+   _pytest.assertion.rewrite	assertionrewriter)   r'   syspathlibr   unittest.mockr   r   pytestpathinsertr   __file__parentutils.event_hooksr   r   r	   r
   r   r   rw   r   r   r   r   r   r   r   r   <module>r     s    F "    
  *  3tH~,,33::; < E E37 37v'4 '4^,8 ,8h( (<! !2- -j# #r   