
    hi3u                        d dl Zd dlmc mZ d dlZd dlZej                  j                  d ej                  j                  ej                  j                  e      d             d dlZd dlmZ d dl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 G d d      Zy)    Nz..)patchc                   R    e 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)TestParseDurationu!   parse_duration() 함수 테스트c                    ddl m} d} ||      }d}||k(  }|st        j                  d|fd||f      dt	        j
                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      t        j                  |      dz  }d	d
|iz  }t        t        j                  |            dx}x}x}}y)u   '30분간' → 30r   parse_duration   30분간 토론해줘   ==z0%(py4)s
{%(py4)s = %(py0)s(%(py2)s)
} == %(py7)sr   py0py2py4py7assert %(py9)spy9N
discussion_managerr   
@pytest_ar_call_reprcompare@py_builtinslocals_should_repr_global_name	_safereprAssertionError_format_explanationselfr   @py_assert1@py_assert3@py_assert6@py_assert5@py_format8@py_format10s           L/home/jay/workspace/services/multimodel-bot/tests/test_discussion_manager.pytest_parse_minutes_koreanz+TestParseDuration.test_parse_minutes_korean   s    55<~56<"<6"<<<<6"<<<<<<~<<<~<<<5<<<6<<<"<<<<<<<    c                    ddl m} d} ||      }d}||k(  }|st        j                  d|fd||f      dt	        j
                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      t        j                  |      dz  }d	d
|iz  }t        t        j                  |            dx}x}x}}y)u   '30분동안' → 30r   r   u   30분동안 얘기해줘r
   r   r   r   r   r   r   Nr   r   s           r'   test_parse_minutes_korean_dongz0TestParseDuration.test_parse_minutes_korean_dong   s    58?~89?R?9R????9R??????~???~???8???9???R???????r)   c                    ddl m} d} ||      }d}||k(  }|st        j                  d|fd||f      dt	        j
                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      t        j                  |      dz  }d	d
|iz  }t        t        j                  |            dx}x}x}}y)u   '2시간동안' → 120r   r   u   2시간동안 토론해줘x   r   r   r   r   r   r   Nr   r   s           r'   test_parse_hours_koreanz)TestParseDuration.test_parse_hours_korean   s    5:B~:;BsB;sBBBB;sBBBBBB~BBB~BBB:BBB;BBBsBBBBBBBr)   c                    ddl m} d} ||      }d}||k(  }|st        j                  d|fd||f      dt	        j
                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      t        j                  |      dz  }d	d
|iz  }t        t        j                  |            dx}x}x}}y)u   '2시간' → 120r   r   u   2시간 토론해줘r-   r   r   r   r   r   r   Nr   r   s           r'   test_parse_hours_korean_barez.TestParseDuration.test_parse_hours_korean_bare%   s    54<~45<<5<<<<5<<<<<<~<<<~<<<4<<<5<<<<<<<<<<r)   c                    ddl m} d} ||      }d}||k(  }|st        j                  d|fd||f      dt	        j
                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      t        j                  |      dz  }d	d
|iz  }t        t        j                  |            dx}x}x}}y)u   '30min' → 30r   r   zdiscuss for 30minr
   r   r   r   r   r   r   Nr   r   s           r'   test_parse_minutes_englishz,TestParseDuration.test_parse_minutes_english+   s    518~128b82b88882b888888~888~88818882888b8888888r)   c                    ddl m} d} ||      }d}||k(  }|st        j                  d|fd||f      dt	        j
                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      t        j                  |      dz  }d	d
|iz  }t        t        j                  |            dx}x}x}}y)u   '2hour' → 120r   r   ztalk for 2hourr-   r   r   r   r   r   r   Nr   r   s           r'   test_parse_hours_englishz*TestParseDuration.test_parse_hours_english1   s    5.6~./636/36666/3666666~666~666.666/66636666666r)   c                    ddl m} d} ||      }d}||k(  }|st        j                  d|fd||f      dt	        j
                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      t        j                  |      dz  }d	d
|iz  }t        t        j                  |            dx}x}x}}y)u   '2hr' → 120r   r   zdiscuss for 2hrr-   r   r   r   r   r   r   Nr   r   s           r'   test_parse_hours_english_hrz-TestParseDuration.test_parse_hours_english_hr7   s    5/7~/07C70C77770C777777~777~777/7770777C7777777r)   c                    ddl m} d} ||      }d}||k(  }|st        j                  d|fd||f      dt	        j
                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      t        j                  |      dz  }d	d
|iz  }t        t        j                  |            dx}x}x}}y)u   300분 → 180분으로 캡r   r   u   300분간 토론   r   r   r   r   r   r   Nr   r   s           r'   test_max_duration_capz'TestParseDuration.test_max_duration_cap=   s    508~018S81S88881S888888~888~88808881888S8888888r)   c                 l   ddl m}  |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)u   10시간 → 180분으로 캡r   r   u   10시간동안 토론r8   r   z%(py0)s == %(py3)sresultr   py3assert %(py5)spy5Nr   )r    r   r<   @py_assert2r!   @py_format4@py_format6s          r'   test_max_hours_capz$TestParseDuration.test_max_hours_capC   sh    5 78v}vvvr)   c                    ddl m} d} ||      }d}||u }|st        j                  d|fd||f      dt	        j
                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      t        j                  |      dz  }d	d
|iz  }t        t        j                  |            dx}x}x}}y)u   일반 텍스트 → Noner   r   u   안녕하세요 반갑습니다Nisz0%(py4)s
{%(py4)s = %(py0)s(%(py2)s)
} is %(py7)sr   r   r   r   r   r   s           r'   test_no_durationz"TestParseDuration.test_no_durationJ   s    5?H~?@HDH@DHHHH@DHHHHHH~HHH~HHH?HHH@HHHDHHHHHHHr)   c                    ddl m} d} ||      }d}||u }|st        j                  d|fd||f      dt	        j
                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      t        j                  |      dz  }d	d
