
    Li;              
           U 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
mZ ddlmZ ddlZej                  j!                  d e ee      j&                  j&                                ed      Zdddd	d
ddiddddddii i i dZeed<   dddd	did	diddiZeed<   dededdfdZdedefdZd edeeeef   fd!Zd/d ede	j:                  f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)0u   
test_bot_settings_sync.py

task-1441.1: _sync_bot_settings()와 ConfigManager.reload() / _sync_check() 단위 테스트.

작성자: 토트 (Thoth) — dev8-team QA
    N)Path)patchz/home/jay/workspacez1.0z
2026-04-04)versionlast_updated
6937032012z$COKACDIR_KEYz	dev1-teamdev1dev1_Hermes_botdev1_hermes_botz/home/jay/workspace/teams/dev1claude-opus-4-6display_nameusernameteam_dirmodel)metachat_idcokacdir_keyteamsbotsteam_to_botwork_levels
thresholds_FAKE_CONSTANTSabc123dev9_TestBot_botdev9_testbot_bot/home/jay/workspace/teams/dev9zsecret-token-123r   r   modelslast_sessionstoken_FAKE_BOT_SETTINGSpathdatareturnc                     | j                   j                  dd       t        | dd      5 }t        j                  ||dd       d d d        y # 1 sw Y   y xY w)	NTparentsexist_okwutf-8encodingF   )ensure_asciiindent)parentmkdiropenjsondump)r#   r$   fs      3/home/jay/workspace/tests/test_bot_settings_sync.py_write_jsonr8   :   sN    KKdT2	dC'	* 9a		$a89 9 9s   AAc                 r    t        | d      5 }t        j                  |      cd d d        S # 1 sw Y   y xY w)Nr+   r,   )r3   r4   load)r#   r6   s     r7   
_read_jsonr;   @   s.    	dW	% yy|  s   -6tmp_pathc                 l    | dz  }| dz  }|j                  dd       |j                  dd       | ||fS )u\   tmp_path 아래에 workspace 뼈대를 만들고 (workspace, config_dir, memory_dir) 반환.configmemoryTr'   )r2   )r<   
config_dir
memory_dirs      r7   _make_workspacerB   E   sI    H$JH$JTD1TD1Z++    c                    t        t              t        j                  vr-t        j                  j	                  dt        t                     	 ddl}t        j                  j                  d      }|#|!|j                  t        j                  d|       t        t        j                  j                               D ]  }|dk(  s	t        j                  |=  ddl}||j                  |d|        |S | |_        |S # t        $ r Y w xY w)u[   dispatch 모듈을 캐시에서 제거한 뒤 재임포트하고 WORKSPACE를 패치한다.r   Ndispatch	WORKSPACE)str
_WORKSPACEsysr#   insertprompts.team_promptsImportErrormodulesgetsetitemlistkeysrE   setattrrF   )r<   monkeypatchprompts_original_dispatchmod_name	_dispatchs         r7   _import_dispatchrX   S   s    
:chh&3z?+#
 4 #5#ACKK5GH))+, &z!H%& !I{H=  '	)  s   C= =	D	D	c                   8    e Zd ZdZdedej                  ddfdZy)TestSyncUpdateConstantsJsonuO   bot_settings.json의 새 봇이 constants.json[bots]에 반영되는지 검증.r<   rS   r%   Nc           	         t        |      \  }}}|dz  }t        |t               |dz  dz  }|j                  dd       |dz  }t        |t               t        ||      }|j                  t        dt        fd             |j                          t        |      }	d	}
|	j                  }d
}i } |||      }|
|v }|st        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                  |      dz  }t        j$                  d      dz   d|iz  }t'        t        j(                  |            d x}
x}x}x}x}}|	d
   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}|
|k(  }|slt        j                  d|fd|
|f      t        j                  |
      t        j                  |      dz  }dd|iz  }t'        t        j(                  |            d x}
