
     j/                       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m	Z	 ddl
Z
 ee      j                  j                  j                  Zedz  Z ee      ej                   vr"ej                   j#                  d ee             ddlmZmZmZ edz  d	z  d
z  dz  Zedz  dz  dz  Zd Zd Zd Zd Zd Zd Zd Zd Zg dZ ddZ!d Z"d Z#y)uf  
tests/regression/test_workflow_sha_payload.py

task-2486 회귀 테스트: CI pull_request SHA payload fallback fix
작성자: 아르고스 (dev1-team 테스터)

대상 모듈: scripts/verify_workflow_sha_payload.py
- _resolve_pr, _resolve_sha, _load_event 헬퍼 단위 테스트
- fixture 기반 dry-run 통합 테스트
- ci.yml 구조 회귀 테스트
    )annotationsN)Path)patchscripts)_load_event_resolve_pr_resolve_shatests
regressionfixturesworkflow_sha_payloadz.github	workflowszci.ymlc                    t         dz  } t         dz  }t        t        |             }t        |dd      5 }t	        j
                  |      }ddd       t        |ddd	      \  }}t        ||xs ddd
      \  }}}	t        |xr |      }
|
rdnd}|d   k(  sJ d|d    d|        ||d   k(  sJ d|d   d|       |t        |d         k(  sJ d|d   d|       |dk(  s
J d|       |dk(  s
J d|       y# 1 sw Y   xY w)uB   A-1: pr_event_normal.json — SHA + PR 정상 추출, exit_code 0.zpr_event_normal.jsonzpr_event_normal.expected.jsonrutf-8encodingN Tbranchrepodry_runr   r   r      	exit_codeexit_code mismatch: expected=, got=shazSHA mismatch: expected=przPR mismatch: expected=1z'SHA stage should be '1' (primary), got=z&PR stage should be '1' (primary), got=	FIXTURES_DIRr   stropenjsonloadr   r	   bool)
event_pathexpected_patheventfexpected	pr_numberpr_stager   	sha_stage_resolved_okgot_exits               A/home/jay/workspace/tests/regression/test_workflow_sha_payload.pytest_resolve_normal_eventr4   -   si    66J #BBMJ(E	mS7	3  q99Q<  &eBRNIx$UI,=BPTUCAs(y)KqQHx,, 
'(='>fXJO, (5/!]%<Xe_<OvVYU\#]]!HTN++ 
 $ 2&F+ TFymTTs?QDXLQQ?%   s   DD
c                 n   t         dz  } t         dz  }t        t        |             }t        |dd      5 }t	        j
                  |      }ddd       j                  di       }t        j                  t        j                  |      5  t        |ddd	
      \  }}t        ||xs ddd	      \  }}	}ddd       t        xr       }
|
rdnd}||d   k(  sJ d|d    d|        ||d   k(  sJ d|d   d|       |dk(  s
J d|       	dk(  s
J d|	       y# 1 sw Y   xY w# 1 sw Y   yxY w)z\A-2: pr_event_empty_sha.json + GITHUB_SHA env_override. fallback SHA = 'fallback_sha_value'.zpr_event_empty_sha.jsonz pr_event_empty_sha.expected.jsonr   r   r   Nenv_overridesr   Tr   r   r   r   r   r   r   r   z fallback SHA mismatch: expected=fallback_sha_valuez&SHA must be 'fallback_sha_value', got=3z)SHA fallback should reach stage '3', got=)r"   r   r#   r$   r%   r&   getr   dictosenvironr   r	   r'   )r(   r)   r*   r+   r,   r6   r-   r0   r   r/   r1   r2   s               r3   !test_resolve_empty_sha_falls_backr=   H   sw    99J #EEMJ(E	mS7	3  q99Q<  LL"5M	BJJ	. 
"5"dK	1(9$2t
Y
 s(y)KqQHx,, 
'(='>fXJO, (5/! 
*8E?*=VC7K! &&X*PQTPW(XX&VHVV-   

 
s   D	*D+D(+D4c                    t         dz  } t         dz  }t        t        |             }t        |dd      5 }t	        j
                  |      }ddd       t        |ddd	      \  }}t        ||xs ddd
      \  }}}t        |xr |      }	|	rdnd}
