
    j;                        d 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ZddlmZ ddlZ ee      j!                         j"                  d   Zedz  dz  ZdZdefd	Zdefd
ZdedefdZdedefdZ G d d      Zdedeeef   fdZ ej<                         d        Z ej<                         d        Z  ej<                         d        Z! ej<                         d        Z"d Z#d Z$d Z%d Z&d Z'ejP                  jS                  e d      d        Z*ejP                  jS                  e d      d        Z+y)uQ  
test_guard7_local_operational_patch.py
task: task-2571 TODO-7 T-5

검증 목표:
- spec §7 guard #7 3-state 정합화 검증
- LOCAL_OPERATIONAL_PATCH doctrine 기반 3-state 분기:
    A. HEAD == origin/main          → PASS
    B. ahead-only (local ahead)     → PASS + WARN
    C. behind (local behind)        → FAIL
    D. diverged (양쪽 다 ahead)     → FAIL

- start_task_guard.py 수정 완료 전에는 spec 기반 reference implementation 으로 검증
- 백엔드 수정 완료 후 실제 호출 검증은 통합 단계에서 수행

작성자: 하누만 (개발4팀 QA)
    N)Path   scriptszstart_task_guard.pyFreturnc                  j    t         j                  j                         } d| d<   d| d<   d| d<   d| d<   | S )u"   git 명령 실행용 환경변수.testGIT_AUTHOR_NAMEtest@example.comGIT_AUTHOR_EMAILGIT_COMMITTER_NAMEGIT_COMMITTER_EMAIL)osenvironcopy)envs    K/home/jay/workspace/tests/regression/test_guard7_local_operational_patch.py_git_envr   .   sC    
**//
C#C0C &C!3CJ    c                  |    t        j                  d      } t               }t        j                  g d| d|       | S )u%   origin 역할의 bare repo 초기화.zguard7-origin-prefix)gitinitz--bare-bmain-qTcwdcheckr   tempfilemkdtempr   
subprocessrun)dr   s     r   _init_bare_originr&   8   s3     01A
*CNN@atY\]Hr   origin_pathc                     t        j                  d      }t               }t        j                  dd| |dgd|       t        j                  g d|d|	       t        j                  g d
|d|	       |S )u5   origin 을 remote 로 clone 한 local repo 초기화.zguard7-local-r   r   cloner   Tr   r   r   configz
user.emailr
   r   r   r,   z	user.namer   r    )r'   r%   r   s      r   _init_local_repor.   @   sb    0A
*CNNE7KD93ONNFAUY_bcNN9qRUVHr   c                    t        j                  d      }t               }	 t        j                  g d|d|       t        j                  g d|d|       t        j                  g d|d|       t        |      dz  j                  d	       t        j                  g d
|d|       t        j                  g d|d|       t        j                  dddd| g|d|       t        j                  g d|d|       t        j                  g d|ddd|      }|j                  j                         t        j                  |d       S # t        j                  |d       w xY w)u   
    origin bare repo 에 초기 커밋 push.
    임시 work repo 를 만들어 커밋 후 origin 으로 push.
    반환값: 초기 커밋 SHA.
    zguard7-work-r   )r   r   r   r   r   Tr   r+   r-   a.txtinitial)r   addr0   )r   commitr   -mr   r   remoter2   origin)r   pushz-ur6   r   r   r   	rev-parseHEAD)r   capture_outputtextr   r   ignore_errors)r!   r"   r   r#   r$   r   