|iz  }t        t        j                  |            dx}x}x}}y)u   빈 문자열 → Noner   r    NrF   rH   r   r   r   r   r   r   s           r'   test_no_duration_emptyz(TestParseDuration.test_no_duration_emptyP   s    5 )~b!)T)!T))))!T))))))~)))~)))b)))!)))T)))))))r)   N)__name__
__module____qualname____doc__r(   r+   r.   r0   r2   r4   r6   r9   rD   rI   rL    r)   r'   r   r      s?    +=@C=9789I*r)   r   c                   p    e 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d Zd Zd Zd Zd Zy)TestDiscussionManageru%   DiscussionManager 클래스 테스트c                     ddl m}  |       S Nr   DiscussionManagerr   rW   r    rW   s     r'   _make_managerz#TestDiscussionManager._make_manager_       8 ""r)   c                    | j                         }d}|j                  } ||      }d}||u }|st        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                  |      rt        j                  |      ndt        j                  |      t        j                  |      dz  }dd	|iz  }t        t        j                  |            d
x}x}x}}|j                  |d       |j                  } ||      }d}||u }|st        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                  |      rt        j                  |      ndt        j                  |      t        j                  |      dz  }dd	|iz  }t        t        j                  |            d
x}x}x}}y
)u>   유저 메시지를 받으면 토론 모드가 활성화된다d   FrF   zZ%(py5)s
{%(py5)s = %(py2)s
{%(py2)s = %(py0)s.is_discussion_active
}(%(py3)s)
} is %(py8)smgrchat_idr   r   r>   r@   py8assert %(py10)spy10N   토론 시작해줘T)rZ   is_discussion_activer   r   r   r   r   r   r   r   on_user_message	r    r_   r`   r!   @py_assert4@py_assert7r#   @py_format9@py_format11s	            r'   &test_user_message_activates_discussionz<TestDiscussionManager.test_user_message_activates_discussiond   sv     "''9'09E90E99990E999999s999s999'9999999999990999E9999999G%:;''8'08D80D88880D888888s888s888'8888888888880888D8888888r)   c                    ddl m}  |       }d}|j                  |d       |j                  |   }|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>   시간 키워드가 있으면 duration_minutes가 설정된다r   rV   e   r	   r
   r   )z8%(py2)s
{%(py2)s = %(py0)s.duration_minutes
} == %(py5)sstater   r   r@   assert %(py7)sr   Nr   rW   rg   _statesduration_minutesr   r   r   r   r   r   r   r   
r    rW   r_   r`   rp   r!   ri   r"   rC   r%   s
             r'   -test_user_message_with_duration_sets_durationzCTestDiscussionManager.test_user_message_with_duration_sets_durationm   s    8!G%<=G$%%++%++++%++++++u+++u+++%++++++++++r)   c                    ddl m}  |       }d}|j                  |d       |j                  |   }|j                  }d}||u }|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)uG   시간 키워드 없으면 duration_minutes가 None이다 (idle 모드)r   rV   f   re   NrF   )z8%(py2)s
{%(py2)s = %(py0)s.duration_minutes
} is %(py5)srp   rq   rr   r   rs   rv   s
             r'   ,test_user_message_without_duration_sets_nonezBTestDiscussionManager.test_user_message_without_duration_sets_nonex   s    8!G%:;G$%%--%----%------u---u---%----------r)   c                 X   ddl m}  |       }d}|j                  |d       |j                  d   }||j                  |   _        |j                  |      }|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}}|j                  |j                  d         }
|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}}|j                  |j                  d         }|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)uG   봇 응답 후 라운드 로빈 순서대로 다음 턴이 설정된다r   rV   g      토론해줘   r   r;   next_botr=   r?   r@   N   	next_bot2	next_bot3)r   rW   rg   BOT_USERNAMESrt   current_turnon_bot_responser   r   r   r   r   r   r   r   )r    rW   r_   r`   	first_botr   rA   r!   rB   rC   r   r   s               r'   test_round_robin_turn_orderz1TestDiscussionManager.test_round_robin_turn_order   s   8!G^4 &33A6	,5G)&&y1,::1==x=====x=======x===x===========''(9(G(G(JK	-;;A>>y>>>>>y>>>>>>>y>>>y>>>>>>>>>>> ''(9(G(G(JK	-;;A>>y>>>>>y>>>>>>>y>>>y>>>>>>>>>>>r)   c                 j   ddl m}  |       }d}|j                  |d       t        j                         |j                  dz   z
  |j
                  |   _        |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}}|j                   } ||      }	d}
|	|
u }|st        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                  |      rt        j                  |      ndt        j                  |	      t        j                  |
      dz  }dd|iz  }t        t        j                  |            dx}x}	x}}
y)uA   IDLE_TIMEOUT 초과 후 advance_turn() 시 토론이 종료된다r   rV   h   r}   <   NrF   z%(py0)s is %(py3)sr<   r=   r?   r@   Fr^   r_   r`   ra   rc   rd   )r   rW   rg   timeIDLE_TIMEOUTrt   last_user_message_timeadvance_turnr   r   r   r   r   r   r   r   rf   )r    rW   r_   r`   r<   rA   r!   rB   rC   ri   rj   r#   rk   rl   s                 r'   "test_idle_timeout_stops_discussionz8TestDiscussionManager.test_idle_timeout_stops_discussion   sX   8!G^46:iikSEUEUXZEZ6[G3!!#v~vvv''9'09E90E99990E999999s999s999'9999999999990999E9999999r)   c                 `   ddl m}  |       }d}|j                  |d       t        j                         dz
  |j                  |   _        |j                  } |       }d}||u }|st        j                  d|fd||f      d	t        j                         v st        j                  |      rt        j                  |      nd	t        j                  |      t        j                  |      t        j                  |      d
z  }dd|iz  }	t        t        j                  |	            dx}x}x}}y)u9   시간 한정 모드에서는 idle 체크를 무시한다r   rV   i   r	   ih  FrF   zP%(py4)s
{%(py4)s = %(py2)s
{%(py2)s = %(py0)s.check_should_stop
}()
} is %(py7)sr_   r   r   r   N)r   rW   rg   r   rt   r   check_should_stopr   r   r   r   r   r   r   r   
r    rW   r_   r`   r!   r"   r#   r$   r%   r&   s
             r'   test_timed_mode_ignores_idlez2TestDiscussionManager.test_timed_mode_ignores_idle   s    8!G%<=6:iikC6GG3 $$/$&/%/&%////&%//////s///s///$///&///%///////r)   c                 `   ddl m}  |       }d}|j                  |d       t        j                         dz
  |j                  |   _        |j                  } |       }d}||u }|st        j                  d|fd||f      d	t        j                         v st        j                  |      rt        j                  |      nd	t        j                  |      t        j                  |      t        j                  |      d
z  }dd|iz  }	t        t        j                  |	            dx}x}x}}y)uC   시간 한정 모드에서 duration_minutes 초과 시 종료된다r   rV   j   u   1분간 토론해줘r-   TrF   r   r_   r   r   r   N)r   rW   rg   r   rt   
start_timer   r   r   r   r   r   r   r   r   r   s
             r'   $test_timed_mode_stops_after_durationz:TestDiscussionManager.test_timed_mode_stops_after_duration   s    8!G%;<*.))+*;G'$$.$&.$.&$....&$......s...s...$...&...$.......r)   c                    ddl m}  |       }d}|j                  |d       t        j                         dz
  |j                  |   _        t        j                         }|j                  |d       t        j                         }|j                  |   j
                  }||k  }d}||z   }	||	k  }
