
    Si=]                    z   d Z ddlmZ ddlZddlZddlZddlmZ ddlm	Z	m
Z
 ddlZ eej                  j                  dd            Z ee      ej                   vr"ej                   j#                  d ee             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y)uG  
tests/test_session_auto_compress.py

SessionAutoCompress 단위 테스트 (TDD - RED 단계)

테스트 항목:
- auto_compress: 메시지 리스트 압축 → 반환 메시지 수 감소 확인
- auto_compress: 이벤트 파일 생성 확인 + JSON 형식 검증
- auto_compress: monitor.reset() 호출 확인
- save_session_summary: 파일 생성 + 경로 반환 확인
- save_session_summary: 파일 내용에 task_id, team_id, modified_files 등 필수 필드 포함 확인
- save_session_summary: 빈 메시지 → 에러 없이 처리
- setup_auto_hooks: 콜백 등록 확인
    )annotationsN)Path)	MagicMockpatchWORKSPACE_ROOT/home/jay/workspace)SessionMonitorc                    g }t        |       D ]A  }|dz  dk(  r|j                  dd| ddz   d       '|j                  dd	| dd
z   d       C |S )u^   테스트용 메시지 리스트를 생성한다. 압축이 일어날 만큼 충분한 크기.   r   useru   질문 z:   xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxrolecontent	assistantu   답변   yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy)rangeappend)countmsgsis      Q/home/jay/workspace/.worktrees/task-2117-dev1/tests/test_session_auto_compress.py_make_messagesr   %   sj    D5\ Wq5A:KKgaSOi4OPQKK71#R99TUV	W
 K    c                  :    e Zd ZdZd Zd Zd Zd Zd Zd Z	d Z