write_textstdoutstripshutilrmtree)r'   work_dirr   rs       r   !_setup_origin_with_initial_commitrF   J   s    ~6H
*C4:PTZ]^JPX`djmn=8SW]`a	h'	!--i8.HDcR<(RV\_`x+FH\`fijD(Z^dghNN7XVZaemqwz{xx~~hd3hd3s   DE E&c                       e Zd ZdZdZdZy)Guard7ResultPASSz	PASS+WARNFAILN)__name__
__module____qualname__rI   	PASS_WARNrJ    r   r   rH   rH   e   s    DIDr   rH   
local_repoc                    t               }t        j                  g d| |d       t        j                  g d| dd|      }t        j                  g d| dd|      }|j                  dk7  s|j                  dk7  rt        j
                  dfS |j                  j                         }|j                  j                         }||k(  rt        j                  d	|d
d  dfS t        j                  g d| |d      }|j                  dk(  rt        j
                  dfS t        j                  g d| |d      }|j                  dk(  rt        j                  d|d
d  d|d
d  dfS t        j
                  d|d
d  d|d
d  fS )u   
    spec §7.3 3-state 기반 guard #7 reference implementation.

    Returns:
        (result, detail_msg)
        result: Guard7Result.PASS / PASS_WARN / FAIL
    )r   fetchr6   r   T)r   r   r;   r8   )r   r;   r<   r   )r   r9   origin/mainr   u)   HEAD 또는 origin/main SHA 조회 실패zHEAD == origin/main (N   ))r   
