
    ?i2(                     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
mZ ddlZ ee      j                  j                  Ze	j                   j#                  d ee             edz  dz  Ze	j                   j#                  d ee             ddlZedz  dz  Zedz  dz  Zd	 Zd
 Zd Zd Zd Zd Zy)u  
test_task_2352_cancel.py

카마소츠 (개발7팀 테스터) 작성 — task-2352 취소 신호 강제 처리 자동 검증

테스트 케이스:
1. test_cancel_task_invalid_id_returns_error
2. test_cancel_task_creates_cancelled_marker
3. test_cancel_task_idempotent_stop_marker
4. test_finish_task_blocks_on_cancelled_marker
5. test_finish_task_detects_top_stop_marker
6. test_qc_verify_handle_gate_skips_on_cancelled
    N)Pathteamssharedmemorytaskseventsc                  f   t        j                  d      } | d   }d}||k(  }|st        j                  d|fd||f      t        j                  |      t        j                  |      dz  }t        j
                  d| d          dz   d	|iz  }t        t        j                  |            d
x}x}}y
)uG   task_id 형식이 틀린 경우 status=="error"를 반환해야 한다.z	not-validstatuserror==z%(py1)s == %(py4)spy1py4u   예상 'error', 실제: 
>assert %(py6)spy6N)dispatchcancel_task
@pytest_ar_call_reprcompare	_saferepr_format_assertmsgAssertionError_format_explanation)result@py_assert0@py_assert3@py_assert2@py_format5@py_format7s         2/home/jay/workspace/tests/test_task_2352_cancel.py)test_cancel_task_invalid_id_returns_errorr#   (   s}    !!+.F(UwUw&UUUwUUUUUUwUUU*B6(CSBT(UUUUUUUU    c                  6   d} t         |  dz  }t        |  dz  }|j                  d       |j                  d       t         j                  dd       |j	                  dd	       	 t        j                  |       }|j                  } |       }|st        j                  d
|       dz   dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      dz  }t        t        j                  |            dx}}|j!                  d	      }d}|j#                         d   }||v }	|	st        j$                  d|	fd||f      t        j                  |      t        j                  |      dz  }t        j                  d|j#                         d         dz   d|iz  }
t        t        j                  |
            dx}x}	}|d   }d}||k(  }	|	st        j$                  d|	fd||f      t        j                  |      t        j                  |      dz  }t        j                  d|d          dz   d|iz  }
t        t        j                  |
            dx}x}	}d}|d   }||v }	|	st        j$                  d|	fd||f      t        j                  |      t        j                  |      dz  }t        j                  d      dz   d|iz  }
t        t        j                  |
            dx}x}	}d}|d   }||v }	|	st        j$                  d|	fd||f      t        j                  |      t        j                  |      dz  }t        j                  d       dz   d|iz  }
t        t        j                  |
            dx}x}	}|j                  d       |j                  d       y# |j                  d       |j                  d       w xY w)!u_   cancel_task 호출 시 .cancelled 이벤트 파일과 task md CANCELLED 마커가 생성된다.z
task-99950.md
.cancelledT
missing_okparentsexist_okz# Test
utf-8encodingu   .cancelled 파일이 없음: C
>assert %(py4)s
{%(py4)s = %(py2)s
{%(py2)s = %(py0)s.exists
}()
}cancelled_filepy0py2r   N	CANCELLEDr   in)z%(py1)s in %(py4)sr   u.   task md 첫 줄에 CANCELLED 없음. 첫 줄: r   r   r
   okr   r   u   예상 'ok', 실제: stop_marker_addedactionsu#   actions에 stop_marker_added 없음cancelled_eventu!   actions에 cancelled_event 없음)
_TASKS_DIR_EVENTS_DIRunlinkmkdir
write_textr   r   existsr   r   @py_builtinslocals_should_repr_global_namer   r   r   	read_text
splitlinesr   )task_id	task_filer1   r   @py_assert1r   r    contentr   r   r!   s              r"   )test_cancel_task_creates_cancelled_markerrK   2   s4   Gy_,I gYj#99N %T* TD1g6/%%g. $$X$&X&XX*GGW(XXXXXXX~XXX~XXX$XXX&XXXXXX %%w%7 	
g00215 	
{55 	
 	
{5 	
 	
 		  	
 	
 		 6 	
 	
  =W=O=O=QRS=T<WX	
 	
 	
 	
 	

 hS4S4'SSS4SSSSSS4SSS+@AQ@R)SSSSSSSS #^fY&7^"&77^^^"&7^^^"^^^&7^^^9^^^^^^^^ ZF9$5Z $55ZZZ $5ZZZ ZZZ$5ZZZ7ZZZZZZZZ 	D). 	D).s   *M#O2 2&Pc                     d} t         |  dz  }t        |  dz  }|j                  d       |j                  d       d}t         j                  dd       |j	                  | dd	
       	 t        j                  |        |j                  d	
      }|j                         dd }t        d |D              }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}}|j                  d       |j                  d       y# |j                  d       |j                  d       w xY w)ur   task md에 이미 STOP 마커가 있는 경우, cancel_task 재호출 시 마커가 중복 삽입되지 않는다.z
