§
    [¿jœ7  ã                  óŠ  — U d Z ddl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	m
Z
 ddlmZmZmZ ddlZddlmZmZ ddlmZ de_         e
e¦  «                             ¦   «         j        j        j        Zed	z  d
z  dz  dz  dz  ZdZded<   dd„Z G d„ d¦  «        Z G d„ d¦  «        Z G d„ d¦  «        Z  G d„ d¦  «        Z!dS )a&  
Adversarial Stress Test Suite for FreeExile 30 Map Styles Assets.
Verifies decompression throughput, SLA latencies, concurrent thread safety,
memory footprint constraints (< 500 KB active biome, < 8 MB all 30 styles),
and resilience against corrupt, zero-byte, truncated, and malicious files.
é    )ÚannotationsN)ÚPath)ÚDictÚListÚTuple)ÚImageÚ	ImageFile)Úlist_available_stylesFÚclientÚwebappÚassetsÚmapÚstyles)	ú	floor.pngúfloor_normal.pngúwall.pngúwall_normal.pngúpath.pngúpath_normal.pngú
liquid.pngúliquid_normal.pngú	props.pngzTuple[str, ...]ÚCORE_ASSET_NAMESÚ	file_pathr   ÚreturnúTuple[int, int, float]c                ó   — t          j        ¦   «         }t          j        | ¦  «        5 }|                     ¦   «          |j        |j        }}ddd¦  «         n# 1 swxY w Y   t          j        ¦   «         |z
  dz  }|||fS )z@Decompresses image file and returns (width, height, elapsed_ms).Nç     @�@)ÚtimeÚperf_counterr   ÚopenÚloadÚwidthÚheight)r   Út0ÚimgÚwÚhÚ
elapsed_mss         úFC:\Projects\FreeExile\tests\unit\test_map_styles_adversarial_stress.pyÚ_load_and_decompressr+   *   s³   € å	Ô	Ñ	Ô	€BÝ	Œ�IÑ	Ô	ð % #Ø�Š‰
Œ
ˆ
ØŒy˜#œ*ˆ1ˆð%ð %ð %ñ %ô %ð %ð %ð %ð %ð %ð %øøøð %ð %ð %ð %õ Ô#Ñ%Ô%¨Ñ*¨fÑ4€JØˆa�ÐÐs   ¨#AÁAÁAc                  ó*   — e Zd ZdZdd„Zdd„Zdd„ZdS )	Ú)TestAssetDecompressionAndThroughputStresszHStress-tests decompression latencies, throughput, and concurrent access.r   ÚNonec                ób  — g }t          ¦   «         }t          |¦  «        dk    sJ ‚|D ]–}t          |                     ¦   «         z  }t          D ]-}t          ||z  ¦  «        \  }}}|                     |¦  «         Œ.|dz                       d¦  «        D ]*}t          |¦  «        \  }}}|                     |¦  «         Œ+Œ—t          |¦  «        dk    sJ ‚t          |¦  «        }	t          |¦  «        t          |¦  «        z  }
t          |¦  «        }|t          t          |¦  «        dz  ¦  «                 }|t          t          |¦  «        dz  ¦  «                 }|	dk     sJ d|	d	›d
�¦   «         ‚|dk     sJ d|d	›d�¦   «         ‚|dk     sJ d|d	›d�¦   «         ‚|
dk     sJ d|
d	›d�¦   «         ‚dS )z;Every single asset must decompress within p99 < 25.0ms SLA.é   Úpropsú*.pngih  gffffffî?g®Gáz®ï?g      9@zMax decompression latency ú.2fz
ms >= 25msg      @zP99 latency z	ms >= 5msg       @zP95 latency z	ms >= 2msg      ð?zMean latency z	ms >= 1msN)r
   ÚlenÚSTYLES_ROOTÚlowerr   r+   ÚappendÚglobÚmaxÚsumÚsortedÚint)ÚselfÚ	latenciesr   Ús_idÚs_dirÚfnameÚ_ÚelapsedÚp_fileÚmax_latÚmean_latÚ
