
    ~i"                       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ZddlZddlmZ ddlmZ ddlZ e ee      j)                         j*                  d         Zeej.                  vrej.                  j1                  de        e ee      j)                         j*                  d   dz        Zeej.                  vrej.                  j1                  de       dddZdd	Z	 	 	 	 	 	 dd
Z	 	 	 	 	 	 ddZ	 	 	 	 	 	 ddZy)u   
test_request_review.py — cmd_request_review 회귀 테스트.

1. bot author PR + human reviewer → PASS (gh pr edit monkeypatched)
2. human author PR + same reviewer → FAIL (self-approval or non-bot author)
    )annotationsN)Path)Any   scriptsc                >   | dz  dz  }|j                  dd       ||g dg dddi dddd	d}dd}t        j                   ||      j                               j	                         }||d	<   || d
z  }|j                  t        j                  |dd      d       y)u6   테스트용 task state json 생성 (checksum 포함)..tasksstateTparentsexist_okN)	git_diff_shachanged_pathsbranch	pr_numberpr_state	ci_checksguard_sh_resultgemini_evidence	qc_report)task_idcurrent_statetransitionsevidencec                    | j                         D ci c]  \  }}|dk7  s|| }}}t        j                  |ddd      S c c}}w )N	_checksumFT),:)ensure_ascii	sort_keys
separators)itemsjsondumps)skvpayloads       R/home/jay/workspace/.worktrees/task-2481-dev4/tests/scripts/test_request_review.py
_canonicalz_make_state.<locals>._canonical2   sF    $%GGIBDAqk1A1a4BBzz'R\]] Cs
   AAr   z.jsonFr   )r   indentutf-8encoding)r%   dictreturnstr)mkdirhashlibsha256encode	hexdigest
write_textr#   r$   )tmp_pathr   r   	state_dirr
   r*   checksum
state_paths           r)   _make_stater<      s    8#g-IOOD4O0 & ##

	E"^ ~~j/6689CCEH!E+y..J$**UqIT[\    c                6    ~ddl }|j                  | ddd      S )u   gh pr edit 성공 mock.r   N )
returncodestdoutstderr)
subprocessCompletedProcess)cmdkwargsrC   s      r)   _fake_run_successrG   =   s"    &&sqB&OOr=   c                   d}|j                  dt        |              |j                  dd       |j                  dd       | dz  dz  }|j                  d	d	
       |dz  j                  t	        j
                  dg g dd      d       |j                  t        j                  dd       t        | |d       ddl
}t        t              dz  dz  }|j                  j                  dt        |            }|j                  j                  |      }|j                   j#                  |       |j%                  |d|        |j%                  |d| dz  dz         |j%                  |d| dz  d z         |j%                  |d!t&               t)        j*                  |d"d#$      }|j-                  |      }	d}
|	|
k(  }|st/        j0                  d%|fd&|	|
f      d't3        j4                         v st/        j6                  |	      rt/        j8                  |	      nd't/        j8                  |
      d(z  }t/        j:                  d)|	       d*z   d+|iz  }t=        t/        j>                  |            dx}}
| dz  d z  |z  }tA        |jC                  d,            }|s{t/        j:                  d-      d.z   d/d0t3        j4                         v st/        j6                  |      rt/        j8                  |      nd0iz  }t=        t/        j>                  |            t	        jD                  |d1   jG                               }|jH                  }d'} ||      }d2}||k(  }|st/        j0                  d%|fd3||f      d4t3        j4                         v st/        j6                  |      rt/        j8                  |      nd4t/        j8                  |      t/        j8                  |      t/        j8                  |      t/        j8                  |      d5z  }t/        j:                  d6|       d7z   d8|iz  }t=        t/        j>                  |            dx}x}x}x}}g }|jH                  }d9} ||      }d}||k(  }|}|s,d:}|jH                  }d9}d;} |||      }t        |      } || v }!|!}|s[t/        j0                  d%|fd<||f      d4t3        j4                         v st/        j6                  |      rt/        j8                  |      nd4t/        j8                  |      t/        j8                  |      t/        j8                  |      t/        j8                  |      d=z  }d>d?|iz  }"|jK                  |"       |s9t/        j0                  d@!fdA f      t/        j8                  |      dBt3        j4                         v st/        j6                  t              rt/        j8                  t              ndBd4t3        j4                         v st/        j6                  |      rt/        j8                  |      nd4t/        j8                        t/        j8                        t/        j8                        t/        j8                        t/        j8                  |       dCz  }#dDdE|#iz  }$|jK                  |$       t/        jL                  |d      i z  }%t/        j:                  dF|       dGz   dH|%iz  }&t=        t/        j>                  |&            dx}x}x}x}x}x}x}x}x}!x}x}x}x}} |jH                  }dI} ||      }d#}||k(  }|st/        j0                  d%|fd3||f      d4t3        j4                         v st/        j6                  |      rt/        j8                  |      nd4t/        j8                  |      t/        j8                  |      t/        j8                  |      t/        j8                  |      d5z  }t/        j:                  dJ|jI                  dI             d7z   d8|iz  }t=        t/        j>                  |            dx}x}x}x}}y)KuE   bot author + human reviewer → PASS. evidence에 result=PASS 기록.	task-2481WORKSPACE_ROOTTASKCTL_TEST_MODE1TASKCTL_PR_AUTHOR_OVERRIDEjeon-jonghyuk-taskctl-bot[bot]memoryspecsTr   allowed_approvers.json   )jonghyuk-jeonJonghyukJeonJeon-Jonghyukversion	approversmanual_loginsr,   r-   utils.bot_pr_authorFraisingPR_OPENr   r   Nr   
taskctl.py_taskctl_scripts	WORKSPACE	STATE_DIRr	   r
   EVIDENCE_DIRr   _rund   rS   r   prreviewer==)z%(py0)s == %(py3)sresult)py0py3zexpected 0 exit code, got z