merge-base--is-ancestorr:   rS   u9   local main 이 origin/main 보다 behind — fetch 권장)r   rV   rW   rS   r:   uG   LOCAL_OPERATIONAL_PATCH: local main 이 origin/main 보다 ahead-only (z > zdiverged: HEAD=z, origin/main=)
r   r#   r$   
returncoderH   rJ   r@   rA   rI   rN   )rP   r   head_rorigin_rhead_sha
origin_shabehind_rahead_rs           r   guard7_checkr_   k   s    *C NN3]ab^^8jY]dhnqrF~~Azbfmqwz{HA!4!4!9  "MMM}}""$H&&(J :  $9(2A,q"III ~~ECH a  $]^^ nnECG Q%%!~SBQ 03
 	
 !~^JWYXYNK[\\\r   c               #      K   t               } t        |        t        |       }| |f t        j                  | d       t        j                  |d       yw)u$   시나리오 A: HEAD == origin/main.Tr=   N)r&   rF   r.   rB   rC   )r6   locals     r   scenario_a_reposrb      sH       F%f-V$E
%-
MM&-
MM%t,s   AAc               #   n  K   t               } t        |        t        |       }t               }t	        |      dz  j                  d       t        j                  g d|d|       t        j                  g d|d|       | |f t        j                  | d       t        j                  |d       yw)	u<   시나리오 B: local main 에 1 커밋 추가 (ahead-only).local_only.txtzlocal operational patch)r   r2   rd   Tr   )r   r3   r   r4   zlocal operational patch commitr=   N)
r&   rF   r.   r   r   r?   r#   r$   rB   rC   )r6   ra   r   s      r   scenario_b_reposre      s       F%f-V$E *C	%[##//0IJNN3dPSTNNRX]eiors
%-
MM&-
MM%t,s   B3B5c               #     K   t               } t        |        t        |       }t        j                  d      }t               }	 t        j                  dd| |dgd|       t        j                  g d|d|	       t        j                  g d
|d|	       t        |      dz  j                  d       t        j                  g d|d|	       t        j                  g d|d|	       t        j                  g d|d|	       t        j                  |d       | |f t        j                  | d       t        j                  |d       y# t        j                  |d       w xY ww)u?   시나리오 C: origin main 에 1 커밋 추가 (local behind).zguard7-scenarioc-work-r   r   r)   r   Tr*   r+   r   r-   origin_new.txtzorigin new commit)r   r2   rg   )r   r3   r   r4   zorigin ahead commitr   r7   r6   r   r   r=   N)r&   rF   r.   r!   r"   r   r#   r$   r   r?   rB   rC   )r6   ra   rD   r   s       r   scenario_c_reposri      s%      F%f-V$E '?@H
*C	4w$?tQTUJPX`djmn=8SW]`a	h*	*667JK7XTWZ[KQYaekno>HTX^abhd3
%-
MM&-
MM%t,	 	hd3s    AE-CE AE-E**E-c               #     K   t               } t        |        t        |       }t               }t	        |      dz  j                  d       t        j                  g d|d|       t        j                  g d|d|       t        j                  d      }	 t        j                  d	d
| |dgd|       t        j                  g d|d|       t        j                  g d|d|       t	        |      dz  j                  d       t        j                  g d|d|       t        j                  g d|d|       t        j                  g d|d|       t        j                  |d       | |f t        j                  | d       t        j                  |d       y# t        j                  |d       w xY ww)u;   시나리오 D: 양쪽 다 다른 커밋 추가 (diverged).local_diverge.txtzlocal diverge)r   r2   rk   Tr   )r   r3   r   r4   zlocal diverge commitzguard7-scenariod-work-r   r   r)   r   r*   r+   r-   origin_diverge.txtzorigin diverge)r   r2   rl   )r   r3   r   r4   zorigin diverge commitrh   r=   N)r&   rF   r.   r   r   r?   r#   r$   r!   r"   rB   rC   )r6   ra   r   rD   s       r   scenario_d_reposrm      si      F%f-V$E
*C 
%[&&22?CNN6ESVWNNHe[_ehi '?@H	4w$?tQTUJPX`djmn=8SW]`a	h.	.::;KL;QU[^_MS[cgmpq>HTX^abhd3
%-
MM&-
MM%t,	 	hd3s    BG CF$ AG $F==G c                 \   | \  }}t        |      \  }}t        j                  }||k(  }|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                  t              rt        j                  t              ndt        j                  |      dz  }t        j                  d| d|       dz   d	|iz  }t        t        j                  |            d
x}}y
)u]   
    시나리오 A: HEAD == origin/main → PASS 기대.
    spec §7.3 첫 번째 행.
    ==)z,%(py0)s == %(py4)s
{%(py4)s = %(py2)s.PASS
}resultrH   py0py2py4u%   시나리오 A: PASS 기대, 실제: 	   
상세: 
>assert %(py6)spy6N)r_   rH   rI   
@pytest_ar_call_reprcompare@py_builtinslocals_should_repr_global_name	_saferepr_format_assertmsgAssertionError_format_explanation)	rb   _ra   rq   detail@py_assert3@py_assert1@py_format5@py_format7s	            r   test_guard7_scenario_a_passr          
 HAu!%(NFF!&& 6&&  6&                "    "    '    0xz&J    r   c                 \   | \  }}t        |      \  }}t        j                  }||k(  }|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                  t              rt        j                  t              ndt        j                  |      dz  }t        j                  d| d|       dz   d	|iz  }t        t        j                  |            d
x}}y
)u   
    시나리오 B: local 이 origin/main 보다 ahead-only → PASS+WARN 기대.
    spec §7.3 세 번째 행 (LOCAL_OPERATIONAL_PATCH 허용).
    ro   z1%(py0)s == %(py4)s
{%(py4)s = %(py2)s.PASS_WARN
}rq   rH   rr   u*   시나리오 B: PASS+WARN 기대, 실제: rv   rw   rx   N)r_   rH   rN   ry   rz   r{   r|   r}   r~   r   r   r   )	re   r   ra   rq   r   r   r   r   r   s	            r    test_guard7_scenario_b_pass_warnr     s    
 HAu!%(NFF!++ 6++  6+                "    "    ,    5VHJvhO    r   c                    | \  }}t        |      \  }}t        j                  }||k(  }|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                  t              rt        j                  t              ndt        j                  |      dz  }dd|iz  }t        t        j                  |            dx}}g }d	}	|j                  }
 |
       }|	|v }|}|sd
}||v }|}|st        j                  d|fd|	|f      t        j                  |	      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |
      t        j                  |      dz  }dd|iz  }|j                  |       |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  }|j                  |       t        j                  |d      i z  }t        j                  d|       dz   d|iz  }t        t        j                  |            dx}x}x}	x}x}
