
    wj                        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
mZ ddlZddlmZmZmZ ddlmZ dZdZd	Zd
edd	 	 	 ddZddZd Zd Zd Zd Zd Zy)u  task-2554+2 §5 신규 fixture #3: 동일 PR + 동일 head 2회 호출 시 2번째 DEDUPED 판정.

회장 §명시 (2026-05-12): 동일 (pr, head) trigger 시도가 반복되면 atomic dedupe 로 2번째
호출이 ``RESULT_DEDUPED`` + http_post 정확히 1회만 발생.
    )annotationsN)Path)OwnerTriggerAuditRESULT_DEDUPEDRESULT_POSTED)OwnerTriggerOnly(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb(cccccccccccccccccccccccccccccccccccccccci   zdecision.jsonprheadfnamec               x    dd||dddddddd}| |z  }|j                  t        j                  |      d	
       |S )Nz anu_v2.owner_trigger_decision.v1ztask-2554+2-testTFr   "POST_GEMINI_REVIEW_TRIGGER_COMMENTz/gemini review)schematask_idr   current_head
queue_headcurrent_head_confirmedgemini_evidence_freshnudge_count_for_pr_headallowed_actioncomment_bodyallowedzutf-8)encoding)
write_textjsondumps)tmp_pathr   r   r   decisionps         G/home/jay/workspace/anu_v2/tests/test_owner_trigger_dedupe_same_head.py_write_decisionr%      sV     5%"&!&#$>(H 	5ALLH%L8H    c                R    g t        |       }fd}t        | |d |      }||fS )Nc                H    j                  | |t        |      d       ddiS )N)methodpathbodystatus   )appenddict)r)   r*   r+   headerspostss       r$   	http_postz _build_module.<locals>.http_post3   s$    d4jIJ#r&   c                      y)Nzowner-token r4   r&   r$   <lambda>z_build_module.<locals>.<lambda>:   s    r&   )workspace_rootr2   token_provideraudit)r   r   )r!   r8   r2   modr1   s       @r$   _build_moduler:   /   s>    Eh'E ,	C ur&   c                P   t        |       }t        |       \  }}}|j                  |ddt              }|j                  |ddt              }|j                  }|t
        k(  }|st        j                  d|fd|t
        f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      dt        j                         v st        j                  t
              rt        j                  t
              nddz  }	d	d
|	iz  }
t        t        j                  |
            dx}}|j                  }|t        k(  }|st        j                  d|fd|t        f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      dt        j                         v st        j                  t              rt        j                  t              nddz  }	d	d
|	iz  }
t        t        j                  |
            d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}}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}}y)uO   동일 (pr=105, head=_HEAD_A) 2회 호출 → 2번째 DEDUPED + http_post 1회.ordecision_pathownerrepocurrent_head_actual==z.%(py2)s
{%(py2)s = %(py0)s.status
} == %(py4)sr1r   py0py2py4assert %(py6)spy6Nr2r   DEDUPE)z2%(py2)s
{%(py2)s = %(py0)s.error_code
} == %(py5)s)rH   rI   py5zassert %(py7)spy7   z0%(py3)s
{%(py3)s = %(py0)s(%(py1)s)
} == %(py6)slenr1   rH   py1py3rL   assert %(py8)spy8)r%   r:   trigger_gemini_review_HEAD_Ar,   r   
@pytest_ar_call_reprcompare@py_builtinslocals_should_repr_global_name	_safereprAssertionError_format_explanationr   
error_coderS   )r!   r?   r9   r1   r8   rF   rM   @py_assert1@py_assert3@py_format5@py_format7@py_assert4@py_format6@py_format8@py_assert2@py_assert5@py_format9s                    r$   2test_same_pr_same_head_second_call_returns_dedupedrn   @   sM   #H-M%h/C		"	"#3Sg 
# 
B 
	"	"#3Sg 
