
    *iv(                     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	j                  j                  dd        ej                  d      Z G d d      Z 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j2                  edg       yy)u   done-watcher.py 테스트

테스트 항목:
1. extract_team_from_done_file() - .done 파일에서 팀 추출
2. set_bot_idle() - 봇 idle 전환
3. scan_done_files() - .done 파일 스캔
4. process_done_files() - .done 파일 처리
    N)Pathz/home/jay/workspace/scriptszdone-watcherc                   "    e Zd ZdZd Zd Zd Zy)TestExtractTeamFromDoneFileu'   extract_team_from_done_file() 테스트c                    |j                  t        dt        |             |dz  }|j                          t        j	                  |      }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
)u:   파일명에서 팀 추출 (task-648.1.dev1.done → dev1)WORKSPACE_ROOTtask-648.1.dev1.donedev1==z%(py0)s == %(py3)sresultpy0py3assert %(py5)spy5Nsetattrdone_watcherstrtouchextract_team_from_done_file
@pytest_ar_call_reprcompare@py_builtinslocals_should_repr_global_name	_safereprAssertionError_format_explanation	selftmp_pathmonkeypatch	done_filer   @py_assert2@py_assert1@py_format4@py_format6s	            ./home/jay/workspace/tests/test_done_watcher.pytest_extract_from_filenamez6TestExtractTeamFromDoneFile.test_extract_from_filename       L*:CMJ55	99)Dvvvv    c                    |j                  t        dt        |             |dz  }|j                          t        j	                  |      }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
)u:   파일명에서 팀 추출 (task-648.1.dev2.done → dev2)r   ztask-648.1.dev2.donedev2r
   r   r   r   r   r   Nr   r!   s	            r*   test_extract_from_filename_dev2z;TestExtractTeamFromDoneFile.test_extract_from_filename_dev2$   r,   r-   c                    |j                  t        dt        |             ddddddii}|dz  j                  d	d	
       |dz  dz  j	                  t        j                  |d      d       |dz  }|j                          t        j                  |      }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)u@   팀 정보가 없는 파일명 → task-timers.json에서 조회r   tasksz
task-648.1dev3
processingz2026-03-17T07:00:00Z)team_idstatus
started_atmemoryT)parentsexist_okztask-timers.json   indentutf-8encodingztask-648.1.doner
   r   r   r   r   r   N)r   r   r   mkdir
write_textjsondumpsr   r   r   r   r   r   r   r   r   r    )
r"   r#   r$   
timer_datar%   r   r&   r'   r(   r)   s
             r*   %test_extract_without_team_in_filenamezATestExtractTeamFromDoneFile.test_extract_without_team_in_filename.   s    L*:CMJ l,^t$uv

 
