
    iw(                    &   d Z ddlm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mZ  ee      j!                         j"                  d   Zedz  ZddZ edd	      Zg d
Zg dZd Zd Zd Zd Zd Zd Zd Zd Zd Z d Z!d Z"d Z#d Z$d Z%d Z&y)u  tests/regression/test_scripts_hardening_2487.py — task-2487 회귀 테스트 (Group B).

scripts/ 영역의 각 파일이 V2 task ID 패턴을 인식하는지 검증한다.

직접 import 가능한 모듈: done-watcher, report_utils
직접 import 어려운 (side-effect / argparse main) 스크립트: 메타 grep 테스트 적용.

헤임달(개발2팀 테스터) 작성 / task-2487.
    )annotationsN)Path   scriptsc                <   t         |z  }t        j                  j                  | t	        |            }||j
                  t        d|       t        j                  j                  |      }|t        j                  | <   |j
                  j                  |       |S )Nzcannot load spec for )	WORKSPACE	importlibutilspec_from_file_locationstrloaderImportErrormodule_from_specsysmodulesexec_module)mod_namefile_rel	file_pathspecmodules        ]/home/jay/workspace/.worktrees/task-2487-dev2/tests/regression/test_scripts_hardening_2487.py_load_moduler      s    H$I>>11(C	NKD|t{{*1)=>>^^,,T2F"CKKKKF#M    tip_2487_scriptszutils/task_id_parser.py)z	task-1234ztask-1234+1ztask-1234_1.2ztask-1234_1.2_a+3ztask-9999+99ztask-0001_3.14ztask-2487_2.1_b+5)1234ztask-abcz
not-a-task ztask-z	TASK-1234c                    t         dz  j                  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}}y)uB   done-watcher.py 소스에 is_valid_task_id import가 존재한다.done-watcher.pyutf-8encodingis_valid_task_idinz%(py1)s in %(py3)ssrcpy1py3u1   done-watcher.py에 is_valid_task_id 사용 없음
>assert %(py5)spy5NSCRIPTS_DIR	read_text
@pytest_ar_call_reprcompare	_saferepr@py_builtinslocals_should_repr_global_name_format_assertmsgAssertionError_format_explanationr'   @py_assert0@py_assert2@py_format4@py_format6s        r   'test_done_watcher_uses_is_valid_task_idr>   <   s    **
5
5w
5
GCY$YYYYYYYYYYYYYYYYYYY&YYYYYYYr   c            	        t         D ]P  } t        j                  } ||       }d}||u }|s$t        j                  d|fd||f      dt        j                         v st        j                  t              rt        j                  t              ndt        j                  |      dt        j                         v st        j                  |       rt        j                  |       ndt        j                  |      t        j                  |      dz  }t        j                  d| d      d	z   d
|iz  }t        t        j                  |            dx}x}x}}S y)uU   done-watcher가 의존하는 is_valid_task_id가 V2 패턴을 모두 통과시킨다.TiszV%(py5)s
{%(py5)s = %(py2)s
{%(py2)s = %(py0)s.is_valid_task_id
}(%(py3)s)
} is %(py8)stiptidpy0py2r*   r,   py8is_valid_task_id(z) should be True
>assert %(py10)spy10N)V2_VALID_CASESrC   r#   r0   r1   r3   r4   r5   r2   r6   r7   r8   rD   @py_assert1@py_assert4@py_assert7@py_assert6@py_format9@py_format11s          r    test_done_watcher_v2_valid_casesrT   B   s     ^##]#C(]D](D0]]](D]]]]]]s]]]s]]]#]]]]]]C]]]C]]](]]]D]]]4EcWL\2]]]]]]]]^r   c            	        t         D ]P  } t        j                  } ||       }d}||u }|s$t        j                  d|fd||f      dt        j                         v st        j                  t              rt        j                  t              ndt        j                  |      dt        j                         v st        j                  |       rt        j                  |       ndt        j                  |      t        j                  |      dz  }t        j                  d| d      d	z   d
|iz  }t        t        j                  |            dx}x}x}}S y)uR   done-watcher가 의존하는 is_valid_task_id가 잘못된 패턴을 거부한다.Fr@   rB   rC   rD   rE   rI   z) should be FalserJ   rK   N)V2_INVALID_CASESrC   r#   r0   r1   r3   r4   r5   r2   r6   r7   r8   rM   s          r   %test_done_watcher_v2_invalid_rejectedrW   H   s     `##_#C(_E_(E1___(E______s___s___#______C___C___(___E___5FsgM^3________`r   c                 l   t         dz  j                  d      } g }t        j                  }d} |||       }|}|s1t        j                  }d} |||       }|}|sd}	|	| v }
|
}|
sd}|| v }|}|s.dd	t	        j
                         v st        j                  t              rt        j                  t              nd	t        j                  |      t        j                  |      d
