§
    V¿jE  ã                  ór  — 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ZddlZe
j                             e
j                             e
j                             e¦  «        dd¦  «        ¦  «        Ze
j                             eddd¦  «        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dd„ZdS )z7Unit tests for Full-Stack Blast Radius Impact Analyzer.é    )ÚannotationsNz..ÚtoolsÚanalysiszblast_radius.pyÚtargetÚstrÚ
extra_argsÚreturnÚdictc                ó^  — t           j        t          d| ddg|¢}t          j        |ddt
          d¬¦  «        }|j        }d}||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œz  }t          j        d|j        › �¦  «        dz   d|iz  }t          t          j        |¦  «        ¦  «        ‚dx}x}}t#          j        |j        ¦  «        S )z4Helper to run blast_radius.py and parse JSON output.z--targetz--formatÚjsonTzutf-8)Úcapture_outputÚtextÚcwdÚencodingr   ©ú==)z2%(py2)s
{%(py2)s = %(py0)s.returncode
} == %(py5)sÚresult)Úpy0Úpy2Úpy5zScript failed with stderr: z
>assert %(py7)sÚpy7N)ÚsysÚ
executableÚSCRIPT_PATHÚ
subprocessÚrunÚPROJECT_ROOTÚ
returncodeÚ
@pytest_arÚ_call_reprcompareÚ@py_builtinsÚlocalsÚ_should_repr_global_nameÚ	_safereprÚ_format_assertmsgÚstderrÚAssertionErrorÚ_format_explanationr   ÚloadsÚstdout)	r   r   Úcmdr   Ú@py_assert1Ú@py_assert4Ú@py_assert3Ú@py_format6Ú@py_format8s	            ú5C:\Projects\FreeExile\tests\unit\test_blast_radius.pyÚrun_blast_radiusr2      sF  € åŒ>�;¨
°F¸JÈÐ
\ÐQ[Ð
\€CÝŒ^˜C°¸4Å\Ð\cÐdÑdÔd€FØÔÐP ÐPÐ Ò!ÐPÐPÐPÕPÔPÐPÐPÐPÐPÐ ÐPÑPÔPÐPÕPÔPÑPÔPÐPÐPÕPÔPˆ6ÑPÔPÐPÕPÔPˆ6ÑPÔPÐPÐPÕPÔPÐÑPÔPÕPÔP ÑPÔPÐPÐPÑPÐPÕPÔPÐ#PÀÄÐ#PÐ#PÑPÔPÐPÑPÐPÐPÐPÑPÐPÕPÕPÔPÐPÑPÔPÑPÔPÐPÐPÐPÐPÐPÐPÐPÝŒ:�f”mÑ$Ô$Ð$ó    ÚNonec                 ó8  — t          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}||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	S )zCTest files or isolated leaf files should be LOW risk and unblocked.ztests/unit/test_movement.pyÚ
risk_levelÚLOWr   )z%(py1)s == %(py4)s©Úpy1Úpy4úassert %(py6)sÚpy6NÚblockedF©Úis©z%(py1)s is %(py4)sr   ©r2   r   r    r$   r'   r(   )ÚresÚ@py_assert0r.   Ú@py_assert2Ú@py_format5Ú@py_format7s         r1   Ú'test_blast_radius_test_file_is_low_riskrG      s  € å
Ð8Ñ
9Ô
9€CØˆ|ÔÐ% Ð%Ð Ò%Ð%Ð%Ð%Õ%Ô%Ð%Ð%Ð%Ð%Ð Ð%Ñ%Ô%Õ%Ô%ÐÑ%Ô%Õ%Ô% Ñ%Ô%Ð%Ð%Ñ%Ð%Ð%Ð%Ð%Ð%Ñ%Ð%Õ%Õ%Ô%Ð%Ñ%Ô%Ñ%Ô%Ð%Ð%Ð%Ð%Ð%Ð%Ð%ØˆyŒ>Ð"˜UÐ"ˆ>˜UÐ"Ð"Ð"Ð"Õ"Ô"Ð"Ð"Ð"Ð"ˆ>˜UÐ"Ñ"Ô"Õ"Ô"ˆ>Ñ"Ô"Õ"Ô"˜UÑ"Ô"Ð"Ð"Ñ"Ð"Ð"Ð"Ð"Ð"Ñ"Ð"Õ"Õ"Ô"Ð"Ñ"Ô"Ñ"Ô"Ð"Ð"Ð"Ð"Ð"Ð"Ð"ØˆxŒ=Ð9Ð9Ð9ˆ=Ð9Ò9Ð9Ð9Ð9Õ9Ô9Ð9Ð9Ð9Ð9ˆ=Ð9Ð9Ñ9Ô9Õ9Ô9ˆ=Ñ9Ô9Õ9Ô9Ð9Ñ9Ô9Ð9Ð9Ñ9Ð9Ð9Ð9Ð9Ð9Ñ9Ð9Õ9Õ9Ô9Ð9Ñ9Ô9Ñ9Ô9Ð9Ð9Ð9Ð9Ð9Ð9Ð9Ð9Ð9r3   c                 óP  — t          d¦  «        } | d         }d}||v }|slt          j        d|fd||f¦  «        t          j        |¦  «        t          j        |¦  «        dœz  }dd|iz  }t	          t          j        |¦  «        ¦  «        ‚d	x}x}}| d
         }t          |¦  «        }d}||k    }|sÇt          j        d|fd||f¦  «        dt          j        ¦   «         v st          j	        t          ¦  «        rt          j        t          ¦  «        ndt          j        |¦  «        t          j        |¦  «        t          j        |¦  «        dœz  }	dd|	iz  }
