
    Li>                       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
ddlZej                  j                  de
j                  j                  e
j                  j                  e      d             ddlmZmZ ddlmZ ddlmZmZmZ ddlZ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! G d d      Z" G d d      Z# G d d      Z$y)u   tests/test_engine_v2_phase5.py — Phase 5 TDD 테스트 스위트.

G13+G15: ChapterRunner, QCHook 검증.
작성 순서: 테스트 먼저(RED), 구현 후 GREEN 확인.
    )annotationsNz..)datetimetimezone)Path)	AsyncMock	MagicMockpatch)EngineResultc                f    t        || | |||||t        ddddddt        j                        	      S )u!   테스트용 EngineResult 생성.i           r   )tzinfo)	enginecontentcleantask_idsteperrorflagged_count	token_est	timestamp)r
   r   r   utc)r   r   r   r   r   r   r   s          J/home/jay/workspace/services/multimodel-bot/tests/test_engine_v2_phase5.py_make_resultr      sA     #4BAqF
 
    c                  J    e Zd ZdZej
                  j                  dd       Zy)TestChapterRunnerOutputDiru"   출력 디렉토리 생성 확인.c                \  	
K   ddl m} t        d      
t        dd      	t        dd      t        d	d
      t        dd      dd	
fd} |dddd      }t        d|      5  t        j                  |j
                  d|      5  |j                          d{    ddd       ddd       |dz  }|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}}|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7 g# 1 sw Y   gxY w# 1 sw Y   lxY ww)uB   run() 호출 시 chapter-N 디렉토리가 생성되어야 한다.r   ChapterRunneru   초안 내용)r      Gemini 초안geminir   r   u   집대성 결과u"   수정 불필요. 우수합니다.codexu   최종 결과claudec                T   K   |dk(  rgS |dk(  rgS |dk(  rgS |dk(  r	gS gS w)N      r       )
