
    (<if'              	          d Z ddlZddlZddlZddlmZ ddlmZmZ ej                  j                  d e ee      j                  j                               ddlmZ ddlmZ ddeded	ed
efdZ G d d      Z G d d      Zy)u   카마소츠(테스터): AST 통합 테스트 — worktree_manager & codex_gate_check.

대상 함수:
  - worktree_manager._get_blast_radius_summary
  - codex_gate_check._get_callers_context
    N)Path)	MagicMockpatch)_get_blast_radius_summary_get_callers_context
returncodestdoutstderrreturnc                 D    t               }| |_        ||_        ||_        |S )u%   subprocess.run 반환값 Mock 생성.)r   r	   r
   r   )r	   r
   r   mocks       S/home/jay/workspace/.worktrees/task-2057-dev2/scripts/tests/test_ast_integration.py
_make_procr      s#    ;D DODKDKK    c                   :    e Zd ZdZd Zd Zd Zd Zd Zd Z	d Z
y	)
TestGetBlastRadiusSummaryu<   worktree_manager._get_blast_radius_summary 유닛 테스트.c                     t        dd      }t        d|      5  t        ddd      }d	d	d	       d
k(  sJ y	# 1 sw Y   xY w)u5   git diff returncode != 0 이면 빈 문자열 반환.   zfatal: not a git repor	   r   subprocess.runreturn_value
/fake/pathfeaturemainN r   r   r   )selfgit_failresults      r   #test_git_diff_failure_returns_emptyz=TestGetBlastRadiusSummary.test_git_diff_failure_returns_empty*   sO    3JK#(; 	P.|YOF	P ||	P 	P	   9Ac                     t        dd      }t        d|      5  t        ddd      }d	d	d	       dk(  sJ y	# 1 sw Y   xY w)
u7   변경된 .py 파일이 없으면 빈 문자열 반환.r   r   r	   r
   r   r   r   r   r   Nr   )r   git_okr!   s      r   #test_no_changed_files_returns_emptyz=TestGetBlastRadiusSummary.test_no_changed_files_returns_empty3   sN    q4#&9 	P.|YOF	P ||	P 	Pr#   c                    t        dd      }dgdgd}t        dt        j                  |            }t        d||g      5  t	        d	d
d      }ddd       j                  d      sJ d|v sJ d|v sJ d|v sJ y# 1 sw Y   /xY w)u5   AST 성공 시 '## Blast Radius' 마크다운 반환.r   zsrc/foo.py
src/bar.py
r%   z
src/baz.pyztests/test_foo.pydirect_importers
test_filesr   side_effectr   r   r   N## Blast Radiusu   변경 파일u   영향받는 파일u   관련 테스트r   jsondumpsr   r   
startswithr   r&   ast_dataast_okr!   s        r   .test_ast_success_returns_blast_radius_markdownzHTestGetBlastRadiusSummary.test_ast_success_returns_blast_radius_markdown<   s    q1KL!-./
 qH1EF#&&1AB 	P.|YOF	P   !2333&((($...!V+++	P 	Ps   B  B	c                     t        dd      }g g d}t        dt        j                  |            }t        d||g      5  t	        ddd	      }d
d
d
       j                  d      sJ d|v sJ y
