
    Z1i                        d 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mZmZmZ ddlZej                   j#                  dd       ej$                  d        Zej$                  d        Zej$                  d	        Zdd
Z G d d      Z G d d      Z G d d      Z G d d      Z G d d      Zy)u   
dispatch.py 및 task-timer.py 재발 방지 로직 테스트

아르고스(테스터)가 작성한 테스트 스위트.
dispatch.py의 팀 가용성 확인, 이중 위임 방지,
task-timer.py의 check-reserved 기능을 검증.
    N)datetime	timedelta)Path)	MagicMockpatch	mock_openz/home/jay/workspacec                     | dz  }|j                  d       |dz  }|j                  d       | dz  }|j                  d       |dz  }|j                  d       | S )u-   임시 워크스페이스 디렉토리 생성memoryT)parentstasksprojectsdaily)mkdir)tmp_path
memory_dir	tasks_dirprojects_dir	daily_dirs        :/home/jay/workspace/teams/dev1/test_dispatch_safeguards.pytmp_workspacer      so     H$JT"W$IOODO!j(Lt$W$IOODO!O    c                     ddddddt        j                         j                         dii}| dz  dz  }|j                  t	        j
                  |d	d
             |S )u0   running 작업이 있는 task-timers.json 생성r   z	task-10.1	dev1-teamu   로그인 페이지 개발runningtask_idteam_iddescriptionstatus
start_timer
   task-timers.jsonF   ensure_asciiindentr   now	isoformat
write_textjsondumpsr   
timer_data
timer_files      r   timer_file_with_runningr/   +   sl     	&&;#&lln668

J ),>>J$**ZeANOr   c           	          ddddddt        j                         j                         t        j                         j                         dii}| dz  dz  }|j                  t	        j
                  |d	d
             |S )u2   completed 작업만 있는 task-timers.json 생성r   ztask-9.1r   u   이전 작업 완료	completed)r   r   r   r   r    end_timer
   r!   Fr"   r#   r&   r,   s      r   timer_file_with_completedr3   >   s~     	%&5%&lln668$LLN446	
J ),>>J$**ZeANOr   c                 f     #t        dt        j                  ddi      d      	 	 d fd	}|S )uc   dispatch() 함수를 임시 워크스페이스 환경에서 실행하도록 패치된 버전 반환r   idzcron-test-123 
returncodestdoutstderrc                    dd l }|j                  }|j                  j                         }		 |_        ddddd|_        t	        d      5  t	        d	d
      5  dz  dz  }
|
j                         r$t        j                  |
j                               }ndi i}dt        j                         j                         d|d   d
<   |
j                  t        j                  |dd             |j                  | ||||||      cd d d        cd d d        ||_        |	|_        S # 1 sw Y   nxY w	 d d d        n# 1 sw Y   nxY w||_        |	|_        y # ||_        |	|_        w xY w)Nr   ztest-anu-keyztest-dev1-keyztest-dev2-keyztest-dev3-keyanudev1dev2dev3dispatch.subprocess.runreturn_valuedispatch.generate_task_id	task-99.1r
   r!   r   reservedr   reserved_atFr"   r#   )
