
    i4                     D   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ZddlZddlmZmZmZ ddlmZ ddlmZmZ ddlZ ee
j,                  j/                  dd            Zedz  d	z  Zej4                  j7                  d
e      Zej4                  j;                  e      Zeej>                  d
<   ej@                  jC                  e        G d d      Z" G d d      Z# G d d      Z$ G d d      Z% G d d      Z& G d d      Z'e(dk(  r ejR                  e*dg       yy)u  bot-status-watchdog.py 테스트

테스트 항목:
1. parse_since_time() - ISO 8601 파싱
2. find_bot_process() - 프로세스 검색
3. should_transition_to_idle() - idle 전환 조건
4. check_and_recover_stuck_bots() - stuck 봇 복구
5. save_bot_activity() - 원자적 쓰기
    N)datetime	timedeltatimezone)Path)	MagicMockpatchWORKSPACE_ROOTz/home/jay/workspacescriptszbot-status-watchdog.pybot_status_watchdogc                   "    e Zd ZdZd Zd Zd Zy)TestParseSinceTimeu   parse_since_time() 테스트c                    t         j                  d      }d}||u}|st        j                  d|fd||f      dt	        j
                         v st        j                  |      rt        j                  |      ndt        j                  |      dz  }dd|iz  }t        t        j                  |            dx}}|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  }dd|iz  }t        t        j                  |            dx}x}}|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  }dd|iz  }t        t        j                  |            dx}x}}|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  }dd|iz  }t        t        j                  |            dx}x}}|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  }dd|iz  }t        t        j                  |            dx}x}}|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  }dd|iz  }t        t        j                  |            dx}x}}|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  }dd|iz  }t        t        j                  |            dx}x}}|j                   }t"        j$                  }	||	k(  }|st        j                  d
|fd||	f      dt	        j
                         v st        j                  |      rt        j                  |      ndt        j                  |      dt	        j
                         v st        j                  t"              rt        j                  t"              ndt        j                  |	      dz  }
dd|
iz  }t        t        j                  |            dx}x}}	y)u(   UTC 형식 파싱 (2026-03-17T06:54:35Z)z2026-03-17T06:54:35ZNis notz%(py0)s is not %(py3)sresultpy0py3assert %(py5)spy5  ==z,%(py2)s
{%(py2)s = %(py0)s.year
} == %(py5)sr   py2r   assert %(py7)spy7   z-%(py2)s
{%(py2)s = %(py0)s.month
} == %(py5)s   z+%(py2)s
{%(py2)s = %(py0)s.day
} == %(py5)s   )z,%(py2)s
{%(py2)s = %(py0)s.hour
} == %(py5)s6   )z.%(py2)s
{%(py2)s = %(py0)s.minute
} == %(py5)s#   )z.%(py2)s
{%(py2)s = %(py0)s.second
} == %(py5)s)zG%(py2)s
{%(py2)s = %(py0)s.tzinfo
} == %(py6)s
{%(py6)s = %(py4)s.utc
}r   )r   r   py4py6zassert %(py8)spy8)r   parse_since_time
@pytest_ar_call_reprcompare@py_builtinslocals_should_repr_global_name	_safereprAssertionError_format_explanationyearmonthdayhourminutesecondtzinfor   utc)selfr   @py_assert2@py_assert1@py_format4@py_format6@py_assert4@py_assert3@py_format8@py_assert5@py_format7@py_format9s               ./home/jay/workspace/tests/test_bot_watchdog.pytest_parse_utc_formatz(TestParseSinceTime.test_parse_utc_format#   s   $556LM!!vT!!!!vT!!!!!!v!!!v!!!T!!!!!!!{{"d"{d""""{d""""""v"""v"""{"""d"""""""|| q |q    |q      v   v   |   q       zzRzRzRvvzR{{a{a{avv{a}}""}""""}""""""v"""v"""}""""""""""}}""}""""}""""""v"""v"""}""""""""""}},,},,,,},,,,,,v,,,v,,,},,,,,,,,,,,,,,,,,,,    c                 (   t         j                  d      }d}||u}|st        j                  d|fd||f      dt	        j
                         v st        j                  |      rt        j                  |      ndt        j                  |      dz  }dd|iz  }t        t        j                  |            dx}}|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  }dd|iz  }t        t        j                  |            dx}x}}|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  }dd|iz  }t        t        j                  |            dx}x}}|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  }dd|iz  }t        t        j                  |            dx}x}}y)u-   KST 형식 파싱 (2026-03-17T15:54:35+09:00)z2026-03-17T15:54:35+09:00Nr   r   r   r   r   r   r   r   r   r   r   r   r    r!   r"   r#   )r   r*   r+   r,   r-   r.   r/   r0   r1   r2   r3   r4   r5   )	r;   r   r<   r=   r>   r?   r@   rA   rB   s	            rF   test_parse_kst_formatz(TestParseSinceTime.test_parse_kst_format/   s   $556QR!!vT!!!!vT!!!!!!v!!!v!!!T!!!!!!!{{"d"{d""""{d""""""v"""v"""{"""d"""""""|| q |q    |q      v   v   |   q       zzRzRzRvvzRrH   c                 :   t         j                  }d} ||      }d}||u }|st        j                  d|fd||f      dt	        j
                         v st        j                  t               rt        j                  t               ndt        j                  |      t        j                  |      t        j                  |      t        j                  |      dz  }dd|iz  }t        t        j                  |            dx}x}x}x}}t         j                  }d	} ||      }d}||u }|st        j                  d|fd||f      dt	        j
                         v st        j                  t               rt        j                  t               ndt        j                  |      t        j                  |      t        j                  |      t        j                  |      dz  }dd|iz  }t        t        j                  |            dx}x}x}x}}t         j                  }d} ||      }d}||u }|st        j                  d|fd||f      dt	        j
                         v st        j                  t               rt        j                  t               ndt        j                  |      t        j                  |      t        j                  |      t        j                  |      dz  }dd|iz  }t        t        j                  |            dx}x}x}x}}y)
