
    i,                     6   d Z ddlZddlZddlZddlmZ ddlmZ ej                  j                  dd       ej                  j                  dd       ddl
Zddlm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edefdZdedefdZddlmZ y)uj   
통합 테스트: cross_model_review.py, scripts/worktree_manager.py
task-1837_5.1 - 닌기르수 작성
    N)Path)patchz/home/jay/workspacez/home/jay/workspace/scripts)_check_rate_limitc                    |j                  t        dt        |              t        |       dz  dz  }|j                  t        d|       |j                  t        dt        |       dz  dz         |j                  t        dt        |       dz  dz  dz         |j                  d	d	
       |dz  j	                  dd       t        j
                  dd      }d|v sJ d|v sJ d|v sJ d|j                         v sJ y)u_   review 모드: 'CRITICAL', 'INFORMATIONAL' 키워드가 프롬프트에 포함되어야 한다.	WORKSPACEmemoryreportsREPORTS_DIR
EVENTS_DIReventsDECISIONS_DIR	decisionsTparentsexist_okztask-test-review.mdu   # 테스트 보고서
내용utf-8encodingztask-test-reviewreviewCRITICALINFORMATIONALN)setattrcmrr   mkdir
write_textbuild_review_promptlowertmp_pathmonkeypatchreports_dirprompts       U/home/jay/workspace/.worktrees/task-2116-dev1/tests/integration/test_gemini_review.py$test_build_review_prompt_review_moder$      s   [$x.9x.8+i7K]K8\4>H+Dx+OP_d8nx.G(.RU`.`adT2((445T_f4g$$%7BFf$$$'''v||~%%%    c                    |j                  t        dt        |              t        |       dz  dz  }|j                  t        d|       |j                  t        dt        |       dz  dz         |j                  t        dt        |       dz  dz  dz         |j                  d	d	
       |dz  j	                  dd       t        j
                  dd      }d|v sJ d|v sJ y)ug   challenge 모드: '적대적', '보안 취약점' 등 챌린지 지시사항이 포함되어야 한다.r   r   r	   r
   r   r   r   r   Tr   ztask-test-challenge.md   # 보고서r   r   ztask-test-challenge	challengeu	   챌린지u   보안 취약점Nr   r   r   r   r   r   r   s       r#   'test_build_review_prompt_challenge_moder*   '   s    [$x.9x.8+i7K]K8\4>H+Dx+OP_d8nx.G(.RU`.`adT2++77PW7X$$%:KHF&   '''r%   c                    |j                  t        dt        |              t        |       dz  dz  }|j                  t        d|       |j                  t        dt        |       dz  dz         |j                  t        dt        |       dz  dz  dz         |j                  d	d	
       |dz  j	                  dd       d}t        j
                  dd|      }||v sJ d|v sJ y)uU   consult 모드: 전달된 질문이 프롬프트에 그대로 포함되어야 한다.r   r   r	   r
   r   r   r   r   Tr   ztask-test-consult.mdr'   r   r   u/   이 설계에서 캐시 전략은 적합한가?ztask-test-consultconsult)questionu	   컨설팅Nr)   )r   r    r!   r-   r"   s        r#   7test_build_review_prompt_consult_mode_includes_questionr.   7   s    [$x.9x.8+i7K]K8\4>H+Dx+OP_d8nx.G(.RU`.`adT2))55mg5V@H$$%8)hWFv&   r%   c                    |j                  t        dt        |              t        |       dz  dz  }|j                  t        d|       |j                  t        dt        |       dz  dz         |j                  t        dt        |       dz  dz  dz         |j                  d	d	
       t        j                  dd      }d|v sJ y)uW   보고서가 없으면 '보고서 없음' 플레이스홀더가 포함되어야 한다.r   r   r	   r
   r   r   r   r   Tr   ztask-no-reportr   u   보고서 없음N)r   r   r   r   r   r   s       r#   4test_build_review_prompt_no_report_shows_placeholderr0   H   s    [$x.9x.8+i7K]K8\4>H+Dx+OP_d8nx.G(.RU`.`adT2 $$%5x@F'''r%   c                 "   |j                  t        dt        |              t        |       dz  dz  }|j                  t        d|       |j                  dd       d}|dz  j	                  |d	
       t        j
                  d      }||k(  sJ y)u?   보고서 파일이 존재하면 내용을 반환해야 한다.r   r   r	   r
   Tr   u&   # 보고서
