
    Li2                       d Z ddlmZ ddlZddlmc mZ ddl	Z	ddl
Z
ddlZddlZej                  j                  de
j                  j                  e
j                  j!                  e      d             ddlmZ ddlmZmZ ddlZddlmZ 	 	 	 	 	 d	 	 	 	 	 	 	 	 	 	 	 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! G d d      Z" G d d      Z#y)u   tests/test_engine_v2_phase4.py — Phase 4 TDD 테스트 스위트.

G09+G10+G11+G12: ConsensusPipeline, CircuitBreaker, CostTracker 검증.
작성 순서: 테스트 먼저(RED), 구현 후 GREEN 확인.
    )annotationsNz..)Path)	AsyncMockpatchEngineResultc                $    t        || | |||      S )u!   테스트용 EngineResult 생성.)enginecontentcleantask_idsteperrorr   )r   r
   r   r   r   s        J/home/jay/workspace/services/multimodel-bot/tests/test_engine_v2_phase4.py_make_resultr      s#          c                      e Zd ZdZddZy)TestCircuitBreakerClosedu&   CLOSED 상태 기본 동작 테스트.c                   ddl m}m}  |       }|j                  }|j                  }||k(  }|st        j                  d|fd||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      dz  }dd	|iz  }t        t        j                  |            d
x}x}}|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
)u5   CLOSED 상태에서 요청이 허용되어야 한다.r   CBStateCircuitBreaker==zI%(py2)s
{%(py2)s = %(py0)s.state
} == %(py6)s
{%(py6)s = %(py4)s.CLOSED
}cbr   py0py2py4py6assert %(py8)spy8NTiszL%(py4)s
{%(py4)s = %(py2)s
{%(py2)s = %(py0)s.allow_request
}()
} is %(py7)sr   r   r    py7assert %(py9)spy9)engine_v2.circuit_breakerr   r   stateCLOSED
@pytest_ar_call_reprcompare@py_builtinslocals_should_repr_global_name	_safereprAssertionError_format_explanationallow_requestselfr   r   r   @py_assert1@py_assert5@py_assert3@py_format7@py_format9@py_assert6@py_format8@py_format10s               r   "test_circuit_breaker_closed_allowsz;TestCircuitBreakerClosed.test_circuit_breaker_closed_allows5   s$   Exx)7>>)x>))))x>))))))r)))r)))x))))))7)))7)))>))))))))!)T)!T))))!T))))))r)))r))))))!)))T)))))))r   NreturnNone)__name__
__module____qualname____doc__rA    r   r   r   r   2   s
    0*r   r   c                      e Zd ZdZddZy)TestCircuitBreakerOpenu   OPEN 상태 전환 테스트.c                
   ddl m}m}  |d      }|j                  }|j                  }||k(  }|st        j                  d|fd||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      d	z  }d