u'   잘못된 형식 파싱 → None 반환invalidNis)zV%(py6)s
{%(py6)s = %(py2)s
{%(py2)s = %(py0)s.parse_since_time
}(%(py4)s)
} is %(py9)sr   )r   r   r'   r(   py9zassert %(py11)spy11 )
r   r*   r+   r,   r-   r.   r/   r0   r1   r2   )r;   r=   rA   rC   @py_assert8@py_assert7@py_format10@py_format12s           rF   test_parse_invalid_formatz,TestParseSinceTime.test_parse_invalid_format7   s   "33FIF3I>F$F>$FFFF>$FFFFFF"FFF"FFF3FFFIFFF>FFF$FFFFFFF"33?B?3B7?4?74????74??????"???"???3???B???7???4???????"33ADA3D9ATA9TAAAA9TAAAAAA"AAA"AAA3AAADAAA9AAATAAAAAAAArH   N)__name__
__module____qualname____doc__rG   rJ   rV    rH   rF   r   r       s    &
- BrH   r   c                   T    e Zd ZdZd Z ed      d        Z ed      d        Zd Zy)TestFindBotProcessu   find_bot_process() 테스트c                 L   t         j                  }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  }t        t        j                  |            dx}}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  }t        t        j                  |            dx}}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  }t        t        j                  |            dx}}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  }t        t        j                  |            dx}}y)u-   봇 이름 → workspace 패턴 매핑 확인anuinz%(py1)s in %(py3)spatternspy1r   r   r   Ndev1dev2dev3)
r   BOT_WORKSPACE_PATTERNSr+   r,   r0   r-   r.   r/   r1   r2   )r;   rc   @py_assert0r<   r>   r?   s         rF   !test_find_process_pattern_mappingz4TestFindBotProcess.test_find_process_pattern_mappingA   ss    '== u    u   u                !v!!!!v!!!v!!!!!!!!!!!!!!!!!v!!!!v!!!v!!!!!!!!!!!!!!!!!v!!!!v!!!v!!!!!!!!!!!!!!!!rH   zsubprocess.runc                    t        ddd      |_        t        j                  d      }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  }t        t	        j                  |            dx}}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  }t        t	        j                  |            dx}}y)u)   프로세스 발견 시 PID 목록 반환r   z12345
67890
rQ   
returncodestdoutstderrrf   90  r`   rb   pidsrd   r   r   N2	 )r   return_valuer   find_bot_processr+   r,   r0   r-   r.   r/   r1   r2   )r;   mock_runrr   rj   r<   r>   r?   s          rF   test_find_process_returns_pidsz1TestFindBotProcess.test_find_process_returns_pidsJ   s     !*Q?OXZ ["33F;u}uuu}uurH   c                    t        ddd      |_        t        j                  d      }g }||k(  }|st	        j
                  d|fd||f      dt        j                         v st	        j                  |      rt	        j                  |      ndt	        j                  |      dz  }d	d
|iz  }t        t	        j                  |            dx}}y)u+   프로세스 없으면 빈 리스트 반환   rQ   rm   rf   r   z%(py0)s == %(py3)srr   r   r   r   N)r   rt   r   ru   r+   r,   r-   r.   r/   r0   r1   r2   )r;   rv   rr   r<   r=   r>   r?   s          rF   test_find_process_no_processz/TestFindBotProcess.test_find_process_no_processS   s}     !*Qr" M"33F;trztrttrrH   c                 z   t         j                  d      }g }||k(  }|st        j                  d|fd||f      dt	        j
                         v st        j                  |      rt        j                  |      ndt        j                  |      dz  }dd|iz  }t        t        j                  |            dx}}y)	u$   알 수 없는 봇 → 빈 리스트unknownr   rz   rr   r   r   r   N)
r   ru   r+   r,   r-   r.   r/   r0   r1   r2   )r;   rr   r<   r=   r>   r?   s         rF   test_find_process_unknown_botz0TestFindBotProcess.test_find_process_unknown_bot[   sj    "33I>trztrttrrH   N)	rW   rX   rY   rZ   rk   r   rw   r{   r~   r[   rH   rF   r]   r]   >   sC    &"    rH   r]   c                      e Zd ZdZd Z ej                  edddg      d        Z ej                  edg        ej                  ed      d	               Z	 ej                  edg        ej                  edd
       ej                  ed      d                      Z
 ej                  edg        ej                  edd
       ej                  edd
      d                      Zy
)TestShouldTransitionToIdleu%   should_transition_to_idle() 테스트c                    t        j                  t        j                        t	        d      z
  }t        j                  t        dg       5  t        j                  d|d      \  }}ddd       d}|u }|st        j                  d	|fd
||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      dz  }dd|iz  }t        t        j                   |            dx}}d}|k(  }|st        j                  d|fd||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      dz  }dd|iz  }t        t        j                   |            dx}}y# 1 sw Y   VxY w)u   30분 미만 → 전환 안 함   minutesru   rt   rf   g      4@NFrM   z%(py0)s is %(py3)sshould_idler   r   r   not_timeoutr   rz   reason)r   nowr   r:   r   r   objectr   should_transition_to_idler+   r,   r-   r.   r/   r0   r1   r2   )r;   
since_timer   r   r<   r=   r>   r?   s           rF   test_not_timeout_yetz/TestShouldTransitionToIdle.test_not_timeout_yetd   s   \\(,,/)B2GG
\\-/APRS 	j"5"O"OPVXbdh"iK	j $#{e####{e######{###{###e#######&&v&&&&v&&&&&&v&&&v&&&&&&&&&&		j 	js   F<<Gru   rq   rs   r   c                 v   t        j                  t        j                        t	        d      z
  }t
        j                  d|d      \  }}d}||u }|st        j                  d|fd||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      d	z  }d
d|iz  }t        t        j                  |            dx}}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  }t        t        j                  |            dx}	}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  }t        t        j                  |            dx}	}y)u,   프로세스 살아있음 → 전환 안 함r&   r   rf        A@FrM   r   r   r   r   r   Nstill_runningr`   rb   r   rd   12345r   r   r   r:   r   r   r   r+   r,   r-   r.   r/   r0   r1   r2   )
r;   	mock_findr   r   r   r<   r=   r>   r?   rj   s
             rF   test_process_still_runningz5TestShouldTransitionToIdle.test_process_still_runningn   sF    \\(,,/)B2GG
