§
    S¿j‰-  ã                  ó  — U d Z ddlm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Zd	ed
<   dZded<   dZded<   ddhZded<   dhZded<   dZded<   dZded<   d5d„Zd6d!„Z e	j        d"¬#¦  «        d7d$„¦   «         Z e	j        d"¬#¦  «        d8d&„¦   «         Z e	j        d"¬#¦  «        d9d(„¦   «         Z G d)„ d*¦  «        Z G d+„ d,¦  «        Z G d-„ d.¦  «        Z G d/„ d0¦  «        Z  G d1„ d2¦  «        Z! G d3„ d4¦  «        Z"dS ):aá  
Unit Test Suite for FreeExile 30 Map Styles Asset Integrity & Quality.
Verifies:
1. Presence of all 30 style folders under client/webapp/assets/map/styles/.
2. Presence of all 9 required textures per style:
   floor.png, wall.png, path.png, liquid.png, props.png,
   floor_normal.png, wall_normal.png, path_normal.png, liquid_normal.png.
3. Valid non-empty PNG magic header (\x89PNG\r\n\x1a\n).
4. Standard dimensions (floor/path/liquid: 64x32 or 128x64 px; wall: 128x128 px).
5. Tangent-space lighting compliance (normal maps Blue channel mean > 128.0).
6. File size efficiency: individual tile files < 60 KB, total asset folder < 10 MB.
7. Adversarial edge cases: corrupt magic, invalid dimensions, inverted normals, oversized files.
é    )Úannotations)ÚPath)ÚListÚSetÚTupleN)ÚImageÚ	ImageStat)Úlist_available_styless   ‰PNG

ÚbytesÚ	PNG_MAGIC)	ú	floor.pngúwall.pngúpath.pngú
liquid.pngú	props.pngúfloor_normal.pngúwall_normal.pngúpath_normal.pngúliquid_normal.pngzTuple[str, ...]ÚREQUIRED_ASSET_FILES)r   r   r   r   ÚNORMAL_MAP_FILES©é@   é    )é€   r   zSet[Tuple[int, int]]ÚVALID_TILE_DIMS)r   r   ÚVALID_WALL_DIMSi ð  ÚintÚMAX_TILE_FILE_SIZE_BYTESi    ÚMAX_TOTAL_FOLDER_SIZE_BYTESÚ	file_pathr   ÚreturnÚboolc                óø   — |                       ¦   «         r|                      ¦   «         j        dk     rdS t          | d¦  «        5 }|                     d¦  «        }ddd¦  «         n# 1 swxY w Y   |t
          k    S )zKVerifies that the file exists, is non-empty, and has valid PNG magic bytes.é   FÚrbN)Úis_fileÚstatÚst_sizeÚopenÚreadr   )r!   ÚfÚheaders      úCC:\Projects\FreeExile\tests\unit\test_map_style_assets_integrity.pyÚverify_png_magic_headerr/   5   s®   € à×ÒÑÔð  )§.¢.Ñ"2Ô"2Ô":¸QÒ">Ð">ØˆuÝ	ˆi˜Ñ	Ô	ð  !Ø—’˜‘”ˆðð ð ñ ô ð ð ð ð ð ð øøøð ð ð ð à•YÒÐs   ÁA&Á&A*Á-A*Úfloatc                ó  — t          j        | ¦  «        5 }t          j        |¦  «        }t	          |j        ¦  «        dk    r&t          |j        d         ¦  «        cddd¦  «         S 	 ddd¦  «         n# 1 swxY w Y   dS )zAComputes the mean intensity of the Blue channel across the image.é   é   Ng        )r   r*   r	   ÚStatÚlenÚmeanr0   )r!   Úimgr(   s      r.   Úcompute_blue_channel_meanr8   >   sÉ   € å	Œ�IÑ	Ô	ð ' #ÝŒ~˜cÑ"Ô"ˆÝˆtŒy‰>Œ>˜QÒÐÝ˜œ 1œÑ&Ô&ð'ð 'ð 'ð 'ñ 'ô 'ð 'ð 'àð'ð 'ð 'ñ 'ô 'ð 'ð 'ð 'ð 'ð 'ð 'øøøð 'ð 'ð 'ð 'ð ˆ3s   •AA5Á5A9Á<A9Úmodule)Úscopec                 ól   — t          t          ¦  «                             ¦   «         j        j        j        S )zReturn repository root path.)r   Ú__file__ÚresolveÚparent© ó    r.   Úproject_rootrA   G   s%   € õ •‰>Œ>×!Ò!Ñ#Ô#Ô*Ô1Ô8Ð8r@   rA   c                ó$   — | dz  dz  dz  dz  dz  S )zBReturn canonical styles directory client/webapp/assets/map/styles.ÚclientÚwebappÚassetsÚmapÚstylesr?   )rA   s    r.   Ústyles_rootrH   M   s#   € ð ˜(Ñ" XÑ-°Ñ8¸5Ñ@À8ÑKÐKr@   ú	List[str]c                 ó|   — t          ¦   «         } t          | ¦  «        dk    sJ dt          | ¦  «        › �¦   «         ‚| S )z$Retrieve all 30 canonical style IDs.é   zExpected 30 styles, got )r
   r5   )rG   s    r.   Úcanonical_stylesrL   S   sB   € õ #Ñ$Ô$€FÝˆv‰;Œ;˜"ÒÐÐÐF½¸V¹¼ÐFÐFÑÔÐØ€Mr@   c                  ó*   — e Zd ZdZdd„Zdd	„Zdd
