
    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 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 ej6                         d        Zd Zdee   dededz  fdZd Z d Z!d Z"d Z#d Z$d Z%d Z&d Z'y)un  
test_stash_lifecycle_classification.py
task: task-2571 TODO-7 T-1

검증 목표:
- spec §2 분류 매트릭스 기준 6 카테고리 stash 메시지 분류 정확성
- 임시 git repo 에서 각 source 1건씩 stash 메시지 시드 후 stash_audit.py --json 호출
- entries[].source 가 기대값과 일치하는지 검증

작성자: 하누만 (개발4팀 QA)
    N)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     K/home/jay/workspace/tests/regression/test_stash_lifecycle_classification.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_pushr3   7   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+   r9   @py_assert1@py_assert4@py_assert3@py_format6@py_format8s          r    _run_audit_jsonrU   @   s   ^^	^,hxPF
   !                    !"    .f.?.?-@ A==/	#     ::fmm$$r"   c               #      K   t               } g d}|D ]  \  }}}t        | ||        | |f t        j                  | d       yw)u   
    spec §2 6 카테고리 stash 메시지 각 1건씩 시드.
    각 stash 는 별도 파일을 dirty 상태로 만들어 push.
    ))pre-taskzf1.txtzWIP: pre-task-2571 stash sample)
quarantinezf2.txtzB[task-2566][source=quarantine][reason=test] finish-task-quarantine)other-fileszf3.txtzE[task-2564][source=other-files][reason=test] other-files-stash sample)finish-taskzf4.txtzH[task-2569][source=finish-task][reason=test] finish-task GIT-GATE sample)wipzf5.txt!WIP on main: 9a651f37 some change)unknownzf6.txt'random unknown stash message no patternT)ignore_errorsN)r!   r3   shutilrmtree)r+   seeds_fnamemsgs        r    six_category_reporf   R   sT       HE  *5#Hc5)* E/
MM($/s   AAc           
         | \  }}t        |      }|j                  dg       }t        |      }d}||k(  }|s1t        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t        j                  |d	d
             dz   d|iz  }	t        t        j                  |	            dx}x}}y)u-   6 카테고리 모두 감지되어야 한다.entries   r7   )z0%(py3)s
{%(py3)s = %(py0)s(%(py1)s)
} == %(py6)slen)r:   py1py3py6u   6건 stash 시드 후 u   건만 감지됨
entries: Fr   )ensure_asciiindentz
>assert %(py8)spy8N)rU   getrj   rC   rD   rE   rF   rG   rH   rI   rM   dumpsrK   rL   )
rf   r+   rc   datarh   @py_assert2@py_assert5rQ   @py_format7@py_format9s
             r    ,test_classification_all_six_sources_detectedrx   p   s?   #KHa8$Dhhy"%Gw< 1 <1   <1                                !W /JJwU1EF	H     r"   rh   fragmentc                 B    | D ]  }||j                  dd      v s|c S  y)u   
    raw_message 에 fragment 가 포함된 entry 를 반환.
    git stash list 는 "On main: <msg>" 형식으로 prefix 를 붙이므로
    exact match 대신 substring search 를 사용.
    raw_message N)rq   )rh   ry   es      r    _find_entry_by_msg_fragmentr~   {   s0      quu]B//H r"   c                 n   | \  }}t        |      }|j                  dg       }d}t        ||      }d}||u}|st        j                  d|fd||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      dz  }	t        j                  d| d	|D 
cg c]  }
|
j                  d
       c}
       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|d
          dz   d|iz  }t        t        j                  |            dx}x}}yc c}