sorted_latÚp95_latÚp99_lats                 r*   Ú%test_all_360_assets_decompression_slazOTestAssetDecompressionAndThroughputStress.test_all_360_assets_decompression_sla7   sä  € à!#ˆ	Ý&Ñ(Ô(ˆÝ�6‰{Œ{˜bÒ Ð Ð Ð àð 	*ð 	*ˆDÝ $§*¢*¡,¤,Ñ.ˆEÝ)ð *ð *�Ý 4°U¸U±]Ñ CÔ C‘��1�gØ× Ò  Ñ)Ô)Ð)Ð)Ø  7™?×0Ò0°Ñ9Ô9ð *ð *�Ý 4°VÑ <Ô <‘��1�gØ× Ò  Ñ)Ô)Ð)Ð)ð*õ �9‰~Œ~ Ò$Ð$Ð$Ð$Ý�i‘.”.ˆÝ�y‘>”>¥C¨	¡N¤NÑ2ˆÝ˜IÑ&Ô&ˆ
Ø�S¥ Z¡¤°4Ñ!7Ñ8Ô8Ô9ˆØ�S¥ Z¡¤°4Ñ!7Ñ8Ô8Ô9ˆà˜Š~ˆ~ˆ~ÐS¸GÐSÐSÐSÐS‰~Œ~ˆ~Ø˜Š}ˆ}ˆ}ÐC¨WÐCÐCÐCÐC‰}Œ}ˆ}Ø˜Š}ˆ}ˆ}ÐC¨WÐCÐCÐCÐC‰}Œ}ˆ}Ø˜#Š~ˆ~ˆ~ÐF¨xÐFÐFÐFÐF‰~Œ~ˆ~ˆ~ˆ~ó    c           	     ó‚  — t          ¦   «         }g }t          d¦  «        D ]±}|D ]¬}t          |                     ¦   «         z  }t	          j        ¦   «         }t          D ]E}t          j        ||z  ¦  «        5 }| 	                    ¦   «          ddd¦  «         n# 1 swxY w Y   ŒFt	          j        ¦   «         |z
  dz  }	| 
                    |	¦  «         Œ­Œ²t          |¦  «        dk    sJ ‚t          |¦  «        t          |¦  «        z  }
t          |¦  «        }|
dk     sJ d|
d›d�¦   «         ‚|d	k     sJ d
|d›d�¦   «         ‚dS )z@Simulates rapid player traversal across 30 biomes over 3 cycles.é   Nr   éZ   g      .@zAverage switch r3   z
ms >= 15msg      I@zMax switch z
ms >= 50ms)r
   Úranger5   r6   r   r    r   r   r!   r"   r7   r4   r:   r9   )r=   r   Útotal_biome_timesrB   r?   r@   r%   rA   r&   Úbiome_time_msÚavg_switch_timeÚmax_switch_times               r*   Ú!test_rapid_biome_switching_stresszKTestAssetDecompressionAndThroughputStress.test_rapid_biome_switching_stressR   sª  € å&Ñ(Ô(ˆØ)+Ðå�q‘”ð 	8ð 	8ˆAØð 8ð 8�Ý# d§j¢j¡l¤lÑ2�ÝÔ&Ñ(Ô(�Ý-ð #ð #�EÝœ E¨E¡MÑ2Ô2ð #°cØŸš™
œ
˜
ð#ð #ð #ñ #ô #ð #ð #ð #ð #ð #ð #øøøð #ð #ð #ð #øå!%Ô!2Ñ!4Ô!4°rÑ!9¸VÑ C�Ø!×(Ò(¨Ñ7Ô7Ð7Ð7ð8õ Ð$Ñ%Ô%¨Ò+Ð+Ð+Ð+ÝÐ/Ñ0Ô0µ3Ð7HÑ3IÔ3IÑIˆÝÐ/Ñ0Ô0ˆØ Ò%Ð%Ð%Ð'X¸Ð'XÐ'XÐ'XÐ'XÑ%Ô%Ð%Ø Ò%Ð%Ð%Ð'T°_Ð'TÐ'TÐ'TÐ'TÑ%Ô%Ð%Ð%Ð%s   Á5B	ÂBÂBc                ó  ‡‡‡— t          ¦   «         }g }|D ]D}t          |                     ¦   «         z  Š|                     ˆfd„t          D ¦   «         ¦  «         ŒEdd„Št
          j                             d¬¦  «        5 Šˆˆfd	„|D ¦   «         }d
„ t
          j                             |¦  «        D ¦   «         }ddd¦  «         n# 1 swxY w Y   t          |¦  «        t          |¦  «        k    sJ ‚t          |¦  «        sJ ‚dS )z<20 concurrent threads decompressing textures simultaneously.c              3  ó"   •K  — | ]	}‰|z  V — Œ
d S )N© )Ú.0Úfr@   s     €r*   ú	<genexpr>ziTestAssetDecompressionAndThroughputStress.test_concurrent_multi_threaded_decompression.<locals>.<genexpr>m   s'   øè è € Ð=Ð= q˜ ™Ð=Ð=Ð=Ð=Ð=Ð=rK   Úpathr   r   Úboolc                ó²   — t          j        | ¦  «        5 }|                     ¦   «          |j        dk    o
|j        dk    cd d d ¦  «         S # 1 swxY w Y   d S )Nr   )r   r!   r"   r#   r$   )r[   r&   s     r*   ÚworkerzfTestAssetDecompressionAndThroughputStress.test_concurrent_multi_threaded_decompression.<locals>.workero   s”   € Ý”˜DÑ!Ô!ð 8 SØ—’‘
”
�
Ø”y 1’}Ð7¨¬°aªð8ð 8ð 8ð 8ñ 8ô 8ð 8ð 8ð 8ð 8ð 8ð 8øøøð 8ð 8ð 8ð 8ð 8ð 8s   •*AÁAÁAé   )Úmax_workersc                ó<   •— g | ]}‰                      ‰|¦  «        ‘ŒS rW   )Úsubmit)rX   ÚpÚexecutorr^   s     €€r*   ú
<listcomp>zjTestAssetDecompressionAndThroughputStress.test_concurrent_multi_threaded_decompression.<locals>.<listcomp>u   s'   ø€ ÐAÐAÐA°a�x—’ v¨qÑ1Ô1ÐAÐAÐArK   c                ó6   — g | ]}|                      ¦   «         ‘ŒS rW   )Úresult)rX   rY   s     r*   re   zjTestAssetDecompressionAndThroughputStress.test_concurrent_multi_threaded_decompression.<locals>.<listcomp>v   s    € ÐTÐTÐT a�q—x’x‘z”zÐTÐTÐTrK   N)r[   r   r   r\   )r
   r5   r6   Úextendr   Ú