t	          t          j        |
¦  «        ¦  «        ‚d	x}x}x}}t          d„ | d
         D ¦   «         ¦  «        }|sƒt          j        d| d
         › �¦  «        dz   ddt          j        ¦   «         v st          j	        |¦  «        rt          j        |¦  «        ndiz  }t	          t          j        |¦  «        ¦  «        ‚d	S )zFCore engine files with many dependents should have HIGH/CRITICAL risk.z(server/world/game_design_matrix_types.pyr6   ©ÚHIGHÚCRITICAL©Úin©z%(py1)s in %(py4)sr8   r;   r<   NÚaffected_filesr   ©ú>©z/%(py4)s
{%(py4)s = %(py0)s(%(py2)s)
} > %(py7)sÚlen©r   r   r:   r   úassert %(py9)sÚpy9c              3  ó   K  — | ]}d |v V — Œ	dS )Úgame_design_matrix_serviceN© ©Ú.0Úfs     r1   ú	<genexpr>z5test_blast_radius_core_engine_file.<locals>.<genexpr>#   s(   è è € ÐWÐW¸AÐ2°aÐ7ÐWÐWÐWÐWÐWÐWr3   z'Expected game_design_matrix_service in ú
>assert %(py0)sr   Úany_service)r2   r   r    r$   r'   r(   rS   r!   r"   r#   Úanyr%   )rB   rC   r.   rD   rE   rF   r,   Ú@py_assert6Ú@py_assert5r0   Ú@py_format10r_   Ú@py_format1s                r1   Ú"test_blast_radius_core_engine_filere      sv  € å
ÐEÑ
FÔ
F€CØˆ|ÔÐ4Ð 4Ð4ÐÐ 4Ð4Ð4Ð4Ð4Õ4Ô4Ð4Ð4Ð4Ð4ÐÐ 4Ð4Ñ4Ô4Õ4Ô4ÐÑ4Ô4Õ4Ô4Ð 4Ñ4Ô4Ð4Ð4Ñ4Ð4Ð4Ð4Ð4Ð4Ñ4Ð4Õ4Õ4Ô4Ð4Ñ4Ô4Ñ4Ô4Ð4Ð4Ð4Ð4Ð4Ð4Ð4ØÐ#Ô$Ð)�3Ð$Ñ%Ô%Ð)¨Ð)Ð%¨Ò)Ð)Ð)Ð)Õ)Ô)Ð)Ð)Ð)Ð)Ð%¨Ð)Ñ)Ô)Ð)Õ)Ô)Ñ)Ô)Ð)Ð)Õ)Ô)�3Ñ)Ô)Ð)Õ)Ô)�3Ñ)Ô)Ð)Ð)Õ)Ô)Ð$Ñ)Ô)Õ)Ô)Ð%Ñ)Ô)Õ)Ô)¨Ñ)Ô)Ð)Ð)Ñ)Ð)Ð)Ð)Ð)Ð)Ñ)Ð)Õ)Õ)Ô)Ð)Ñ)Ô)Ñ)Ô)Ð)Ð)Ð)Ð)Ð)Ð)Ð)Ð)Ð)ÝÐWÐWÀÐEUÔAVÐWÑWÔWÑWÔW€KØÐYÕYÔYÐYÀ#ÐFVÔBWÐYÐYÑYÔYÐYÑYÐYÐYÕYÔYÑYÔYÐYÐYÕYÔYˆ;ÑYÔYÐYÕYÔYˆ;ÑYÔYÐYÐYÐYÑYÐYÕYÕYÔYÐYÑYÔYÑYÔYÐYÐYÐYr3   c                 ó2  — d} t          | 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
S )z)Acknowledging a target should unblock it.zserver/world/combat_engine.pyz--ackÚacknowledgedTr>   r@   r8   r;   r<   Nr=   FrA   )r   Úres_ackrC   r.   rD   rE   rF   s          r1   Ú%test_blast_radius_acknowledgment_flowri   '   sn  € à,€FÝ˜v wÑ/Ô/€GØ�>Ô"Ð* dÐ*Ð" dÐ*Ð*Ð*Ð*Õ*Ô*Ð*Ð*Ð*Ð*Ð" dÐ*Ñ*Ô*Õ*Ô*Ð"Ñ*Ô*Õ*Ô* dÑ*Ô*Ð*Ð*Ñ*Ð*Ð*Ð*Ð*Ð*Ñ*Ð*Õ*Õ*Ô*Ð*Ñ*Ô*Ñ*Ô*Ð*Ð*Ð*Ð*Ð*Ð*Ð*Ø�9ÔÐ& Ð&Ð Ð&Ð&Ð&Ð&Õ&Ô&Ð&Ð&Ð&Ð&Ð Ð&Ñ&Ô&Õ&Ô&ÐÑ&Ô&Õ&Ô& Ñ&Ô&Ð&Ð&Ñ&Ð&Ð&Ð&Ð&Ð&Ñ&Ð&Õ&Õ&Ô&Ð&Ñ&Ô&Ñ&Ô&Ð&Ð&Ð&Ð&Ð&Ð&Ð&Ð&Ð&r3   c                 óP  — d} t          | ¦  «        }|d         }t          |¦  «        }d}||k    }|sÇt          j        d|fd||f¦  «        dt	          j        ¦   «         v st          j        t          ¦  «        rt          j        t          ¦  «        ndt          j        |¦  «        t          j        |¦  «        t          j        |¦  «        dœz  }dd	|iz  }t          t          j	        |¦  «        ¦  «        ‚d
x}x}x}}t          d„ |d         D ¦   «         ¦  «        }|sƒt          j        d|d         › �¦  «        dz   ddt	          j        ¦   «         v st          j        |¦  «        rt          j        |¦  «        ndiz  }	t          t          j	        |	¦  «        ¦  «        ‚d
S )z7Modifying a JS module should detect dependent JS files.zclient/webapp/js/ui/tooltips.jsrO   r   rP   rR   rS   rT   rU   rV   Nc              3  ó   K  — | ]}d |v V — Œ	dS )zmain.jsNrY   rZ   s     r1   r]   z;test_blast_radius_js_client_dependencies.<locals>.<genexpr>5   s&   è è € ÐAÐA a�9 �>ÐAÐAÐAÐAÐAÐAr3   z-Expected main.js to import tooltips.js, got: r^   r   Úany_main©r2   rS   r   r    r!   r"   r#   r$   r'   r(   r`   r%   )
r   rB   r,   r.   ra   rb   r0   rc   rl   rd   s
             r1   Ú(test_blast_radius_js_client_dependenciesrn   /   sÍ  € à.€FÝ
˜6Ñ
"Ô
"€CØÐ#Ô$Ð)�3Ð$Ñ%Ô%Ð)¨Ð)Ð%¨Ò)Ð)Ð)Ð)Õ)Ô)Ð)Ð)Ð)Ð)Ð%¨Ð)Ñ)Ô)Ð)Õ)Ô)Ñ)Ô)Ð)Ð)Õ)Ô)�3Ñ)Ô)Ð)Õ)Ô)�3Ñ)Ô)Ð)Ð)Õ)Ô)Ð$Ñ)Ô)Õ)Ô)Ð%Ñ)Ô)Õ)Ô)¨Ñ)Ô)Ð)Ð)Ñ)Ð)Ð)Ð)Ð)Ð)Ñ)Ð)Õ)Õ)Ô)Ð)Ñ)Ô)Ñ)Ô)Ð)Ð)Ð)Ð)Ð)Ð)Ð)Ð)Ð)åÐAÐA¨3Ð/?Ô+@ÐAÑAÔAÑAÔA€HØÐ\Õ\Ô\Ð\ÀSÐIYÔEZÐ\Ð\Ñ\Ô\Ð\Ñ\Ð\Ð\Õ\Ô\Ñ\Ô\Ð\Ð\Õ\Ô\ˆ8Ñ\Ô\Ð\Õ\Ô\ˆ8Ñ\Ô\Ð\Ð\Ð\Ñ\Ð\Õ\Õ\Ô\Ð\Ñ\Ô\Ñ\Ô\Ð\Ð\Ð\r3   c                 óp  — d} t          | ¦  «        }t          d„ |d         D ¦   «         ¦  «        }|sƒt          j        d|d         › �¦  «        dz   ddt	          j        ¦   «         v st          j        |¦  «        rt          j        |¦  «        ndiz  }t          t          j	        |¦  «        ¦  «        ‚dS )	zLModifying server meridian_catalog.py should flag client meridian_catalog.js.z server/world/meridian_catalog.pyc              3  ó   K  — | ]}d |v V — Œ	dS )zmeridian_catalog.jsNrY   rZ   s     r1   r]   z7test_blast_radius_dual_stack_catalog.<locals>.<genexpr>=   s(   è è € ÐSÐS¸Ð.°!Ð3ÐSÐSÐSÐSÐSÐSr3   rO   z3Expected client meridian_catalog.js counterpart in r^   r   Úany_client_catN©
r2   r`   r   r%   r!   r"   r#   r$   r'   r(   )r   rB   rq   rd   s       r1   Ú$test_blast_radius_dual_stack_catalogrs   9   sÇ   € à/€FÝ
˜6Ñ
"Ô
"€CÝÐSÐS¸SÐAQÔ=RÐSÑSÔSÑSÔS€NØÐhÕhÔhÐhÐQTÐUeÔQfÐhÐhÑhÔhÐhÑhÐhÐhÕhÔhÑhÔhÐhÐhÕhÔhˆ>ÑhÔhÐhÕhÔhˆ>ÑhÔhÐhÐhÐhÑhÐhÕhÕhÔhÐhÑhÔhÑhÔhÐhÐhÐhr3   c                 ót  — d} t          | ¦  «        }|d         }d}||v }|slt          j        d|fd||f¦  «        t          j        |¦  «        t          j        |¦  «        dœz  }dd|iz  }t	          t          j        |¦  «        ¦  «        ‚d	x}x}}t          d
„ |d         D ¦   «         ¦  «        }|sƒt          j        d|d         › �¦  «        dz   ddt          j	        ¦   «         v st          j
        |¦  «        rt          j        |¦  «        ndiz  }t	          t          j        |¦  «        ¦  «        ‚d	S )zMModifying proto/meridian.proto should flag dependent server and client files.zproto/meridian.protor6   rI   rL   rN   r8   r;   r<   Nc              3  ó   K  — | ]}d |v V — Œ	dS )ÚmeridianNrY   rZ   s     r1   r]   z1test_blast_radius_proto_schema.<locals>.<genexpr>F   s&   è è € ÐEÐE¨!�j A�oÐEÐEÐEÐEÐEÐEr3   rO   zExpected meridian services in r^   r   r_   )r2   r   r    r$   r'   r(   r`   r%   r!   r"   r#   )	r   rB   rC   r.   rD   rE   rF   r_   rd   s	            r1   Útest_blast_radius_proto_schemarw   A   ss  € à#€FÝ
˜6Ñ
"Ô
"€CØˆ|ÔÐ4Ð 4Ð4ÐÐ 4Ð4Ð4Ð4Ð4Õ4Ô4Ð4Ð4Ð4Ð4ÐÐ 4Ð4Ñ4Ô4Õ4Ô4ÐÑ4Ô4Õ4Ô4Ð 4Ñ4Ô4Ð4Ð4Ñ4Ð4Ð4Ð4Ð4Ð4Ñ4Ð4Õ4Õ4Ô4Ð4Ñ4Ô4Ñ4Ô4Ð4Ð4Ð4Ð4Ð4Ð4Ð4ÝÐEÐE¨sÐ3CÔ/DÐEÑEÔEÑEÔE€KØÐPÕPÔPÐP¸Ð=MÔ9NÐPÐPÑPÔPÐPÑPÐPÐPÕPÔPÑPÔPÐPÐPÕPÔPˆ;ÑPÔPÐPÕPÔPˆ;ÑPÔPÐPÐPÐPÑPÐPÕPÕPÔPÐPÑPÔPÑPÔPÐPÐPÐPr3   c                 óp  — d} t          | ¦  «        }t          d„ |d         D ¦   «         ¦  «        }|sƒt          j        d|d         › �¦  «        dz   ddt	          j        ¦   «         v st          j        |¦  «        rt          j        |¦  «        ndiz  }t          t          j	        |¦  «        ¦  «        ‚dS )	zAModifying server_cpp FFI should flag python native engine bridge.zserver_cpp/src/sim_core_ffi.cppc              3  ó   K  — | ]}d |v V — Œ	dS )znative_engine_bridge.pyNrY   rZ   s     r1   r]   z/test_blast_radius_cpp_engine.<locals>.<genexpr>N   s(   è è € ÐSÐS¸Ð.°!Ð3ÐSÐSÐSÐSÐSÐSr3   rO   z$Expected native_engine_bridge.py in r^   r   Ú
any_bridgeNrr   )r   rB   rz   rd   s       r1   Útest_blast_radius_cpp_enginer{   J   sÆ   € à.€FÝ
˜6Ñ
"Ô
"€CÝÐSÐS¸SÐAQÔ=RÐSÑSÔSÑSÔS€JØÐUÕUÔUÐU¸cÐBRÔ>SÐUÐUÑUÔUÐUÑUÐUÐUÕUÔUÑUÔUÐUÐUÕUÔUˆ:ÑUÔUÐUÕUÔUˆ:ÑUÔUÐUÐUÐUÑUÐUÕUÕUÔUÐUÑUÔUÑUÔUÐUÐUÐUr3   c                 óP  — d} t          | ¦  «        }|d         }t          |¦  «        }d}||k    }|sÇt          j        d|fd||f¦  «        dt	          j        ¦   «         v st          j        t          ¦  «        rt          j        t          ¦  «        ndt          j        |¦  «        t          j        |¦  «        t          j        |¦  «        dœz  }dd	|iz  }t          t          j	        |¦  «        ¦  «        ‚d
x}x}x}}t          d„ |d         D ¦   «         ¦  «        }|sƒt          j        d|d         › �¦  «        dz   ddt	          j        ¦   «         v st          j        |¦  «        rt          j        |¦  «        ndiz  }	t          t          j	        |	¦  «        ¦  «        ‚d
S )zOQuerying an Act or Boss entity should retrieve cross_relationships from SQLite.ÚACT_I_HUNGERÚdomain_impactsr   rP   rR   rS   rT   rU   rV   Nc              3  ó&   K  — | ]}d |v pd|v V — ŒdS )ÚACT_CONTAINS_ZONEÚzone_NrY   )r[   Úimps     r1   r]   z3test_blast_radius_matrix_triples.<locals>.<genexpr>W   s1   è è € Ð`Ð`À3Ð%¨Ð,Ð>°¸3°Ð`Ð`Ð`Ð`Ð`Ð`r3   zExpected relational triples in r^   r   Úany_relrm   )
r   rB   r,   r.   ra   rb   r0   rc   rƒ   rd   s
             r1   Ú test_blast_radius_matrix_triplesr„   R   sÍ  € à€FÝ
