
    iL+                        d Z ddlmZ ddlZddlZddlZddlmZ ddl	Z	 ee
      j                         j                  d   ZddZ edd      Zdd	Zd
 Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zy)u  tests/regression/test_silent_corruption.py — task-2471 회귀 테스트.

토르가 commit ea702b51 에서 추가한 ``utils.silent_corruption_guard`` 의
3 fail-closed check (mergedAt / mergeCommit.oid / origin/main ancestry) 와
``verify_done_preconditions`` 를 영구 차단한다.

외부 호출 (subprocess, gh, git) 은 monkeypatch 로 fake 처리.
실제 ``gh`` / ``git`` 호출 절대 금지 — 격리된 단위 테스트.

헤임달(개발2팀 테스터) 작성.
    )annotationsN)Path   c                <   t         |z  }t        j                  j                  | t	        |            }||j
                  t        d|       t        j                  j                  |      }|t        j                  | <   |j
                  j                  |       |S )uO   Worktree 의 절대 경로로 모듈을 직접 로드 (sys.path 충돌 회피).zcannot load spec for )	WORKSPACE	importlibutilspec_from_file_locationstrloaderImportErrormodule_from_specsysmodulesexec_module)mod_namefile_rel	file_pathspecmodules        >/home/jay/workspace/tests/regression/test_silent_corruption.py_load_moduler      s    H$I>>11(C	NKD|t{{*1)=>>^^,,T2F"CKKKKF#M    "silent_corruption_guard_test_aliasz utils/silent_corruption_guard.pyc                    g dddfd
}| j                  t        d|       | j                  t        j                  dd        S )u/  ``silent_corruption_guard._run`` 을 사전 정의된 응답 맵으로 fake.

    ``response_map`` 은 ``cmd[0:N]`` 의 prefix tuple 또는 임의 매칭 함수를
    키로 받아 ``(rc, stdout, stderr)`` 를 반환.

    실제 호출 사실을 추적하기 위해 호출 로그 list 를 반환.
    N)cwdtimeoutc               B   j                  t        |       ||d       | r| d   dk(  rj                  dd      S | rb| d   dk(  rZt        |       dkD  r| d   nd}|dk(  rj                  d	d
      S |dk(  rj                  dd      S |dk(  rj                  dd
      S y
)N)cmdr   r   r   gh)r   z{} git   r!   fetch	git_fetchr   r!   r!   	rev-parsegit_rev_parse)r   zabc123
r!   z
merge-basegit_merge_base)appendlistgetlen)r   r   r   subcallsresponse_maps       r   	_fake_runz_patch_run.<locals>._fake_run:   s    T#YswGH3q6T>##D-883q6U?HqL#a&bCg~#''[AAk!#''9LMMl"#''(8+FFr   _runsleepc                     y N _s    r   <lambda>z_patch_run.<locals>.<lambda>K       r   )setattrscgtime)monkeypatchr0   r1   r/   s    ` @r   
_patch_runr?   0   sC     E"D  VY/'>:Lr   c                    t        j                  d ddid      }t        | dd|dfi       t        j	                  ddd	
      }|d   du sJ |d   d   dk(  sJ d|d   v sd|d   d   d   d   v sJ y y )NoiddeadbeefmergedAtmergeCommitr    r   r!   *   
owner/repomain	pr_numberrepobase_branchokFdetailfailed_check	merged_atrD   reasonchecksjsondumpsr?   r<   verify_done_preconditionsr>   payloadresults      r   $test_mergedAt_null_fails_verify_donerZ   T   s    jjdE:;NOPG{TAw#345**<V + F $<5   (N+{:::))Z6(;KH;U<< .   .)r   c                    t        j                  dddid      }t        | dd|dfi       t        j	                  dd	      }|d
   du sJ d|d   j                         v sd|d   j                         v sJ yy)u@   check_pr_merged_at 단독 호출 시 mergedAt=null → ok=False.NrA   xrC   r    r   r!      rG   rM   FnullrQ   z
