
    ji                         d Z ddlZddlmc mZ ddlZddlm	Z	 ddl
mZmZ ddlZddlmZ ej                   j#                  d e e	e      j(                               ddlmZmZmZ ej2                  de	de	fd	       Zej2                  de	de	fd
       Z G d d      Z G d d      Z G d d      Z G d d      Z G d d      Z y)u  TDD 테스트 — iptc_tagger.py IPTC/XMP 메타데이터 삽입 유틸리티.

테스트 범위:
- make_xmp_packet(): XMP 패킷 생성 (내용, 형식, trainedAlgorithmicMedia 포함)
- encode_iptc_iim(): IPTC IIM 바이트 인코딩
- tag_image(): PNG/JPEG 파일 태깅
    N)Path)	MagicMockpatch)Image)encode_iptc_iimmake_xmp_packet	tag_imagetmp_pathreturnc                 x    t        j                  ddd      }| dz  }|j                  t        |      d       |S )u)   테스트용 작은 PNG 이미지 생성.RGBd   r   )   r   r   colorztest.pngPNGformatr   newsavestrr
   imgps      :/home/jay/workspace/tools/ai-image-gen/test_iptc_tagger.py
sample_pngr      s9     ))E:[
9C:AHHSVEH"H    c                 x    t        j                  ddd      }| dz  }|j                  t        |      d       |S )u*   테스트용 작은 JPEG 이미지 생성.r   r   )r   r   r   r   ztest.jpgJPEGr   r   r   s      r   sample_jpegr"   #   s9     ))E:[
9C:AHHSVFH#Hr   c                   <    e Zd ZddZddZddZddZddZddZy)	TestMakeXmpPacketNc                 b   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}}y)	u@   make_xmp_packet() 반환값에 'trainedAlgorithmicMedia' 포함.trainedAlgorithmicMediainz%(py1)s in %(py3)sresultpy1py3assert %(py5)spy5N	r   
@pytest_ar_call_reprcompare	_saferepr@py_builtinslocals_should_repr_global_nameAssertionError_format_explanationselfr*   @py_assert0@py_assert2@py_format4@py_format6s         r   'test_contains_trained_algorithmic_mediaz9TestMakeXmpPacket.test_contains_trained_algorithmic_media2   sf     "(2(F2222(F222(222222F222F2222222r   c                 b   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}}y)	u4   반환값에 'Iptc4xmpExt:DigitalSourceType' 포함.zIptc4xmpExt:DigitalSourceTyper'   r)   r*   r+   r.   r/   Nr0   r9   s         r   $test_contains_xmp_iptc_ext_namespacez6TestMakeXmpPacket.test_contains_xmp_iptc_ext_namespace7   sf     ".8.&8888.&888.888888&888&8888888r   c                 f   t        d      }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	)
uC   make_xmp_packet(title='테스트') 반환값에 '테스트' 포함.	   테스트titler'   r)   r*   r+   r.   r/   Nr0   r9   s         r   !test_contains_title_when_providedz3TestMakeXmpPacket.test_contains_title_when_provided<   se     {3${f$$$${f$$${$$$$$$f$$$f$$$$$$$r   c                 h   t        dg      }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	)
uN   make_xmp_packet(keywords=['AI-generated']) 반환값에 'AI-generated' 포함.AI-generatedkeywordsr'   r)   r*   r+   r.   r/   Nr0   r9   s         r   test_contains_keyword_in_outputz1TestMakeXmpPacket.test_contains_keyword_in_outputA   sh     >*:;'~''''~'''~''''''''''''''''r   c                 X   t               }t        |t              }|sd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dt        j                         v st        j                  t              rt        j                  t              ndt        j                  |      dz  }t        t        j                  |            d}y)u   반환값이 str 타입.5assert %(py4)s
{%(py4)s = %(py0)s(%(py1)s, %(py2)s)
}
isinstancer*   r   py0r,   py2py4N)
r   rN   r   r4   r5   r1   r6   r3   r7   r8   r:   r*   @py_assert3@py_format5s       r   test_returns_stringz%TestMakeXmpPacket.test_returns_stringF   s     "&#&&&&&&&&z&&&z&&&&&&&&&&&&&&&&&#&&&#&&&&&&&&&&r   c                    t               }|j                  }d} ||      }|sddt        j                         v st	        j
                  |      rt	        j                  |      ndt	        j                  |      t	        j                  |      t	        j                  |      dz  }t        t	        j                  |            dx}x}}y)u$   반환값이 '<?xpacket' 로 시작.z	<?xpacketzLassert %(py6)s
{%(py6)s = %(py2)s
{%(py2)s = %(py0)s.startswith
}(%(py4)s)
}r*   )rP   rQ   rR   py6N)	r   
startswithr4   r5   r1   r6   r3   r7   r8   )r:   r*   @py_assert1rT   @py_assert5@py_format7s         r   test_xpacket_wrappingz'TestMakeXmpPacket.test_xpacket_wrappingK   sz     "  -- --------v---v--- -------------r   r   N)	__name__
__module____qualname__r?   rA   rF   rK   rV   r]    r   r   r$   r$   1   s     3
9
%
(
'
.r   r$   c                   ,    e Zd ZddZddZddZddZy)TestEncodeIptcIimNc                 X   t               }t        |t              }|sd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dt        j                         v st        j                  t              rt        j                  t              ndt        j                  |      dz  }t        t        j                  |            d}y)u,   encode_iptc_iim() 반환값이 bytes 타입.rM   rN   r*   bytesrO   N)
r   rN   rf   r4   r5   r1   r6   r3   r7   r8   rS   s       r   test_returns_bytesz$TestEncodeIptcIim.test_returns_bytesW   s     "&%((((((((z(((z((((((&(((&((((((%(((%((((((((((r   c                 b   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}}y)	u(   반환값에 IPTC 마커 b'\x1c' 포함.   r'   r)   r*   r+   r.   r/   N	r   r1   r2   r3   r4   r5   r6   r7   r8   r9   s         r   test_contains_iptc_markerz+TestEncodeIptcIim.test_contains_iptc_marker\   sc     " w&    w&   w      &   &       r   c                 f   t        d      }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=   title 있으면 record=2, dataset=5 (b'\x1c\x02\x05') 포함.u   테스트 타이틀rD   s   r'   r)   r*   r+   r.   r/   Nrj   r9   s         r   )test_with_title_contains_record2_dataset5z;TestEncodeIptcIim.test_with_title_contains_record2_dataset5a   sf     '<=(&((((&(((((((((&(((&(((((((r   c                 h   t        dg      }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@   keyword 있으면 record=2, dataset=25 (b'\x1c\x02\x19') 포함.rH   rI   s   r'   r)   r*   r+   r.   r/   Nrj   r9   s         r   ,test_with_keyword_contains_record2_dataset25z>TestEncodeIptcIim.test_with_keyword_contains_record2_dataset25f   sh     >*:;(&((((&(((((((((&(((&(((((((r   r^   )r_   r`   ra   rg   rk   rm   ro   rb   r   r   rd   rd   V   s    )
!
)
)r   rd   c                   L    e Zd ZdeddfdZdeddfdZdeddfdZdeddfdZy)TestTagImagePngr   r   Nc                    t        |ddg      }||k(  }|st        j                  d|fd||f      dt        j                         v st        j
                  |      rt        j                  |      nddt        j                         v st        j
                  |      rt        j                  |      nddz  }d	d
|iz  }t        t        j                  |            d}y)u8   PNG 태깅 시 입력 경로와 동일한 경로 반환.rC   rH   rE   rJ   ==z%(py0)s == %(py2)sr*   r   rP   rQ   assert %(py4)srR   N	r	   r1   r2   r4   r5   r6   r3   r7   r8   )r:   r   r*   rZ   @py_format3rU   s         r   test_returns_same_path_pngz*TestTagImagePng.test_returns_same_path_pngr   s{    :[NCST####v######v###v################r   c                 f   t        |       |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}}y)u   태깅 후 파일이 존재함.Aassert %(py4)s
{%(py4)s = %(py2)s
{%(py2)s = %(py0)s.exists
}()
}r   rP   rQ   rR   N	r	   existsr4   r5   r1   r6   r3   r7   r8   )r:   r   rZ   rT   rU   s        r   test_png_tagged_file_existsz+TestTagImagePng.test_png_tagged_file_existsw   sh    *  " """"""""z"""z""" """"""""""r   c                    t        |d       t        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}}y)
u1   태깅 후 PIL Image.open()으로 열 수 있음.u   읽기 테스트rD   N)is not)z%(py0)s is not %(py3)sr   )rP   r-   r.   r/   )r	   r   openr1   r2   r4   r5   r6   r3   r7   r8   )r:   r   r   r<   rZ   r=   r>   s          r   "test_png_is_readable_after_taggingz2TestTagImagePng.test_png_is_readable_after_tagging|   ss    *$67jj$s$s$ss$r   c                    t        |ddg       t        j                  |      }|j                  D ch c])  }d|j	                         v sd|j	                         v s(|+ }}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c c}w )u/   태깅된 PNG의 info에 XMP 관련 키 존재.u   XMP 테스트rH   rs   xmpxmlr   )>)z/%(py3)s
{%(py3)s = %(py0)s(%(py1)s)
} > %(py6)slenxmp_keys)rP   r,   r-   rX   zassert %(py8)spy8N)r	   r   r   infolowerr   r1   r2   r4   r5   r6   r3   r7   r8   )
r:   r   r   kr   r<   r[   @py_assert4r\   @py_format9s
             r   test_png_metadata_contains_xmpz.TestTagImagePng.test_png_metadata_contains_xmp   s    *O~>NOjj$"xxT!5AGGI+=!'')ASATT8} q }q    }q      s   s      8   8   }   q        Us   )E4E4)r_   r`   ra   r   r{   r   r   r   rb   r   r   rq   rq   q   sN    $T $d $
#d #t #
T d ! !$ !r   rq   c                   ,    e Zd ZdeddfdZdeddfdZy)TestTagImageJpegr"   r   Nc                    t        |d      }||k(  }|st        j                  d|fd||f      dt        j                         v st        j
                  |      rt        j                  |      nddt        j                         v st        j
                  |      rt        j                  |      nddz  }dd	|iz  }t        t        j                  |            d
}y
)u%   JPEG 태깅 시 동일 경로 반환.u   JPEG 테스트rD   rt   rv   r*   r"   rw   rx   rR   Nry   )r:   r"   r*   rZ   rz   rU   s         r   test_returns_same_path_jpegz,TestTagImageJpeg.test_returns_same_path_jpeg   sw    ;.>?$$$$v$$$$$$v$$$v$$$$$$$$$$$$$$$$r   c                 f   t        |       |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}}y)u   태깅 후 파일 존재.r}   r"   r~   Nr   )r:   r"   rZ   rT   rU   s        r   test_jpeg_tagged_file_existsz-TestTagImageJpeg.test_jpeg_tagged_file_exists   sh    +!!#!########{###{###!##########r   )r_   r`   ra   r   r   r   rb   r   r   r   r      s(    %t % %
$ $ $r   r   c                   <    e Zd ZdeddfdZdeddfdZdeddfdZy)TestTagImageEdgeCasesr
   r   Nc                     |dz  }t        j                  t              5  t        |       ddd       y# 1 sw Y   yxY w)u4   존재하지 않는 파일 전달 시 예외 발생.z	ghost.pngN)pytestraises	Exceptionr	   )r:   r
   nonexistents      r   &test_nonexistent_file_raises_exceptionz<TestTagImageEdgeCases.test_nonexistent_file_raises_exception   s5    ,]]9% 	#k"	# 	# 	#s   4=r   c                 f   t        d      }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)
uJ   keywords=None 전달 시 'AI-generated' 자동 포함 (XMP 패킷 확인).NrI   rH   r'   r)   r   r+   r.   r/   r0   )r:   r   r   r;   r<   r=   r>   s          r   *test_default_keywords_include_ai_generatedz@TestTagImageEdgeCases.test_default_keywords_include_ai_generated   se    t,$~$$$$~$$$~$$$$$$$$$$$$$$$$r   c                 Z   t        |      }t        |t              }|sd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dt        j                         v st        j                  t              rt        j                  t              ndt        j                  |      dz  }t        t        j                  |            d}y)u   반환값이 Path 타입.rM   rN   r*   r   rO   N)
r	   rN   r   r4   r5   r1   r6   r3   r7   r8   )r:   r   r*   rT   rU   s        r   test_returns_path_typez,TestTagImageEdgeCases.test_returns_path_type   s    :&&$''''''''z'''z''''''&'''&''''''$'''$''''''''''r   )r_   r`   ra   r   r   r   r   rb   r   r   r   r      s;    #t # #%T %d %
( ($ (r   r   )!__doc__builtinsr4   _pytest.assertion.rewrite	assertionrewriter1   syspathlibr   unittest.mockr   r   r   PILr   pathinsertr   __file__parentiptc_taggerr   r   r	   fixturer   r"   r$   rd   rq   r   r   rb   r   r   <module>r      s     
  *   3tH~,,- . C C  $   $ 4  . .J) )6! !>	$ 	$"( (r   