>assert %(py5)spy5*.jsonevidence file not created
>assert %(py0)srl   ev_filesPASSzI%(py6)s
{%(py6)s = %(py2)s
{%(py2)s = %(py0)s.get
}(%(py4)s)
} == %(py9)sev_datarl   py2py4py6py9zexpected result=PASS, got: 
>assert %(py11)spy11authorzjeon-jonghyuk-taskctl-botr?   )zJ%(py8)s
{%(py8)s = %(py4)s
{%(py4)s = %(py2)s.get
}(%(py6)s)
} == %(py11)s)rx   ry   rz   py8r}   z%(py13)spy13in)z{%(py16)s in %(py29)s
{%(py29)s = %(py18)s(%(py27)s
{%(py27)s = %(py21)s
{%(py21)s = %(py19)s.get
}(%(py23)s, %(py25)s)
})
}r1   )py16py18py19py21py23py25py27py29z%(py31)spy31zbot author not in evidence: z
>assert %(py34)spy34rh   zreviewer mismatch: )'setenvr1   r2   r7   r#   r$   delitemsysmodulesr<   importlib.utilr   _WORKTREE_ROOTutilspec_from_file_locationmodule_from_specloaderexec_modulesetattrrG   argparse	Namespacecmd_request_review
@pytest_ar_call_reprcompare@py_builtinslocals_should_repr_global_name	_saferepr_format_assertmsgAssertionError_format_explanationsortedglobloads	read_textgetappend_format_boolop)'r8   monkeypatchr   allowed_dir	importlibtaskctl_pathspectcargsrk   @py_assert2@py_assert1@py_format4@py_format6evidence_dirrr   @py_format1rv   @py_assert3@py_assert5@py_assert8@py_assert7@py_format10@py_format12@py_assert10@py_assert9@py_assert0@py_assert15@py_assert20@py_assert22@py_assert24@py_assert26@py_assert28@py_assert17@py_format14@py_format30@py_format32@py_format33@py_format35s'                                          r)   )test_request_review_human_reviewer_passesr   D   s    G'X7*C035UV X%/KdT2++77

KD 9 	 8  %:EJ';')3lBL>>112Dc,FWXD		(	(	.BKKBK2KH)<w)FGNHx,?*,LM F$56 D ""4(F=6Q;===6Q======6===6===Q===4VH======= h&3g=Ll''12H0000000008000800000jj"//12G;;SxS;x SFS F*SSS FSSSSSS7SSS7SSS;SSSxSSS SSSFSSS.I',SSSSSSSS47;; 4x 4;x  4$D 4 $DD 4&4.5kk4:B4DF4.9(B.G4*-.G*H4&*HH4 4"3"34 $D 4 4-3V4 433  4 4*3)  4 4*3)  4 4*3)   4 4*3) ! 4 4*3) %E 4 4 4-3V4-34"3"34&*H4 4*3) '4 4-3V4 433 +.4 4*3) +.4 4-3V4 433 /64 4*3) /64 4*3) /:4 4*3) ;C4 4*3) EG4 4*3) /H4 4*3) +I4 4 4-3V4-34%3^4 4"3"3)'34 4 4 3 34 4 4 4 4 ;; z ;z" o "o5  "o                  "    #    '6    gkk*567     r=   c                
   d}|j                  dt        |              |j                  dd       |j                  dd       t        | |d       d	d
