§
    ¸¾j­2  ã                  óD  — 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mZmZmZmZ ddlZddlmZmZmZmZ ddlmZmZ ddlmZmZmZmZm Z m!Z!  ej"        d¬	¦  «        dd„¦   «         Z#dd„Z$ G d„ d¦  «        Z% G d„ d¦  «        Z& G d„ d¦  «        Z'dS )aÕ  
Empirical Adversarial Verification Suite for Milestone M1-2:
Cross-Language Binary Compatibility between Python map_binary_serializer.py
and JavaScript (Node.js) tile_grid_loader.js.

Verifies:
1. All 9 canonical wilderness zones across multiple seeds serialize in Python
   and deserialize in Node.js with 100% byte-for-byte and tile-for-tile fidelity.
2. Buffer truncation at every critical boundary (header, POI, encounter, grid).
3. Header corruption handling (magic bytes, dimensions, biomes).
4. Out-of-bounds getTileAt query edge cases (negative, large, float, NaN).
5. In-place tile mutation via setTileAt (boss gate breach to floor).
6. Performance metrics: serialization/deserialization latency and memory budget.
é    )ÚannotationsN)ÚDictÚAnyÚListÚTuple)ÚTileTypeÚTileCellÚMapGridDataÚEncounterZone)ÚWildernessMapGeneratorÚZONE_DEFAULT_SIZES)Úserialize_map_gridÚdeserialize_map_gridÚHEADER_MAGICÚHEADER_SIZEÚBIOME_TO_CODEÚCODE_TO_BIOMEÚmodule)ÚscopeÚreturnÚboolc                 ó.   — t          j        d¦  «        d uS )NÚnode)ÚshutilÚwhich© ó    úFC:\Projects\FreeExile\tests\unit\test_challenger_m1_2_binary_compat.pyÚnode_availabler   ,   s   € åŒ<˜ÑÔ tÐ+Ð+r   Újs_codeÚstrú subprocess.CompletedProcess[str]c                óD   — d| › d�}t          j        dd|gddd¬¦  «        S )z;Helper to run a Node.js snippet with global.window defined.zƒ
    global.window = {};
    const { TileGridLoader, BIOME_CODES } = require('./client/webapp/js/engine/tile_grid_loader.js');
    z
    r   z-eTzc:\Projects\FreeExile)Úcapture_outputÚtextÚcwd)Ú
subprocessÚrun)r    Úwrappers     r   Úrun_node_evalr*   1   sK   € ðð ðð ð €Gõ
 Œ>Ø	��wÐØØØ$ð	ñ ô ð r   c                  ó�   — e Zd ZdZej                             d e ej	        ¦   «         ¦  «        ¦  «        d	d„¦   «         Z
d
d„ZdS )ÚTestCrossLanguageBinaryFidelityzBVerifies Python serialization -> Node.js deserialization fidelity.Úzone_idr!   r   ÚNonec                ó  — t          j        d¦  «        st          j        d¦  «         t	          j        |¦  «        }|                     d¬¦  «        }t          |¦  «        }||› d�z  }|                     |¦  «         t          |¦  «         
                    dd¦  «        }d|› d	|j        › d