테스트 내용입니다.ztask-load-test.mdr   r   ztask-load-testNr   r   r   r   r   _load_report)r   r    r!   expectedresults        r#   ,test_load_report_returns_content_when_existsr6   Y   s    [$x.9x.8+i7K]K8dT28H&&228g2N./FXr%   c                     |j                  t        dt        |              t        |       dz  dz  }|j                  t        d|       |j                  dd       t        j                  d      }|J y)	u:   보고서 파일이 없으면 None을 반환해야 한다.r   r   r	   r
   Tr   ztask-nonexistentN)r   r   r   r   r3   )r   r    r!   r5   s       r#   *test_load_report_returns_none_when_missingr8   g   sk    [$x.9x.8+i7K]K8dT201F>>r%   c                 "   |j                  t        dt        |              t        |       dz  dz  }|j                  t        d|       |j                  dd       d}|dz  j	                  |d	
       t        j
                  d      }||k(  sJ y)uL   UTF-8 한글이 포함된 보고서 내용을 정확히 반환해야 한다.r   r   r	   r
   Tr   uF   ## 작업 완료 보고서

변경사항: 함수 추가, 버그 수정ztask-korean.mdr   r   ztask-koreanNr2   )r   r    r!   korean_contentr5   s        r#   "test_load_report_with_utf8_contentr;   r   s    [$x.9x.8+i7K]K8dT2_N##///Qm,F^###r%   c                     |j                  t        dt        |              t        |       dz  dz  dz  }|j                  t        d|       t        j                  ddd       |d	z  }|j	                         sJ y
)u9   결정 기록 시 JSONL 파일이 생성되어야 한다.r   r   r   r   r   ztask-record-testg1_gateapprovedztask-record-test.jsonlN)r   r   r   _record_decisionexists)r   r    decisions_dirdecisions_files       r#   'test_record_decision_creates_jsonl_filerC      sr    [$x.9NX-8;FM_m<+Y
C"%==N  """r%   c                    |j                  t        dt        |              t        |       dz  dz  dz  }|j                  t        d|       t        j                  dddd	
       |dz  }|j	                  d      j                         j                         d   }t        j                  |      }|d   dk(  sJ |d   dk(  sJ |d   dk(  sJ d|v sJ |d   d	k(  sJ y)uV   JSONL 파일의 각 줄은 task_id, stage, decision, timestamp를 포함해야 한다.r   r   r   r   r   ztask-struct-testcross_reviewr>   r   )modeztask-struct-test.jsonlr   r   r   task_idstagedecision	timestamprF   N)	r   r   r   r?   	read_textstrip
splitlinesjsonloads)r   r    rA   rB   lineentrys         r#   ,test_record_decision_jsonl_content_structurerR      s    [$x.9NX-8;FM_m<+^ZhW"%==N##W#5;;=HHJ1MDJJtE1111>^+++
***%=H$$$r%   c                    |j                  t        dt        |              t        |       dz  dz  dz  }|j                  t        d|       t        j                  ddd       t        j                  dd	d
       |dz  }|j	                  d      j                         j                         }t        |      dk(  sJ t        j                  |d         }t        j                  |d         }|d   dk(  sJ |d   d	k(  sJ y)uR   _record_decision 여러 번 호출 시 각 줄이 JSONL에 추가되어야 한다.r   r   r   r   r   z
task-multistage_1
decision_1stage_2
decision_2ztask-multi.jsonlr   r      r      rH   N)
r   r   r   r?   rK   rL   rM   lenrN   rO   )r   r    rA   rB   linesentry1entry2s          r#   -test_record_decision_appends_multiple_entriesr^      s    [$x.9NX-8;FM_m<y,?y,?"%77N$$g$6<<>IIKEu:??ZZa!FZZa!F'?i''''?i'''r%   c                     | dz  t        j                  d      }j                  t        j                  |dd      d       ddlm} |j                  |d	fd
       |j                         }|i k(  sd|vsJ yy)u7   일 33건 미만이면 빈 dict를 반환해야 한다.gemini_rate_tracker.json%Y-%m-%d   datecountr   r   r   Nr   c                      t               S )N)_check_rate_limit_with_path)tracker_files   r#   <lambda>zAtest_check_rate_limit_below_limit_returns_empty.<locals>.<lambda>   s    +L9 r%   warning)	timestrftimer   rN   dumpsscripts.worktree_managerworktree_managerr   r   )r   r    todaywmr5   rh   s        @r#   /test_check_rate_limit_below_limit_returns_emptyrr      s    88LMM*%EDJJ'BCgV)