concurrentÚfuturesÚThreadPoolExecutorÚas_completedr4   Úall)	r=   r   Útasksr?   rj   Úresultsrd   r@   r^   s	         @@@r*   Ú,test_concurrent_multi_threaded_decompressionzVTestAssetDecompressionAndThroughputStress.test_concurrent_multi_threaded_decompressiong   si  øøø€ å&Ñ(Ô(ˆØˆØð 	>ð 	>ˆDÝ $§*¢*¡,¤,Ñ.ˆEØ�LŠLÐ=Ð=Ð=Ð=Õ,<Ð=Ñ=Ô=Ñ=Ô=Ð=Ð=ð	8ð 	8ð 	8ð 	8õ
 Ô×2Ò2¸rÐ2ÑBÔBð 	UÀhØAÐAÐAÐAÐA¸5ÐAÑAÔAˆGØTÐT­:Ô+=×+JÒ+JÈ7Ñ+SÔ+SÐTÑTÔTˆGð	Uð 	Uð 	Uñ 	Uô 	Uð 	Uð 	Uð 	Uð 	Uð 	Uð 	Uøøøð 	Uð 	Uð 	Uð 	Uõ �7‰|Œ|�s 5™zœzÒ)Ð)Ð)Ð)Ý�7‰|Œ|ÐÐˆ|ÐÐs   Á?9CÃCÃCN©r   r.   )Ú__name__Ú
__module__Ú__qualname__Ú__doc__rJ   rT   rp   rW   rK   r*   r-   r-   4   s^   € € € € € ØRÐRðGð Gð Gð Gð6Uð Uð Uð Uð*ð ð ð ð ð rK   r-   c                  ó�   — e Zd ZdZdd„Zej                             dg d¢¦  «        dd
„¦   «         Zdd„Z	dd„Z
dd„Zdd„Zdd„ZdS )Ú)TestAdversarialFileCorruptionAndEdgeCaseszQStress-tests behavior under corrupted, zero-byte, truncated, and malicious files.Útmp_pathr   r   r.   c                ó  — |dz  }|                      ¦   «          t          j        t          f¦  «        5  t	          j        |¦  «        5 }|                     ¦   «          ddd¦  «         n# 1 swxY w Y   ddd¦  «         dS # 1 swxY w Y   dS )z=Zero-byte file must raise UnidentifiedImageError or EOFError.zzero.pngN)ÚtouchÚpytestÚraisesÚ	Exceptionr   r!   r"   )r=   rx   Ú	zero_filer&   s       r*   Útest_zero_byte_asset_rejectionzHTestAdversarialFileCorruptionAndEdgeCases.test_zero_byte_asset_rejection   s  € à˜zÑ)ˆ	Ø�ŠÑÔÐÝŒ]�I˜<Ñ(Ô(ð 	ð 	Ý”˜IÑ&Ô&ð ¨#Ø—’‘
”
�
ðð ð ñ ô ð ð ð ð ð ð øøøð ð ð ð ð	ð 	ð 	ñ 	ô 	ð 	ð 	ð 	ð 	ð 	ð 	ð 	øøøð 	ð 	ð 	ð 	ð 	ð 	s5   ´BÁ	A*ÁBÁ*A.	Á.BÁ1A.	Á2BÂBÂ	BÚlength)é   é   é   é   é   r<   c                óz  — t           dz  dz  }|                     ¦   «         }|d|› d�z  }|                     |d|…         ¦  «         t          j        t
          f¦  «        5  t          j        |¦  «        5 }|                     ¦   «          ddd¦  «         n# 1 swxY w Y   ddd¦  «         dS # 1 swxY w Y   dS )z@Truncated byte streams must be detected and rejected gracefully.Ústy_01_hoang_mang_co_lor   Útrunc_z.pngN)	r5   Ú