|j        › d|j        d         › d|j        d         › dt          j        |j        ¦  «        › dt#          |j        ¦  «        › dt#          |j        ¦  «        › d�}t)          |¦  «        }	|	j        }
d}|
|k    }|sÊt-          j        d|fd|
|f¦  «        dt1          j        ¦   «         v st-          j        |	¦  «        rt-          j        |	¦  «        ndt-          j        |
¦  «        t-          j        |¦  «        dœz  }t-          j        d|› d|	j        › �¦  «        dz   d|iz  }t=          t-          j        |¦  «        ¦  «        ‚d x}
x}}d S )Nr   úNode.js not availablei90  ©Úseedz.binú\ú/úH
        const fs = require('fs');
        const buf = fs.readFileSync('a
  ');
        const meta = TileGridLoader.loadBinaryMap(buf);
        if (!meta) {
            console.error("loadBinaryMap returned null");
            process.exit(1);
        }
        if (meta.version !== 1) process.exit(2);
        if (window.currentMapWidth !== z;) process.exit(3);
        if (window.currentMapHeight !== z0) process.exit(4);
        if (meta.spawn.x !== r   z || meta.spawn.y !== é   zL) process.exit(5);

        // Check boss gate
        const expectedBoss = a/  ;
        if (expectedBoss) {
            if (!meta.bossGate || meta.bossGate.x !== expectedBoss[0] || meta.bossGate.y !== expectedBoss[1]) process.exit(6);
        } else {
            if (meta.bossGate !== null) process.exit(7);
        }

        // Check POI counts
        if (meta.pois.length !== z>) process.exit(8);
        if (meta.encounterZones.length !== za) process.exit(9);

        // Spot check samples or full tiles
        process.exit(0);
        ©ú==©z2%(py2)s
{%(py2)s = %(py0)s.returncode
} == %(py5)sÚres©Úpy0Úpy2Úpy5zNode verification failed for z: ú
>assert %(py7)sÚpy7) r   r   ÚpytestÚskipr   Úfor_zoneÚgenerater   Úwrite_bytesr!   ÚreplaceÚwidthÚheightÚspawn_pointÚjsonÚdumpsÚ	boss_gateÚlenÚ
poi_pointsÚencounter_zonesr*   Ú
returncodeÚ
@pytest_arÚ_call_reprcompareÚ@py_builtinsÚlocalsÚ_should_repr_global_nameÚ	_safereprÚ_format_assertmsgÚstderrÚAssertionErrorÚ_format_explanation)Úselfr-   Útmp_pathÚgenÚmap_dataÚraw_binÚbin_fileÚbin_path_strr    r:   Ú@py_assert1Ú@py_assert4Ú@py_assert3Ú@py_format6Ú@py_format8s                  r   Ú0test_all_canonical_zones_full_tile_grid_fidelityzPTestCrossLanguageBinaryFidelity.test_all_canonical_zones_full_tile_grid_fidelityC   sk  € õ
 Œ|˜FÑ#Ô#ð 	1ÝŒKÐ/Ñ0Ô0Ð0å$Ô-¨gÑ6Ô6ˆØ—<’< U�<Ñ+Ô+ˆÝ$ XÑ.Ô.ˆà Ð.Ð.Ð.Ñ.ˆØ×Ò˜WÑ%Ô%Ð%Ý˜8‘}”}×,Ò,¨T°3Ñ7Ô7ˆðà&2ðð ð )1¬ðð ð *2¬ðð ð 'Ô2°1Ô5ðð ð MUÔL`ÐabÔLcðð õ #œj¨Ô);Ñ<Ô<ðð õ, #& hÔ&9Ñ":Ô":ð-ð õ. -0°Ô0HÑ,IÔ,Ið/ð ð ˆõ8 ˜GÑ$Ô$ˆØŒ~Ð[ Ð[ˆ~ Ò"Ð[Ð[Ð[Õ[Ô[Ð[Ð[Ð[Ð[ˆ~ Ð[Ñ[Ô[Ð[Õ[Ô[Ñ[Ô[Ð[Ð[Õ[Ô[ˆsÑ[Ô[Ð[Õ[Ô[ˆsÑ[Ô[Ð[Ð[Õ[Ô[ˆ~Ñ[Ô[Õ[Ô[ Ñ[Ô[Ð[Ð[Ñ[Ð[Õ[Ô[Ð$[ÀGÐ$[Ð$[ÈsÌzÐ$[Ð$[Ñ[Ô[Ð[Ñ[Ð[Ð[Ð[Ñ[Ð[Õ[Õ[Ô[Ð[Ñ[Ô[Ñ[Ô[Ð[Ð[Ð[Ð[Ð[Ð[Ð[Ð[Ð[r   c                ó  ‡— t          j        d¦  «        st          j        d¦  «         t	          j        d¦  «        }|                     d¬¦  «        Št          ‰¦  «        }|dz  }|                     |¦  «         t          |¦  «         
                    dd¦  «        }ˆfd	„t          ‰j        ¦  «        D ¦   «         }|d
z  }|                     t          j        |¦  «        ¦  «         t          |¦  «         
                    dd¦  «        }d|› d|› d�}	t!          |	¦  «        }