promptsenginesr   r   timeoutmock_result_geminimock_result_ok
mock_step2
mock_step3
mock_step5s
        r   fake_run_stepzXTestChapterRunnerOutputDir.test_chapter_runner_creates_output_dir.<locals>.fake_run_stepE   sP     qy&(:;;"|#"|#"|#"##s   %(c   z	task-testu	   가이드u   챕터 정보chapterr   guidechapter_info%publishing.chapter_runner._OUTPUT_DIRrun_stepside_effectNz
chapter-99Aassert %(py4)s
{%(py4)s = %(py2)s
{%(py2)s = %(py0)s.exists
}()
}chapter_dirpy0py2py4zAassert %(py4)s
{%(py4)s = %(py2)s
{%(py2)s = %(py0)s.is_dir
}()
}i  returnlist[EngineResult])publishing.chapter_runnerr!   r   r	   object_adapterrunexists@py_builtinslocals
@pytest_ar_should_repr_global_name	_safereprAssertionError_format_explanationis_dir)selftmp_pathr!   r4   runnerr?   @py_assert1@py_assert3@py_format5r/   r0   r1   r2   r3   s            @@@@@r   &test_chapter_runner_creates_output_dirzATestChapterRunnerOutputDir.test_chapter_runner_creates_output_dir:   s     	<%o>)/(S!*<XN
!*NW^_
!/(K
		$ 		$ r;k`op :HE 	#fooz}U #jjl""#	# -!!#!########{###{###!##########!!#!########{###{###!##########	 ## #	# 	#sI   A*H,1#HH(H)H-H5EH,HH	HH)$H,NrV   r   rF   None)__name__
__module____qualname____doc__pytestmarkasyncior[   r+   r   r   r   r   7   s!    ,[[$ $r   r   c                  J    e Zd ZdZej
                  j                  dd       Zy)TestChapterRunnerStep1Parallelu-   Step 1이 claude+gemini 병렬 호출 확인.c                  K   ddl m} g ddfd} |dddd      }t        d|      5  t        j                  |j                  d	|
      5  |j                          d{    ddd       ddd       D cg c]  }|d   dk(  s| }}t        |      }d}||k(  }	|	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}	}d}|d   d   }||v }|slt        j                  d|fd||f      t        j                  |      t        j                  |      dz  }dd|iz  }
t        t        j                  |
            dx}x}}d}|d   d   }||v }|slt        j                  d|fd||f      t        j                  |      t        j                  |      dz  }dd|iz  }
t        t        j                  |
            dx}x}}y7 B# 1 sw Y   BxY w# 1 sw Y   GxY wc c}w w)u<   Step 1은 claude와 gemini를 동시에 호출해야 한다.r   r    c                  K   j                  |t        |      d       |dk(  rt        dd      t        dd      gS |dk(  rt        d	d      gS |d
k(  rt        dd      gS |dk(  rt        dd      gS t               gS w)Nr   r-   r(   u   Claude 초안r&   r$   r"   r#   r)   	   집대성r   "   수정 불필요. 충분합니다.r%   r*      최종appendlistr   r,   r-   r   r   r.   captured_callss        r   r4   zXTestChapterRunnerStep1Parallel.test_chapter_runner_step1_parallel.<locals>.fake_run_stepf   s     !!4DM"JKqy J J  $[JKK$-QZabcc$XhGHH N##   BBr(   z
task-step1 r6   r:   r;   r<   Nr   ==z0%(py3)s
{%(py3)s = %(py0)s(%(py1)s)
} == %(py6)slenstep1_callsrA   py1py3py6assert %(py8)spy8r&   r-   inz%(py1)s in %(py4)srz   rC   assert %(py6)sr|   r#   rD   rE   rH   r!   r	   rI   rJ   rK   rw   rO   _call_reprcomparerM   rN   rP   rQ   rR   rS   )rU   rV   r!   r4   rW   crx   @py_assert2@py_assert5@py_assert4@py_format7@py_format9@py_assert0rY   rZ   rq   s                  @r   "test_chapter_runner_step1_parallelzATestChapterRunnerStep1Parallel.test_chapter_runner_step1_parallel_   s     	<%'	$ q,bWYZ:HE 	#fooz}U #jjl""#	#
 #1CQAfINqCC;$1$1$$$$1$$$$$$s$$$s$$$$$$;$$$;$$$$$$1$$$$$$$4;q>)44x44444x4444x444444444444;q>)44x44444x4444x44444444444 ## #	# 	#
 DsY   (K#J4J'"J$#J''J4/K;K	KHK$J''J1	,J44J>9KNr\   )r^   r_   r`   ra   rb   rc   rd   r   r+   r   r   rf   rf   \   s!    7[[5 5r   rf   c                  J    e Zd ZdZej
                  j                  dd       Zy)!TestChapterRunnerStep5ClaudeFinalu,   Step 5가 claude 엔진으로 호출 확인.c                  K   ddl m} g ddfd} |dddd      }t        d|      5  t        j                  |j                  d	|
      5  |j                          d{    ddd       ddd       D cg c]  }|d   dk(  s| }}t        |      }d}||k(  }	|	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}	}|d   d   }dg}||k(  }|slt        j                  d|fd||f      t        j                  |      t        j                  |      dz  }dd|iz  }
t        t        j                  |
            dx}x}}y7 # 1 sw Y   xY w# 1 sw Y   xY wc c}w w)u9   Step 5는 반드시 claude 엔진을 사용해야 한다.r   r    c                  K   j                  |t        |      d       |dk(  rt        dd      t        dd      gS |dk(  rt        d	d      gS |d
