
    i&H                         d 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d Z	d Z
	 	 ddeded	ed
ee   dz  def
dZdedededefdZdededefdZ G d d      Z G d d      Z G d d      Zy)ul  
test_signature_check.py — signature_check verifier + verify-done.py 테스트

작성자: 아르고스 (개발1팀 테스터)
task-1972: .done 자동 검증 게이트 구현 테스트 (TDD RED)

테스트 대상:
  - teams/shared/verifiers/signature_check.py :: verify(task_id, workspace_root)
  - scripts/verify-done.py :: verify_done(task_id, workspace_root)
    N)Path)patch	MagicMockc                  l    t         j                  j                  dd       dd l} | j	                  d      S )Nr   z*/home/jay/workspace/teams/shared/verifierssignature_check)syspathinsert	importlibimport_moduler   s    K/home/jay/workspace/.worktrees/task-2116-dev1/tests/test_signature_check.py_import_signature_checkr      s*    HHOOACD""#455    c                      t         j                  j                  dd       dd l} | j	                  dj                  dd            S )Nr   z/home/jay/workspace/scriptszverify-done-_)r   r	   r
   r   r   replacer   s    r   _import_verify_doner      s6    HHOOA45""=#8#8c#BCCr   tmp_pathtask_idlevel
signaturesreturnc                 .   | dz  dz  }|j                  dd       d| dg}|r|j                  d| d       |-|j                  d	       |D ]  }|j                  d
| d        dj                  |      }|| dz  }|j                  |d       |S )u*   tmp_path/memory/tasks/{task_id}.md 생성.memorytasksTparentsexist_okz# u*   : 테스트용 task

## 목적
테스트.
u   
## 레벨
- 
u   
## 완료 시그니처
z-  z.mdutf-8encoding)mkdirappendjoin
write_text)	r   r   r   r   	tasks_dirlinessigcontent	task_files	            r   _make_task_filer/   '   s     8#g-IOOD4O0'HIJEugR0112 	'CLL2cU"&	' ggenGwisO+I73r   rel_pathr-   c                 p    | |z  }|j                   j                  dd       |j                  |d       |S )u(   tmp_path 하위에 코드 파일 생성.Tr   r#   r$   )parentr&   r)   )r   r0   r-   targets       r   _make_code_filer4   A   s;     F
MMt4
g0Mr   c                 z    | dz  dz  }|j                  dd       || dz  }|j                  d| dd	       |S )
u-   tmp_path/memory/events/{task_id}.done 생성.r   eventsTr   z.donezdone: r!   r#   r$   )r&   r)   )r   r   
events_dir	done_files       r   _make_done_filer9   I   sW    H$x/JTD1y..I6'"-@r   c                   p    e Zd ZdZdefdZdefdZdefdZdefdZdefdZ	defdZ
defd	Zdefd
Zy)TestSignatureCheckVerifyu*   signature_check.verify() 유닛 테스트.r   c                     t               }d}d}d}t        |||       t        ||dd| dg       |j                  |t	        |            }|d	   d
k(  s
J d|        d|v sJ y)u8   시나리오 1: grep 패턴이 파일에 존재 → PASSztask-test-passscripts/sample.pyz#def my_function():
    return True
normalz[grep] `def my_function` @ ``r   r   workspace_rootstatusPASS   PASS 기대, 실제: detailsNr   r4   r/   verifystr)selfr   scr   code_relcode_contentresults          r   test_signature_pass_grep_existsz8TestSignatureCheckVerify.test_signature_pass_grep_existsY   s    $&"&>(L96xjBC		
 73x=Ah6)K-B6(+KK)F"""r   c                     t               }d}d}t        ||d       t        ||dd| dg       |j                  |t	        |            }|d	   d
k(  s
J d|        d|v sJ y)u8   시나리오 2: grep 패턴이 파일에 없음 → FAILztask-test-failr=   zdef other_function():
    pass
r>   z![grep] `def missing_function` @ `r?   r@   rA   rC   FAIL   FAIL 기대, 실제: rF   NrG   rJ   r   rK   r   rL   rN   s         r    test_signature_fail_grep_missingz9TestSignatureCheckVerify.test_signature_fail_grep_missingn   s    $&"&(,OP;H:QGH		
 73x=Ah6)K-B6(+KK)F"""r   c                     t               }d}t        ||       |j                  |t        |            }|d   dk(  s
J d|        d|v sJ y)uO   시나리오 3: 시그니처 섹션 없는 기존 task → SKIP (하위 호환)ztask-old-no-sigrA   rC   SKIP   SKIP 기대, 실제: rF   Nr   r/   rH   rI   rJ   r   rK   r   rN   s        r   test_signature_skip_no_sectionz7TestSignatureCheckVerify.test_signature_skip_no_section   s]    $&#'*73x=Ah6)K-B6(+KK)F"""r   c                    t               }d}d}t        ||d       t        ||dd| ddg       t        d	      5 }t	        d
dd      |_        |j                  |t        |            }ddd       d   dv s
J d|        j                  D cg c]>  }|j                  r0t        |j                  d
   t              rd|j                  d
   v r|@ }}t        |      d