H	##D4#@	H	1	1==djj\]>^ip=q 00	99)Dvvvvr-   N)__name__
__module____qualname____doc__r+   r0   rF    r-   r*   r   r      s    1   r-   r   c                   "    e Zd ZdZd Zd Zd Zy)TestSetBotIdleu   set_bot_idle() 테스트c                    |j                  t        d|dz         |j                  t        d|dz         ddddd	ii}|dz  j                  t        j                  |d
      d       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}}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)u   idle 전환 성공BOT_ACTIVITY_FILEbot-activity.jsonDONE_PROTOCOL_LOGdone-protocol.logbotsr	   r4   2026-03-17T06:54:35Zr6   sincer;   r<   r>   r?   Tisz%(py0)s is %(py3)sr   r   r   r   Nr6   idler
   z%(py1)s == %(py4)spy1py4assert %(py6)spy6)r   r   rB   rC   rD   set_bot_idler   r   r   r   r   r   r   r    loads	read_text)r"   r#   r$   datar   r&   r'   r(   r)   updated@py_assert0@py_assert3@py_format5@py_format7s                 r*   test_set_idle_successz$TestSetBotIdle.test_set_idle_successD   sX   L*=xJ]?]^L*=xJ]?]^ LCY!Z[\	'	'33DJJtA4NY`3a**62v~vvv **h)<<GGQXGYZvv&x0:F:0F::::0F:::0:::F:::::::r-   c                 H   |j                  t        d|dz         |j                  t        d|dz         ddddd	ii}|dz  j                  t        j                  |d
      d       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}}y)u   이미 idle인 경우 스킵rO   rP   rQ   rR   rS   r	   rZ   rT   rU   r;   r<   r>   r?   TrW   rY   r   r   r   r   Nr   r   rB   rC   rD   ra   r   r   r   r   r   r   r   r    	r"   r#   r$   rd   r   r&   r'   r(   r)   s	            r*   test_set_idle_already_idlez)TestSetBotIdle.test_set_idle_already_idleT   s    L*=xJ]?]^L*=xJ]?]^ F=S!TUV	'	'33DJJtA4NY`3a**62v~vvvr-   c                 H   |j                  t        d|dz         |j                  t        d|dz         ddddd	ii}|dz  j                  t        j                  |d
      d       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}}y)u   알 수 없는 팀rO   rP   rQ   rR   rS   r	   r4   rT   rU   r;   r<   r>   r?   unknown_teamFrW   rY   r   r   r   r   Nrl   rm   s	            r*   test_set_idle_unknown_teamz)TestSetBotIdle.test_set_idle_unknown_team`   s    L*=xJ]?]^L*=xJ]?]^LCY!Z[\	'	'33DJJtA4NY`3a**>:vvvvr-   N)rG   rH   rI   rJ   rj   rn   rq   rK   r-   r*   rM   rM   A   s    "; 
	r-   rM   c                       e Zd ZdZd Zd Zy)TestScanDoneFilesu   scan_done_files() 테스트c                    |j                  t        d|       |dz  j                          |dz  j                          |dz  j                          |dz  j                          t        j                         }t	        |      }d}||k(  }|st        j                  d|fd||f      d	t        j                         v st        j                  t              rt        j                  t              nd	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   .done 파일 스캔
EVENTS_DIRr   task-648.2.dev2.doneztask-648.3.doneztask-648.4.dev3.done.acked   r
   z0%(py3)s
{%(py3)s = %(py0)s(%(py1)s)
} == %(py6)slenr   r   r]   r   r`   assert %(py8)spy8N)r   r   r   scan_done_filesry   r   r   r   r   r   r   r   r    	r"   r#   r$   r   r&   @py_assert5@py_assert4ri   @py_format9s	            r*   test_scan_done_filesz&TestScanDoneFiles.test_scan_done_fileso   s    L,A 
*	*113	*	*113	%	%,,. 
0	0779--/6{a{a{ass66{ar-   c                 z   |j                  t        d|       t        j                         }t        |      }d}||k(  }|st	        j
                  d|fd||f      dt        j                         v st	        j                  t              rt	        j                  t              nd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   .done 파일이 없는 경우ru   r   r
   rx   ry   r   rz   r{   r|   N)r   r   r}   ry   r   r   r   r   r   r   r   r    r~   s	            r*   test_scan_no_done_filesz)TestScanDoneFiles.test_scan_no_done_files~   s    L,A--/6{a{a{ass66{ar-   N)rG   rH   rI   rJ   r   r   rK   r-   r*   rs   rs   l   s    %  r-   rs   c                       e Zd ZdZd Zy)TestProcessDoneFilesu   process_done_files() 테스트c                 r   |j                  t        d|       |j                  t        d|dz         |j                  t        d|dz         |j                  t        dt        |             ddd	d
ddd
di}|dz  j                  t	        j
                  |d      d       |dz  j                          |dz  j                          t        j                         }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)"u'   .done 파일 처리 → bot idle 전환ru   rO   rP   rQ   rR   r   rS   r4   rT   rU   z2026-03-17T06:54:36Z)r	   r/   r;   r<   r>   r?   r   rv   r
   r   	processedr   r   r   Nr	   r6   rZ   r[   r\   r_   r`   r/   )r   r   r   rB   rC   rD   r   process_done_filesr   r   r   r   r   r   r   r    rb   rc   )r"   r#   r$   rd   r   r&   r'   r(   r)   re   rf   rg   rh   ri   s                 r*   test_process_done_filesz,TestProcessDoneFiles.test_process_done_files   s   L,AL*=xJ]?]^L*=xJ]?]^L*:CMJ #/:PQ#/:PQ
 