not merged)rT   rU   r?   r<   check_pr_merged_atlowerrW   s      r   -test_check_pr_merged_at_null_returns_ok_falsera   c   s    jjdE3<HIG{TAw#345##A|4F$<5   VH%++--AQAWAWAY1YYY1Y-r   c                    t        j                  dd d      }t        | dd|dfi       t        j	                  ddd	      }|d
   du sJ |d   d   dk(  sJ y )N2026-05-07T00:00:00ZrC   r    r   r!   c   rG   rH   rI   rM   FrN   rO   merge_commit_oidrS   rW   s      r   ,test_merge_commit_oid_null_fails_verify_donerf   r   su    jj&<TRSG{TAw#345**<V + F $<5   (N+/AAAAr   c                    t        j                  di d      }t        | dd|dfi       t        j	                  dd      }|d   d	u sJ d
|d   j                         v sJ y)u9   mergeCommit 객체는 있지만 oid 키가 없는 경우.rc   rC   r    r   r!      rG   rM   FrA   rQ   N)rT   rU   r?   r<   check_pr_merge_commit_oidr`   rW   s      r   #test_merge_commit_missing_oid_fieldrj   ~   sl    jj&<RPQG{TAw#345**2|<F$<5   F8$**,,,,r   c                    t        j                  dddid      }t        | d|dfddd	d
       t        j	                  ddd      }|d   du sJ |d   d   dk(  sJ y)u:   merge-base --is-ancestor 가 rc!=0 인 경우 fail-closed.rc   rA   merge_sha_xyzrC   r   r!   r&   )r   zorigin_sha_123
r!   )r#   r!   znot ancestorr    r%   r(   r)   7   rG   rH   rI   rM   FrN   rO   ancestryNrS   rW   s      r   +test_ancestry_check_fails_when_not_ancestorrp      s    jj*/ G gr"$85		
 **<V + F $<5   (N+z999r   c                6   t        g d      fd}| j                  t        d|       | j                  t        j                  dd        t        j	                  dd      }|d	   d
u sJ d|d   j                         v sd|d   j                         v sJ yy)uL   origin/<base> SHA 가 2회 fetch 사이 흔들리면 race detected → fail.)zsha_a
zsha_b
zsha_c
zsha_d
c                h    ~| d   dk(  r| d   dk(  rdt        d      dfS | d   dk(  r	| d   dk(  ryy)	Nr   r"   r#   r'   zsha_x
r!   r$   r&   )next)r   _kwargssha_iters     r   r1   z:test_ancestry_unstable_origin_sha_fails.<locals>._fake_run   sL    q6U?s1v4tHi0"55q6U?s1v0r   r2   r3   c                     y r5   r6   r7   s    r   r9   z9test_ancestry_unstable_origin_sha_fails.<locals>.<lambda>   r:   r   	merge_sharH   rL   rM   FracerQ   unstableN)iterr;   r<   r=   check_origin_main_ancestryr`   )r>   r1   rY   ru   s      @r   'test_ancestry_unstable_origin_sha_failsr}      s       H
 VY/'>:++KV+LF$<5   VH%++--vh?O?U?U?W1WWW1W-r   c                P   d}t        j                  dd|id      }t        | d|dfdd| ddfdd	       t        j	                  d
