
    Ei                       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
e
j                  j                  de	j                  j                  e	j                  j                  e      d             ddlZddlmZ  G d d      Zy)uT   tests/test_content_sanitizer.py — content_sanitizer.sanitize_output TDD 테스트.    )annotationsNz..)sanitize_outputc                  `    e Zd ZdZddZddZddZddZddZddZ	ddZ
dd	Zdd
ZddZy)TestSanitizeOutputu2   sanitize_output() — 봇 출력 필터링 검증.c                |   d}t        |      }||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                  |      dt        j                         v st        j
                  |      rt        j                  |      nddz  }dd|iz  }t        t        j                  |            d	x}}y	)
u2   일반 텍스트는 그대로 통과해야 한다.uL   안녕하세요, Claude입니다. 도움이 필요하시면 말씀하세요.==)z0%(py3)s
{%(py3)s = %(py0)s(%(py1)s)
} == %(py5)sr   text)py0py1py3py5zassert %(py7)spy7N	r   
@pytest_ar_call_reprcompare@py_builtinslocals_should_repr_global_name	_safereprAssertionError_format_explanation)selfr
   @py_assert2@py_assert4@py_format6@py_format8s         K/home/jay/workspace/services/multimodel-bot/tests/test_content_sanitizer.pytest_normal_text_passes_throughz2TestSanitizeOutput.test_normal_text_passes_through   s    ]t$,$,,,,$,,,,,,,,,,,,,,,t,,,t,,,$,,,,,,,,,,,,,,,,    c                   d}t        |      }d}||v}|st        j                  d|fd||f      t        j                  |      dt	        j
                         v st        j                  |      rt        j                  |      nddz  }dd|iz  }t        t        j                  |            d	x}}d
}||v}|st        j                  d|fd||f      t        j                  |      dt	        j
                         v st        j                  |      rt        j                  |      nddz  }dd|iz  }t        t        j                  |            d	x}}d}||v }|st        j                  d|fd||f      t        j                  |      dt	        j
                         v st        j                  |      rt        j                  |      nddz  }dd|iz  }t        t        j                  |            d	x}}y	)uI   CLAUDE.md 시스템 프롬프트 헤더 패턴을 필터링해야 한다.ud   # 오딘 - 개발2팀장

## 정체성
당신은 오딘입니다.

실제 응답 텍스트입니다.u   오딘 - 개발2팀장not inz%(py1)s not in %(py3)sresultr   r   assert %(py5)sr   Nu   ## 정체성u    실제 응답 텍스트입니다inz%(py1)s in %(py3)s	r   r   r   r   r   r   r   r   r   r   r
   r%   @py_assert0r   @py_format4r   s          r   test_filters_claude_md_headerz0TestSanitizeOutput.test_filters_claude_md_header   s"   z &'5'v5555'v555'555555v555v5555555+~V++++~V+++~++++++V+++V+++++++1;1V;;;;1V;;;1;;;;;;V;;;V;;;;;;;r    c                   d}t        |      }d}||v}|st        j                  d|fd||f      t        j                  |      dt	        j
                         v st        j                  |      rt        j                  |      nddz  }dd|iz  }t        t        j                  |            d	x}}d
}||v}|st        j                  d|fd||f      t        j                  |      dt	        j
                         v st        j                  |      rt        j                  |      nddz  }dd|iz  }t        t        j                  |            d	x}}d}||v }|st        j                  d|fd||f      t        j                  |      dt	        j
                         v st        j                  |      rt        j                  |      nddz  }dd|iz  }t        t        j                  |            d	x}}y	)u`   시스템 프롬프트 섹션 헤더(## 역할, ## 작업 규칙 등)를 필터링해야 한다.ul   ## 역할
백엔드 개발자입니다.
## 작업 규칙
코드를 작성하세요.

실제 답변입니다.u	   ## 역할r"   r$   r%   r&   r'   r   Nu   ## 작업 규칙u   실제 답변입니다r(   r*   r+   r,   s          r   #test_filters_system_prompt_sectionsz6TestSanitizeOutput.test_filters_system_prompt_sections   s%    C &({&(((({&((({((((((&(((&(((((((!/!////!///!////////////////'1'61111'6111'111111611161111111r    c                   d}t        |      }d}||v}|st        j                  d|fd||f      t        j                  |      dt	        j
                         v st        j                  |      rt        j                  |      nddz  }dd|iz  }t        t        j                  |            d	x}}d
}||v }|st        j                  d|fd||f      t        j                  |      dt	        j
                         v st        j                  |      rt        j                  |      nddz  }dd|iz  }t        t        j                  |            d	x}}d}||v }|st        j                  d|fd||f      t        j                  |      dt	        j
                         v st        j                  |      rt        j                  |      nddz  }dd|iz  }t        t        j                  |            d	x}}y	)uH   tool 실행 내용이 포함된 코드 블록을 필터링해야 한다.uO   답변입니다.

