
    (<i/              
       4   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mZmZ ddlm	Z	 ddl
mZmZmZ  e	ej                  j                  d e e	e      j%                         j&                  j&                                    Zedz  Zedz  Zed	z  Zed
z  Zedz  Zedz  dz  Zedz  Zedz  Zej                  j                  dd      Zej                  j                  dd      ZdZdZ defdZ!dedededefdZ"deddfdZ#dededdfdZ$dededdfdZ%d e	ddfd!Z&dee'ef   fd"Z(dee'ef   fd#Z)dee'ef   fd$Z*dee'ef   fd%Z+dee'ef   fd&Z,dee'ef   fd'Z-dee'ef   fd(Z.d)ee/   d*e'ddfd+Z0de1fd,Z2e3d-k(  r ejh                   e2              yy).u   
canary-test.py — 일 1회 실행되는 시스템 건강도 canary 테스트.

시스템 핵심 기능이 정상 작동하는지 검증하고 실패 시 텔레그램으로 알림 전송.
    N)datetimetimezone)Path)ListOptionalTupleWORKSPACE_ROOTmemoryeventslogsztask-timer.pyztask-timers.jsonscriptsznotify-completion.pyzcanary-status.jsonzcanary-test.logCOKACDIR_CHAT_ID
6937032012COKACDIR_KEY_ANUc119085addb0f8b7d   iQ returnc                  H    t        j                         j                  d      S )Nz%Y-%m-%d %H:%M:%S)r   nowstrftime     D/home/jay/workspace/.worktrees/task-2057-dev2/scripts/canary-test.py_now_strr   *   s    <<>""#677r   level	test_namedescriptionc                 .    dt                d|  d| d| S )N[] [z] : )r   )r   r   r   s      r   	_log_liner"   .   s#    xzl#eWBykK=AAr   linec                 D   t         j                  dd       g }t        j                         r$t        j	                  d      j                         }|j                  |        |t         d }t        j                  dj                  |      dz   d       t        |        y)uK   로그 파일에 한 줄 추가 후 마지막 LOG_KEEP_LINES 줄만 유지.Tparentsexist_okutf-8encodingN
)LOGS_DIRmkdir
CANARY_LOGexists	read_text
splitlinesappendLOG_KEEP_LINES
write_textjoinprint)r#   existingtrimmeds      r   	write_logr9   2   s    NN4$N/H'''9DDFOOD'(G$))G,t3gF	$Kr   c                 0    t        t        d| |             y )NPASSr9   r"   r   r   s     r   log_passr>   A       i	;78r   c                 0    t        t        d| |             y )NFAILr<   r=   s     r   log_failrB   E   r?   r   log_filec                     	 ddt        |       dt        dt        g}t        j                  |dd       y# t
        $ r Y yw xY w)	uJ   로그 파일을 텔레그램으로 전송. 실패해도 조용히 무시.cokacdirz
--sendfilez--chatz--key   T)timeoutcapture_outputN)strCHAT_IDANU_KEY
subprocessrun	Exception)rC   cmds     r   send_telegram_logrP   L   sK    M
 	sBt< s   25 	A Ac                  P   d} 	 t         j                         sdt          dfS t         j                  d      }t        j                  |       t         j
                  dz  }|j                  dd       |j                          y# t        $ r}dt        |      fcY d	}~S d	}~ww xY w)
