
    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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 g dZ! ejD                         d        Z#d Z$d Z%d Z&d Z'd Z(d  Z)d! Z*y)"u  
test_stash_lifecycle_legacy.py
task: task-2571 TODO-7 T-4

검증 목표:
- spec §9 legacy stash 호환성 검증
- legacy 포맷 (표준 메타데이터 없는 stash) 은 source=unknown 으로 분류
- unknown 분기 적용 시 모두 preserve

작성자: 하누만 (개발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     C/home/jay/workspace/tests/regression/test_stash_lifecycle_legacy.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   .   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   8   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(  }|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z   d|iz  }t        t        j                   |            dx}x}}t#        j$                  |j&                        S )u7   stash_audit.py --json 실행 후 파싱된 dict 반환.z--jsonz--workspaceT)capture_outputtextr   ==)z2%(py2)s
{%(py2)s = %(py0)s.returncode
} == %(py5)sresult)py0py2py5u#   stash_audit.py 실행 실패 (exit=z
)
stderr: z
>assert %(py7)spy7N)r   r   sys
executablestrSTASH_AUDIT_PY
returncode
@pytest_ar_call_reprcompare@py_builtinslocals_should_repr_global_name	_saferepr_format_assertmsgstderrAssertionError_format_explanationjsonloadsstdout)r-   r;   @py_assert1@py_assert4@py_assert3@py_format6@py_format8s          r"   _run_audit_jsonrW   A   s   ^^	^,hxPF
   !                    !"    .f.?.?-@ A==/	#     ::fmm$$r$   sourceapprovepr_verifiedidx_in_drop_listetidtask_idc                 `    | dk(  r|rdS dS | dk(  r|r|r||k(  ry|syy| dk(  r|r|ryy| d	v ryy
)u0   spec §2 결정 흐름 reference implementation.zpre-taskpoppedzdry-run-popzfinish-task	preservedzother-filesdroppedzdry-run-drop)wip
quarantineunknownskipped rX   rY   rZ   r[   r\   r]   s         r"   decide_actionrh   S   s[     "x55{ '11r$   entriesc           	      :   g }d}| D ]N  }|d   }|j                  d      }|d   }t        ||dd||      }	|dk(  r|dz  }|j                  ||||	d	       P t        j                  t
        j                        j                         ||rd
ndt        |       ||dS )u-   spec §2/§3 기반 dispatch 시뮬레이션.r   rX   r]   indexFrg   rd      )rk   rX   r]   actionapprovedzdry-run)timestamp_utcr]   approval_modestash_count_before	decisionsskipped_unknown_count)	getrh   appendr   nowr   utc	isoformatlen)
ri   rY   r]   rr   rs   erX   r\   idxrm   s
             r"   simulate_dispatchr|   q   s    I 8uuYj"
 Y!Q&!	
 	#2 "hll3==?'.I!'l!6 r$   )zsome old stash from 2025zMy work before vacationztemp changes backup 20240301c               #      K   t               } t        t              D ]  \  }}t        | |d| d        |  t	        j
                  | d       yw)u/   legacy 포맷 stash 3건 시드된 임시 repo.legacy_z.txtT)ignore_errorsN)r#   	enumerateLEGACY_STASH_MESSAGESr5   shutilrmtree)r-   imsgs      r"   legacy_repor      sS       H12 63HcWQCt#456 N