session_id
project_idforceverify)dispatch	WORKSPACEBOT_KEYScopyr   existsr*   loads	read_textr   r'   r(   r)   r+   )r   	task_desclevelrI   rJ   rK   rL   dispatch_moduleoriginal_workspaceoriginal_bot_keysr.   tdmock_subprocess_resultr   s               r   patched_dispatchz,make_dispatch_func.<locals>.patched_dispatch[   s~   *,66+4499; 	9(5O%%'''	(O$ 0?UV 6[Q !.!9<N!NJ!((*!ZZ
(<(<(>?%r]",'/||~'?'?'A0BwK, ))$**ReTU*VW*33E#-#-#% 4   , );O%'8O$-    , );O%'8O$ );O%'8O$sB    E D<B*D&	D<	E &D/	+D<3	E <EE E')normalNNFF)r   r*   r+   )r   rZ   r[   s   `` r   make_dispatch_funcr]   R   sC    %!*::t_56"
 IM>C'9R r   c                   (    e Zd ZdZd Zd Zd Zd Zy)TestTeamAvailabilityu+   dispatch.py: 팀 가용성 확인 테스트c                    ddl }|j                  }	 ||_        t        |j                   d      r|j                   j                  dd      nd}|@|j                  j                         }ddddd|_        	 |j                  dd      }||_        ||_        |d   d	k(  s
J d
|        d|d   v sJ d|d           y# ||_        w xY w# ||_        w xY w)uW   1a: team_id에 running 작업이 있을 때 에러 반환 (message에 '--force' 포함)r   N__wrapped__r   u   새 작업 설명test-keyr<   r   erroru.   running 작업이 있을 때 error여야 함: z--forcemessageu*   message에 '--force'가 포함돼야 함: )rM   rN   hasattrra   rO   rP   )selfr   r/   rV   rW   resultrX   s          r   $test_1a_running_task_blocks_dispatchz9TestTeamAvailability.test_1a_running_task_blocks_dispatch   s   *,66	;(5O% 11=A %--990GK  ~$3$<$<$A$A$C!%z&
,(A,55kCVWF/@O,(:O%h7*e.\]c\d,ee*F9--o1[\bcl\m[n/oo- 0AO,(:O%s$   A#C	 6B= C	 =	CC	 		Cc           	         ddl }t        dt        j                  ddi      d      }|j                  }|j
                  j                         }	 ||_        ddddd|_        t        d	|
      5  t        dd
      5  t        j                  |j                               }dt        j                         j                         d|d   d<   |j                  t        j                  |dd             |j                  ddd      }ddd       ddd       ||_        ||_        d   dk(  s
J d|        y# 1 sw Y   2xY w# 1 sw Y   6xY w# ||_        ||_        w xY w)uK   1b: running 작업이 있고 force=True → 정상 진행 (mock subprocess)r   Nr5   zcron-abc-123r6   r7   rb   r<   rA   rB   rD   rE   rF   rG   r   Fr"   r#   r   u   강제 위임 작업TrK   r   
dispatchedu'   force=True이면 dispatched여야 함: rM   r   r*   r+   rN   rO   rP   r   rR   rS   r   r'   r(   r)   )	rf   r   r/   rV   mock_resultrW   rX   rY   rg   s	            r   (test_1b_running_task_with_force_proceedsz=TestTeamAvailability.test_1b_running_task_with_force_proceeds   sq   *::t^45
 -66+4499;	9(5O%!:"J(O$ 0{K 6[Q $;$E$E$GHB",'/||~'?'?'A0BwK, ,66

2E!D -55#%;4 6 F );O%'8O$h</ 	?5fX>	?/#   );O%'8O$s=    E /E=B
D8EE 8E	=EE	E E c           	         ddl }t        dt        j                  ddi      d      }|j                  }|j
                  j                         }	 ||_        ddddd|_        t        d	|
      5  t        dd
      5  t        j                  |j                               }dt        j                         j                         d|d   d<   |j                  t        j                  |dd             |j                  dd      }ddd       ddd       ||_        ||_        d   dk(  s
J d|        y# 1 sw Y   2xY w# 1 sw Y   6xY w# ||_        ||_        w xY w)u;   1c: team_id에 completed 작업만 있을 때 정상 진행r   Nr5   zcron-xyz-456r6   r7   rb   r<   rA   rB   rD   rE   rF   rG   r   Fr"   r#   r   u$   새 작업 (이전 completed 상태)r   rk   u5   completed 작업만 있을 때 dispatched여야 함: rl   )	rf   r   r3   rV   rm   rW   rX   rY   rg   s	            r   &test_1c_completed_task_allows_dispatchz;TestTeamAvailability.test_1c_completed_task_allows_dispatch   sl   *::t^45
 -66+4499;	9(5O%!:"J(O$ 0{K 6[Q $=$G$G$IJB",'/||~'?'?'A0BwK, .88

2E!D -55#%KF );O%'8O$h</ 	MCF8L	M/!   );O%'8O$s=    E /E=BD6EE 6D?	;EEE Ec           	         ddl }|dz  dz  }|j                         rJ d       t        dt        j                  ddi      d	      }|j
                  }|j                  j                         }	 ||_        d
d
d
d
d|_        t        d|      5  t        dd      5  dddt        j                         j                         dii}|j                  t        j                  |dd             |j                  dd      }ddd       ddd       ||_        ||_        d   dk(  s
J d|        y# 1 sw Y   2xY w# 1 sw Y   6xY w# ||_        ||_        w xY w)u0   1d: task-timers.json이 없을 때 정상 진행r   Nr
   r!   u   timer 파일이 없어야 함r5   zcron-new-789r6   r7   rb   r<   rA   rB   rD   rE   r   rF   rG   Fr"   r#   r   u+   timer 파일 없는 상태에서 첫 위임r   rk   u1   timer 파일 없을 때도 dispatched여야 함: )rM   rQ   r   r*   r+   rN   rO   rP   r   r   r'   r(   r)   )	rf   r   rV   r.   rm   rW   rX   rY   rg   s	            r   %test_1d_no_timer_file_allows_dispatchz:TestTeamAvailability.test_1d_no_timer_file_allows_dispatch   s   * #X-0BB
$$&G(GG&::t^45
 -66+4499;	9(5O%!:"J(O$ 0{K 
6[Q 	!K",'/||~'?'?'A2 $ B ))$**ReTU*VW,55#%RF	
 );O%'8O$h</ 	I?xH	I/	 	
 
 );O%'8O$s=   . E D<A#D0?D<E 0D9	5D<<EE EN)__name__
__module____qualname____doc__rh   rn   rp   rr    r   r   r_   r_      s    5p8%?N$ML&Ir   r_   c                   p    e Zd ZdZej
                  d        Zej
                  d        Zd Zd Z	d Z
d Zy)	TestDoubleDispatchPreventionu+   dispatch.py: 이중 위임 방지 테스트c                     d}dddd|dd dt        j                         j                         dii}|d	z  d
z  }|j                  t	        j
                  |dd             ||fS )u  running 상태에 특정 description이 있는 timer 파일 생성.

        description 중복 검사(2단계)를 테스트하기 위해:
        - 팀 가용성 검사(1단계): team_id가 'dev1-team'인 running 작업만 차단
        - 중복 description 검사(2단계): 다른 팀(dev2-team) running 작업의 description과 같은지 비교
        따라서 fixture는 dev1-team과 다른 팀(dev2-team)에 running 작업을 두고,
        dev1-team으로 dispatch 시 description 중복만 걸리도록 설정.
        실제로는 같은 팀 running 작업이 아닌 reserved 상태로 description 중복 테스트가 명확함.
        u\   동일 작업 - 이미 예약된 로그인 페이지 개발 프로젝트입니다 (reserved)r   z	task-11.1r   N<   rF   r   r   r   r   rH   r
   r!   Fr"   r#   r&   rf   r   descr-   r.   s        r   timer_with_running_descz4TestDoubleDispatchPrevention.timer_with_running_desc'  s~     n**#'9(#+<<>#;#;#=	

 #X-0BB