x}x}}y)up   
    시나리오 B: WARN 메시지에 'ahead' 또는 'LOCAL_OPERATIONAL_PATCH' 가 포함되어야 한다.
    ro   r   rq   rH   rr   zassert %(py6)srx   NaheadLOCAL_OPERATIONAL_PATCHin)zD%(py3)s in %(py9)s
{%(py9)s = %(py7)s
{%(py7)s = %(py5)s.lower
}()
}r   )py3py5py7py9z%(py11)spy11)z%(py14)s in %(py16)s)py14py16z%(py18)spy18   uC   WARN 메시지에 'ahead' 또는 'LOCAL_OPERATIONAL_PATCH' 없음: z
>assert %(py21)spy21)r_   rH   rN   ry   rz   r{   r|   r}   r~   r   r   lowerappend_format_boolopr   )re   r   ra   rq   r   r   r   r   r   @py_assert2@py_assert6@py_assert8@py_assert4@py_assert0@py_assert13@py_assert15@py_format10@py_format12@py_format17@py_format19@py_format20@py_format22s                         r   2test_guard7_scenario_b_warn_message_mentions_aheadr     s:    HAu!%(NFF!+++6+++++6+++++++6+++6++++++\+++\+++++++++++7 fll ln 7n$ (A (AV(K   7n                  #    %     (AV    )B      FL    FL        NfXV      r   c                 \   | \  }}t        |      \  }}t        j                  }||k(  }|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                  t              rt        j                  t              ndt        j                  |      dz  }t        j                  d| d|       dz   d	|iz  }t        t        j                  |            d
x}}y
)um   
    시나리오 C: local 이 origin/main 보다 behind → FAIL 기대.
    spec §7.3 두 번째 행.
    ro   z,%(py0)s == %(py4)s
{%(py4)s = %(py2)s.FAIL
}rq   rH   rr   u%   시나리오 C: FAIL 기대, 실제: rv   rw   rx   Nr_   rH   rJ   ry   rz   r{   r|   r}   r~   r   r   r   )	ri   r   ra   rq   r   r   r   r   r   s	            r   test_guard7_scenario_c_failr   '  r   r   c                 \   | \  }}t        |      \  }}t        j                  }||k(  }|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                  t              rt        j                  t              ndt        j                  |      dz  }t        j                  d| d|       dz   d	|iz  }t        t        j                  |            d
x}}y
)ur   
    시나리오 D: diverged → FAIL 기대.
    spec §7.3 네 번째 행 (BYPASS 금지 doctrine 유지).
    ro   r   rq   rH   rr   u%   시나리오 D: FAIL 기대, 실제: rv   rw   rx   Nr   )	rm   r   ra   rq   r   r   r   r   r   s	            r   test_guard7_scenario_d_failr   7  r   r   uV   start_task_guard.py guard #7 3-state 정합화 미완료 (백엔드 수정 대기 중))reasonc                    | \  }}t         j                  j                         }||d<   t        j                  t
        j                  t        t              ddgdd|      }|j                  }d}||k(  }|st        j                  d|fd||f      d	t        j                         v st        j                  |      rt        j                  |      nd	t        j                  |      t        j                  |      d
z  }t        j                   d|j                   d|j"                   d|j$                         dz   d|iz  }	t'        t        j(                  |	            dx}x}}g }d}
|j$                  }|
|v }|}|s'd}|j$                  }|j*                  } |       }||v }|}|st        j                  d|fd|
|f      t        j                  |
      d	t        j                         v st        j                  |      rt        j                  |      nd	t        j                  |      dz  }	dd|	iz  }|j-                  |       |st        j                  dfdf      t        j                  |      d	t        j                         v st        j                  |      rt        j                  |      nd	t        j                        t        j                        t        j                  |      dz  }dd|iz  }|j-                  |       t        j.                  |d      i z  }t        j                   d|j$                         dz   d|iz  }t'        t        j(                  |            dx}x}x}