9
 !!#FR<9F2222<r%   c                 D   | dz  }t        j                  d      }|j                  t        j                  |dd      d       t        d      5 }t        |       }t               }||_        ||_	        t        |      }ddd       d	v sJ d
|d	   v sJ y# 1 sw Y   xY w)uJ   일 33건 초과 시 warning 키를 포함한 dict를 반환해야 한다.r`   ra   !   rc   r   r   zscripts.worktree_manager.PathNrj   34)rk   rl   r   rN   rm   r   r   	MagicMockparentreturn_value_call_rate_limit_with_tracker)r   rh   rp   mock_path_clsmock_parentmock_path_instancer5   s          r#   -test_check_rate_limit_exceeds_returns_warningr}      s    88LMM*%EDJJ'CDwW 
.	/ ==8n&[$/!%7" /|<= 6)$$$$= =s   /BBc                     | dz  }|j                  t        j                  ddd      d       t        |      }|i k(  sJ t        j                  |j                               }|d   dk(  sJ |d	   dk7  sJ y
)uO   날짜가 다르면 카운트를 0으로 리셋하고 1로 시작해야 한다.r`   z
2020-01-01c   rc   r   r   re   rY   rd   N)r   rN   rm   ry   rO   rK   )r   rh   r5   datas       r#   *test_check_rate_limit_new_day_resets_countr      s    88L

L267'   +<8FR<<::l,,./D=A<<'''r%   tracker_pathreturnc                    t        j                  d      }i }| j                         r$	 t        j                  | j                               }|j                  d      |k7  r|dd}|dxx   dz  cc<   | j                  t        j                  |             |d   dkD  rdd	|d    d
iS i S # t        j                  t        f$ r i }Y |w xY w)uQ   _check_rate_limit 로직을 tracker_path를 인자로 직접 실행하는 헬퍼.ra   rd   r   rc   re   rY   rt   rj   zGemini daily limit exceeded: z/33)rk   rl   r@   rN   rO   rK   JSONDecodeErrorOSErrorgetr   rm   )r   rp   r   s      r#   ry   ry      s    MM*%ED	::l4467D xx5 *MQMDJJt,-G}r:4=/MNNI $$g. 	D	s   #B+ +C	C	c                     t        |       S )uM   tracker_path를 지정해서 _check_rate_limit 로직을 실행하는 헬퍼.)ry   )r   s    r#   rg   rg      s    (66r%   )rv   )__doc__rN   sysrk   pathlibr   unittest.mockr   pathinsertcross_model_reviewr   rn   r   r$   r*   r.   r0   r6   r8   r;   rC   rR   r^   rr   r}   r   dictry   rg   rv    r%   r#   <module>r      s   
  
    ( ) 0 1   6
&$( !"("$ 	#%$((3 %*("  $7d 7t 7 $r%   