t	        j
                         v st        j                  |       rt        j                  |       nd
t        j                  |      dz  }|j                  |       |sdd	t	        j
                         v st        j                  t              rt        j                  t              nd	t        j                        t        j                        d
t	        j
                         v st        j                  |       rt        j                  |       nd
t        j                        dz  }|j                  |       |st        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                  |       |
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}x}x}	x}
x}}y)uW   done-watcher.py 내 .done 파일명 정규식이 V2 suffix(_/+) 토큰을 포함한다.r   r    r!   
_\\d\+\\\\z_\\\\d\+\\\\z_\d+\.	_\d+\.\d+J%(py9)s
{%(py9)s = %(py4)s
{%(py4)s = %(py2)s.search
}(%(py6)s, %(py7)s)
}rer'   rG   py4py6py7py9zQ%(py18)s
{%(py18)s = %(py13)s
{%(py13)s = %(py11)s.search
}(%(py15)s, %(py16)s)
})py11py13py15py16py18r$   )z%(py21)s in %(py23)s)py21py23%(py25)spy25)z%(py28)s in %(py30)s)py28py30z%(py32)spy32   uM   done-watcher.py 파일명 패턴에 V2 언더스코어 phase 토큰이 없음z
>assert %(py35)spy35N)r.   r/   r\   searchr3   r4   r0   r5   r2   appendr1   _format_boolopr6   r7   r8   )r'   rN   @py_assert3@py_assert5@py_assert8r:   @py_assert12@py_assert14@py_assert17@py_assert20@py_assert22@py_assert27@py_assert29@py_format10@py_format19@py_format24@py_format26@py_format31@py_format33@py_format34@py_format36s                        r   (test_done_watcher_file_pattern_covers_v2r   N   sQ   **
5
5w
5
GC299 ] 9]C( ( (BII o Ios,K ,K ,Ky y\_O_ co cosvcv                  #      %(    %(    )    )     -/    -/    -6    7F      HK    HK    -L    -L  y\_    PY      ]`    ]`     cosv    dp      tw    tw        	X       r   c                    t         dz  j                  d      } g }d}|| v }|}|s%d}|| v }|}|sd}| j                  } |       }	||	v }
|
}|s%t        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                  |       |sBt        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                  |       |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                  |       t        j                  |d      i z  }t        j                  d      dz   d|iz  }t        t        j                  |            dx}x}x}x}x}x}x}x}
x}}	y)uQ   notify-completion.py에 _RE_TASK_ID 또는 TASK_ID 관련 패턴이 존재한다.notify-completion.pyr    r!   _RE_TASK_IDTASK_IDtask_idr$   z%(py3)s in %(py5)sr'   r*   r,   %(py7)sr`   z%(py10)s in %(py12)srK   py12%(py14)spy14)zJ%(py17)s in %(py23)s
{%(py23)s = %(py21)s
{%(py21)s = %(py19)s.lower
}()
})py17py19rg   rh   ri   rj   rn   u7   notify-completion.py에 task ID 관련 심볼이 없음z
>assert %(py28)srk   N)r.   r/   lowerr0   r1   r2   r3   r4   r5   rq   rr   r6   r7   r8   )r'   rN   r;   rO   r:   @py_assert9@py_assert11@py_assert16ry   rz   @py_assert18r=   @py_format8@py_format13@py_format15r   r   @py_format27@py_format29s                      r   .test_notify_completion_task_id_pattern_presentr   ^   s9   //
:
:G
:
LC= =C 9 9#3 y CII IK yK7O   =C                     9    $-      14    14     yK    8A      EH    EH    EN    EP        	B      r   c                    t         dz  j                  d      } t        t        j                  d|       xs d| v xs d| v xs
 d| v xs d| v       }|s{t        j                  d	      d
z   ddt        j                         v st        j                  |      rt        j                  |      ndiz  }t        t        j                  |            y)u   notify-completion.py가 V2 패턴(_\d+\.\d+ 또는 +\d+)을 소스에 포함하거나
    utils.task_id_parser를 사용한다 — 미지원이면 FAIL(코드 수정 필요 신호).r   r    r!   rY   rZ   z\+\d+task_id_parserr#   u   notify-completion.py: V2 패턴(_\d+\.\d+ / +\d+) 미포함 및 task_id_parser 미사용 — _RE_TASK_ID가 V1 dot-phase 전용일 가능성