|r|
st        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t        j                         v st        j                  |      rt        j                  |      ndt        j                  |      dz  }dd|iz  }t        t        j                  |            dx}x}
x}}	y)u9   유저 메시지가 오면 idle 타이머가 리셋된다r   rV   k   r}     u   계속 얘기해줘g{Gz?)<=r   )z%(py0)s <= %(py3)sz%(py3)s <= (%(py4)s + %(py6)s)beforenew_timeafter)r   r>   r   py6r   r   N)r   rW   rg   r   rt   r   r   r   r   r   r   r   r   r   )r    rW   r_   r`   r   r   r   r!   r$   rj   rA   r%   r&   s                r'   #test_user_message_resets_idle_timerz9TestDiscussionManager.test_user_message_resets_idle_timer   s*   8!G^46:iikC6GG3 G%:;		;;w'>>11T1UT\1\11111v\111111v111v111111111111111U111U111T1111111r)   c                    ddl m}  |       }d}|j                  |d       |j                  } ||      }d}||u }|st	        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                  |      rt	        j                  |      nd	t	        j                  |      t	        j                  |      d
z  }dd|iz  }	t        t	        j                  |	            dx}x}x}}|j                          |j                  } ||      }d}||u }|st	        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                  |      rt	        j                  |      nd	t	        j                  |      t	        j                  |      d
z  }dd|iz  }	t        t	        j                  |	            dx}x}x}}y)u6   stop_discussion() 호출 시 상태가 초기화된다r   rV   l   r}   TrF   r^   r_   r`   ra   rc   rd   NF)r   rW   rg   rf   r   r   r   r   r   r   r   r   stop_discussion)
r    rW   r_   r`   r!   ri   rj   r#   rk   rl   s
             r'   !test_stop_discussion_resets_statez7TestDiscussionManager.test_stop_discussion_resets_state   s~   8!G^4''8'08D80D88880D888888s888s888'8888888888880888D8888888''9'09E90E99990E999999s999s999'9999999999990999E9999999r)   c                     ddl m}  |       }d}|j                  |d       |j                  d   }||j                  |   _        |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}}y)uC   토론 모드에서 현재 턴이 자신이면 True를 반환한다r   rV   m   r}   someuserTbot_usernamesender_usernamesender_is_botr`   rF   r   r<   r=   r?   r@   Nr   rW   rg   r   rt   r   should_bot_respondr   r   r   r   r   r   r   r   )
r    rW   r_   r`   my_botr<   rA   r!   rB   rC   s
             r'   1test_should_bot_respond_during_discussion_my_turnzGTestDiscussionManager.test_should_bot_respond_during_discussion_my_turn   s    8!G^4"003,2G)''&	 ( 
 v~vvvr)   c                    ddl m}  |       }d}|j                  |d       |j                  d   |j                  |   _        |j                  |j                  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}}y)uK   토론 모드에서 현재 턴이 자신이 아니면 False를 반환한다r   rV   n   r}   r~   r   Tr   FrF   r   r<   r=   r?   r@   Nr   	r    rW   r_   r`   r<   rA   r!   rB   rC   s	            r'   #test_should_bot_respond_not_my_turnz9TestDiscussionManager.test_should_bot_respond_not_my_turn   s    8!G^4,=,K,KA,NG)''*88;&	 ( 
 vvvvr)   c                    ddl m}  |       }d}|j                  |j                  d   |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}}y)uE   토론 모드가 아닐 때 봇 메시지에는 False를 반환한다r   rV   o   r~   Tr   FrF   r   r<   r=   r?   r@   N)r   rW   r   r   r   r   r   r   r   r   r   r   r   s	            r'   8test_should_bot_respond_non_discussion_bot_message_falsezNTestDiscussionManager.test_should_bot_respond_non_discussion_bot_message_false	  s    8! ''*88;-;;A>	 ( 
 vvvvr)   c                    ddl m}  |       }d}|j                  |d       |j                  d   }||j                  |   _        |j                         }|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)uH   get_next_bot()은 마지막 봇 다음에 첫 번째 봇을 반환한다r   rV   p   r}   r   r;   r   r=   r?   r@   N)r   rW   rg   r   rt   r   get_next_botr   r   r   r   r   r   r   r   )
r    rW   r_   r`   last_botr   rA   r!   rB   rC   s
             r'   test_get_next_bot_wraps_aroundz4TestDiscussionManager.test_get_next_bot_wraps_around  s    8!G^4$2226,4G)##%,::1==x=====x=======x===x===========r)   c                    ddl m}  |       }d}d}|j                  |d       |j                  } ||      }d}||u }|st	        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                  |      rt	        j                  |      nd
t	        j                  |      t	        j                  |      dz  }	dd|	iz  }
t        t	        j                  |
            dx}x}x}}|j                  } ||      }d}||u }|st	        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                  |      rt	        j                  |      ndt	        j                  |      t	        j                  |      dz  }	dd|	iz  }
t        t	        j                  |
            dx}x}x}}y)u9   서로 다른 chat_id는 독립적인 상태를 가진다r   rV         r}   TrF   r^   r_   	chat_id_ara   rc   rd   NF	chat_id_b)r   rW   rg   rf   r   r   r   r   r   r   r   r   )r    rW   r_   r   r   r!   ri   rj   r#   rk   rl   s              r'   %test_multiple_chats_independent_statez;TestDiscussionManager.test_multiple_chats_independent_state'  sw   8!		I~6'':'	2:d:2d::::2d::::::s:::s:::'::::::	:::	:::2:::d:::::::'';'	2;e;2e;;;;2e;;;;;;s;;;s;;;';;;;;;	;;;	;;;2;;;e;;;;;;;r)   c                    ddl m}  |       }d}|j                  |d       t        j                         |j                  |   _        |j                  d   |j                  |   _        |j                         }|j                  }||v }|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t        j                  |      d	z  }d
d|iz  }t        t        j                   |            dx}}y)uG   토론 진행 중 advance_turn()은 다음 봇 username을 반환한다r   rV   q   r}   )in)z5%(py0)s in %(py4)s
{%(py4)s = %(py2)s.BOT_USERNAMES
}r<   rW   )r   r   r   zassert %(py6)sr   N)r   rW   rg   r   rt   r   r   r   r   r   r   r   r   r   r   r   r   )	r    rW   r_   r`   r<   r"   r!   @py_format5@py_format7s	            r'   .test_advance_turn_returns_next_bot_when_activezDTestDiscussionManager.test_advance_turn_returns_next_bot_when_active3  s    8!G^46:iikG3,=,K,KA,NG)!!#*888v88888v8888888v888v888888*888*88888888888r)   N)rM   rN   rO   rP   rZ   rm   rw   rz   r   r   r   r   r   r   r   r   r   r   r   r   rQ   r)   r'   rS   rS   \   sU    /#
9	,	.?.:0/2&:&$ >
<9r)   rS   c                   P    e Zd ZdZddededefdZddedefd	Zd
 Z	d Z
d Zd Zy)TestShouldRespondBotMessagesuV   bot_utils.should_respond()의 봇 메시지 처리 테스트 (수정된 동작 반영)user_idis_botusernamec                 J    ddl m}  |       }||_        ||_        ||_        |S Nr   	MagicMock)unittest.mockr   idr   r   )r    r   r   r   r   users         r'   
_make_userz'TestShouldRespondBotMessages._make_userK  s&    +{ r)   Ntext	chat_typec                     ddl m}m}  |       }||_        ||_         |       |_        ||j
                  _        d |_        |xs g |_         |       |_	        |S )Nr   )	AsyncMockr   )
r   r   r   r   	from_userchattypereply_to_messageentities
reply_text)r    r   r   r   r   r   r   msgs           r'   _make_messagez*TestShouldRespondBotMessages._make_messageT  sO    6k!;!#~2"
r)   c                 ^    ddl m}  |       }||_        ||_        |j                  |_        |S r   )r   r   messageeffective_messager   effective_user)r    r   r   updates       r'   _make_updatez)TestShouldRespondBotMessages._make_updatea  s.    + #*  ' 1 1r)   c                 Z   ddl m} | j                  ddd      }t        ddg	      j	                         }d
|_        d|_        t        d      |_        | j                  d|d|g      }| 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}}y)uS   자기 자신(같은 username)이 보낸 봇 메시지에는 응답하지 않는다r   should_respond  Tmybotr   r   r   zunittest.mockr   )fromlistmention@mybot   @mybot 안녕groupr   r   r   r   [r   owner_user_idFrF   r   r<   r=   r?   r@   N)	bot_utilsr   r   
__import__r   r   offsetlenlengthr   r   r   r   r   r   r   r   r   r   )r    r   self_botentityr   r   r<   rA   r!   rB   rC   s              r'   #test_self_bot_message_returns_falsez@TestShouldRespondBotMessages.test_self_bot_message_returns_falsej  s    , ??3tg?NO{mDNNPH$$ X	 % 
 ""7+WIVvvvvr)   c                 <   ddl m} ddlm} | j	                  ddd      } |       }d|_        d|_        t        d	      |_        | j                  d