x}x}x}x}x}x}}y) u   
    [통합 테스트] 실제 start_task_guard.py 를 호출하여 시나리오 B 에서
    exit code 0 (PASS+WARN) 검증.
    백엔드 정합화 완료 후 GUARD7_REFINED_IMPL_AVAILABLE = True 로 변경.
    WORKSPACE_ROOT--task	task-testTr;   r<   r   r   ro   )z2%(py2)s
{%(py2)s = %(py0)s.returncode
} == %(py5)srq   rs   rt   r   u7   실제 guard #7 시나리오 B: exit 0 기대, 실제: z	
stdout: z	
stderr: 
>assert %(py7)sr   NWARNr   r   )z.%(py3)s in %(py7)s
{%(py7)s = %(py5)s.stderr
})r   r   r   z%(py9)sr   )zh%(py12)s in %(py20)s
{%(py20)s = %(py18)s
{%(py18)s = %(py16)s
{%(py16)s = %(py14)s.stderr
}.lower
}()
})py12r   r   r   py20z%(py22)spy22r   u   WARN 메시지 없음
stderr: z
>assert %(py25)spy25)r   r   r   r#   r$   sys
executablestrSTART_TASK_GUARD_PYrX   ry   rz   r{   r|   r}   r~   r   r@   stderrr   r   r   r   r   )re   r   ra   r   rq   r   r   r   @py_format6@py_format8r   r   r   @py_assert11r   @py_assert17@py_assert19r   r   @py_format21@py_format23@py_format24@py_format26s                          r   *test_guard7_real_impl_scenario_b_pass_warnr   G  s    HAu
**//
C!C^^	018[I	F   !                    !"    B&BSBSAT U==/FMM?	<    
6 V]] 6]" g  1D1D 1D1F g1F&F   6]                  #     g1F    '.      28    28    2?    2E    2G        *&--9      r   c                    | \  }}t         j                  j                         }||d<   t        j                  t
        j                  t        t              ddgdd|      }|j                  }d}||k7  }|st        j                  d|fd||f      d	t        j                         v st        j                  |      rt        j                  |      nd	t        j                  |      t        j                  |      d
z  }t        j                   d|j                         dz   d|iz  }	t#        t        j$                  |	            dx}x}}y)u   
    [통합 테스트] 실제 start_task_guard.py 를 호출하여 시나리오 C 에서
    exit code != 0 (FAIL) 검증.
    r   r   r   Tr   r   )!=)z2%(py2)s
{%(py2)s = %(py0)s.returncode
} != %(py5)srq   r   u>   실제 guard #7 시나리오 C: FAIL(exit!=0) 기대, 실제: r   r   N)r   r   r   r#   r$   r   r   r   r   rX   ry   rz   r{   r|   r}   r~   r   r   r   )
ri   r   ra   r   rq   r   r   r   r   r   s
             r   %test_guard7_real_impl_scenario_c_failr   f  s%    HAu
**//
C!C^^	018[I	F   !                    !"    IIZIZH[\     r   ),__doc__builtinsr{   _pytest.assertion.rewrite	assertionrewritery   r   rB   r#   r   r!   pathlibr   pytest__file__resolveparentsWORKTREE_ROOTr   GUARD7_REFINED_IMPL_AVAILABLEdictr   r   r&   r.   rF   rH   tupler_   fixturerb   re   ri   rm   r   r   r   r   r   markskipifr   r   rO   r   r   <module>r      s  $  	   
   X&&(003#i/2GG  !& $ 3 # # 43 43 46 .]S .]U38_ .]j - - - -" - -2 - -F	 		 	 	  %%c  	6 %%c  	r   