# 1 sw Y   #xY w)uN   AST 성공이지만 direct_importers/test_files 비어도 마크다운 반환.r   src/foo.py
r%   r)   r   r,   r   r   r   Nr.   u   없음r/   r3   s        r    test_ast_success_empty_importersz:TestGetBlastRadiusSummary.test_ast_success_empty_importersM   s    q@(*"=qH1EF#&&1AB 	P.|YOF	P   !23336!!!		P 	Ps   A22A;c                     t        dt        j                  dd            5  t        ddd      }d	d	d	       d
k(  sJ y	# 1 sw Y   xY w)u:   subprocess.TimeoutExpired 발생 시 빈 문자열 반환.r   git   cmdtimeoutr,   r   r   r   Nr   )r   
subprocessTimeoutExpiredr   r   r!   s     r   %test_subprocess_timeout_returns_emptyz?TestGetBlastRadiusSummary.test_subprocess_timeout_returns_emptyY   sP    #1J1Ju^`1ab 	P.|YOF	P ||	P 	Ps   AA
c                     t        dd      }t        dd      }t        d||g      5  t        ddd	      }d
d
d
       dk(  sJ y
# 1 sw Y   xY w)uB   AST stdout이 유효하지 않은 JSON이면 빈 문자열 반환.r   r8   r%   zNOT VALID JSON {{{r   r,   r   r   r   Nr   r   )r   r&   ast_badr!   s       r   %test_json_parse_failure_returns_emptyz?TestGetBlastRadiusSummary.test_json_parse_failure_returns_empty`   s`    q@2FG#&'1BC 	P.|YOF	P ||	P 	P   AAc                     t        dd      }t        dd      }t        d||g      5  t        d	d
d      }ddd       dk(  sJ y# 1 sw Y   xY w)u=   AST 스크립트 returncode != 0 이면 빈 문자열 반환.r   r8   r%   r   zError: script failedr   r   r,   r   r   r   Nr   r   )r   r&   ast_failr!   s       r   %test_ast_script_failure_returns_emptyz?TestGetBlastRadiusSummary.test_ast_script_failure_returns_emptyj   s`    q@3IJ#&(1CD 	P.|YOF	P ||	P 	PrG   N)__name__
__module____qualname____doc__r"   r'   r6   r9   rC   rF   rJ    r   r   r   r   '   s(    F,"
"r   r   c                   @    e Zd ZdZd Zd Zd Zd Zd Zd Z	d Z
d	 Zy
)TestGetCallersContextu7   codex_gate_check._get_callers_context 유닛 테스트.c                 *    t        g d      }|dk(  sJ y)u/   빈 affected_files 리스트 → 빈 문자열.z/fake/workspacer   Nr   rB   s     r   test_empty_list_returns_emptyz3TestGetCallersContext.test_empty_list_returns_empty}   s    %b*;<||r   c                 >    t        dgt        |            }|dk(  sJ y)u:   AST 스크립트 파일이 없으면 빈 문자열 반환.
src/foo.pyr   N)r   str)r   tmp_pathr!   s      r   'test_ast_script_not_found_returns_emptyz=TestGetCallersContext.test_ast_script_not_found_returns_empty   s"     &|nc(mD||r   c                 R   |dz  }|j                          |dz  j                          ddg dii}t        dt        j                  |            }t        d|	      5  t        d
gt        |            }ddd       j                  d      sJ d
|v sJ d|v sJ y# 1 sw Y   )xY w)uL   AST 성공 + callers 있음 → '함수 호출자 정보:' 포함 문자열.scriptsast_dependency_map.pyblast_radiuscallers)a.pyb.pyzc.pyr   r%   r   r   rU   N   함수 호출자 정보:u   3곳에서 호출됨)	mkdirtouchr   r0   r1   r   r   rV   r2   r   rW   ast_dirr4   r5   r!   s         r   *test_ast_success_with_callers_returns_infoz@TestGetCallersContext.test_ast_success_with_callers_returns_info   s     Y&	*	*113 3

 qH1EF#&9 	I)<.#h-HF	I   !;<<<v%%%%///	I 	Is   BB&c                    |dz  }|j                          |dz  j                          ddg ii}t        dt        j                  |            }t        d|      5  t        d	gt        |            }d
d
d
       dk(  sJ y
# 1 sw Y   xY w)u4   AST 성공 + callers 비어있음 → 빈 문자열.rZ   r[   r\   r]   r   r%   r   r   rU   Nr   )ra   rb   r   r0   r1   r   r   rV   rc   s         r   )test_ast_success_no_callers_returns_emptyz?TestGetCallersContext.test_ast_success_no_callers_returns_empty   s    Y&	*	*113"YO4qH1EF#&9 	I)<.#h-HF	I ||	I 	Is   BBc                     |dz  }|j                          |dz  j                          t        dt        j                  dd            5  t        dgt        |            }d	d	d	       d
k(  sJ y	# 1 sw Y   xY w)u(   TimeoutExpired 발생 시 빈 문자열.rZ   r[   r   python3r<   r=   r,   rU   Nr   )ra   rb   r   r@   rA   r   rV   )r   rW   rd   r!   s       r   rC   z;TestGetCallersContext.test_subprocess_timeout_returns_empty   sy    Y&	*	*113#1J1Jybd1ef 	I)<.#h-HF	I ||	I 	Is   A22A;c                 
   |dz  }|j                          |dz  j                          t        d      D cg c]  }d| d
 }}dd|ii}t        dt	        j
                  |      	      }t        d