|d|g      }| 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}	}y)uO   다른 봇이 @멘션한 메시지에는 응답해야 한다 (수정된 동작)r   r   r   x  Totherbotr   r   r   r   r   r   r   r   r   rF   r   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    r   r   	other_botr   r   r   r<   rA   r!   rB   rC   s               r'   0test_other_bot_message_with_mention_returns_truezMTestShouldRespondBotMessages.test_other_bot_message_with_mention_returns_true  s    +,OOCzOR	H$$ X	 % 
 ""7+WIVv~vvvr)   c                 ^   ddl m} ddlm} | j	                  ddd      } |       }d|_        d|_        t        d	      |_        | j                  d
|d|g      }d|j                  _        | 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}	}y)uH   다른 봇이지만 sender.username이 None이면 응답하지 않는다r   r   r   r  TNr   r   r   r   r   r   r   r   r   rF   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  s               r'   *test_other_bot_username_none_returns_falsezGTestShouldRespondBotMessages.test_other_bot_username_none_returns_false  s    +,OOCtOL	H$$ X	 % 
 &*"""7+WIV v~vvvr)   )Ftestuser)r   N)rM   rN   rO   rP   intboolstrr   r   r   r  r  r	  rQ   r)   r'   r   r   H  sF    `# t s # S ,0r)   r   c                   4    e Zd ZdZd Zd Zd Zd Zd Zd Z	y)	TestDetectCodeAnalysisu'   detect_code_analysis() 함수 테스트c                    ddl m} d} ||      }d}||u }|st        j                  d|fd||f      dt	        j
                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      t        j                  |      dz  }d	d
|iz  }t        t        j                  |            dx}x}x}}y)uE   '코드 구조를 분석해줘' → True (코드, 분석 2개 매칭)r   detect_code_analysis   코드 구조를 분석해줘TrF   rH   r  r   r   r   N
r   r  r   r   r   r   r   r   r   r   r    r  r!   r"   r#   r$   r%   r&   s           r'   +test_detect_code_analysis_with_two_keywordszBTestDetectCodeAnalysis.test_detect_code_analysis_with_two_keywords  s    ;$CL#$CDLLDLLLLDLLLLLL#LLL#LLL$CLLLDLLLLLLLLLLr)   c                    ddl m} d} ||      }d}||u }|st        j                  d|fd||f      dt	        j
                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      t        j                  |      dz  }d	d
|iz  }t        t        j                  |            dx}x}x}}y)u-   .py 파일 읽어줘 → True (경로 패턴)r   r  u   .py 파일 읽어줘TrF   rH   r  r   r   r   Nr  r  s           r'   #test_detect_code_analysis_with_pathz:TestDetectCodeAnalysis.test_detect_code_analysis_with_path  s    ;$:C#$:;CtC;tCCCC;tCCCCCC#CCC#CCC$:CCC;CCCtCCCCCCCr)   c                    ddl m} d} ||      }d}||u }|st        j                  d|fd||f      dt	        j
                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      t        j                  |      dz  }d	d
|iz  }t        t        j                  |            dx}x}x}}y)u9   /home/jay/workspace 코드 → True (프로젝트 경로)r   r  u   /home/jay/workspace 코드TrF   rH   r  r   r   r   Nr  r  s           r'   +test_detect_code_analysis_with_project_pathzBTestDetectCodeAnalysis.test_detect_code_analysis_with_project_path  s    ;$@I#$@AITIATIIIIATIIIIII#III#III$@IIIAIIITIIIIIIIr)   c                    ddl m} d} ||      }d}||u }|st        j                  d|fd||f      dt	        j
                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      t        j                  |      dz  }d	d
|iz  }t        t        j                  |            dx}x}x}}y)u!   '오늘 날씨 어때?' → Falser   r     오늘 날씨 어때?FrF   rH   r  r   r   r   Nr  r  s           r'   (test_detect_code_analysis_normal_messagez?TestDetectCodeAnalysis.test_detect_code_analysis_normal_message  s    ;$;E#$;<EE<EEEE<EEEEEE#EEE#EEE$;EEE<EEEEEEEEEEr)   c                    ddl m} d} ||      }d}||u }|st        j                  d|fd||f      dt	        j
                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      t        j                  |      dz  }d	d
|iz  }t        t        j                  |            dx}x}x}}y)u*   '코드 좋아' → False (1개만 매칭)r   r  u   코드 좋아FrF   rH   r  r   r   r   Nr  r  s           r'   (test_detect_code_analysis_single_keywordz?TestDetectCodeAnalysis.test_detect_code_analysis_single_keyword  s    ;$3=#O4==4====4======#===#===O===4==========r)   c                    ddl m} d} ||      }d}||u }|st        j                  d|fd||f      dt	        j
                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      t        j                  |      dz  }d	d
|iz  }t        t        j                  |            dx}x}x}}y)u.   'analyze the function implementation' → Truer   r  z#analyze the function implementationTrF   rH   r  r   r   r   Nr  r  s           r'   !test_detect_code_analysis_englishz8TestDetectCodeAnalysis.test_detect_code_analysis_english  s    ;$IR#$IJRdRJdRRRRJdRRRRRR#RRR#RRR$IRRRJRRRdRRRRRRRr)   N)
rM   rN   rO   rP   r  r  r  r  r  r!  rQ   r)   r'   r  r    s(    1MDJF>Sr)   r  c                   :    e Zd ZdZd Zd Zd Zd Zd Zd Z	d Z
y	)
!TestDiscussionManagerCodeAnalysisu0   DiscussionManager 코드 분석 모드 테스트c                     ddl m}  |       S rU   rX   rY   s     r'   rZ   z/TestDiscussionManagerCodeAnalysis._make_manager  r[   r)   c                    | j                         }d}|j                  |d       |j                  |   }|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
)uJ   코드 분석 메시지 시 current_turn이 'claude_view_bot'이어야 함i,  r  claude_view_botr   )z4%(py2)s
{%(py2)s = %(py0)s.current_turn
} == %(py5)srp   rq   rr   r   N)rZ   rg   rt   r   r   r   r   r   r   r   r   r   	r    r_   r`   rp   r!   ri   r"   rC   r%   s	            r'   )test_code_analysis_mode_sets_claude_firstzKTestDiscussionManagerCodeAnalysis.test_code_analysis_mode_sets_claude_first  s      "G%DEG$!!6%66!%66666!%6666666u666u666!666%66666666r)   c                    | j                         }d}|j                  |d       |j                  |   }|j                  }d}||u }|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<   코드 분석 메시지 시 state.code_analysis_mode == Truei-  r  TrF   z:%(py2)s
{%(py2)s = %(py0)s.code_analysis_mode
} is %(py5)srp   rq   rr   r   NrZ   rg   rt   code_analysis_moder   r   r   r   r   r   r   r   r'  s	            r'    test_code_analysis_mode_flag_setzBTestDiscussionManagerCodeAnalysis.test_code_analysis_mode_flag_set  s      "G%DEG$''/4/'4////'4//////u///u///'///4///////r)   c                    | j                         }d}|j                  |d       |j                  |   }|j                  }d}||u }|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
)u6   일반 메시지 시 state.code_analysis_mode == Falsei.  r  FrF   r*  rp   rq   rr   r   Nr+  r'  s	            r'   )test_normal_message_no_code_analysis_modezKTestDiscussionManagerCodeAnalysis.test_normal_message_no_code_analysis_mode  s      "G%<=G$''050'50000'5000000u000u000'00050000000r)   c                    | j                         }d}|j                  |d       |j                  } ||      }d}||u }|st        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                  |      rt        j                  |      ndt        j                  |      t        j                  |      dz  }d	d
|iz  }t        t        j                  |            dx}x}x}}y)u/   is_code_analysis_mode() 메서드 동작 확인i/  r  TrF   )z[%(py5)s
{%(py5)s = %(py2)s
{%(py2)s = %(py0)s.is_code_analysis_mode
}(%(py3)s)
} is %(py8)sr_   r`   ra   rc   rd   N)rZ   rg   is_code_analysis_moder   r   r   r   r   r   r   r   rh   s	            r'   'test_is_code_analysis_mode_returns_truezITestDiscussionManagerCodeAnalysis.test_is_code_analysis_mode_returns_true
  s      "G%DE((9(19T91T99991T999999s999s999(9999999999991999T9999999r)   c                    | j                         }|j                  }d} ||      }d}||u }|st        j                  d|fd||f      dt	        j
                         v st        j                  |      rt        j                  |      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$   존재하지 않는 chat_id면 False韆 FrF   )z[%(py6)s
{%(py6)s = %(py2)s
{%(py2)s = %(py0)s.is_code_analysis_mode
}(%(py4)s)
} is %(py9)sr_   r   r   r   r   r   assert %(py11)spy11N)
rZ   r1  r   r   r   r   r   r   r   r   	r    r_   r!   r"   r$   @py_assert8rj   r&   @py_format12s	            r'   5test_is_code_analysis_mode_returns_false_unknown_chatzWTestDiscussionManagerCodeAnalysis.test_is_code_analysis_mode_returns_false_unknown_chat  s      "((88(/858/58888/5888888s888s888(888888/888588888888r)   c                    | j                         }d}d}|j                  }|j                  |d       |j                  }d}||z   }||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                  |      rt        j                  |      ndt        j                  |      d	z  }	d
d|	iz  }
t        t        j                  |
            dx}x}x}}|j                          |j                  |d       |j                  }d}||z   }||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                  |      rt        j                  |      ndt        j                  |      d	z  }	d
d|	iz  }
t        t        j                  |
            dx}x}x}}y)u4   _start_index가 코드 분석과 무관하게 증가i0  i1  r  r~   r   )z@%(py2)s
{%(py2)s = %(py0)s._start_index
} == (%(py4)s + %(py6)s)r_   initial_index)r   r   r   r   r   r   Nr  r   )rZ   _start_indexrg   r   r   r   r   r   r   r   r   r   )r    r_   r   r   r=  r!   r$   rj   r"   r%   r&   s              r'   3test_code_analysis_mode_does_not_change_start_indexzUTestDiscussionManagerCodeAnalysis.test_code_analysis_mode_does_not_change_start_index  s     "		((I'FG414=1#44#44444#4444444s444s444444444=444=44414444444I'>?414=1#44#44444#4444444s444s444444444=444=44414444444r)   N)rM   rN   rO   rP   rZ   r(  r-  r/  r2  r;  r?  rQ   r)   r'   r#  r#    s(    :#
701:95r)   r#  c                   R    e 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)TestDiscussionPhaseu/   DiscussionPhase + get_current_phase() 테스트c                     ddl m}  |       S rU   rX   rY   s     r'   rZ   z!TestDiscussionPhase._make_manager/  r[   r)   c                    ddl m} |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 )Nr   DiscussionPhasediverger   )z/%(py2)s
{%(py2)s = %(py0)s.DIVERGE
} == %(py5)srE  rq   rr   r   converge)z0%(py2)s
{%(py2)s = %(py0)s.CONVERGE
} == %(py5)s	consensus)z1%(py2)s
{%(py2)s = %(py0)s.CONSENSUS
} == %(py5)s)r   rE  DIVERGEr   r   r   r   r   r   r   r   CONVERGE	CONSENSUS)r    rE  r!   ri   r"   rC   r%   s          r'   test_phase_enum_valuesz*TestDiscussionPhase.test_phase_enum_values4  s[   6&&3)3&)3333&)333333333333&333)3333333''5:5':5555':555555555555'555:5555555((7K7(K7777(K777777777777(777K7777777r)   c           	      >   | j                         }d}|j                  |d       ddlm} |j                  } ||      }|j
                  }||k(  }|sCt        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                  |      rt        j                  |      ndt        j                  |      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}x}x}}y)u   idle 모드 시작 시 DIVERGEr   r}   r   rD  r   zt%(py5)s
{%(py5)s = %(py2)s
{%(py2)s = %(py0)s.get_current_phase
}(%(py3)s)
} == %(py9)s
{%(py9)s = %(py7)s.DIVERGE
}r_   r`   rE  r   r   r>   r@   r   r   r6  r7  N)rZ   rg   r   rE  get_current_phaserI  r   r   r   r   r   r   r   r   
r    r_   r`   rE  r!   ri   r9  r#   r&   r:  s
             r'   'test_initial_phase_is_diverge_idle_modez;TestDiscussionPhase.test_initial_phase_is_diverge_idle_mode;  s      "G^46$$H$W-H1H1HH-1HHHHH-1HHHHHHHsHHHsHHH$HHHHHHWHHHWHHH-HHHHHHHHHHHH1HHHHHHHHr)   c           	      f   | j                         }d}|j                  |d       d|j                  |   _        ddlm} |j                  } ||      }|j                  }||k(  }|sCt        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                  |      rt        j                  |      nd	t        j                  |      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}x}x}}y)u&   idle 모드: 4라운드에서 CONVERGEi  r}      r   rD  r   zu%(py5)s
{%(py5)s = %(py2)s
{%(py2)s = %(py0)s.get_current_phase
}(%(py3)s)
} == %(py9)s
{%(py9)s = %(py7)s.CONVERGE
}r_   r`   rE  rO  r6  r7  N)rZ   rg   rt   round_countr   rE  rP  rJ  r   r   r   r   r   r   r   r   rQ  s
             r'   "test_idle_mode_converge_at_round_4z6TestDiscussionPhase.test_idle_mode_converge_at_round_4D  s	     "G^4+,G(6$$I$W-I1I1II-1IIIII-1IIIIIIIsIIIsIII$IIIIIIWIIIWIII-IIIIIIIIIIII1IIIIIIIIr)   c           	      f   | j                         }d}|j                  |d       d|j                  |   _        ddlm} |j                  } ||      }|j                  }||k(  }|sCt        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                  |      rt        j                  |      nd	t        j                  |      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}x}x}}y)u'   idle 모드: 7라운드에서 CONSENSUSi  r}      r   rD  r   zv%(py5)s
{%(py5)s = %(py2)s
{%(py2)s = %(py0)s.get_current_phase
}(%(py3)s)
} == %(py9)s
{%(py9)s = %(py7)s.CONSENSUS
}r_   r`   rE  rO  r6  r7  N)rZ   rg   rt   rV  r   rE  rP  rK  r   r   r   r   r   r   r   r   rQ  s
             r'   #test_idle_mode_consensus_at_round_7z7TestDiscussionPhase.test_idle_mode_consensus_at_round_7N  s	     "G^4+,G(6$$J$W-J1J1JJ-1JJJJJ-1JJJJJJJsJJJsJJJ$JJJJJJWJJJWJJJ-JJJJJJJJJJJJ1JJJJJJJJr)   c           	      F   ddl }| j                         }d}|j                  |d       ddlm} |j
                  } ||      }|j                  }||k(  }|sCt        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                  |      rt        j                  |      nd	t        j                  |      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}x}x}}y)u'   시간 모드: 초기(0~60%)에 DIVERGEr   Ni     10분간 토론해줘rD  r   rN  r_   r`   rE  rO  r6  r7  )r   rZ   rg   r   rE  rP  rI  r   r   r   r   r   r   r   r   r    r   r_   r`   rE  r!   ri   r9  r#   r&   r:  s              r'   test_timed_mode_diverge_earlyz1TestDiscussionPhase.test_timed_mode_diverge_earlyX  s      "G%<=6$$H$W-H1H1HH-1HHHHH-1HHHHHHHsHHHsHHH$HHHHHHWHHHWHHH-HHHHHHHHHHHH1HHHHHHHHr)   c           	         ddl }| j                         }d}|j                  |d        |j                          dz
  |j                  |   _        ddlm} |j                  } ||      }|j                  }||k(  }|sCt        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                  |      rt        j                  |      nd
t        j                  |      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}x}x}}y)u!   시간 모드: 70%에서 CONVERGEr   Ni  r]  i  rD  r   rU  r_   r`   rE  rO  r6  r7  )r   rZ   rg   rt   r   r   rE  rP  rJ  r   r   r   r   r   r   r   r   r^  s              r'   &test_timed_mode_converge_at_70_percentz:TestDiscussionPhase.test_timed_mode_converge_at_70_percentd  s     "G%<=*3$))+*;G'6$$I$W-I1I1II-1IIIII-1IIIIIIIsIIIsIII$IIIIIIWIIIWIII-IIIIIIIIIIII1IIIIIIIIr)   c           	         ddl }| j                         }d}|j                  |d        |j                          dz
  |j                  |   _        ddlm} |j                  } ||      }|j                  }||k(  }|sCt        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                  |      rt        j                  |      nd
t        j                  |      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}x}x}}y)u"   시간 모드: 95%에서 CONSENSUSr   Ni  r]  i:  rD  r   rZ  r_   r`   rE  rO  r6  r7  )r   rZ   rg   rt   r   r   rE  rP  rK  r   r   r   r   r   r   r   r   r^  s              r'   'test_timed_mode_consensus_at_95_percentz;TestDiscussionPhase.test_timed_mode_consensus_at_95_percentq  s     "G%<=*3$))+*;G'6$$J$W-J1J1JJ-1JJJJJ-1JJJJJJJsJJJsJJJ$JJJJJJWJJJWJJJ-JJJJJJJJJJJJ1JJJJJJJJr)   c                 D   | j                         }d}|j                  |d       |j                  |   j                  }|j	                  |      }|j                  |   }|j
                  }d}||k(  }|st        j                  d|fd||f      t        j                  |      t        j                  |      t        j                  |      dz  }	dd|	iz  }
t        t        j                  |
            d	x}x}x}}|j	                  |      }|j                  |   }|j
                  }d}||k(  }|st        j                  d|fd||f      t        j                  |      t        j                  |      t        j                  |      dz  }	dd|	iz  }
t        t        j                  |
            d	x}x}x}}|j	                  |       |j                  |   }|j
                  }d
}||k(  }|st        j                  d|fd||f      t        j                  |      t        j                  |      t        j                  |      dz  }	dd|	iz  }
t        t        j                  |
            d	x}x}x}}|j                  |   }|j                  }d}||k(  }|st        j                  d|fd||f      t        j                  |      t        j                  |      t        j                  |      dz  }	dd|	iz  }
t        t        j                  |
            d	x}x}x}}y	)u'   3봇 응답 후 round_count가 1 증가i  r}   r   r   z3%(py3)s
{%(py3)s = %(py1)s.round_count
} == %(py6)spy1r>   r   assert %(py8)srb   Nr~   z:%(py3)s
{%(py3)s = %(py1)s.bot_response_count
} == %(py6)s)rZ   rg   rt   r   r   rV  r   r   r   r   r   bot_response_count)r    r_   r`   r   bot2@py_assert0rA   r$   ri   r   rk   bot3s               r'   1test_round_count_increments_after_3_bot_responseszETestDiscussionPhase.test_round_count_increments_after_3_bot_responses~  s!     "G^4KK(55	 ""9-{{7#4#//414/14444/1444#444/44414444444""4({{7#4#//414/14444/1444#444/44414444444D!{{7#4#//414/14444/1444#444/44414444444{{7#;#66;!;6!;;;;6!;;;#;;;6;;;!;;;;;;;r)   c                 l   | j                         }d}|j                  |d       d|j                  |   _        d|j                  |   _        |j                          |j                  |   }|j                  }d}||k(  }|st        j                  d|fd||f      t        j                  |      t        j                  |      t        j                  |      dz  }d	d
|iz  }t        t        j                  |            dx}x}x}}|j                  |   }|j                  }d}||k(  }|st        j                  d|fd||f      t        j                  |      t        j                  |      t        j                  |      dz  }d	d
|iz  }t        t        j                  |            dx}x}x}}y)u-   stop_discussion()은 round_count도 초기화i  r}      r   r   r   re  rf  rh  rb   Nri  )rZ   rg   rt   rV  rj  r   r   r   r   r   r   	r    r_   r`   rl  rA   r$   ri   r   rk   s	            r'   'test_stop_discussion_resets_round_countz;TestDiscussionPhase.test_stop_discussion_resets_round_count  s/     "G^4+,G(23G/{{7#4#//414/14444/1444#444/44414444444{{7#;#66;!;6!;;;;6!;;;#;;;6;;;!;;;;;;;r)   c           	         | j                         }ddlm} |j                  }d} ||      }|j                  }||k(  }|st        j                  d|fd||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      t        j                  |      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}x}x}x}}y)u0   비활성 chat에서도 기본값 DIVERGE 반환r   rD  r   r   )zv%(py6)s
{%(py6)s = %(py2)s
{%(py2)s = %(py0)s.get_current_phase
}(%(py4)s)
} == %(py10)s
{%(py10)s = %(py8)s.DIVERGE
}r_   rE  )r   r   r   r   rb   rd   zassert %(py12)spy12N)rZ   r   rE  rP  rI  r   r   r   r   r   r   r   r   )
r    r_   rE  r!   r"   r$   @py_assert9rj   rl   @py_format13s
             r'   "test_inactive_chat_returns_divergez6TestDiscussionPhase.test_inactive_chat_returns_diverge  s      "6$$DSD$S)D_-D-DD)-DDDDD)-DDDDDDDsDDDsDDD$DDDSDDD)DDDDDD_DDD_DDD-DDDDDDDDDr)   N)rM   rN   rO   rP   rZ   rL  rR  rW  r[  r_  ra  rc  rn  rr  rw  rQ   r)   r'   rA  rA  ,  sC    9#
8IJK
IJK<$	<Er)   rA  c                   :    e Zd ZdZd Zd Zd Zd Zd Zd Z	d Z
y	)
TestDiscussionManagerChainGuardu0   DiscussionManager 체인 중복 방지 테스트c                     ddl m}  |       S rU   rX   rY   s     r'   rZ   z-TestDiscussionManagerChainGuard._make_manager  r[   r)   c                    | j                         }|j                  }d} ||      }d}||u }|st        j                  d|fd||f      dt	        j
                         v st        j                  |      rt        j                  |      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   기본값은 Falser]   FrF   zV%(py6)s
{%(py6)s = %(py2)s
{%(py2)s = %(py0)s.is_chain_running
}(%(py4)s)
} is %(py9)sr_   r5  r6  r7  N)
rZ   is_chain_runningr   r   r   r   r   r   r   r   r8  s	            r'    test_chain_running_default_falsez@TestDiscussionManagerChainGuard.test_chain_running_default_false  s      "##1C1#C(1E1(E1111(E111111s111s111#111C111(111E11111111r)   c                 B   | j                         }|j                  dd       |j                  }d} ||      }d}||u }|st        j                  d|fd||f      dt        j                         v st        j                  |      rt        j                  |      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	)
u1   set_chain_running(True) 후 is_chain_running Truer]   TrF   r|  r_   r5  r6  r7  NrZ   set_chain_runningr}  r   r   r   r   r   r   r   r   r8  s	            r'   test_set_chain_running_truez;TestDiscussionManagerChainGuard.test_set_chain_running_true  s      "c4(##0C0#C(0D0(D0000(D000000s000s000#000C000(000D00000000r)   c                 f   | j                         }|j                  dd       |j                  dd       |j                  }d} ||      }d}||u }|st        j                  d|fd||f      dt        j                         v st        j                  |      rt        j                  |      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
)u3   set_chain_running(False) 후 is_chain_running Falser]   TFrF   r|  r_   r5  r6  r7  Nr  r8  s	            r'   test_set_chain_running_falsez<TestDiscussionManagerChainGuard.test_set_chain_running_false  s      "c4(c5)##1C1#C(1E1(E1111(E111111s111s111#111C111(111E11111111r)   c                    | j                         }d}|j                  |d       |j                  |d       |j                          |j                  } ||      }d}||u }|st        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                  |      rt        j                  |      ndt        j                  |      t        j                  |      d	z  }d
d|iz  }t        t        j                  |            dx}x}x}}y)u0   stop_discussion() 시 chain_running도 초기화i  r}   TFrF   )zV%(py5)s
{%(py5)s = %(py2)s
{%(py2)s = %(py0)s.is_chain_running
}(%(py3)s)
} is %(py8)sr_   r`   ra   rc   rd   N)rZ   rg   r  r   r}  r   r   r   r   r   r   r   r   rh   s	            r'   )test_stop_discussion_resets_chain_runningzITestDiscussionManagerChainGuard.test_stop_discussion_resets_chain_running  s      "G^4gt,##5#G,55,5555,555555s555s555#555555G555G555,5555555555r)   c                    | j                         }|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}}y
)u4   새 토론 시작 시 on_user_message는 True 반환r]   r}   TrF   r   r<   r=   r?   r@   N
rZ   rg   r   r   r   r   r   r   r   r   r    r_   r<   rA   r!   rB   rC   s          r'   4test_on_user_message_returns_true_for_new_discussionzTTestDiscussionManagerChainGuard.test_on_user_message_returns_true_for_new_discussion  sz      "$$S.9v~vvvr)   c                    | j                         }|j                  dd       |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}}y)u:   이미 활성 토론 중 유저 메시지 시 False 반환r]   r}   u   계속해줘FrF   r   r<   r=   r?   r@   Nr  r  s          r'   8test_on_user_message_returns_false_for_active_discussionzXTestDiscussionManagerChainGuard.test_on_user_message_returns_false_for_active_discussion  s      "C0$$S.9vvvvr)   N)rM   rN   rO   rP   rZ   r~  r  r  r  r  r  rQ   r)   r'   ry  ry    s(    :#
2
126r)   ry  c                   X    e 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d Zy)TestDeepModeu%   --deep 모드 + codex_model 테스트c                     ddl m}  |       S rU   rX   rY   s     r'   rZ   zTestDeepMode._make_manager  r[   r)   c                    | j                         }d}|j                  |d       |j                  |   }|j                  }d}||k(  }|st	        j
                  d|fd||f      t	        j                  |      t	        j                  |      t	        j                  |      dz  }dd|iz  }t        t	        j                  |            d	x}x}x}}y	)
u(   기본 codex_model은 gpt-5.1-codex-miniiX  r}   gpt-5.1-codex-minir   z3%(py3)s
{%(py3)s = %(py1)s.codex_model
} == %(py6)srf  rh  rb   N	rZ   rg   rt   codex_modelr   r   r   r   r   rq  s	            r'    test_default_codex_model_is_miniz-TestDeepMode.test_default_codex_model_is_mini  s      "G^4{{7#G#//G3GG/3GGGGG/3GGGG#GGG/GGG3GGGGGGGGr)   c                    | j                         }d}|j                  |d       |j                  |   }|j                  }d}||k(  }|st	        j
                  d|fd||f      t	        j                  |      t	        j                  |      t	        j                  |      dz  }dd|iz  }t        t	        j                  |            d	x}x}x}}y	)
u8   --deep 포함 시 codex_model이 gpt-5.2-codex로 설정iY  u!   --deep 이 주제를 토론해줘gpt-5.2-codexr   r  rf  rh  rb   Nr  rq  s	            r'   test_deep_flag_sets_codex_modelz,TestDeepMode.test_deep_flag_sets_codex_model  s      "G%HI{{7#B#//B?B/?BBBB/?BBB#BBB/BBB?BBBBBBBr)   c                    | j                         }d}|j                  |d       |j                  |   }|j                  }d}||u }|st	        j
                  d|fd||f      t	        j                  |      t	        j                  |      t	        j                  |      dz  }dd|iz  }t        t	        j                  |            dx}x}x}}y)	uS   --deep 플래그가 제거된 후 duration 파싱 및 코드분석 감지에 사용iZ  u   --deep 일반 토론NrF   )z8%(py3)s
{%(py3)s = %(py1)s.duration_minutes
} is %(py6)srf  rh  rb   )	rZ   rg   rt   ru   r   r   r   r   r   rq  s	            r'   $test_deep_flag_stripped_from_messagez1TestDeepMode.test_deep_flag_stripped_from_message  s      "G%;<{{7#<#44<<4<<<<4<<<#<<<4<<<<<<<<<<r)   c                    | j                         }d}|j                  |d       |j                  |   }|j                  }d}||k(  }|st	        j
                  d|fd||f      t	        j                  |      t	        j                  |      t	        j                  |      dz  }dd|iz  }t        t	        j                  |            d	x}x}x}}|j                  |   }|j                  }d
}||k(  }|st	        j
                  d|fd||f      t	        j                  |      t	        j                  |      t	        j                  |      dz  }dd|iz  }t        t	        j                  |            d	x}x}x}}y	)u(   --deep과 시간 키워드 동시 사용i[  u   --deep 30분간 토론해줘r  r   r  rf  rh  rb   Nr
   )z8%(py3)s
{%(py3)s = %(py1)s.duration_minutes
} == %(py6)s)
rZ   rg   rt   r  r   r   r   r   r   ru   rq  s	            r'   test_deep_flag_with_durationz)TestDeepMode.test_deep_flag_with_duration  s     "G%CD{{7#B#//B?B/?BBBB/?BBB#BBB/BBB?BBBBBBB{{7#:#44::4::::4:::#:::4::::::::::r)   c                    | j                         }d}|j                  |d       |j                  } ||      }d}||k(  }|st        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                  |      rt        j                  |      ndt        j                  |      t        j                  |      dz  }d	d
|iz  }t        t        j                  |            dx}x}x}}y)u,   get_codex_model()이 올바른 모델 반환i\     --deep 토론r  r   zU%(py5)s
{%(py5)s = %(py2)s
{%(py2)s = %(py0)s.get_codex_model
}(%(py3)s)
} == %(py8)sr_   r`   ra   rc   rd   NrZ   rg   get_codex_modelr   r   r   r   r   r   r   r   rh   s	            r'   "test_get_codex_model_returns_modelz/TestDeepMode.test_get_codex_model_returns_model  s      "G_5"">"7+>>+>>>>+>>>>>>s>>>s>>>">>>>>>7>>>7>>>+>>>>>>>>>>r)   c                    | j                         }d}|j                  |d       |j                  } ||      }d}||k(  }|st        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                  |      rt        j                  |      ndt        j                  |      t        j                  |      dz  }d	d
|iz  }t        t        j                  |            dx}x}x}}y)u%   get_codex_model()이 기본값 반환i]  u   일반 토론r  r   r  r_   r`   ra   rc   rd   Nr  rh   s	            r'   test_get_codex_model_defaultz)TestDeepMode.test_get_codex_model_default  s      "G_5""C"7+C/CC+/CCCCC+/CCCCCCCsCCCsCCC"CCCCCC7CCC7CCC+CCC/CCCCCCCCr)   c                     | j                         }|j                  }d} ||      }d}||k(  }|st        j                  d|fd||f      dt	        j
                         v st        j                  |      rt        j                  |      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	)
u6   존재하지 않는 chat_id에 대해 기본값 반환r4  r  r   )zU%(py6)s
{%(py6)s = %(py2)s
{%(py2)s = %(py0)s.get_codex_model
}(%(py4)s)
} == %(py9)sr_   r5  r6  r7  N)
rZ   r  r   r   r   r   r   r   r   r   r8  s	            r'   !test_get_codex_model_unknown_chatz.TestDeepMode.test_get_codex_model_unknown_chat  s      """A5A"5)A-AA)-AAAAA)-AAAAAAAsAAAsAAA"AAA5AAA)AAA-AAAAAAAAAr)   c                    | j                         }d}|j                  |d       |j                  |   }|j                  }d}||k(  }|st	        j
                  d|fd||f      t	        j                  |      t	        j                  |      t	        j                  |      dz  }dd|iz  }t        t	        j                  |            d	x}x}x}}|j                          |j                  |   }|j                  }d
}||k(  }|st	        j
                  d|fd||f      t	        j                  |      t	        j                  |      t	        j                  |      dz  }dd|iz  }t        t	        j                  |            d	x}x}x}}y	)u+   stop_discussion() 시 codex_model 초기화i^  r  r  r   r  rf  rh  rb   Nr  )