djj%PQRS4r   c                     d}dddd|dd dt        j                         j                         dii}|d	z  d
z  }|j                  t	        j
                  |dd             ||fS )uC   reserved 상태에 특정 description이 있는 timer 파일 생성uN   동일 작업 - 이미 예약된 API 서버 구축 작업입니다 (예약됨)r   z	task-12.1r   Nr{   rF   r|   r
   r!   Fr"   r#   r&   r}   s        r   timer_with_reserved_descz5TestDoubleDispatchPrevention.timer_with_reserved_descC  s~     `**#'9(#+<<>#;#;#=


 #X-0BB
djj%PQRS4r   c                 <   ddl }|\  }}|j                  }|j                  j                         }	 ||_        ddddd|_        |j                  d|      }||_        ||_        |d   dk(  s
J d|        d	|d
   v sJ d|d
           y# ||_        ||_        w xY w)u  2a: 같은 description(첫 60자)이 running/reserved에 있을 때 에러 반환.

        dispatch 코드 로직:
        1단계 - 팀 가용성 확인: team_id 일치 + status=running 인 작업이 있으면 차단
        2단계 - 이중 위임 방지: status=running/reserved 이고 description[:60] 동일하면 차단

        reserved 상태 작업으로 테스트하여 1단계를 우회하고 2단계(description 중복)만 검사.
        r   Nrb   r<   r   r   rc   u*   중복 description이면 error여야 함: "   이미 진행 중인 동일 작업rd   .   message에 중복 안내가 포함돼야 함: rM   rN   rO   rP   )	rf   r   r   rV   r.   r~   rW   rX   rg   s	            r   -test_2a_duplicate_description_blocks_dispatchzJTestDoubleDispatchPrevention.test_2a_duplicate_description_blocks_dispatchV  s     	+2
D,66+4499;
	9(5O%!:"J(O$
 %--k4@F(:O%'8O$h7* 	B8A	B*3vi7HH 	Q<VI=N<OP	QH );O%'8O$s   %B Bc                    ddl }|\  }}|j                  }|j                  j                         }	 ||_        ddddd|_        |j                  d|      }||_        ||_        |d   dk(  s
J d|        y# ||_        ||_        w xY w)	uI   2a-reserved: reserved 상태에도 동일 description이면 에러 반환r   Nrb   r<   r   r   rc   u:   reserved 상태 중복 description이면 error여야 함: r   )	rf   r   r   rV   r.   r~   rW   rX   rg   s	            r   -test_2a_reserved_duplicate_description_blockszJTestDoubleDispatchPrevention.test_2a_reserved_duplicate_description_blocksv  s    *3
D,66+4499;		9(5O%!:"J(O$ %--k4@F(:O%'8O$h7* 	RHQ	R* );O%'8O$s   %A7 7Bc                    ddl }d}d||dddt        j                         j                         dii}|d	z  d
z  }|j	                  t        j                  |dd             |j                  }|j                  j                         }	 ||_        ddddd|_        d}|j                  d|      }	||_        ||_        |	d   dk(  s
J d|	        d|	d   v sJ d|	d           y# ||_        ||_        w xY w)u  2b: 프롬프트에 기존 task_id가 포함될 때 에러 반환.

        dispatch 코드 로직:
        1단계 - 팀 가용성 확인: team_id 일치 + running 작업 차단
        2단계 - 이중 위임 방지: 프롬프트에 기존 task_id(running/reserved) 문자열 포함 시 차단

        다른 팀(dev1-team)에 running 작업을 두고, dev2-team으로 dispatch하면서
        프롬프트에 task_id 포함 → 1단계 우회, 2b 검사에서 차단.
        r   Nz	task-13.1r   r   u   기존 작업r   r   r
   r!   Fr"   r#   rb   r<   u4   task-13.1에 대한 후속 작업을 진행하세요	dev2-teamr   rc   u+   task_id 참조 포함 시 error여야 함: r   rd   r   )
rM   r   r'   r(   r)   r*   r+   rN   rO   rP   )
rf   r   rV   existing_task_idr-   r.   rW   rX   task_desc_with_idrg   s
             r   )test_2b_task_id_in_prompt_blocks_dispatchzFTestDoubleDispatchPrevention.test_2b_task_id_in_prompt_blocks_dispatch  sF    	+ ' /*#2'"*,,.":":"<#


 #X-0BB