>assert %(py0)srF   has_v2_patternN)r.   r/   boolr\   rp   r0   r6   r3   r4   r5   r2   r7   r8   )r'   r   @py_format1s      r   *test_notify_completion_v2_meta_or_explicitr   f   s     //
:
:G
:
LC
		-% 	%3	%s?	% s"	% $N   	W              >r   c                    t         dz  j                  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}}y)uZ   auto_merge.py가 report_parser를 import하는지 확인 (V2 branch 패턴 간접 검증).zauto_merge.pyr    r!   report_parserr$   r&   r'   r(   u5   auto_merge.py가 report_parser를 import하지 않음r+   r,   Nr-   r9   s        r   %test_auto_merge_imports_report_parserr   |   s    (
3
3W
3
ECZ?c!ZZZ?cZZZ?ZZZZZZcZZZcZZZZ#ZZZZZZZr   c                 (   t         dz  j                  d      } g }t        j                  }d} |||       }|}|sd}|| v }|}|sddt	        j
                         v st        j                  t              rt        j                  t              ndt        j                  |      t        j                  |      dt	        j
                         v st        j                  |       rt        j                  |       ndt        j                  |      d	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}}y)uJ   report_parser.py의 merge_branch 패턴이 V2 suffix(_/+)를 포함한다.zreport_parser.pyr    r!   z&_\\?\\d\+\\.\\d\+|_\d\+\\\.\d\+|_\\d\+rZ   r[   r\   r'   r]   r$   )z%(py12)s in %(py14)s)r   r   z%(py16)sre   rn   uG   report_parser.py merge_branch 패턴에 V2 언더스코어 phase 없음z
>assert %(py19)sr   N)r   r/   r\   rp   r3   r4   r0   r5   r2   rq   r1   rr   r6   r7   r8   )r'   rN   rs   rt   ru   r:   r   @py_assert13r}   r   @py_format17@py_format18@py_format20s                r   'test_auto_merge_report_parser_branch_v2r      s   ))
4
4g
4
FC299 > 9>D D D X[H[                  ?      AD    AD    E    E  X[    IU      Y\    Y\        	R      r   c                    t         dz  j                  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}}y)u=   token-tracker.py에 TASK_RE 컴파일 패턴이 존재한다.token-tracker.pyr    r!   TASK_REr$   r&   r'   r(   u)   token-tracker.py에 TASK_RE 정의 없음r+   r,   Nr-   r9   s        r   "test_token_tracker_task_re_presentr      s    ++
6
6
6
HCH9HHH9HHH9HHHHHHHHHHHHHHHHHHHHr   c                    t         dz  j                  d      } d| v xs d| v xs
 d| v xs d| v }|sUd}|sNt        j                  d	      d
z   dt        j                  |      iz  }t        t        j                  |            d}yy)u   token-tracker.py TASK_RE가 V2 패턴(_/+)을 포함하거나 task_id_parser를 사용한다.
    TASK_RE = re.compile(r'task-\d+(?:\.\d+)?') 처럼 dot-phase 전용이면 FAIL.r   r    r!   rZ   z_\\d\+r   r#   Fu   token-tracker.py TASK_RE가 V2 언더스코어 phase 미지원 — task-1234_1.2 같은 ID를 task-1234 로 잘못 파싱할 수 있음