dd      }|d   du sJ |d   d   |k(  sJ |d   d   dk(  sJ d|d   v sJ |d   d   }|d   d   du sJ |d   d   du sJ |d   d   du sJ y )N(1234567890abcdef1234567890abcdef12345678rc   rA   rC   r   r!   r&   
rm      rG   rH   rI   rM   TrN   merge_commit_sharP   rR   re   ro   rS   )r>   rw   rX   rY   rR   s        r   #test_all_checks_pass_yields_ok_truer      s'   :Ijj*y) G gr"$I;b!126)		
 **Lf + F $<4(./9<<<(K(,BBBBvh''''Hh'F+t$,,,$%d+t333*d#t+++r   c                    t        | ddi       t        j                  ddd      }|d   du sJ d|d	   v s
d
|d	   v sJ yy)uL   gh rc != 0 → mergedAt check 실패 → verify_done_preconditions ok=False.r    )r#   r!   zgh: not authenticatedr#   rG   rH   rI   rM   FrQ   rP   N)r?   r<   rV   r>   rY   s     r   $test_gh_command_failure_fails_closedr      sg    {T#CDE**,F + F $<5   6(##{fX6F'FFF'F#r   c                    d }| j                  t        d|       | j                  t        j                  dd        t        j                  dd      }|d   du sJ y	)
uE   subprocess 예외 (FileNotFoundError 등) 시 fail-closed (ok=False).c                     ~ ~y)N)r!   zFileNotFoundError: gh not foundr6   )_cmdrt   s     r   
_raise_runz=test_gh_subprocess_exception_fails_closed.<locals>._raise_run   s
    ':r   r2   r3   c                     y r5   r6   r7   s    r   r9   z;test_gh_subprocess_exception_fails_closed.<locals>.<lambda>   r:   r   r#   rG   rM   FN)r;   r<   r=   r_   )r>   r   rY   s      r   )test_gh_subprocess_exception_fails_closedr      sU    ; VZ0'>:##A|4F$<5   r   c                    t        | ddi       t        j                  dd      }|d   du sJ d|d   v sd	|d   j                         v sJ y
y
)u-   gh stdout 가 JSON 이 아니면 fail-closed.r    )r   znot-json garbager!   r   rG   rM   FJSONrQ   decodeN)r?   r<   r_   r`   r   s     r   )test_gh_returns_invalid_json_fails_closedr      sd    {T#>?@##A|4F$<5   VH%%VH5E5K5K5M)MMM)M%r   c                    g fd}| j                  t        d|       t        j                  ddg d       sJ d       d   }|d	d
 g dk(  sJ d|d	d         d|v rd|v sJ y	)uW   gh_cmd=["custom-gh"] 전달 시 실제 명령 prefix 가 그것으로 시작해야 함.c                t    ~j                  t        |              dt        j                  dddid      dfS )Nr   r\   rA   yrC   r!   )r*   r+   rT   rU   )r   rt   captureds     r   r1   z0test_gh_cmd_parameter_is_used.<locals>._fake_run  s5    S	"4::3s|LMrRRr   r2      rG   )z	custom-ghz--tokenT)gh_cmdu$   fake _run 이 호출되지 않았음r   N   u   cmd prefix 미일치: prview)r;   r<   r_   )r>   r1   cmd0r   s      @r   test_gh_cmd_parameter_is_usedr     s    HS
 VY/1l3PQ;;;8A;D844Y8NtTVUVxj6YY44<FdN**Nr   c                     t         j                  dd      } | d   du sJ d| d   j                         v s
d| d   v sJ y	y	)
uS   check_origin_main_ancestry 가 빈 SHA 받으면 즉시 fail (subprocess 호출 X).r!   rH   rx   rM   FemptyrQ   r   N)r<   r|   r`   )rY   s    r   *test_empty_merge_commit_sha_short_circuitsr   %  sX    ++BF+CF$<5   fX&,,..2DxHX2XXX2X.r   )r   r   r   r   )r>   zpytest.MonkeyPatchr0   dictreturnr+   )__doc__
__future__r   importlib.utilr   rT   r   pathlibr   pytest__file__resolveparentsr   r   r<   r?   rZ   ra   rf   rj   rp   r}   r   r   r   r   r   r   r6   r   r   <module>r      s   
 #   
   N""$,,Q/		 (&HZ	B-:0X:,HG!N+0Yr   