
    ;j)                        d Z ddl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mZ ddl	m
Z
 ddlZ e
e      j                         j                  d   Zedz  dz  Zdefd	Zdefd
ZdedededdfdZdedefdZdedededededz  dedz  defdZdee   dededefdZ ej6                         d        Zd Zd Zd Zd Z d Z!d Z"d  Z#d! Z$d" Z%y)#u/  
test_stash_lifecycle_quarantine.py
task: task-2571 TODO-7 T-3

검증 목표:
- spec §2 unknown 분기 정책 검증
- unknown stash 는 항상 preserved
- wip stash 는 항상 preserved
- pre-task stash 는 dry-run 시 dry-run-pop
- skipped_unknown_count 검증

작성자: 하누만 (개발4팀 QA)
    N)datetimetimezone)Path   scriptszstash_audit.pyreturnc                     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|       | S )u$   격리된 임시 git repo 초기화.zstash-lifecycle-test-)prefix)gitinit-qz-bmainTcwdcheckenv)r   configz
user.emailtest@example.com)r   r   z	user.nametesta.txthello)r   addr   )r   commitr   -mr   )tempfilemkdtemp_git_env
subprocessrunr   
write_text)dr   s     3tests/regression/test_stash_lifecycle_quarantine.py_init_temp_repor#   #   s     78A
*CNN6ATsSNNFAUY_bcNN9qRUV	!Ww""7+NN*3GNN8atQTUH    c                  j    t         j                  j                         } d| d<   d| d<   d| d<   d| d<   | S )u"   git 명령 실행용 환경변수.r   GIT_AUTHOR_NAMEr   GIT_AUTHOR_EMAILGIT_COMMITTER_NAMEGIT_COMMITTER_EMAIL)osenvironcopy)r   s    r"   r   r   0   sC    
**//
C#C0C &C!3CJr$   repo_dirmessagefilenamec                     t               }t        |       |z  }|j                  d| d       t        j                  dd|g| d|       t        j                  dddd	|g| d|       y
)u3   파일 하나 dirty 상태로 만들고 stash push.zdirty: 
r   r   Tr   stashpushr   N)r   r   r    r   r   )r-   r.   r/   r   fpaths        r"   _stash_pushr5   :   sf    
*CNX%E	wwir*+NNE5(+3ONNE7FD':PTZ]^r$   c                    t        j                  t        j                  t	        t
              dd| gdd      }|j                  dk(  s!J d|j                   d|j                          t        j                  |j                        S )u7   stash_audit.py --json 실행 후 파싱된 dict 반환.z--jsonz--workspaceT)capture_outputtextr   u#   stash_audit.py 실행 실패 (exit=z
)
stderr: )r   r   sys
executablestrSTASH_AUDIT_PY
returncodestderrjsonloadsstdout)r-   results     r"   _run_audit_jsonrC   C   s    ^^	^,hxPF
 ! 
-f.?.?-@ A==/	#! ::fmm$$r$   sourceapprovepr_verifiedidx_in_drop_listetidtask_idc                 b    | dk(  r|ryy| dk(  r|r|r||k(  ry|syy| dk(  r	|r|ry|syy| d	v ryy
)u:   
    spec §2 결정 흐름 reference implementation.
    pre-taskpoppeddry-run-popzfinish-task	preservedzother-filesdroppedzdry-run-drop)wip
quarantineunknownskipped rD   rE   rF   rG   rH   rI   s         r"   decide_actionrV   U   s]     { '!11r$   entriesc           
      \   g }d}| D ]_  }|d   }|j                  d      }|d   }t        ||dd||      }	|dk(  r|dz  }|j                  ||||j                  d	d
      |	d       a t        j                  t
        j                        j                         ||rdndt        |       ||dS )uj   
    spec §2/§3 기반 dispatch 시뮬레이션.
    audit log 포맷(§4.2)에 맞는 dict 반환.
    r   rD   rI   indexFrU   rR      reason )rY   rD   rI   r[   actionapprovedzdry-run)timestamp_utcrI   approval_modestash_count_before	decisionsskipped_unknown_count)	getrV   appendr   nowr   utc	isoformatlen)
rW   rE   rI   rb   rc   erD   rH   idxr]   s
             r"   simulate_dispatchrl   y   s    
 I 8uuYj"
 Y!Q&!eeHb)
 	#4 "hll3==?'.I!'l!6 r$   c               #      K   t               } g d}|D ]  \  }}t        | ||        |  t        j                  | d       yw)uM   
    unknown stash 3건 + wip 1건 + pre-task 1건 시드.
    총 5건.
    ))zu1.txtz#random unknown stash alpha no match)zu2.txtz'completely unrelated stash message beta)zu3.txtz"some garbage stash data gamma 9999)zw1.txtz&WIP on main: 9a651f37 work in progress)zp1.txtzWIP: pre-task-2571 stash sampleT)ignore_errorsN)r#   r5   shutilrmtree)r-   seedsfnamemsgs       r"   mixed_quarantine_report      sM       HE  *