```shell
cat /home/jay/CLAUDE.md
```

이후 답변입니다.zcat /home/jay/CLAUDE.mdr"   r$   r%   r&   r'   r   N   답변입니다r(   r*   u   이후 답변입니다r+   r,   s          r   'test_filters_tool_execution_code_blocksz:TestSanitizeOutput.test_filters_tool_execution_code_blocks&   s%   f &(6(6666(666(6666666666666666 * F**** F*** ******F***F*******'1'61111'6111'111111611161111111r    c                   dj                  t        d      D cg c]  }d| d
 c}      }d| d}t        |      }d}||v}|st        j                  d|fd	||f      t        j
                  |      d
t        j                         v st        j                  |      rt        j
                  |      nd
dz  }dd|iz  }t        t        j                  |            dx}}d}||v}|st        j                  d|fd	||f      t        j
                  |      d
t        j                         v st        j                  |      rt        j
                  |      nd
dz  }dd|iz  }t        t        j                  |            dx}}d}||v }|st        j                  d|fd||f      t        j
                  |      d
t        j                         v st        j                  |      rt        j
                  |      nd
dz  }dd|iz  }t        t        j                  |            dx}}d}||v }|st        j                  d|fd||f      t        j
                  |      d
t        j                         v st        j                  |      rt        j
                  |      nd
dz  }dd|iz  }t        t        j                  |            dx}}yc c}w )uN   20줄 이상의 연속 코드 블록(파일 덤프)을 필터링해야 한다.
   zline z: some code contentu   답변입니다.

```
u   
```

결론입니다.zline 0: some code contentr"   r$   r%   r&   r'   r   Nzline 24: some code contentr3   r(   r*      결론입니다)joinranger   r   r   r   r   r   r   r   r   )	r   i
code_linesr
   r%   r-   r   r.   r   s	            r   test_filters_long_code_dumpsz/TestSanitizeOutput.test_filters_long_code_dumps.   s   YYb	R1%s*= >RS
*:,6OP &*8*&8888*&888*888888&888&8888888+9+69999+6999+999999699969999999 * F**** F*** ******F***F******* * F**** F*** ******F***F*******  Ss   Kc                   d}d| d}t        |      }d}||v }|st        j                  d|fd||f      t        j                  |      dt	        j
                         v st        j                  |      rt        j                  |      nddz  }d	d
|iz  }t        t        j                  |            dx}}d}||v }|st        j                  d|fd||f      t        j                  |      dt	        j
                         v st        j                  |      rt        j                  |      nddz  }d	d
|iz  }t        t        j                  |            dx}}y)u:   짧은 코드 블록(19줄 이하)은 보존해야 한다.zdef hello():
    return 'world'u#   예시 코드입니다:

```python
u    
```

