UNPKG

es-vm

Version:

A visual machine run in ES env like Node/Browser

302 lines (222 loc) 6.8 kB
const assert = require('assert'); const pack = require('./pack'); pack(({ESVM, Statement}) => describe('Kernel::', function () { const statement = new Statement(); statement.execute = function* ($) { yield $.vm.flag = 1; return 'RET'; }; describe('Method::', function () { it('get position', function() { const vm = new ESVM(); assert.equal(null, vm.getPosition); const statement = new Statement(); vm.pushOperation(statement); assert.equal(statement.position, vm.getPosition); }); it('$clearOperationStack', function () { const vm = new ESVM(); const statement = new Statement(); vm.pushOperation(statement); assert.equal(statement, vm.$operationStack[0]); vm.$clearOperationStack(); assert.equal(vm.$operationStack.length, 0); }); it('pushOperation', function () { const vm = new ESVM(); const statement = new Statement(); vm.pushOperation(statement); assert.equal(statement, vm.$operationStack[0]); }); it('popOperation', function () { const vm = new ESVM(); const statement = new Statement(); vm.pushOperation(statement); assert.equal(statement, vm.$operationStack[0]); assert.equal(vm.popOperation(), statement); }); it('setOnFetch', function () { const vm = new ESVM(); assert.throws(() => { vm.setOnFetch(); }, '[ESVM-DEV]: Need a funtion for vm.setOnFetch.'); assert.equal(vm.setOnFetch(() => {}), vm); }); describe('fetch::', function () { this.timeout(5000); const testStatement = new Statement(); testStatement.execute = function* ($) { const signal = $.vm.fetch({ type: 'remote' }, 400); assert.equal(signal, 'VM::BLOCKED'); yield signal; yield 'after fetch'; }; it('timeout', function (done) { const vm = new ESVM(); vm.setOnFetch(invoking => { assert.equal(invoking.type, 'remote'); return new Promise(resolve => { setTimeout(resolve, 500); }); }); vm.$loadProgram(testStatement).$launch(); vm.on('error', err => { assert.equal(err.message, 'Fetching timeout.'); done(); }); }); it('halt without event#program-end', function (done) { const vm = new ESVM(); vm.setOnFetch(invoking => { assert.equal(invoking.type, 'remote'); return new Promise(resolve => { setTimeout(resolve, 500); }); }); vm.$loadProgram(testStatement).$launch(); setTimeout(() => { vm.$halt(); }, 300); setTimeout(() => { assert.equal(vm.$runtime, null); done(); }, 400); vm.on('program-end', $vm => { assert.equal(vm, $vm); throw new Error('It was wrong'); }); }); it('rpc with ret', function (done) { const vm = new ESVM(); const RPCStatement = new Statement(); const mockInvoking = {}; RPCStatement.execute = function* ($) { const ret = yield $.vm.fetch(mockInvoking, 400); assert.equal(ret, 'RPC-RET'); }; vm.on('program-end', () => { done(); }); vm.setOnFetch(invoking => { assert.equal(invoking, mockInvoking); return new Promise(resolve => { setTimeout(()=> resolve('RPC-RET'), 300); }); }); vm.$loadProgram(RPCStatement).$launch(); }); it('rpc with outter-exception & inner handle.', function (done) { const vm = new ESVM(); const RPCStatement = new Statement(); const mockInvoking = {}; RPCStatement.execute = function* ($) { try { yield $.vm.fetch(mockInvoking, 400); } catch (err) { assert.equal(err.message.match('RPC-ERROR') !== null, true); } return 'success'; }; vm.on('program-end', (err, ret, $vm) => { assert.equal(err, null); assert.equal(ret, 'success'); assert.equal($vm, vm); done(); }); vm.setOnFetch(invoking => { assert.equal(invoking, mockInvoking); return new Promise((resolve, reject) => { setTimeout(() => reject(new Error('RPC-ERROR')), 300); }); }); vm.on('error', function () { throw new Error('It was wrong'); }); vm.$loadProgram(RPCStatement).$launch(); }); it('rpc with outer-exception but no-handling', function (done) { const outterError = new Error('RPC-ERROR'); const vm = new ESVM(); const RPCStatement = new Statement(); const mockInvoking = {}; RPCStatement.execute = function* ($) { yield $.vm.fetch(mockInvoking, 400); }; vm.on('program-end', (err, ret, $vm) => { assert.equal(err, outterError); assert.equal(ret, undefined); assert.equal($vm, vm); done(); }); vm.setOnFetch(invoking => { assert.equal(invoking, mockInvoking); return new Promise((_, reject) => { setTimeout(reject(outterError), 300); }); }); vm.on('error', function (err) { assert.equal(err.message.match('RPC-ERROR') !== null, true); }); vm.$loadProgram(RPCStatement).$launch(); }); }); it('$loadProgram', function () { const vm = new ESVM(); assert.throws(() => { vm.$loadProgram(); }, '[ESVM-DEV]: Invalid statement.'); vm.$loadProgram(statement); assert.notEqual(vm.$runtime, null); }); it('$launch', function (done) { const vm = new ESVM(); assert.throws(() => { vm.$launch(); }, '[ESVM]: No program in vm. Use vm.$loadProgram before.'); vm.$loadProgram(statement); vm.on('program-start', ($vm) => { assert.equal(vm, $vm); done(); }); // vm.on('writeback', console.log); vm.$launch(); }); describe('$run::', function () { it('get VM::BLOCKED', function () { const blocked = new Statement(); blocked.execute = function* () { yield '123'; yield 'VM::BLOCKED'; }; const vm = new ESVM(); const ret = vm.$loadProgram(blocked).$launch(); assert.equal('suspend', ret); }); it('inner-exception', function (done) { const exception = new Statement(); exception.execute = function* (test) { yield 1; if (test) { throw new Error('for test'); } yield 'VM::BLOCKED'; }; const vm = new ESVM(); vm.on('error', function (err) { assert.equal(err.message, 'for test'); }); vm.on('program-end', function () { done(); }); vm.$loadProgram(exception).$launch(); }); }); it('$complete', function (done) { const vm = new ESVM(); vm.on('program-end', function () { done(); }); vm.$complete(); }); }); }));