u0   1. task-timers.json 읽기/쓰기 가능 여부.   task-timers.json 읽기/쓰기Fu    파일이 존재하지 않음r(   r)   .canary-write-testok)Tu   읽기/쓰기 정상N)
TASK_TIMERS_JSONr/   r0   jsonloadsparentr4   unlinkrN   rI   )r   content	test_filees       r   test_task_timers_json_rwr]   `   s    0I&&(-..LMMM",,g,>

7$++.BB	TG4+ c!f}s#   B A!B 	B%B B% B%c                      d} 	 t         j                  dd       t         dz  }|j                  dd       |j                          y# t        $ r}d	t        |      fcY d
}~S d
}~ww xY w)u4   2. memory/events/ 디렉토리 쓰기 가능 여부.   memory/events/ 쓰기Tr%   rS   rT   r(   r)   )Tu   쓰기 정상FN)
EVENTS_DIRr-   r4   rY   rN   rI   )r   r[   r\   s      r   test_events_dir_writablera   r   sj    'I5!55	TG4$ c!f}s   AA 	A(A#A(#A(c                     	 t        j                  t        j                  t	        t
              ddgddd      } | j                  dk7  r,dd| j                   d	| j                  j                          fS | j                  j                         }|sy
t        j                  |       y# t         j                  $ r Y yt        $ r}dt	        |      fcY d}~S d}~ww xY w)uQ   3. task-timer.py `status` 명령 동작 확인 (list 명령으로 동작 검증).listrunningTrF   rH   textrG   r   F
exit code r!   Fu   출력 없음)Tu(   task-timer.py list running 정상 응답Fu   타임아웃 (30초)N)rL   rM   sys
executablerI   TASK_TIMER_PY
returncodestderrstripstdoutrV   rW   TimeoutExpiredrN   )resultoutputr\   s      r   test_task_timer_statusrt      s    ^^S/C	
 !Jv'8'8&9FMM<O<O<Q;RSSS$$&)

6?$$ -, c!f}s0   A2B( 5B( B( (C=CCCCc                  >   	 t        j                  t        j                  t	        t
              ddgddd      } | j                  dk7  r,dd| j                   d	| j                  j                          fS | j                  j                         }|sy
t        j                  |      }|j                  d      dk7  rdd|j                  d       fS dd|j                  dd       fS # t         j                  $ r Y yt        $ r}dt	        |      fcY d}~S d}~ww xY w)u3   4. task-timer.py `cleanup --dry-run` 동작 확인.cleanupz	--dry-runTrF   re   r   Frg   r!   rh   statusdry_runu   예상치 않은 status: u"   dry_run 정상, would_clean_count=would_clean_countri   N)rL   rM   rj   rk   rI   rl   rm   rn   ro   rp   rV   rW   getrq   rN   )rr   rs   parsedr\   s       r   test_task_timer_cleanup_dry_runr|      s   ^^S/KH	
 !Jv'8'8&9FMM<O<O<Q;RSSS$$&)F#::h9,5fjj6J5KLLL9&**EXZ[:\9]^^^$$ -, c!f}s6   A2C( 5C( >C( C( (D=DDDDc                  Z   	 t        j                         j                  d      } t        d|  dz  }t        j	                  dd       |j                  dt                dd	       |j                         j                  }dd
| dfS # t        $ r}dt        |      fcY d}~S d}~ww xY w)u-   5. 일일 로그 파일 쓰기 가능 여부.z%Y-%m-%dzcanary-daily-z.logTr%   r   z] canary write test
r(   r)   u   일일 로그 쓰기 정상 (
   바이트)FN)r   r   r   r,   r-   r4   r   statst_sizerN   rI   )	today_str	daily_logsizer\   s       r   test_daily_log_writabler      s    LLN++J7	yk>>	td3
|01 	 	
 ~~''4TF*EEE c!f}s   BB
 
	B*B%B*%B*c                      	 t         j                         r:t         j                         r&t         j                         j                  } dd|  dfS dt          dfS # t
        $ r}dt        |      fcY d}~S d}~ww xY w)u-   6. notify-completion.py 파일 존재 확인.Tu   파일 존재 (r~   Fu    파일 없음N)NOTIFY_COMPLETION_PYr/   is_filer   r   rN   rI   )r   r\   s     r   test_notify_completion_existsr      sy    &&(-A-I-I-K',,.66D?4&
;;;-.n=== c!f}s$   AA 
A 	A;$A60A;6A;c                     	 t        j                  t        j                  t	        t
              ddgddd      } | j                  dk7  rdd| j                  j                          fS | j                  j                         }|sy	t        j                  |      }|j                  d
g       }t        j                         }g }|D ]  }|j                  d      }|s|j                  dd      }	 t        j                   |      }	||	z
  j%                         }
|
t&        k\  s\|
dz  }|j)                  |j                  dd       d|dd        |r"ddt+        |       ddj-                  |       fS ddt+        |       dfS # t"        $ r Y w xY w# t         j.                  $ r Y yt0        $ r}dt	        |      fcY d}~S d}~ww xY w)u?   7. 현재 running 중인 stale 작업 감지 (24시간 이상).rc   rd   TrF   re   r   Fu   list running 실패: )Tu   실행 중인 작업 없음tasks
start_timeZ i  task_id?z (z.1fzh)u   stale 작업 u   개 감지: z, u   running 작업 u   개, stale 없음ri   N)rL   rM   rj   rk   rI   rl   rm   rn   ro   rp   rV   rW   rz   r   r   replacefromisoformat
ValueErrortotal_secondsSTALE_THRESHOLD_SECONDSr2   lenr5   rq   rN   )rr   rs   r{   r   r   stale_taskstask	start_strstart_str_cleanstart_dtelapsedhoursr\   s                r   test_stale_running_tasksr      s   &^^S/C	
 !1&--2E2E2G1HIII$$&6F#"JJw3lln!# 	QD'+xx'=I'//R8O#11/B X~446G11$""dhhy#&>%?r%B#OP	Q  =[)9(:,tyyQ\G]F^___s5zl2CDDD   $$ -, c!f}sb   A%F (F A(F .FF  AF 3F 	FF FF G(G0G<GGresults
all_passedc                     t               |t        d | D              t        d | D              | d}t        j                  dd       t        j                  t        j                  |dd      d	
       y)u5   canary-status.json에 마지막 실행 결과 기록.c              3   ,   K   | ]  }|d    s	d  ywpassed   Nr   .0rs     r   	<genexpr>z%save_canary_status.<locals>.<genexpr>   s     <(!<   
c              3   ,   K   | ]  }|d    r	d  ywr   r   r   s     r   r   z%save_canary_status.<locals>.<genexpr>   s     @AhK!@r   )last_runr   
pass_count
fail_countr   Tr%   F   )ensure_asciiindentr(   r)   N)r   sum
MEMORY_DIRr-   CANARY_STATUS_JSONr4   rV   dumps)r   r   rw   s      r   save_canary_statusr      sm     J <W<<@W@@F TD1!!

6a8 " r   c                     t        dt                d       dt        fdt        fdt        fdt
        fdt        fdt        fd	t        fg} g }d
}| D ]B  \  }}	  |       \  }}|rt        ||       nt        ||       d}|j                  |||d       D t        d |D              }t        |      |z
  }	dt        |       d| d|	 }
t        dt                d|rdnd d|
        	 t        ||       |s&t        dt                d       t!        t"               |rdS dS # t        $ r}d}d| }Y d }~d }~ww xY w# t        $ r#}t        dt                d|        Y d }~rd }~ww xY w)Nr   u   ] [INFO] canary-test 시작rR   r_   u   task-timer.py status 동작u&   task-timer.py cleanup --dry-run 동작u   일일 로그 쓰기u   notify-completion.py 존재u    stale 작업 감지 (24h 이상)TFu   예외 발생: )testr   detailc              3   ,   K   | ]  }|d    s	d  ywr   r   r   s     r   r   zmain.<locals>.<genexpr>*  s     711X;Q7r   u   총 u   개 테스트 — PASS: z, FAIL: r    r;   rA   u   ] 최종 결과: u+   ] [FAIL] canary-status.json 저장 실패: u*   ] [INFO] 텔레그램 알림 전송 시도r   r   )r9   r   r]   ra   rt   r|   r   r   r   rN   r>   rB   r2   r   r   r   rP   r.   )testsr   r   r   test_fnr   r   r\   r   r   summarys              r   mainr   
  s   (*89: 
*+CD	 ":;	&(>?	13RS	!89	&(EF	+-EFE GJ# U	7	0"))FK
 Y,Y,J	V{STU  777JW
*JS\N"::,hzl[G(*S:6 BBST[S\]^R7J/
 Ahj\!KLM*%1!!;  	0F+A3/K	0*  RAhj\!LQCPQQRs0   
D%+E %	D?.D::D?	E.E))E.__main__)5__doc__rV   osrL   rj   tempfiler   r   pathlibr   typingr   r   r   environrz   rI   __file__resolverX   r	   r   r`   r,   rl   rU   r   r   r.   rJ   rK   r3   r   r   r"   r9   r>   rB   rP   boolr]   ra   rt   r|   r   r   r   dictr   intr   __name__exitr   r   r   <module>r      sc    	  
  '  ( ( bjjnn%5s4>;Q;Q;S;Z;Z;a;a7bcdh&
("
F"_, 22 %	14JJ "66 ))
 **..+\
:
**..+-?
@  $ 8# 8BS BS Bs Bs BC D 9 9# 9$ 99 9# 9$ 9  (%c	"2 $
%c	"2 
dCi 0 .tSy)9 0tSy!1  uT3Y'7 (%c	"2 (\T
   &0"c 0"f zCHHTV r   