l}t	        t
              dz  dz  }|j                  j                  dt        |            }|j                  j                  |      }|j                  j                  |       |j                  |d|        |j                  |d| dz  dz         |j                  |d| dz  dz         |j                  |dt               t        j                  |dd      }t        j                   t"              5 }|j%                  |       d
d
d
       j&                  }	|	j(                  }
d	}|
|k7  }|st+        j,                  d|fd|
|f      dt/        j0                         v st+        j2                  |      rt+        j4                  |      ndt+        j4                  |	      t+        j4                  |
      t+        j4                  |      dz  }t+        j6                  d|j&                  j(                         dz   d|iz  }t9        t+        j:                  |            d
x}	x}
x}}| dz  dz  |z  }t=        |j?                  d            }|s{t+        j6                  d      d z   d!d"t/        j0                         v st+        j2                  |      rt+        j4                  |      nd"iz  }t9        t+        j:                  |            tA        jB                  |d#   jE                               }|jF                  }	d$}
 |	|
      }d%}||k(  }|st+        j,                  d&|fd'||f      d(t/        j0                         v st+        j2                  |      rt+        j4                  |      nd(t+        j4                  |	      t+        j4                  |
      t+        j4                  |      t+        j4                  |      d)z  }t+        j6                  d*|       d+z   d,|iz  }t9        t+        j:                  |            d