k(  s
J d|        y# 1 sw Y   xY wc c}w )uX   시나리오 4: Lv.1-2 (normal) task → [pytest] 시그니처는 무시, grep만 검증ztask-lv1-normalzscripts/feature.pyzFEATURE_FLAG = True
r>   z[grep] `FEATURE_FLAG` @ `r?   z0[pytest] `tests/test_feature.py::test_something`r@   subprocess.runr   r"   
returncodestdoutstderrrA   NrC   )rD   rV   u5   normal 레벨에서 PASS 또는 SKIP 기대, 실제: pytestu:   Lv.1-2 (normal)에서 pytest 호출이 있으면 안 됨: r   r4   r/   r   r   return_valuerH   rI   call_args_listargs
isinstancelistlen)	rJ   r   rK   r   rL   mock_runrN   callpytest_callss	            r   test_level_normal_grep_onlyz4TestSignatureCheckVerify.test_level_normal_grep_only   s1   $&#'(,CD+H:Q7B			
 #$ 	F$-2b$QH!YYws8}YEF	F h#33 	
CF8L	
3 &44
yyZ		!d;DIIVWL@X 
 
 < A% 	
HW	
%	F 	F
s   0C1AC=1C:c                 <   t               }d}d}t        ||d       t        ||dd| ddg       g fd	}t        d
|      5  |j	                  |t        |            }ddd       t              dkD  sJ d       d   dv s
J d|        y# 1 sw Y   0xY w)uD   시나리오 5: Lv.3+ (critical) → [grep] + [pytest] 모두 검증ztask-lv3-criticalzscripts/secure.pyzdef validate_token(): pass
criticalz[grep] `def validate_token` @ `r?   z.[pytest] `tests/test_secure.py::test_validate`r@   c                     t        |       }d|v rj                  |        t        ddd      S t        t        j
                  d      r#t	        j
                  j                  | g|i |S t        ddd      S )Nra   r   1 passedr"   r]   __wrapped__match)rI   r'   r   hasattr
subprocessrunrq   )cmdre   kwargscmd_strpytest_calleds       r   fake_runzBTestSignatureCheckVerify.test_level_critical_all.<locals>.fake_run   s    #hG7"$$S) AjLLGNz~~_lGm:>>--cCDCFC  fs|  IJ  SZ  ce  tf  fr   r\   side_effectrA   Nr   u5   Lv.3+ (critical)에서 pytest 호출이 있어야 함rC   )rD   rQ   u7   critical 레벨에서 PASS 또는 FAIL 기대, 실제: r   r4   r/   r   rH   rI   rh   )rJ   r   rK   r   rL   rz   rN   ry   s          @r   test_level_critical_allz0TestSignatureCheckVerify.test_level_critical_all   s    $&%&(,JK1(1=@		
 	f #: 	FYYws8}YEF	F =!A% 	
C	
% h#33 	
EfXN	
3	F 	Fs   BBc           	          t               }d}d}t        ||d       t        ||dd| dd| dg       |j                  |t	        |      	      }|d
   dk(  s
J d|        y)u;   여러 grep 시그니처 중 하나라도 실패하면 FAILztask-multi-grepzscripts/multi.pyzdef present_func():
    pass
r>   z[grep] `def present_func` @ `r?   z[grep] `def absent_func` @ `r@   rA   rC   rQ   u,   일부 grep 실패 시 FAIL 기대, 실제: NrG   rS   s         r   test_grep_signature_multiplez5TestSignatureCheckVerify.test_grep_signature_multiple   s    $&#%(,MN/z;.xj:		
 73x=Ah6) 	
:6(C	
)r   c                     t               }d}t        ||ddg       |j                  |t        |            }|d   dk(  s
J d|        y	)
u1   grep 대상 파일이 존재하지 않으면 FAILztask-no-filer>   z0[grep] `some_pattern` @ `scripts/nonexistent.py`r@   rA   rC   rQ   u*   파일 미존재 시 FAIL 기대, 실제: NrX   rY   s        r   test_signature_file_not_foundz6TestSignatureCheckVerify.test_signature_file_not_found   sb    $& JK		
 73x=Ah6) 	
