|
|
|
@@ -2,7 +2,7 @@ const test = require('node:test'), assert = require('node:assert/strict');
|
|
|
|
|
const fs = require('node:fs'), vm = require('node:vm');
|
|
|
|
|
const source = fs.readFileSync('build-templates/wechatgame/memory-diagnostics.js', 'utf8');
|
|
|
|
|
const ROOT = '/user/memory-diagnostics/';
|
|
|
|
|
function fixture(files = new Map(), envVersion = 'trial', now = 1800000000000, initiallyFull = false) {
|
|
|
|
|
function fixture(files = new Map(), envVersion = 'trial', now = 1800000000000, initiallyFull = false, enabled = true) {
|
|
|
|
|
const handlers = {}, timers = [], modals = [], sheets = [], calls = [], logins = [], requests = [], timeouts = new Map();
|
|
|
|
|
let timeoutId = 0;
|
|
|
|
|
let failWrite = initiallyFull;
|
|
|
|
@@ -30,7 +30,7 @@ function fixture(files = new Map(), envVersion = 'trial', now = 1800000000000, i
|
|
|
|
|
const module = { exports: {} };
|
|
|
|
|
vm.runInNewContext(source, { module, Date: Clock, setInterval: fn => { timers.push(fn); return timers.length; }, clearInterval: id => { timers[id - 1] = null; },
|
|
|
|
|
setTimeout: fn => { timeouts.set(++timeoutId, fn); return timeoutId; }, clearTimeout: id => timeouts.delete(id) });
|
|
|
|
|
const api = module.exports.create(wx, { id: 'build-123', builtAt: '2026-10-26', flags: { iOSHighPerformance: true, 'iOSHighPerformance+': true } });
|
|
|
|
|
const api = module.exports.create(wx, { id: 'build-123', builtAt: '2026-10-26', flags: { iOSHighPerformance: true, 'iOSHighPerformance+': true } }, enabled);
|
|
|
|
|
const rows = () => [...files.values()].flatMap(s => s.split('\n').filter(Boolean).flatMap(line => { try { return [JSON.parse(line)]; } catch (_) { return []; } }));
|
|
|
|
|
return { api, wx, files, handlers, timers, modals, sheets, calls, rows, logins, requests, timeouts,
|
|
|
|
|
full() { failWrite = true; }, advance(ms) { now += ms; }, tick() { now += 5000; timers.filter(Boolean).forEach(fn => fn()); } };
|
|
|
|
@@ -66,6 +66,28 @@ function fakeEngine() {
|
|
|
|
|
Director: { EVENT_BEFORE_SCENE_LOADING: 'load', EVENT_BEFORE_SCENE_LAUNCH: 'before', EVENT_AFTER_SCENE_LAUNCH: 'after', EVENT_AFTER_UPDATE: 'frame' }, find: () => null };
|
|
|
|
|
return { cc, events, calls, Bundle };
|
|
|
|
|
}
|
|
|
|
|
test('diagnostics default to off before accessing WeChat APIs', () => {
|
|
|
|
|
const module = { exports: {} };
|
|
|
|
|
vm.runInNewContext(source, { module });
|
|
|
|
|
const wx = new Proxy({}, { get() { throw Error('WeChat API accessed while disabled'); } });
|
|
|
|
|
for (const enabled of [undefined, false, null, 0, 1, 'true']) {
|
|
|
|
|
assert.equal(module.exports.create(wx, {}, enabled).enabled, false);
|
|
|
|
|
}
|
|
|
|
|
assert.equal(module.exports.create(wx).enabled, false);
|
|
|
|
|
});
|
|
|
|
|
test('master switch disables diagnostics in every channel without side effects', () => {
|
|
|
|
|
for (const env of ['develop', 'trial', 'release']) {
|
|
|
|
|
const files = new Map([[ROOT + '1800000000000-abcdefgh.start.jsonl', '{"event":"session.start"}\n']]);
|
|
|
|
|
const before = [...files];
|
|
|
|
|
const f = fixture(files, env, 1800000010000, false, false), e = fakeEngine(), original = e.Bundle.prototype.load;
|
|
|
|
|
let launched = 0, exported = 0;
|
|
|
|
|
f.api.attachEngine(e.cc); f.api.record('x'); f.api.beforeBoot(() => launched++); f.api.exportPrevious(() => exported++);
|
|
|
|
|
assert.equal(f.api.enabled, false); assert.equal(launched, 1); assert.equal(exported, 1);
|
|
|
|
|
assert.equal(e.Bundle.prototype.load, original); assert.deepEqual([...files], before);
|
|
|
|
|
for (const entries of [f.calls, f.timers, f.modals, f.sheets, f.logins, f.requests, Object.keys(f.handlers), Object.keys(e.events)]) assert.equal(entries.length, 0);
|
|
|
|
|
assert.equal(f.timeouts.size, 0);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
test('release/unknown/unavailable channel performs no persistence, listeners, timers or engine patching', () => {
|
|
|
|
|
for (const env of ['release', null, 'unknown', 'throws']) {
|
|
|
|
|
const f = fixture(new Map(), env), e = fakeEngine(), original = e.Bundle.prototype.load;
|
|
|
|
@@ -349,7 +371,10 @@ test('bootstrap keeps the recovery prompt before adapter/engine initialization a
|
|
|
|
|
const boot = fs.readFileSync('build-templates/wechatgame/game.js', 'utf8');
|
|
|
|
|
const calls = [], context = { wx: {}, window: { boot: () => calls.push('boot') }, cc: { view: {}, sys: { platform: 1, WECHAT_GAME_SUB: 2 }, macro: {} },
|
|
|
|
|
requirePlugin: () => calls.push('engine'), __globalAdapter: { init() {}, adaptEngine() {} },
|
|
|
|
|
require: name => name === './memory-diagnostics' ? { create: () => ({ enabled: false, beforeBoot: next => { context.resume = next; }, attachEngine() {} }) } : {} };
|
|
|
|
|
require: name => name === './memory-diagnostics' ? { create: (wx, build, enabled) => {
|
|
|
|
|
assert.equal(enabled, false);
|
|
|
|
|
return { enabled: false, beforeBoot: next => { context.resume = next; }, attachEngine() {} };
|
|
|
|
|
} } : {} };
|
|
|
|
|
vm.runInNewContext(boot, context); assert.deepEqual(calls, []); context.resume(); assert.deepEqual(calls, ['engine', 'boot']);
|
|
|
|
|
assert(boot.includes('window.boot();'));
|
|
|
|
|
});
|
|
|
|
|