x}	x}
x}x}}|jF                  }	d-}
 |	|
      }|st+        j6                  d.|       d/z   d(t/        j0                         v st+        j2                  |      rt+        j4                  |      nd(t+        j4                  |	      t+        j4                  |
      t+        j4                  |      d0z  }t9        t+        j:                  |            d
x}	x}
}y
# 1 sw Y   xY w)1uU   human author + same reviewer (self-approval) → SystemExit, evidence에 result=FAIL.rI   rJ   rK   rL   rM   z
human-userr]   r^   r   Nr   r_   r`   ra   rb   r	   r
   rc   r   rd   re   rf   !=zG%(py4)s
{%(py4)s = %(py2)s
{%(py2)s = %(py0)s.value
}.code
} != %(py7)sexc_inforl   rx   ry   py7z=expected non-zero exit for self-approval/non-bot author, got 
>assert %(py9)sr{   ro   z)evidence file not created even on failurerq   rl   rr   rs   rk   FAILri   ru   rv   rw   'expected result=FAIL in evidence, got: r|   r}   reasonz"reason field missing in evidence: zG
>assert %(py6)s
{%(py6)s = %(py2)s
{%(py2)s = %(py0)s.get
}(%(py4)s)
})rl   rx   ry   rz   )$r   r1   r<   r   r   r   r   r   r   r   r   r   rG   r   r   pytestraises
SystemExitr   valuecoder   r   r   r   r   r   r   r   r   r   r   r#   r   r   r   )r8   r   r   r   r   r   r   r   r   r   r   @py_assert6r   @py_format8r   r   rr   r   rv   r   r   r   @py_format7s                          r)   *test_request_review_self_approval_rejectedr      s>    G'X7*C03\B';')3lBL>>112Dc,FWXD		(	(	.BKKBK2KH)<w)FGNHx,?*,LMF$56D 
z	" $h
d#$ >> > ! !#  !                      #$    HH[H[G\]     
 h&3g=Ll''12H@@@@@@@@@8@@@8@@@@@jj"//12G;; x ;x  F  F*   F                       !    %+    2';      ;;PxP;x P PP$Fwi"PPPPPPP7PPP7PPP;PPPxPPP PPPPPP!$ $s   T::Uc                L   d}|j                  dt        |              |j                  dd       |j                  dd       | dz  dz  }|j                  d	d	
       |dz  j                  t	        j
                  dg ddgd      d       t        | |d       ddl}t        t              dz  dz  }|j                  j                  dt        |            }|j                  j                  |      }|j                  j                  |       |j                  |d|        |j                  |d| dz  dz         |j                  |d| dz  dz         |j                  |dt                |j#                  t$        j&                  d d!"       t)        j*                  |d#d$%      }t-        j.                  t0              5 }	|j3                  |       ddd       	j4                  }
|
j6                  }d}||k7  }|st9        j:                  d&|fd'||f      d(t=        j>                         v st9        j@                  |	      rt9        jB                  |	      nd(t9        jB                  |
      t9        jB                  |      t9        jB                  |      d)z  }t9        jD                  d*|	j4                  j6                         d+z   d,|iz  }tG        t9        jH                  |            dx}
x}x}}| dz  dz  |z  }tK        |jM                  d-            }|s{t9        jD                  d.      d/z   d0d1t=        j>                         v st9        j@                  |      rt9        jB                  |      nd1iz  }tG        t9        jH                  |            t	        jN                  |d2   jQ                               }|jR                  }
d3} |
|      }d4}||k(  }|st9        j:                  d5|fd6||f      d7t=        j>                         v st9        j@                  |      rt9        jB                  |      nd7t9        jB                  |
      t9        jB                  |      t9        jB                  |      t9        jB                  |      d8z  }t9        jD                  d9|       d:z   d;|iz  }tG        t9        jH                  |            dx}
x}x}x}}g }
d<}|jR                  }d=}d>} |||      }t        |      }||v }|}|s,d?}|jR                  }d=} d>}! || |!      }"t        |"      }#||#v }$|$}|st9        j:                  d@|fdA||f      t9        jB                  |      dBt=        j>                         v st9        j@                  t              rt9        jB                  t              ndBd7t=        j>                         v st9        j@                  |      rt9        jB                  |      nd7t9        jB                  |      t9        jB                  |      t9        jB                  |      t9        jB                  |      t9        jB                  |      dCz  }%dDdE|%iz  }&|
jU                  |&       |s9t9        j:                  d@$fdF#f      t9        jB                  |      dBt=        j>                         v st9        j@                  t              rt9        jB                  t              ndBd7t=        j>                         v st9        j@                  |      rt9        jB                  |      nd7t9        jB                        t9        jB                         t9        jB                  !      t9        jB                  "      t9        jB                  |#      dGz  }'dHdI|'iz  }(|
jU                  |(       t9        jV                  |
d      i z  })t9        jD                  dJ|       dKz   dL|)iz  }*tG        t9        jH                  |*            dx}x}
x}x}x}x}x}x}x}x}x}$x}x} x}!x}"}#y# 1 sw Y   LxY w)MuV   allowed_approvers.json이 정의된 환경에서 비허용 사람 reviewer → reject.rI   rJ   rK   rL   rM   rN   rO   rP   Tr   rQ   rR   rT   rU   rV   r,   r-   r]   r^   r   Nr   r_   _taskctl_scripts2ra   rb   r	   r
   rc   r   rd   rZ   Fr[   re   zrandom-strangerrf   r   r   r   r   z6expected non-zero exit for unauthorized reviewer, got r   r{   ro   rp   rq   rl   rr   rs   rk   r   ri   ru   rv   rw   r   r|   r}   allowed_approversr   r?   rY   r   )zv%(py3)s in %(py16)s
{%(py16)s = %(py5)s(%(py14)s
{%(py14)s = %(py8)s
{%(py8)s = %(py6)s.get
}(%(py10)s, %(py12)s)
})
}r1   )rm   rn   rz   r   py10py12py14r   z%(py18)sr   )z{%(py21)s in %(py34)s
{%(py34)s = %(py23)s(%(py32)s
{%(py32)s = %(py26)s
{%(py26)s = %(py24)s.get
}(%(py28)s, %(py30)s)
})
})r   r   py24py26py28py30py32r   z%(py36)spy36z!reason should mention allowlist: z
>assert %(py39)spy39),r   r1   r2   r7   r#   r$   r<   r   r   r   r   r   r   r   r   r   rG   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   )+r8   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   rr   r   rv   r   r   r   r   r   @py_assert11@py_assert13r   @py_assert4r   r   @py_assert25@py_assert27@py_assert29@py_assert31@py_assert33r   @py_format17@py_format19r   @py_format37@py_format38@py_format40s+                                              r)   8test_request_review_unauthorized_human_reviewer_rejectedr      sA    G'X7*C035UV X%/KdT2++77

(/:D 9 	 8  ';')3lBL>>112Es<GXYD		(	(	.BKKBK2KH)<w)FGNHx,?*,LMF$56 %:EJ"D 
z	" $h
d#$ >> > ! !#  !                      #$    AATAT@UV      h&3g=Ll''12H0000000008000800000jj"//12G;; x ;x  F  F*   F                       !    %+    2';      gkk ( B k(B&? #&?"@ "@@ ")++.68:"-h";!";<<<  "@          #&    #&      '.    '.    '2    3;    =?    '@    #A     <        "   "     #*   #*   #.   /7   9;   #<   =       ,G95        $ $s   =``#)r]   )r8   r   r   r1   r   r1   r0   None)rE   z	list[str]rF   r   )r8   r   r   zpytest.MonkeyPatchr0   r   )__doc__
__future__r   builtinsr   _pytest.assertion.rewrite	assertionrewriter   r   r3   r#   r   pathlibr   typingr   r   r1   __file__resolver   r   pathinsert_SCRIPTS_DIRr<   rG   r   r   r    r=   r)   <module>r     s   #      
    T(^++-55a89!HHOOA~&4>))+33A6BCsxxHHOOA|$]BP99!39	9x-Q-Q!3-Q	-Q`;;!3;	;r=   