이렇게 사용하세요.zdef hello():r(   r*   r%   r&   r'   r   Nzreturn 'world'r+   )r   coder
   r%   r-   r   r.   r   s           r    test_preserves_short_code_blocksz3TestSanitizeOutput.test_preserves_short_code_blocks8   s    17v=`a &'~''''~'''~'''''''''''''''')6))))6)))))))))6)))6)))))))r    c                   d}t        |      }d}||k(  }|st        j                  d|fd||f      dt        j                         v st        j
                  t               rt        j                  t               ndt        j                  |      t        j                  |      t        j                  |      dz  }dd|iz  }t        t        j                  |            dx}x}x}}y)	u>   빈 문자열 입력 시 빈 문자열을 반환해야 한다. r   )z0%(py4)s
{%(py4)s = %(py0)s(%(py2)s)
} == %(py7)sr   )r   py2py4r   zassert %(py9)spy9Nr   )r   @py_assert1@py_assert3@py_assert6@py_assert5r   @py_format10s          r   test_empty_string_returns_emptyz2TestSanitizeOutput.test_empty_string_returns_empty@   s    !(r"(b("b(((("b((((((((((((r((("(((b(((((((r    c                >   d}t        |      }t        |      }d}||kD  }|st        j                  d|fd||f      dt	        j
                         v st        j                  t              rt        j                  t              nddt	        j
                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      dz  }dd	|iz  }t        t        j                  |            d
x}x}}y
)u^   필터링 후 결과가 빈 문자열이면 원본을 반환해야 한다 (빈 응답 방지).u   ## 역할
개발자입니다.r   )>)z/%(py3)s
{%(py3)s = %(py0)s(%(py1)s)
} > %(py6)slenr%   )r   r   r   py6zassert %(py8)spy8N)
r   rN   r   r   r   r   r   r   r   r   )r   r
   r%   r   rI   r   @py_format7@py_format9s           r   test_filtered_result_not_emptyz1TestSanitizeOutput.test_filtered_result_not_emptyD   s    / &6{Q{Q{Qss66{Qr    c                   d}t        |      }d}||v}|st        j                  d|fd||f      t        j                  |      dt	        j
                         v st        j                  |      rt        j                  |      nddz  }dd|iz  }t        t        j                  |            d	x}}d
}||v }|st        j                  d|fd||f      t        j                  |      dt	        j
                         v st        j                  |      rt        j                  |      nddz  }dd|iz  }t        t        j                  |            d	x}}y	)u]   Read, Grep, Glob 등 tool 이름 패턴이 포함된 실행 블록을 필터링해야 한다.u   답변입니다.

```
Read file: /home/jay/workspace/CLAUDE.md
     1→# Content here
     2→More content
```

결론입니다.z
Read file:r"   r$   r%   r&   r'   r   Nr8   r(   r*   r+   r,   s          r   $test_filters_read_grep_tool_patternsz7TestSanitizeOutput.test_filters_read_grep_tool_patternsJ   s     \ &)|6))))|6)))|))))))6)))6))))))) * F**** F*** ******F***F*******r    c                    ddl }d}t        |      }|sedddt        j                         v st	        j
                  |      rt	        j                  |      ndiz  }t        t	        j                  |            y)uG   필터링 전/후 길이 차이를 DEBUG 레벨로 로깅해야 한다.r   Nu   ## 역할
내용
실제 답변zassert %(py0)sr   r%   )	loggingr   r   r   r   r   r   r   r   )r   rW   r
   r%   @py_format1s        r   test_logging_debug_outputz,TestSanitizeOutput.test_logging_debug_outputQ   s9     2 &vvvr    N)returnNone)__name__
__module____qualname____doc__r   r/   r1   r4   r=   r@   rK   rS   rU   rY    r    r   r   r      s7    <-
<22+*)+r    r   )r_   
__future__r   builtinsr   _pytest.assertion.rewrite	assertionrewriter   ossyspathinsertr9   dirname__file__pytestengine_v2.content_sanitizerr   r   r`   r    r   <module>rn      sU    Z "   	 
 277<< 94@ A  7J Jr    