
    i                       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mZ ddlZ ee      j!                         j"                  d   Zedz  dz  Z ej(                  d	      d
        Zd Zd Zd Zd Zd Zd Zd Zd Zd Zy)u}  tests/state_machine/test_recoverable.py — task-2471 회귀 테스트.

토르가 commit 4795c5e2 에서 추가한 RECOVERABLE_BLOCKED 상태 + 전이 규칙을
영구 차단한다.

- ``RECOVERABLE_BLOCKED`` 가 ``STATES`` tuple 에 포함
- ``ALLOWED_TRANSITIONS["MERGING"]`` 에 ``"RECOVERABLE_BLOCKED"`` 포함
- ``ALLOWED_TRANSITIONS["RECOVERABLE_BLOCKED"]`` 가
  MERGING/FAILED/ESCALATED/PR_OPEN 모두 포함
- subprocess taskctl CLI 호출 없이 import + 정적 검증만 수행

worktree 경로 hardcode 절대 금지 — ``importlib.util.spec_from_file_location``
로 동적 로드.

헤임달(개발2팀 테스터) 작성.
    )annotationsN)Path   scriptsz
taskctl.pymodule)scopec                 N   t         j                  }  |        }|st        j                  dt                dz   dt	        j
                         v st        j                  t               rt        j                  t               ndt        j                  |       t        j                  |      dz  }t        t        j                  |            dx} }t        t        dz        }d}|t        j                  vr"t        j                  j                  d|       d	}	 t        j                   j#                  d
t        t                     }g } d}||u}|}|r|j$                  }d}	||	u}
|
}|slt        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  }| j)                  |       |rt        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  }| j)                  |       t        j*                  | d      i z  }dd|iz  }t        t        j                  |            dx}x} x}x}x}x}
}	t        j                   j-                  |      }|t        j.                  |j0                  <   |j$                  j3                  |       |r"	 t        j                  j5                  |       |S |S # t6        $ r Y |S w xY w# |r0	 t        j                  j5                  |       w # t6        $ r Y w w xY ww xY w)u   worktree 의 ``scripts/taskctl.py`` 를 절대 경로로 로드.

    sys.path 조작 없이 importlib 로 직접 로드하여 다른 워크트리의 동명 파일과
    충돌하지 않게 한다.
    ztaskctl.py not found: zC
>assert %(py4)s
{%(py4)s = %(py2)s
{%(py2)s = %(py0)s.exists
}()
}TASKCTL_PATH)py0py2py4Nr   Fr   Ttaskctl_recoverable_test_alias)is not)z%(py2)s is not %(py5)sspec)r   py5z%(py7)spy7)z5%(py11)s
{%(py11)s = %(py9)s.loader
} is not %(py14)s)py9py11py14z%(py16)spy16zassert %(py19)spy19)r
   exists
@pytest_ar_format_assertmsg@py_builtinslocals_should_repr_global_name	_safereprAssertionError_format_explanationstr	WORKSPACEsyspathinsert	importlibutilspec_from_file_locationloader_call_reprcompareappend_format_boolopmodule_from_specmodulesnameexec_moduleremove
ValueError)@py_assert1@py_assert3@py_format5scripts_diraddedr   @py_assert4@py_assert0@py_assert10@py_assert13@py_assert12@py_format6@py_format8@py_format15@py_format17@py_format18@py_format20mods                     ;/home/jay/workspace/tests/state_machine/test_recoverable.pytaskctl_modrE      sR    I I II$:<."IIIIIII<III<IIIIII IIIIII i)+,KE#((";'~~55,c,.?
 	<4;t4;DKK;t;Kt$;;;;;t4;;;;;;t;;;t;;;4;;;;;;;Kt;;;;;;D;;;D;;;K;;;t;;;;;;;;;;;;;;nn--d3!$DII$, J3J  J ,  sC   H!M0 =M   	M-,M-0N$4NN$	N N$N  N$c                   d}| j                   }||v }|st        j                  d|fd||f      t        j                  |      dt	        j
                         v st        j                  |       rt        j                  |       ndt        j                  |      dz  }t        j                  d| j                          dz   d|iz  }t        t        j                  |            d	x}x}}y	)