k(  rt        dd      gS |dk(  rt        dd      gS t               gS w)Nri   r(      초안1r&   r$      초안2r#   r)   rj   r   rk   r%   r*   u   최종 통합rm   rp   s        r   r4   z_TestChapterRunnerStep5ClaudeFinal.test_chapter_runner_step5_claude_final.<locals>.fake_run_step   s     !!4DM"JKqy 8D 8D  $[JKK$-QZabcc$_XNOO N##rr   r)   z
task-step5rs   r6   r:   r;   r<   Nr   r*   r(   rt   rv   rw   step5_callsry   r}   r~   r-   r&   z%(py1)s == %(py4)sr   r   r|   rD   rE   r   )rU   rV   r!   r4   rW   r   r   r   r   r   r   r   r   rY   rZ   rq   s                  @r   &test_chapter_runner_step5_claude_finalzHTestChapterRunnerStep5ClaudeFinal.test_chapter_runner_step5_claude_final   s     	<%'	$ q,bWYZ:HE 	#fooz}U #jjl""#	# #1CQAfINqCC;$1$1$$$$1$$$$$$s$$$s$$$$$$;$$$;$$$$$$1$$$$$$$1~i(6XJ6(J6666(J666(666J6666666	 ## #	# 	# DsY   (I#H4H'"H$#H''H4/I;I	IFI$H''H1	,H44H>9INr\   )r^   r_   r`   ra   rb   rc   rd   r   r+   r   r   r   r      s!    6[[7 7r   r   c                  J    e Zd ZdZej
                  j                  dd       Zy)$TestChapterRunnerConsensusStopsAtMaxu$   최대 3라운드 후 종료 확인.c                $  K   ddl m} ddlm} dddfd} |dddd      }t	        d	|      5  t	        j
                  |j                  d
|      5  |j                          d{    ddd       dd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}d}	|	k\  }|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7 # 1 sw Y   xY w# 1 sw Y   xY ww)uL   Step 3-4 반복이 MAX_CONSENSUS_ROUNDS(3) 이하로 수행되어야 한다.r   r    )MAX_CONSENSUS_ROUNDSc                  K   |dk(  rt        dd      t        dd      gS |dk(  rt        dd      gS |d	k(  rdz  t        d
d      gS |dk(  rt        dd      gS |dk(  rt        dd      gS t               gS w)Nr(   r   r&   r$   r   r#   r)   rj   r   u&   수정 필요. 오류가 있습니다.r%      u   반영된 내용r*   rl   )r   )r,   r-   r   r   r.   step3_call_counts        r   r4   zfTestChapterRunnerConsensusStopsAtMax.test_chapter_runner_consensus_stops_at_max.<locals>.fake_run_step   s     qy 8D 8D  $[JKK A% $-U^efgg$-?QRR$XhGHH N##s   A<A?r   ztask-consensusrs   r6   r:   r;   r<   N)<=)z%(py0)s <= %(py2)sr   r   )rA   rB   zassert %(py4)srC   r(   )>=)z%(py0)s >= %(py3)s)rA   r{   assert %(py5)spy5rD   rE   )rH   r!   publishing.consensus_pipeliner   r	   rI   rJ   rK   rO   r   rM   rN   rP   rQ   rR   rS   )rU   rV   r!   r   r4   rW   rX   @py_format3rZ   r   @py_format4@py_format6r   s               @r   *test_chapter_runner_consensus_stops_at_maxzOTestChapterRunnerConsensusStopsAtMax.test_chapter_runner_consensus_stops_at_max   sY     	<F	$& q2B"[]^:HE 	#fooz}U #jjl""#	#
  #77777#7777777777777777#7777#77777777#$$1$$$$1$$$$$$$$$$$$1$$$$$$$	 ## #	# 	#sG   .H#HG6(G3)G6-H5E>H3G66H 	;HHHNr\   )r^   r_   r`   ra   rb   rc   rd   r   r+   r   r   r   r      s!    .[["% "%r   r   c                  0    e Zd ZdZddZddZddZddZy)TestParseArgsu   CLI 인수 파싱 확인.c                d   ddl m}  |g d      }|j                  }d}||k(  }|st        j                  d|fd||f      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}}|j                  }d}||k(  }|st        j                  d|fd||f      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}}|j                  }d}||k(  }|st        j                  d|fd||f      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}}|j                  }d}||k(  }|st        j                  d|fd||f      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)uB   --chapter와 --task-id가 필수 인수로 파싱되어야 한다.r   
parse_args)	--chapter5	--task-idtask-007r*   rt   z/%(py2)s
{%(py2)s = %(py0)s.chapter
} == %(py5)sargsrA   rB   r   assert %(py7)spy7Nr   z/%(py2)s
{%(py2)s = %(py0)s.task_id
} == %(py5)srs   z-%(py2)s
{%(py2)s = %(py0)s.guide
} == %(py5)sz4%(py2)s
{%(py2)s = %(py0)s.chapter_info
} == %(py5)srH   r   r7   rO   r   rM   rN   rP   rQ   rR   rS   r   r8   r9   rU   r   r   rX   r   rY   r   @py_format8s           r   test_parse_args_requiredz&TestParseArgs.test_parse_args_required   s   8EF|| q |q    |q      t   t   |   q       ||)z)|z))))|z))))))t)))t)))|)))z)))))))zzRzRzRttzR  &B& B&&&& B&&&&&&t&&&t&&& &&&B&&&&&&&r   c                d   ddl m}  |g d      }|j                  }d}||k(  }|st        j                  d|fd||f      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}}|j                  }d}||k(  }|st        j                  d|fd||f      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}}|j                  }d}||k(  }|st        j                  d|fd||f      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}}|j                  }d}||k(  }|st        j                  d|fd||f      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)uB   --guide와 --chapter-info 선택 인수가 파싱되어야 한다.r   r   )r   3r   task-003z--guide   집필가이드 내용z--chapter-info   챕터 3 정보r   rt   r   r   r   r   r   Nr   r   r   r   r   r   r   r   s           r   test_parse_args_optionalz&TestParseArgs.test_parse_args_optional   s   8	
 || q |q    |q      t   t   |   q       ||)z)|z))))|z))))))t)))t)))|)))z)))))))zz555z55555z5555555t555t555z55555555555  5$55 $55555 $5555555t555t555 555$55555555r   c                    ddl m} t        j                  t              5   |ddg       ddd       y# 1 sw Y   yxY w)u9   --chapter가 없으면 SystemExit이 발생해야 한다.r   r   r   task-001NrH   r   rb   raises