8A	
)r   c                 x    t               }d}|j                  |t        |            }|d   dk(  s
J d|        y)u;   task 파일 자체가 없으면 SKIP (graceful degradation)z
task-ghostrA   rC   rV   u,   task 파일 없을 때 SKIP 기대, 실제: N)r   rH   rI   rY   s        r   %test_task_file_not_found_returns_skipz>TestSignatureCheckVerify.test_task_file_not_found_returns_skip	  sK    $& 73x=Ah6) 	
:6(C	
)r   N)__name__
__module____qualname____doc__r   rO   rT   rZ   rl   r~   r   r   r    r   r   r;   r;   V   sg    4# #*# #(#t #%
D %
N%
 %
N
T 
2
d 
&
d 
r   r;   c                   L    e Zd ZdZdefdZdefdZdefdZdefdZdefdZ	y)	TestVerifyDoneu.   verify-done.py verify_done() 유닛 테스트.r   c                    t               }d}d}t        ||d       t        ||dd| dg       t        ||      }|j	                  |t        |            }|d	   d
k(  s
J d|        |d   dk(  s
J d|        d|v sJ |j                         sJ d       |j                  | dz  }|j                         rJ d       y)uR   .done 파일 + 시그니처 검증 PASS → .done 유지, status=PASS, action=keepztask-vd-passzscripts/app.pyzdef main(): pass
r>   z[grep] `def main` @ `r?   r@   rA   rC   rD   rE   actionkeepu   action=keep 기대, 실제: rF   u#   .done 파일이 유지되어야 함.done.rejectedu-   .done.rejected 파일이 생성되면 안 됨N)r   r4   r/   r9   verify_donerI   existsr2   )rJ   r   vdr   rL   r8   rN   rejected_files           r   test_verify_done_passz$TestVerifyDone.test_verify_done_pass  s     " #(,@A/z;<		
 $Hg6	HFh6)K-B6(+KK)h6)R-I&+RR)F""" !H#HH!!((gYn+EE '')Z+ZZ))r   c                    t               }d}d}t        ||d       t        ||dd| dg       t        ||      }|j	                  |t        |            }|d	   d
k(  s
J d|        |d   dk(  s
J d|        d|v sJ d|v s
J d|        t        |d         dkD  s
J d|        |dz  dz  }|| dz  }|j                         sJ d       y)uP   .done 파일 + 시그니처 검증 FAIL → .done.rejected 생성, action=rejectztask-vd-failzscripts/broken.pyz# empty
r>   z"[grep] `def required_function` @ `r?   r@   rA   rC   rQ   rR   r   rejectu   action=reject 기대, 실제: rF   failed_signaturesu*   FAIL 시 failed_signatures 포함 필요: r   u4   실패한 시그니처가 1개 이상이어야 함: r   r6   r   u,   .done.rejected 파일이 생성되어야 함N)r   r4   r/   r9   r   rI   rh   r   )	rJ   r   r   r   rL   r8   rN   r7   r   s	            r   &test_verify_done_fail_creates_rejectedz5TestVerifyDone.test_verify_done_fail_creates_rejected:  s9    " &(K8<XJaHI		
 $Hg6	HFh6)K-B6(+KK)h8+V/MfX-VV+F""" #f, 	
8A	
, 6-./!3 	
B6(K	
3
 (83
"y%??##%U'UU%r   c                     t               }d}t        ||       t        ||       |j                  |t	        |            }|d   dk(  s
J d|        |d   dk(  s
J d|        d	|v sJ y
)uE   시그니처 섹션 없는 task → SKIP, action=skip (하위 호환)ztask-vd-skiprA   rC   rV   rW   r   skipu   action=skip 기대, 실제: rF   N)r   r/   r9   r   rI   )rJ   r   r   r   rN   s        r   "test_verify_done_skip_no_signaturez1TestVerifyDone.test_verify_done_skip_no_signature^  s     " '*'*HFh6)K-B6(+KK)h6)R-I&+RR)F"""r   c                 H   t               }d}d}t        ||d       t        ||dd| dg       t        ||       |j	                  |t        |            }|d	z  d
z  }|| dz  }|j                         r+|j                  d      }||v sd|v sd|v s
J d|       yyyy)uH   .done.rejected 생성 시 거절 사유가 파일에 기록되어야 함ztask-vd-reasonzscripts/impl.pyz# no matching content
r>   z[grep] `class MyClass` @ `r?   r@   rA   r   r6   r   r#   r$   rQ   zclass MyClassu7   .done.rejected 파일에 사유 기록 필요. 내용: N)r   r4   r/   r9   r   rI   r   	read_text)	rJ   r   r   r   rL   rN   r7   r   r-   s	            r   0test_verify_done_rejected_contains_reject_reasonz?TestVerifyDone.test_verify_done_rejected_contains_reject_reasonm  s     ""$(,EF4XJa@A		
 	'*HF (83
"y%??!#--w-?Gg%7):oQX>X I'UX>X):% "r   c                 V   t               }d}d}t        ||d       t        ||dd| dg       t        ||       t	        d      5 }t        d	d
d
      |_        |j                  |t        |            }ddd       d   dk(  sJ |d   dk(  sJ d|v sJ d       y# 1 sw Y   )xY w)uO   .done.rejected 시 자동 재위임 메시지 관련 정보가 result에 포함ztask-vd-delegatezscripts/gate.pyz# placeholder
rn   z[grep] `def gate_function` @ `r?   r@   r\      r"   r]   rA   NrC   rQ   r   r   r   u=   재위임 메시지 전송을 위해 failed_signatures 필요)	r   r4   r/   r9   r   r   rc   r   rI   )rJ   r   r   r   rL   ri   rN   s          r   1test_verify_done_autodelegate_message_on_rejectedz@TestVerifyDone.test_verify_done_autodelegate_message_on_rejected  s     "$$(,=>0
!<		
 	'* #$ 	K$-2b$QH!^^GCM^JF	K h6)))h8+++ #f, 	
K	
,	K 	Ks   0BB(N)
r   r   r   r   r   r   r   r   r   r   r   r   r   r   r     sF    8[d [8"Vt "VH#4 # :
$ 
r   r   c                   (    e Zd ZdZdefdZdefdZy)TestLevelDetectionu&   레벨 판별 관련 통합 테스트.r   c                    t               }d}d}t        ||d       t        ||dd| ddg       g fd	}t        d
|      5  |j	                  |t        |             ddd       t              dkD  sJ d       y# 1 sw Y   xY w)uB   security 레벨도 Lv.3+로 취급 → grep + pytest 모두 검증ztask-security-levelzscripts/auth.pyzdef authenticate(): pass
securityz[grep] `def authenticate` @ `r?   z0[pytest] `tests/test_auth.py::test_authenticate`r@   c                 x    dt        |       v rj                  |        t        ddd      S t        ddd      S )Nra   r   rp   r"   r]   rr   )rI   r'   r   )rv   re   rw   ry   s      r   rz   zLTestLevelDetection.test_security_level_treated_as_critical.<locals>.fake_run  s;    3s8#$$S) AjLL'"EEr   r\   r{   rA   Nr   uC   security 레벨에서 pytest 호출이 있어야 함 (Lv.3+ 취급)r}   )rJ   r   rK   r   rL   rz   ry   s         @r   'test_security_level_treated_as_criticalz:TestLevelDetection.test_security_level_treated_as_critical  s    $&'$(,HI/z;B		
 	F #: 	=IIgc(mI<	= =!A% 	
Q	
%	= 	=s   BB
c                    t               }d}d}t        ||d       t        ||d| dg       t        d      5 }t	        dd	d
      |_        |j                  |t        |            }ddd       j                  D cg c]>  }|j                  r0t        |j                  d   t              rd|j                  d   v r|@ }}t        |      dk(  sJ d       y# 1 sw Y   rxY wc c}w )u6   레벨 섹션 없으면 기본적으로 grep만 검증ztask-no-levelzscripts/default.pyzDEFAULT_VALUE = 42
z[grep] `DEFAULT_VALUE` @ `r?   )r   r\   r   rr   r"   r]   rA   Nra   u0   레벨 미지정 시 pytest 호출 없어야 함rb   )	rJ   r   rK   r   rL   ri   rN   crk   s	            r   +test_no_level_section_defaults_to_grep_onlyz>TestLevelDetection.test_no_level_section_defaults_to_grep_only  s    $&!'(,BC 	4XJa@A	
 #$ 	F$-7SU$VH!YYws8}YEF	F
  ..
vv*QVVAY5(affQi:O 
 
 < A% 	
>	
%	F 	F
s   0C AC'C$N)r   r   r   r   r   r   r   r   r   r   r   r     s    0
 
B
D 
r   r   )r"   N)r   r   rt   pathlibr   unittest.mockr   r   ra   r   r   rI   rg   r/   r4   r9   r;   r   r   r   r   r   <module>r      s   	    * 6D #'	  S	D 	
 
4d c C D d S T ~
 ~
JN
 N
j>
 >
r   