u4   ``RECOVERABLE_BLOCKED`` 가 STATES tuple 에 존재.RECOVERABLE_BLOCKEDin)z.%(py1)s in %(py5)s
{%(py5)s = %(py3)s.STATES
}rE   py1py3r   u&   RECOVERABLE_BLOCKED 미정의: STATES=z
>assert %(py7)sr   N)
STATESr   r*   r   r   r   r   r   r   r    rE   r9   r8   @py_assert2r=   r>   s         rD   "test_recoverable_blocked_in_statesrP   C   s      K$6$6  $66   $6    !      %0    %0    %7    11C1C0DE         c                   d}| j                   }||v}|st        j                  d|fd||f      t        j                  |      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}x}}y)	uL   ``RECOVERABLE_BLOCKED`` 는 terminal 이 아니어야 함 (transient block).rG   )not in)z;%(py1)s not in %(py5)s
{%(py5)s = %(py3)s.TERMINAL_STATES
}rE   rJ   assert %(py7)sr   N)	TERMINAL_STATESr   r*   r   r   r   r   r   r    rN   s         rD   %test_recoverable_blocked_not_terminalrV   J   sw     C(C(CC (CCCCC (CCCC CCCCCCCCCCCC(CCCCCCCCrQ   c                   | j                   j                  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  }t        j                  dt        |             dz   d	|iz  }t        t        j                  |            d
x}}y
)u8   MERGING 의 허용 전이에 RECOVERABLE_BLOCKED 포함.MERGINGrG   rH   z%(py1)s in %(py3)smerging_targetsrK   rL   u2   MERGING -> RECOVERABLE_BLOCKED 미허용: targets=z
>assert %(py5)sr   N)ALLOWED_TRANSITIONSgetsetr   r*   r   r   r   r   r   sortedr   r    )rE   rZ   r9   rO   @py_format4r=   s         rD   2test_merging_can_transition_to_recoverable_blockedra   T   s    !5599)SUKO   O3   O    !      %4    %4    =VO=T<UV    rQ   c                h   | j                   j                  dt                     }h d}||z
  }| }|s~t        j                  d|       dz   ddt        j                         v st        j                  |      rt        j                  |      ndiz  }t        t        j                  |            d}y)uN   MERGING 의 허용 전이는 {MERGED, FAILED, RECOVERABLE_BLOCKED} 를 포함.rX   >   FAILEDMERGEDrG   u   MERGING 의 누락된 전이: 
>assert not %(py0)sr   missingN)r\   r]   r^   r   r   r   r   r   r   r   r    )rE   rZ   expectedrf   r3   @py_format2s         rD   !test_merging_targets_set_completeri   \   sv    !5599)SUKO:H(G;B;BB8	BBBBBBBwBBBwBBBBBBrQ   c                   | j                   j                  dt                     }h d}||z
  }| }|st        j                  d| dt        |       d      dz   ddt        j                         v st        j                  |      rt        j                  |      ndiz  }t        t        j                  |            d	}y	)
uL   RECOVERABLE_BLOCKED 는 {MERGING, FAILED, ESCALATED, PR_OPEN} 모두 포함.rG   >   rc   rX   PR_OPEN	ESCALATEDu*   RECOVERABLE_BLOCKED 의 누락된 전이: u
    (실제: )re   r   rf   N)r\   r]   r^   r   r   r_   r   r   r   r   r   r    )rE   
rb_targetsrg   rf   r3   rh   s         rD    test_recoverable_blocked_targetsro   d   s    00445JCERJ<H#G; ;   5WIZzHZG[[\]              rQ   c                   | j                   j                  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}}y	)
uI   RECOVERABLE_BLOCKED -> MERGING 전이 허용 (cmd_recover 자동 복귀).rG   rX   rH   rY   rn   r[   assert %(py5)sr   Nr\   r]   r^   r   r*   r   r   r   r   r   r    rE   rn   r9   rO   r`   r=   s         rD   .test_recoverable_blocked_can_return_to_mergingrt   n   sv    00445JCERJ"9
""""9
"""9""""""
"""
"""""""rQ   c                   | j                   j                  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}}y	)
u/   RECOVERABLE_BLOCKED -> ESCALATED 전이 허용.rG   rl   rH   rY   rn   r[   rq   r   Nrr   rs   s         rD   %test_recoverable_blocked_can_escalaterv   t   sv    00445JCERJ$;*$$$$;*$$$;$$$$$$*$$$*$$$$$$$rQ   c                   d}| j                   }||v }|st        j                  d|fd||f      t        j                  |      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}x}}y)	uX   ALLOWED_TRANSITIONS dict 에 키로 존재 (entry 자체가 등록되어 있어야 함).rG   rH   )z;%(py1)s in %(py5)s
{%(py5)s = %(py3)s.ALLOWED_TRANSITIONS
}rE   rJ   rT   r   N)	r\   r   r*   r   r   r   r   r   r    rN   s         rD   2test_recoverable_blocked_key_exists_in_transitionsrx   z   sw     CK$C$CC $CCCCC $CCCC CCCCCCKCCCKCCC$CCCCCCCCrQ   c                   d}t        | |      }|st        j                  d      dz   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)
u?   ``cmd_recover`` 함수가 모듈에 정의되어 있어야 함.cmd_recoveruC   cmd_recover 함수 미정의 (토르 commit 4795c5e2 누락 의심)z7
>assert %(py5)s
{%(py5)s = %(py0)s(%(py1)s, %(py3)s)
}hasattrrE   )r   rK   rL   r   NzMassert %(py5)s
{%(py5)s = %(py0)s(%(py3)s
{%(py3)s = %(py1)s.cmd_recover
})
}callable)r{   r   r   r   r   r   r   r   r    rz   r|   )rE   rO   r8   r=   s       rD    test_cmd_recover_function_existsr}      sV    - 7;. .   	N                       !.    /       ++,8+,,,,,,,,8,,,8,,,,,,K,,,K,,,+,,,,,,,,,,rQ   )__doc__
__future__r   builtinsr   _pytest.assertion.rewrite	assertionrewriter   importlib.utilr&   r#   pathlibr   pytest__file__resolveparentsr"   r
   fixturerE   rP   rV   ra   ri   ro   rt   rv   rx   r}    rQ   rD   <module>r      s     #     
   N""$,,Q/	9$|3 h  HDC#%D-rQ   