SystemExitrU   r   s     r   &test_parse_args_missing_chapter_raisesz4TestParseArgs.test_parse_args_missing_chapter_raises   s3    8]]:& 	2Z01	2 	2 	2   4=c                    ddl m} t        j                  t              5   |ddg       ddd       y# 1 sw Y   yxY w)u9   --task-id가 없으면 SystemExit이 발생해야 한다.r   r   r   1Nr   r   s     r   &test_parse_args_missing_task_id_raisesz4TestParseArgs.test_parse_args_missing_task_id_raises   s3    8]]:& 	+S)*	+ 	+ 	+r   NrF   r]   )r^   r_   r`   ra   r   r   r   r   r+   r   r   r   r      s    #'6*2+r   r   c                       e Zd ZdZddZddZy)TestQCHookOnEngineCompleteu*   on_engine_complete() 파일 생성 확인.c                N	   ddl m}  ||      }t        dddddd	      }|j                  |       |d
z  }|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}}t        j                  |j                  d            }	|	d   }
d}|
|k(  }|slt        j                  d|fd|
|f      t        j                  |
      t        j                  |      dz  }dd|iz  }t        t        j                  |            dx}
x}}|	d   }
d}|
|k(  }|slt        j                  d|fd|
|f      t        j                  |
      t        j                  |      dz  }dd|iz  }t        t        j                  |            dx}
x}}|	d   }
d}|
|k(  }|slt        j                  d|fd|
|f      t        j                  |
      t        j                  |      dz  }dd|iz  }t        t        j                  |            dx}
x}}|	d   }
d}|
|u }|slt        j                  d|fd|
|f      t        j                  |
      t        j                  |      dz  }dd|iz  }t        t        j                  |            dx}
x}}|	d   }
d}|
|k(  }|slt        j                  d|fd|
|f      t        j                  |
      t        j                  |      dz  }dd|iz  }t        t        j                  |            dx}