read_bytesÚwrite_bytesr{   r|   r}   r   r!   r"   )r=   rx   r€   Úsample_pathÚraw_dataÚ
trunc_filer&   s          r*   Útest_truncated_stream_rejectionzITestAdversarialFileCorruptionAndEdgeCases.test_truncated_stream_rejection‡   s=  € õ "Ð$=Ñ=ÀÑKˆØ×)Ò)Ñ+Ô+ˆØÐ 5¨Ð 5Ð 5Ð 5Ñ5ˆ
Ø×Ò˜x¨¨¨Ô0Ñ1Ô1Ð1åŒ]�I˜<Ñ(Ô(ð 	ð 	Ý”˜JÑ'Ô'ð ¨3Ø—’‘
”
�
ðð ð ñ ô ð ð ð ð ð ð øøøð ð ð ð ð	ð 	ð 	ñ 	ô 	ð 	ð 	ð 	ð 	ð 	ð 	ð 	øøøð 	ð 	ð 	ð 	ð 	ð 	s6   Á"B0Á7BÂB0ÂB	ÂB0ÂB	Â B0Â0B4Â7B4c                ó  — t           dz  dz  }t          |                     ¦   «         ¦  «        }|                     d¦  «        }|dk    sJ ‚t	          d¦  «        D ]}||dz   |z            dz  ||dz   |z   <   Œ|dz  }|                     |¦  «         t          j        t          f¦  «        5  t          j
        |¦  «        5 }|                     ¦   «          d	d	d	¦  «         n# 1 swxY w Y   d	d	d	¦  «         d	S # 1 swxY w Y   d	S )
z?Corrupted IDAT chunk payload must fail without unhandled crash.r‡   r   s   IDATéÿÿÿÿr„   rƒ   éÿ   zcorrupt_idat.pngN)r5   Ú	bytearrayr‰   ÚfindrO   rŠ   r{   r|   r}   r   r!   r"   )r=   rx   r‹   ÚdataÚidat_posÚiÚcorrupt_filer&   s           r*   Útest_corrupted_idat_zlib_streamzITestAdversarialFileCorruptionAndEdgeCases.test_corrupted_idat_zlib_stream“   s�  € å!Ð$=Ñ=ÀÑKˆÝ˜×/Ò/Ñ1Ô1Ñ2Ô2ˆØ—9’9˜WÑ%Ô%ˆØ˜2Š~ˆ~ˆ~ˆ~å�r‘”ð 	Eð 	EˆAØ&*¨8°a©<¸!Ñ+;Ô&<¸tÑ&CˆD�˜A‘ Ñ!Ñ"Ð"àÐ"4Ñ4ˆØ× Ò  Ñ&Ô&Ð&ÝŒ]�I˜<Ñ(Ô(ð 	ð 	Ý”˜LÑ)Ô)ð ¨SØ—’‘
”
�
ðð ð ñ ô ð ð ð ð ð ð øøøð ð ð ð ð	ð 	ð 	ñ 	ô 	ð 	ð 	ð 	ð 	ð 	ð 	ð 	øøøð 	ð 	ð 	ð 	ð 	ð 	s6   Â,C:ÃC"ÃC:Ã"C&	Ã&C:Ã)C&	Ã*C:Ã:C>ÄC>c                óÜ  — t           dz  dz  }t          |                     ¦   «         ¦  «        }|                     d¦  «        }|dk    sJ ‚||dz   xx         dz  cc<   |dz  }|                     |¦  «         t          j        t          f¦  «        5  t          j	        |¦  «        5 }| 
                    ¦   «          ddd¦  «         n# 1 swxY w Y   ddd¦  «         dS # 1 swxY w Y   dS )	z<Tampered CRC32 checksum in PNG chunk is rejected or flagged.r‡   r   ó   IHDRr�   é   r‘   zcorrupt_crc.pngN)r5   r’   r‰   r“   rŠ   r{   r|   r}   r   r!   Úverify)r=   rx   r‹   r”   Úihdr_posr—   r&   s          r*   Útest_corrupted_crc32_checksumzGTestAdversarialFileCorruptionAndEdgeCases.test_corrupted_crc32_checksum£   sm  € å!Ð$=Ñ=ÀÑKˆÝ˜×/Ò/Ñ1Ô1Ñ2Ô2ˆØ—9’9˜WÑ%Ô%ˆØ˜2Š~ˆ~ˆ~ˆ~àˆX˜‰]ÐÐÔ˜tÑ#ÐÐÑØÐ"3Ñ3ˆØ× Ò  Ñ&Ô&Ð&ÝŒ]�I˜<Ñ(Ô(ð 	ð 	Ý”˜LÑ)Ô)ð ¨SØ—
’
‘”�ðð ð ñ ô ð ð ð ð ð ð øøøð ð ð ð ð	ð 	ð 	ñ 	ô 	ð 	ð 	ð 	ð 	ð 	ð 	ð 	øøøð 	ð 	ð 	ð 	ð 	ð 	s6   ÂC!Â(C	Â=C!Ã	C	ÃC!ÃC	ÃC!Ã!C%Ã(C%c                ó   — t           dz  dz  t           dz  dz  dz  dz  t           dz  dz  t          d¦  «        g}|D ]�}|                     ¦   «         rJ ‚t          j        t
          t          f¦  «        5  t          j        |¦  «        5 }| 	                    ¦   «          d	d	d	¦  «         n# 1 swxY w Y   d	d	d	¦  «         n# 1 swxY w Y   Œ‘d	S )
