
    i0#                     D   d Z ddlZddlZddlZddlZddlmZ ddlZdej                  vrej                  j                  dd       ddl
mZmZmZmZ ej                  d        Zdedefd	Zed
z   fdedef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  task-2422 Fix B 회귀 테스트: 신호등 봇 실 PID 종합 판정

검증 포인트:
- evaluate_task_liveness 6 시나리오 (completed/no-hb/fresh-pid-alive/fresh-pid-dead/stale/escalated-status박제)
- _PidLivenessProvider override 동작
- get_running_tasks_by_team이 status=escalated여도 PID alive 시 작업중 표시 (사고 회귀 차단)
- task-2414/2417/2420 사고 재현: status가 escalated로 박제되어도 신호등 작업중 정확
    N)Pathz/home/jay/workspace)
DataLoaderHEARTBEAT_FRESH_SECONDS_PidLivenessProviderevaluate_task_livenessc               #   x   K   t        j                         5 } t        |        d d d        y # 1 sw Y   y xY ww)N)tempfileTemporaryDirectoryr   )tmps    B/home/jay/workspace/tests/dashboard/test_signal_pid_aggregation.pytmp_heartbeat_dirr      s1     		$	$	& #3i  s   :.	:7:hb_dirtask_idc                 6    | | dz  }|j                          |S )u'   방금 mtime의 heartbeat 파일 생성
.heartbeat)touch)r   r   fs      r   _touch_freshr   #   s!    G9J''AGGIH    <   c                     | | dz  }|j                          t        j                         |z
  }t        j                  |||f       |S )u*   오래된 mtime의 heartbeat 파일 생성r   )r   timeosutime)r   r   age_secr   pasts        r   _touch_staler   *   sC    G9J''AGGI99; DHHQtHr   c                     t        | d       t               }|j                  ddi       t        dddd| |      }|dk(  sJ y)u0   status=completed → idle (heartbeat/PID 무관)t1zsched-1T	completedstatusschedule_ididleNr   r   set_overrider   r   presults      r   +test_liveness_completed_status_returns_idler*   3   sP    "D)ANNIt$%#Y?ARTUF Vr   c                 n    t               }|j                  ddi       t        dddd| |      }|dk(  sJ y)u0   status=running, heartbeat 파일 없음 → idlezsched-2Tt2runningr!   r$   N)r   r&   r   r'   s      r   /test_liveness_running_no_heartbeat_returns_idler.   >   sE    ANNIt$%#9=?PRSF Vr   c                     t        | d       t               }|j                  ddi       t        dddd| |      }|dk(  sJ y)u8   status=running + fresh heartbeat + PID alive → workingt3zsched-3Tr-   r!   workingNr%   r'   s      r   ?test_liveness_running_fresh_heartbeat_pid_alive_returns_workingr2   H   sP    "D)ANNIt$%#9=?PRSF Yr   c                     t        | d       t               }|j                  i        t        dddd| |      }|dk(  sJ y)u@   status=running + fresh heartbeat + PID dead → bot_suspect_deadt4r-   zsched-4r!   bot_suspect_deadNr%   r'   s      r   Gtest_liveness_running_fresh_heartbeat_pid_dead_returns_bot_suspect_deadr6   S   sL    "D)ANN2#9=?PRSF ''''r   c                     t        | d       t               }|j                  ddi       t        dddd| |      }|dk(  sJ y)u;   status=running + stale heartbeat → idle (PID alive여도)t5zsched-5Tr-   r!   r$   N)r   r   r&   r   r'   s      r   2test_liveness_running_stale_heartbeat_returns_idler9   ^   sP    "D)ANNIt$%#9=?PRSF Vr   c                     t        | d       t               }|j                  ddi       t        dddd| |      }|dk(  s
J d|        y)	u   ★ 핵심: status=escalated여도 fresh heartbeat + PID alive → working (status박제 무시)

    task-2414/2417/2420 사고 회귀 차단의 핵심 시나리오.
    t6zsched-6T	escalatedr!   r1   u:   status박제에 휘둘림 (회귀): expected working, got Nr%   r'   s      r   Atest_liveness_escalated_status_with_alive_signals_returns_workingr=   i   sa    
 "D)ANNIt$%#Y?ARTUF Ye"\]c\d eer   c                     t        | d       t               }|j                  ddi       t        dddd| |      }|dk(  sJ y)u+   status=foobar 등 알수없는 값 → idlet7zsched-7Tfoobarr!   r$   Nr%   r'   s      r   )test_liveness_unknown_status_returns_idlerA   w   sP    "D)ANNIt$%#)<>OQRF Vr   c                      t               } | j                  ddi       | j                  d      du sJ | j                  d      du sJ | j                  d      du sJ y)u,   override map에 없는 schedule_id → Falsezsched-ATzsched-BF Nr   r&   is_aliver(   s    r   =test_pid_provider_override_returns_false_for_missing_schedulerG      s_    ANNIt$%::i E)))::b>U"""::du$$$r   c                      t               } | j                  ddi       | j                  d      du sJ | j                  d       | j                  d      du sJ y)u@   set_override(None) → 실제 pgrep 모드 복귀 (캐시 reset)zsched-XTNFrD   rF   s    r   6test_pid_provider_clear_override_resets_to_real_lookuprI      sU    ANNIt$%::i D(((NN4::i E)))r   c            
         t        j                         5 } t        |       }|dz  }|dz  j                  d       t	        |      }|dz  dz  j                          dddd	d