rZ   rg   rt   r  r   r   r   r   r   r   rq  s	            r'   'test_stop_discussion_resets_codex_modelz4TestDeepMode.test_stop_discussion_resets_codex_model  s     "G_5{{7#B#//B?B/?BBBB/?BBB#BBB/BBB?BBBBBBB{{7#G#//G3GG/3GGGGG/3GGGG#GGG/GGG3GGGGGGGGr)   c                    | j                         }d}|j                  |d       |j                  |   }|j                  }d}||k(  }|st	        j
                  d|fd||f      t	        j                  |      t	        j                  |      t	        j                  |      dz  }dd|iz  }t        t	        j                  |            d	x}x}x}}y	)
u   --deep만 있는 경우i_  z--deepr  r   r  rf  rh  rb   Nr  rq  s	            r'   !test_deep_flag_without_extra_textz.TestDeepMode.test_deep_flag_without_extra_text   s      "GX.{{7#B#//B?B/?BBBB/?BBB#BBB/BBB?BBBBBBBr)   c                    | j                         }d}|j                  |d       |j                  |   }|j                  }d}||k(  }|st	        j
                  d|fd||f      t	        j                  |      t	        j                  |      t	        j                  |      dz  }dd|iz  }t        t	        j                  |            d	x}x}x}}y	)
