
    Ri7                    H   d Z ddlmZ ddlZddlZddlZej                  j                  dej                  j                  ej                  j                  e
      d             ddlmZmZmZ ddlZ	 	 	 d	 	 	 	 	 	 	 ddZddZ G d d	      Z G d
 d      Z G d d      Zy)u   tests/test_cli_runner.py — CLIRunner TDD 테스트 스위트.

작성 순서: 테스트 먼저(RED), 구현 후 GREEN 확인.
    )annotationsNz..)	AsyncMock	MagicMockpatchc                l    t               }||_        t        | |f      |_        t               |_        |S )uB   asyncio.subprocess.Process를 모킹하는 객체를 반환한다.return_value)r   
returncoder   communicatekill)stdout_datastderr_datar
   procs       ^/home/jay/workspace/.worktrees/task-2117-dev1/services/multimodel-bot/tests/test_cli_runner.py_make_mock_processr      s2     ;D DO {K.HIDDIK    c                     t               } d| _        t        t        j                               | _        t               | _        | S )u]   communicate()에서 asyncio.TimeoutError를 발생시키는 목 프로세스를 반환한다.Nside_effect)r   r
   r   asyncioTimeoutErrorr   r   )r   s    r   _make_timeout_processr   $   s4    ;DDO W-A-A-CDDDIKr   c                      e Zd ZdZej
                  j                  dd       Zej
                  j                  dd       Zy)TestRunClaudeu   CLIRunner.run_claude() 검증.c                4  K   t        ddd      }t        d|      5  ddlm} |j	                  d       d	{   }d	d	d	       j
                  d