w )uQ   'WIP: pre-task-2571 stash sample' 은 source=pre-task 로 분류되어야 한다.rh   zpre-task-2571 stash sampleNis notz%(py0)s is not %(py3)sentryr:   rl   'u'   ' 포함 entry 미발견
raw_messages: r{   
>assert %(py5)sr<   sourcerW   r7   z%(py1)s == %(py4)srk   py4u   기대: pre-task, 실제: 
raw_message: 
>assert %(py6)srm   rU   rq   r~   rC   rD   rE   rF   rG   rH   rI   rK   rL   )rf   r+   rc   rs   rh   ry   r   rt   rP   @py_format4r}   rS   @py_assert0rR   @py_format5rv   s                   r    "test_classification_pretask_sourcer      s   #KHa8$Dhhy"%G+H':E 5  5                  H: 8?@1!%%.@A	C     ? j ?j(  ?j        )    %U8_$5_U=EYDZ[      As   F2c                 &   | \  }}t        |      }|j                  dg       }d}t        ||      }d}||u}|st        j                  d|fd||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      dz  }	t        j                  d| 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|d          dz   d|iz  }t        t        j                  |            dx}x}}y)uU   finish-task-quarantine 패턴 stash 는 source=quarantine 로 분류되어야 한다.rh   zfinish-task-quarantineNr   r   r   r   r      ' 포함 entry 미발견r   r<   r   rX   r7   r   r   u   기대: quarantine, 실제: r   r{   r   rm   r   rf   r+   rc   rs   rh   ry   r   rt   rP   r   rS   r   rR   r   rv   s                  r    %test_classification_quarantine_sourcer      sy   #KHa8$Dhhy"%G'H':E 5  5                  H:-.     ? l ?l*  ?l        +    'uX&7u]G[F\]     r"   c                 &   | \  }}t        |      }|j                  dg       }d}t        ||      }d}||u}|st        j                  d|fd||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      dz  }	t        j                  d| 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|d          dz   d|iz  }t        t        j                  |            dx}x}}y)uQ   other-files-stash 패턴 stash 는 source=other-files 로 분류되어야 한다.rh   zother-files-stash sampleNr   r   r   r   r   r   r   r<   r   rY   r7   r   r   u   기대: other-files, 실제: r   r{   r   rm   r   r   s                  r    &test_classification_other_files_sourcer      sy   #KHa8$Dhhy"%G)H':E 5  5                  H:-.     ? m ?m+  ?m        ,    (h'8mH\G]^     r"   c                 &   | \  }}t        |      }|j                  dg       }d}t        ||      }d}||u}|st        j                  d|fd||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      dz  }	t        j                  d| 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|d          dz   d|iz  }t        t        j                  |            dx}x}}y)uK   finish-task 패턴 stash 는 source=finish-task 로 분류되어야 한다.rh   zfinish-task GIT-GATE sampleNr   r   r   r   r   r   r   r<   r   rZ   r7   r   r   u   기대: finish-task, 실제: r   r{   r   rm   r   r   s                  r    &test_classification_finish_task_sourcer      sy   #KHa8$Dhhy"%G,H':E 5  5                  H:-.     ? m ?m+  ?m        ,    (h'8mH\G]^     r"   c                 $   | \  }}t        |      }|j                  dg       }d}t        ||      }d}||u}|st        j                  d|fd||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      dz  }	t        j                  d| d	      d
z   d|	iz  }
t        t        j                  |
            dx}}|d   }d}||v }|st        j                  d|fd||f      t        j                  |      t        j                  |      dz  }t        j                  d|d    d|d          dz   d|iz  }t        t        j                  |            dx}x}}y)uc  
    'WIP on main: 9a651f37 some change' 패턴 stash 는 source=wip 로 분류되어야 한다.
    주의: git stash push -m "WIP on main: ..." 시 stash list 는 "On main: WIP on main: ..."
    로 표시될 수 있음. raw_message 기반 패턴 매칭(^WIP on \w) 은 stash_audit.py
    SOURCE_PATTERNS 5번 패턴. "On main: WIP on main: ..." 처럼 prefix 붙은 경우
    ^WIP 매칭이 안 될 수 있어 unknown 으로 분류될 수 있음.
    이 경우 "WIP on main:" 포함 여부로 source 를 검증하되,
    wip 또는 unknown 둘 다 허용 (stash_audit.py 현행 패턴 제약 반영).
    rh   r\   Nr   r   r   r   r   r   r   r<   r   )r[   r]   in)z%(py1)s in %(py4)sr   u$   기대: wip 또는 unknown, 실제: r   r{   r   rm   r   r   s                  r    test_classification_wip_sourcer      s    $KHa8$Dhhy"%G2H':E 5  5                  H:-.     ? 0 ?00  ?0        1    /uX.?uUbOcNde     r"   c                 &   | \  }}t        |      }|j                  dg       }d}t        ||      }d}||u}|st        j                  d|fd||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      dz  }	t        j                  d| 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|d          dz   d|iz  }t        t        j                  |            dx}x}}y)uI   패턴 매칭 없는 stash 는 source=unknown 로 분류되어야 한다.rh   r^   Nr   r   r   r   r   r   r   r<   r   r]   r7   r   r   u   기대: unknown, 실제: r   r{   r   rm   r   r   s                  r    "test_classification_unknown_sourcer      sy   #KHa8$Dhhy"%G8H':E 5  5                  H:-.     ? i ?i'  ?i        (    $E(O#4OE-DXCYZ     r"   c           	      8   | \  }}t        |      }|j                  dg       }|D ]  }dD ]  }||v }|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                  |      rt        j                  |      nddz  }t        j                  d| d	|       d
z   d|iz  }	t        t        j                  |	            d}  y)uO   모든 entry 가 필수 필드(index, source, raw_message)를 가져야 한다.rh   )indexr   r{   r   )z%(py0)s in %(py2)sfieldr}   )r:   r;   u   entry 에 'u   ' 필드 없음
entry: z
>assert %(py4)sr   N)rU   rq   rC   rD   rE   rF   rG   rH   rI   rK   rL   )
rf   r+   rc   rs   rh   r}   r   rP   @py_format3r   s
             r    4test_classification_all_entries_have_required_fieldsr      s   #KHa8$Dhhy"%G 7 	EA:  5A  v     I   v     I     eW$<QC@    	r"   c                 "   | \  }}t        |      }|j                  di       }|j                  di       }t        |j                               }d}||k(  }|st	        j
                  d|fd||f      dt        j                         v st	        j                  |      rt	        j                  |      ndt	        j                  |      dz  }	t	        j                  d| d	|       d
z   d|	iz  }
t        t	        j                  |
            dx}}y)u4   summary.count_by_source 합계가 6이어야 한다.summarycount_by_sourceri   r7   )z%(py0)s == %(py3)stotalr   u'   count_by_source 합계가 6이 아님: z
count_by_source: r   r<   N)rU   rq   sumvaluesrC   rD   rE   rF   rG   rH   rI   rK   rL   )rf   r+   rc   rs   r   r   r   rt   rP   r   rS   s              r    2test_classification_count_by_source_matches_matrixr      s    #KHa8$Dhhy"%Gkk"3R8O&&()E 5A:  5A                  2% 9+,	.    r"   )(__doc__builtinsrE   _pytest.assertion.rewrite	assertionrewriterC   rM   r(   r`   r   r>   r   pathlibr   pytest__file__resolveparentsWORKTREE_ROOTrA   r@   r!   dictr   r3   rU   fixturerf   rx   listr~   r   r   r   r   r   r   r   r    r"   r    <module>r      s  
   	   
   X&&(003*-==
 
$ _# _ _s _t _%c %d %$ 0 0:	d 	s 	td{ 	"   6 	
r"   