'	'33DJJtA4NY`3a 
*	*113	*	*113 !335	yA~yAyyA **h)<<GGQXGYZvv&x0:F:0F::::0F:::0:::F:::::::vv&x0:F:0F::::0F:::0:::F:::::::r-   N)rG   rH   rI   rJ   r   rK   r-   r*   r   r      s
    (;r-   r   c                   "    e Zd ZdZd Zd Zd Zy)TestScanFailedFilesu   scan_failed_files() 테스트c                    |j                  t        d|       |dz  j                  d       |dz  j                  d       t        j                         }t	        |      }d}||k(  }|st        j                  d|fd||f      d	t        j                         v st        j                  t              rt        j                  t              nd	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   .failed 파일 스캔ru   task-100.failed.{"task_id":"task-100","fail_reason":"QC FAIL"}ztask-200.failedz.{"task_id":"task-200","fail_reason":"QC FAIL"}r;   r
   rx   ry   r   rz   r{   r|   N)r   r   rB   scan_failed_filesry   r   r   r   r   r   r   r   r    r~   s	            r*   test_scan_failed_filesz*TestScanFailedFiles.test_scan_failed_files   s    L,A	%	%112bc	%	%112bc//16{a{a{ass66{ar-   c                    |j                  t        d|       |dz  j                  d       |dz  j                          t        j	                         }t        |      }d}||k(  }|st        j                  d|fd||f      dt        j                         v st        j                  t
              rt        j                  t
              nd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(   .failed.acked 마커가 있으면 제외ru   r   r   task-100.failed.ackedr   r
   rx   ry   r   rz   r{   r|   N)r   r   rB   r   r   ry   r   r   r   r   r   r   r   r    r~   s	            r*   test_scan_failed_excludes_ackedz3TestScanFailedFiles.test_scan_failed_excludes_acked   s    L,A	%	%112bc	+	+224//16{a{a{ass66{ar-   c                 z   |j                  t        d|       t        j                         }t        |      }d}||k(  }|st	        j
                  d|fd||f      dt        j                         v st	        j                  t              rt	        j                  t              nd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   .failed 파일이 없는 경우ru   r   r
   rx   ry   r   rz   r{   r|   N)r   r   r   ry   r   r   r   r   r   r   r   r    r~   s	            r*   test_scan_no_failed_filesz-TestScanFailedFiles.test_scan_no_failed_files   s    L,A//16{a{a{ass66{ar-   N)rG   rH   rI   rJ   r   r   r   rK   r-   r*   r   r      s    '   r-   r   c                   "    e Zd ZdZd Zd Zd Zy)TestProcessFailedFilesu    process_failed_files() 테스트c                    |j                  t        d|       |j                  t        d|dz         |j                  dd       |dz  j                  d       t        j	                         }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}}d}||z  }|j                  }	 |	       }
|
sddt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |	      t        j                  |
      dz  }t        t        j                  |            dx}x}x}	}
y)uH   .failed 파일 처리 - bot token 없으면 알림 실패, rename 안됨ru   rQ   rR   ANU_BOT_TOKENFraisingr   P{"task_id":"task-100","fail_reason":"QC FAIL","timestamp":"2026-04-20T10:00:00"}r   r
   r   r   r   r   r   NMassert %(py7)s
{%(py7)s = %(py5)s
{%(py5)s = (%(py0)s / %(py2)s).exists
}()
}r#   r   py2r   py7)r   r   delenvrB   process_failed_filesr   r   r   r   r   r   r   r    exists)r"   r#   r$   r   r&   r'   r(   r)   rg   r   @py_assert6@py_format8s               r*   &test_process_failed_files_no_bot_tokenz=TestProcessFailedFiles.test_process_failed_files_no_bot_token   s<   L,AL*=xJ]?]^?E:	%	%11  3E  	F 557	yA~yAyyA,6,,6,446466666666666666,66646666666666r-   c                    |j                  t        d|       |j                  t        d|dz         |dz  j                  d       t        j                         }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)u/   .failed 파일 JSON 파싱 실패 시 건너뜀ru   rQ   rR   r   znot json contentr   r
   r   r   r   r   r   N)r   r   rB   r   r   r   r   r   r   r   r   r    )r"   r#   r$   r   r&   r'   r(   r)   s           r*   $test_process_failed_files_json_errorz;TestProcessFailedFiles.test_process_failed_files_json_error   s    L,AL*=xJ]?]^	%	%112DE 557	yA~yAyyAr-   c                 n   |j                  t        d|       |j                  t        d|dz         dt        dt        fd}|j                  t        d|       |dz  j	                  d	       t        j                         }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}}d}||z  }	|	j                  }
 |
       }| }|sddt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |
      t        j                  |      dz  }t        t        j                  |            dx}x}	x}
x}}d}||z  }	|	j                  }
 |
       }|sddt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |
      t        j                  |      dz  }t        t        j                  |            dx}x}	x}
}y)u8   .failed 파일 처리 성공 시 .failed.acked로 renameru   rQ   rR   messagereturnc                 N   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)	NzQC FAIL)in)z%(py1)s in %(py3)sr   )r]   r   r   r   T)r   r   r   r   r   r   r   r    )r   rf   r&   r(   r)   s        r*   	mock_sendzRTestProcessFailedFiles.test_process_failed_files_with_mock_send.<locals>.mock_send   s^    '9''''9'''9''''''''''''''''r-   send_telegram_notificationr   r      r
   r   r   r   r   r   NzQassert not %(py7)s
{%(py7)s = %(py5)s
{%(py5)s = (%(py0)s / %(py2)s).exists
}()
}r#   r   r   r   )r   r   r   boolrB   r   r   r   r   r   r   r   r   r    r   )r"   r#   r$   r   r   r&   r'   r(   r)   rg   r   r   @py_assert8r   r   s                  r*   (test_process_failed_files_with_mock_sendz?TestProcessFailedFiles.test_process_failed_files_with_mock_send   s   L,AL*=xJ]?]^	s 	t 	 	L*F	R	%	%11  3E  	F 557	yA~yAyyA0:H00:088:8:::::::::::H:::H:::0:::8:::::::::::2<22<2::<:<<<<<<<<<<<<<<2<<<:<<<<<<<<<<r-   N)rG   rH   rI   rJ   r   r   r   rK   r-   r*   r   r      s    *7=r-   r   c                       e Zd ZdZd Zy)TestSendTelegramNotificationu&   send_telegram_notification() 테스트c                    |j                  t        dt        d             |j                  dd       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}}y)u    bot token 없으면 False 반환rQ   z/tmp/test-done-protocol.logr   Fr   ztest messagerW   rY   r   r   r   r   N)r   r   r   r   r   r   r   r   r   r   r   r   r    )r"   r$   r   r&   r'   r(   r)   s          r*   test_no_bot_tokenz.TestSendTelegramNotification.test_no_bot_token   s    L*=tDa?bc?E:88Hvvvvr-   N)rG   rH   rI   rJ   r   rK   r-   r*   r   r      s
    0r-   r   __main__z-v)rJ   builtinsr   _pytest.assertion.rewrite	assertionrewriter   	importlibrC   syspathlibr   pytestpathinsertimport_moduler   r   rM   rs   r   r   r   r   rG   main__file__rK   r-   r*   <module>r      s        
   0 1&y&&~6'  ' T( (V   4; ;B   6*= *=Z  zFKK4 ! r-   