d|iz  }t        t        j                  |            dx}x}}|j                          |j                  }|j                  }||k(  }|st        j                  d|fd||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      d	z  }d
d|iz  }t        t        j                  |            dx}x}}|j                          |j                  }|j                  }||k(  }|st        j                  d|fd||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      d	z  }d
d|iz  }t        t        j                  |            dx}x}}|j                          |j                  }|j                  }||k(  }|st        j                  d|fd||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      d	z  }d
d|iz  }t        t        j                  |            dx}x}}|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)u6   3회 실패 후 OPEN 상태로 전환되어야 한다.r   r      )fail_thresholdr   r   r   r   r   r"   r#   N)zG%(py2)s
{%(py2)s = %(py0)s.state
} == %(py6)s
{%(py6)s = %(py4)s.OPEN
}Fr$   r&   r'   r)   r*   )r+   r   r   r,   r-   r.   r/   r0   r1   r2   r3   r4   r5   record_failureOPENr6   r7   s               r   *test_circuit_breaker_open_after_3_failureszATestCircuitBreakerOpen.test_circuit_breaker_open_after_3_failuresA   s   E1-xx)7>>)x>))))x>))))))r)))r)))x))))))7)))7)))>)))))))
xx)7>>)x>))))x>))))))r)))r)))x))))))7)))7)))>)))))))
xx)7>>)x>))))x>))))))r)))r)))x))))))7)))7)))>)))))))
xx'7<<'x<''''x<''''''r'''r'''x''''''7'''7'''<'''''''*!*U*!U****!U******r***r******!***U*******r   NrB   )rE   rF   rG   rH   rQ   rI   r   r   rK   rK   >   s
    '+r   rK   c                  (    e Zd ZdZddZddZddZy)TestCircuitBreakerHalfOpenu"   HALF_OPEN 상태 전환 테스트.c                r   ddl m}m}  |dd      }|j                          |j                          |j                          |j                  }|j
                  }||k(  }|st        j                  d|fd||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      d	t        j                         v st        j                  |      rt        j                  |      nd	t        j                  |      d
z  }dd|iz  }t        t        j                  |            dx}x}} |dd      }	|	j                          |	j                          |	j                          t        j                  d       |	j                   }|j"                  }||k(  }|st        j                  d|fd||f      dt        j                         v st        j                  |	      rt        j                  |	      ndt        j                  |      d	t        j                         v st        j                  |      rt        j                  |      nd	t        j                  |      d
z  }dd|iz  }t        t        j                  |            dx}x}}y)u?   recovery_sec 경과 후 HALF_OPEN으로 전환되어야 한다.r   r   rM   <   rN   recovery_secr   )zH%(py2)s
{%(py2)s = %(py0)s._state
} == %(py6)s
{%(py6)s = %(py4)s.OPEN
}r   r   r   r"   r#   N{Gz?zL%(py2)s
{%(py2)s = %(py0)s.state
} == %(py6)s
{%(py6)s = %(py4)s.HALF_OPEN
}cb2)r+   r   r   rO   _staterP   r.   r/   r0   r1   r2   r3   r4   r5   timesleepr,   	HALF_OPEN)
r8   r   r   r   r9   r:   r;   r<   r=   rZ   s
             r   *test_circuit_breaker_recovery_to_half_openzETestCircuitBreakerHalfOpen.test_circuit_breaker_recovery_to_half_openV   s   E12>


yy(GLL(yL((((yL((((((r(((r(((y((((((G(((G(((L((((((( AA>

4yy-G---y-----y-------s---s---y------G---G-----------r   c                >   ddl m}m}  |dd      }|j                          |j                          |j                          t	        j
                  d       |j                  }|j                  }||k(  }|st        j                  d|fd||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      d	t        j                         v st        j                  |      rt        j                  |      nd	t        j                  |      d
z  }dd|iz  }t        t        j                  |            dx}x}}|j!                          |j#                          |j                  }|j$                  }||k(  }|st        j                  d|fd||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      d	t        j                         v st        j                  |      rt        j                  |      nd	t        j                  |      d
z  }dd|iz  }t        t        j                  |            dx}x}}y)uC   HALF_OPEN에서 성공 기록 시 CLOSED로 전환되어야 한다.r   r   rM   rV   rX   r   rY   r   r   r   r"   r#   Nr   )r+   r   r   rO   r\   r]   r,   r^   r.   r/   r0   r1   r2   r3   r4   r5   r6   record_successr-   )	r8   r   r   r   r9   r:   r;   r<   r=   s	            r   -test_circuit_breaker_half_open_success_closeszHTestCircuitBreakerHalfOpen.test_circuit_breaker_half_open_success_closesj   s~   E11=




4xx,7,,,x,,,,,x,,,,,,,r,,,r,,,x,,,,,,7,,,7,,,,,,,,,,,

xx)7>>)x>))))x>))))))r)))r)))x))))))7)))7)))>)))))))r   c                j   ddl m}m}  |ddd      }|j                          |j                          |j                          t	        j
                  d       |j                  }|j                  }||k(  }|st        j                  d|fd||f      d	t        j                         v st        j                  |      rt        j                  |      nd	t        j                  |      d
t        j                         v st        j                  |      rt        j                  |      nd
t        j                  |      dz  }dd|iz  }t        t        j                  |            dx}x}}|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}}	|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)uM   HALF_OPEN 상태에서 half_max_calls=1이면 1회만 허용되어야 한다.r   r   rM      )rN   rW   half_max_callsrX   r   rY   r   r   r   r"   r#   NTr$   r&   r'   r)   r*   F)r+   r   r   rO   r\   r]   r,   r^   r.   r/   r0   r1   r2   r3   r4   r5   r6   r7   s               r   (test_circuit_breaker_half_open_max_callszCTestCircuitBreakerHalfOpen.test_circuit_breaker_half_open_max_callsz   s   E11QO




4xx,7,,,x,,,,,x,,,,,,,r,,,r,,,x,,,,,,7,,,7,,,,,,,,,,, )!)T)!T))))!T))))))r)))r))))))!)))T)))))))*!*U*!U****!U******r***r******!***U*******r   NrB   )rE   rF   rG   rH   r_   rb   rf   rI   r   r   rS   rS   S   s    ,.(* +r   rS   c                  (    e Zd ZdZddZddZddZy)TestCostTrackerLogUsageu   log_usage() 기록 테스트.c                	   ddl m} t        dd      }t        j                  |d|dz        5  |j                  |d	d
       ddd       |dz  }|j                  } |       }|sddt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      dz  }t        t        j                  |            dx}}|j                  d      j                         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}}
t'        j(                  |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	}||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
}||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"}||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}||k(  }	|	slt        j$                  d|	fd||f      t        j                  |      t        j                  |      dz  }dd|iz  }t        t        j                  |            dx}x}	}y# 1 sw Y   xY w)$u4   JSONL 파일에 사용량이 기록되어야 한다.r   cost_trackeru   테스트 결과clauder   r
   _get_log_pathztest_usage.jsonlreturn_valued   gGz?prompt_charsduration_secNAassert %(py4)s
{%(py4)s = %(py2)s
{%(py2)s = %(py0)s.exists
}()
}log_filer   r   r    zutf-8)encodingrd   r   z0%(py3)s
{%(py3)s = %(py0)s(%(py1)s)
} == %(py6)slenlinesr   py1py3r!   r"   r#   r
   z%(py1)s == %(py4)sr}   r    assert %(py6)sr!   rs   rt   r   task-001r   )	engine_v2rk   r   r   object	log_usageexistsr0   r1   r.   r2   r3   r4   r5   	read_textstrip
splitlinesrz   r/   jsonloads)r8   tmp_pathrk   resultrv   r9   r;   @py_format5r{   @py_assert2r:   @py_assert4r<   r=   entry@py_assert0s                   r   test_cost_tracker_log_usagez3TestCostTrackerLogUsage.test_cost_tracker_log_usage   s   *&8J \\,hQcFcd 	P""6$"O	P 00         x   x             ""G"4::<GGI5zQzQzQss55zQ

58$X*(*(****(******(*******^$++$++++$+++$++++++++++^$,,$,,,,$,,,$,,,,,,,,,,Y-:-:----:------:-------V}!!}!!!!}!!!}!!!!!!!!!!	P 	Ps   SSc                   ddl m} t        dd      }t        ddd	      }|d
z  }t        j                  |d|      5  |j                  |dd       |j                  |dd       ddd       t        j                  |d|      5  |j                  d      }ddd       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}	}|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}||k(  }|slt        j                  d|fd||f      t        j                  |      t        j                  |      dz  }dd |iz  }
t        t        j                  |
            dx}x}}y# 1 sw Y   RxY w# 1 sw Y   .xY w)"u;   기록된 JSONL을 읽어 리스트로 반환해야 한다.r   rj   u   응답1rl   rm   u   응답2gemini   )r   r
   r   zengine_usage_2026-03.jsonlrn   ro   2   g      ?rr   P   g?N_LOG_DIRz2026-03r   ry   rz   entriesr|   r"   r#   r
   r   r   r   r!   rd   )r   rk   r   r   r   r   
read_usagerz   r.   r/   r0   r1   r2   r3   r4   r5   )r8   r   rk   result1result2rv   r   r   r:   r   r<   r=   r   r;   r   s                  r   test_cost_tracker_read_usagez4TestCostTrackerLogUsage.test_cost_tracker_read_usage   s   *yByJ::\\,hO 	O""7#"N""7#"N	O \\,
H= 	9"--i8G	9 7| q |q    |q      s   s      7   7   |   q       qz(#/x/#x////#x///#///x///////qz(#/x/#x////#x///#///x///////	O 	O	9 	9s   )J8K8KKc                   ddl m }m} ddlm} ddlm} t        d      }|dz  }|dz  }t        j                  |d	|
      5  |j                  |dd       ddd       t        j                  |d	|
      5  |j                  |dd       ddd       |j                  }	 |	       }
|
sddt        j                         v st        j                  |      rt        j                  |      ndt        j                  |	      t        j                  |
      dz  }t        t        j                   |            dx}	}
|j                  }	 |	       }
|
sddt        j                         v st        j                  |      rt        j                  |      ndt        j                  |	      t        j                  |
      dz  }t        t        j                   |            dx}	}
t#        j$                  |j'                         j)                               }t#        j$                  |j'                         j)                               }|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}
||
k(  }|slt        j*                  d|fd||
f      t        j                  |      t        j                  |
      dz  }dd|iz  }t        t        j                   |            dx}x}}
y# 1 sw Y   xY w# 1 sw Y   xY w)u2   월별로 다른 파일에 기록되어야 한다.r   )datetimetimezone)r   rj   u   월별 테스트)r   zengine_usage_2026-01.jsonlzengine_usage_2026-02.jsonlrn   ro   
   g?rr   N   g?ru   jan_filerw   feb_filers   r   r   r   r   r!   )r   r   unittest.mockr   r   rk   r   r   r   r   r0   r1   r.   r2   r3   r4   r5   r   r   r   r   r/   )r8   r   r   r   uprk   r   r   r   r9   r;   r   jan_datafeb_datar   r   r<   s                    r   test_cost_tracker_monthly_filez6TestCostTrackerLogUsage.test_cost_tracker_monthly_file   sF   /-*&89 ::::\\,hO 	N""6"M	N \\,hO 	N""6"M	N          x   x                      x   x             ::h00288:;::h00288:;'-2-'2----'2---'---2-------'-2-'2----'2---'---2-------	N 	N	N 	Ns   M8MMMN)r   r   rC   rD   )rE   rF   rG   rH   r   r   r   rI   r   r   rh   rh      s    '".0,.r   rh   c                      e Zd ZdZddZy)TestConsensusEvaluateHighScoreu3   합의 점수 >= threshold → converged 테스트.c                h   ddl m}  |d      }t        dd      t        dd	      g}|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                  }|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}}
|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                  |	      t	        j                  |
      dz  }dd|iz  }t        t	        j                  |            dx}x}	x}}
y)uV   긍정 시그널만 있으면 합의 점수 >= 0.75이고 converged=True여야 한다.r   ConsensusPipeline      ?	thresholduC   수정 불필요. 충분히 적절하고 우수한 내용입니다.rl   rm   u"   양호합니다. 수정 불필요.r   Fr$   z%(py0)s is %(py3)sshould_continuer   r~   assert %(py5)spy5NTzL%(py4)s
{%(py4)s = %(py2)s
{%(py2)s = %(py0)s.state
}.converged
} is %(py7)spipeliner'   r)   r*   >=)zR%(py4)s
{%(py4)s = %(py2)s
{%(py2)s = %(py0)s.state
}.consensus_score
} >= %(py7)spublishing.consensus_pipeliner   r   r   r.   r/   r0   r1   r2   r3   r4   r5   r,   	convergedconsensus_scorer8   r   r   resultsr   r   r9   @py_format4@py_format6r;   r>   r:   r?   r@   s                 r   "test_consensus_evaluate_high_scorezATestConsensusEvaluateHighScore.test_consensus_evaluate_high_score   s   C$t4!fowx!EhW

 #227;"''%''''%''''''''''''%'''''''~~/~''/4/'4////'4//////x///x///~///'///4///////~~5~--55-5555-555555x555x555~555-5555555555r   NrB   )rE   rF   rG   rH   r   rI   r   r   r   r      s
    =6r   r   c                      e Zd ZdZddZy)TestConsensusEvaluateLowScoreu1   합의 점수 < threshold → continue 테스트.c                h   ddl m}  |d      }t        dd      t        dd	      g}|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                  }|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}}
|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                  |	      t	        j                  |
      dz  }dd|iz  }t        t	        j                  |            dx}x}	x}}
y)uT   부정 시그널만 있으면 합의 점수 < 0.75이고 continue=True여야 한다.r   r   r   r   uD   수정 필요. 오류가 있으며 누락된 내용이 많습니다.rl   rm   uF   부족합니다. major issue가 있고 missing 항목이 있습니다.r   Tr$   r   r   r   r   r   NFr   r   r'   r)   r*   )<)zQ%(py4)s
{%(py4)s = %(py2)s
{%(py2)s = %(py0)s.state
}.consensus_score
} < %(py7)sr   r   s                 r   !test_consensus_evaluate_low_scorez?TestConsensusEvaluateLowScore.test_consensus_evaluate_low_score   s   C$t4!gpxy!irz{

 #227;"&&$&&&&$&&&&&&&&&&&&$&&&&&&&~~0~''050'50000'5000000x000x000~000'00050000000~~4~--44-4444-444444x444x444~444-4444444444r   NrB   )rE   rF   rG   rH   r   rI   r   r   r   r      s
    ;5r   r   c                      e Zd ZdZddZy)TestConsensusMaxRoundsu)   최대 라운드 강제 종료 테스트.c                    ddl m}m} 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      }t        dd      g}|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                  }|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                  |
      t        j                  |      dz  }dd|iz  }t        t        j                  |            d
x}x}
x}}|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                  }|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                  |
      t        j                  |      dz  }dd|iz  }t        t        j                  |            d
x}x}
x}}|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                  }|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                  |
      t        j                  |      dz  }dd|iz  }t        t        j                  |            d
x}x}
x}}|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
)uF   3라운드 후 강제 종료되어야 한다 (MAX_CONSENSUS_ROUNDS=3).r   )MAX_CONSENSUS_ROUNDSr   rM   r   )z%(py0)s == %(py3)sr   r   r   r   Nr   r   u&   수정 필요. 오류가 있습니다.rl   rm   Tr$   r   r1rd   )zO%(py4)s
{%(py4)s = %(py2)s
{%(py2)s = %(py0)s.state
}.round_number
} == %(py7)sr   r'   r)   r*   r2r   Fr3r   )r   r   r   r.   r/   r0   r1   r2   r3   r4   r5   r   r   r,   round_numberr   )r8   r   r   r   r9   r   r   r   low_score_resultsr   r;   r>   r:   r?   r@   r   r   s                    r   test_consensus_max_roundsz0TestConsensusMaxRounds.test_consensus_max_rounds  s   Y'((#q((((#q((((((#(((#(((q((((((($t4!IRZ[

 %%&78rTzrTrrT~~/~**/a/*a////*a//////x///x///~///*///a/////// %%&78rTzrTrrT~~/~**/a/*a////*a//////x///x///~///*///a/////// %%&78rU{rUrrU~~/~**/a/*a////*a//////x///x///~///*///a///////~~0~''050'50000'5000000x000x000~000'00050000000r   NrB   )rE   rF   rG   rH   r   rI   r   r   r   r   	  s
    31r   r   c                      e Zd ZdZddZy)!TestConsensusMinorityPreservationu   소수 의견 보존 테스트.c           	        ddl m}  |d      }t        dd      t        dd	      g}|j                  |       |j                  }|j
                  }t        |      }d
}||k\  }|st        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                  |      t        j                  |      t        j                  |      dz  }	dd|	iz  }
t        t        j                  |
            dx}x}x}x}}d |j                  j
                  D        }t        |      }|sddt        j                         v st        j                  t              rt        j                  t              ndt        j                  |      t        j                  |      dz  }t        t        j                  |            dx}}y)uX   반대/우려 키워드가 있는 의견이 minority_opinions에 보존되어야 한다.r   r   r   r   u"   수정 불필요. 우수합니다.rl   rm   u@   그러나 concern이 있습니다. however 추가 검토 필요.r   rd   r   )zs%(py7)s
{%(py7)s = %(py0)s(%(py5)s
{%(py5)s = %(py3)s
{%(py3)s = %(py1)s.state
}.minority_opinions
})
} >= %(py10)srz   r   )r   r}   r~   r   r(   py10zassert %(py12)spy12Nc              3  $   K   | ]  }d |v  
 yw)r   NrI   ).0ops     r   	<genexpr>zYTestConsensusMinorityPreservation.test_consensus_minority_preservation.<locals>.<genexpr>7  s     Mb8r>Ms   z,assert %(py4)s
{%(py4)s = %(py0)s(%(py2)s)
}anyrw   )r   r   r   r   r,   minority_opinionsrz   r.   r/   r0   r1   r2   r3   r4   r5   r   )r8   r   r   r   r   r   r>   @py_assert9@py_assert8@py_format11@py_format13r9   r;   r   s                 r   $test_consensus_minority_preservationzFTestConsensusMinorityPreservation.test_consensus_minority_preservation+  sb   C$t4!EhW!cltu

 	  )>>9>339s3499499994999999s999s99999989998999>999399949999999999MHNN,L,LMMsMMMMMMMMMsMMMsMMMMMMMMMMMMMMr   NrB   )rE   rF   rG   rH   r   rI   r   r   r   r   (  s    )Nr   r   c                  J    e Zd ZdZej
                  j                  dd       Zy)$TestOrchestratorCircuitBreakerBlocksu>   Circuit Breaker OPEN 시 에러 EngineResult 반환 테스트.c                  K   ddl m}m} ddlm}  |       }|j
                  d   j                          |j
                  d   j                          |j
                  d   j                          |j
                  d   }|j                  }|j                  }||k(  }|st        j                  d|fd||f      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}}|j#                  ddgdgdd       d{   }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}}|d   }|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}}|d   }|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7 Yw)uO   CircuitBreaker가 OPEN 상태이면 에러 EngineResult를 반환해야 한다.r   r   )EngineOrchestratorrl   r   )zG%(py3)s
{%(py3)s = %(py1)s.state
} == %(py7)s
{%(py7)s = %(py5)s.OPEN
}r   )r}   r~   r   r(   r)   r*   N
SEQUENTIALu   테스트 프롬프트zcb-test-001rd   )modepromptsenginesr   r   ry   rz   r   r|   r"   r#   Tr$   )z-%(py3)s
{%(py3)s = %(py1)s.error
} is %(py6)s)r}   r~   r!   )z.%(py3)s
{%(py3)s = %(py1)s.engine
} == %(py6)s)r+   r   r   engine_v2.engine_orchestratorr   	_breakersrO   r,   rP   r.   r/   r3   r0   r1   r2   r4   r5   runrz   r   r
   )r8   r   r   r   orchestratorr   r   r>   r   r?   r@   r   r:   r<   r=   s                  r   (test_orchestrator_circuit_breaker_blockszMTestOrchestratorCircuitBreakerBlocks.test_orchestrator_circuit_breaker_blocksB  s     	FD)+ 	x(779x(779x(779%%h/E/55EE5EEEE5EEE/EEE5EEEEEEEEEEEEEEEEEEE %((-.J! ) 
 
 7| q |q    |q      s   s      7   7   |   q       qz'z'4'4''''4'''z''''''4'''''''qz,z  ,H, H,,,, H,,,z,,, ,,,H,,,,,,,
s   E?OOIONrB   )rE   rF   rG   rH   pytestmarkasyncior   rI   r   r   r   r   ?  s!    H[[- -r   r   )u   정상 응답rl   Fr   rd   )r   strr
   r   r   boolr   r   r   intrC   r   )$rH   
__future__r   builtinsr0   _pytest.assertion.rewrite	assertionrewriter.   r   ossysr\   pathinsertjoindirname__file__pathlibr   r   r   r   r   engine_v2.engine_resultr   r   r   rK   rS   rh   r   r   r   r   r   rI   r   r   <module>r     s   #    	 
  277<< 94@ A  *  0 #  	
  .	* 	*+ +*6+ 6+|J. J.d6 6&5 5&1 1>N N.- -r   