z6Invalid paths and path traversal payloads fail safely.Ústy_non_existentr   z..r   z	ghost.pngr‡   zmissing.pngz)C:/Windows/System32/drivers/etc/hosts.pngN)
r5   r   Úis_filer{   r|   ÚFileNotFoundErrorÚOSErrorr   r!   r"   )r=   Útraversal_pathsrc   r&   s       r*   Ú$test_nonexistent_paths_and_traversalzNTestAdversarialFileCorruptionAndEdgeCases.test_nonexistent_paths_and_traversal±   sQ  € õ Ð,Ñ,¨{Ñ:Ý˜$Ñ Ñ%¨Ñ0°;Ñ>ÝÐ3Ñ3°mÑCÝÐ<Ñ=Ô=ð	
ˆð !ð 	ð 	ˆAØ—y’y‘{”{Ð"Ð"�?Ý”Õ 1µ7Ð;Ñ<Ô<ð ð Ý”Z ‘]”]ð  cØ—H’H‘J”J�Jðð ð ñ ô ð ð ð ð ð ð øøøð ð ð ð ðð ð ñ ô ð ð ð ð ð ð øøøð ð ð ð øð	ð 	s6   Á5CÂ
B+ÂCÂ+B/Â/CÂ2B/Â3CÃC	Ã	C	c                ó`  — dddddœ}|                      ¦   «         D ]‘\  }}||z  }|                     |¦  «         t          j        t          f¦  «        5  t          j        |¦  «        5 }|                     ¦   «          ddd¦  «         n# 1 swxY w Y   ddd¦  «         n# 1 swxY w Y   Œ’dS )zENon-PNG text, HTML, and JSON payloads disguised as .png are rejected.s'   <html><body>404 Not Found</body></html>s&   {"error": "Unauthorized", "code": 401}s   GIF89a  €  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 ÿª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 ÿª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 ÿªU ÿªU ÿªU ÿªU ÿªU ÿªU ÿªU ÿªU ÿªU ÿªU ÿªU ÿªU ÿªU ÿªU)zhtml.pngzjson.pngzfake_gif.pngzbinary_junk.pngN)ÚitemsrŠ   r{   r|   r}   r   r!   r"   )r=   rx   ÚpayloadsÚnameÚcontentrY   r&   s          r*   Útest_disguised_non_png_fileszFTestAdversarialFileCorruptionAndEdgeCases.test_disguised_non_png_files¿   s6  € ð CØAØAØ8ð	&
ð &
ˆð &Ÿ^š^Ñ-Ô-ð 	ð 	‰MˆD�'Ø˜4‘ˆAØ�MŠM˜'Ñ"Ô"Ð"Ý”¥	˜|Ñ,Ô,ð ð Ý”Z ‘]”]ð  cØ—H’H‘J”J�Jðð ð ñ ô ð ð ð ð ð ð øøøð ð ð ð ðð ð ñ ô ð ð ð ð ð ð øøøð ð ð ð øð	ð 	s6   ÁB"Á*BÁ?B"ÂBÂB"ÂBÂB"Â"B&	Â)B&	c                ó´  — t          j        ¦   «         }t          j        ddd¦  «                             |d¬¦  «         t          |                     ¦   «         ¦  «        }|                     d¦  «        }t          j	        d||dz   d	d	¦  «         |||d
z   …         }t          j        |¦  «        }t          j	        d||d
z   |¦  «         |dz  }|                     |¦  «         t          j        t          f¦  «        5  t          j        |¦  «        5 }|                     ¦   «          ddd¦  «         n# 1 swxY w Y   ddd¦  «         dS # 1 swxY w Y   dS )zECrafted huge dimension header is trapped safely by PIL safety limits.ÚRGB)r�   r�   )r   r   r   ÚPNG)Úformatrš   z>IIr‚   iÿÿ  r›   z>Izbomb.pngN)ÚioÚBytesIOr   ÚnewÚsaver’   Úgetvaluer“   ÚstructÚ	pack_intoÚzlibÚcrc32rŠ   r{   r|   r}   r!   r"   )	r=   rx   Úbior”   r�   Ú
chunk_dataÚnew_crcÚ	bomb_pathr&   s	            r*   Ú,test_decompression_dimension_overflow_safetyzVTestAdversarialFileCorruptionAndEdgeCases.test_decompression_dimension_overflow_safetyÎ   s¹  € õ Œj‰lŒlˆÝŒ	�%˜ Ñ+Ô+×0Ò0°¸UÐ0ÑCÔCÐCÝ˜Ÿš™œÑ(Ô(ˆØ—9’9˜WÑ%Ô%ˆÝÔ˜  h°¡l°E¸5ÑAÔAÐAà˜( X°¡]Ð2Ô3ˆ
Ý”*˜ZÑ(Ô(ˆÝÔ˜˜t X°¡]°GÑ<Ô<Ð<à˜zÑ)ˆ	Ø×Ò˜dÑ#Ô#Ð#åŒ]�I˜<Ñ(Ô(ð 	ð 	Ý”˜IÑ&Ô&ð ¨#Ø—’‘
”
�
ðð ð ñ ô ð ð ð ð ð ð øøøð ð ð ð ð	ð 	ð 	ñ 	ô 	ð 	ð 	ð 	ð 	ð 	ð 	ð 	øøøð 	ð 	ð 	ð 	ð 	ð 	s6   Ã?EÄD5Ä)EÄ5D9	Ä9EÄ<D9	Ä=EÅEÅEN)rx   r   r   r.   )rx   r   r€   r<   r   r.   rq   )rr   rs   rt   ru   r   r{   ÚmarkÚparametrizerŽ   r˜   rž   r¥   r«   r½   rW   rK   r*   rw   rw   |   sÌ   € € € € € Ø[Ð[ðð ð ð ð „[×Ò˜XÐ'8Ð'8Ð'8Ñ9Ô9ð	ð 	ð 	ñ :Ô9ð	ðð ð ð ð ð ð ð ðð ð ð ðð ð ð ðð ð ð ð ð rK   rw   c                  ó*   — e Zd ZdZdd„Zdd„Zdd„ZdS )	Ú!TestMemoryConsumptionVerificationzKVerifies RAM and disk budgets: active biome < 500 KB, all 30 styles < 8 MB.r   r.   c                ó*  — t          ¦   «         }d}|D ]ì}t          |                     ¦   «         z  }d}t          D ]F}t	          j        ||z  ¦  «        5 }||j        |j        z  dz  z  }ddd¦  «         n# 1 swxY w Y   ŒG|dz                       d¦  «        D ]C}t	          j        |¦  «        5 }||j        |j        z  dz  z  }ddd¦  «         n# 1 swxY w Y   ŒD||k    r|}|dk     sJ |› d|dz  d	›d
�¦   «         ‚Œí|dk    sJ d|› �¦   «         ‚dS )z=Every active biome raw RGBA buffer must be strictly < 500 KB.r   r‚   Nr1   r2   i Ð z memory i   r3   z KB exceeds 500 KB limiti € zUnexpected footprint: )	r
   r5   r6   r   r   r!   r#   r$   r8   )	r=   r   Úmax_biome_ramr?   r@   Ú	biome_ramrA   r&   rD   s	            r*   Ú4test_active_biome_uncompressed_footprint_under_500kbzVTestMemoryConsumptionVerification.test_active_biome_uncompressed_footprint_under_500kbæ   sÚ  € å&Ñ(Ô(ˆØˆàð 	ð 	ˆDÝ $§*¢*¡,¤,Ñ.ˆEØˆIå)ð <ð <�Ý”Z ¨¡Ñ.Ô.ð <°#Ø ¤¨S¬ZÑ!7¸!Ñ!;Ñ;�Ið<ð <ð <ñ <ô <ð <ð <ð <ð <ð <ð <øøøð <ð <ð <ð <øð ! 7™?×0Ò0°Ñ9Ô9ð <ð <�Ý”Z Ñ'Ô'ð <¨3Ø ¤¨S¬ZÑ!7¸!Ñ!;Ñ;�Ið<ð <ð <ñ <ô <ð <ð <ð <ð <ð <ð <øøøð <ð <ð <ð <øð ˜=Ò(Ð(Ø )�ð ˜zÒ)Ð)Ð)ØÐOÐO ¨TÑ!1ÐOÐOÐOÐOñ *Ô)Ð)Ð)ð
  
Ò*Ð*Ð*Ð,TÀ]Ð,TÐ,TÑ*Ô*Ð*Ð*Ð*s$   ÁA5Á5A9Á<A9Â/CÃCÃCc                ó   — d}t          ¦   «         D ]R}t          |                     ¦   «         z  }|                     d¦  «        D ]}||                     ¦   «         j        z  }ŒŒS|dz  }|dk     sJ d|d›d�¦   «         ‚dS )	zHTotal disk size across all 30 style directories must be strictly < 8 MB.r   r2   é   ç       @zTotal disk size r3   z MB unexpectedly highN)r
   r5   r6   ÚrglobÚstatÚst_size)r=   Útotal_disk_bytesr?   r@   rY   Útotal_disk_mbs         r*   Ú0test_all_30_styles_aggregate_disk_size_under_8mbzRTestMemoryConsumptionVerification.test_all_30_styles_aggregate_disk_size_under_8mb  s¢   € àÐÝ)Ñ+Ô+ð 	5ð 	5ˆDÝ $§*¢*¡,¤,Ñ.ˆEØ—[’[ Ñ)Ô)ð 5ð 5�Ø  A§F¢F¡H¤HÔ$4Ñ4Ð Ð ð5ð )¨KÑ8ˆà˜sÒ"Ð"Ð"Ð$_°}Ð$_Ð$_Ð$_Ð$_Ñ"Ô"Ð"Ð"Ð"rK   c                óx  — d}d}t          ¦   «         D ]g}t          |                     ¦   «         z  }|D ]F}t          j        ||z  ¦  «        5 }||j        |j        z  dz  z  }ddd¦  «         n# 1 swxY w Y   ŒGŒh|dz  }|dk     sJ d|d›d	�¦   «         ‚t          |d
z
  ¦  «        dk     sJ d|d›d�¦   «         ‚dS )zCIn-memory core albedo textures across all 30 styles must be < 8 MB.)r   r   r   r   r   r   r‚   NrÇ   rÈ   zAlbedo buffer r3   z MB exceeds 8.0 MB budgetg\�Âõ(\@gš™™™™™¹?zExpected ~6.09 MB, got z MB)r
   r5   r6   r   r!   r#   r$   Úabs)r=   Úalbedo_namesÚtotal_albedo_ramr?   r@   rA   r&   Útotal_albedo_mbs           r*   Ú*test_all_30_styles_albedo_buffer_under_8mbzLTestMemoryConsumptionVerification.test_all_30_styles_albedo_buffer_under_8mb  sP  € àWˆØÐå)Ñ+Ô+ð 	Cð 	CˆDÝ $§*¢*¡,¤,Ñ.ˆEØ%ð Cð C�Ý”Z ¨¡Ñ.Ô.ð C°#Ø$¨¬	°C´JÑ(>ÀÑ(BÑBÐ$ðCð Cð Cñ Cô Cð Cð Cð Cð Cð Cð Cøøøð Cð Cð Cð CøðCð +¨kÑ:ˆØ Ò$Ð$Ð$ØK˜_ÐKÐKÐKÐKñ %Ô$Ð$õ �? TÑ)Ñ*Ô*¨SÒ0Ð0Ð0Ð2dÈOÐ2dÐ2dÐ2dÐ2dÑ0Ô0Ð0Ð0Ð0s   ÁA.Á.A2Á5A2Nrq   )rr   rs   rt   ru   rÅ   rÎ   rÔ   rW   rK   r*   rÁ   rÁ   ã   sd   € € € € € ØUÐUðUð Uð Uð Uð8
`ð 
`ð 
`ð 
`ðeð eð eð eð eð erK   rÁ   c                  ó*   — e Zd ZdZdd„Zdd„Zdd„ZdS )	Ú)TestTexturePixelIntegrityAndNormalVectorszMVerifies pixel validity, alpha masks, normal vector distributions, and props.r   r.   c                ó|  — t          ¦   «         }|D ]ª}t          |                     ¦   «         z  }dD ]‰}t          j        ||z  ¦  «        5 }|j        dk    sJ ‚|                     ¦   «         d         }|                     ¦   «         }|d         dk    sJ |› d|› d�¦   «         ‚	 ddd¦  «         n# 1 swxY w Y   ŒŠŒ«dS )	zLFloor, wall, path, liquid tiles must contain non-transparent colored pixels.)r   r   r   r   ÚRGBArM   r�   r‘   ú/z has no opaque pixelsN©r
   r5   r6   r   r!   ÚmodeÚsplitÚ
getextrema)r=   r   r?   r@   rA   r&   Ú
alpha_chanÚextremas           r*   Ú+test_albedo_tiles_not_empty_and_valid_alphazUTestTexturePixelIntegrityAndNormalVectors.test_albedo_tiles_not_empty_and_valid_alpha#  s0  € å&Ñ(Ô(ˆØð 	Uð 	UˆDÝ $§*¢*¡,¤,Ñ.ˆEØLð Uð U�Ý”Z ¨¡Ñ.Ô.ð U°#Øœ8 vÒ-Ð-Ð-Ð-Ø!$§¢¡¤¨Q¤�JØ(×3Ò3Ñ5Ô5�Gà" 1œ:¨Ò,Ð,Ð,°Ð.TÐ.T¸Ð.TÐ.TÐ.TÑ,Ô,Ð,Ð,ðUð Uð Uñ Uô Uð Uð Uð Uð Uð Uð Uøøøð Uð Uð Uð UøðUð	Uð 	Us   Á
AB/Â/B3Â6B3c           
     ó�  — t          ¦   «         }d}|D ]²}t          |                     ¦   «         z  }|D ]‘}t          j        ||z  ¦  «        5 }|j        dk    sJ ‚|                     ¦   «         \  }}}	}
|	                     ¦   «         }|d         dk    sJ |› d|› d|d         › d�¦   «         ‚	 ddd¦  «         n# 1 swxY w Y   Œ’Œ³dS )	zGTangent normal maps must have valid Z orientation across all 30 styles.)r   r   r   r   rØ   r�   é€   rÙ   z
 max blue z < 128NrÚ   )r=   r   Únormal_namesr?   r@   rA   r&   ÚrÚgÚbÚaÚ	b_extremas               r*   Ú%test_normal_map_z_vector_distributionzOTestTexturePixelIntegrityAndNormalVectors.test_normal_map_z_vector_distribution0  sF  € å&Ñ(Ô(ˆð
ˆð ð 	`ð 	`ˆDÝ $§*¢*¡,¤,Ñ.ˆEØ%ð `ð `�Ý”Z ¨¡Ñ.Ô.ð `°#Øœ8 vÒ-Ð-Ð-Ð-Ø!$§¢¡¤‘J�A�q˜!˜QØ !§¢¡¤�Ià$ Qœ<¨3Ò.Ð.Ð.°4Ð0_Ð0_¸%Ð0_Ð0_È9ÐUVÌ<Ð0_Ð0_Ð0_Ñ.Ô.Ð.Ð.ð`ð `ð `ñ `ô `ð `ð `ð `ð `ð `ð `øøøð `ð `ð `ð `øð`ð	`ð 	`s   ÁA B9Â9B=Ã B=c           	     óè  — t          ¦   «         D ]â}t          |                     ¦   «         z  dz  }t          j        |¦  «        5 }|j        dk    r|j        dk    sJ ‚t          d¦  «        D ]l}|                     |dz  d|dz   dz  df¦  «        }| 	                    ¦   «         d          
                    ¦   «         }|d         dk    sJ |› d|› d�¦   «         ‚Œm	 d	d	d	¦  «         n# 1 swxY w Y   Œãd	S )