djj%PQRS,66+4499;	9(5O%!:"J(O$
 #W$--k;LMF(:O%'8O$h7* 	C9&B	C*3vi7HH 	Q<VI=N<OP	QH );O%'8O$s   	'C% %C5c           	         ddl }|\  }}t        dt        j                  ddi      d      }|j                  }|j
                  j                         }	 ||_        ddddd|_        t        d	|
      5  t        dd
      5  t        j                  |j                               }	dt        j                         j                         d|	d   d<   |j                  t        j                  |	dd             |j                  d|d      }
ddd       ddd       ||_        ||_        
d   dk(  s
J d|
        y# 1 sw Y   2xY w# 1 sw Y   6xY w# ||_        ||_        w xY w)u7   2c: force=True로 중복 작업도 강제 진행 가능r   Nr5   zcron-force-001r6   r7   rb   r<   rA   rB   rD   rE   rF   rG   r   Fr"   r#   r   Trj   r   rk   u2   force=True 중복 작업도 dispatched여야 함: rl   )rf   r   r   rV   r.   r~   rm   rW   rX   rY   rg   s              r   &test_2c_force_bypasses_duplicate_checkzCTestDoubleDispatchPrevention.test_2c_force_bypasses_duplicate_check  sx   *2
D::t%567
 -66+4499;	9(5O%!:"J(O$ 0{K 
6[Q 	J$8$8$:;B",'/||~'?'?'A0BwK, ))$**ReTU*VW,55#T 6 F	
 );O%'8O$h</ 	J@I	J/	 	
 
 );O%'8O$s=    E 4E	B
D=E	E =E	E		EE E%N)rs   rt   ru   rv   pytestfixturer   r   r   r   r   r   rw   r   r   ry   ry   $  sM    5^^   6 ^^   $Q@R,.Q`$Jr   ry   c                   .    e Zd ZdZd Zd Zd Zd Zd Zy)TestCheckReservedu.   task-timer.py: check-reserved 기능 테스트c                 h   ddl }|j                  j                  dd      }|x}|j                  _        |j                  j	                  |      }|j
                  j                  |       |dz  dz  }|j                  t        j                  |dd	             |j                  t        |      
      S )uR   임시 워크스페이스에 timer 파일 생성 후 TaskTimer 인스턴스 반환r   N
task_timer(/home/jay/workspace/memory/task-timer.pyr
   r!   Fr"   r#   workspace_path)importlib.utilutilspec_from_file_locationload_from_specmodule_from_specloaderexec_moduler)   r*   r+   	TaskTimerstr)rf   r   r-   	importlibspectask_timer_modulemodr.   s           r   _make_timerzTestCheckReserved._make_timer  s     	~~556
 =A@INN9nn--d3$"X-0BB
djj%PQRS}}C,>}??r   c                 <   t        j                         t        d      z
  j                         }dddddd|dii}| j	                  ||      }|j                  d	
      }|d   dk(  s
J d|        t        |d         dkD  s
J d|        |d   d   d   dk(  sJ y)u^   3a: reserved 상태가 timeout 이상 지속된 작업 감지 → warning + stale_tasks 반환   hoursr   z	task-20.1r   u   오래된 예약 작업rF   r|   ,  timeout_secondsr   warningu9   stale reserved 작업이 있으면 warning이어야 함: stale_tasksr   u(   stale_tasks에 항목이 있어야 함: r   N)r   r'   r   r(   r   check_reservedlen)rf   r   old_timer-   timerrg   s         r   test_3a_stale_reserved_detectedz1TestCheckReserved.test_3a_stale_reserved_detected  s     LLNYQ%77BBD**#<(#+


   
;%%c%:h9, 	QGxP	Q,6-()A- 	@6vh?	@-m$Q'	2kAAAr   c                     t        j                         j                         }dddddd|dii}| j                  ||      }|j	                  d      }|d	   d
k(  s
J d|        |d   g k(  s
J d|        y)u=   3b: 모든 작업이 timeout 미만일 때 ok, stale_tasks=[]r   z	task-21.1r   u   방금 예약된 작업rF   r|   r   r   r   oku.   신선한 reserved 작업이면 ok여야 함: r   u(   stale_tasks가 빈 배열이어야 함: N)r   r'   r(   r   r   )rf   r   
fresh_timer-   r   rg   s         r   test_3b_fresh_reserved_okz+TestCheckReserved.test_3b_fresh_reserved_ok  s     \\^--/
**#<(#-


   
; %%c%:h4' 	F<VHE	F'm$* 	@6vh?	@*r   c                     dddddddii}| j                  ||      }|j                  d      }d	|v sJ d
       |d   g k(  s
J d|        y)uB   3c: reserved_at 필드가 없는 작업 → 무시 (에러 없음)r   z	task-22.1z	dev3-teamu    reserved_at 없는 예약 작업rF   )r   r   r   r   r   r   r   u(   결과에 status 필드가 있어야 함r   u>   reserved_at 없으면 stale_tasks가 빈 배열이어야 함: N)r   r   )rf   r   r-   r   rg   s        r   ,test_3c_reserved_without_reserved_at_ignoredz>TestCheckReserved.test_3c_reserved_without_reserved_at_ignored-  s     **#E(	


   
; %%a%86!M#MM!m$* 	VLVHU	V*r   c                 D   t        j                         t        d      z
  j                         }dddddd|dii}|d	z  d
z  }|j	                  t        j                  |dd             t        j                  j                         }t        |      |d<   t        j                  g ddd|      }|j                  dk(  sJ d|j                          t        j                  |j                         }|d   dk(  s
J d|        t#        |d         dkD  s
J d|        y)uJ   3d: CLI 실행 테스트: python3 task-timer.py check-reserved --timeout 0
   )secondsr   z	task-23.1r   u   CLI 테스트용 예약 작업rF   r|   r
   r!   Fr"   r#   WORKSPACE_ROOT)python3r   zcheck-reservedz	--timeout0T)capture_outputtextenvr   u6   CLI 실행이 성공해야 함 (returncode=0): stderr=r   r   u5   timeout=0이면 reserved 작업이 감지돼야 함: r   u(   stale_tasks에 작업이 있어야 함: N)r   r'   r   r(   r)   r*   r+   osenvironrP   r   
subprocessrunr8   r:   rR   r9   r   )rf   r   r   r-   r.   r   procoutputs           r   'test_3d_cli_check_reserved_timeout_zeroz9TestCheckReserved.test_3d_cli_check_reserved_timeout_zeroC  s@    LLNYr%::EEG**#C(#+


 #X-0BB
djj%PQRSjjoo #M 2~~1d
 !# 	SDT[[MR	S# DKK(h9, 	MCF8L	M,6-()A- 	@6vh?	@-r   N)	rs   rt   ru   rv   r   r   r   r   r   rw   r   r   r   r     s#    8@"B2@2V,"@r   r   c                   \    e Zd ZdZej
                  d        Z	 d
dZd Zd Z	d Z
d Zd	 Zy)TestDispatchResultFieldsu2   dispatch.py: 결과 필드 포함 여부 테스트c                 l    di i}|dz  dz  }|j                  t        j                  |dd             |S )u   빈 timer 파일 생성r   r
   r!   Fr"   r#   )r)   r*   r+   )rf   r   r-   r.   s       r   clean_timer_filez)TestDispatchResultFields.clean_timer_fileo  s?     r]
"X-0BB
djj%PQRSr   Nc           	         ddl }|ddi}t        dt        j                  |      d      }|j                  }|j
                  j                         }		 ||_        ddddd|_        t        d	|
      5  t        dd
      5  t        j                  |j                               }
dt        j                         j                         d|
d   d<   |j                  t        j                  |
dd             |j                  d||      cddd       cddd       ||_        |	|_        S # 1 sw Y   nxY w	 ddd       n# 1 sw Y   nxY w||_        |	|_        y# ||_        |	|_        w xY w)u"   mock subprocess로 dispatch 실행r   Nr5   zcron-field-test-001r6   r7   rb   r<   rA   rB   rD   rE   rF   rG   r   Fr"   r#   r   rL   rl   )rf   r   r.   rT   rL   cron_responserV   rm   rW   rX   rY   s              r   _dispatch_with_mockz,TestDispatchResultFields._dispatch_with_mockw  sz    	+ !#89M::m,
 -66+4499;	9(5O%!:"J(O$ 0{K 
6[Q 	J$8$8$:;B",'/||~'?'?'A0BwK, ))$**ReTU*VW*33#Yv 4 	 	
 
 );O%'8O$	 	 	
 
 
 );O%'8O$ );O%'8O$sC    E 3EB	D+
	E	E +D4	0E8	E E
E E,c                     | j                  ||dddi      }|d   dk(  s
J d|        d|v s
J d	|        |d   dk(  s
J d
|        y)uB   dispatch 성공 결과에 cron_id 필드가 포함되는지 확인u   cron_id 테스트 작업r5   z
cron-12345r   r   rk      dispatched여야 함: cron_idu!   cron_id 필드가 있어야 함: u#   cron_id가 'cron-12345'여야 함: Nr   rf   r   r   rg   s       r   test_4a_cron_id_in_resultz2TestDispatchResultFields.test_4a_cron_id_in_result  s    ))+&. * 
 h</R3I&1RR/F"P&Gx$PP"i L0 	;1&:	;0r   c                     | j                  ||d      }|d   dk(  s
J d|        d|v s
J d|        |d   }t        |      dk(  s
J d|        y	)
uM   dispatch 성공 결과에 expected_execution 필드가 포함되는지 확인u#   expected_execution 테스트 작업r   rk   r   expected_executionu,   expected_execution 필드가 있어야 함:    u2   expected_execution 포맷이 올바르지 않음: Nr   r   )rf   r   r   rg   	exec_times        r   $test_4b_expected_execution_in_resultz=TestDispatchResultFields.test_4b_expected_execution_in_result  s    ))+1

 h</R3I&1RR/#v- 	D:6(C	D- /0	9~# 	M@L	M#r   c                     | j                  ||dd      }|d   dk(  s
J d|        d|v s
J d|        t        |d         d	kD  s
J d
|        y)u?   verify=True일 때 verify_note 필드가 포함되는지 확인u   verify 테스트 작업Tr   r   rk   r   verify_noteu8   verify=True일 때 verify_note 필드가 있어야 함: r   u(   verify_note가 비어있으면 안 됨: Nr   r   s       r   (test_4c_verify_true_includes_verify_notezATestDispatchResultFields.test_4c_verify_true_includes_verify_note  s    ))+% * 
 h</R3I&1RR/& 	PFvhO	P&6-()A- 	@6vh?	@-r   c                 n    | j                  ||dd      }|d   dk(  s
J d|        d|vs
J d|        y	)
uE   verify=False(기본값)일 때 verify_note 필드가 없는지 확인u   verify False 테스트 작업Fr   r   rk   r   r   u2   verify=False일 때 verify_note가 없어야 함: Nr   r   s       r   #test_4d_verify_false_no_verify_notez<TestDispatchResultFields.test_4d_verify_false_no_verify_note  sf    ))++ * 
 h</R3I&1RR/F* 	J@I	J*r   c                     | j                  ||dddi      }|d   dk(  s
J d|        d|v s
J d|        |d   
J d
|        y	)uG   cokacdir 응답에 id 필드가 없을 때 cron_id가 None인지 확인u   id 없는 응답 테스트r   r   r   rk   r   r   u!   cron_id 필드는 있어야 함: Nu5   id 없는 응답이면 cron_id가 None이어야 함: r   r   s       r   +test_4e_cron_id_none_when_no_id_in_responsezDTestDispatchResultFields.test_4e_cron_id_none_when_no_id_in_response  s    ))+(#T* * 
 h</R3I&1RR/F"P&Gx$PP"i ( 	MCF8L	M(r   )FN)rs   rt   ru   rv   r   r   r   r   r   r   r   r   r   rw   r   r   r   r   l  sC    <^^  :>#9J;M@
JMr   r   c                   .    e Zd ZdZd Zd Zd Zd Zd Zy)TestTaskTimerImportu9   task-timer.py TaskTimer 클래스 직접 import 테스트c                     ddl }|j                  j                  dd      }|j                  j                  |      }|j                  j                  |       |S )u   task-timer.py 모듈 로드r   Nr   r   )r   r   r   r   r   r   )rf   r   r   r   s       r   _load_task_timer_modulez+TestTaskTimerImport._load_task_timer_module  sL    ~~556
 nn--d3$
r   c                    | j                         }t        j                         t        d      z
  j	                         }ddd|dii}|dz  dz  }|j                  t        j                  |d	d
             |j                  t        |            }|j                  d      }|d   dk(  sJ |d   }t        |      dk(  sJ |d   d   dk(  sJ |d   d   dk\  sJ y)u:   TaskTimer.check_reserved: 오래된 reserved 작업 감지r   )minutesr   z	task-30.1rF   rG   r
   r!   Fr"   r#   r   r{   r   r   r   r   r   r   r   age_secondsNr   r   r'   r   r(   r)   r*   r+   r   r   r   r   )	rf   r   r   r   r-   r.   r   rg   stales	            r   $test_task_timer_check_reserved_stalez8TestTaskTimerImport.test_task_timer_check_reserved_stale  s    **,LLNYr%::EEG(#+

 #X-0BB
djj%PQRSS-?@%%b%9h9,,,}%5zQQx	"k111Qx&",,,r   c                 Z   | j                         }t        j                         j                         }ddd|dii}|dz  dz  }|j	                  t        j                  |dd	             |j                  t        |      
      }|j                  d      }|d   dk(  sJ |d   g k(  sJ y)u<   TaskTimer.check_reserved: 신선한 reserved 작업이면 okr   z	task-31.1rF   rG   r
   r!   Fr"   r#   r   r   r   r   r   r   N)
r   r   r'   r(   r)   r*   r+   r   r   r   )rf   r   r   r   r-   r.   r   rg   s           r   !test_task_timer_check_reserved_okz5TestTaskTimerImport.test_task_timer_check_reserved_ok  s    **,\\^--/
(#-

 #X-0BB
djj%PQRSS-?@%%c%:h4'''m$***r   c                    | j                         }ddddiii}|dz  dz  }|j                  t        j                  |dd	             |j	                  t        |      
      }|j                  d      }|d   dk(  sJ |d   g k(  sJ y)u:   TaskTimer.check_reserved: reserved_at 없는 작업 무시r   z	task-32.1r   rF   r
   r!   Fr"   r#   r   r   r   r   r   N)r   r)   r*   r+   r   r   r   )rf   r   r   r-   r.   r   rg   s          r   -test_task_timer_check_reserved_no_reserved_atzATestTaskTimerImport.test_task_timer_check_reserved_no_reserved_at!  s    **, j

 #X-0BB
djj%PQRSS-?@%%a%8h4'''m$***r   c                    | j                         }t        j                         t        d      z
  j	                         }t        j                         j	                         }dd|dd|dd|ddi}|d	z  d
z  }|j                  t        j                  |dd             |j                  t        |            }|j                  d      }|d   dk(  sJ t        |d         dk(  sJ |d   d   d   dk(  sJ y)uI   TaskTimer.check_reserved: stale와 fresh가 섞인 경우 stale만 반환r"   r   r   rF   rG   r   )r   r    )	task-33.1z	task-33.2z	task-33.3r
   r!   Fr#   r   r   r   r   r   r   r   r   r   r   Nr   )	rf   r   r   r   r   r-   r.   r   rg   s	            r   $test_task_timer_check_reserved_mixedz8TestTaskTimerImport.test_task_timer_check_reserved_mixed7  s   **,LLNYQ%77BBD\\^--/
(#+
 )#-
 ("*

  #X-0BB
djj%PQRSS-?@%%c%:h9,,,6-()Q...m$Q'	2kAAAr   N)	rs   rt   ru   rv   r   r   r   r   r   rw   r   r   r   r     s    C	-2+,+,Br   r   )N)rv   r*   r   r   systempfiler   r   r   pathlibr   unittest.mockr   r   r   r   pathinsertr   r   r/   r3   r]   r_   ry   r   r   r   rw   r   r   <module>r      s     	  
   (  5 5  ( ) 
 
  $  &2rRI RIr|J |JF~@ ~@JqM qMpqB qBr   