y	)
TestAutoCompressuC   auto_compress()가 올바르게 메시지를 압축하는지 확인c                   ddl m} t        d      } ||d|dz  |dz        }t        d      }|j	                  |      }t        |t              sJ t        |      d	k(  sJ |\  }}t        |t              sJ t        |t              sJ y
)u<   auto_compress가 (list, dict) 튜플을 반환해야 한다.r   SessionAutoCompress@ context_limiteventssessionsmonitorr"   
events_dirsessions_dir   r   N)
utils.session_auto_compressr   r	   r   auto_compress
isinstancetuplelenlistdict)	selftmp_pathr   r&   sacmessagesresultcompressed_msgs
event_infos	            r    test_auto_compress_returns_tuplez1TestAutoCompress.test_auto_compress_returns_tuple8   s    C w7!!(*!J.	
 ""%""8,&%(((6{a&,#/4000*d+++r   c                    ddl m} t        d      } ||d|dz  |dz        }t        d      }|j	                  |      \  }}t        |      t        |      k  sJ y	)
uD   압축 후 메시지 수가 원본보다 적거나 같아야 한다.r   r   r    r!   r#   r$   r%      N)r*   r   r	   r   r+   r.   )r1   r2   r   r&   r3   r4   r6   _s           r   (test_auto_compress_reduces_message_countz9TestAutoCompress.test_auto_compress_reduces_message_countK   sg    C w7!!(*!J.	
 ""% ..x8?#s8}444r   c                    ddl m} t        d      }|dz  } ||d||dz        }t        d      }|j	                  |       t        |j                  d	            }t        |      d
k(  sJ y)uD   압축 후 events_dir에 이벤트 파일이 생성되어야 한다.r   r   r    r!   r#   r$   r%   
   session-compressed-*.json   N)r*   r   r	   r   r+   r/   globr.   )r1   r2   r   r&   r'   r3   r4   event_filess           r   %test_auto_compress_event_file_createdz6TestAutoCompress.test_auto_compress_event_file_created\   su    C w7(
!!!!J.	
 ""%(#:??+FGH;1$$$r   c                   ddl m} t        d      }|dz  } ||d||dz        }t        d      }|j	                  |       t        |j                  d	            }t        |      d
k(  sJ t        |d   d      5 }t        j                  |      }	ddd       	d   dk(  sJ d|	v sJ d|	v sJ d|	v sJ d|	v sJ d|	v sJ |	d   t        |      k(  sJ y# 1 sw Y   ExY w)uO   이벤트 파일이 올바른 JSON 형식과 필수 키를 포함해야 한다.r   r   r    r!   r#   r$   r%   r>   r?   r@   utf-8encodingNeventsession_compressed	timestampbefore_countafter_counttokens_beforetokens_after)r*   r   r	   r   r+   r/   rA   r.   openjsonload)
r1   r2   r   r&   r'   r3   r4   rB   fdatas
             r   )test_auto_compress_event_file_json_formatz:TestAutoCompress.test_auto_compress_event_file_json_formatn   s   C w7(
!!!!J.	
 ""%(#:??+FGH;1$$$+a.73 	 q99Q<D	  G} 4444d"""%%%$$$$&&&%%%N#s8}444	  	 s   =CC c                    ddl m} t        d      }|j                  d        ||d|dz  |dz  	      }t	        d
      }|j                  |       |j                         }|d   dk  sJ y)u5   압축 후 monitor.reset()이 호출되어야 한다.r   r   r    r!   i  )	new_totalr#   r$   r%   r>   total_tokensN)r*   r   r	   resetr   r+   get_usage_status)r1   r2   r   r&   r3   r4   statuss          r   'test_auto_compress_monitor_reset_calledz8TestAutoCompress.test_auto_compress_monitor_reset_called   sz    C w7(!!(*!J.	
 ""%(# ))+n%///r   c                    ddl m} t        d      } ||d|dz  |dz        }|j                  g       \  }}|g k(  sJ t	        |t
              sJ y)	@   빈 메시지 리스트도 에러 없이 처리되어야 한다.r   r   r    r!   r#   r$   r%   N)r*   r   r	   r+   r,   r0   )r1   r2   r   r&   r3   r6   r7   s          r   !test_auto_compress_empty_messagesz2TestAutoCompress.test_auto_compress_empty_messages   sd    C w7!!(*!J.	
 '*&7&7&;#"$$$*d+++r   c                    ddl m} t        d      } ||d|dz  |dz        }t        d      }|j	                  |      \  }}d	|v sJ |d	   d
k(  sJ d|v sJ d|v sJ y)uB   반환된 event_info dict에 필수 키가 포함되어야 한다.r   r   r    r!   r#   r$   r%   r>   rH   rI   rK   rL   N)r*   r   r	   r   r+   )r1   r2   r   r&   r3   r4   r;   r7   s           r   'test_auto_compress_event_info_in_returnz8TestAutoCompress.test_auto_compress_event_info_in_return   s    C w7!!(*!J.	
 ""%))(3:*$$$'"&::::+++
***r   N)__name__
__module____qualname____doc__r8   r<   rC   rT   r[   r^   r`    r   r   r   r   5   s(    M,&5"%$5:0*,+r   r   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)TestSaveSessionSummaryuN   save_session_summary()가 올바르게 요약 파일을 저장하는지 확인c                    ddl m} t        d      }|dz  } ||d|dz  |      }t        d      }|j	                  |d	d
      }t        |t              sJ y)u;   save_session_summary가 Path 객체를 반환해야 한다.r   r   r    r!   r$   r#   r%      
task-100.1	dev6-teamr4   task_idteam_idN)r*   r   r	   r   save_session_summaryr,   r   )r1   r2   r   r&   r(   r3   r4   r5   s           r   &test_save_session_summary_returns_pathz=TestSaveSessionSummary.test_save_session_summary_returns_path   sp    C w7*,!!(*%	
 "!$))  * 

 &$'''r   c                    ddl m} t        d      }|dz  } ||d|dz  |      }t        d      }|j	                  |d	d
      }|j                         sJ |j                  dk(  sJ y)uK   save_session_summary 호출 후 파일이 실제로 생성되어야 한다.r   r   r    r!   r$   r#   r%   ri   rj   rk   rl   z.mdN)r*   r   r	   r   ro   existssuffixr1   r2   r   r&   r(   r3   r4   paths           r   %test_save_session_summary_file_existsz<TestSaveSessionSummary.test_save_session_summary_file_exists   s    C w7*,!!(*%	
 "!$''  ( 

 {{}}{{e###r   c                    ddl m} t        d      }|dz  } ||d|dz  |      }t        d      }|j	                  |d	d
      }d	|j
                  v sJ y)u:   저장 파일 이름에 task_id가 포함되어야 한다.r   r   r    r!   r$   r#   r%   ri   z
task-999.9rk   rl   N)r*   r   r	   r   ro   namert   s           r   3test_save_session_summary_filename_contains_task_idzJTestSaveSessionSummary.test_save_session_summary_filename_contains_task_id   sr    C w7*,!!(*%	
 "!$''  ( 

 tyy(((r   c                    ddl m} t        d      }|dz  } ||d|dz  |      }t        d      }|j	                  |d	d
      }|j                  d      }d	|v sJ y)u3   파일 내용에 task_id가 포함되어야 한다.r   r   r    r!   r$   r#   r%   ri   rj   rk   rl   rE   rF   Nr*   r   r	   r   ro   	read_text	r1   r2   r   r&   r(   r3   r4   ru   r   s	            r   -test_save_session_summary_content_has_task_idzDTestSaveSessionSummary.test_save_session_summary_content_has_task_id  s~    C w7*,!!(*%	
 "!$''  ( 

 ..'.2w&&&r   c                    ddl m} t        d      }|dz  } ||d|dz  |      }t        d      }|j	                  |d	d
      }|j                  d      }d
|v sJ y)u3   파일 내용에 team_id가 포함되어야 한다.r   r   r    r!   r$   r#   r%   ri   rj   rk   rl   rE   rF   Nr{   r}   s	            r   -test_save_session_summary_content_has_team_idzDTestSaveSessionSummary.test_save_session_summary_content_has_team_id  s~    C w7*,!!(*%	
 "!$''  ( 

 ..'.2g%%%r   c                    ddl m} t        d      }|dz  } ||d|dz  |      }t        d      }|j	                  |d	d
ddg      }|j                  d      }d|v sJ d|v sJ y)uA   파일 내용에 modified_files 목록이 포함되어야 한다.r   r   r    r!   r$   r#   r%   ri   rj   rk   zutils/foo.pyzutils/bar.py)r4   rm   rn   modified_filesrE   rF   Nr{   r}   s	            r   4test_save_session_summary_content_has_modified_fileszKTestSaveSessionSummary.test_save_session_summary_content_has_modified_files2  s    C w7*,!!(*%	
 "!$'' *N;	 ( 
 ..'.2((((((r   c                    ddl m} t        d      }|dz  } ||d|dz  |      }t        d      }|j	                  |d	d
ddg      }|j                  d      }d|v sJ d|v sJ y)uB   파일 내용에 remaining_tasks 목록이 포함되어야 한다.r   r   r    r!   r$   r#   r%   ri   rj   rk   u   작업A 완료u   작업B 시작)r4   rm   rn   remaining_tasksrE   rF   Nr{   r}   s	            r   5test_save_session_summary_content_has_remaining_taskszLTestSaveSessionSummary.test_save_session_summary_content_has_remaining_tasksI  s    C w7*,!!(*%	
 "!$'' -/?@	 ( 
 ..'.27***7***r   c                    ddl m} t        d      }|dz  } ||d|dz  |      }t        d      }|j	                  |d	d
d      }|j                  d      }d|v sJ y)u=   파일 내용에 last_success_step이 포함되어야 한다.r   r   r    r!   r$   r#   r%   ri   rj   rk   u   테스트 통과 완료)r4   rm   rn   last_success_steprE   rF   Nr{   r}   s	            r   7test_save_session_summary_content_has_last_success_stepzNTestSaveSessionSummary.test_save_session_summary_content_has_last_success_step`  s    C w7*,!!(*%	
 "!$'' 7	 ( 
 ..'.2(G333r   c                    ddl m} t        d      }|dz  } ||d|dz  |      }t        d      }|j	                  |d	d
ddg      }|j                  d      }d|v sJ d|v sJ y)u9   파일 내용에 errors 목록이 포함되어야 한다.r   r   r    r!   r$   r#   r%   ri   rj   rk   zImportError: module not foundzTypeError: expected str)r4   rm   rn   errorsrE   rF   Nr{   r}   s	            r   ,test_save_session_summary_content_has_errorszCTestSaveSessionSummary.test_save_session_summary_content_has_errorsv  s    C w7*,!!(*%	
 "!$'' 35NO	 ( 
 ..'.2.'999(G333r   c                    ddl m} t        d      }|dz  } ||d|dz  |      }|j                  g dd	
      }|j	                         sJ |j                  d      }d|v sJ y)r]   r   r   r    r!   r$   r#   r%   ztask-empty.1rk   rl   rE   rF   N)r*   r   r	   ro   rr   r|   )r1   r2   r   r&   r(   r3   ru   r   s           r   (test_save_session_summary_empty_messagesz?TestSaveSessionSummary.test_save_session_summary_empty_messages  s    C w7*,!!(*%	
 ''" ( 

 {{}}..'.2(((r   c           	         ddl m} t        d      }|dz  } ||d|dz  |      }t        d      }|j	                  |d	d