|      5  t        dgt        |            }ddd       dv sJ |j                  dd      d   }|j                  d      D 	cg c]  }	|	j                          }
}	t        |
      dk(  sJ yc c}w # 1 sw Y   fxY wc c}	w )u6   callers가 6개 이상이어도 상위 5개만 표시.rZ   r[      caller_z.pyr\   r]   r   r%   r   r   rU   Nu   8곳에서 호출됨z:    ,   )ra   rb   ranger   r0   r1   r   r   rV   splitstriplen)r   rW   rd   ir]   r4   r5   r!   caller_partclisteds              r   test_top_5_callers_onlyz-TestGetCallersContext.test_top_5_callers_only   s   Y&	*	*113-21X6WQCs#66"Y$89qH1EF#&9 	I)<.#h-HF	I &///ll4+B/%0%6%6s%;<!'')<<6{a 7	I 	I =s   C/8C4D 4C=c                 
   |dz  }|j                          |dz  j                          d }t        d|      5  t        ddgt	        |            }ddd       j                  d	      sJ d
|v sJ d|vsJ y# 1 sw Y   )xY w)u=   여러 파일 처리 시 callers 있는 파일만 행 생성.rZ   r[   c                     d| v r| j                  d      nd}|dk\  r| |dz      nd}d|v r	ddd	d
gii}nddg ii}t        dt        j                  |            S )N--filesr   r   r   foo.pyr\   r]   r^   r_   r%   indexr   r0   r1   r>   _kw	files_idxfile_argdatas        r   r-   zKTestGetCallersContext.test_multiple_files_with_callers.<locals>.side_effect   sq     1:S0@		),bI-6!^s9q=)H8#&VV4D(EF&B84::d3CDDr   r   r,   rU   
src/bar.pyNr`   r~   bar.pyra   rb   r   r   rV   r2   r   rW   rd   r-   r!   s        r    test_multiple_files_with_callersz6TestGetCallersContext.test_multiple_files_with_callers   s    Y&	*	*113		E #= 	W)<*FHVF	W   !;<<<6!!!v%%%	W 	Ws   A99Bc                     |dz  }|j                          |dz  j                          d }t        d|      5  t        ddgt	        |            }ddd       j                  d	      sJ d
|v sJ y# 1 sw Y   #xY w)u>   JSON 파싱 실패한 파일은 건너뛰고 나머지 반환.rZ   r[   c                     d| v r| j                  d      nd}|dk\  r| |dz      nd}d|v rt        dd      S d	d
dgii}t        dt        j                  |            S )Nr|   r}   r   r   r   r~   zINVALID JSONr%   r\   r]   zx.pyr   r   s        r   r-   zMTestGetCallersContext.test_json_parse_failure_skips_file.<locals>.side_effect   sk    09S0@		),bI-6!^s9q=)H8#!Q~FF"Y$9:D4::d3CDDr   r   r,   rU   r   Nr`   r   r   r   s        r   "test_json_parse_failure_skips_filez8TestGetCallersContext.test_json_parse_failure_skips_file   s    Y&	*	*113	E #= 	W)<*FHVF	W   !;<<<6!!!	W 	Ws   A33A<N)rK   rL   rM   rN   rS   rX   re   rg   rC   ry   r   r   rO   r   r   rQ   rQ   z   s-    A
0*	 (&0"r   rQ   )r   r   r   )rN   r0   r@   syspathlibr   unittest.mockr   r   pathinsertrV   __file__parentworktree_managerr   codex_gate_checkr   intr   r   rQ   rO   r   r   <module>r      s      
  * 3tH~,,334 5 6 13 C c 9 K Kf{" {"r   