x}}|	d   }
d}|
|k(  }|slt        j                  d|fd|
|f      t        j                  |
      t        j                  |      dz  }dd|iz  }t        t        j                  |            dx}
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)&uF   on_engine_complete() 호출 시 JSON 파일이 생성되어야 한다.r   
FileQCHook
output_diru   엔진 응답r&   ztask-qc-001r(   *   )r   r   r   r   r   r   ztask-qc-001_step1_claude.jsonr>   expected_filer@   Nutf-8encodingr   rt   r   r   r   r|   r   r   r   Fisz%(py1)s is %(py4)sr   r   r   r   )z%(py1)s in %(py3)sdata)rz   r{   r   r   engine_v2.qc_hookr   r   on_engine_completerL   rM   rN   rO   rP   rQ   rR   rS   jsonloads	read_textr   )rU   rV   r   hookresultr   rX   rY   rZ   r   r   r   r   r   r   s                  r   test_qc_hook_on_engine_completez:TestQCHookOnEngineComplete.test_qc_hook_on_engine_complete  s   0X.#!
 	' #BB##%#%%%%%%%%}%%%}%%%#%%%%%%%%%%zz-1171CDH~))~))))~)))~))))))))))I/-/-////-//////-///////F| q |q    |q   |   q       G}%%}%%%%}%%%}%%%%%%%%%%O$))$))))$)))$))))))))))K &B& B&&&& B&&& &&&B&&&&&&&"{d""""{d"""{""""""d"""d"""""""r   c                   ddl m}  ||      }t        ddddd	      }|j                  |       |d
z  }|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}}t        j                  |j                  d            }	|	d   }
d}|
|u }|slt        j                  d|fd|
|f      t        j                  |
      t        j                  |      dz  }dd|iz  }t        t        j                  |            dx}
x}}|	d   }
d}|
|k(  }|slt        j                  d|fd|
|f      t        j                  |
      t        j                  |      dz  }dd|iz  }t        t        j                  |            dx}
x}}y)u7   에러 결과도 JSON 파일로 기록되어야 한다.r   r   r   rs   r#   Tztask-qc-errr   )r   r   r   r   r   ztask-qc-err_step3_gemini.jsonr>   r   r@   Nr   r   r   r   r   r   r   r|   r   rt   r   r   )rU   rV   r   r   r   r   rX   rY   rZ   r   r   r   r   s                r   ,test_qc_hook_on_engine_complete_error_resultzGTestQCHookOnEngineComplete.test_qc_hook_on_engine_complete_error_result$  sY   0X.!
 	' #BB##%#%%%%%%%%}%%%}%%%#%%%%%%%%%%zz-1171CDG}$$}$$$$}$$$}$$$$$$$$$$H~))~))))~)))~))))))))))r   Nr\   )r^   r_   r`   ra   r   r   r+   r   r   r   r     s    4#8*r   r   c                  (    e Zd ZdZddZddZddZy)TestQCHookOnPipelineCompleteu2   on_pipeline_complete() summary.json 생성 확인.c           	     8   ddl m}  ||      }t        dddd      t        d	d
dd      t        ddddd      g}|j                  |       |dz  }|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}}t        j                  |j                  d            }	|	d   }
d}|
|k(  }|slt        j                  d|fd|
|f      t        j                  |
      t        j                  |      dz  }dd|iz  }t        t        j                  |            dx}
x}}|	d   }
d}|
|k(  }|slt        j                  d|fd|
|f      t        j                  |
      t        j                  |      dz  }dd|iz  }t        t        j                  |            dx}
x}}|	d   }
d}|
|k(  }|slt        j                  d|fd|
|f      t        j                  |
      t        j                  |      dz  }dd|iz  }t        t        j                  |            dx}
x}}d}
|	d    }|
|v }|slt        j                  d!|fd"|
|f      t        j                  |
      t        j                  |      dz  }dd|iz  }t        t        j                  |            dx}
x}}d
}
|	d    }|
|v }|slt        j                  d!|fd"|
|f      t        j                  |
      t        j                  |      dz  }dd|iz  }t        t        j                  |            dx}
x}}d}
|	d    }|
|v }|slt        j                  d!|fd"|
|f      t        j                  |
      t        j                  |      dz  }dd|iz  }t        t        j                  |            dx}