k(  sJ |j                  dk(  sJ |j                  dk(  sJ |j                  du sJ y	7 P# 1 sw Y   OxY ww)uU   Claude CLI 성공 시 stdout 텍스트를 CLIResult.stdout으로 반환해야 한다.s   Claude response textr   r   )r   r   r
   asyncio.create_subprocess_execr   	CLIRunneru   안녕하세요NzClaude response textclaudeF)	r   r   engine_v2.cli_runnerr   
run_claudestdoutr
   engine	timed_outself	mock_procr   results       r   test_run_claude_successz%TestRunClaude.test_run_claude_success5   s      '/
	 3)L 	C6$//0ABBF	C
 }} 6666  A%%%}}(((5((( C	C 	Cs,   BBB
BAB
BBBc                h  K   t               }t        d|      5  ddlm} |j	                  dd       d{   }ddd       j
                  d	u sJ |j                  d
k(  sJ |j                  dk(  sJ d|j                  v sd|j                  j                         v sJ yy7 l# 1 sw Y   kxY ww)uD   타임아웃 시 timed_out=True이고 returncode=-1이어야 한다.r   r   r   r   u   타임아웃 테스트   )timeoutNTr   Timeoutr,   )
r   r   r    r   r!   r$   r
   r#   stderrlowerr%   s       r   test_run_claude_timeoutz%TestRunClaude.test_run_claude_timeoutH   s      *+	3)L 	U6$//0HRS/TTF	U
 4'''  B&&&}}(((FMM)Y&--:M:M:O-OOO-O) U	U 	Us,   B2B&B$B&A(B2$B&&B/+B2NreturnNone)	__name__
__module____qualname____doc__pytestmarkr   r)   r1    r   r   r   r   2   sA    ([[) )$ [[P Pr   r   c                      e Zd ZdZej
                  j                  dd       Zej
                  j                  dd       Zej
                  j                  dd       Z	ej
                  j                  dd       Z
y)TestRunCodexu   CLIRunner.run_codex() 검증.c                j  K   t        dd      }t        d|      5 }ddlm} |j	                  dd	
       d{   }ddd       j
                  du sJ |j                  dk(  sJ t        j                  j                        }dj                  |      }d|v sJ d	|vsJ y7 j# 1 sw Y   ixY ww)u\   gpt-5.2-codex 요청 시 gpt-5.1-codex-mini로 치환되고 fallback_used=True여야 한다.s   codex responser   r   r   r   r   r   r   	   테스트zgpt-5.2-codexmodelNTcodex gpt-5.1-codex-minir   r   r    r   	run_codexfallback_usedr#   list	call_argsargsjoinr&   r'   	mock_execr   r(   rJ   cmd_strs          r   test_run_codex_fallbackz$TestRunCodex.test_run_codex_fallback`   s      '3DRUV	3)L 	SPY6$..{/.RRF	S
 ##t+++}}''',,112	((9%#w...g--- S	S 	Ss,   B3B'B%B'A&B3%B''B0,B3c                ^  K   t        dd      }t        d|      5 }ddlm} |j	                  dd	
       d{   }ddd       j
                  du sJ |j                  dk(  sJ t        j                  j                        }dj                  |      }d	|v sJ y7 d# 1 sw Y   cxY ww)uM   gpt-5.1-codex-mini 요청 시 치환 없이 fallback_used=False여야 한다.s   mini responser   r?   r   r   r   r   r@   rE   rA   NFrC   rD   rF   rM   s          r   test_run_codex_no_fallbackz'TestRunCodex.test_run_codex_no_fallbackr   s      '3CQTU	3)L 	XPY6$..{BV.WWF	X
 ##u,,,}}''',,112	((9%#w... X	X 	Xs,   B-B!BB!A B-B!!B*&B-c                   K   t        dd      }t        d|      5 }ddlm} |j	                  d       d	{    d	d	d	       t        j                  j                        }d
|v sJ y	7 2# 1 sw Y   1xY ww)uK   cmd에 --skip-git-repo-check 플래그가 반드시 포함되어야 한다.   okr   r?   r   r   r   r   u   플래그 확인Nz--skip-git-repo-check)r   r   r    r   rG   rI   rJ   rK   )r&   r'   rN   r   rJ   s        r   test_run_codex_skip_git_flagz)TestRunCodex.test_run_codex_skip_git_flag   sz      '5cJ	3)L 	:PY6%%&8999	:
 ,,112	&)333 :	: 	:s+   A9A-A+A-.A9+A--A62A9c                <  K   t        dd      }t        d|      5 }ddlm} |j	                  dd	
       d{   }ddd       j
                  du sJ t        j                  j                        }dj                  |      }d|v sJ y7 S# 1 sw Y   RxY ww)u\   gpt-5.1-codex 요청 시 gpt-5.1-codex-mini로 치환되고 fallback_used=True여야 한다.rT   r   r?   r   r   r   r   r@   zgpt-5.1-codexrA   NTrD   rE   )
r   r   r    r   rG   rH   rI   rJ   rK   rL   rM   s          r   test_run_codex_gpt51_fallbackz*TestRunCodex.test_run_codex_gpt51_fallback   s      '5cJ	3)L 	SPY6$..{/.RRF	S
 ##t+++,,112	((9%#w... S	S 	Ss,   BBBBABBBBNr2   )r5   r6   r7   r8   r9   r:   r   rP   rR   rU   rW   r;   r   r   r=   r=   ]   s{    '[[. ." [[/ / [[
4 
4 [[/ /r   r=   c                      e Zd ZdZej
                  j                  dd       Zej
                  j                  dd       Zy)TestExecFileNotFoundu(   _exec() FileNotFoundError 처리 검증.c                T  K   t        dt                     5  ddlm} |j	                  d       d{   }ddd       j
                  dk(  sJ |j                  dk(  sJ d	|j                  j                         v st        |j                        dkD  sJ yy7 f# 1 sw Y   exY ww)
u`   명령어가 PATH에 없을 때 returncode=-1이고 stderr에 오류 내용이 있어야 한다.r   r   r   r      명령어 없음Nr-   r   z	not found)
r   FileNotFoundErrorr    r   r!   r
   r#   r/   r0   lenr&   r   r(   s      r   test_exec_file_not_foundz-TestExecFileNotFound.test_exec_file_not_found   s      ,)+
 	D 7$//0BCCF	D   B&&&}}(((fmm1133s6==7IA7MMM7M3	 D	D 	Ds,   B(BBBA"B(BB%!B(c                   K   t        dt                     5  ddlm} |j	                  d       d{   }ddd       j
                  dk(  sJ |j                  dk(  sJ y7 /# 1 sw Y   .xY ww)	uD   codex 명령어가 PATH에 없을 때 returncode=-1이어야 한다.r   r   r   r   r[   Nr-   rC   )r   r\   r    r   rG   r
   r#   r^   s      r   test_exec_codex_file_not_foundz3TestExecFileNotFound.test_exec_codex_file_not_found   sy      ,)+
 	C 7$../ABBF	C   B&&&}}''' C	C 	Cs+   A1A%A#A%+A1#A%%A.*A1Nr2   )	r5   r6   r7   r8   r9   r:   r   r_   ra   r;   r   r   rY   rY      sA    2[[N N [[( (r   rY   )r   r   r   )r   bytesr   rb   r
   intr3   r   )r3   r   )r8   
__future__r   r   ossyspathinsertrL   dirname__file__unittest.mockr   r   r   r9   r   r   r   r=   rY   r;   r   r   <module>rl      s   
 #  	 
 277<< 94@ A 5 5  


 
 	
#P #PV?/ ?/N( (r   