
    i*                     H   d Z ddlZddlmZ ddlZej
                  j                  d e ee      j                  j                  j                               ddl
mZmZmZmZ dZdZdZdZ G d	 d
      Z G d d      Z G d d      Zedk(  r ej.                  edg       yy)u/   utils/patch_parser.py 테스트 스위트 (TDD)    N)Path)apply_patchgenerate_patchparse_patchverify_patchzS--- a/hello.py
+++ b/hello.py
@@ -1,3 +1,3 @@
 line1
-line2
+line2_modified
 line3
z--- a/multi.py
+++ b/multi.py
@@ -1,4 +1,4 @@
 alpha
-beta
+beta_new
 gamma
 delta
@@ -10,4 +10,4 @@
 echo
-foxtrot
+foxtrot_new
 golf
 hotel
zH--- a/add.py
+++ b/add.py
@@ -1,2 +1,4 @@
 first
 second
+third
+fourth
zJ--- a/del.py
+++ b/del.py
@@ -1,4 +1,2 @@
 keep1
-remove1
-remove2
 keep2
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)TestParsePatchu   parse_patch() 단위 테스트c                 B    t        t              }t        |      dk(  sJ y)u.   단순 패치 파싱 — 파일 엔트리 1개   Nr   SIMPLE_PATCHlenselfresults     N/home/jay/workspace/.worktrees/task-2116-dev1/utils/tests/test_patch_parser.py(test_simple_patch_returns_one_file_entryz7TestParsePatch.test_simple_patch_returns_one_file_entryJ   s    \*6{a    c                 V    t        t              }|d   d   dk(  sJ |d   d   dk(  sJ y)u!   old_file / new_file 경로 파싱r   old_file
a/hello.pynew_file
b/hello.pyNr   r   r   s     r   test_simple_patch_file_namesz+TestParsePatch.test_simple_patch_file_namesO   s:    \*ay$444ay$444r   c                 N    t        t              }t        |d   d         dk(  sJ y)u   단순 패치 hunk 1개r   hunksr   Nr   r   s     r   test_simple_patch_hunk_countz+TestParsePatch.test_simple_patch_hunk_countU   s(    \*6!9W%&!+++r   c                     t        t              d   d   d   }|d   dk(  sJ |d   dk(  sJ |d   dk(  sJ |d   dk(  sJ y	)
u?   hunk 헤더 파싱 (old_start, old_count, new_start, new_count)r   r   	old_startr   	old_count   	new_start	new_countNr   r   hunks     r   test_simple_patch_hunk_headerz,TestParsePatch.test_simple_patch_hunk_headerZ   sg    <(+G4Q7K A%%%K A%%%K A%%%K A%%%r   c                 j    t        t              d   d   d   }d|d   v sJ d|d   v sJ d|d   v sJ y)u   hunk lines 내용 확인r   r   z line1linesz-line2z+line2_modifiedNr   r%   s     r   test_simple_patch_hunk_linesz+TestParsePatch.test_simple_patch_hunk_linesb   sQ    <(+G4Q74=(((4=((( DM111r   c                 N    t        t              }t        |d   d         dk(  sJ y)u    여러 hunk 파싱 — hunk 2개r   r      N)r   MULTI_HUNK_PATCHr   r   s     r   test_multi_hunk_patch_countz*TestParsePatch.test_multi_hunk_patch_counti   s)    -.6!9W%&!+++r   c                 \    t        t              d   d   d   }|d   dk(  sJ |d   dk(  sJ y)u   두 번째 hunk 헤더 파싱r   r   r   r    
   r#   N)r   r-   r%   s     r   "test_multi_hunk_second_hunk_headerz1TestParsePatch.test_multi_hunk_second_hunk_headern   sB    +,Q/8;K B&&&K B&&&r   c                 (    t        d      }|g k(  sJ y)u&   빈 패치 텍스트 → 빈 리스트 Nr   r   s     r   #test_empty_patch_returns_empty_listz2TestParsePatch.test_empty_patch_returns_empty_listt   s    R||r   c                 (    t        d      }|g k(  sJ y)u)   공백만 있는 패치 → 빈 리스트z   

   Nr4   r   s     r   -test_whitespace_only_patch_returns_empty_listz<TestParsePatch.test_whitespace_only_patch_returns_empty_listy   s    \*||r   c                 \    t        t              d   d   d   }|d   dk(  sJ |d   dk(  sJ y)u&   추가 라인 패치 hunk count 확인r   r   r!   r,   r$      N)r   ADDED_LINES_PATCHr%   s     r   "test_added_lines_patch_hunk_countsz1TestParsePatch.test_added_lines_patch_hunk_counts~   sB    ,-a09!<K A%%%K A%%%r   c                 \    t        t              d   d   d   }|d   dk(  sJ |d   dk(  sJ y)u&   삭제 라인 패치 hunk count 확인r   r   r!   r9   r$   r,   N)r   DELETED_LINES_PATCHr%   s     r   $test_deleted_lines_patch_hunk_countsz3TestParsePatch.test_deleted_lines_patch_hunk_counts   sB    ./27;A>K A%%%K A%%%r   N)__name__
__module____qualname____doc__r   r   r   r'   r*   r.   r1   r5   r7   r;   r>    r   r   r	   r	   G   s<    ( 
5,
&2,
'

&&r   r	   c                   (    e Zd ZdZd Zd Zd Zd Zy)TestGeneratePatchu!   generate_patch() 단위 테스트c                 4    t        dd      }d|v sJ d|v sJ y)u$   unified diff --- / +++ 헤더 생성zline1
line2
zline1
line2_new
z---z+++Nr   r   patchs     r   *test_generate_produces_unified_diff_headerz<TestGeneratePatch.test_generate_produces_unified_diff_header   s(    /1EF~~~~r   c                 :    t        dddd      }d|v sJ d|v sJ y)u%   fromfile / tofile 파라미터 반영zold
znew
zsrc.pyzdst.pyfromfiletofileNrG   rH   s     r   #test_generate_with_custom_filenamesz5TestGeneratePatch.test_generate_with_custom_filenames   s.    w(8T5   5   r   c                 *    t        dd      }|dk(  sJ y)u   동일 내용 → 빈 패치zsame
r3   NrG   rH   s     r   +test_generate_identical_content_empty_patchz=TestGeneratePatch.test_generate_identical_content_empty_patch   s    x2{{r   c                 `    t        dd      }|dk7  sJ t        |      }t        |      dk\  sJ y)u0   생성된 패치가 parse_patch로 파싱 가능za
b
c
z
a
b_new
c
r3   r   N)r   r   r   )r   rI   r   s      r   test_generate_patch_parseablez/TestGeneratePatch.test_generate_patch_parseable   s6    {O<{{U#6{ar   N)r?   r@   rA   rB   rJ   rO   rQ   rS   rC   r   r   rE   rE      s    +!
 r   rE   c                   j    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y)TestApplyPatchu/   apply_patch() / verify_patch() 통합 테스트c                     |dz  }|j                  d       t        dddd      }t        ||      }|du sJ |j                         dk(  sJ y)	u   단순 패치 적용 성공zhello.pyline1
line2
line3
zline1
line2_modified
line3
r   r   rL   TN
write_textr   r   	read_text)r   tmp_pathtargetrI   r   s        r   test_apply_simple_patch_successz.TestApplyPatch.test_apply_simple_patch_success   sf    J&1268Xco  yE  FVU+~~!%EEEEr   c                     |dz  }d}d}|j                  |       t        ||      }t        ||       |j                         |k(  sJ y)u-   패치 적용 후 파일 내용 변경 확인zfile.txtzalpha
beta
gamma
zalpha
beta_changed
gamma
NrX   )r   r[   r\   originalmodifiedrI   s         r   test_apply_patch_modifies_filez-TestApplyPatch.test_apply_patch_modifies_file   sQ    J&)1(#x2FE"!X---r   c                 \    |dz  }|j                  d       t        |t              }|du sJ y)u'   컨텍스트 불일치 시 False 반환zmismatch.pycompletely
different
content
FN)rY   r   r   r   r[   r\   r   s       r   /test_apply_patch_context_mismatch_returns_falsez>TestApplyPatch.test_apply_patch_context_mismatch_returns_false   s3    M)<=V\2r   c                 ~    |dz  }d}|j                  |       t        |t               |j                         |k(  sJ y)u&   패치 실패 시 원본 파일 유지zsafe.pyrc   N)rY   r   r   rZ   )r   r[   r\   r_   s       r   -test_apply_patch_file_not_modified_on_failurez<TestApplyPatch.test_apply_patch_file_not_modified_on_failure   s@    I%5(#FL)!X---r   c                 6    t        |dz  t              }|du sJ y)u5   존재하지 않는 파일에 패치 시 False 반환zghost.pyFN)r   r   )r   r[   r   s      r   /test_apply_patch_nonexistent_file_returns_falsez>TestApplyPatch.test_apply_patch_nonexistent_file_returns_false   s    X
2LAr   c                     |dz  }d}|j                  |       t        |d      }t        t        |      |      }|du sJ y)u-   문자열 경로로 apply_patch 호출 가능zstr_path.txtrW   line1
line2_mod
line3
TN)rY   r   r   str)r   r[   r\   r_   rI   r   s         r   $test_apply_patch_accepts_string_pathz3TestApplyPatch.test_apply_patch_accepts_string_path   sH    N**(#x)DES[%0~~r   c                     d}d}|dz  }|j                  |       t        ||      }t        ||      }|du sJ |j                         |k(  sJ y)u.   generate_patch → apply_patch 라운드트립zfoo
bar
baz
zfoo
bar_updated
baz
qux
zroundtrip.txtTNrX   )r   r[   r_   r`   r\   rI   r   s          r   "test_roundtrip_generate_then_applyz1TestApplyPatch.test_roundtrip_generate_then_apply   s_    $1O+(#x2VU+~~!X---r   c                 l    |dz  }d}|j                  |       t        |d      }t        ||      du sJ y)u0   verify_patch — 적용 가능한 패치에 Truez
verify.txtrW   rk   TN)rY   r   r   r   r[   r\   r_   rI   s        r   (test_verify_patch_returns_true_for_validz7TestApplyPatch.test_verify_patch_returns_true_for_valid   sA    L(*(#x)DEFE*d222r   c                 X    |dz  }|j                  d       t        |t              du sJ y)u0   verify_patch — 컨텍스트 불일치에 Falsezno_match.pyrc   FN)rY   r   r   )r   r[   r\   s      r   ,test_verify_patch_returns_false_for_mismatchz;TestApplyPatch.test_verify_patch_returns_false_for_mismatch   s0    M)<=FL1U:::r   c                     |dz  }d}|j                  |       t        |d      }t        ||       |j                         |k(  sJ y)u3   verify_patch 호출 후 파일 내용 변경 없음zunchanged.txtrW   rk   N)rY   r   r   rZ   rq   s        r   &test_verify_patch_does_not_modify_filez5TestApplyPatch.test_verify_patch_does_not_modify_file   sM    O+*(#x)DEVU#!X---r   c                 T    |dz  }|j                  d       t        |d      }|du sJ y)u0   빈 패치(변경 없음) 적용 시 True 반환zno_change.txtzcontent
r3   TN)rY   r   rd   s       r   #test_apply_empty_patch_returns_truez2TestApplyPatch.test_apply_empty_patch_returns_true  s2    O++&VR(~~r   c                     |dz  }d}d}|j                  |       t        ||      }t        ||      }|du sJ |j                         |k(  sJ y)u   라인 추가 패치 적용zadd.txtzfirst
second
zfirst
second
third
fourth
TNrX   r   r[   r\   r_   r`   rI   r   s          r   test_apply_added_lines_patchz+TestApplyPatch.test_apply_added_lines_patch  s_    I%$3(#x2VU+~~!X---r   c                     |dz  }d}d}|j                  |       t        ||      }t        ||      }|du sJ |j                         |k(  sJ y)u   라인 삭제 패치 적용zdel.txtzkeep1
remove1
remove2
keep2
zkeep1
keep2
TNrX   rz   s          r   test_apply_deleted_lines_patchz-TestApplyPatch.test_apply_deleted_lines_patch  s_    I%5#(#x2VU+~~!X---r   c                 2    t        |dz  t              du sJ y)u1   존재하지 않는 파일 verify_patch → Falsezmissing.txtFN)r   r   )r   r[   s     r   0test_verify_patch_nonexistent_file_returns_falsez?TestApplyPatch.test_verify_patch_nonexistent_file_returns_false#  s    H}4lCuLLLr   c                     |dz  }d}d}|j                  |d       t        ||      }t        ||      }|du sJ |j                  d      |k(  sJ y)u+   유니코드 내용 파일에 패치 적용zunicode.txtu   안녕
세계
끝
u   안녕
세상
끝
zutf-8)encodingTNrX   rz   s          r   $test_apply_multiline_unicode_contentz3TestApplyPatch.test_apply_multiline_unicode_content'  si    M)**(W5x2VU+~~1X===r   N)r?   r@   rA   rB   r]   ra   re   rg   ri   rm   ro   rr   rt   rv   rx   r{   r}   r   r   rC   r   r   rU   rU      sR    9F..
	.3;.	.	.M	>r   rU   __main__z-v)rB   syspathlibr   pytestpathinsertrl   __file__parentutils.patch_parserr   r   r   r   r   r-   r:   r=   r	   rE   rU   r?   mainrC   r   r   <module>r      s    5 
   3tH~,,33::; < U U "   A& A&R   B> >D zFKK4 ! r   