68 lines
3.7 KiB
JavaScript
68 lines
3.7 KiB
JavaScript
// Execute the actual Emscripten library against SocketTask and browser test doubles.
|
|
const fs = require('fs');
|
|
const vm = require('vm');
|
|
const assert = require('assert/strict');
|
|
const source = fs.readFileSync('AIClient/Assets/Plugins/WebGL/GameWebSocket.jslib', 'utf8');
|
|
let checks = 0;
|
|
function environment(kind) {
|
|
let sockets = [], memory = {}, next = 1;
|
|
const make = () => {
|
|
const s = { callbacks: {}, sent: [], closes: 0,
|
|
onOpen(fn) { this.callbacks.open = fn; }, onMessage(fn) { this.callbacks.message = fn; },
|
|
onError(fn) { this.callbacks.error = fn; }, onClose(fn) { this.callbacks.close = fn; },
|
|
close() { this.closes++; },
|
|
send(arg) { if (this.throwSend) throw Error('send rejected'); this.sent.push(arg); },
|
|
emit(type, data = {}) { (this.callbacks[type] || this['on' + type])(data); } };
|
|
sockets.push(s); return s;
|
|
};
|
|
const context = { LibraryManager: { library: {} }, mergeInto: Object.assign,
|
|
UTF8ToString: x => typeof x === 'string' ? x : memory[x],
|
|
lengthBytesUTF8: x => Buffer.byteLength(x), _malloc: () => next++,
|
|
stringToUTF8: (x, p) => memory[p] = x };
|
|
const wx = { connectSocket(options) { const s = make(); s.options = options; return s; } };
|
|
if (kind === 'wechat') context.wx = wx;
|
|
else if (kind === 'global') context.GameGlobal = { wx };
|
|
else if (kind === 'browser') context.WebSocket = function (url) { const s = make(); s.url = url; return s; };
|
|
vm.createContext(context); vm.runInContext(source, context);
|
|
context.AIGameSockets = context.LibraryManager.library.$AIGameSockets;
|
|
const api = context.LibraryManager.library;
|
|
return { api, sockets, context, poll(id) { const p = api.AIGame_WsPoll(id); const text = memory[p]; delete memory[p]; return text; } };
|
|
}
|
|
for (const kind of ['wechat', 'global', 'browser']) {
|
|
const e = environment(kind), id = e.api.AIGame_WsCreate('wss://game.test/ws');
|
|
const s = e.sockets[0];
|
|
s.emit('open'); assert.equal(e.poll(id), 'O');
|
|
s.emit('message', { data: '中文消息🙂' }); assert.equal(e.poll(id), 'M中文消息🙂');
|
|
e.api.AIGame_WsSend(id, 'hello');
|
|
assert.equal(kind === 'browser' ? s.sent[0] : s.sent[0].data, 'hello');
|
|
s.emit('error', { errMsg: 'offline' }); s.emit('close', { code: 1006 });
|
|
assert.ok(e.poll(id).startsWith('E')); assert.equal(e.poll(id), undefined);
|
|
e.api.AIGame_WsDispose(id); assert.equal(s.closes, 1);
|
|
s.emit('message', { data: 'stale' }); assert.equal(e.poll(id), undefined);
|
|
assert.equal(Object.keys(e.context.AIGameSockets.sockets).length, 0);
|
|
checks++;
|
|
}
|
|
{
|
|
const e = environment('wechat'), id = e.api.AIGame_WsCreate('wss://test');
|
|
e.api.AIGame_WsDispose(id); e.sockets[0].emit('open');
|
|
assert.equal(e.sockets[0].closes, 2); assert.equal(e.poll(id), undefined); checks++;
|
|
}
|
|
for (const mode of ['throw', 'callback']) {
|
|
const e = environment('wechat'), id = e.api.AIGame_WsCreate('wss://test'), s = e.sockets[0];
|
|
s.emit('open'); e.poll(id);
|
|
if (mode === 'throw') s.throwSend = true;
|
|
e.api.AIGame_WsSend(id, 'hello');
|
|
if (mode === 'callback') s.sent[0].fail({ errMsg: 'send denied' });
|
|
assert.ok(e.poll(id).startsWith('E')); e.api.AIGame_WsDispose(id); checks++;
|
|
}
|
|
{
|
|
const e = environment('wechat'), id = e.api.AIGame_WsCreate('wss://test');
|
|
e.sockets[0].options.fail({ errMsg: 'domain rejected' });
|
|
assert.equal(e.poll(id), 'Edomain rejected'); e.api.AIGame_WsDispose(id); checks++;
|
|
}
|
|
{
|
|
const e = environment('missing'), id = e.api.AIGame_WsCreate('wss://test');
|
|
assert.ok(e.poll(id).startsWith('E')); e.api.AIGame_WsDispose(id); checks++;
|
|
}
|
|
console.log(`PASS: ${checks} WebSocket bridge scenarios (WeChat, GameGlobal, browser, UTF-8, error, send failure, disposal).`);
|