MM($/s   AAc                    t        |       }|j                  dg       }t        |      }d}||k(  }|st        j                  d|fd||f      dt        j                         v st        j                  t              rt        j                  t              nddt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      dz  }t        j                  dt        |       d      d	z   d
|iz  }t        t        j                  |            dx}x}}y)u3   legacy stash 3건이 모두 감지되어야 한다.ri      r9   )z0%(py3)s
{%(py3)s = %(py0)s(%(py1)s)
} == %(py6)sry   )r<   py1py3py6u   3건 시드 후 u   건 감지됨z
>assert %(py8)spy8N)rW   rt   ry   rE   rF   rG   rH   rI   rJ   rK   rM   rN   )r   datari   @py_assert2@py_assert5rS   @py_format7@py_format9s           r"    test_legacy_all_stashes_detectedr      s   ;'Dhhy"%Gw< 1 <1   <1                                3w<.6     r$   c           
         t        |       }|j                  dg       }|D ]  }|d   }d}||k(  }|st        j                  d|fd||f      t        j                  |      t        j                  |      dz  }t        j
                  d|d    d|j                  d	d
             dz   d|iz  }t        t        j                  |            dx}x}} y)u   
    legacy 포맷 stash 3건 모두 source=unknown 으로 분류되어야 한다.
    spec §2.2: 패턴 매칭 실패 → source=unknown → quarantine.
    ri   rX   rd   r9   z%(py1)s == %(py4)sr   py4u%   legacy stash 가 unknown 이 아닌 'u   ' 로 분류됨
raw_message: raw_message 
>assert %(py6)sr   N)rW   rt   rE   rF   rJ   rK   rM   rN   )	r   r   ri   entry@py_assert0rT   r   @py_format5r   s	            r"   %test_legacy_all_classified_as_unknownr      s    
 ;'Dhhy"%G 
X 	
) 	
)+ 	
 	
) 	
 	
 
	  	
 	
 
	 #, 	
 	
  4E(O3D E!IImR89;	
 	
 	
 	
 	
 	

r$   c                    t        |       }|j                  dg       }t        |dd      }|d   D ]  }|d   }d}||k(  }|st        j                  d|fd	||f      t        j
                  |      t        j
                  |      d
z  }t        j                  d|d          dz   d|iz  }	t        t        j                  |	            dx}x}} t        |dd      }
|
d   D ]  }|d   }d}||k(  }|st        j                  d|fd	||f      t        j
                  |      t        j
                  |      d
