'use strict'; const test = require('node:test'); const assert = require('node:assert/strict'); const { encodeGid, decodeGid } = require('../src/gid'); test('encodeGid: known reference value (0,12,1) = 196', () => { assert.equal(encodeGid(0, 12, 1), 196); }); test('encodeGid: default rotation is 0', () => { assert.equal(encodeGid(0, 12), 192); }); test('encodeGid: zero tuple yields 0', () => { assert.equal(encodeGid(0, 0, 0), 0); }); test('encodeGid: high atlas (255) produces unsigned u32', () => { // 255 << 24 = 0xFF000000 = 4278190080 (must NOT be negative) assert.equal(encodeGid(255, 0, 0), 4278190080); }); test('encodeGid: max tile_id (1048575) fits 20 bits', () => { // tile << 4 = 0xFFFFF0 = 16777200 assert.equal(encodeGid(0, 1048575, 0), 16777200); }); test('encodeGid: throws on out-of-range atlas', () => { assert.throws(() => encodeGid(256, 0, 0), /atlas/); assert.throws(() => encodeGid(-1, 0, 0), /atlas/); }); test('encodeGid: throws on out-of-range tile', () => { assert.throws(() => encodeGid(0, 1048576, 0), /tile/); assert.throws(() => encodeGid(0, -1, 0), /tile/); }); test('encodeGid: throws on out-of-range rotation', () => { assert.throws(() => encodeGid(0, 0, 4), /rotation/); assert.throws(() => encodeGid(0, 0, -1), /rotation/); }); test('encodeGid: throws on non-integer inputs', () => { assert.throws(() => encodeGid(1.5, 0, 0), /atlas/); assert.throws(() => encodeGid(0, '12', 0), /tile/); }); test('decodeGid: empty (0) returns zeros', () => { assert.deepEqual(decodeGid(0), { atlas: 0, tile: 0, rotation: 0 }); }); test('decodeGid: 196 unpacks to (0,12,1)', () => { assert.deepEqual(decodeGid(196), { atlas: 0, tile: 12, rotation: 1 }); }); test('decodeGid: 16777232 from real demo map unpacks to (1,1,0)', () => { // demo_v2.map.json wall layer uses 16777232 = (1<<24)|(1<<4) assert.deepEqual(decodeGid(16777232), { atlas: 1, tile: 1, rotation: 0 }); }); test('decodeGid: high atlas (255,0,0) round-trip', () => { assert.deepEqual(decodeGid(4278190080), { atlas: 255, tile: 0, rotation: 0 }); }); test('decodeGid: throws on non-integer or negative', () => { assert.throws(() => decodeGid(-1), /gid/); assert.throws(() => decodeGid(1.5), /gid/); assert.throws(() => decodeGid(0x100000000), /gid/); // > u32 max }); test('round-trip: 100 random tuples encode→decode losslessly', () => { for (let i = 0; i < 100; i++) { const atlas = Math.floor(Math.random() * 256); const tile = Math.floor(Math.random() * 1048576); const rotation = Math.floor(Math.random() * 4); const gid = encodeGid(atlas, tile, rotation); const decoded = decodeGid(gid); assert.equal(decoded.atlas, atlas, `atlas mismatch for ${gid}`); assert.equal(decoded.tile, tile, `tile mismatch for ${gid}`); assert.equal(decoded.rotation, rotation, `rotation mismatch for ${gid}`); } });