>assert %(py1)sr)   Nr.   r/   r0   r6   r2   r7   r8   r'   has_v2r:   @py_format2s       r   &test_token_tracker_task_re_v2_coverager      s     ++
6
6
6
HC 	 	%	%s"	% $	   	
u 	
 S	
 	
 
	  	
 	
 	
 	
 	
 r   c                    t         dz  j                  d      } t        |       }d}||kD  }|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
      dz   d|iz  }t        t        j                  |            dx}x}}y)u=   pattern-detector.py 파일이 존재하고 읽을 수 있다.pattern-detector.pyr    r!   d   >z/%(py3)s
{%(py3)s = %(py0)s(%(py1)s)
} > %(py6)slenr'   rF   r)   r*   r_   u<   pattern-detector.py 파일이 비어 있거나 너무 작음
>assert %(py8)srH   Nr.   r/   r   r0   r1   r3   r4   r5   r2   r6   r7   r8   r'   r;   rt   rO   @py_format7rR   s         r   "test_pattern_detector_loads_sourcer      s    ..
9
97
9
KCs8YcY8c>YYY8cYYYYYY3YYY3YYYYYYsYYYsYYY8YYYcYYYYYYYYYYYr   c                    t         dz  j                  d      } t        j                  d|       }|rg }d}|| v }|}|sd}|| v }|}|snt	        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                  |	       |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}}yy)uZ   pattern-detector.py가 task-\d+\.\d+ 전용 패턴 없이 동작하거나 V2 호환이다.r   r    r!   ztask-\\\\d\+\\\\\.\\\\d\+r   rZ   r$   r   r'   r   r   r`   r   r   r   r   rn   uO   pattern-detector.py에 V1 dot-phase 전용 패턴이 있으나 V2 대응 없음z
>assert %(py17)sr   N)r.   r/   r\   findallr0   r1   r2   r3   r4   r5   rq   rr   r6   r7   r8   )r'   dot_onlyrN   r;   rO   r:   r   r   r=   r   r   r   @py_format16r   s                 r   3test_pattern_detector_no_hard_coded_v1_only_task_rer      s   ..
9
97
9
KC zz6<H	
 	
3& 	
, 	
,#*= 	
 	
 	
3 	
 	
 		   	
 	
	6	
 	
  $' 	
 	
 		 $' 	
 	
 	
	6	
		
 	
,# 	
 	
 		 +7 	
 	
	6	
 	
  ;> 	
 	
 		 ;> 	
 	
 	
	6	
		
 	
 	
  ^	
 	
 	
 	
 	
 	
 r   c                 P   t         dz  j                  d      } d| v xs
 d| v xs d| v }|s{t        j                  d      dz   d	d
t	        j
                         v st        j                  |      rt        j                  |      nd
iz  }t        t        j                  |            y)uc   report_utils.py 내 제목 추출 정규식이 V2 ID(언더스코어 phase) 제거를 지원한다.zreport_utils.pyr    r!   rZ   z_\\d+r   uX   report_utils.py 제목 추출 정규식이 V2 언더스코어 phase(_\d+\.\d+) 미지원r   rF   r   N)
r.   r/   r0   r6   r3   r4   r5   r2   r7   r8   )r'   r   r   s      r   )test_report_utils_title_pattern_covers_v2r      s    **
5
5w
5
GCS NHON7G37NF   	f              6r   c                    t         dz  j                  d      } t        |       }d}||kD  }|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
      dz   d|iz  }t        t        j                  |            dx}x}}y)u=   start_task_guard.py 파일이 존재하고 읽을 수 있다.start_task_guard.pyr    r!      r   r   r   r'   r   u;   start_task_guard.py 파일이 비어있거나 너무 작음r   rH   Nr   r   s         r   %test_start_task_guard_source_readabler      s    ..
9
97
9
KCs8XcX8c>XXX8cXXXXXX3XXX3XXXXXXsXXXsXXX8XXXcXXXXXXXXXXXr   c                    t         dz  j                  d      } d| v xs d| v xs
 d| v xs d| v }|sUd}|sNt        j                  d	      d
z   dt        j                  |      iz  }t        t        j                  |            d}yy)u   start_task_guard.py의 branch에서 task-id 추출 로직이 V2 suffix를 처리할 수 있다.
    현재 단순 split('-') 방식이면 task-1234+1-dev4 에서 task-1234 를 잘못 추출할 수 있음.r   r    r!   r   extract_task_id_from_branchrZ   z+\d+Fu   start_task_guard.py: branch에서 task-id 추출 시 V2 suffix 미처리 — task/task-1234+1-dev4 에서 task-1234+1 을 올바르게 추출하는지 확인 필요r   r)   Nr   r   s       r   *test_start_task_guard_branch_extraction_v2r      s     ..
9
97
9
KC 	C 	(C/	3	 c>	   	
u 	
 f	
 	
 
	  	
 	
 	
 	
 	
 r   )r   r   r   r   )'__doc__
__future__r   builtinsr3   _pytest.assertion.rewrite	assertionrewriter0   importlib.utilr	   r\   r   pathlibr   __file__resolveparentsr   r.   r   rC   rL   rV   r>   rT   rW   r   r   r   r   r   r   r   r   r   r   r   r    r   r   <module>r      s    #     	 
 N""$,,Q/	)#" %'@A Z^` ,[I
0Z	
"Y
r   