dddd      }|j                         sJ y)uG   optional 필드가 None일 때도 에러 없이 처리되어야 한다.r   r   r    r!   r$   r#   r%      z
task-opt.1z	dev1-teamN)r4   rm   rn   r   r   r   r   )r*   r   r	   r   ro   rr   rt   s           r   .test_save_session_summary_none_optional_fieldszETestSaveSessionSummary.test_save_session_summary_none_optional_fields  sz    C w7*,!!(*%	
 "!$''  " ( 
 {{}}r   c                    ddl m} t        d      }|dz  } ||d|dz  |      }t        d      }|j	                  |d	d
      }|j                  d      }d|v sJ d|v sJ d|v sJ y)u@   파일 내용에 마크다운 헤더 구조가 있어야 한다.r   r   r    r!   r$   r#   r%   ri   rj   rk   rl   rE   rF   u   # 세션 요약u   ## 기본 정보u   ## 자동 요약Nr{   r}   s	            r   *test_save_session_summary_markdown_headerszATestSaveSessionSummary.test_save_session_summary_markdown_headers  s    C w7*,!!(*%	
 "!$''  ( 

 ..'.2 G+++!W,,,!W,,,r   N)ra   rb   rc   rd   rp   rv   ry   r~   r   r   r   r   r   r   r   r   re   r   r   rg   rg      sA    X(($*)('*&*).+.4,4.),0-r   rg   c                  (    e Zd ZdZd Zd Zd Zd Zy)TestSetupAutoHooksuC   setup_auto_hooks()가 콜백을 올바르게 등록하는지 확인c                   ddl m} t        d      } ||d|dz  |dz        }t        |j                  j                  dg             }|j                          t        |j                  j                  dg             }||d	z   k(  sJ y
)uQ   setup_auto_hooks 호출 후 monitor에 critical 콜백이 등록되어야 한다.r   r   r    r!   r#   r$   r%   criticalr@   Nr*   r   r	   r.   
_callbacksgetsetup_auto_hooksr1   r2   r   r&   r3   rK   rL   s          r   (test_setup_auto_hooks_registers_callbackz;TestSetupAutoHooks.test_setup_auto_hooks_registers_callback  s    C w7!!(*!J.	
 7--11*bAB',,00R@AlQ....r   c                    ddl m} t        d      } ||d|dz  |dz        }|j                          |j                  j                  dg       }t        |      dkD  sJ t        |d	         sJ y
)u-   등록된 콜백이 callable이어야 한다.r   r   r    r!   r#   r$   r%   r   N)r*   r   r	   r   r   r   r.   callable)r1   r2   r   r&   r3   	callbackss         r   *test_setup_auto_hooks_callback_is_callablez=TestSetupAutoHooks.test_setup_auto_hooks_callback_is_callable  sy    C w7!!(*!J.	
 	&&**:r:	9~!!!	"&&&r   c                    ddl m} t        d      } ||d|dz  |dz        }|j                          	 |j	                  ddd	       y# t
        $ r"}t        j                  d
|        Y d}~yd}~ww xY w)uF   critical 레벨 도달 시 등록된 콜백이 호출되어야 한다.r   r   r    r!   r#   r$   r%   i )input_tokensoutput_tokensu*   critical 콜백 실행 중 예외 발생: N)r*   r   r	   r   update	Exceptionpytestfail)r1   r2   r   r&   r3   excs         r   2test_setup_auto_hooks_callback_invoked_on_criticalzETestSetupAutoHooks.test_setup_auto_hooks_callback_invoked_on_critical  s}    C w7!!(*!J.	
 		LNNGaHI 	LKKDSEJKK	Ls   A 	A6A11A6c                4   ddl m} t        d      } ||d|dz  |dz        }t        |j                  j                  dg             }|j                          |j                          t        |j                  j                  dg             }||d	z   k(  sJ y
)uR   setup_auto_hooks를 두 번 호출하면 콜백이 두 번 등록되어야 한다.r   r   r    r!   r#   r$   r%   r   r   Nr   r   s          r    test_setup_auto_hooks_idempotentz3TestSetupAutoHooks.test_setup_auto_hooks_idempotent  s    C w7!!(*!J.	
 7--11*bAB',,00R@AlQ....r   N)ra   rb   rc   rd   r   r   r   r   re   r   r   r   r     s    M/"' L(/r   r   c                  "    e Zd ZdZd Zd Zd Zy)TestDefaultPathsub   기본 경로가 WORKSPACE/memory/events/, WORKSPACE/memory/sessions/으로 설정되는지 확인c                    ddl m} t        d      } ||      }t        t        j
                  j                  dd            }|j                  |dz  d	z  k(  sJ y
)u>   events_dir 기본값이 WORKSPACE/memory/events/여야 한다.r   r   r    r!   r&   r   r   memoryr#   N)r*   r   r	   r   osenvironr   r'   r1   r   r&   r3   	workspaces        r   test_default_events_dirz(TestDefaultPaths.test_default_events_dir+  sP    C w7!'2(8:OPQ	~~X!5!@@@@r   c                    ddl m} t        d      } ||      }t        t        j
                  j                  dd            }|j                  |dz  d	z  k(  sJ y
)uB   sessions_dir 기본값이 WORKSPACE/memory/sessions/여야 한다.r   r   r    r!   r   r   r   r   r$   N)r*   r   r	   r   r   r   r   r(   r   s        r   test_default_sessions_dirz*TestDefaultPaths.test_default_sessions_dir4  sR    C w7!'2(8:OPQ	9x#7*#DDDDr   c                    ddl m} t        d      } |||dz  |dz        }|j                  |dz  k(  sJ |j                  |dz  k(  sJ y)	u8   커스텀 경로가 올바르게 설정되어야 한다.r   r   r    r!   	my_eventsmy_sessions)r&   r'   r(   N)r*   r   r	   r'   r(   )r1   r2   r   r&   r3   s        r   test_custom_dirs_acceptedz*TestDefaultPaths.test_custom_dirs_accepted=  s^    C w7!+-!M1

 ~~K!77778m#;;;;r   N)ra   rb   rc   rd   r   r   r   re   r   r   r   r   (  s    lAE<r   r   c                      e Zd ZdZd Zy)#TestEstimateTokensKoreanIntegrationuT   session_auto_compress의 토큰 추정이 한국어 보정을 사용하는지 확인c                v    ddl m} d}dt        |      z  }d|dg}d|dg} ||      } ||      }||kD  sJ y)ud   한국어 메시지가 같은 길이의 영어 메시지보다 더 많은 토큰으로 추정된다.r   )_estimate_tokens_for_messagesu  안녕하세요 테스트입니다 안녕하세요 테스트입니다 안녕하세요 테스트입니다 안녕하세요 테스트입니다 안녕하세요 테스트입니다 안녕하세요 테스트입니다 안녕하세요 테스트입니다 안녕하세요 테스트입니다 안녕하세요 테스트입니다 안녕하세요 테스트입니다 안녕하세요 테스트입니다 안녕하세요 테스트입니다 안녕하세요 테스트입니다 안녕하세요 테스트입니다 안녕하세요 테스트입니다 안녕하세요 테스트입니다 안녕하세요 테스트입니다 안녕하세요 테스트입니다 안녕하세요 테스트입니다 안녕하세요 테스트입니다 ar   r   N)r*   r   r.   )r1   r   ko_texten_textko_msgsen_msgs	ko_tokens	en_tokenss           r   %test_korean_messages_estimated_higherzITestEstimateTokensKoreanIntegration.test_korean_messages_estimated_higherS  sT    M<G$"w78"w781':	1':	9$$$r   N)ra   rb   rc   rd   r   re   r   r   r   r   P  s
    ^%r   r   )r)   )r   intreturnz
list[dict])rd   
__future__r   rP   r   syspathlibr   unittest.mockr   r   r   r   r   
_WORKSPACEstrru   insertutils.session_monitorr	   r   r   rg   r   r   r   re   r   r   <module>r      s    #  	 
  * "**..!13HIJ
z?#(("HHOOAs:' 0 K+ K+fH- H-`H/ H/` <  <P% %r   