
    >i?                     L   d Z ddlZddlmc mZ ddlZddl	Z	ddl
Z
ddlZddlZddlZddlmZmZmZ ddlmZ ddlmZ ddlZdZej.                  j1                  de
j2                  j5                  edd	            Zej.                  j9                  e      Zeej<                  d<   ej>                  jA                  e       ejB                  Z!ejD                  Z"ejF                  Z#ejH                  Z$ej.                  j1                  d
e
j2                  j5                  edd            Z%ej.                  j9                  e%      Z&e%j>                  jA                  e&        ejN                  d      d        Z( ejN                         defd       Z) ejN                         defd       Z* G d d      Z+ G d d      Z, G d d      Z- G d d      Z. ejN                         d        Z/ G d d      Z0 G d d      Z1 G d d       Z2 G d! d"      Z3 G d# d$      Z4 G d% d&      Z5y)'u   
tests/dev7/test_done_semantics.py

옵션 D 시맨틱 핵심 동작 검증 (task-2374)
Phase 마커 3개 (work-done / merged / merge-failed) × 시나리오 4개 매트릭스

카마소츠(개발7팀 테스터) 작성
    N)datetime	timedeltatimezone)Path)	MagicMockz-/home/jay/workspace/.worktrees/task-2374-dev7auto_merge_wtscriptszauto_merge.pydone_watcherzdone-watcher.pyT)autousec                 j    | dz  dz  }|j                  dd       |j                  t        d|       |S )u8   auto_merge._STATE_DIR을 tmp_path 기반으로 redirect.memorystateTparentsexist_ok
