Unknown RPC errors, fixed error handler structure, multiple RPCservers on different paths, optional throws
This commit is contained in:
+215
-79
@@ -12,7 +12,7 @@ import { PromiseIOClient } from "../src/PromiseIO/Client";
|
||||
const noop = (...args) => { }
|
||||
|
||||
const add = (...args: number[]) => { return args.reduce((a, b) => a + b, 0) }
|
||||
function makeServer(onCallback = noop, connectionHandler = noop, hookCloseHandler = noop, closeHandler = noop, errorHandler = (socket, err) => { throw err }) {
|
||||
function makeServer(onCallback = noop, connectionHandler = noop, hookCloseHandler = noop, closeHandler = noop, errorHandler = noop) {
|
||||
let subcallback
|
||||
const serv = new RPCServer([{
|
||||
name: 'test',
|
||||
@@ -38,7 +38,7 @@ function makeServer(onCallback = noop, connectionHandler = noop, hookCloseHandle
|
||||
},
|
||||
add,
|
||||
function triggerCallback(...messages: any[]): number { return subcallback.apply({}, messages) },
|
||||
function brokenRPC(){ throw new Error("Intended error") }
|
||||
function brokenRPC() { throw new Error("Intended error") }
|
||||
]
|
||||
}],
|
||||
{
|
||||
@@ -57,15 +57,15 @@ describe('PromiseIO', () => {
|
||||
const server = new PromiseIO()
|
||||
server.attach(new http.Server())
|
||||
server.on("socket", clientSocket => {
|
||||
clientSocket.bind("test123", (p1,p2) => {
|
||||
clientSocket.bind("test123", (p1, p2) => {
|
||||
server.close()
|
||||
if(p1 === "p1" && p2 === "p2")
|
||||
if (p1 === "p1" && p2 === "p2")
|
||||
done()
|
||||
})
|
||||
});
|
||||
|
||||
server.listen(21003)
|
||||
PromiseIOClient.connect(21003, "localhost", "http").then(cli => {
|
||||
PromiseIOClient.connect(21003, "localhost", { protocol: 'http' }).then(cli => {
|
||||
cli.fire("test123", "p1", "p2")
|
||||
cli.close()
|
||||
})
|
||||
@@ -75,19 +75,19 @@ describe('PromiseIO', () => {
|
||||
const server = new PromiseIO()
|
||||
server.attach(new http.Server())
|
||||
server.on("socket", clientSocket => {
|
||||
clientSocket.hook("test123", (p1,p2) => {
|
||||
if(p1 === "p1" && p2 === "p2")
|
||||
clientSocket.hook("test123", (p1, p2) => {
|
||||
if (p1 === "p1" && p2 === "p2")
|
||||
return "OK"
|
||||
})
|
||||
});
|
||||
|
||||
server.listen(21003)
|
||||
PromiseIOClient.connect(21003, "localhost", "http").then(cli => {
|
||||
PromiseIOClient.connect(21003, "localhost", { protocol: 'http' }).then(cli => {
|
||||
cli.call("test123", "p1", "p2").then(resp => {
|
||||
cli.close()
|
||||
server.close()
|
||||
|
||||
if(resp === "OK")
|
||||
if (resp === "OK")
|
||||
done()
|
||||
})
|
||||
})
|
||||
@@ -97,15 +97,15 @@ describe('PromiseIO', () => {
|
||||
const server = new PromiseIO()
|
||||
server.attach(new http.Server())
|
||||
server.on("socket", clientSocket => {
|
||||
clientSocket.on("test123", (p1,p2) => {
|
||||
clientSocket.on("test123", (p1, p2) => {
|
||||
server.close()
|
||||
if(p1 === "p1" && p2 === "p2")
|
||||
if (p1 === "p1" && p2 === "p2")
|
||||
done()
|
||||
})
|
||||
});
|
||||
|
||||
server.listen(21003)
|
||||
PromiseIOClient.connect(21003, "localhost", "http").then(cli => {
|
||||
PromiseIOClient.connect(21003, "localhost", { protocol: 'http' }).then(cli => {
|
||||
cli.emit("test123", "p1", "p2")
|
||||
cli.close()
|
||||
})
|
||||
@@ -256,6 +256,194 @@ describe('RPCServer with premade http server', () => {
|
||||
})
|
||||
})
|
||||
|
||||
describe('should be able to attach to non-standard path', () => {
|
||||
let client: RPCSocket, server: RPCServer
|
||||
const echo = (x) => x
|
||||
|
||||
before(done => {
|
||||
server = new RPCServer([{
|
||||
name: 'HelloWorldRPCGroup',
|
||||
RPCs: () => [
|
||||
echo, //named function variable
|
||||
function echof(x) { return x }, //named function
|
||||
{
|
||||
name: 'echoExplicit', //describing object
|
||||
call: async (x, y, z) => [x, y, z]
|
||||
}
|
||||
]
|
||||
}])
|
||||
server.listen(21003, {path: '/test'})
|
||||
client = new RPCSocket(21003, 'localhost', {path: '/test'})
|
||||
done()
|
||||
})
|
||||
|
||||
after(done => {
|
||||
client.close()
|
||||
server.close()
|
||||
|
||||
done()
|
||||
})
|
||||
|
||||
it('should be able to use all kinds of RPC definitions', (done) => {
|
||||
client.connect().then(async () => {
|
||||
const r0 = await client['HelloWorldRPCGroup'].echo('Hello')
|
||||
const r1 = await client['HelloWorldRPCGroup'].echof('World')
|
||||
const r2 = await client['HelloWorldRPCGroup'].echoExplicit('R', 'P', 'C!')
|
||||
|
||||
|
||||
if (r0 === 'Hello' && r1 === 'World' && r2.join('') === 'RPC!') {
|
||||
done()
|
||||
} else {
|
||||
done(new Error("Bad response"))
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
describe('can attach multiple RPCServers to same http server', () => {
|
||||
const echo = (x) => x
|
||||
const RPCs = [
|
||||
echo, //named function variable
|
||||
function echof(x) { return x }, //named function
|
||||
{
|
||||
name: 'echoExplicit', //describing object
|
||||
call: async (x, y, z) => [x, y, z]
|
||||
}
|
||||
]
|
||||
|
||||
const RPCExporters = [
|
||||
{
|
||||
name: 'HelloWorldRPCGroup',
|
||||
RPCs: RPCs,
|
||||
}
|
||||
]
|
||||
|
||||
const RPCExporters2 = [
|
||||
{
|
||||
name: 'Grp2',
|
||||
RPCs: [
|
||||
function test() { return "/test" }
|
||||
],
|
||||
}
|
||||
]
|
||||
|
||||
let client: RPCSocket, client2: RPCSocket, server: RPCServer, server2: RPCServer
|
||||
|
||||
before(done => {
|
||||
const expressServer = express()
|
||||
const httpServer = new http.Server(expressServer)
|
||||
|
||||
server = new RPCServer(
|
||||
RPCExporters,
|
||||
)
|
||||
server2 = new RPCServer(
|
||||
RPCExporters2
|
||||
)
|
||||
|
||||
server.attach(httpServer)
|
||||
server2.attach(httpServer, {
|
||||
path: "test"
|
||||
})
|
||||
|
||||
httpServer.listen(8080)
|
||||
|
||||
new RPCSocket(8080, 'localhost').connect().then(sock => {
|
||||
client = sock
|
||||
new RPCSocket(8080, 'localhost', { path: "test" }).connect().then(sock2 => {
|
||||
client2 = sock2
|
||||
done()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
after(done => {
|
||||
client.close()
|
||||
client2.close()
|
||||
server.close()
|
||||
server2.close()
|
||||
|
||||
done()
|
||||
})
|
||||
|
||||
it('both servers should answer', (done) => {
|
||||
client['HelloWorldRPCGroup'].echo("test").then(res => {
|
||||
if(res != "test"){
|
||||
done(new Error("response was "+res))
|
||||
}else{
|
||||
client2['Grp2'].test().then(res => {
|
||||
if(res != "/test"){
|
||||
done(new Error("response2 was "+res))
|
||||
}else{
|
||||
done()
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
})
|
||||
|
||||
describe("can attach second RPCServer if first is already running", () => {
|
||||
|
||||
const RPCExporters = [
|
||||
{
|
||||
name: 'HelloWorldRPCGroup',
|
||||
RPCs: [
|
||||
function echo (x) { return x}, //named function variable
|
||||
function echof(x) { return x }, //named function
|
||||
{
|
||||
name: 'echoExplicit', //describing object
|
||||
call: async (x, y, z) => [x, y, z]
|
||||
}
|
||||
],
|
||||
}
|
||||
]
|
||||
|
||||
const RPCExporters2 = [
|
||||
{
|
||||
name: 'Grp2',
|
||||
RPCs: [
|
||||
function test() { return "/test" }
|
||||
],
|
||||
}
|
||||
]
|
||||
|
||||
it("attaches correctly", done => {
|
||||
const expressServer = express()
|
||||
const httpServer = new http.Server(expressServer)
|
||||
|
||||
const server = new RPCServer(
|
||||
RPCExporters,
|
||||
)
|
||||
const server2 = new RPCServer(
|
||||
RPCExporters2
|
||||
)
|
||||
|
||||
server.attach(httpServer)
|
||||
|
||||
httpServer.listen(8080)
|
||||
server2.attach(httpServer, {
|
||||
path: "test"
|
||||
})
|
||||
|
||||
new RPCSocket(8080, 'localhost').connect().then(sock => {
|
||||
new RPCSocket(8080, 'localhost', { path: "test" }).connect().then(sock2 => {
|
||||
sock2.Grp2.test().then(resp => {
|
||||
if(resp === "/test")
|
||||
done()
|
||||
else
|
||||
done(new Error("response did not match"))
|
||||
|
||||
server.close()
|
||||
server2.close()
|
||||
sock.close()
|
||||
sock2.close()
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('Serverside Triggers', () => {
|
||||
let server, client
|
||||
@@ -273,23 +461,24 @@ describe('Serverside Triggers', () => {
|
||||
})
|
||||
})
|
||||
|
||||
/* testing framework has trouble terminating on this one
|
||||
it('trigger connectionHandler', (done) => {
|
||||
server = makeServer(undefined, closerFunction(done))
|
||||
client = new RPCSocket(21010, "localhost")
|
||||
client.connect()
|
||||
})
|
||||
*/
|
||||
|
||||
|
||||
it('trigger hook closeHandler', (done) => {
|
||||
server = makeServer(undefined, undefined, closerFunction(done))
|
||||
client = new RPCSocket(21010, "localhost")
|
||||
client.connect().then(_ => {
|
||||
client['test'].subscribe(function cb(){
|
||||
client['test'].subscribe(function cb() {
|
||||
cb['destroy']()
|
||||
}).then(_ => client['test'].triggerCallback())
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
|
||||
it('trigger global closeHandler', (done) => {
|
||||
server = makeServer(undefined, undefined, undefined, () => {
|
||||
@@ -301,8 +490,6 @@ describe('Serverside Triggers', () => {
|
||||
client['test'].subscribe(noop).then(_ => client.close())
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
})
|
||||
|
||||
describe('RPCSocket', () => {
|
||||
@@ -512,7 +699,7 @@ describe('Sesame should unlock the socket', () => {
|
||||
client.close()
|
||||
server.close()
|
||||
})
|
||||
|
||||
|
||||
it('should work with sesame', (done) => {
|
||||
client.test.checkCandy().then(c => done())
|
||||
})
|
||||
@@ -526,7 +713,7 @@ describe('Sesame should unlock the socket', () => {
|
||||
|
||||
it('should not work without sesame', (done) => {
|
||||
const sock = new RPCSocket(21004, "localhost")
|
||||
sock.connect( /* no sesame */).then(async (cli) => {
|
||||
sock.connect().then(async (cli) => {
|
||||
if (!cli.test)
|
||||
done()
|
||||
else {
|
||||
@@ -733,7 +920,6 @@ type myExporterIfc = {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
describe("Class binding", () => {
|
||||
|
||||
let exporter1: MyExporter
|
||||
@@ -802,32 +988,6 @@ describe("Class binding", () => {
|
||||
serv.close()
|
||||
})
|
||||
|
||||
/* The server-side socket will enter a 30s timeout if destroyed by a RPC.
|
||||
to mitigate the impact on testing time these are not run.
|
||||
|
||||
it("binds correctly", function(done){
|
||||
this.timeout(1000)
|
||||
sock['MyExporter'].myRPC().then((res) => {
|
||||
done(new Error(res))
|
||||
}).catch(e => {
|
||||
//job will time out because of setExporters
|
||||
allowed = true
|
||||
done()
|
||||
})
|
||||
})
|
||||
|
||||
it("changes exporters", (done) => {
|
||||
|
||||
sock['MyExporter'].myRPC().then((res) => {
|
||||
if (res === "Hello Borld")
|
||||
done()
|
||||
else
|
||||
done(new Error(res))
|
||||
})
|
||||
})
|
||||
*/
|
||||
|
||||
|
||||
it("use sesameFilter for available", (done) => {
|
||||
if (sock['MyExporter']) {
|
||||
allowed = false
|
||||
@@ -842,6 +1002,14 @@ describe("Class binding", () => {
|
||||
})
|
||||
})
|
||||
|
||||
/*
|
||||
describe('finally', () => {
|
||||
it('print open handles (Ignore `DNSCHANNEL` and `Immediate`)', () => {
|
||||
//log(console)
|
||||
})
|
||||
})
|
||||
*/
|
||||
|
||||
|
||||
describe("attaching handlers before connecting", () => {
|
||||
it("fires error if server is unreachable", (done) => {
|
||||
@@ -870,17 +1038,8 @@ describe("attaching handlers before connecting", () => {
|
||||
})
|
||||
})
|
||||
|
||||
/*
|
||||
* ## 1.11.0 breaking ##
|
||||
*
|
||||
* API change: Move from bsock to socketio changes underlying API for when errors are thrown.
|
||||
* socketio does not throw on unknown listener. This behaviour is considered more consistent with the design
|
||||
* goals of RPClibrary and was thus adopted
|
||||
*
|
||||
|
||||
|
||||
it("fires error if call is unknown", (done) => {
|
||||
const serv = new RPCServer(21004)
|
||||
const serv = new RPCServer().listen(21004)
|
||||
const sock = new RPCSocket(21004, 'localhost')
|
||||
|
||||
sock.on('error', (err) => {
|
||||
@@ -900,27 +1059,4 @@ describe("attaching handlers before connecting", () => {
|
||||
})
|
||||
})
|
||||
|
||||
it("demands catch on method invocation if call is unknown", (done) => {
|
||||
const serv = new RPCServer(21004)
|
||||
const sock = new RPCSocket(21004, 'localhost')
|
||||
|
||||
sock.connect().then(_ => {
|
||||
sock.call("unknownRPC123", "AAAAA").catch(e => {
|
||||
sock.close()
|
||||
serv.close()
|
||||
done()
|
||||
})
|
||||
}).catch(e => {
|
||||
console.log("unexpected connect catch clause");
|
||||
done(e)
|
||||
})
|
||||
})
|
||||
*/
|
||||
|
||||
})
|
||||
|
||||
describe('finally', () => {
|
||||
it('print open handles (Ignore `DNSCHANNEL` and `Immediate`)', () => {
|
||||
//log(console)
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user