x}}y )Nconstants.json	fake_home	.cokacdirTr'   bot_settings.jsonhomec                       S N r]   s   r7   <lambda>zNTestSyncUpdateConstantsJson.test_sync_updates_constants_json.<locals>.<lambda>       y rC   dev9r   in)zT%(py1)s in %(py11)s
{%(py11)s = %(py5)s
{%(py5)s = %(py3)s.get
}(%(py7)s, %(py9)s)
}updated)py1py3py5py7py9py11u:   dev9 봇이 constants.json[bots]에 추가되어야 한다z
>assert %(py13)spy13r   r   ==)z%(py1)s == %(py4)s)rk   py4zassert %(py6)spy6r   r   r   r   r   r   rB   r8   r   r2   r"   rX   rR   r   staticmethod_sync_bot_settingsr;   rN   
@pytest_ar_call_reprcompare	_saferepr@py_builtinslocals_should_repr_global_name_format_assertmsgAssertionError_format_explanation)selfr<   rS   _r@   constants_pathcokacdir_dirsettings_pathdispatch_modrj   @py_assert0@py_assert4@py_assert6@py_assert8@py_assert10@py_assert2@py_format12@py_format14
dev9_entry@py_assert3@py_format5@py_format7r]   s                         @r7    test_sync_updates_constants_jsonz<TestSyncUpdateConstantsJson.test_sync_updates_constants_jsonz   s   *84:q $&66NO4 {*	 ;.4$7$'::M#56'+> 	D&,7H*IJ'')^,nnVnRnVR0nv00nnnv0nnnvnnnnnnnnnnnnnnnVnnnRnnn0nnn2nnnnnnnnV_V,
.)?-??)-?????)-????)???-????????*%;);;%);;;;;%);;;;%;;;);;;;;;;;'"7&77"&77777"&7777"777&77777777*%I)II%)IIIII%)IIII%III)IIIIIIIIrC   )__name__
__module____qualname____doc__r   pytestMonkeyPatchr   rc   rC   r7   rZ   rZ   w   s*    YJ JFL^L^ Jcg JrC   rZ   c                   8    e Zd ZdZdedej                  ddfdZy)TestSyncPreservesExistingBotsuG   sync 실행 후 constants.json의 기존 봇이 유지되는지 검증.r<   rS   r%   Nc                 R   t        |      \  }}}|dz  }t        |t               |dz  dz  }|j                  dd       t        |dz  t               t        ||      }|j                  t        dt        fd             |j                          t        |      }|j                  d	i       }	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      dz   d|iz  }t'        t        j(                  |            d 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  }t        j$                  d      dz   d|iz  }t'        t        j(                  |            d x}
}y )Nr\   r]   r^   Tr'   r_   r`   c                       S rb   rc   rd   s   r7   re   zQTestSyncPreservesExistingBots.test_sync_preserves_existing_bots.<locals>.<lambda>   rf   rC   r   r   rh   )z%(py1)s in %(py3)s)rk   rl   u0   기존 dev1 봇은 삭제되어서는 안 된다
>assert %(py5)srm   rg   u-   새로 추가된 dev9 봇도 있어야 한다rv   )r   r<   rS   r   r@   r   r   r   rj   r   r   r   @py_format4@py_format6r]   s                 @r7   !test_sync_preserves_existing_botsz?TestSyncPreservesExistingBots.test_sync_preserves_existing_bots   ss   *84:q#&66NO4{*	 ;.4$7L#668JK'+>D&,7H*IJ'')^,{{62&Qv~QQQvQQQvQQQQQQQQQQQQQQQQQQQQNv~NNNvNNNvNNNNNNNNNNNNNNNNNNNNrC   )r   r   r   r   r   r   r   r   rc   rC   r7   r   r      s*    QO$ OVM_M_ Odh OrC   r   c                   8    e Zd ZdZdedej                  ddfdZy)TestSyncSkipsWithoutBotSettingsud   bot_settings.json 부재 시 함수가 조용히 종료되고 constants.json이 불변임을 검증.r<   rS   r%   Nc                    t        |      \  }}}|dz  }t        |t               |dz  dz  j                  dd       t	        ||      }|j                  t        dt        fd             |j                          t        |      }|t        k(  }|st        j                  d|fd	|t        f      d
t        j                         v st        j                  |      rt        j                  |      nd
dt        j                         v st        j                  t              rt        j                  t              nddz  }	t        j                   d      dz   d|	iz  }
t#        t        j$                  |
            d }y )Nr\   r]   r^   Tr'   r`   c                       S rb   rc   rd   s   r7   re   zVTestSyncSkipsWithoutBotSettings.test_sync_skips_without_bot_settings.<locals>.<lambda>   rf   rC   rr   )z%(py0)s == %(py2)s	unchangedr   )py0py2uL   bot_settings.json 없을 때 constants.json은 변경되지 않아야 한다z
