
    j                    n   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ZddlmZ ddlZ ee      j#                         j$                  d   Z eedz        Zej,                  D  cg c]
  } | ek7  s	|  c} ej,                  dd  ee      ej,                  vr"ej,                  j/                  d ee             ddZ edd	        ee      j#                         j2                  j2                  j2                  Zedz  d
z  dz  ZddZddZ	 	 	 	 ddZ	 	 	 	 ddZddZ ddZ!ddZ"ddZ#yc c} w )u  tests.regression.test_bot_settings_policy_loader — task-2640 Track C.

회장 verbatim unfork #5 — bot_settings 정책 위치 + require_anu_callback_on_finish
=true 기본값 + fail-closed.

Layer A / NO-CRON: subprocess / cokacdir / merge / cron 호출 0.
    )annotationsN)Path   testsc                   t         j                  j                  |       }|3t        |dd      r&t	        |j
                        j                  |      r|S t        j                  j                  | t        |z        }g }d }||u}|}|r|j                  }d }	||	u}
|
}|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  }|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  }t        j(                  d|       dz   d|iz  }t+        t        j,                  |            d x}x}x}x}x}x}
}	t        j                  j/                  |      }|t         j                  | <   |j                  j1                  |       |S )N__file__ )is not)z%(py2)s is not %(py5)sspec)py2py5%(py7)spy7)z5%(py11)s
{%(py11)s = %(py9)s.loader
} is not %(py14)s)py9py11py14z%(py16)spy16r   zspec not found: z
>assert %(py19)spy19)sysmodulesgetgetattrstrr   endswith	importlibutilspec_from_file_location_ROOTloader
@pytest_ar_call_reprcompare@py_builtinslocals_should_repr_global_name	_safereprappend_format_boolop_format_assertmsgAssertionError_format_explanationmodule_from_specexec_module)modnamerelpathexistingr   @py_assert1@py_assert4@py_assert3@py_assert0@py_assert10@py_assert13@py_assert12@py_format6@py_format8@py_format15@py_format17@py_format18@py_format20mods                     G/home/jay/workspace/tests/regression/test_bot_settings_policy_loader.py
_load_realr?      s   {{w'H*b Ac(J[J[F\FeFefmFn>>11'57?KDUtU4tUU4U4 7UUUU4tUUUUUU4UUU4UUUtUUUUUUU4UUUUUUUUUUUUUUU4UUUUUUUUUU;KG99UUUUUUUUU
..
)
)$
/CCKKKKC J    z utils.bot_settings_policy_loaderz#utils/bot_settings_policy_loader.pyfixturesself_collector_enforcementc                    t         | z  }t        j                  |dz  j                  d            }t        j                  |dz  j                  d            }||fS )Nzevidence.jsonutf-8encodingzexpected.json)FIXTURE_ROOTjsonloads	read_text)scenariofdirevidenceexpecteds       r>   _load_fixturerO   0   sY    ("Dzz4/1<<g<NOHzz4/1<<g<NOHXr@   c                    ddl m}  | d   }d}||u }|slt        j                  d|fd||f      t        j                  |      t        j                  |      dz  }dd	|iz  }t        t        j                  |            d
x}x}}| d   }d}||u }|slt        j                  d|fd||f      t        j                  |      t        j                  |      dz  }dd	|iz  }t        t        j                  |            d
x}x}}| d   }d}||u }|slt        j                  d|fd||f      t        j                  |      t        j                  |      dz  }dd	|iz  }t        t        j                  |            d
x}x}}| d   }d}||u }|slt        j                  d|fd||f      t        j                  |      t        j                  |      dz  }dd	|iz  }t        t        j                  |            d
x}x}}| d   }d}||u }|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
)uH   DEFAULT_POLICY 가 spec §4.1 verbatim 안전 기본값을 보존한다.r   )DEFAULT_POLICYrequire_anu_callback_on_finishTisz%(py1)s is %(py4)spy1py4assert %(py6)spy6Nself_collector_forbiddensendfile_only_forbiddennot_registered_forbiddenfail_closed_on_violationanu_key_single_sourcec119085addb0f8b7==z%(py1)s == %(py4)s) utils.bot_settings_policy_loaderrQ   r    r!   r%   r)   r*   )rQ   r3   r2   @py_assert2@py_format5@py_format7s         r>   *test_default_policy_safe_defaults_verbatimrh   7   s   ?:;CtC;tCCCC;tCCC;CCCtCCCCCCC45==5====5===5==========34<<4<<<<4<<<4<<<<<<<<<<45==5====5===5==========45==5====5===5==========12H6HH26HHHHH26HHHH2HHH6HHHHHHHHr@   c                @   ddl m}m} t        d      \  }}|d   D cg c]  }| t	        |      j
                  z   }} ||      }|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}
}	|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}
}	|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}
}	|j                   }||k(  }
|
st        j                  d|
fd||f      d	t        j                         v st        j                  |      rt        j                  |      nd	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c c}w )uK   모든 후보 파일 부재 시 DEFAULT_POLICY 안전 적용 (fail-closed).r   rQ   load_callback_policy"bot_settings_default_safe_fallbackcandidate_pathsrm   sourcera   )z.%(py2)s
{%(py2)s = %(py0)s.source
} == %(py5)sresultpy0r   r   assert %(py7)sr   Nfell_back_to_default)z<%(py2)s
{%(py2)s = %(py0)s.fell_back_to_default
} == %(py5)spolicy)z.%(py2)s
{%(py2)s = %(py0)s.policy
} == %(py5)s)z.%(py2)s
{%(py2)s = %(py0)s.policy
} == %(py4)srQ   rr   r   rX   rY   rZ   )rd   rQ   rk   rO   r   namero   r    r!   r"   r#   r$   r%   r)   r*   rt   ru   )tmp_pathrQ   rk   rM   rN   p
candidatesrp   r0   r1   r2   r7   r8   rf   rg   s                  r>   Gtest_load_callback_policy_falls_back_to_default_when_candidates_missingr{   C   s0   
 ''KLHh3;<M3NOa(T!W\\)OJO!*=F==.HX..=.....=.......6...6...=...........&&J(3I*JJ&*JJJJJ&*JJJJJJJ6JJJ6JJJ&JJJ*JJJJJJJJ==.HX..=.....=.......6...6...=...........==*=N****=N******6***6***=******N***N******* Ps   Nc                   ddl m}m} | dz  }|j                  t	        j
                  ddddi      d	        ||g
      }|j                  }t        |      }||k(  }|s7t        j                  d|fd||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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                   }d}