_STATE_DIR)mkdirsetattr
auto_merge)tmp_pathmonkeypatch	state_dirs      O/home/jay/workspace/.worktrees/task-2374-dev7/tests/dev7/test_done_semantics.py_patch_state_dirr   7   s;     8#g-IOOD4O0
L)<    returnc                 <    | dz  dz  }|j                  dd       |S )Nr   eventsTr   )r   )r   ds     r   
events_dirr    @   s&    8h&AGGD4G(Hr   c                     | dz  dz  S )Nr   r    )r   s    r   r   r   G   s    h((r   c                       e Zd Zd Zd Zd Zy)TestCreateMergedMarkerAtomicc                 H   t        |dd      }d}||z  }||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t        j                  |      d	z  }d
d|i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?   _create_merged_marker가 .merged 파일을 atomic 생성한다.	task-9999abc123merge_commit_shatask-9999.merged==z%(py0)s == (%(py2)s / %(py4)s)resultr    py0py2py4assert %(py7)spy7NAassert %(py4)s
{%(py4)s = %(py2)s
{%(py2)s = %(py0)s.exists
}()
})
_create_merged_marker
@pytest_ar_call_reprcompare@py_builtinslocals_should_repr_global_name	_safereprAssertionError_format_explanationexists
selfr    r   r.   @py_assert3@py_assert5@py_assert1@py_format6@py_format8@py_format5s
             r   test_creates_merged_filez5TestCreateMergedMarkerAtomic.test_creates_merged_fileQ   s    &z;QYZ&88&888v88888v8888888v888v888888888888&88888888}}}vv}r   c                    t        |dd       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}}|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)u>   .merged 파일 내용에 task_id / merge_commit_sha가 있다.r&   r'   r(   r*   utf-8encodingtask_idr+   z%(py1)s == %(py4)spy1r2   assert %(py6)spy6Nr)   	merged_atinz%(py1)s in %(py3)sdatarP   py3assert %(py5)spy5)r6   jsonloads	read_textr7   r8   r<   r=   r>   r9   r:   r;   rA   r    r   rW   @py_assert0rB   @py_assert2rG   @py_format7@py_format4rE   s              r   !test_merged_file_has_correct_jsonz>TestCreateMergedMarkerAtomic.test_merged_file_has_correct_jsonX   s*   j+Qzz:(::EEwEWXI-+-+----+------+-------&'383'83333'8333'33383333333"{d""""{d"""{""""""d"""d"""""""r   c                    t        |dd       t        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}	}y)u.   state.json의 phase가 merged로 갱신된다.r&   r'   r(   task-9999.jsonr5   
state_filer/   NrJ   rK   phasemergedr+   rN   rO   rQ   rR   r)   )r6   r   r   r?   r9   r:   r7   r;   r<   r=   r>   r\   r]   r^   r8   )rA   r    r   rg   rD   rB   rG   r   r`   ra   rb   s              r   test_state_json_phase_mergedz9TestCreateMergedMarkerAtomic.test_state_json_phase_mergeda   s:   j+Q**-==
  " """"""""z"""z""" """"""""""

:///ABW~))~))))~)))~))))))))))'(4H4(H4444(H444(444H4444444r   N)__name__
__module____qualname__rH   rd   rj   r"   r   r   r$   r$   P   s    #5r   r$   c                       e Zd Zd Zy) TestCreateMergedMarkerIdempotentc                 ^   |dz  }|j                  t        j                  ddd      d       t        |dd      }t        j                  |j                  d            }|j                  }d	} ||      }d}	||	u }
|
st        j                  d
|
fd||	f      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}
}	||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)u9   이미 .merged가 있으면 no-op (기존 파일 유지).r*   r&   T)rM   originalrJ   rK   new_shar(   rq   )is)zI%(py6)s
{%(py6)s = %(py2)s
{%(py2)s = %(py0)s.get
}(%(py4)s)
} is %(py9)srW   )r0   r1   r2   rR   py9zassert %(py11)spy11Nr+   z%(py0)s == %(py2)sr.   ri   r0   r1   assert %(py4)sr2   )
write_textr\   dumpsr6   r]   r^   getr7   r8   r9   r:   r;   r<   r=   r>   )rA   r    r   ri   r.   rW   rD   rB   rC   @py_assert8@py_assert7@py_format10@py_format12@py_format3rG   s                  r   test_no_op_when_already_existsz?TestCreateMergedMarkerIdempotent.test_no_op_when_already_existsm   sW   00$**$%OP[bc&z;QZ[zz&**G*<=xx+
+x
#+t+#t++++#t++++++t+++t+++x+++
+++#+++t+++++++vvvr   N)rk   rl   rm   r   r"   r   r   ro   ro   l   s    	 r   ro   c                       e Zd Zd Zd Zd Zy)TestBumpRetryCounterc                 0   t        |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}}t        |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}}t        |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	)u6   retry_count가 0 → 1 → 2 → 3으로 증가한다.r&      r+   z%(py0)s == %(py3)scount1r0   rY   rZ   r[   N   count2   count3)	_bump_retry_counterr7   r8   r9   r:   r;   r<   r=   r>   )
rA   r    r   r   ra   rD   rc   rE   r   r   s
             r   test_increments_from_zeroz.TestBumpRetryCounter.test_increments_from_zeroz   s.   $Z=v{vvv$Z=v{vvv$Z=v{vvvr   c           
         t        |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                  }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                  |      t	        j                  |      t	        j                  |      t	        j                  |	      t	        j                  |
      dz  }dd|iz  }t        t	        j                  |            dx}x}x}x}x}	x}}
y)u'   .retry_count 파일도 동기화된다.r&   ztask-9999.retry_countr5   
retry_filer/   NrJ   rK   1r+   )z%(py10)s
{%(py10)s = %(py8)s
{%(py8)s = %(py6)s
{%(py6)s = %(py2)s
{%(py2)s = %(py0)s.read_text
}(encoding=%(py4)s)
}.strip
}()
} == %(py13)s)r0   r1   r2   rR   py8py10py13zassert %(py15)spy15)r   r?   r9   r:   r7   r;   r<   r=   r>   r^   stripr8   )rA   r    r   r   rD   rB   rG   rC   r}   @py_assert9@py_assert12@py_assert11@py_format14@py_format16s                 r   test_retry_count_file_syncedz1TestBumpRetryCounter.test_retry_count_file_synced   s>   J4"99
  " """"""""z"""z""" """"""""""##DWD#W5D5;;D;=DD=DDDD=DDDDDDzDDDzDDD#DDDWDDD5DDD;DDD=DDDDDDDDDDDr   c                    t        |dd       t        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)   last_error가 state.json에 저장된다.r&   zmerge conflict)
last_errorrf   rJ   rK   r   r+   rN   rO   rQ   rR   N)r   r\   r]   r   r   r^   r7   r8   r<   r=   r>   	rA   r    r   r   r`   rB   ra   rG   rb   s	            r   test_last_error_storedz+TestBumpRetryCounter.test_last_error_stored   s    J@PQ