1KKFT^`deV##{e####{e######{###{###e#######(&((((&(((((((((&(((&((((((( w&    w&   w      &   &       rH   find_recent_done_filec                    t        j                  t        j                        t	        d      z
  }t
        dz  dz  dz  |_        t        j                  d|d      \  }}d}||u }|st        j                  d	|fd
||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      dz  }dd|iz  }	t        t        j                   |	            dx}}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  }	t        t        j                   |	            dx}
}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  }	t        t        j                   |	            dx}
}y)u   .done 파일 있음 → 전환r&   r   memoryeventsztask-123.1.dev1.donerf   r   TrM   r   r   r   r   r   N	completedr`   rb   r   rd   z.doner   r   r   r:   r   
_WORKSPACErt   r   r   r+   r,   r-   r.   r/   r0   r1   r2   )r;   	mock_doner   r   r   r   r<   r=   r>   r?   rj   s              rF   test_done_file_existsz0TestShouldTransitionToIdle.test_done_file_existsy   s^    \\(,,/)B2GG
!+h!6!ADZ!Z	1KKFT^`deV""{d""""{d""""""{"""{"""d"""""""${f$$$${f$$${$$$$$$f$$$f$$$$$$$ w&    w&   w      &   &       rH   Nfind_recent_reportc                    t        j                  t        j                        t	        d      z
  }t
        dz  dz  dz  |_        t        j                  d|d      \  }}d}||u }|st        j                  d	|fd
||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      dz  }	dd|	iz  }
t        t        j                   |
            dx}}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  }
t        t        j                   |
            dx}}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  }
t        t        j                   |
            dx}}y)u"   보고서 파일 있음 → 전환r&   r   r   reportsztask-123.1.mdrf   r   TrM   r   r   r   r   r   Nr   r`   rb   r   rd   u	   보고서r   r;   mock_reportr   r   r   r   r   r<   r=   r>   r?   rj   s               rF   test_report_existsz-TestShouldTransitionToIdle.test_report_exists   s]   
 \\(,,/)B2GG