>assert %(py4)srt   )rB   r8   r   r2   rX   rR   r   rw   rx   r;   ry   rz   r|   r}   r~   r{   r   r   r   )r   r<   rS   r   r@   r   r   r   @py_assert1@py_format3r   r]   s              @r7   $test_sync_skips_without_bot_settingszDTestSyncSkipsWithoutBotSettings.test_sync_skips_without_bot_settings   s    *84:q#&66NO4 {*		[	 ''t'D'+>D&,7H*IJ 	'') ~.	O+{{{yO{{{{{{y{{{y{{{{{{O{{{O{{{{-{{{{{{{rC   )r   r   r   r   r   r   r   r   rc   rC   r7   r   r      s+    n|T |PVPbPb |gk |rC   r   c                   8    e Zd ZdZdedej                  ddfdZy)TestReloadMethoduM   ConfigManager.reload() 호출 후 수정된 상수가 반영되는지 검증.r<   rS   r%   Nc           
      j   ddl m} |j                          |dz  }|j                  dd       t        dz  }dd l}dD ]  }|j                  ||z  ||z          t        j                         D 	ci c]  \  }}	||	
 }
}}	t        |dz  |
       |j                  d|       |j                          |j                         }d	}|j                  }|j                  }d
}i } |||      }||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                   |      dz  }t        j(                  d      dz   d|iz  }t+        t        j,                  |            d x}x}x}x}x}x}}i |
}ddddd|j/                  d
i       d	<   t        |dz  |       |j1                          d	}|j                  }|j                  }d
}i } |||      }||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                   |      dz  }t        j(                  d      dz   d|iz  }t+        t        j,                  |            d x}x}x}x}x}x}}|j                          y c c}	}w )Nr   )ConfigManagerr>   Tr'   )z
paths.jsonzdesign-system.jsonzmodule-registry.jsonr\   zconfig.loader.CONFIG_DIRrg   r   )not in)zx%(py1)s not in %(py13)s
{%(py13)s = %(py7)s
{%(py7)s = %(py5)s
{%(py5)s = %(py3)s.constants
}.get
}(%(py9)s, %(py11)s)
}cfg)rk   rl   rm   rn   ro   rp   rq   u&   초기 상태에는 dev9 없어야 함z
>assert %(py15)spy15r   r   r   r   r   rh   )zt%(py1)s in %(py13)s
{%(py13)s = %(py7)s
{%(py7)s = %(py5)s
{%(py5)s = %(py3)s.constants
}.get
}(%(py9)s, %(py11)s)
}u<   reload() 후 dev9 봇이 constants에 반영되어야 한다)config.loaderr   resetr2   rH   shutilcopyr   itemsr8   rR   get_instance	constantsrN   ry   rz   r{   r|   r}   r~   r   r   r   
setdefaultreload)r   r<   rS   r   r@   real_config_dirr   fnamekvinitial_constantsr   r   r   r   r   r   @py_assert12r   r   @py_format16updated_constantss                         r7   test_reload_methodz#TestReloadMethod.test_reload_method   s   / 	 (
5 %x/Q 	EEKK%/e1CD	E />.C.C.EFdaQTFFJ!113DE6
C 	((*dS]]d]..dvdrd.vr:dv::dddv:dddvddddddSdddSddd]ddd.dddvdddrddd:ddd<ddddddddd 201.*8&	<
$$VR08 	J!113DE

vv**v6v2v*626vv66vvvv6vvvvvvvvvvvvvvvvvvv*vvv6vvv2vvv6vvv8vvvvvvvvv 	5 Gs   2N/)r   r   r   r   r   r   r   r   rc   rC   r7   r   r      s&    W,4 ,f>P>P ,UY ,rC   r   c                   8    e Zd ZdZdedej                  ddfdZy)TestSyncCheckOkuF   _sync_bot_settings() 후 _sync_check()가 0을 반환하는지 검증.r<   rS   r%   Nc                    t        |      \  }}}|dz  }t        |t               |dz  dz  }|j                  dd       t        |dz  t               t        ||      }|j                  t        dt        fd             |j                          d	d
l
m}	 |j                  |	d|       |dz  }
|
j                  } |       }|st        j                  d      dz   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      5 }	 d d d        t.        dz  }|dz  }d }|j                         rt1        |      }	 t        |t1        |
             t+        j,                  |	d|      5  |	j3                         }d d d        d	}|k(  }|st        j4                  d|fd||f      dt        j                          v st        j"                  |      rt        j$                  |      ndt        j$                  |      dz  }t        j                  d|       dz   d|iz  }t'        t        j(                  |            d x}}|t        ||       y |j                         r|j7                          y y # 1 sw Y   kxY w# 1 sw Y   xY w# |t        ||       w |j                         r|j7                          w w xY w)Nr\   r]   r^   Tr'   r_   r`   c                       S rb   rc   rd   s   r7   re   z4TestSyncCheckOk.test_sync_check_ok.<locals>.<lambda>   rf   rC   r   loader