|
dk(  s
J d|
        |
d   k(  sJ |r
J d|       |dk(  s
J d|       y# 1 sw Y   |xY w)u>   A-3: pr_event_empty_pr.json — PR 추출 실패, exit_code 1.zpr_event_empty_pr.jsonzpr_event_empty_pr.expected.jsonr   r   r   Nr   Tr   r   r   r   z'empty PR should yield exit_code=1, got=r   PR should be empty, got=nonezPR stage should be 'none', got=r!   )r(   r)   r*   r+   r,   r-   r.   r   r0   r1   r2   s              r3   test_resolve_empty_pr_failsrA   g   s     88J #DDMJ(E	mS7	3  q99Q<  &eBRNIxUI$5BMICAs(y)KqQHq=NCH:NN=x,,,,B4YMBB=vM!@MM   s   CCc                    t         dz  } t         dz  }t        t        |             }t        |dd      5 }t	        j
                  |      }ddd       t        j                  j                         D ci c]  \  }}|dk7  s|| }}}t        j                  t        j                  |d	      5  t        |d
d
d      \  }}	t        ||xs dd
d      \  }
}	}	ddd       t        
xr       }|rdnd}|dk(  s
J d|        |d   k(  sJ |
r
J d|
       r
J d|       y# 1 sw Y   xY wc c}}w # 1 sw Y   bxY w)uM   A-4: pr_event_empty_both.json — SHA + PR 모두 추출 실패, exit_code 1.zpr_event_empty_both.jsonz!pr_event_empty_both.expected.jsonr   r   r   N
GITHUB_SHAT)clearr   r   r   r   r   z)empty both should yield exit_code=1, got=r   zSHA should be empty, got=r?   )r"   r   r#   r$   r%   r&   r;   r<   itemsr   r:   r   r	   r'   )r(   r)   r*   r+   r,   kvenv_without_shar-   r0   r   r1   r2   s                r3   test_resolve_empty_both_failsrI   |   sZ    ::J #FFMJ(E	mS7	3  q99Q<  )+

(8(8(:P1a<>Oq!tPOP	BJJt	< R"5"dK	1 	(9TDQ	QR s(y)KqQHq=PEhZPP=x,,,,7/w777B4YMBB=y    QR Rs#   D)4D5D50*D;)D2;Ec                     ddddddi} t        d      5 }t        | dd	d
      \  }}}ddd       dk(  sJ dk(  sJ d
u sJ j                          y# 1 sw Y   .xY w)uC   B-5: SHA 1단계(primary) 채택 시 gh pr view 호출 0건 확인.pull_request/   (deadbeef1234567890abcdef1234567890abcdefztask-2486-dev1r   refnumberhead+scripts.verify_workflow_sha_payload._run_gh47
owner/repoT)r-   r   r   Nr    )r   r	   assert_not_called)r*   mock_ghr   r/   sha_is_canonicals        r3   %test_canonical_skip_when_primary_usedrY      s     	A'
E 
<	= 
+7Td,
(Y(
 <<<<t###
 
s   AA c                     ddl m}  d}d}d}d}t        j                  d|i      }t	        d|	      5   | |||      \  }}d
d
d
       du sJ d       |k(  sJ d|d|       ||k7  sJ d       y
# 1 sw Y   3xY w)u]   B-6: fallback SHA(3단계) 사용 시 canonical 비교 강제. mismatch → canonical 교체.r   )_verify_canonicalr7   $canonical_sha_value_abcdef1234567890rT   rU   
headRefOidrS   return_valueNTz%canonical mismatch should be detectedzfinal SHA should be canonical=r   z3fallback SHA should have been replaced by canonical)#scripts.verify_workflow_sha_payloadr[   r%   dumpsr   )r[   fallback_shacanonical_shar-   r   mock_output	final_shawas_mismatchs           r3   !test_canonical_used_when_fallbackrg      s    E'L:MID **lM:;K	<;	W S"3L)T"R	<S 4H!HH% 
((9	}M% $[&[[$S Ss   A33A<c                    ddddddd} t        j                  dddd	id
dddd	id
g      }t        d|      5  t        | ddd      \  }}ddd       dk(  s
J d|       dk(  s
J d|       y# 1 sw Y   (xY w)uO   C-7: gh pr list 결과 2건 이상이면 PR fallback 실패 (모호함 방지).Nsome_shafeature-branchrN   rP   )rK   rQ   
   loginowner)rQ   headRefNameheadRepositoryOwner   rS   r^   rU   Fr   r   zAPR should be empty when gh pr list returns multiple results, got=r@   z3PR stage should be 'none' on ambiguous result, got=)r%   ra   r   r   )r*   multi_resultr-   r.   s       r3   test_pr_list_multiple_abortsrr      s    
 &/?@
 E ::&6PWY`Oab&6PWY`Oab L
 