task-99951r&   r'   Tr(   u0   ★★★ 작업 취소됨 (CANCELLED) ★★★r*   z	

# Test
r-   r.   N   c              3   *   K   | ]  }d |v sd  yw)r5      N ).0lines     r"   	<genexpr>z:test_cancel_task_idempotent_stop_marker.<locals>.<genexpr>q   s     ID[D5HaIs   	rO   )<=)z%(py0)s <= %(py3)scancelled_count)r3   py3u"   CANCELLED 마커가 head-3 내에 u!   번 등장 (중복 삽입 발생)z
>assert %(py5)spy5)r<   r=   r>   r?   r@   r   r   rE   rF   sumr   r   rB   rC   rD   r   r   r   r   )rG   rH   r1   stop_markerrJ   head3rU   r   rI   @py_format4@py_format6s              r"   'test_cancel_task_idempotent_stop_markerr]   \   s   Gy_,I gYj#99N %T* EKTD1K=5H/W% %%w%7""$Ra(IEII"# 	
!# 	
 	
! 	
 	
	6	
 	
   	
 	
 		  	
 	
 		 #$ 	
 	
  10AAbc	
 	
 	
 	
 	

 	D). 	D).s   /DF   &Gc                  	   d} t         |  dz  }t        |  dz  }t        |  dz  }|j                  d       |j                  d       |j                  d       t         j                  dd       t        j                  dd       |j	                  dd	
       | ddd}|j	                  t        j                  |      d	
       	 t        j                  dt        t        dz  dz        | 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}}|j,                  |j&                  z   }g }d}||v }|}|sd}||v }|}|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/                  |
       |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        j0                  |d'      i z  }t        j$                  d(|j,                   d)|j&                         d*z   d+|iz  }t)        t        j*                  |            dx}x}x}x}x}}|j2                  } |       }| }|st        j$                  d,|       d-z   d.t        j                         v st        j                   |      rt        j"                  |      nd.t        j"                  |      t        j"                  |      d/z  }	t)        t        j*                  |	            dx}x}}|j                  d       |j                  d       |j                  d       y# |j                  d       |j                  d       |j                  d       w xY w)0u`   finish-task.sh 실행 시 .cancelled 마커가 있으면 .done 파일이 생성되지 않는다.z
task-99952r&   r'   .doneTr(   r*   z# Test task-99952
r-   r.   2026-05-02T00:00:00testrG   cancelled_atreasonbashscriptsfinish-task.shcapture_outputtextr   r   z2%(py2)s
{%(py2)s = %(py0)s.returncode
} == %(py5)sr   r3   r4   rW   /   finish-task.sh가 비정상 종료 (returncode=
)
stderr: 
>assert %(py7)spy7Nz[CANCELLED]u   .cancelled 마커 발견r6   )z%(py3)s in %(py5)scombined)rV   rW   z%(py7)s)z%(py10)s in %(py12)s)py10py12z%(py14)spy14rO   u1   CANCELLED 메시지가 출력에 없음.
stdout: z	
stderr: z
>assert %(py17)spy171   .done 파일이 생성되었음 (차단 실패): G
>assert not %(py4)s
{%(py4)s = %(py2)s
{%(py2)s = %(py0)s.exists
}()
}	done_filer2   )r<   r=   r>   r?   r@   jsondumps
subprocessrunstr
_WORKSPACE
returncoder   r   rB   rC   rD   r   r   stderrr   r   stdoutappend_format_booloprA   )rG   rH   r1   rx   cancelled_datar   rI   @py_assert4r   r\   @py_format8rq   r   r   @py_assert9@py_assert11@py_format13@py_format15@py_format16@py_format18@py_assert5s                        r"   +test_finish_task_blocks_on_cancelled_markerr      si   Gy_,I gYj#99N	//I %T*% TD1dT2.A "):O[abNdjj87K*Si/2BBCWM
    	
A 	
 A% 	
 	
 A 	
 	
 
6	
 	
   	
 	
 
	  	
 	
 
	 ! 	
 	
 
	 %& 	
 	
  >f>O>O=P Q}}o'	
 	
 	
 	
 	
 ==6==0	
} 	
}( 	
,F 	
,F(,R 	
 	
 	
} 	
 	
 		  	
 	
	6	
 	
  !) 	
 	
 		 !) 	
 	
 	
	6	
		
 	