#-#89#D#V 1KKFT^`deV""{d""""{d""""""{"""{"""d"""""""${f$$$${f$$${$$$$$$f$$$f$$$$$$$${f$$$${f$$${$$$$$$f$$$f$$$$$$$rH   c                 ,   t        j                  t        j                        t	        d      z
  }t
        j                  d|d      \  }}d}||u }|st        j                  d|fd||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      d	z  }	d
d|	iz  }
t        t        j                  |
            dx}}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  }
t        t        j                  |
            dx}}y)u-   프로세스 없음 + 30분 초과 → 전환r&   r   rf   r   TrM   r   r   r   r   r   Ntimeoutr`   rb   r   rd   r   r   s               rF   test_timeout_no_processz2TestShouldTransitionToIdle.test_timeout_no_process   s    
 \\(,,/)B2GG
1KKFT^`deV""{d""""{d""""""{"""{"""d""""""""yF""""yF"""y""""""F"""F"""""""rH   )rW   rX   rY   rZ   r   r   r   r   r   r   r   r   r[   rH   rF   r   r   a   s$   /' U\\%'9PUW! X! U\\%'9KU\\%'>?	! @ L	! U\\%'9KU\\%'>TRU\\%';<	% = S L	% U\\%'9KU\\%'>TRU\\%';$O# P S L#rH   r   c                   F    e Zd ZdZej
                  d        Zd Zd Zd Z	y)TestCheckAndRecoverStuckBotsu(   check_and_recover_stuck_bots() 테스트c                    t        j                  t        j                        t	        d      z
  }|j                  d      }t        j                  t        j                        t	        d      z
  }|j                  d      }dd|dd|dd|dd	i}|d
z  }|j                  t        j                  |d      d       ||fS )u   임시 bot-activity.json 생성(   r   %Y-%m-%dT%H:%M:%SZ
   bots
processingstatussinceidle)rf   rg   rh   bot-activity.json   indentutf-8encoding)	r   r   r   r:   r   strftime
write_textjsondumps)r;   tmp_pathold_timeold_time_strrecent_timerecent_time_strdatabot_activity_files           rF   temp_bot_activityz.TestCheckAndRecoverStuckBots.temp_bot_activity   s     <<-	"0EE(()=> ll8<<09R3HH%../CD #/,G#//J#)OD
 %'::$$TZZQ%?'$R~rH   c                    |\  }}|j                  t        d|dz         |j                  t        d|dz         |j                  t        d|dz         |j                  t        d|dz         t        j                  t        d	g 
      5  t        j                  t        dd
      5  t        j                  t        dd
      5  t        j	                         }ddd       ddd       d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  }dd|iz  }	t        t        j                  |	            dx}}t        j                  |dz  j                  d            }
|
d   d   d   }d}||k(  }|slt        j                  d|fd||f      t        j                  |      t        j                  |      dz  }dd|iz  }t        t        j                  |            dx}x}}|
d   d   d   }d }||k(  }|slt        j                  d|fd||f      t        j                  |      t        j                  |      dz  }dd|iz  }t        t        j                  |            dx}x}}y# 1 sw Y   xY w# 1 sw Y   xY w# 1 sw Y   xY w)!u   stuck 봇 복구 테스트BOT_ACTIVITY_FILEr   
EVENTS_DIRr   REPORTS_DIRr   WATCHDOG_LOGbot-watchdog.logru   r   r   Nr   ry   r   rz   	recoveredr   r   r   r   r   r   rf   r   r   z%(py1)s == %(py4)sre   r'   assert %(py6)sr(   rg   r   )setattrr   r   r   check_and_recover_stuck_botsr+   r,   r-   r.   r/   r0   r1   r2   r   loads	read_text)r;   r   monkeypatchr   r   r   r<   r=   r>   r?   updated_datarj   rA   @py_format5rD   s                  rF   test_recover_stuck_botsz4TestCheckAndRecoverStuckBots.test_recover_stuck_bots   s;   *$ 	/1DhQdFde/x(?RS/9@TU/L^A^_ \\-/APRS 	S13JY]^ S\\"57KZ^_ S 3 P P RISS	S yA~yAyyA zz8.A#A"L"LV]"L"^_F#F+H5??5????5???5??????????F#F+H5EE5EEEE5EEE5EEEEEEEEEES SS S	S 	Ss<   
K&'KKK!K&KKK#	K&&K0c                    |j                  t        d|dz         |j                  t        d|dz         |j                  t        d|dz         |j                  t        d|dz         t        j                  t        j
                        t        d	
      z
  }|j                  d      }dd|dd|ddi}|dz  j                  t        j                  |d      d       t        j                  t        dg       5  t        j                         }d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  }	dd|	iz  }
t)        t        j*                  |
            dx}}y# 1 sw Y   xY w)u   stuck 봇이 없는 경우r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   )rf   rg   r   r   r   r   ru   r   Nr   r   rz   r   r   r   r   )r   r   r   r   r   r:   r   r   r   r   r   r   r   r   r+   r,   r-   r.   r/   r0   r1   r2   )r;   r   r   r   r   r   r   r<   r=   r>   r?   s              rF   test_no_stuck_botsz/TestCheckAndRecoverStuckBots.test_no_stuck_bots   sn   /1DhQdFde/x(?RS/9@TU/L^A^_ll8<<09R3HH%../CD #//J#)OD
 
'	'33DJJtA4NY`3a\\-/APRS 	K+HHJI	K yA~yAyyA	K 	Ks   >GGc                    |j                  t        d|dz         |j                  t        d|dz         |j                  t        d|dz         |j                  t        d|dz         t        j                  t        j
                        t        d	
      z
  }|j                  d      }ddd|dii}|dz  j                  t        j                  |d      d       t        j                  t        ddg      5  t        j                         }d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  }	dd|	iz  }
t)        t        j*                  |
            dx}}t        j,                  |dz  j/                  d            }|d   d   d   }d}||k(  }|slt        j                  d|fd ||f      t        j&                  |      t        j&                  |      d!z  }d"d#|iz  }t)        t        j*                  |            dx}x}}y# 1 sw Y   _xY w)$u0   프로세스 살아있으면 idle 전환 안 함r   r   r   r   r   r   r   r   r   r   r   r   rf   r   r   r   r   r   r   ru   rq   r   Nr   r   rz   r   r   r   r   r   r   r   r   r(   )r   r   r   r   r   r:   r   r   r   r   r   r   r   r   r+   r,   r-   r.   r/   r0   r1   r2   r   r   )r;   r   r   r   r   r   r   r<   r=   r>   r?   r   rj   rA   r   rD   s                   rF   test_skip_if_process_runningz9TestCheckAndRecoverStuckBots.test_skip_if_process_running   s   /1DhQdFde/x(?RS/9@TU/L^A^_ <<-	"0EE(()=>L<!PQR	'	'33DJJtA4NY`3a \\-/AQVPWX 	K+HHJI	K yA~yAyyAzz8.A#A"L"LV]"L"^_F#F+H5EE5EEEE5EEE5EEEEEEEEEE	K 	Ks   ;I--I7N)
rW   rX   rY   rZ   pytestfixturer   r   r   r   r[   rH   rF   r   r      s,    2^^ .F00FrH   r   c                       e Zd ZdZd Zy)TestSaveBotActivityu   save_bot_activity() 테스트c                    |j                  t        d|dz         dddddii}t        j                  |      }d}||u }|st        j                  d	|fd
||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      dz  }dd|iz  }t        t        j                  |            dx}}|dz  }	|	j                  } |       }
|
sddt        j                         v st        j                  |	      rt        j                  |	      ndt        j                  |      t        j                  |
      dz  }t        t        j                  |            dx}}
t        j                  |	j                  d            }||k(  }|st        j                  d|fd||f      dt        j                         v st        j                  |      rt        j                  |      nddt        j                         v st        j                  |      rt        j                  |      nddz  }dd|iz  }t        t        j                  |            d}y)u   원자적 쓰기 테스트r   r   r   rf   r   z2026-03-17T07:00:00Zr   TrM   r   r   r   r   r   NAassert %(py4)s
{%(py4)s = %(py2)s
{%(py2)s = %(py0)s.exists
}()
}r   r   r   r'   r   r   r   )z%(py0)s == %(py2)sloadedr   )r   r   zassert %(py4)sr'   )r   r   save_bot_activityr+   r,   r-   r.   r/   r0   r1   r2   existsr   r   r   )r;   r   r   r   r   r<   r=   r>   r?   r   rA   r   r   @py_format3s                 rF   test_atomic_writez%TestSaveBotActivity.test_atomic_write	  s   /1DhQdFdeF=S!TUV$66t<v~vvv %':: '')')))))))) ))) )))')))))))))) -777IJ~vvvrH   N)rW   rX   rY   rZ   r   r[   rH   rF   r   r     s
    'rH   r   c                       e Zd ZdZd Zy)TestWatchdogOnceu   워치독 1회 실행 테스트c                    |j                  t        d|dz         |j                  t        d|dz         |j                  t        d|dz         |j                  t        d|dz         t        j                  t        j
                        t        d	
      z
  }|j                  d      }ddd|dii}|dz  j                  t        j                  |d      d       t        j                  t        dg       5  t        j                  t        dd      5  t        j                  t        dd      5  t        j                          ddd       ddd       ddd       |dz  }|j                  } |       }|sddt        j                          v st#        j$                  |      rt#        j&                  |      ndt#        j&                  |      t#        j&                  |      dz  }	t)        t#        j*                  |	            dx}}t        j,                  |dz  j/                  d            }
|
d   d   d   }d}||k(  }|slt#        j0                  d|fd||f      t#        j&                  |      t#        j&                  |      d z  }	d!d"|	iz  }t)        t#        j*                  |            dx}x}}y# 1 sw Y   txY w# 1 sw Y   yxY w# 1 sw Y   ~xY w)#u   1회 실행 테스트r   r   r   r   r   r   r   r   r   r   r   r   rf   r   r   r   r   r   r   ru   r   r   Nr   r   log_filer   r   r   r   r   r   r   r(   )r   r   r   r   r   r:   r   r   r   r   r   r   r   run_oncer   r-   r.   r+   r/   r0   r1   r2   r   r   r,   )r;   r   r   r   r   r   r   r=   rA   r   r   rj   r<   rD   s                 rF   test_run_oncezTestWatchdogOnce.test_run_once  s=    	/1DhQdFde/x(?RS/9@TU/L^A^_ <<-	"0EE(()=>L<!PQR	'	'33DJJtA4NY`3a \\-/APRS 	313JY]^ 3\\"57KZ^_ 3'00233	3 00         x   x              zz8.A#A"L"LV]"L"^_F#F+H5??5????5???5??????????3 33 3	3 	3s<   :KK4J;	KK;K KK	KKN)rW   rX   rY   rZ   r   r[   rH   rF   r   r     s    )@rH   r   __main__z-v)+rZ   builtinsr-   _pytest.assertion.rewrite	assertionrewriter+   importlib.util	importlibr   ossystempfiler   r   r   pathlibr   unittest.mockr   r   r   environgetr   SCRIPT_PATHutilspec_from_file_locationspecmodule_from_specr   modulesloaderexec_moduler   r]   r   r   r   r   rW   main__file__r[   rH   rF   <module>r     s       	 
  2 2  *  "**..!13HIJ
9$'??~~--.C[Qnn55d; %8! "   + ,B B<   F=# =#@bF bFJ *@ @D zFKK4 ! rH   