Check imported world size, buffers, materials and block codes (t80)
This commit is contained in:
@@ -1,8 +1,56 @@
|
||||
// Reload wakes nearby areas first, without losing distant water, fire or saved state.
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const { load, suite, flatWorld, rect, count, ticks } = require('./harness');
|
||||
const { run } = load();
|
||||
const { check, done } = suite();
|
||||
|
||||
// Exercise the real hover function headlessly, without starting a browser or GPU.
|
||||
run("const localStorage = { getItem: () => '{}', setItem() {} };");
|
||||
for (const f of ['ui/state.js', 'ui/hud.js', 'ui/cursor.js', 'ui/info.js'])
|
||||
run(fs.readFileSync(path.join(__dirname, '../src', f), 'utf8'));
|
||||
flatWorld(run, 256, 256, 200);
|
||||
run('globalThis.validationSave = serializeWorld();');
|
||||
function refusedBeforeAlloc(label, doctor, message) {
|
||||
check(label, run(`(() => {
|
||||
const s = { meta: { ...validationSave.meta, cols: { ...validationSave.meta.cols } }, buffers: { ...validationSave.buffers } };
|
||||
${doctor}
|
||||
const originalAlloc = alloc, originalMat = mat, originalBlocks = blockP;
|
||||
const oldW = W, oldH = H, oldMoney = money, oldX = bot.x;
|
||||
let allocations = 0, error;
|
||||
alloc = () => { allocations++; throw new Error('Allocation reached'); };
|
||||
try { deserializeWorld(s.meta, s.buffers); } catch (e) { error = e; }
|
||||
finally { alloc = originalAlloc; }
|
||||
return error instanceof Error && ${message}.test(error.message) && allocations === 0
|
||||
&& W === oldW && H === oldH && mat === originalMat && blockP === originalBlocks
|
||||
&& money === oldMoney && bot.x === oldX;
|
||||
})()`));
|
||||
}
|
||||
for (const [w, h] of [[1000000, 1000000], [6145, 1024], [2048, 2049], [0, 1024], [2048, -1], [2048.5, 1024], [2048, NaN]])
|
||||
refusedBeforeAlloc(`invalid size ${w} x ${h} is refused before touching the world`, `s.meta.W = ${w}; s.meta.H = ${h};`, '/world size/i');
|
||||
for (const key of ['mat', 'temp', 'life', 'flags', 'part', 'blockP', 'blockV', 'bgm', 'fog']) {
|
||||
refusedBeforeAlloc(`short ${key} buffer is refused before touching the world`, `s.buffers.${key} = s.buffers.${key}.subarray(1);`, `/${key}/i`);
|
||||
refusedBeforeAlloc(`long ${key} buffer is refused before touching the world`, `s.buffers.${key} = new s.buffers.${key}.constructor(s.buffers.${key}.length + 1);`, `/${key}/i`);
|
||||
}
|
||||
for (const key of ['mat', 'temp', 'life', 'flags', 'part', 'blockP', 'blockV'])
|
||||
refusedBeforeAlloc(`missing ${key} buffer is refused before touching the world`, `delete s.buffers.${key};`, `/${key}/i`);
|
||||
for (const key of ['surfY', 'dirtY', 'graniteY', 'basaltY', 'magmaY'])
|
||||
refusedBeforeAlloc(`short ${key} column is refused before touching the world`, `s.meta.cols.${key} = [];`, `/${key}/i`);
|
||||
refusedBeforeAlloc('short slope phases are refused before touching the world', 's.meta.slopePhases = [0];', '/slopePhases/i');
|
||||
for (const [label, doctor, clean] of [
|
||||
['unknown cell material', 's.buffers.mat[20 * W + 20] = 250;', 'mat[20 * W + 20] === EMPTY'],
|
||||
['unknown block code', 's.buffers.blockP[5 * BW + 5] = 250;', 'blockP[5 * BW + 5] === 0'],
|
||||
]) {
|
||||
check(label + ' loads cleaned and permits hover and removal', run(`(() => {
|
||||
const s = serializeWorld(); ${doctor}
|
||||
try {
|
||||
deserializeWorld(s.meta, s.buffers);
|
||||
SET.fog = false; player.lens = false;
|
||||
return ${clean} && hoverInfo(20, 20).air && removePieceAt(20, 20) === '';
|
||||
} catch (e) { return false; }
|
||||
})()`));
|
||||
}
|
||||
|
||||
flatWorld(run, 1024, 256, 200);
|
||||
run(`
|
||||
bot.x = 510; bot.y = 170;
|
||||
|
||||
Reference in New Issue
Block a user