„ZdS )ÚTestMapStyleDirectoryStructurez@Validates root styles directory and all 30 style subdirectories.rH   r   r"   ÚNonec                óŠ   — |                      ¦   «         sJ d|› �¦   «         ‚|                     ¦   «         sJ d|› �¦   «         ‚dS )z4Root styles directory must exist and be a directory.zStyles root does not exist: z Styles root is not a directory: N)ÚexistsÚis_dir)ÚselfrH   s     r.   Ú!test_styles_root_directory_existsz@TestMapStyleDirectoryStructure.test_styles_root_directory_exists^   sZ   € à×!Ò!Ñ#Ô#ÐQÐQÐ%QÀKÐ%QÐ%QÑQÔQÐ#Ø×!Ò!Ñ#Ô#ÐUÐUÐ%UÈÐ%UÐ%UÑUÔUÐ#ÐUÐUr@   rL   rI   c                óB   ‡— ˆfd„|D ¦   «         }|rJ d|› �¦   «         ‚dS )zAAll 30 canonical styles must have a matching lowercase directory.c                óf   •— g | ]-}‰|                      ¦   «         z                       ¦   «         °+|‘Œ.S r?   )ÚlowerrR   )Ú.0Ús_idrH   s     €r.   ú
<listcomp>zYTestMapStyleDirectoryStructure.test_all_30_style_subdirectories_exist.<locals>.<listcomp>g   sH   ø€ ð 
ð 
ð 
ØØ $§*¢*¡,¤,Ñ.×6Ò6Ñ8Ô8ð
Øð
ð 
ð 
r@   zMissing style subdirectories: Nr?   )rS   rH   rL   Úmissings    `  r.   Ú&test_all_30_style_subdirectories_existzETestMapStyleDirectoryStructure.test_all_30_style_subdirectories_existc   sO   ø€ ð
ð 
ð 
ð 
Ø-ð
ñ 
ô 
ˆð ÐFÐFÐF¸WÐFÐFÑFÔFˆ{ÐFÐFr@   c                ó‚   — d„ |D ¦   «         }d„ |                      ¦   «         D ¦   «         }||z
  }|rJ d|› �¦   «         ‚dS )z=Only the 30 canonical style subdirectories should be present.c                ó6   — h | ]}|                      ¦   «         ’ŒS r?   )rW   )rX   rY   s     r.   ú	<setcomp>z[TestMapStyleDirectoryStructure.test_no_unrecognized_style_subdirectories.<locals>.<setcomp>q   s    € ÐCÐCÐC¨$˜Ÿš™œÐCÐCÐCr@   c                óD   — h | ]}|                      ¦   «         ¯|j        ’ŒS r?   )rR   Úname)rX   Úps     r.   r_   z[TestMapStyleDirectoryStructure.test_no_unrecognized_style_subdirectories.<locals>.<setcomp>r   s7   € ð 
ð 
ð 
Ø°Q·X²X±Z´Zð
ØŒFð
ð 
ð 
r@   z,Unexpected subdirectories in styles folder: N)Úiterdir)rS   rH   rL   Úexpected_dirsÚactual_dirsÚ
unexpecteds         r.   Ú)test_no_unrecognized_style_subdirectorieszHTestMapStyleDirectoryStructure.test_no_unrecognized_style_subdirectoriesm   sq   € ð DÐCÐ2BÐCÑCÔCˆð
ð 
Ø'×/Ò/Ñ1Ô1ð
ñ 
ô 
ˆð ! =Ñ0ˆ
ØÐZÐZÐZÈjÐZÐZÑZÔZˆ~ÐZÐZr@   N©rH   r   r"   rO   )rH   r   rL   rI   r"   rO   )Ú__name__Ú
__module__Ú__qualname__Ú__doc__rT   r\   rg   r?   r@   r.   rN   rN   [   sd   € € € € € ØJÐJðVð Vð Vð Vð
Gð Gð Gð Gð	[ð 	[ð 	[ð 	[ð 	[ð 	[r@   rN   c                  ó   — e Zd ZdZej                             d e¦   «         ¦  «        dd„¦   «         Zej                             d e¦   «         ¦  «        dd	„¦   «         Z	ej                             d e¦   «         ¦  «        dd
„¦   «         Z
dS )Ú$TestMapStyleFileCompletenessAndMagiczGValidates presence and PNG magic headers for all required style assets.Ústyle_idrH   r   Ústrr"   rO   c                óÀ   ‡— ||                      ¦   «         z  Š‰                     ¦   «         sJ d‰› �¦   «         ‚ˆfd„t          D ¦   «         }|rJ |› d|› �¦   «         ‚dS )z;Each style folder must contain the 9 mandatory asset files.zStyle folder not found: c                óB   •— g | ]}‰|z                        ¦   «         °|‘ŒS r?   )r'   )rX   ÚfnameÚ	style_dirs     €r.   rZ   zaTestMapStyleFileCompletenessAndMagic.test_style_contains_all_9_required_files.<locals>.<listcomp>ƒ   s@   ø€ ð 
ð 
ð 
ØØ Ñ%×.Ò.Ñ0Ô0ð
Øð
ð 
ð 
r@   z missing required files: N)rW   rR   r   )rS   rH   ro   Úmissing_filesrt   s       @r.   Ú(test_style_contains_all_9_required_fileszMTestMapStyleFileCompletenessAndMagic.test_style_contains_all_9_required_files|   s”   ø€ ð
   (§.¢.Ñ"2Ô"2Ñ2ˆ	Ø×ÒÑ!Ô!ÐIÐIÐ#I¸iÐ#IÐ#IÑIÔIÐ!ð
ð 
ð 
ð 
Ý3ð
ñ 
ô 
ˆð !ÐWÐW XÐ"WÐ"WÈÐ"WÐ"WÑWÔWÐ ÐWÐWr@   c                ó   — ||                      ¦   «         z  }t          D ]n}||z  }|                     ¦   «         sJ d|› �¦   «         ‚|                     ¦   «         j        dk    sJ d|› �¦   «         ‚t          |¦  «        sJ d|› �¦   «         ‚ŒodS )zEEvery required file must be non-empty and start with PNG magic bytes.zFile does not exist: r   zFile is empty: zInvalid PNG magic in N)rW   r   r'   r(   r)   r/   )rS   rH   ro   rt   rs   Úfpaths         r.   Ú3test_style_files_have_valid_png_magic_and_non_emptyzXTestMapStyleFileCompletenessAndMagic.test_style_files_have_valid_png_magic_and_non_empty‰   s¸   € ð
   (§.¢.Ñ"2Ô"2Ñ2ˆ	Ý)ð 	Sð 	SˆEØ Ñ%ˆEØ—=’=‘?”?ÐCÐCÐ$C¸EÐ$CÐ$CÑCÔC�?Ø—:’:‘<”<Ô'¨!Ò+Ð+Ð+Ð-F¸uÐ-FÐ-FÑ+Ô+Ð+Ý*¨5Ñ1Ô1ÐRÐRÐ3RÈ5Ð3RÐ3RÑRÔRÐ1ÐRð		Sð 	Sr@   c                ó2  — ||                      ¦   «         z  }t          D ]w}||z  }t          j        |¦  «        5 }|j        dk    sJ |› d|j        › d�¦   «         ‚|j        dk    r|j        dk    sJ d|› �¦   «         ‚	 ddd¦  «         n# 1 swxY w Y   ŒxdS )z@PIL must successfully decode every required file as a PNG image.ÚPNGz format is z, expected PNGr   zInvalid dimensions for N)rW   r   r   r*   ÚformatÚwidthÚheight)rS   rH   ro   rt   rs   rx   r7   s          r.   Ú%test_style_files_are_decodable_by_pilzJTestMapStyleFileCompletenessAndMagic.test_style_files_are_decodable_by_pil•   s  € ð
   (§.¢.Ñ"2Ô"2Ñ2ˆ	Ý)ð 	[ð 	[ˆEØ Ñ%ˆEÝ”˜EÑ"Ô"ð [ cØ”z UÒ*Ð*Ð*¨uÐ,[Ð,[ÀÄÐ,[Ð,[Ð,[Ñ*Ô*Ð*Ø”y 1’}�}¨¬°aª¨¨Ð9ZÐSXÐ9ZÐ9Z©¬Ð7¨ð[ð [ð [ñ [ô [ð [ð [ð [ð [ð [ð [øøøð [ð [ð [ð [øð	[ð 	[s   ºABÂB	ÂB	N©rH   r   ro   rp   r"   rO   )ri   rj   rk   rl   ÚpytestÚmarkÚparametrizer
   rv   ry   r   r?   r@   r.   rn   rn   y   sà   € € € € € ØQÐQà„[×Ò˜ZÐ)>Ð)>Ñ)@Ô)@ÑAÔAð
Xð 
Xð 
Xñ BÔAð
Xð „[×Ò˜ZÐ)>Ð)>Ñ)@Ô)@ÑAÔAð	Sð 	Sð 	Sñ BÔAð	Sð „[×Ò˜ZÐ)>Ð)>Ñ)@Ô)@ÑAÔAð	[ð 	[ð 	[ñ BÔAð	[ð 	[ð 	[r@   rn   c                  ó   — e Zd ZdZej                             d e¦   «         ¦  «        dd„¦   «         Zej                             d e¦   «         ¦  «        dd	„¦   «         Z	ej                             d e¦   «         ¦  «        dd
„¦   «         Z
dS )ÚTestMapStyleDimensionszFValidates isometric and wall dimension contracts across all 30 styles.ro   rH   r   rp   r"   rO   c           
     ó  — ||                      ¦   «         z  }d}|D ]e}||z  }t          j        |¦  «        5 }|j        |j        f}|t
          v sJ |› d|› d|› dt
          › �¦   «         ‚	 ddd¦  «         n# 1 swxY w Y   ŒfdS )z@Floor, path, and liquid tiles must be either 64x32 or 128x64 px.)r   r   r   r   r   r   ú/ú dimensions ú not in N)rW   r   r*   r}   r~   r   )	rS   rH   ro   rt   Ú
tile_filesrs   rx   r7   Údimss	            r.   Útest_isometric_tile_dimensionsz5TestMapStyleDimensions.test_isometric_tile_dimensions¥   sò   € ð
   (§.¢.Ñ"2Ô"2Ñ2ˆ	ð
ˆ
ð  ð 	ð 	ˆEØ Ñ%ˆEÝ”˜EÑ"Ô"ð  cØœ	 3¤:Ð.�Ø�Ð.Ð.Ð.ØÐTÐT %ÐTÐT°TÐTÐTÅ?ÐTÐTñ /Ô.Ð.Ð.ðð ð ñ ô ð ð ð ð ð ð øøøð ð ð ð øð	ð 	s   ·2A6Á6A:	Á=A:	c           
     ó  — ||                      ¦   «         z  }dD ]e}||z  }t          j        |¦  «        5 }|j        |j        f}|t
          v sJ |› d|› d|› dt
          › �¦   «         ‚	 ddd¦  «         n# 1 swxY w Y   ŒfdS )zFWall albedo and normal maps must be 128x128 px for vertical extrusion.)r   r   r‡   rˆ   r‰   N)rW   r   r*   r}   r~   r   )rS   rH   ro   rt   rs   rx   r7   r‹   s           r.   Útest_wall_tile_dimensionsz0TestMapStyleDimensions.test_wall_tile_dimensions·   sé   € ð
   (§.¢.Ñ"2Ô"2Ñ2ˆ	Ø4ð 	ð 	ˆEØ Ñ%ˆEÝ”˜EÑ"Ô"ð  cØœ	 3¤:Ð.�Ø�Ð.Ð.Ð.ØÐTÐT %ÐTÐT°TÐTÐTÅ?ÐTÐTñ /Ô.Ð.Ð.ðð ð ñ ô ð ð ð ð ð ð øøøð ð ð ð øð	ð 	s   µ2A4Á4A8	Á;A8	c                ó  — ||                      ¦   «         z  }|dz  }t          j        |¦  «        5 }|j        dk    sJ |› d|j        › d�¦   «         ‚|j        dk    sJ |› d|j        › d�¦   «         ‚	 ddd¦  «         dS # 1 swxY w Y   dS )	z;Props sheet must be a non-empty image with width >= height.r   r   z/props.png width z < 64r   z/props.png height z < 32N)rW   r   r*   r}   r~   )rS   rH   ro   rt   Ú
props_pathr7   s         r.   Útest_props_sheet_dimensionsz2TestMapStyleDimensions.test_props_sheet_dimensionsÅ   sÿ   € ð
   (§.¢.Ñ"2Ô"2Ñ2ˆ	Ø Ñ,ˆ
ÝŒZ˜
Ñ#Ô#ð 	V sØ”9 ’?�?�? xÐ$RÐ$RÀ#Ä)Ð$RÐ$RÐ$R‘?”?�?Ø”: Ò#Ð#Ð#¨Ð%UÐ%UÀCÄJÐ%UÐ%UÐ%UÑ#Ô#Ð#Ð#ð	Vð 	Vð 	Vñ 	Vô 	Vð 	Vð 	Vð 	Vð 	Vð 	Vð 	Vð 	Vøøøð 	Vð 	Vð 	Vð 	Vð 	Vð 	Vs   ±AB Â BÂBNr€   )ri   rj   rk   rl   r�   r‚   rƒ   r
   rŒ   rŽ   r‘   r?   r@   r.   r…   r…   ¢   sØ   € € € € € ØPÐPà„[×Ò˜ZÐ)>Ð)>Ñ)@Ô)@ÑAÔAðð ð ñ BÔAðð" „[×Ò˜ZÐ)>Ð)>Ñ)@Ô)@ÑAÔAðð ð ñ BÔAðð „[×Ò˜ZÐ)>Ð)>Ñ)@Ô)@ÑAÔAðVð Vð Vñ BÔAðVð Vð Vr@   r…   c                  ól   — e Zd ZdZej                             d e¦   «         ¦  «        d
d„¦   «         Zd	S )Ú"TestMapStyleNormalMapsTangentSpacezEValidates tangent-space normal maps Blue channel dominance (> 128.0).ro   rH   r   rp   r"   rO   c                ó¤   — ||                      ¦   «         z  }t          D ]0}||z  }t          |¦  «        }|dk    sJ |› d|› d|d›d�¦   «         ‚Œ1dS )zCNormal maps must have Blue channel mean > 128 for lighting shaders.ç      `@r‡   z B-channel mean ú.2fz	 <= 128.0N)rW   r   r8   )rS   rH   ro   rt   rs   rx   Úb_means          r.   Ú'test_normal_maps_blue_channel_dominancezJTestMapStyleNormalMapsTangentSpace.test_normal_maps_blue_channel_dominanceÔ   s}   € ð
   (§.¢.Ñ"2Ô"2Ñ2ˆ	Ý%ð 	ð 	ˆEØ Ñ%ˆEÝ.¨uÑ5Ô5ˆFØ˜E’>�>�>ØÐJÐJ˜eÐJÐJ°VÐJÐJÐJÐJñ "”>�>�>ð	ð 	r@   Nr€   )	ri   rj   rk   rl   r�   r‚   rƒ   r
   r˜   r?   r@   r.   r“   r“   Ñ   sV   € € € € € ØOÐOà„[×Ò˜ZÐ)>Ð)>Ñ)@Ô)@ÑAÔAð