|
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  }t5          t%          j        |¦  «        ¦  «        ‚dx}x}}dS )zDExhaustively compares all 10,800 tiles in the largest zone (120x90).r   r0   Úzone_boundless_celestial_palaceiç  r1   zmax_zone.binr3   r4   c                óT   •‡— g | ]#Šˆˆfd „t          ‰j        ¦  «        D ¦   «         ‘Œ$S )c                óJ   •— g | ]}‰j         ‰         |         j        j        ‘Œ S r   )ÚtilesÚ	tile_typeÚvalue)Ú.0Úxr^   Úys     €€r   ú
<listcomp>zgTestCrossLanguageBinaryFidelity.test_complete_grid_exhaustive_comparison.<locals>.<listcomp>.<listcomp>‚   s+   ø€ ÐQÐQÐQ°aˆXŒ^˜AÔ˜qÔ!Ô+Ô1ÐQÐQÐQr   )ÚrangerG   )ro   rq   r^   s    @€r   rr   z\TestCrossLanguageBinaryFidelity.test_complete_grid_exhaustive_comparison.<locals>.<listcomp>�   sL   øø€ ð 
ð 
ð 
àð RÐQÐQÐQÐQ½5ÀÄÑ;PÔ;PÐQÑQÔQð
ð 
ð 
r   zexpected_tiles.jsonr5   z›');
        const meta = TileGridLoader.loadBinaryMap(buf);
        if (!meta) process.exit(1);

        const expectedTiles = JSON.parse(fs.readFileSync('aÉ  '));
        let mismatches = 0;
        for (let y = 0; y < window.currentMapHeight; y++) {
            for (let x = 0; x < window.currentMapWidth; x++) {
                const jsTile = TileGridLoader.getTileAt(x, y);
                const pyTile = expectedTiles[y][x];
                if (jsTile !== pyTile) {
                    mismatches++;
                    if (mismatches <= 5) {
                        console.error(`Mismatch at (${x}, ${y}): JS=${jsTile}, PY=${pyTile}`);
                    }
                }
            }
        }
        if (mismatches > 0) {
            console.error(`Total mismatches: ${mismatches}`);
            process.exit(10);
        }
        process.exit(0);
        r   r7   r9   r:   r;   z#Exhaustive tile comparison failed: r?   r@   N)r   r   rA   rB   r   rC   rD   r   rE   r!   rF   rs   rH   Ú
