You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

242 lines
7.3 KiB

4 years ago
/// <reference path="../typings/index.d.ts"/>
import * as assert from 'assert';
import RpcProvider from '../src/RpcProvider';
suite('RPC provider', function() {
let local: RpcProvider,
remote: RpcProvider,
transferLocalToRemote: Array<any>,
transferRemoteToLocal: Array<any>,
errorLocal: Error,
errorRemote: Error;
setup(function() {
local = new RpcProvider(
(message, transfer) => (transferLocalToRemote = transfer, remote.dispatch(message)),
50
);
local.error.addHandler(err => errorLocal = err);
remote = new RpcProvider(
(message, transfer) => (transferRemoteToLocal = transfer, local.dispatch(message)),
50
);
remote.error.addHandler(err => errorRemote = err);
transferLocalToRemote = transferRemoteToLocal = undefined;
errorRemote = errorLocal = undefined
});
suite('signals', function() {
test('Signals are propagated', function() {
let x = -1;
remote.registerSignalHandler('action', (value: number) => x = value);
local.signal('action', 5);
assert(!errorLocal);
assert(!errorRemote);
assert.strictEqual(x, 5);
});
test('Unregistered signals raise an error', function() {
local.signal('action', 10);
assert(errorLocal);
assert(errorRemote);
});
test('Multiple signals do not interfere', function() {
let x = -1, y = -1;
remote.registerSignalHandler('setx', (value: number) => x = value);
remote.registerSignalHandler('sety', (value: number) => y = value);
local.signal('setx', 5);
local.signal('sety', 6);
assert(!errorLocal);
assert(!errorRemote);
assert.strictEqual(x, 5);
assert.strictEqual(y, 6);
});
test('Multiple handlers can be bound to one signal', function() {
let x = -1;
remote.registerSignalHandler('action', (value: number) => x = value);
local.signal('action', 1);
local.signal('action', 2);
assert(!errorLocal);
assert(!errorRemote);
assert.strictEqual(x, 2);
});
test('Handlers can be deregistered', function() {
let x = -1;
const handler = (value: number) => x = value;
remote.registerSignalHandler('action', handler);
remote.deregisterSignalHandler('action', handler);
local.signal('action', 5);
assert(!errorLocal);
assert(!errorRemote);
assert.strictEqual(x, -1);
});
test('Transfer is honored', function() {
let x = -1;
const transfer = [1, 2, 3];
remote.registerSignalHandler('action', (value: number) => x = value);
local.signal('action', 2, transfer);
assert(!errorLocal);
assert(!errorRemote);
assert.strictEqual(x, 2);
assert.strictEqual(transferLocalToRemote, transfer);
assert(!transferRemoteToLocal);
});
});
suite('RPC', function() {
test('RPC handlers can return values', function() {
remote.registerRpcHandler('action', () => 10);
return local
.rpc('action')
.then(result => (
assert.strictEqual(result, 10),
assert(!errorLocal),
assert(!errorRemote)
));
});
test('RPC handlers can return promises', function() {
remote.registerRpcHandler('action', () => new Promise(r => setTimeout(() => r(10), 15)));
return local
.rpc('action')
.then(result => (
assert.strictEqual(result, 10),
assert(!errorLocal),
assert(!errorRemote)
));
})
test('Promise rejection is transferred', function() {
remote.registerRpcHandler('action', () => new Promise((resolve, reject) => setTimeout(() => reject(10), 15)));
return local
.rpc('action')
.then(
() => Promise.reject('should have been rejected'),
result => (
assert.strictEqual(result, 10),
assert(!errorLocal),
assert(!errorRemote)
)
);
});
test('Invalid RPC calls are rejected', function() {
return local
.rpc('action')
.then(
() => Promise.reject('should have been rejected'),
() => undefined
);
});
test('Invalid RPC calls throw on both ends', function() {
return local
.rpc('action')
.then(
() => Promise.reject('should have been rejected'),
() => undefined
)
.then(() => (
assert(errorLocal),
assert(errorRemote)
));
});
test('RPC calls time out', function() {
remote.registerRpcHandler('action', () => new Promise(r => setTimeout(() => r(10), 100)));
return local
.rpc('action')
.then(
() => Promise.reject('should have been rejected'),
() => (assert(errorLocal), new Promise(r => setTimeout(r, 100)))
)
.then(() => assert(errorRemote));
});
test('Multiple RPC handlers do not interfere', function() {
remote.registerRpcHandler('a1', (value: number) => new Promise(r => setTimeout(() => r(value), 30)));
remote.registerRpcHandler('a2', (value: number) => 2 * value);
return Promise
.all([
local.rpc('a1', 10),
local.rpc('a2', 20)
])
.then(([r1, r2]) => (
assert.strictEqual(r1, 10),
assert.strictEqual(r2, 40),
assert(!errorLocal),
assert(!errorRemote)
));
});
test('RPC handler can be deregistered', function() {
const handler = () => 10;
remote.registerRpcHandler('action', handler);
remote.deregisterRpcHandler('action', handler);
return local
.rpc('action')
.then(
() => Promise.reject('should have been rejected'),
() => (
assert(errorLocal),
assert(errorRemote)
)
);
});
test('Transfer is honored', function() {
const transfer = [1, 2, 3];
remote.registerRpcHandler('action', () => 10);
return local
.rpc('action', undefined, transfer)
.then(x => (
assert.strictEqual(transferLocalToRemote, transfer),
assert.strictEqual(x, 10),
assert(!errorLocal),
assert(!errorRemote)
));
});
});
});