ð 
ð 
ñ BÔAð
ð 
ð 
r@   r“   c                  ót   — e Zd ZdZej                             d e¦   «         ¦  «        dd„¦   «         Zdd	„Z	d
S )ÚTestMapStyleFileSizeAndBudgetzCValidates file size budgets for mobile efficiency and fast loading.ro   rH   r   rp   r"   rO   c                óÈ   — ||                      ¦   «         z  }t          D ]B}||z  }|                     ¦   «         j        }|t          k     sJ |› d|› d|dz  d›d�¦   «         ‚ŒCdS )zBIndividual tile textures and normal maps must be strictly < 60 KB.r‡   z size i   z.1fz KB >= 60 KB budgetN)rW   r   r(   r)   r   )rS   rH   ro   rt   rs   rx   Ú
size_bytess          r.   Ú%test_individual_tile_files_under_60kbzCTestMapStyleFileSizeAndBudget.test_individual_tile_files_under_60kbå   sŒ   € ð
   (§.¢.Ñ"2Ô"2Ñ2ˆ	Ý)ð 	ð 	ˆEØ Ñ%ˆEØŸš™œÔ-ˆJØÕ 8Ò8Ð8Ð8ØÐUÐU˜eÐUÐU¨:¸Ñ+<ÐUÐUÐUÐUñ 9Ô8Ð8Ð8ð	ð 	r@   c                ó˜   — t          d„ |                     d¦  «        D ¦   «         ¦  «        }|t          k     sJ d|dz  d›d�¦   «         ‚dS )zCTotal size of all assets under map/styles must be strictly < 10 MB.c              3  óp   K  — | ]1}|                      ¦   «         ¯|                     ¦   «         j        V — Œ2d S )N)r'   r(   r)   )rX   r,   s     r.   ú	<genexpr>zYTestMapStyleFileSizeAndBudget.test_total_assets_folder_size_under_10mb.<locals>.<genexpr>ô   sN   è è € ð 