CONFIG_DIRbot_settings_sync.jsonu0   bot_settings_sync.json이 생성되어야 한다zC
>assert %(py4)s
{%(py4)s = %(py2)s
{%(py2)s = %(py0)s.exists
}()
}	sync_path)r   r   rt   __new__r?   rr   z%(py0)s == %(py3)sresultr   rl   uH   _sync_check()는 동기화 완료 후 0을 반환해야 한다, 실제: r   rm   )rB   r8   r   r2   r"   rX   rR   r   rw   rx   r>   r   existsry   r   r|   r}   r~   r{   r   r   r   objectrH   r;   _sync_checkrz   unlink)r   r<   rS   r   r@   rA   r   r   r   
loader_modr   r   r   r   real_memory_dirreal_sync_pathbackupr   r   r   r   r]   s                        @r7   test_sync_check_okz"TestSyncCheckOk.test_sync_check_ok  s   $3H$=!:z#&66NO4{*	 ;.4$7L#668JK'+>D&,7H*IJ 	'') 	0JjA !99	U!U!UU#UUUUUUUyUUUyUUUUUU!UUUUUU\\*//95 		 %x/(+CC #  "/F	(
9(=> j,
C 2#//12 s6Q;sss6Qssssss6sss6sssQsss"jkqjr sssssss !NF3&&(%%' )9	 	(2 2 !NF3&&(%%' )s1   K:,L 1LCL :LLL 2M)r   r   r   r   r   r   r   r   rc   rC   r7   r   r     s&    P8(4 8(f>P>P 8(UY 8(rC   r   c                        e Zd ZdZdeddfdZy)TestSyncCheckDetectsMismatchuq   bot_settings_sync.json에 constants.json에 없는 봇이 있으면 _sync_check()가 1을 반환하는지 검증.r<   r%   Nc                    t        |      \  }}}|dz  }t        |t               dddddiddidd	i}|d
z  }t        ||       ddlm} t
        dz  }	|	d
z  }
d }|
j                         rt        |
      }	 t        |
|       t        j                  |d|      5  |j                         }d d 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  }t        j"                  d      dz   d|iz  }t%        t        j&                  |            d x}}|t        |
|       y |
j                         r|
j)                          y y # 1 sw Y   xY w# |t        |
|       w |
j                         r|
j)                          w w xY w)Nr\   r   r   r   r   r   r   z***REDACTED***r   r   r   r   r?   r      rr   r   r   r   un   _sync_check()는 bot_settings_sync.json에 constants.json에 없는 봇이 있을 때 1을 반환해야 한다r   rm   )rB   r8   r   r>   r   rH   r   r;   r   r   r   ry   rz   r|   r}   r~   r{   r   r   r   r   )r   r<   r   r@   rA   r   	sync_datar   r   r   r   r   r   r   r   r   r   s                    r7    test_sync_check_detects_mismatchz=TestSyncCheckDetectsMismatch.test_sync_check_detects_mismatchW  s   $3H$=!:z $&66NO4  2.'):;".0P!Q)	
	 !99	Iy)/ %x/(+CC"  "/F	(	2j,
C 2#//12  6Q;  6Q  v     I   I     A     !NF3&&(%%' )2 2 !NF3&&(%%' )s%   6#F+ F*CF+ F($F+ +2G)r   r   r   r   r   r   rc   rC   r7   r   r   T  s    {,( ,($ ,(rC   r   rb   )%r   builtinsr|   _pytest.assertion.rewrite	assertionrewritery   r4   rI   typespathlibr   unittest.mockr   r   r#   rJ   rG   __file__r1   rH   r   dict__annotations__r"   r8   r;   tuplerB   
ModuleTyperX   rZ   r   r   r   r   r   rc   rC   r7   <module>r      s     
     3tH~,,334 5 '(
 |<#6"-)8&	
  & *&!23&(HI# D 9d 9$ 94 9T d 
,d ,uT4-='> ,t %:J:J HJ JNO O>| |:/ /n;( ;(F/( /(rC   