J114DDOOY`Oab\"6&66"&66666"&6666"666&66666666r   N)rk   rl   rm   r   r   r   r"   r   r   r   r   y   s    	E7r   r   c                       e Zd Zd Zd Zd Zy)TestCreateMergeFailedMarkerc                 J   t        |ddd      }d}||z  }||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	t        j                  |      d
z  }dd|i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,   .merge-failed 파일이 atomic 생성된다.r&      zbranch conflictretry_countr   task-9999.merge-failedr+   r-   r.   r    r/   r3   r4   Nr5   )
_create_merge_failed_markerr7   r8   r9   r:   r;   r<   r=   r>   r?   r@   s
             r   test_creates_merge_failed_filez:TestCreateMergeFailedMarker.test_creates_merge_failed_file   s    ,?P
 '?>&>>>v>>>>>v>>>>>>>v>>>v>>>>>>>>>>>>&>>>>>>>>}}}vv}r   c                    t        |ddd       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}}|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)u.   .merge-failed JSON에 필수 필드가 있다.r&   r   errr   r   rJ   rK   rM   r+   rN   rO   rQ   rR   Nr   	failed_atrT   rV   rW   rX   rZ   r[   )r   r\   r]   r^   r7   r8   r<   r=   r>   r9   r:   r;   r_   s              r   test_merge_failed_json_contentz:TestCreateMergeFailedMarker.test_merge_failed_json_content   s-   #JW\]zz:(@@KKU\K]^I-+-+----+------+-------M"'a'"a''''"a'''"'''a'''''''"{d""""{d"""{""""""d"""d"""""""r   c                    t        |ddd       t        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)u4   state.json의 phase가 merge-failed로 갱신된다.r&   r   r   r   rf   rJ   rK   rh   merge-failedr+   rN   rO   rQ   rR   N)r   r\   r]   r   r   r^   r7   r8   r<   r=   r>   r   s	            r   "test_state_json_phase_merge_failedz>TestCreateMergeFailedMarker.test_state_json_phase_merge_failed   s    #JW\]

J114DDOOY`OabW~//~////~///~//////////r   N)rk   rl   rm   r   r   r   r"   r   r   r   r      s    #0r   r   c                     | dz  dz  }| dz  dz  }|j                  dd       |j                  dd       |j                  t        d|       |j                  t        d|       ||fS )uI   done-watcher의 EVENTS_DIR / STATE_DIR을 tmp_path 기반으로 redirect.r   r   r   Tr   
EVENTS_DIR	STATE_DIR)r   r   r
   )r   r   r   r   s       r   patched_dw_dirsr      sp      8+Fx')E