x}}y)#uJ   on_pipeline_complete() 호출 시 _summary.json이 생성되어야 한다.r   r   r      결과1r&   ztask-pipe-001r(   )r   r   r   r      결과2r#   r)   rs   r%   r   T)r   r   r   r   r   ztask-pipe-001_summary.jsonr>   r   r@   Nr   r   r   rt   r   r   r   r|   total_stepserrorsengines_usedr   r   )r   r   r   on_pipeline_completerL   rM   rN   rO   rP   rQ   rR   rS   r   r   r   r   )rU   rV   r   r   resultsr   rX   rY   rZ   r   r   r   r   s                r   !test_qc_hook_on_pipeline_completez>TestQCHookOnPipelineComplete.test_qc_hook_on_pipeline_complete>  s   0X.8_[\]8_[\]G_ST\`a
 	!!'* #??##%#%%%%%%%%}%%%}%%%#%%%%%%%%%%zz-1171CDI1/1/1111/111111/1111111M"'a'"a''''"a'''"'''a'''''''H~""~""""~"""~""""""""""/4//x/////x////x////////////4//x/////x////x///////////.$~..w.....w....w...........r   c           	        ddl m}  ||      }|j                  g        |j                  } |       }t	        |      }g }||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                  |      t        j                  |      t        j                  |      t        j                  |      dz  }	d	d
|	iz  }
t        t        j                  |
            dx}x}x}x}}y)uZ   빈 결과 목록에서 on_pipeline_complete()가 파일을 생성하지 않아야 한다.r   r   r   rt   )ze%(py7)s
{%(py7)s = %(py0)s(%(py5)s
{%(py5)s = %(py3)s
{%(py3)s = %(py1)s.iterdir
}()
})
} == %(py10)sro   rV   )rA   rz   r{   r   r   py10zassert %(py12)spy12N)r   r   r   iterdirro   rO   r   rM   rN   rP   rQ   rR   rS   )rU   rV   r   r   r   r   @py_assert6@py_assert9@py_assert8@py_format11@py_format13s              r   'test_qc_hook_on_pipeline_complete_emptyzDTestQCHookOnPipelineComplete.test_qc_hook_on_pipeline_complete_emptyV  s    0X.!!"% $$-$&-t&'-2-'2----'2------t---t------H---H---$---&---'---2--------r   c                   ddl m}  ||      }t        ddddd	      t        d
dddd	      g}|j                  |       t	        j
                  |dz  j                  d            }|d   }d}||k(  }|slt        j                  d|fd||f      t        j                  |      t        j                  |      dz  }	dd|	iz  }
t        t        j                  |
            dx}x}}y)u@   total_flagged가 flagged_count 합계로 기록되어야 한다.r   r   r   r   r&   z	task-flagr(   r)   )r   r   r   r   r   r   r#   r   ztask-flag_summary.jsonr   r   total_flaggedr*   rt   r   r   r   r|   N)r   r   r   r   r   r   r   rO   r   rQ   rR   rS   )rU   rV   r   r   r   r   r   rY   r   rZ   r   s              r   /test_qc_hook_on_pipeline_complete_flagged_totalzLTestQCHookOnPipelineComplete.test_qc_hook_on_pipeline_complete_flagged_total`  s    0X.8[WXhij8[WXhij

 	!!'*zz8&>>IISZI[\O$))$))))$)))$))))))))))r   Nr\   )r^   r_   r`   ra   r   r   r   r+   r   r   r   r   ;  s    </0.*r   r   c                  (    e Zd ZdZddZddZddZy)TestQCHandlerProtocolu4   QCHandler Protocol 인터페이스 적합성 확인.c                   ddl m}m}  ||      }d}t        ||      }|sd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  }t        t        j                  |            d	x}}d
}t        ||      }|sd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  }t        t        j                  |            d	x}}|j                  }t        |      }|sd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  }t        t        j                  |            d	x}}|j                  }t        |      }|sd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  }t        t        j                  |            d	x}}y	)u8   FileQCHook이 QCHandler Protocol을 충족해야 한다.r   )r   	QCHandlerr   r   z5assert %(py5)s
{%(py5)s = %(py0)s(%(py1)s, %(py3)s)
}hasattrr   )rA   rz   r{   r   Nr   zTassert %(py5)s
{%(py5)s = %(py0)s(%(py3)s
{%(py3)s = %(py1)s.on_engine_complete
})
}callablezVassert %(py5)s
{%(py5)s = %(py0)s(%(py3)s
{%(py3)s = %(py1)s.on_pipeline_complete
})
})r   r   r  r  rM   rN   rO   rP   rQ   rR   rS   r   r  r   )rU   rV   r   r  r   r   r   r   s           r   "test_qc_handler_protocol_file_hookz8TestQCHandlerProtocol.test_qc_handler_protocol_file_hooks  s   ;X. 22wt122222222w222w222222t222t2221222222222234wt344444444w444w444444t444t44434444444444//0x/00000000x000x000000000000/0000000000112x122222222x222x22222222222212222222222r   c                   ddl m}  G d d      } |       }t               }|j                  |       |j	                  |g       |j
                  }t        |      }d}||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                  |      t        j                  |      t        j                  |      d
z  }
dd|
iz  }t        t        j                  |            dx}x}x}	}|j                  }d}||u }|st        j                  d|fd||f      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>   커스텀 QCHandler 구현이 Protocol을 충족해야 한다.r   )r  c                  (    e Zd ZdZddZddZddZy)	]TestQCHandlerProtocol.test_qc_handler_protocol_custom_implementation.<locals>.CustomQCHandleru   커스텀 QC 핸들러.c                     g | _         d| _        y )NF)	completedpipeline_done)rU   s    r   __init__zfTestQCHandlerProtocol.test_qc_handler_protocol_custom_implementation.<locals>.CustomQCHandler.__init__  s    57+0"r   c                :    | j                   j                  |       y )N)r  rn   )rU   r   s     r   r   zpTestQCHandlerProtocol.test_qc_handler_protocol_custom_implementation.<locals>.CustomQCHandler.on_engine_complete  s    %%f-r   c                    d| _         y )NT)r  )rU   r   s     r   r   zrTestQCHandlerProtocol.test_qc_handler_protocol_custom_implementation.<locals>.CustomQCHandler.on_pipeline_complete  s
    %)"r   Nr   )r   r
   rF   r]   )r   rG   rF   r]   )r^   r_   r`   ra   r  r   r   r+   r   r   CustomQCHandlerr
    s    )1.*r   r  r(   rt   )zO%(py5)s
{%(py5)s = %(py0)s(%(py3)s
{%(py3)s = %(py1)s.completed
})
} == %(py8)srw   custom)rA   rz   r{   r   r~   zassert %(py10)sr   NTr   )z5%(py2)s
{%(py2)s = %(py0)s.pipeline_done
} is %(py5)sr   r   r   )r   r  r   r   r   r  rw   rO   r   rM   rN   rP   rQ   rR   rS   r  )rU   rV   r  r  r  r   r   r   @py_assert7r   r   r   rX   rY   r   r   s                   r   .test_qc_handler_protocol_custom_implementationzDTestQCHandlerProtocol.test_qc_handler_protocol_custom_implementation  sX   /	* 	* !"!!&)##VH-##)s#$))$))))$))))))s)))s))))))6)))6)))#)))$))))))))))##+t+#t++++#t++++++v+++v+++#+++t+++++++r   c                   ddl m} |dz  dz  }|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}x}} ||	      }|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=   FileQCHook이 output_dir을 자동으로 생성해야 한다.r   r   nestedqczEassert not %(py4)s
{%(py4)s = %(py2)s
{%(py2)s = %(py0)s.exists
}()
}new_dirr@   Nr   r>   )
r   r   rL   rM   rN   rO   rP   rQ   rR   rS   )
rU   rV   r   r  rX   rY   r   r   r   rZ   s
             r   -test_qc_hook_creates_output_dir_automaticallyzCTestQCHandlerProtocol.test_qc_hook_creates_output_dir_automatically  s    0X%,>>#>###########7###7###>##########W-~~~ww~r   Nr\   )r^   r_   r`   ra   r  r  r  r+   r   r   r  r  p  s    >
3,2 r   r  )u   정상 응답r&   Fr   r(   r   
   )r   strr   r  r   boolr   r  r   intr   r  r   r  rF   r
   )%ra   
__future__r   builtinsrM   _pytest.assertion.rewrite	assertionrewriterO   r   ossyspathinsertjoindirname__file__r   r   pathlibr   unittest.mockr   r   r	   rb   engine_v2.engine_resultr
   r   r   rf   r   r   r   r   r   r  r+   r   r   <module>r-     s   #    	 
 277<< 94@ A '  5 5  0 #  	
    8"$ "$J#5 #5L!7 !7H&% &%R.+ .+l3* 3*l2* 2*j0  0 r   