zMProps composite sheet (192x64) segments cleanly into 3 non-empty 64x64 cells.r   éÀ   é@   rM   r   r�   z/props.png cell z	 is emptyN)r
   r5   r6   r   r!   r#   r$   rO   ÚcroprÜ   rÝ   )r=   r?   Ú
sheet_pathÚsheetr–   ÚcellÚalpha_extremas          r*   Útest_props_sheet_segmentationzGTestTexturePixelIntegrityAndNormalVectors.test_props_sheet_segmentationC  s`  € å)Ñ+Ô+ð 	Wð 	WˆDÝ$ t§z¢z¡|¤|Ñ3°kÑAˆJÝ”˜JÑ'Ô'ð W¨5Ø”{ cÒ)Ð)¨e¬l¸bÒ.@Ð.@Ð.@Ð@Ý˜q™œð Wð W�AØ Ÿ:š: q¨2¡v¨q°1°q±5¸B±,ÀÐ&CÑDÔD�DØ$(§J¢J¡L¤L°¤O×$>Ò$>Ñ$@Ô$@�MØ(¨Ô+¨aÒ/Ð/Ð/°DÐ1VÐ1VÈ!Ð1VÐ1VÐ1VÑ/Ô/Ð/Ð/ðWðWð Wð Wñ Wô Wð Wð Wð Wð Wð Wð Wøøøð Wð Wð Wð Wøð	Wð 	Ws   ÁBC&Ã&C*	Ã-C*	Nrq   )rr   rs   rt   ru   rà   ré   rò   rW   rK   r*   rÖ   rÖ      sd   € € € € € ØWÐWðUð Uð Uð Uð`ð `ð `ð `ð&	Wð 	Wð 	Wð 	Wð 	Wð 	WrK   rÖ   )r   r   r   r   )"ru   Ú
__future__r   Úconcurrent.futuresri   r°   rµ   r   r·   Úpathlibr   Útypingr   r   r   r{   ÚPILr   r	   Úserver.world.map_style_catalogr
   ÚLOAD_TRUNCATED_IMAGESÚ__file__ÚresolveÚparentÚPROJECT_ROOTr5   r   Ú__annotations__r+   r-   rw   rÁ   rÖ   rW   rK   r*   ú<module>rÿ      s  ððð ð ð #Ð "Ð "Ð "Ð "Ð "à Ð Ð Ð Ø 	€	€	€	Ø €€€Ø €€€Ø €€€Ø Ð Ð Ð Ð Ð Ø $Ð $Ð $Ð $Ð $Ð $Ð $Ð $Ð $Ð $à €€€Ø  Ð  Ð  Ð  Ð  Ð  Ð  Ð  à @Ð @Ð @Ð @Ð @Ð @ð #(€	Ô àˆt�H‰~Œ~×%Ò%Ñ'Ô'Ô.Ô5Ô<€Ø˜XÑ%¨Ñ0°8Ñ;¸eÑCÀhÑN€ð
%Ð ð 
ð 
ð 
ñ 
ðð ð ð ðEð Eð Eð Eð Eñ Eô Eð EðPdð dð dð dð dñ dô dð dðN:eð :eð :eð :eð :eñ :eô :eð :eðz,Wð ,Wð ,Wð ,Wð ,Wñ ,Wô ,Wð ,Wð ,Wð ,WrK   