||
u }|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}}
|j#                         D ]  \  }}g }|j$                  |   }||k(  }
|
}|
sd}||v }|}|sXt        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  }|j'                  |       |
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  }|j'                  |       t        j(                  |d$      i z  }d%d&|iz  }t        t        j                  |            dx}x}x}x}
x}} y)'uE   후보 파일 존재 시 그 내용을 DEFAULT 위에 overlay 한다.r   rj   callback_policy.jsoncallback_policyTr`   )rR   r_   rD   rE   rn   ra   )zL%(py2)s
{%(py2)s = %(py0)s.source
} == %(py7)s
{%(py7)s = %(py4)s(%(py5)s)
}rp   r   	candidate)rr   r   rX   r   r   zassert %(py9)sr   NFrS   )z<%(py2)s
{%(py2)s = %(py0)s.fell_back_to_default
} is %(py5)srq   rs   r   )z%(py3)s == %(py5)sv)py3r   r   in)z%(py9)s in %(py12)sk)r   py12z%(py14)sr      zassert %(py17)spy17)rd   rQ   rk   
write_textrH   dumpsro   r   r    r!   r"   r#   r$   r%   r)   r*   rt   itemsru   r&   r'   )rx   rQ   rk   r   rp   r0   @py_assert6r2   r8   @py_format10r1   r7   r   r   re   r3   @py_assert11r4   @py_format13r9   @py_format16r;   s                         r>   =test_load_callback_policy_reads_workspace_config_when_presentr   W   s   
 11I

!6:-?$	
   
 "9+>F==*C	N*=N****=N******6***6***=******C***C******	***	***N*******&&/%/&%////&%//////6///6///&///%///////$$& 
1	
v}}Q 	
1$ 	
 .
 	
 .
 )
 	
 	
 	
1 	
 	
 
	   	
 	
 
6	
 	
  $% 	
 	
 
	 $% 	
 	
 	
 
6	
 
	
 	
 .
 	
 	
 
6	
 	
  )* 	
 	
 
	 )* 	
 	
 
	.
 	
 	
 	
 
6	
 
	
 	
 	
 	
 	
 	
 	
 	