write_textrJ   rK   r*   rP   rQ   rR   rS   rT   rU   rV   rW   rX   rY   rZ   )r[   r\   r]   r_   r`   ra   Úpy_tilesÚtiles_json_fileÚtiles_json_strr    r:   rb   rc   rd   re   rf   r^   s                   @r   Ú(test_complete_grid_exhaustive_comparisonzHTestCrossLanguageBinaryFidelity.test_complete_grid_exhaustive_comparisons   sA  ø€ åŒ|˜FÑ#Ô#ð 	1ÝŒKÐ/Ñ0Ô0Ð0å$Ô-Ð.OÑPÔPˆØ—<’< S�<Ñ)Ô)ˆÝ$ XÑ.Ô.ˆà˜nÑ,ˆØ×Ò˜WÑ%Ô%Ð%Ý˜8‘}”}×,Ò,¨T°3Ñ7Ô7ˆð
ð 
ð 
ð 
å˜8œ?Ñ+Ô+ð
ñ 
ô 
ˆð #Ð%:Ñ:ˆØ×"Ò"¥4¤:¨hÑ#7Ô#7Ñ8Ô8Ð8Ý˜_Ñ-Ô-×5Ò5°d¸CÑ@Ô@ˆðà&2ðð ð <Jðð ð ˆõ4 ˜GÑ$Ô$ˆØŒ~ÐV ÐVˆ~ Ò"ÐVÐVÐVÕVÔVÐVÐVÐVÐVˆ~ ÐVÑVÔVÐVÕVÔVÑVÔVÐVÐVÕVÔVˆsÑVÔVÐVÕVÔVˆsÑVÔVÐVÐVÕVÔVˆ~ÑVÔVÕVÔV ÑVÔVÐVÐVÑVÐVÕVÔVÐ$VÈ#Ì*Ð$VÐ$VÑVÔVÐVÑVÐVÐVÐVÑVÐVÕVÕVÔVÐVÑVÔVÑVÔVÐVÐVÐVÐVÐVÐVÐVÐVÐVr   N)r-   r!   r   r.   ©r   r.   )Ú__name__Ú
__module__Ú__qualname__Ú__doc__rA   ÚmarkÚparametrizeÚlistr   Úkeysrg   rx   r   r   r   r,   r,   @   s‰   € € € € € ØLÐLà„[×ÒØØˆÐ$ÐÔ$Ñ&Ô&Ñ'Ô'ñô ð*\ð *\ð *\ñ	ô ð*\ðX1Wð 1Wð 1Wð 1Wð 1Wð 1Wr   r,   c                  ó2   — e Zd ZdZd	d„Zd	d„Zd	d„Zd	d„ZdS )
ÚTestAdversarialStressCaseszOStress tests buffer truncation, corruption, OOB queries, and in-place mutation.r   r.   c                óø  — t          j        d¦  «        }|                     d¬¦  «        }t          |¦  «        }t	          |¦  «        }ddd|dz
  |dz
  dfD ]J}t          j        t          ¦  «        5  t          |d	|…         ¦  «         d	d	d	¦  «         n# 1 swxY w Y   ŒKt          j
        d
¦  «        st          j        d¦  «         |dz  }|                     |¦  «         t          |¦  «                             dd¦  «        }d|› d�}	t          |	¦  «        }
|
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  }t3          t#          j        |¦  «        ¦  «        ‚d	x}x}}d	S )zETests that truncated buffers are rejected by both Python and Node.js.Úzone_tang_kiem_nhaié*   r1   r   r6   é   é2   é   Nr   r0   z	valid.binr3   r4   r5   a©  ');
        const cuts = [0, 1, 15, buf.length - 1, buf.length - 50, 16];
        for (const cut of cuts) {
            const truncated = buf.subarray(0, cut);
            const res = TileGridLoader.loadBinaryMap(truncated);
            if (res !== null) {
                console.error(`Failed to reject truncation at ${cut} bytes`);
                process.exit(1);
            }
        }
        process.exit(0);
        r7   r9   r:   r;   zNode failed truncation tests: r?   r@   )r   rC   rD   r   rM   rA   ÚraisesÚ
ValueErrorr   r   r   rB   rE   r!   rF   r*   rP   rQ   rR   rS   rT   rU   rV   rW   rX   rY   rZ   )r[   r\   r]   r^   Ú	valid_bufÚ	total_lenÚcutr`   ra   r    r:   rb   rc   rd   re   rf   s                   r   Ú test_buffer_truncation_detectionz;TestAdversarialStressCases.test_buffer_truncation_detectionª   se  € å$Ô-Ð.CÑDÔDˆØ—<’< R�<Ñ(Ô(ˆÝ& xÑ0Ô0ˆ	Ý˜	‘N”Nˆ	ð �q˜"˜i¨!™m¨Y¸©^¸RÐ@ð 	6ð 	6ˆCÝ”�zÑ*Ô*ð 6ð 6Ý$ Y¨t°¨t¤_Ñ5Ô5Ð5ð6ð 6ð 6ñ 6ô 6ð 6ð 6ð 6ð 6ð 6ð 6øøøð 6ð 6ð 6ð 6øõ Œ|˜FÑ#Ô#ð 	1ÝŒKÐ/Ñ0Ô0Ð0à˜kÑ)ˆØ×Ò˜YÑ'Ô'Ð'Ý˜8‘}”}×,Ò,¨T°3Ñ7Ô7ˆðà&2ðð ð ˆõ ˜GÑ$Ô$ˆØŒ~ÐQ ÐQˆ~ Ò"ÐQÐQÐQÕQÔQÐQÐQÐQÐQˆ~ ÐQÑQÔQÐQÕQÔQÑQÔQÐQÐQÕQÔQˆsÑQÔQÐQÕQÔQˆsÑQÔQÐQÐQÕQÔQˆ~ÑQÔQÕQÔQ ÑQÔQÐQÐQÑQÐQÕQÔQÐ$QÀSÄZÐ$QÐ$QÑQÔQÐQÑQÐQÐQÐQÑQÐQÕQÕQÔQÐQÑQÔQÑQÔQÐQÐQÐQÐQÐQÐQÐQÐQÐQs   Á2BÂB	ÂB	c                óÖ  — t          j        d¦  «        }|                     d¬¦  «        }t          t	          |¦  «        ¦  «        }t          |¦  «        }t          d¦  «        |d<   t          d¦  «        |d<   t          j        t          d¬¦  «        5  t          t          |¦  «        ¦  «         d	d	d	¦  «         n# 1 swxY w Y   t          j        d
¦  «        st          j        d¦  «         dt          |¦  «        › d�}t          |¦  «        }|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¦  «        dz   d|
iz  }t1          t#          j        |¦  «        ¦  «        ‚d	x}x}	}d	S )z0Verifies corruption of magic header is rejected.r…   éM   r1   ÚXr   r6   zInvalid map magic)ÚmatchNr   r0   z!
        const buf = Buffer.from(z†);
        const res = TileGridLoader.loadBinaryMap(buf);
        if (res !== null) process.exit(1);
        process.exit(0);
        r7   r9   r:   r;   z%Node failed to reject corrupted magicr?   r@   )r   rC   rD   Ú	bytearrayr   ÚordrA   rŠ   r‹   r   Úbytesr   r   rB   r€   r*   rP   rQ   rR   rS   rT   rU   rV   rW   rY   rZ   )r[   r]   r^   rŒ   Ú	corruptedr    r:   rb   rc   rd   re   rf   s               r   Ú%test_corrupted_magic_header_rejectionz@TestAdversarialStressCases.test_corrupted_magic_header_rejectionÏ   s4  € å$Ô-Ð.CÑDÔDˆØ—<’< R�<Ñ(Ô(ˆÝÕ0°Ñ:Ô:Ñ;Ô;ˆ	õ ˜iÑ(Ô(ˆ	Ý˜3‘x”xˆ	�!‰Ý˜3‘x”xˆ	�!‰õ Œ]�:Ð-@ÐAÑAÔAð 	3ð 	3Ý ¥ yÑ!1Ô!1Ñ2Ô2Ð2ð	3ð 	3ð 	3ñ 	3ô 	3ð 	3ð 	3ð 	3ð 	3ð 	3ð 	3øøøð 	3ð 	3ð 	3ð 	3õ Œ|˜FÑ#Ô#ð 	1ÝŒKÐ/Ñ0Ô0Ð0ðÝ!% i¡¤ðð ð ˆõ ˜GÑ$Ô$ˆØŒ~ÐK ÐKˆ~ Ò"ÐKÐKÐKÕKÔKÐKÐKÐKÐKˆ~ ÐKÑKÔKÐKÕKÔKÑKÔKÐKÐKÕKÔKˆsÑKÔKÐKÕKÔKˆsÑKÔKÐKÐKÕKÔKˆ~ÑKÔKÕKÔK ÑKÔKÐKÐKÑKÐKÕKÔKÐ$KÑKÔKÐKÑKÐKÐKÐKÑKÐKÕKÕKÔKÐKÑKÔKÑKÔKÐKÐKÐKÐKÐKÐKÐKÐKÐKs   ÂB>Â>CÃCc                ó¶  — t          j        d¦  «        st          j        d¦  «         t	          j        d¦  «        }|                     d¬¦  «        }|j        }d}||u}|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  }dd|iz  }t          t          j        |¦  «        ¦  «        ‚dx}x}}|j        \  }	}
|dz  }|                     t#          |¦  «        ¦  «         t%          |¦  «                             dd¦  «        }d|› d�}t)          |¦  «        }|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}}dS )zHVerifies in-place mutation of BOSS_GATE (10) to FLOOR (1) via setTileAt.r   r0   r…   ix  r1   N)úis not)z5%(py2)s
{%(py2)s = %(py0)s.boss_gate
} is not %(py5)sr^   r;   zassert %(py7)sr@   zboss_gate_test.binr3   r4   r5   a  ');
        const meta = TileGridLoader.loadBinaryMap(buf);
        if (!meta || !meta.bossGate) process.exit(1);

        const bx = meta.bossGate.x;
        const by = meta.bossGate.y;

        // Verify initial state is BOSS_GATE (10)
        const initialTile = TileGridLoader.getTileAt(bx, by);
        if (initialTile !== 10) {
            console.error(`Initial tile at (${bx}, ${by}) is ${initialTile}, expected 10`);
            process.exit(2);
        }

        // Mutate to FLOOR (1)
        const mutateOk = TileGridLoader.setTileAt(bx, by, 1);
        if (!mutateOk) process.exit(3);

        // Verify lookup immediately reflects FLOOR (1)
        const updatedTile = TileGridLoader.getTileAt(bx, by);
        if (updatedTile !== 1) process.exit(4);

        // Verify out-of-bounds mutation returns false
        if (TileGridLoader.setTileAt(-1, 0, 1) !== false) process.exit(5);
        if (TileGridLoader.setTileAt(window.currentMapWidth + 10, 0, 1) !== false) process.exit(6);

        process.exit(0);
        r   r7   r9   r:   z$Node in-place mutation test failed: r?   )r   r   rA   rB   r   rC   rD   rL   rQ   rR   rS   rT   rU   rV   rY   rZ   rE   r   r!   rF   r*   rP   rW   rX   )r[   r\   r]   r^   rb   rc   rd   re   rf   Úbg_xÚbg_yr`   ra   r    r:   s                  r   Ú test_in_place_boss_gate_mutationz;TestAdversarialStressCases.test_in_place_boss_gate_mutationë   s   € åŒ|˜FÑ#Ô#ð 	1ÝŒKÐ/Ñ0Ô0Ð0å$Ô-Ð.CÑDÔDˆØ—<’< S�<Ñ)Ô)ˆØÔ!Ð-¨Ð-Ð!¨Ð-Ð-Ð-Ð-Õ-Ô-Ð-Ð-Ð-Ð-Ð!¨Ð-Ñ-Ô-Ð-Õ-Ô-Ñ-Ô-Ð-Ð-Õ-Ô-ˆxÑ-Ô-Ð-Õ-Ô-ˆxÑ-Ô-Ð-Ð-Õ-Ô-Ð!Ñ-Ô-Õ-Ô-¨Ñ-Ô-Ð-Ð-Ñ-Ð-Ð-Ð-Ð-Ð-Ñ-Ð-Õ-Õ-Ô-Ð-Ñ-Ô-Ñ-Ô-Ð-Ð-Ð-Ð-Ð-Ð-Ð-ØÔ'‰
ˆˆdàÐ2Ñ2ˆØ×ÒÕ/°Ñ9Ô9Ñ:Ô:Ð:Ý˜8‘}”}×,Ò,¨T°3Ñ7Ô7ˆðà&2ðð ð ˆõ< ˜GÑ$Ô$ˆØŒ~ÐW ÐWˆ~ Ò"ÐWÐWÐWÕWÔWÐWÐWÐWÐWˆ~ ÐWÑWÔWÐWÕWÔWÑWÔWÐWÐWÕWÔWˆsÑWÔWÐWÕWÔWˆsÑWÔWÐWÐWÕWÔWˆ~ÑWÔWÕWÔW ÑWÔWÐWÐWÑWÐWÕWÔWÐ$WÈ3Ì:Ð$WÐ$WÑWÔWÐWÑWÐWÐWÐWÑWÐWÕWÕWÔWÐWÑWÔWÑWÔWÐWÐWÐWÐWÐWÐWÐWÐWÐWr   c                ó4  — t          j        d¦  «        st          j        d¦  «         d}t	          |¦  «        }|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}}dS )zMVerifies getTileAt returns 2 (WALL) for negative and beyond-boundary queries.r   r0   a‹  
        TileGridLoader.loadFallbackGrid(60, 45, 1);
        if (TileGridLoader.getTileAt(-1, 0) !== 2) process.exit(1);
        if (TileGridLoader.getTileAt(0, -1) !== 2) process.exit(2);
        if (TileGridLoader.getTileAt(60, 0) !== 2) process.exit(3);
        if (TileGridLoader.getTileAt(0, 45) !== 2) process.exit(4);
        if (TileGridLoader.getTileAt(-1e6, -1e6) !== 2) process.exit(5);
        if (TileGridLoader.getTileAt(1e6, 1e6) !== 2) process.exit(6);
        if (TileGridLoader.getTileAt(Infinity, 0) !== 2) process.exit(7);
        if (TileGridLoader.getTileAt(-Infinity, 0) !== 2) process.exit(8);
        process.exit(0);
        r   r7   r9   r:   r;   zNode OOB queries failed: r?   r@   N)r   r   rA   rB   r*   rP   rQ   rR   rS   rT   rU   rV   rW   rX   rY   rZ   )r[   r    r:   rb   rc   rd   re   rf   s           r   Útest_out_of_bounds_queriesz5TestAdversarialStressCases.test_out_of_bounds_queries  s:  € åŒ|˜FÑ#Ô#ð 	1ÝŒKÐ/Ñ0Ô0Ð0ðˆõ ˜GÑ$Ô$ˆØŒ~ÐL ÐLˆ~ Ò"ÐLÐLÐLÕLÔLÐLÐLÐLÐLˆ~ ÐLÑLÔLÐLÕLÔLÑLÔLÐLÐLÕLÔLˆsÑLÔLÐLÕLÔLˆsÑLÔLÐLÐLÕLÔLˆ~ÑLÔLÕLÔL ÑLÔLÐLÐLÑLÐLÕLÔLÐ$LÀÄ
Ð$LÐ$LÑLÔLÐLÑLÐLÐLÐLÑLÐLÕLÕLÔLÐLÑLÔLÑLÔLÐLÐLÐLÐLÐLÐLÐLÐLÐLr   Nry   )rz   r{   r|   r}   r�   r˜   r�   rŸ   r   r   r   rƒ   rƒ   §   s~   € € € € € ØYÐYð#Rð #Rð #Rð #RðJLð Lð Lð Lð8-Xð -Xð -Xð -Xð^Mð Mð Mð Mð Mð Mr   rƒ   c                  ó   — e Zd ZdZdd„ZdS )ÚTestPerformanceMetricsz*Measures decode latency and RAM footprint.r   r.   c                óÐ  — t          j        d¦  «        }|                     d¬¦  «        }d}t          j        ¦   «         }t          |¦  «        D ]}t          |¦  «        }Œt          j        ¦   «         }||z
  |z  dz  }t          j        ¦   «         }t          |¦  «        D ]}t          |¦  «        }Œt          j        ¦   «         }||z
  |z  dz  }	t          d|d›d�¦  «         t          d	|	d›d�¦  «         t          d
t          |¦  «        › dt          |¦  «        dz  d›d�¦  «         d}
||
k     }|s¬t          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}}
d}
|	|
k     }|s¬t          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          |¦  «        }
d}d}||z  }|
|k     }|�st          j        d|fd|
|f¦  «        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        |
¦  «        t          j        |¦  «        t          j        |¦  «        dœz  }t          j        d ¦  «        d!z   d"|iz  }t#          t          j        |¦  «        ¦  «        ‚dx}
x}x}x}}dS )#z;Benchmarks Python serialization and deserialization speeds.ri   i+  r1   iô  iè  z&
[BENCHMARK] Python Serialize 120x90: z.3fz ms/opz'[BENCHMARK] Python Deserialize 120x90: z![BENCHMARK] Binary payload size: z bytes (i   z.2fz KB)g      .@)ú<)z%(py0)s < %(py3)sÚ	py_ser_ms)r<   Úpy3zSerialization must be < 15msz
>assert %(py5)sr>   Ng     ÀR@Úpy_deser_msz%Python deserialization must be < 75mséd   )z;%(py3)s
{%(py3)s = %(py0)s(%(py1)s)
} < (%(py6)s * %(py8)s)rM   Úb)r<   Úpy1r¥   Úpy6Úpy8zPayload must be < 100 KBz
>assert %(py11)sÚpy11)r   rC   rD   ÚtimeÚperf_counterrs   r   r   ÚprintrM   rQ   rR   rS   rT   rU   rV   rW   rY   rZ   )r[   r]   r^   ÚitersÚt0Ú_r¨   Út1r¤   r¦   Ú@py_assert2rb   Ú@py_format4re   Ú@py_assert5Ú@py_assert7Ú@py_assert9rc   Ú@py_format10Ú@py_format12s                       r   Útest_benchmark_metricsz-TestPerformanceMetrics.test_benchmark_metrics2  sI  € å$Ô-Ð.OÑPÔPˆØ—<’< S�<Ñ)Ô)ˆð ˆÝÔÑ Ô ˆÝ�u‘”ð 	-ð 	-ˆAÝ" 8Ñ,Ô,ˆAˆAÝÔÑ Ô ˆØ˜2‘g Ñ&¨$Ñ.ˆ	õ ÔÑ Ô ˆÝ�u‘”ð 	(ð 	(ˆAÝ$ QÑ'Ô'ˆAˆAÝÔÑ Ô ˆØ˜R™ 5Ñ(¨DÑ0ˆåÐM¸	ÐMÐMÐMÐMÑNÔNÐNÝÐO¸ÐOÐOÐOÐOÑPÔPÐPÝÐWµ#°a±&´&ÐWÐWÅ#ÀaÁ&Ä&ÈÁ+ÐWÐWÐWÐWÑXÔXÐXàÐ?ˆy˜4ÒÐ?Ð?Ð?Õ?Ô?Ð?Ð?Ð?Ð?ˆy˜4Ð?Ñ?Ô?Ð?Õ?Ô?Ñ?Ô?Ð?Ð?Õ?Ô?ˆyÑ?Ô?Ð?Õ?Ô?ˆyÑ?Ô?Ð?Ð?Õ?Ô?˜4Ñ?Ô?Ð?Ð?Ñ?Ð?Õ?Ô?Ð!?Ñ?Ô?Ð?Ñ?Ð?Ð?Ð?Ñ?Ð?Õ?Õ?Ô?Ð?Ñ?Ô?Ñ?Ô?Ð?Ð?Ð?Ð?Ð?ð "ÐJˆ{˜TÒ!ÐJÐJÐJÕJÔJÐJÐJÐJÐJˆ{˜TÐJÑJÔJÐJÕJÔJÑJÔJÐJÐJÕJÔJˆ{ÑJÔJÐJÕJÔJˆ{ÑJÔJÐJÐJÕJÔJ˜TÑJÔJÐJÐJÑJÐJÕJÔJÐ#JÑJÔJÐJÑJÐJÐJÐJÑJÐJÕJÕJÔJÐJÑJÔJÑJÔJÐJÐJÐJÐJÐJÝ�1‰vŒvÐ>˜Ð>˜dÐ>˜˜d™
Ð>ˆv˜
Ò"Ð>Ð>Ñ>Õ>Ô>Ð>Ð>Ð>Ð>ˆv˜
Ð>Ñ>Ô>Ð>Õ>Ô>Ñ>Ô>Ð>Ð>Õ>Ô>�sÑ>Ô>Ð>Õ>Ô>�sÑ>Ô>Ð>Ð>Ð>Õ>Ô>Ñ>Ô>Ð>Ð>Õ>Ô>�1Ñ>Ô>Ð>Õ>Ô>�1Ñ>Ô>Ð>Ð>Õ>Ô>ˆvÑ>Ô>Õ>Ô>˜Ñ>Ô>Õ>Ô>˜dÑ>Ô>Ð>Ð>Ñ>Ð>Õ>Ô>Ð$>Ñ>Ô>Ð>Ñ>Ð>Ð>Ð>Ñ>Ð>Õ>Õ>Ô>Ð>Ñ>Ô>Ñ>Ô>Ð>Ð>Ð>Ð>Ð>Ð>Ð>Ð>Ð>Ð>Ð>Ð>Ð>r   Nry   )rz   r{   r|   r}   r»   r   r   r   r¡   r¡   /  s.   € € € € € Ø4Ð4ð?ð ?ð ?ð ?ð ?ð ?r   r¡   )r   r   )r    r!   r   r"   )(r}   Ú
__future__r   ÚbuiltinsrS   Ú_pytest.assertion.rewriteÚ	assertionÚrewriterQ   rJ   r   r'   r­   Útypingr   r   r   r   rA   Úserver.world.map_data_typesr   r	   r
   r   Ú%server.world.wilderness_map_generatorr   r   Ú"server.world.map_binary_serializerr   r   r   r   r   r   Úfixturer   r*   r,   rƒ   r¡   r   r   r   ú<module>rÆ      s-  ððð ð #Ð "Ð "Ð "Ð "Ð "Ø  € € € € € € € € € € € € €€€€Ø €€€Ø Ð Ð Ð Ø €€€Ø )Ð )Ð )Ð )Ð )Ð )Ð )Ð )Ð )Ð )Ð )Ð )Ø €€€ðð ð ð ð ð ð ð ð ð ð ð ðð ð ð ð ð ð ð ðð ð ð ð ð ð ð ð ð ð ð ð ð ð ð ð €„�hÐÑÔð,ð ,ð ,ñ  Ôð,ðð ð ð ðdWð dWð dWð dWð dWñ dWô dWð dWðNEMð EMð EMð EMð EMñ EMô EMð EMðP?ð ?ð ?ð ?ð ?ñ ?ô ?ð ?ð ?ð ?r   