z  }t        j                  d|d          dz   d|iz  }	t        t        j                  |	            dx}x}} y)uQ   dispatch 정책 적용 시 legacy stash 전부 action=preserved 이어야 한다.ri   F	task-2571rY   r]   rr   rm   r`   r9   r   r   u3   legacy (dry-run) action 기대: preserved, 실제: r   r   NTu4   legacy (approved) action 기대: preserved, 실제: 	rW   rt   r|   rE   rF   rJ   rK   rM   rN   )r   r   ri   log_dryr!   r   rT   r   r   r   log_approveds              r"   "test_legacy_dispatch_all_preservedr      s   ;'Dhhy"%G  LG[! 
{ 	
k 	
{k) 	
 	
{k 	
 	
 		  	
 	
 		 * 	
 	
  B!H+O	
 	
 	
 	
 	
 	

 %WdKPL+& 
{ 	
k 	
{k) 	
 	
{k 	
 	
 		  	
 	
 		 * 	
 	
  C1X;-P	
 	
 	
 	
 	
 	

r$   c                    t        |       }|j                  dg       }t        |dd      }|d   }d}||k(  }|st        j                  d|fd||f      t        j
                  |      t        j
                  |      d	z  }t        j                  d
|d          dz   d|iz  }t        t        j                  |            dx}x}}y)u,   skipped_unknown_count 가 3이어야 한다.ri   Fr   r   rs   r   r9   r   r   u)   skipped_unknown_count 기대: 3, 실제: r   r   Nr   )	r   r   ri   logr   rT   r   r   r   s	            r"   &test_legacy_skipped_unknown_count_is_3r      s    ;'Dhhy"%G
GUK
HC&' 1 '1,  '1    (    ,-    4C8O4P3QR     r$   c           
         t        |       }|j                  dg       }|D ]<  }|j                  }d} ||      }d}||u }|st        j                  d|fd||f      dt	        j
                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      t        j                  |      t        j                  |      dz  }	t        j                  d|j                  d       d	|j                  d
d             dz   d|	iz  }
t        t        j                  |
            dx}x}x}x}}? y)u?   legacy stash 메시지에서 task_id 가 None 이어야 한다.ri   r]   N)is)zI%(py6)s
{%(py6)s = %(py2)s
{%(py2)s = %(py0)s.get
}(%(py4)s)
} is %(py9)sr   )r<   r=   r   r   py9u8   legacy stash 에서 예상치 못한 task_id 추출됨: z
raw_message: r   r   z
>assert %(py11)spy11)rW   rt   rE   rF   rG   rH   rI   rJ   rK   rM   rN   )r   r   ri   r   rR   rT   r   @py_assert8@py_assert7@py_format10@py_format12s              r"    test_legacy_no_task_id_extractedr      sd   ;'Dhhy"%G 
yy 	
 	
y# 	
t 	
#t+ 	
 	
 	
#t 	
 	
 
6	
 	
   	
 	
 
	  	
 	
 
	  	
 	
 
	 # 	
 	
 
	 $ 	
 	
 
	 (, 	
 	
  GuyyQZG[F\ ]!IImR89;	
 	
 	
 	
 	
 	

r$   c                 z   t        |       }|j                  dg       }|D ]  }d}||v }|st        j                  d|fd||f      t        j                  |      dt        j                         v st        j                  |      rt        j                  |      nddz  }t        j                  d|       dz   d	|iz  }t        t        j                  |            d
x}}|d   }|sNt        j                  d      dz   dt        j                  |      iz  }t        t        j                  |            d
} y
)u:   legacy entries 에 raw_message 필드가 있어야 한다.ri   r   inz%(py1)s in %(py3)sr   r   r   u   entry 에 raw_message 없음: 
>assert %(py5)sr>   Nu    raw_message 가 빈 문자열임z
>assert %(py1)sr   rW   rt   rE   rF   rJ   rG   rH   rI   rK   rM   rN   )	r   r   ri   r   r   r   @py_format4rU   @py_format2s	            r"   $test_legacy_entries_have_raw_messager      s   ;'Dhhy"%G H 	
}% 	
 	
} 	
 	
 		  	
 	
	6	
 	
  !& 	
 	
 		 !& 	
 	
  -UG4	
 	
 	
 	
 	
 ]#G#GG%GGGG#GGGGGG	Hr$   c                    t        |       }|j                  di       }|j                  di       }d}||v }|st        j                  d|fd||f      t        j                  |      dt        j                         v st        j                  |      rt        j                  |      nddz  }t        j                  d|       dz   d	|iz  }t        t        j                  |            d
x}}|d   }d}||k(  }|st        j                  d|fd||f      t        j                  |      t        j                  |      dz  }	t        j                  d|d          dz   d|	iz  }
t        t        j                  |
            d
x}x}}y
)uC   summary.count_by_source 에 unknown 카운트가 3이어야 한다.summarycount_by_sourcerd   r   r   r   u(   count_by_source 에 unknown 키 없음: r   r>   Nr   r9   r   r   u!   unknown count 기대: 3, 실제: r   r   r   )r   r   r   r   r   r   r   rU   rT   r   r   s              r"   0test_legacy_audit_json_summary_has_unknown_countr     sf   ;'Dhhy"%Gkk"3R8O 9'  9          (    (    3?2CD     9%  %*  %    &    *+    ,OI,F+GH     r$   )+__doc__builtinsrG   _pytest.assertion.rewrite	assertionrewriterE   rO   r*   r   r   r@   r   r   r   pathlibr   pytest__file__resolveparentsWORKTREE_ROOTrC   rB   r#   dictr   r5   rW   boolrh   listr|   r   fixturer   r   r   r   r   r   r   r   rf   r$   r"   <module>r      sg  
   	   
  '  X&&(003*-==
 
$ _# _ _s _t _%c %d %$  	
 * 4Z 	<$tDz $D $3 $4 $X  	0 	0 

(	
	Hr$   