# 
B 99%9%%%%9%%%%%%2%%%2%%%9%%%%%%%%%%%%%%%%99&9&&&&9&&&&&&2&&&2&&&9&&&&&&&&&&&&&&&&==$H$=H$$$$=H$$$$$$2$$$2$$$=$$$H$$$$$$$u::?:33uu:r&   c           	     f   t        |       }t        |       \  }}}t        d      D cg c]  }|j                  |ddt               }}|D cg c]  }|j
                   }}t        t        t        g}	||	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}
}	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}}yc c}w c c}w )uQ   동일 (pr, head) 3회 호출 → 1차 POSTED, 2차/3차 DEDUPED. http_post 1회.   r<   r=   r>   rC   )z%(py0)s == %(py3)sstatuses)rH   rV   zassert %(py5)srO   NrQ   rR   rS   r1   rT   rW   rX   )r%   r:   rangerY   rZ   r,   r   r   r[   r\   r]   r^   r_   r`   ra   rb   rS   )r!   r?   r9   r1   r8   _resultsr=   rq   rk   rd   @py_format4ri   rl   rh   rg   rm   s                    r$   +test_same_head_three_calls_only_first_postsrv   Q   sm   #H-M%h/C
 q	  	!!'sRY 	" 	
G  #**Q*H*%~~FF8FFFFF8FFFFFFF8FFF8FFFFFFFFFFFu::?:33uu: +s    H)H.c                   t        | t        d      }t        | t        d      }t        |       \  }}}|j	                  |ddt              }|j	                  |ddt              }|j
                  }|t        k(  }	|	st        j                  d|	fd|t        f      d	t        j                         v st        j                  |      rt        j                  |      nd	t        j                  |      d
t        j                         v st        j                  t              rt        j                  t              nd
dz  }
dd|
iz  }t        t        j                  |            dx}}	|j
                  }|t        k(  }	|	st        j                  d|	fd|t        f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      d
t        j                         v st        j                  t              rt        j                  t              nd
dz  }
dd|
iz  }t        t        j                  |            dx}}	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}}y)uQ   동일 PR 의 head 가 변경되면 각각 별도 trigger — 2개 모두 POSTED.za.json)r   r   zb.jsonr<   r=   r>   rC   rE   r_ar   rG   rK   rL   Nr_b   rR   rS   r1   rT   rW   rX   )r%   rZ   _HEAD_Br:   rY   r,   r   r[   r\   r]   r^   r_   r`   ra   rb   rS   )r!   d_ad_br9   r1   rs   rx   ry   rd   re   rf   rg   rk   rl   rh   rm   s                   r$   3test_different_head_same_pr_each_post_independentlyr~   `   s   
(
AC
(
AC!(+MC

#
#3G $ C 
#
#3G $ C ::&:&&&&:&&&&&&3&&&3&&&:&&&&&&&&&&&&&&&&::&:&&&&:&&&&&&3&&&3&&&:&&&&&&&&&&&&&&&&u::?:33uu:r&   c                   t        | dt        d      }t        | dt        d      }t        |       \  }}}|j                  |ddt              }|j                  |ddt              }|j                  }|t
        k(  }	|	st        j                  d	|	fd
|t
        f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      dt        j                         v st        j                  t
              rt        j                  t
              nddz  }
dd|
iz  }t        t        j                  |            dx}}	|j                  }|t
        k(  }	|	st        j                  d	|	fd
|t
        f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      dt        j                         v st        j                  t
              rt        j                  t
              nddz  }
dd|
iz  }t        t        j                  |            dx}}	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}}y)uk   다른 PR 의 head 가 우연히 같아도 (테스트 시나리오) PR 단위로 독립 — 둘 다 POSTED.h   z	p104.jsonr   r   z	p105.jsonr<   r=   r>   rC   rE   rF   r   rG   rK   rL   NrM   rz   rR   rS   r1   rT   rW   rX   )r%   _HEAD_Cr:   rY   r,   r   r[   r\   r]   r^   r_   r`   ra   rb   rS   )r!   d_p1d_p2r9   r1   rs   rF   rM   rd   re   rf   rg   rk   rl   rh   rm   s                   r$   3test_different_pr_same_head_each_post_independentlyr   p   s   8'MD8'MD!(+MC		"	"#CW 
# 
B 
	"	"#CW 
# 
B 99%9%%%%9%%%%%%2%%%2%%%9%%%%%%%%%%%%%%%%99%9%%%%9%%%%%%2%%%2%%%9%%%%%%%%%%%%%%%%u::?:33uu:r&   c                   t        |       }t        |       \  }}}|j                  |ddt               |j                  |ddt               t	        |j                               }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}||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   }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   }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   }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)uC   2번째 (DEDUPED) 호출도 audit 에 기록 (atomic, lock 내부).r<   r=   r>   rp   rC   rR   rS   rowsrT   rW   rX   Nr   resultPENDING)z%(py1)s == %(py4)s)rU   rJ   rK   rL   rQ   POSTEDrz   DEDUPEDrc   rN   )r%   r:   rY   rZ   list
_iter_rowsrS   r[   r\   r]   r^   r_   r`   ra   rb   )r!   r?   r9   rs   r8   r   rk   rl   rh   rg   rm   @py_assert0re   rf   s                 r$   #test_deduped_record_logged_in_auditr      sN   #H-M!(+MCE#3Sg   #3Sg     "#Dt99>933tt978)	)	))))	))))))	)))))))78(((((((((((((((((((78)	)	))))	))))))	)))))))7< ,H, H,,,, H,,, ,,,H,,,,,,,r&   )
r!   r   r   intr   strr   r   returnr   )r!   r   )__doc__
__future__r   builtinsr]   _pytest.assertion.rewrite	assertionrewriter[   r   pathlibr   pytestanu_v2.owner_trigger_auditr   r   r   anu_v2.owner_trigger_onlyr   rZ   r{   r   r%   r:   rn   rv   r~   r   r   r4   r&   r$   <module>r      sy    #      
 7 

 25'!059(""  -r&   