LLL-	KKtK,lF;k595=r   c                       e Zd Zd Zd Zy)$TestReconcileMetaTaskImmediateMergedc                    |\  }}ddddd}|dz  j                  t        j                  |      d       |d	z  }|j                  t        j                  d
di      d       t        j	                  |      }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}	}d}	||	z  }|j                  } |       }|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}x}}y)uI   kind=meta + merge_required=False → .merged 즉시 생성 (system-done).z	task-9001z	work-donemetaF)rM   rh   kindmerge_requiredztask-9001.jsonrJ   rK   ztask-9001.work-donerM   system-doner+   r   r.   r   rZ   r[   Nztask-9001.mergedMassert %(py7)s
{%(py7)s = %(py5)s
{%(py5)s = (%(py0)s / %(py2)s).exists
}()
}r   r0   r1   r[   r4   ry   r\   rz   r
   reconcile_work_doner7   r8   r9   r:   r;   r<   r=   r>   r?   rA   r   r   r   r   
state_datawdr.   ra   rD   rc   rE   rB   @py_assert4@py_assert6rF   s                   r   )test_meta_kind_creates_merged_immediatelyzNTestReconcileMetaTaskImmediateMerged.test_meta_kind_creates_merged_immediately   sS   ' # #	

 
!	!--djj.Dw-W ++
djj)[!9:WM11"5&&v&&&&v&&&&&&v&&&v&&&&&&&&&&+5++5+335355555555555555+55535555555555r   c                    |\  }}dddd}|dz  j                  t        j                  |      d       |dz  }|j                  t        j                  d	di      d       t        j	                  |      }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}	}d}	||	z  }|j                  } |       }|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}x}}y)u;   merge_required=False (kind=code) → .merged 즉시 생성.z	task-9002codeF)rM   r   r   ztask-9002.jsonrJ   rK   ztask-9002.work-donerM   r   r+   r   r.   r   rZ   r[   Nztask-9002.mergedr   r   r   r   r   s                   r   4test_merge_required_false_creates_merged_immediatelyzYTestReconcileMetaTaskImmediateMerged.test_merge_required_false_creates_merged_immediately   sN   ' ##


 
!	!--djj.Dw-W++
djj)[!9:WM11"5&&v&&&&v&&&&&&v&&&v&&&&&&&&&&+5++5+335355555555555555+55535555555555r   N)rk   rl   rm   r   r   r"   r   r   r   r      s    6,6r   r   c                       e Zd Zd Zy)TestReconcilePollingNoMergedYetc                 t   |\  }}ddddd}|dz  j                  t        j                  |      d       |d	z  }|j                  t        j                  ddd
      d       t               d_        t        j                  ddd      _        d_        |j                  t        dfd       t        j                  |      }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}
}	d}
||
z  }|j&                  } |       }| }|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}x}x}}y)uG   gh pr view mergedAt=null → polling 상태 유지 (.merged 미생성).z	task-9003r   Tz$https://github.com/test/repo/pull/42rM   r   r   pr_urlztask-9003.jsonrJ   rK   ztask-9003.work-donerM   r   r   NmergedAtmergeCommit runc                      S Nr"   akwmock_results     r   <lambda>zYTestReconcilePollingNoMergedYet.test_gh_pr_no_merged_at_returns_polling.<locals>.<lambda>        r   pollingr+   r   r.   r   rZ   r[   ztask-9003.mergedzQassert not %(py7)s
{%(py7)s = %(py5)s
{%(py5)s = (%(py0)s / %(py2)s).exists
}()
}r   r   )ry   r\   rz   r   
returncodestdoutstderrr   
subprocessr
   r   r7   r8   r9   r:   r;   r<   r=   r>   r?   )rA   r   r   r   r   r   r   r   r.   ra   rD   rc   rE   rB   r   r   r|   @py_format9r   s                     @r   'test_gh_pr_no_merged_at_returns_pollingzGTestReconcilePollingNoMergedYet.test_gh_pr_no_merged_at_returns_polling   s   ' #"<	

 