ddddii|_        |j                  j                  d
di       |j                         }d	|v s
J d|        t        |d	         dk(  sJ |d	   d   }|d   dk(  sJ |j                  d      dk(  sJ 	 ddd       y# 1 sw Y   yxY w)uf   ★ 통합 테스트: status=escalated + fresh heartbeat + PID alive → 신호등에 작업중 표시memory
heartbeatsTparentsztask-9999.heartbeattasksz	task-9999r<   z	dev2-teamzsched-test-9999z	test taskz2026-05-01T00:00:00zbot-x)r"   team_idr#   description
start_timebotu:   escalated + alive 봇이 신호등에서 누락 (회귀):    r   r   livenessr1   N)r	   r
   r   mkdirr   r   	task_datapid_providerr&   get_running_tasks_by_teamlenget)r   	workspacerK   loaderr)   entrys         r   Gtest_get_running_tasks_by_team_with_escalated_status_includes_alive_botr_      s5   		$	$	& 2#I	X%	,	%%d%3I&	,	!6	6==? )*#4#."7"	
 	((*;T)BC113f$k(bcibj&kk$6+&'1,,,{#A&Y;...yy$	11192 2 2s   CC..C7c                     t        j                         5 } t        |       }|dz  }|dz  j                  d       t	        |      }|dz  dz  }|j                          t        j                         t        z
  dz
  }t        j                  |||f       ddd	d
dddii|_
        |j                  j                  ddi       |j                         }d
|vsJ d       	 ddd       y# 1 sw Y   yxY w)uB   status=running이지만 heartbeat stale → 신호등에서 제외rK   rL   TrM   ztask-9998.heartbeatd   rO   z	task-9998r-   z	dev1-teamz
sched-9998z
stale taskr"   rP   r#   rQ   Fu.   stale heartbeat task가 신호등에 포함됨N)r	   r
   r   rV   r   r   r   r   r   r   rW   rX   r&   rY   )r   r\   rK   r]   hbr   r)   s          r   =test_get_running_tasks_by_team_excludes_running_with_dead_botrd      s    		$	$	& [#I	X%	,	%%d%3I&l"%::

yy{44s:
dD\"'*#/#/		
 	((,)>?113&(Z*ZZ(/[ [ [s   CC&&C/c                     t        j                         5 } t        |       }|dz  }|dz  j                  d       t	        |      }|dz  dz  j                          dddd	d
ddii|_        |j                  j                  i        |j                         }d	|v sJ |d	   d   d   dk(  sJ 	 ddd       y# 1 sw Y   yxY w)u>   fresh heartbeat + PID dead → entry liveness=bot_suspect_deadrK   rL   TrM   ztask-7777.heartbeatrO   z	task-7777r-   z	dev3-teamz
sched-7777zbot crashedrb   r   rU   r5   N)
r	   r
   r   rV   r   r   rW   rX   r&   rY   )r   r\   rK   r]   r)   s        r   5test_get_running_tasks_by_team_marks_bot_suspect_deadrf      s    		$	$	& H#I	X%	,	%%d%3I&	,	!6	6==?'*#/#0		
 	((,113f$$$k"1%j15GGGG)H H Hs   BB77C c                  0   t        j                         5 } t        t        |             }t	        |d      sJ t        |j                  t              sJ t	        |d      sJ |j                  t        |       dz  dz  k(  sJ 	 ddd       y# 1 sw Y   yxY w)u5   DataLoader 인스턴스에 pid_provider 속성 존재rX   heartbeat_dirrK   rL   N)	r	   r
   r   r   hasattr
isinstancerX   r   rh   )r   r]   s     r   )test_data_loader_initializes_pid_providerrk      s    		$	$	& K#DI&v~...&--/CDDDv///##tCy8';l'JJJJK K Ks   A-BB)!__doc__r   sysr	   r   pathlibr   pytestpathinsertdashboard.data_loaderr   r   r   r   fixturer   strr   r   r*   r.   r2   r6   r9   r=   rA   rG   rI   r_   rd   rf   rk    r   r   <module>rv      s    
 
     (HHOOA,-   
   6Mr5Q   (f%*2B[8H2Kr   