˜6Ñ
"Ô
"€CØÐ#Ô$Ð)�3Ð$Ñ%Ô%Ð)¨Ð)Ð%¨Ò)Ð)Ð)Ð)Õ)Ô)Ð)Ð)Ð)Ð)Ð%¨Ð)Ñ)Ô)Ð)Õ)Ô)Ñ)Ô)Ð)Ð)Õ)Ô)�3Ñ)Ô)Ð)Õ)Ô)�3Ñ)Ô)Ð)Ð)Õ)Ô)Ð$Ñ)Ô)Õ)Ô)Ð%Ñ)Ô)Õ)Ô)¨Ñ)Ô)Ð)Ð)Ñ)Ð)Ð)Ð)Ð)Ð)Ñ)Ð)Õ)Õ)Ô)Ð)Ñ)Ô)Ñ)Ô)Ð)Ð)Ð)Ð)Ð)Ð)Ð)Ð)Ð)ÝÐ`Ð`È#ÐN^ÔJ_Ð`Ñ`Ô`Ñ`Ô`€GØÐMÕMÔMÐM°cÐ:JÔ6KÐMÐMÑMÔMÐMÑMÐMÐMÕMÔMÑMÔMÐMÐMÕMÔMˆ7ÑMÔMÐMÕMÔMˆ7ÑMÔMÐMÐMÐMÑMÐMÕMÕMÔMÐMÑMÔMÑMÔMÐMÐMÐMr3   )r   r   r   r   r	   r
   )r	   r4   )Ú__doc__Ú
__future__r   Úbuiltinsr!   Ú_pytest.assertion.rewriteÚ	assertionÚrewriter   r   Úosr   r   ÚpytestÚpathÚabspathÚjoinÚdirnameÚ__file__r   r   r2   rG   re   ri   rn   rs   rw   r{   r„   rY   r3   r1   ú<module>r’      sŒ  ðØ =Ð =Ø "Ð "Ð "Ð "Ð "Ð "à  € € € € € € € € € € € € €€€€Ø 	€	€	€	Ø Ð Ð Ð Ø 
€
€
€
Ø €€€àŒw�Š˜rœwŸ|š|¨B¬G¯OªO¸HÑ,EÔ,EÀtÈTÑRÔRÑSÔS€ØŒg�lŠl˜<¨°*Ð>OÑPÔP€ð%ð %ð %ð %ð:ð :ð :ð :ðZð Zð Zð Zð'ð 'ð 'ð 'ð]ð ]ð ]ð ]ðið ið ið iðQð Qð Qð QðVð Vð Vð VðNð Nð Nð Nð Nð Nr3   