<<	X 
)*u
	8
 ? 
KI=Y? v 
=h\J
 
s   A66A?c                 z    ddddddd} t        | ddd	
      \  }}|dk(  s
J d|       |dk(  s
J d|       y)uY   C-8: event.pull_request.number 없고 event.number 만 있는 경우 event.number 사용.c   Nsome_sha_value_hererj   rN   rP   )rQ   rK   r   Tr   99z)should fall back to event.number=99, got=2z2should use stage '2' (event.number fallback), got=)r   )r*   r-   r.   s      r3   test_pr_event_number_fallbackrx      sv     ,'
	E &eBRNIx 
3I=A s? 
<XLI?    )	zcancel-kill-switchzqc-checkzhidden-path-auditzlock-in-checkzmerge-safety-checkgemini-review-gatephase3-merge-gatezci-guardguardc                 |    t        t        dd      5 } t        j                  |       cd d d        S # 1 sw Y   y xY w)Nr   r   r   )r$   CI_YMLyaml	safe_load)r+   s    r3   _load_ci_ymlr     s1    	fcG	, !~~a ! ! !s   2;c                     t               } | j                  di       }t        D cg c]	  }||vs| }}|r$J d| dt        |j	                                       yc c}w )u>   D-9: ci.yml 에 필수 job 9개 모두 존재하는지 확인.jobsu(   ci.yml 에서 다음 job 이 누락됨: u   
존재하는 job: N)r   r9   REQUIRED_JOBSlistkeys)cir   jobmissings       r3    test_ci_yml_required_jobs_intactr     sk    	B#D+?ss$s?G? 
27) <!$))+./	1;w @s
   	AAc                    t               } | j                  di       }ddg}d}|D ]  }||v sJ d| d       ||   j                  dg       }d}|D ]d  }|j                  d	d
      xs d
}||v rd} nF|j                  di       xs i }	|	j                         D ]  }
t        |
t              s||
v sd} d f |rJ d| d| d|D cg c]  }|j                  dd       c}         yc c}w )uy   D-10: gemini-review-gate 와 phase3-merge-gate 의 steps 에 verify_workflow_sha_payload.py --mode resolve 포함 확인.r   rz   r{   z-verify_workflow_sha_payload.py --mode resolvezjob 'z' not found in ci.ymlstepsFrunr   Twithu   ' steps 에서 'u   ' 를 찾지 못함.
steps: namez	(no name)N)r   r9   values
isinstancer#   )r   r   target_jobsEXPECTED_FRAGMENTjob_namer   foundsteprun_cmdwith_valrG   ss               r3   test_ci_yml_uses_resolve_stepr   &  s9   	B#D')<=KG 
4H5
2G!HHX""7B/ 	Dhhub)/RG G+xx+1rH__& a%*;q*@ E	  	
H:-.?-@ A;@AaquuV[1ABD	
u%
( Bs   C*)returnr:   )$__doc__
__future__r   r%   r;   syspathlibr   unittest.mockr   r   __file__parentWORKTREE_ROOTSCRIPTS_DIRr#   pathinsertr`   r   r   r	   r"   r~   r4   r=   rA   rI   rY   rg   rr   rx   r   r   r   r    ry   r3   <module>r      s   
 #  	 
   
 X%%,,33i'{388#HHOOAs=)*  w&5
BE[[		"[	08	;R6W>N*C: 2\6>8
!
	
ry   