,F( 	
 	
 		 -G 	
 	
	6	
 	
  KS 	
 	
 		 KS 	
 	
 	
	6	
		
 	
 	
  AzZ`ZgZgYhi	
 	
 	
 	
 	
 	

 ##f#%f%%f%ff)Z[dZe'fffffff9fff9fff#fff%ffffff 	D).D) 	D).D)s   N.R0 08S(c                  t   d} t         |  dz  }t        |  dz  }t        |  dz  }|j                  d       |j                  d       |j                  d       t         j                  dd       t        j                  dd       |j	                  dd	
       	 t        j                  dt        t        dz  dz        | 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}}|j(                  } |       }|st        j                   d|       dz   dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      dz  }
t%        t        j&                  |
            dx}}|j(                  } |       }| }|st        j                   d|       dz   dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      dz  }t%        t        j&                  |            dx}x}}|j                  d       |j                  d       |j                  d       y# |j                  d       |j                  d       |j                  d       w xY w) uv   task md 첫 줄에 STOP 마커가 있으면 finish-task.sh가 .cancelled를 생성하고 .done은 만들지 않는다.z
task-99953r&   r'   r_   Tr(   r*   uD   ★★★ 작업 취소됨 (CANCELLED) ★★★

# Test task-99953
r-   r.   re   rf   rg   rh   r   r   rk   r   rl   rm   rn   ro   rp   NuA   STOP 마커 감지 후 .cancelled 파일이 생성되지 않음: r0   r1   r2   rv   rw   rx   )r<   r=   r>   r?   r@   r{   r|   r}   r~   r   r   r   rB   rC   rD   r   r   r   r   r   rA   )rG   rH   r1   rx   r   rI   r   r   r\   r   r    r   s               r"   (test_finish_task_detects_top_stop_markerr      sd   Gy_,I gYj#99N	//I %T*% TD1dT2Q  
*Si/2BBCWM
    	
A 	
 A% 	
 	
 A 	
 	
 
6	
 	
   	
 	
 
	  	
 	
 
	 ! 	
 	
 
	 %& 	
 	
  >f>O>O=P Q}}o'	
 	
 	
 	
 	
 $$ 	
$& 	
& 	
  PP^O_`	
 	
	6	
 	
   	
 	
 		  	
 	
 		 % 	
 	
 		 ' 	
 	
 	
 	
 	

 ##f#%f%%f%ff)Z[dZe'fffffff9fff9fff#fff%ffffff 	D).D) 	D).D)s   J)M? ?8N7c                    ddl }d}t        | dz  }t        | dz  }|j                  d       |j                  d       | j                  dt	        t
                     t        j                  dd	       |d
dd}|j                  t        j                  |      d       di d}	 |j                  ||d       |j                  } |       }| }	|	st        j                  d|       dz   dt        j                         v st        j                   |      rt        j"                  |      ndt        j"                  |      t        j"                  |      dz  }
t%        t        j&                  |
            dx}x}}	|d   }d}||k(  }|st        j(                  d|fd||f      t        j"                  |      t        j"                  |      dz  }t        j                  d|d          dz   d|iz  }t%        t        j&                  |            dx}x}}|j                  d       |j                  d       y# |j                  d       |j                  d       w xY w)u~   _handle_gate 호출 시 .cancelled 마커가 있으면 .qc-result가 생성되지 않고 overall이 CANCELLED로 변경된다.r   Nz
task-99954r'   z
.qc-resultTr(   WORKSPACE_ROOTr*   r`   ra   rb   r-   r.   PASS)overallchecksdev7uA   .qc-result 파일이 생성되었음 (.cancelled 가드 실패): rw   qc_result_filer2   r   r5   r   r   r   u    overall이 CANCELLED가 아님: r   r   )	qc_verifyr=   r>   setenvr}   r~   r?   r@   ry   rz   _handle_gaterA   r   r   rB   rC   rD   r   r   r   r   )monkeypatchr   rG   r1   r   r   dummy_resultrI   r   r   r\   r   r   r    r!   s                  r"   -test_qc_verify_handle_gate_skips_on_cancelledr      sc   G gYj#99N gYj#99N T*T* 'Z9 dT2!(:O[abNdjj87K%4L/|Wf= "(( 	
(* 	
** 	
* 	
  PP^O_`	
 	
	6	
 	
  " 	
 	
 		 " 	
 	
 		 ) 	
 	
 		 + 	
 	
 	
 	
 	

 I& 	
+ 	
&+5 	
 	
&+ 	
 	
 		 ' 	
 	
 		 +6 	
 	
  /|I/F.GH	
 	
 	
 	
 	

 	.. 	..s   +E3I &I))__doc__builtinsrB   _pytest.assertion.rewrite	assertionrewriter   ry   r{   syspathlibr   pytest__file__parentr~   pathinsertr}   _SHAREDr   r<   r=   r#   rK   r]   r   r   r   rP   r$   r"   <module>r      s       
   (^""))
 3z? # w

) 3w<   ("W,
8#h.V#/T/F.*j,*f%/r$   