ð 
Ø!"ÀÇ	Â	ÁÄð
Ø�FŠF‰HŒHÔð
ð 
ð 
ð 
ð 
ð 
r@   Ú*zTotal styles size i   r–   z MB >= 10 MB budgetN)ÚsumÚrglobr    )rS   rH   Ú
total_sizes      r.   Ú(test_total_assets_folder_size_under_10mbzFTestMapStyleFileSizeAndBudget.test_total_assets_folder_size_under_10mbò   ss   € åð 
ð 
Ø&1×&7Ò&7¸Ñ&<Ô&<ð
ñ 
ô 
ñ 
ô 
ˆ
ð Õ7Ò7Ð7Ð7ØT ¨{Ñ!;ÐTÐTÐTÐTñ 8Ô7Ð7Ð7Ð7r@   Nr€   rh   )
ri   rj   rk   rl   r�   r‚   rƒ   r
   r�   r¥   r?   r@   r.   rš   rš   â   sj   € € € € € ØMÐMà„[×Ò˜ZÐ)>Ð)>Ñ)@Ô)@ÑAÔAð
ð 
ð 
ñ BÔAð
ð
ð 
ð 
ð 
ð 
ð 
r@   rš   c                  ó:   — e Zd ZdZdd„Zdd„Zdd„Zdd	„Zdd
„ZdS )Ú(TestMapStyleAssetAdversarialAndEdgeCaseszEAdversarial stress tests for integrity validators and error handling.Útmp_pathr   r"   rO   c                ó\   — |dz  }|                      d¦  «         t          |¦  «        rJ ‚dS )z.Corrupted header bytes must fail verification.zcorrupt.pngs   NOT_A_PNG_FILE_HEADERN©Úwrite_bytesr/   ©rS   r¨   Ú	fake_files      r.   Ú&test_corrupt_png_magic_header_detectedzOTestMapStyleAssetAdversarialAndEdgeCases.test_corrupt_png_magic_header_detectedÿ   s;   € à˜}Ñ,ˆ	Ø×ÒÐ6Ñ7Ô7Ð7Ý*¨9Ñ5Ô5Ð5Ð5Ð5Ð5Ð5r@   c                ó\   — |dz  }|                      d¦  «         t          |¦  «        rJ ‚dS )z5Files with fewer than 8 bytes must fail verification.ztruncated.pngs   ‰PNGNrª   r¬   s      r.   Ú#test_truncated_header_file_detectedzLTestMapStyleAssetAdversarialAndEdgeCases.test_truncated_header_file_detected  s:   € à˜Ñ.ˆ	Ø×Ò˜jÑ)Ô)Ð)Ý*¨9Ñ5Ô5Ð5Ð5Ð5Ð5Ð5r@   c                ó2   — |dz  }t          |¦  «        rJ ‚dS )z7Missing file must safely return False without crashing.z	ghost.pngN)r/   )rS   r¨   Úghosts      r.   Útest_nonexistent_file_detectedzGTestMapStyleAssetAdversarialAndEdgeCases.test_nonexistent_file_detected  s&   € à˜;Ñ&ˆÝ*¨5Ñ1Ô1Ð1Ð1Ð1Ð1Ð1r@   c                ó˜   — |dz  }t          j        ddd¦  «        }|                     |d¬¦  «         t          |¦  «        }|dk    sJ ‚dS )	z9Normal map with Blue channel mean <= 128 must be flagged.zbad_normal.pngÚRGBr   )éÈ   r¶   rK   r{   )r|   r•   N)r   ÚnewÚsaver8   )rS   r¨   Úbad_normr7   r—   s        r.   Ú)test_low_blue_channel_normal_map_detectedzRTestMapStyleAssetAdversarialAndEdgeCases.test_low_blue_channel_normal_map_detected  sT   € àÐ.Ñ.ˆÝŒi˜˜x¨Ñ8Ô8ˆØ�Š� %ˆÑ(Ô(Ð(Ý*¨8Ñ4Ô4ˆØ˜Šˆˆˆˆˆr@   c                ó6   — d}|t           vsJ ‚|t          vsJ ‚dS )zJArbitrary dimension (e.g. 100x100) must not match tile or wall dimensions.)éd   r¼   N)r   r   )rS   Údims     r.   Ú#test_invalid_tile_dimension_flaggedzLTestMapStyleAssetAdversarialAndEdgeCases.test_invalid_tile_dimension_flagged  s/   € àˆØ�/Ð)Ð)Ð)Ð)Ø�/Ð)Ð)Ð)Ð)Ð)Ð)r@   N)r¨   r   r"   rO   )r"   rO   )	ri   rj   rk   rl   r®   r°   r³   rº   r¾   r?   r@   r.   r§   r§   ü   s~   € € € € € ØOÐOð6ð 6ð 6ð 6ð6ð 6ð 6ð 6ð2ð 2ð 2ð 2ð
ð ð ð ð*ð *ð *ð *ð *ð *r@   r§   )r!   r   r"   r#   )r!   r   r"   r0   )r"   r   )rA   r   r"   r   )r"   rI   )#rl   Ú
__future__r   Úpathlibr   Útypingr   r   r   r�   ÚPILr   r	   Úserver.world.map_style_catalogr
   r   Ú__annotations__r   r   r   r   r   r    r/   r8   ÚfixturerA   rH   rL   rN   rn   r…   r“   rš   r§   r?   r@   r.   ú<module>rÆ      só  ððð ð ð #Ð "Ð "Ð "Ð "Ð "à Ð Ð Ð Ð Ð Ø #Ð #Ð #Ð #Ð #Ð #Ð #Ð #Ð #Ð #à €€€Ø  Ð  Ð  Ð  Ð  Ð  Ð  Ð  à @Ð @Ð @Ð @Ð @Ð @à'€	Ð 'Ð 'Ð 'Ñ 'ð
)Ð ð 
ð 
ð 
ñ 
ð%Ð ð ð ð ñ ð *2°9Ð(=€Ð =Ð =Ð =Ñ =Ø)3¨€Ð 4Ð 4Ð 4Ñ 4à )Ð Ð )Ð )Ð )Ñ )Ø#3Ð Ð 3Ð 3Ð 3Ñ 3ðð ð ð ðð ð ð ð €„�hÐÑÔð9ð 9ð 9ñ  Ôð9ð
 €„�hÐÑÔðLð Lð Lñ  ÔðLð
 €„�hÐÑÔðð ð ñ  Ôðð[ð [ð [ð [ð [ñ [ô [ð [ð<&[ð &[ð &[ð &[ð &[ñ &[ô &[ð &[ðR,Vð ,Vð ,Vð ,Vð ,Vñ ,Vô ,Vð ,Vð^ð ð ð ð ñ ô ð ð"
ð 
ð 
ð 
ð 
ñ 
ô 
ð 
ð4 *ð  *ð  *ð  *ð  *ñ  *ô  *ð  *ð  *ð  *r@   