sHc5)* N
MM($/s   AAc                     t        |       }|j                  dg       }t        |      dk(  sJ dt        |       d       y)u-   5건 stash 가 모두 감지되어야 한다.rW      u   5건 시드 후 u   건 감지됨NrC   rd   ri   )rt   datarW   s      r"   !test_quarantine_total_stash_country      sF    01Dhhy"%Gw<1 
3w<.6r$   c           	          t        |       }|j                  dg       }|D cg c]  }|d   dk(  s| }}t        |      dk(  s'J dt        |       d|D cg c]  }|d   	 c}        yc c}w c c}w )u+   unknown 분류 건수가 3이어야 한다.rW   rD   rR      u"   unknown 건수 기대: 3, 실제: z

sources: Nrw   )rt   rx   rW   rj   unknown_entriess        r"   "test_quarantine_unknown_count_is_3r}      s    01Dhhy"%G")FQQx[I-EqFOF1$ 
,S-A,B C*12QQx[23	5$ G 3s   A,A,A1c                     t        |       }|j                  dg       }|D cg c]  }|d   dk(  s| }}t        |      dk(  sJ dt        |              yc c}w )u'   wip 분류 건수가 1이어야 한다.rW   rD   rP   rZ   u   wip 건수 기대: 1, 실제: Nrw   )rt   rx   rW   rj   wip_entriess        r"   test_quarantine_wip_count_is_1r      sj    01Dhhy"%G%>8)=1>K>{q  
([)9(:;  ?
   AAc                     t        |       }|j                  dg       }|D cg c]  }|d   dk(  s| }}t        |      dk(  sJ dt        |              yc c}w )u,   pre-task 분류 건수가 1이어야 한다.rW   rD   rK   rZ   u#   pre-task 건수 기대: 1, 실제: Nrw   )rt   rx   rW   rj   pretask_entriess        r"   "test_quarantine_pretask_count_is_1r      sk    01Dhhy"%G")GQQx[J-FqGOG1$ 
-c/.B-CD$ Hr   c                    t        |       }|j                  dg       }t        |dd      }|d   D cg c]  }|d   dk(  s| }}t        |      dk(  sJ d	t        |              |D ]  }|d
   dk(  rJ d|d
    d|         yc c}w )u9   unknown 3건 모두 action == preserved 이어야 한다.rW   F	task-2571rE   rI   rb   rD   rR   r{   u)   unknown decisions 수 기대: 3, 실제: r]   rN   u0   unknown stash action 기대: preserved, 실제: z
decision: NrC   rd   rl   ri   rt   rx   rW   logr!   unknown_decisionss         r"   %test_quarantine_unknown_all_preservedr      s    01Dhhy"%G
GUK
HC$'$4Qq(y8PQQ !Q& 
3C8I4J3KL&  
{k) 	
>q{m L	
)
	 Rs   BBc                 f   t        |       }|j                  dg       }t        |dd      }|d   D cg c]  }|d   dk(  s| }}|D ]  }|d   d	k(  rJ d
|d            t        |dd      }|d   D cg c]  }|d   dk(  s| }}|D ]  }|d   d	k(  rJ d|d            yc c}w c c}w )uL   wip stash 는 action == preserved 이어야 한다 (항상, approve 무관).rW   Fr   r   rb   rD   rP   r]   rN   u.   wip dry-run action 기대: preserved, 실제: Tu/   wip approved action 기대: preserved, 실제: NrC   rd   rl   )rt   rx   rW   log_dryr!   wip_decisions_drylog_approvedwip_decisions_approveds           r"   test_quarantine_wip_preservedr      s    01Dhhy"%G  LG$+K$8QqAhK5<PQQ 
{k) 	
<Qx[MJ	
)
 %WdKPL)5k)B[AakUZFZa[[# 
{k) 	
=ak]K	
)
 R \s   B)B)8B.B.c                     t        |       }|j                  dg       }t        |dd      }|d   D cg c]  }|d   dk(  s| }}t        |      dk(  sJ |d	   d
   dk(  sJ d|d	   d
           yc c}w )uF   pre-task stash 는 dry-run 시 action == dry-run-pop 이어야 한다.rW   Fr   r   rb   rD   rK   rZ   r   r]   rM   u5   pre-task dry-run action 기대: dry-run-pop, 실제: Nr   )rt   rx   rW   r   r!   pretask_decisionss         r"   #test_quarantine_pretask_dry_run_popr     s    01Dhhy"%G
GUK
HC$'$4Rq(z8QRR !Q&&&Q)]: 
?@QRS@TU]@^?_`: Ss   A3A3c                     t        |       }|j                  dg       }t        |dd      }|d   dk(  sJ d|d           y)	u   
    audit log 의 skipped_unknown_count == 3 검증.
    spec §4.2 포맷에서 unknown 건은 skipped_unknown_count 로 박제.
    rW   Fr   r   rc   r{   u)   skipped_unknown_count 기대: 3, 실제: Nr   )rt   rx   rW   r   s       r"   *test_quarantine_skipped_unknown_count_is_3r      sY    
 01Dhhy"%G
GUK
HC&'1, 
3C8O4P3QR,r$   c                     t        |       }|j                  dg       }t        |dd      }|d   D cg c]  }|d   dk(  s| }}|D ]  }|d   d	k(  rJ d
|d            yc c}w )uh   
    APPROVE=1 이어도 unknown stash 는 preserved 여야 한다 (spec §3.1 — cleanup 금지).
    rW   Tr   r   rb   rD   rR   r]   rN   u>   APPROVE=1 이어도 unknown action 기대: preserved, 실제: Nr   r   s         r"   3test_quarantine_unknown_preserved_even_with_approver   .  s     01Dhhy"%G
GT;
GC$'$4Qq(y8PQQ 
{k) 	
LQx[MZ	
)
 Rs   A$A$)&__doc__r?   r*   ro   r   r9   r   r   r   pathlibr   pytest__file__resolveparentsWORKTREE_ROOTr<   r;   r#   dictr   r5   rC   boolrV   listrl   fixturert   ry   r}   r   r   r   r   r   r   r   rT   r$   r"   <module>r      se    	   
  '  X&&(003*-==
 
$ _# _ _s _t _%c %d %$!!! ! 	!
 *! 4Z! 	!H(tDz (D (3 (4 (^ 0 06
"
,

r$   