
     jK                        d Z ddlmZ ddlZddlZddlZddlmZ ddlZ ee	      j                         j                  j                  j                  Z ee      ej                  v r!ej                  j                   ee             ej                  j!                  d ee             ddlmZmZmZmZmZmZmZmZmZ dZdZdZdd	Zdd
Zeefd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)u   
tests/regression/test_canonical_workspace_resolver_2517.py

헤임달 (QA 테스터) — task-2517 회귀 테스트 14건
canonical_workspace_resolver 4 ambiguity 구조적 제거 + 정상 흐름 + edge case + hook 통합
    )annotationsN)Path)	CanonicalWorkspaceassert_cwd_matches_workspaceassert_finish_task_contextassert_main_freshevaluate_scope_dirty	from_dictresolve_canonical_workspaceresolve_for_hooksto_json(a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2	task-2517ztask/task-2517-dev2c                     dd fd
}|S )zN
    responses key: tuple of args
    value: (returncode, stdout, stderr)
    Ncwdc                   t        |       }|vrt        d|d| d      |   \  }}}t        j                  | |||      S )NMock missing:  (cwd=)args
returncodestdoutstderr)tupleKeyError
subprocessCompletedProcess)r   r   keyrcouterr	responsess         N/home/jay/workspace/tests/regression/test_canonical_workspace_resolver_2517.pyrunnerz make_mock_runner.<locals>.runner0   sU    Dki^C7&Q?@@ ~C**CX[\\     )r$   r&   s   ` r%   make_mock_runnerr)   +   s    
 ! ] Mr'   c                &    d|  d| d| d| d| dS )N	worktree 
HEAD z"
branch refs/heads/main

worktree z
branch refs/heads/z

r(   )	main_rootworktree_pathbranchshas       r%   _porcelain_worktree_outputr1   9   sB    
I; u  "? #u #H %		r'   c                f    t        | |||      }d| ddfd|dfdd| ddfd| ddfd| ddfdS )u  공통으로 사용되는 mock runner 응답 맵을 반환한다.

    show-toplevel은 worktree_path를 반환한다 (git worktree 실제 동작).
    workspace_root는 git worktree list --porcelain의 첫 번째 entry(main_root)로 결정된다.
    is_main 판정은 cwd == workspace_root (== main_root) 비교이므로,
    worktree에서 호출하면 is_main=False가 된다.
    r   
 r   r4   r4   git	rev-parsez--show-toplevelr8   worktreelist--porcelainr8   fetchoriginmainz--quietr8   r9   zorigin/mainr8   r9   z--abbrev-refHEADr8   r9   rD   )r1   )r-   r.   r/   r0   	porcelains        r%   _make_standard_responsesrG   F   sl     +9mVSQI23b5I21N56	24F7B./C5R-@78VHB-6L'(SE*b&9 r'   c                   | dz  }|j                  d       d| dt         d}d| dd	fd|d	fd
dt         dd	fddt         dd	fd}t        |      }t        t        |d|      }|j
                  |j                         k(  sJ |j                  |j                         k(  sJ |j                  du sJ |j                  t        k(  sJ y)u?   main repo에서 resolve → workspace_root == cwd, is_main=TruerA   Tparentsr+   r,   
branch refs/heads/main

r   r3   r4   r5   r   zmain
r4   r6   r   r?   r&   N)
mkdirFAKE_SHAr)   r   TASK_IDworkspace_rootresolver   is_maintask_idtmp_pathr-   rF   r$   r&   wss         r%   test_resolve_in_main_reporX   ^   s    6!IOODO! I; z %	&  34	{"5Er1J56	24F7B./H:R"-E6G'(XJb/2&>I i(F	$W)4PV	WB	 1 1 333366Y&&((((::::   r'   c                   | dz  }| dz  dz  }|j                  d       |j                  d       t        t        |      t        |      t        t              }d| ddfd|dfd	dt         ddfdt         ddfdt         ddfd
}t        |      }t        t        |d|      }|j                  |j                         k(  sJ |j                  |j                         k(  sJ |j                  du sJ |j                  t        k(  sJ y)u   worktree에서 resolve → worktree_path == cwd, branch_name 매칭, is_main=False

    실제 git worktree에서 `git rev-parse --show-toplevel`은 main_root를 반환한다.
    따라서 workspace_root = main_root, cwd = worktree → is_main=False.
    rA   
.worktreestask-2517-dev2TrI   r   r3   r4   r5   r6   rM   FN)rN   r1   strBRANCHrO   r)   r   rP   r.   rR   r   rS   branch_name)rV   r-   r;   rF   r$   r&   rW   s          r%   test_resolve_in_worktreer_   |   s"    6!I,&)99HOODO!NN4N *3y>3x=&RZ[I 34	{"5Er1J56	24F7B./H:R"-E78VHB-6L'(XJb/2&>I i(F	$W($v	VBx//111166X%%''''::>>V###r'   c                *   | dz  }| dz  dz  }|j                  d       |j                  d       d}t        t        |      t        |      |      }t        |      }t	        t
        |d|      }|j                  |k(  sJ |j                  |k(  sJ y	)
u(   fetch 후 origin/main HEAD 정확 매칭rA   rZ   r[   TrI   (deadbeefdeadbeefdeadbeefdeadbeefdeadbeefr0   rM   N)rN   rG   r\   r)   r   rP   main_head_shabase_sha)rV   r-   r;   	fixed_shar$   r&   rW   s          r%   test_main_head_sha_lockrf      s    6!I,&)99HOODO!NN4N I(YXIVIi(F	$W($v	VBy(((;;)###r'   c                x   | dz  }| dz  dz  }|j                  d       |j                  d       d}|j                  d|       t        t        |      t        |            }t	        |      }t        t        |d|      }t        |j                        |k7  sJ |j                  |j                         k(  sJ y	)
uS   환경변수 WORKSPACE_ROOT 우선순위 — git rev-parse와 충돌 시 git 우선rA   rZ   r[   TrI   z/some/completely/wrong/pathWORKSPACE_ROOTrM   N	rN   setenvrG   r\   r)   r   rP   rQ   rR   )rV   monkeypatchr-   r;   stale_env_rootr$   r&   rW   s           r%   test_env_var_priority_git_winsrm      s    6!I,&)99HOODO!NN4N 2N'8(YXGIi(F	$W($v	VB r  !^333	 1 1 3333r'   c                f   | dz  }| dz  dz  }| dz  }|j                  d       |j                  d       |j                  d       t        t        |      t        |            }t        |      }t	        t
        |d|      }t        |j                  |j                  |j                  |j                  |j                  |j                  |j                         |j                  |j                  	      }t!        j"                  t$        d	
      5  t'        |       ddd       y# 1 sw Y   yxY w)uM   잘못된 cwd → assert_cwd_matches_workspace RuntimeError('WRONG_CWD: ...')rA   rZ   r[   some_other_dirTrI   rM   )	rT   rQ   r.   r^   rc   rd   r   rS   is_clean	WRONG_CWDmatchN)rN   rG   r\   r)   r   rP   r   rT   rQ   r.   r^   rc   rd   rR   rS   rp   pytestraisesRuntimeErrorr   )rV   r-   r;   	wrong_dirr$   r&   rW   ws_wrongs           r%   test_wrong_cwd_raisesry      s   6!I,&)99H++IOODO!NN4N OODO!(YXGIi(F	$W($v	VB "

((&&NN&&


H 
|;	7 /$X./ / /s   D''D0c                   | dz  }| dz  dz  |j                  d       j                  d       ddt        t        |      t              t              dd	id
dfd
}t	        t
        d|      }|j                  k(  sJ t        j                  t        d      5  t        ||       d
d
d
       y
# 1 sw Y   y
xY w)uZ   fetch 후 origin/main 변경 시뮬레이션 → assert_main_fresh FAIL('STALE_MAIN: ...')rA   rZ   r[   TrI   (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbnr   Nr   c               @   t        |       }|dk(  r5dxx   dz  cc<   d   dk(  r
n}t        j                  | d| dd      S d ddfd	dfddt         ddfd
 ddfd	}||vrt	        d
|d| d      ||   \  }}}t        j                  | |||      S )NrB   r}      r   r3   r4   r   r5   )r7   r:   r>   rC   rE   r   r   r   )r   r   r   r]   r   )r   r   r    r0   fixedr!   r"   r#   
call_countrF   sha1sha2r;   s           r%   stateful_runnerz/test_stale_main_raises.<locals>.stateful_runner   s    Dk55sOq O$S/Q.$DC..DQRUQVVXzbdee67H:R"5M9:Ir8J;F;<mR:P+,bk2*>
 e^C7&Q?@@SzC**CX[\\r'   rM   
STALE_MAINrr   r&   )rN   r1   r\   r]   r   rP   rc   rt   ru   rv   r   )	rV   r-   r   rW   r   rF   r   r   r;   s	       @@@@@r%   test_stale_main_raisesr      s    6!I,&)99HOODO!NN4N DD +3y>3x=&RVWIqJ%) ] ]$ 
%W($	_Bt### 
|<	8 6"_56 6 6s   .CCc                6   | dz  }| dz  dz  }|j                  d       |j                  d       dg}t        g d|z         }t        t        |      t        |            }d||<   t	        |      }t        t        |d|	      }t        |||
      }|du sJ y)uS   expected_files 외 파일이 dirty → evaluate_scope_dirty IS_CLEAN (False 반환)rA   rZ   r[   TrI   z%utils/canonical_workspace_resolver.py)r8   statusr=   z--r5   rM   r   FN)rN   r   rG   r\   r)   r   rP   r	   )	rV   r-   r;   expected_filesclean_status_keyr$   r&   rW   results	            r%   $test_dirty_workspace_false_detectionr     s    6!I,&)99HOODO!NN4N =>NCnTU(YXGI"-Ii(F	$W($v	VB ""nVDFU??r'   c                   | dz  }| dz  dz  }|j                  d       |j                  d       d}d}t        t        |      t        |      |      }d	| d
df|d<   t        |      }t	        t
        |d|      }||j                  t        |j                        d}t        j                  t        d      5  t        |||       ddd       y# 1 sw Y   yxY w)u|   HEAD SHA 변경 후 finish_target 불일치 → assert_finish_task_context RuntimeError('FINISH_TASK_CONTEXT_MISMATCH: ...')rA   rZ   r[   TrI   (cccccccccccccccccccccccccccccccccccccccc(ddddddddddddddddddddddddddddddddddddddddrb   r   r3   r4   rE   rM   head_shar^   r.   FINISH_TASK_CONTEXT_MISMATCHrr   r   N)rN   rG   r\   r)   r   rP   r^   r.   rt   ru   rv   r   )	rV   r-   r;   original_head_shachanged_head_shar$   r&   rW   finish_targets	            r%   !test_finish_task_context_mismatchr   )  s    6!I,&)99HOODO!NN4N  (YXL]^I 015E4Fb2I2.NI*+i(F	$W($v	VB &~~R--.M 
|+I	J E"2}VDE E Es   =CCc                R   | dz  }|j                  d       d| dt         d}d| dd	fd|d	fd
dt         dd	fddt         dd	fd}t        |      }t        t        |d|      }|j
                  J dt        |j
                        v sdt        |j
                        v sJ yy)ud   worktree 없을 때 resolve — worktree_path만 산출, 생성 X (실제 디렉토리 없어도 OK)rA   TrI   r+   r,   rK   r   r3   r4   r5   rL   r6   rM   Nr   dev1)rN   rO   r)   r   rP   r.   r\   rU   s         r%   "test_resolve_when_worktree_missingr   L  s    6!IOODO! I; z %	&  34	{"5Er1J56	24F7B./H:R"-E6G'(XJb/2&>I i(F	$W)4PV	WB '''#b..//6SAQAQ=R3RRR3R/r'   c                x   | dz  }| dz  dz  }|j                  d       |j                  d       d}|j                  d|       t        t        |      t        |            }t	        |      }t        t        |d|      }t        |j                        |k7  sJ |j                  |j                         k(  sJ y	)
u8   PROJECT_PATH 환경변수 stale 시 git rev-parse 우선rA   rZ   r[   TrI   z/old/stale/project/pathPROJECT_PATHrM   Nri   )rV   rk   r-   r;   stale_project_pathr$   r&   rW   s           r%   test_env_var_project_path_staler   l  s    6!I,&)99HOODO!NN4N 2~'9:(YXGIi(F	$W($v	VB r  !%7777	 1 1 3333r'   c                   | dz  }| dz  dz  }|j                  d       |j                  d       t        t        |      t        |            }t        |      }t	        t
        |d|      }t        |      }t        j                  |      }t        |      }|j                  |j                  k(  sJ |j                  |j                  k(  sJ |j                  |j                  k(  sJ |j                  |j                  k(  sJ |j                  |j                  k(  sJ |j                  |j                  k(  sJ |j                   |j                   k(  sJ |j"                  |j"                  k(  sJ |j$                  |j$                  k(  sJ y)uF   to_json → from_dict 라운드트립 무결성 (모든 필드 동일)rA   rZ   r[   TrI   rM   N)rN   rG   r\   r)   r   rP   r   jsonloadsr
   rT   rQ   r.   r^   rc   rd   r   rS   rp   )	rV   r-   r;   r$   r&   ws_originaljson_strparsedws_restoreds	            r%   (test_canonical_workspace_json_round_tripr     ss   6!I,&)99HOODO!NN4N (YXGIi(F-g84X^_K {#HZZ!FF#K +"5"5555%%)C)CCCC$$(A(AAAA""k&=&====$$(A(AAAA;#7#7777??koo---+"5"5555;#7#7777r'   c                   | dz  }| dz  dz  }|j                  d       |j                  d       t        t        |      t        |            }t        |      }t	        t
        d|d|      }t	        t
        d|d|      }|j                  |j                  k(  sJ |j                  |j                  k(  sJ |j                  |j                  k(  sJ |j                  |j                  k(  sJ y)	uW   resolve_for_hooks('scope-guard') 두 번 호출 시 동일 workspace fields (확정성)rA   rZ   r[   TrI   zscope-guardrM   N)
rN   rG   r\   r)   r   rP   rQ   r.   r^   rc   )rV   r-   r;   r$   r&   ws1ws2s          r%   &test_hook_scope_guard_shares_workspacer     s    6!I,&)99HOODO!NN4N (YXGIi(F
G]U[
\C
G]U[
\C !3!3333 1 1111??coo--- 1 1111r'   c                J   | dz  }| dz  dz  }|j                  d       |j                  d       t        t        |      t        |            }t        |      }t	        t
        d|d|      }t        |j                  t        |j                        d}t        |||	       y
)uW   resolve_for_hooks('finish-task') 결과로 assert_finish_task_context PASS (mismatch 0)rA   rZ   r[   TrI   zfinish-taskrM   r   r   N)
rN   rG   r\   r)   r   rP   rO   r^   r.   r   )rV   r-   r;   r$   r&   rW   r   s          r%   &test_hook_finish_task_shares_workspacer     s    6!I,&)99HOODO!NN4N (YXGIi(F	7MxtTZ	[B ~~R--.M r=@r'   c                h   | dz  }| dz  dz  }|j                  d       |j                  d       t        t        |      t        |            }t        |      }t	        t
        d|d|      }t	        t
        d|d|      }|j                  |j                  k(  sJ |j                  t        k(  sJ y	)
uM   resolve_for_hooks('smoke')와 resolve_for_hooks('qc')가 동일 main_head_sharA   rZ   r[   TrI   smokerM   qcN)rN   rG   r\   r)   r   rP   rc   rO   )rV   r-   r;   r$   r&   ws_smokews_qcs          r%   test_hooks_share_main_head_shar     s    6!I,&)99HOODO!NN4N (YXGIi(F 'xtTZ[HgtfUE !!U%8%8888!!X---r'   )r$   dict)
r-   r\   r.   r\   r/   r\   r0   r\   returnr\   )r-   r\   r.   r\   r/   r\   r0   r\   )/__doc__
__future__r   r   r   syspathlibr   rt   __file__rR   parent_WORKTREE_ROOTr\   pathremoveinsert"utils.canonical_workspace_resolverr   r   r   r   r	   r
   r   r   r   rO   rP   r]   r)   r1   rG   rX   r_   rf   rm   ry   r   r   r   r   r   r   r   r   r   r(   r'   r%   <module>r      s	   #   
   h'')0077>>~#(("HHOOC'( 3~& '
 
 
  6
	
 PVbj 0!<$@$$44/@%6R0EFS@4,8D2*A0.r'   