r@   c                    ddl m}  t        d      \  }} | |d   |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                  |      dz  }dd|iz  }t        t	        j                  |            dx}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}}|d   D ]  }	|j                  }|	|v }|s t	        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  }
t	        j                  d|	d|j                         dz   d|
iz  }t        t	        j                  |            dx}} y)uD   callback 미등록 + sendfile_only=True → fail-closed 3종 분류.r   )check_finalize_policy1bot_finalize_require_callback_missing_fail_closedfinalize_stateru   ru   verdictra   z/%(py2)s
{%(py2)s = %(py0)s.verdict
} == %(py5)srp   rq   rs   r   Nprimary_classification)z>%(py2)s
{%(py2)s = %(py0)s.primary_classification
} == %(py5)smust_contain_classificationsr   )z7%(py0)s in %(py4)s
{%(py4)s = %(py2)s.classifications
}clsrv   zmissing classification z in z
>assert %(py6)srZ   )rd   r   rO   r   r    r!   r"   r#   r$   r%   r)   r*   r   classificationsr(   )r   rM   rN   rp   r0   r1   r2   r7   r8   r   rf   rg   s               r>   <test_check_finalize_policy_fail_closed_when_callback_missingr   w   s,   F&;Hh #!"8H+=F >>0Xi00>00000>000000060006000>00000000000((NH5M,NN(,NNNNN(,NNNNNNN6NNN6NNN(NNN,NNNNNNNN67 
,, 	
s,, 	
 	
 	
s, 	
 	
	6	
 	
   	
 	
 		  	
 	
	6	
 	
   	
 	
 		  	
 	
 		 - 	
 	
  &cWD1G1G0HI	
 	
 	
 	
 	

r@   c            
     X   ddl m} m}  |ddddddd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                  |      dz  }dd|iz  }t        t	        j                  |            dx}x}}|j                  }g }||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}}y)uF   callback 정상 등록 + schedule_id 존재 + 정합 anu_key → PASS.r   rQ   r   Tz task-2640-finalize-pass-cron-001Fr`   1e41a2324a3ccdd0ztask-fixture-2640-finalize-passcallback_registeredschedule_idsendfile_onlyself_collector_attemptedanu_keyexecutor_keytask_idr   PASSra   r   rp   rq   rs   r   N)z7%(py2)s
{%(py2)s = %(py0)s.classifications
} == %(py5)srd   rQ   r   r   r    r!   r"   r#   r$   r%   r)   r*   r   )rQ   r   rp   r0   r1   r2   r7   r8   s           r>   @test_check_finalize_policy_pass_when_registered_with_schedule_idr      s   
 ##'="(-).8	
 F >>#V#>V####>V######6###6###>###V#######!!'R'!R''''!R''''''6'''6'''!'''R'''''''r@   c            
        ddl m} m}  |ddddddd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                  |      dz  }dd|iz  }t        t	        j                  |            dx}x}}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}	}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)uF   executor self-key 등록 시도 → SELF_COLLECTOR_FORBIDDEN_FINALIZE.r   r   Tz$task-2640-finalize-self-key-cron-001Fr   z task-fixture-2640-self-collectorr   r   FAILra   r   rp   rq   rs   r   N!SELF_COLLECTOR_FORBIDDEN_FINALIZEr   )z7%(py1)s in %(py5)s
{%(py5)s = %(py3)s.classifications
})rW   r   r   ANU_KEY_MISMATCH_FINALIZEr   )
rQ   r   rp   r0   r1   r2   r7   r8   r3   re   s
             r>   9test_check_finalize_policy_self_collector_attempt_blockedr      s   
 ##'A"(,).9	
 F >>#V#>V####>V######6###6###>###V#######.H&2H2HH.2HHHHH.2HHHH.HHHHHH&HHH&HHH2HHHHHHHH&@&*@*@@&*@@@@@&*@@@@&@@@@@@&@@@&@@@*@@@@@@@@r@   c                 ,   t         dz  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	            }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}}|d
   }	|	d   }d}||u }|slt        j                  d|fd||f      t        j                  |      t        j                  |      dz  }dd|iz  }
t        t        j                  |
            dx}x}}|	d   }d}||u }|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}||u }|slt        j                  d|fd||f      t        j                  |      t        j                  |      dz  }dd|iz  }
t        t        j                  |
            dx}x}}y)uH   config/callback_policy.json 후보 파일이 존재하고 schema 정합.configr}   uM   task-2640 Track C 후보 파일 부재 — config/callback_policy.json 필요zC
>assert %(py4)s
{%(py4)s = %(py2)s
{%(py2)s = %(py0)s.exists
}()
}r   rv   NrD   rE   r~   r   )z%(py1)s in %(py3)sobj)rW   r   zassert %(py5)sr   rR   TrS   rU   rV   rY   rZ   r[   r_   r`   ra   rc   r^   )	WORKSPACEexistsr    r(   r"   r#   r$   r%   r)   r*   rH   rI   rJ   r!   )r   r0   r2   rf   r   r3   re   @py_format4r7   cprg   s              r>   :test_workspace_callback_policy_json_exists_and_well_formedr      s   H$'==I     	X                       **Y(('(:
;C########################		B./747/47777/4777/77747777777()1T1)T1111)T111)111T1111111%&<*<<&*<<<<<&*<<<<&<<<*<<<<<<<<()1T1)T1111)T111)111T1111111r@   )r-   r   r.   r   )rK   r   returnztuple[dict, dict])r   None)rx   r   r   r   )$__doc__
__future__r   builtinsr"   _pytest.assertion.rewrite	assertionrewriter    importlib.utilr   rH   r   pathlibr   pytestr   resolveparentsr   r   
_TESTS_DIRpathinsertr?   parentr   rG   rO   rh   r{   r   r   r   r   r   )ry   s   0r>   <module>r      s9   #      
   	X ((+!
((6Qa:oq6u:SXXHHOOAs5z"	 &)
 N""$++2299	7"Z/2NN	I++	+(

	
@
$(.A02E 7s   (
D23D2