u%   --deep 없으면 기본 모델 유지i`  u   보험에 대해 토론해줘r  r   r  rf  rh  rb   Nr  rq  s	            r'   test_no_deep_flag_keeps_defaultz,TestDeepMode.test_no_deep_flag_keeps_default'  s      "G%DE{{7#G#//G3GG/3GGGGG/3GGGG#GGG/GGG3GGGGGGGGr)   c                    | j                         }d}|j                  |d       |j                  } ||      }d}||u }|st        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                  |      rt        j                  |      ndt        j                  |      t        j                  |      dz  }d	d
|iz  }t        t        j                  |            dx}x}x}}|j                  } ||      }d}||u }|st        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                  |      rt        j                  |      ndt        j                  |      t        j                  |      dz  }d	d
|iz  }t        t        j                  |            dx}x}x}}y)u1   should_announce_deep_mode() 한번만 True 반환ia  r  TrF   )z_%(py5)s
{%(py5)s = %(py2)s
{%(py2)s = %(py0)s.should_announce_deep_mode
}(%(py3)s)
} is %(py8)sr_   r`   ra   rc   rd   NF)rZ   rg   should_announce_deep_moder   r   r   r   r   r   r   r   rh   s	            r'   test_deep_mode_announced_flagz*TestDeepMode.test_deep_mode_announced_flag.  su     "G_5,,=,W5==5====5======s===s===,======W===W===5==========,,>,W5>>5>>>>5>>>>>>s>>>s>>>,>>>>>>W>>>W>>>5>>>>>>>>>>r)   N)rM   rN   rO   rP   rZ   r  r  r  r  r  r  r  r  r  r  r  rQ   r)   r'   r  r    sH    /#
HC=;?DB
HCH?r)   r  )builtinsr   _pytest.assertion.rewrite	assertionrewriter   ossyspathinsertjoindirname__file__r   r   r   pytestr   rS   r   r  r#  rA  ry  r  rQ   r)   r'   <module>r     s      	 
 277<< 94@ A   D* D*Xd9 d9Xj jd%S %SZ=5 =5JtE tEx. .lV? V?r)   