!	!--djj.Dw-W++
djj[Dj!klw~  k!"!ZZT$(OPJ/KL11"5""v""""v""""""v"""v""""""""""/9F//9/779799999999999F999F999/999799999999999r   N)rk   rl   rm   r   r"   r   r   r   r      s    :r   r   c                       e Zd Zd Zy)TestReconcileMergedObservedc                    |\  }}ddddd}|dz  j                  t        j                  |      d       |d	z  }|j                  t        j                  ddd
      d       t               d_        t        j                  dddid      _        d_        |j                  t        dfd       t        j                  |      }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}
}	|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}	}y)$u4   gh pr view mergedAt!=null → atomic .merged 생성.z	task-9004r   Tz$https://github.com/test/repo/pull/43r   ztask-9004.jsonrJ   rK   ztask-9004.work-doner   r   z2026-05-02T10:00:00Zoiddeadbeef123r   r   r   c                      S r   r"   r   s     r   r   zXTestReconcileMergedObserved.test_gh_pr_merged_at_creates_merged_marker.<locals>.<lambda>  r   r   ri   r+   r   r.   r   rZ   r[   Nztask-9004.mergedr5   merged_filer/   r)   rN   rO   rQ   rR   )ry   r\   rz   r   r   r   r   r   r   r
   r   r7   r8   r9   r:   r;   r<   r=   r>   r?   r]   r^   )rA   r   r   r   r   r   r   r   r.   ra   rD   rc   rE   r   rB   rG   rW   r`   rb   r   s                      @r   *test_gh_pr_merged_at_creates_merged_markerzFTestReconcileMergedObserved.test_gh_pr_merged_at_creates_merged_marker	  s   ' #"<	

 
!	!--djj.Dw-W++
djj[Dj!klw~k!"!ZZ.!=1)
   J/KL11"5!!v!!!!v!!!!!!v!!!v!!!!!!!!!!11!!#!########{###{###!##########zz+///AB&'8=8'=8888'=888'888=8888888r   N)rk   rl   rm   r   r"   r   r   r   r     s    9r   r   c                       e Zd Zd Zy)!TestReconcile30MinTimeoutToFailedc                    |\  }}dddddd}|dz  j                  t        j                  |      d	       |d
z  }|j                  t        j                  ddd      d	       t        j                         dz
  }t	        j
                  |||f       t               d_        t        j                  ddd      _        d_	        |j                  t        dfd       t        j                  |      }	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}}
|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.                  |j1                  d	            }d}|j2                  }d}d} |||      }|j4                  } |       }||v }
|
st        j                  d|
fd ||f      t        j&                  |      d!t!        j"                         v st        j$                  |      rt        j&                  |      nd!t        j&                  |      t        j&                  |      t        j&                  |      t        j&                  |      t        j&                  |      t        j&                  |      d"z  }d#d$|iz  }t)        t        j*                  |            dx}x}
x}x}x}x}x}}y)%uC   work-done mtime 31분 전 + mergedAt null → .merge-failed 생성.z	task-9005r   Tz$https://github.com/test/repo/pull/44r   )rM   r   r   r   r   ztask-9005.jsonrJ   rK   ztask-9005.work-doner   iD  Nr   r   r   c                      S r   r"   r   s     r   r   zgTestReconcile30MinTimeoutToFailed.test_work_done_mtime_31min_ago_creates_merge_failed.<locals>.<lambda>D  r   r   r   r+   r   r.   r   rZ   r[   ztask-9005.merge-failedr5   failed_filer/   timeoutr   rT   )z%(py1)s in %(py15)s
{%(py15)s = %(py13)s
{%(py13)s = %(py11)s
{%(py11)s = %(py5)s
{%(py5)s = %(py3)s.get
}(%(py7)s, %(py9)s)
}.lower
}()
}rW   )rP   rY   r[   r4   rt   ru   r   r   zassert %(py17)spy17)ry   r\   rz   timeosutimer   r   r   r   r   r   r
   r   r7   r8   r9   r:   r;   r<   r=   r>   r?   r]   r^   r{   lower)rA   r   r   r   r   r   r   r   	past_timer.   ra   rD   rc   rE   r   rB   rG   rW   r`   r   r   r|   @py_assert10r   @py_assert14r   @py_format18r   s                              @r   3test_work_done_mtime_31min_ago_creates_merge_failedzUTestReconcile30MinTimeoutToFailed.test_work_done_mtime_31min_ago_creates_merge_failed+  s   ' #"<

 
!	!--djj.Dw-W++
djj[Dj!klw~ IIK7+	
i+,  k!"!ZZT$(OPJ/KL11"5''v''''v''''''v'''v''''''''''77!!#!########{###{###!##########zz+///AB>DHH>\>2>H\26>6<<><>>y>>>>>y>>>>y>>>>>>D>>>D>>>H>>>\>>>2>>>6>>><>>>>>>>>>>>>r   N)rk   rl   rm   r   r"   r   r   r   r   *  s    !?r   r   c                       e Zd Zd Zy) TestFinishTaskCreatesDoneSymlinkc           	         |dz  dz  }|j                  dd       |dz  }ddt        j                  t        t	        d	                  j                  d
      d}|j                  t        j                  |      d       |dz  }|j                  |       |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}}|j&                  } |       }|j&                  }	 |	       }
||
k(  }|st        j(                  d|fd||
f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      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}x}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}}y)ub   .work-done 생성 후 .done이 symlink로 .work-done을 가리키는 케이스를 시뮬레이트.r   r   Tr   ztask-9999.work-doner&   	work_done	   )hoursz%Y-%m-%dT%H:%M:%S+09:00)rM   status
created_atrJ   rK   ztask-9999.doner5   r/   NzEassert %(py4)s
{%(py4)s = %(py2)s
{%(py2)s = %(py0)s.is_symlink
}()
}	done_linkr+   )z|%(py4)s
{%(py4)s = %(py2)s
{%(py2)s = %(py0)s.resolve
}()
} == %(py10)s
{%(py10)s = %(py8)s
{%(py8)s = %(py6)s.resolve
}()
})r0   r1   r2   rR   r   r   zassert %(py12)spy12rM   rN   rO   rQ   rR   r  )r   r   nowr   r   strftimery   r\   rz   
symlink_tor?   r9   r:   r7   r;   r<   r=   r>   
is_symlinkresolver8   r]   r^   )rA   r   r   r   payloadr  rD   rB   rG   r}   r   rC   @py_format11@py_format13	done_datar`   ra   rb   s                     r   %test_done_symlink_points_to_work_donezFTestFinishTaskCreatesDoneSymlink.test_done_symlink_points_to_work_doneT  s   H$x/TD1 22	"!",,x	0B'CDMMNgh

 	TZZ07C --	Y' !!!!!!!!!y!!!y!!!!!!!!!!!!!##%#%%%%%%%%y%%%y%%%#%%%%%%%%%%  9 "9i&7&79&7&99"&99999"&9999999y999y999 999"999999i999i999&7999&99999999 JJy22G2DE	#2{2#{2222#{222#222{2222222"1k1"k1111"k111"111k1111111r   N)rk   rl   rm   r  r"   r   r   r   r   S  s    2r   r   c                       e Zd Zd Zd Zy)TestAtomicWriteNoPartialFilec                    ddl }|dz  }ddd}|j                  t        |j                        d|j                   dd	      \  }}t        |      }	 t        j                  |d
d      5 }t        j                  ||dd       ddd       |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}
}t        j$                  ||       |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}	x}
}t        j*                  |j-                  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# 1 sw Y   xY w# t&        $ r |j)                  d        w xY w)uC   tempfile + rename 패턴이 partial file을 노출하지 않는다.r   Nzatomic_test.jsonvalue*   )keynumber.z.tmp)dirprefixsuffixwrJ   rK   Fr   )ensure_asciiindentzEassert not %(py4)s
{%(py4)s = %(py2)s
{%(py2)s = %(py0)s.exists
}()
}targetr/   T)
missing_okr5   tmp_filer+   rv   loadedrW   rw   rx   r2   )tempfilemkstempstrparentnamer   r   fdopenr\   dumpr?   r9   r:   r7   r;   r<   r=   r>   rename	Exceptionunlinkr]   r^   r8   )rA   r   r!  r  rW   fdtmp_path_strr  frD   rB   rC   rE   rG   r   r   s                   r   )test_atomic_write_no_partial_file_exposedzFTestAtomicWriteNoPartialFile.test_atomic_write_no_partial_file_exposedv  ss   .."- $++FMM"v{{m1% , 
L
 %
	2sW5 A		$a@A }}&}&&&&&&&&&v&&&v&&&}&&&&&&&&&IIlF+ }}}vv}??$?$$$$$$$$$$$8$$$8$$$?$$$$$$$$$$F,,g,>?~vvvA A  	OOtO,	s%   N! +NC	N! NN! !N>c                    |dz  }ddd}t         j                  ||       |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}	}y)uC   auto_merge._atomic_write_json이 올바르게 JSON을 기록한다.ztest_output.jsonr&   ri   )rM   rh   r5   r  r/   NrJ   rK   rM   r+   rN   rO   rQ   rR   rh   )r   _atomic_write_jsonr?   r9   r:   r7   r;   r<   r=   r>   r\   r]   r^   r8   )rA   r   r  r
  rD   rB   rG   r   r`   ra   rb   s              r   !test_auto_merge_atomic_write_jsonz>TestAtomicWriteNoPartialFile.test_auto_merge_atomic_write_json  s:   ..)H=%%fg6}}}vv}F,,g,>?i /K/ K//// K/// ///K///////g*(*(****(******(*******r   N)rk   rl   rm   r.  r1  r"   r   r   r  r  u  s    B
+r   r  )6__doc__builtinsr9   _pytest.assertion.rewrite	assertionrewriter7   importlib.util	importlibr\   r   r   sysr   r   r   r   pathlibr   unittest.mockr   pytestWORKTREEutilspec_from_file_locationpathjoin_am_specmodule_from_specr   modulesloaderexec_moduler6   r   r   _update_state_json_dw_specr
   fixturer   r    r   r$   ro   r   r   r   r   r   r   r   r   r  r"   r   r   <module>rJ     s       	  
  2 2  #  ; >>11GGLL9o6 ^^,,X6
)O    J '"88 (DD  44 22  >>11GGLL9&78 ~~..x8   L )   D   )4 ) )5 58
  
 7 780 0>  (6 (6V: ::9 9D"? "?R2 2D,+ ,+r   