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.

Test.ts 26KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926
  1. import { describe, it } from "mocha";
  2. import { RPCServer, RPCSocket } from '../Index'
  3. import { RPCExporter, Socket } from "../src/Interfaces";
  4. import { ConnectedSocket } from "../src/Types";
  5. import * as log from 'why-is-node-running';
  6. import * as http from 'http';
  7. import * as express from 'express';
  8. import * as fetch from 'node-fetch';
  9. import { PromiseIO } from "../src/PromiseIO/Server";
  10. import { PromiseIOClient } from "../src/PromiseIO/Client";
  11. const noop = (...args) => { }
  12. const add = (...args: number[]) => { return args.reduce((a, b) => a + b, 0) }
  13. function makeServer(onCallback = noop, connectionHandler = noop, hookCloseHandler = noop, closeHandler = noop, errorHandler = (socket, err) => { throw err }) {
  14. let subcallback
  15. const serv = new RPCServer([{
  16. name: 'test',
  17. RPCs: [
  18. {
  19. name: 'echo',
  20. call: async (s: string) => s,
  21. }, {
  22. name: 'simpleSubscribe',
  23. hook: async (callback) => {
  24. subcallback = callback
  25. return { topic: "test" }
  26. },
  27. onDestroy: hookCloseHandler
  28. }, {
  29. name: 'subscribe',
  30. hook: async (callback) => {
  31. subcallback = callback
  32. return { topic: "test" }
  33. },
  34. onDestroy: hookCloseHandler,
  35. onCallback: onCallback
  36. },
  37. add,
  38. function triggerCallback(...messages: any[]): number { return subcallback.apply({}, messages) },
  39. function brokenRPC(){ throw new Error("Intended error") }
  40. ]
  41. }],
  42. {
  43. connectionHandler: connectionHandler,
  44. closeHandler: closeHandler,
  45. errorHandler: errorHandler
  46. })
  47. serv.listen(21010)
  48. return serv
  49. }
  50. describe('PromiseIO', () => {
  51. it("bind + fire", (done) => {
  52. const server = new PromiseIO()
  53. server.attach(new http.Server())
  54. server.on("socket", clientSocket => {
  55. clientSocket.bind("test123", (p1,p2) => {
  56. server.close()
  57. if(p1 === "p1" && p2 === "p2")
  58. done()
  59. })
  60. });
  61. server.listen(21003)
  62. PromiseIOClient.connect(21003, "localhost", "http").then(cli => {
  63. cli.fire("test123", "p1", "p2")
  64. cli.close()
  65. })
  66. })
  67. it("hook + call", (done) => {
  68. const server = new PromiseIO()
  69. server.attach(new http.Server())
  70. server.on("socket", clientSocket => {
  71. clientSocket.hook("test123", (p1,p2) => {
  72. if(p1 === "p1" && p2 === "p2")
  73. return "OK"
  74. })
  75. });
  76. server.listen(21003)
  77. PromiseIOClient.connect(21003, "localhost", "http").then(cli => {
  78. cli.call("test123", "p1", "p2").then(resp => {
  79. cli.close()
  80. server.close()
  81. if(resp === "OK")
  82. done()
  83. })
  84. })
  85. })
  86. it("on + emit", (done) => {
  87. const server = new PromiseIO()
  88. server.attach(new http.Server())
  89. server.on("socket", clientSocket => {
  90. clientSocket.on("test123", (p1,p2) => {
  91. server.close()
  92. if(p1 === "p1" && p2 === "p2")
  93. done()
  94. })
  95. });
  96. server.listen(21003)
  97. PromiseIOClient.connect(21003, "localhost", "http").then(cli => {
  98. cli.emit("test123", "p1", "p2")
  99. cli.close()
  100. })
  101. })
  102. })
  103. describe('RPCServer', () => {
  104. let client, server
  105. const echo = (x) => x
  106. before(done => {
  107. server = new RPCServer([{
  108. name: 'HelloWorldRPCGroup',
  109. RPCs: () => [
  110. echo, //named function variable
  111. function echof(x) { return x }, //named function
  112. {
  113. name: 'echoExplicit', //describing object
  114. call: async (x, y, z) => [x, y, z]
  115. }
  116. ]
  117. }])
  118. server.listen(21003)
  119. client = new RPCSocket(21003, 'localhost')
  120. done()
  121. })
  122. after(done => {
  123. client.close()
  124. server.close()
  125. done()
  126. })
  127. it('should be able to use all kinds of RPC definitions', (done) => {
  128. client.connect().then(async () => {
  129. const r0 = await client['HelloWorldRPCGroup'].echo('Hello')
  130. const r1 = await client['HelloWorldRPCGroup'].echof('World')
  131. const r2 = await client['HelloWorldRPCGroup'].echoExplicit('R', 'P', 'C!')
  132. if (r0 === 'Hello' && r1 === 'World' && r2.join('') === 'RPC!') {
  133. done()
  134. } else {
  135. done(new Error("Bad response"))
  136. }
  137. })
  138. })
  139. it('new RPCServer() should fail on bad RPC', (done) => {
  140. try {
  141. const sv = new RPCServer([{
  142. name: 'bad',
  143. RPCs: () => [
  144. (aaa, bbb, ccc) => { return aaa + bbb + ccc }
  145. ]
  146. }])
  147. sv.listen(20001)
  148. done(new Error("Didn't fail with bad RPC"))
  149. } catch (badRPCError) {
  150. done()
  151. }
  152. })
  153. })
  154. describe('RPCServer with premade http server', () => {
  155. const echo = (x) => x
  156. const RPCs = [
  157. echo, //named function variable
  158. function echof(x) { return x }, //named function
  159. {
  160. name: 'echoExplicit', //describing object
  161. call: async (x, y, z) => [x, y, z]
  162. }
  163. ]
  164. const RPCExporters = [
  165. {
  166. name: 'HelloWorldRPCGroup',
  167. RPCs: RPCs,
  168. }
  169. ]
  170. const RPCExporters2 = [
  171. {
  172. name: 'Grp2',
  173. RPCs: [
  174. function test() { return "test" }
  175. ],
  176. }
  177. ]
  178. let client: RPCSocket, server: RPCServer
  179. before(done => {
  180. const expressServer = express()
  181. const httpServer = new http.Server(expressServer)
  182. expressServer.get('/REST_ping', (req, res) => {
  183. return res
  184. .send('REST_pong')
  185. .status(200)
  186. })
  187. server = new RPCServer(
  188. RPCExporters,
  189. )
  190. server.attach(httpServer)
  191. httpServer.listen(8080)
  192. client = new RPCSocket(8080, 'localhost')
  193. done()
  194. })
  195. after(done => {
  196. client.close()
  197. server.close()
  198. done()
  199. })
  200. it('should serve REST', (done) => {
  201. fetch('http://localhost:8080/REST_ping').then(response => {
  202. response.text().then(text => {
  203. if (text === "REST_pong")
  204. done()
  205. else
  206. done(new Error("REST repsonse was " + text))
  207. })
  208. })
  209. })
  210. it('should be able to use all kinds of RPC definitions', (done) => {
  211. client.connect().then(async () => {
  212. const r0 = await client['HelloWorldRPCGroup'].echo('Hello')
  213. const r1 = await client['HelloWorldRPCGroup'].echof('World')
  214. const r2 = await client['HelloWorldRPCGroup'].echoExplicit('R', 'P', 'C!')
  215. if (r0 === 'Hello' && r1 === 'World' && r2.join('') === 'RPC!') {
  216. done()
  217. } else {
  218. done(new Error("Bad response"))
  219. }
  220. })
  221. })
  222. })
  223. describe('Serverside Triggers', () => {
  224. let server, client
  225. const closerFunction = (done) => () => {
  226. client.close()
  227. server.close()
  228. done()
  229. }
  230. it('trigger onCallback', (done) => {
  231. server = makeServer(closerFunction(done))
  232. client = new RPCSocket(21010, "localhost")
  233. client.connect().then(_ => {
  234. client['test'].subscribe(noop).then(_ => client['test'].triggerCallback())
  235. })
  236. })
  237. it('trigger connectionHandler', (done) => {
  238. server = makeServer(undefined, closerFunction(done))
  239. client = new RPCSocket(21010, "localhost")
  240. client.connect()
  241. })
  242. it('trigger hook closeHandler', (done) => {
  243. server = makeServer(undefined, undefined, closerFunction(done))
  244. client = new RPCSocket(21010, "localhost")
  245. client.connect().then(_ => {
  246. client['test'].subscribe(function cb(){
  247. cb['destroy']()
  248. }).then(_ => client['test'].triggerCallback())
  249. })
  250. })
  251. it('trigger global closeHandler', (done) => {
  252. server = makeServer(undefined, undefined, undefined, () => {
  253. server.close()
  254. done()
  255. })
  256. client = new RPCSocket(21010, "localhost")
  257. client.connect().then(_ => {
  258. client['test'].subscribe(noop).then(_ => client.close())
  259. })
  260. })
  261. })
  262. describe('RPCSocket', () => {
  263. let client: RPCSocket
  264. let server: RPCServer
  265. before(async () => {
  266. server = makeServer()
  267. client = new RPCSocket(21010, "localhost")
  268. return await client.connect()
  269. })
  270. after(() => {
  271. client.close()
  272. server.close()
  273. })
  274. it('should have rpc echo', (done) => {
  275. client['test'].echo("x").then(x => {
  276. if (x === 'x')
  277. done()
  278. else
  279. done(new Error('echo RPC response did not match'))
  280. })
  281. })
  282. it('should add up to 6', (done) => {
  283. client['test'].add(1, 2, 3).then(x => {
  284. if (x === 6)
  285. done()
  286. else
  287. done(new Error('add RPC response did not match'))
  288. })
  289. })
  290. it('should subscribe with success', (done) => {
  291. client['test'].simpleSubscribe(console.log).then(res => {
  292. if (res.topic === 'test') {
  293. done()
  294. } else {
  295. console.error(res)
  296. done(new Error('Subscribe did not return success'))
  297. }
  298. })
  299. })
  300. it('subscribe should call back', (done) => {
  301. client['test'].subscribe((...args: any) => {
  302. if (args[0] === "test" && args[1] === "callback")
  303. done()
  304. else
  305. done(new Error("Bad callback value " + args))
  306. }).then(async () => {
  307. await client['test'].triggerCallback("test", "callback")
  308. })
  309. })
  310. it('simpleSubscribe should call back', (done) => {
  311. client['test'].simpleSubscribe((...args: any) => {
  312. if (args[0] === "test_" && args[1] === "callback_")
  313. done()
  314. else
  315. done(new Error("Bad callback value " + args))
  316. }).then(async () => {
  317. await client['test'].triggerCallback("test_", "callback_")
  318. })
  319. })
  320. })
  321. describe('It should do unhook', () => {
  322. const yesCandy = "OK"
  323. const noCandy = "stolen"
  324. let candy = yesCandy
  325. let cb: Function
  326. let cb2: Function
  327. let client: RPCSocket
  328. let server: RPCServer
  329. before(async () => {
  330. server = new RPCServer([{
  331. name: "test",
  332. RPCs: () => [{
  333. name: 'subscribe',
  334. hook: async (callback): Promise<void> => {
  335. cb = <Function>callback
  336. return
  337. }
  338. },
  339. {
  340. name: 'subscribeWithParam',
  341. hook: async (param, callback): Promise<{ uuid: string }> => {
  342. if (param != "OK") {
  343. console.log("param was" + param);
  344. return {
  345. uuid: "no",
  346. }
  347. }
  348. cb2 = <Function>callback
  349. return {
  350. uuid: "OK",
  351. }
  352. }
  353. },
  354. function publish(): string { cb(candy); return candy },
  355. function unsubscribe(): string { candy = noCandy; cb(candy); cb = () => { }; return candy }
  356. ]
  357. }],
  358. {
  359. connectionHandler: noop,
  360. closeHandler: noop,
  361. errorHandler: (socket, err) => { throw err }
  362. })
  363. server.listen(21010)
  364. client = new RPCSocket(21010, "localhost")
  365. return await client.connect()
  366. })
  367. after(() => {
  368. client.close()
  369. server.close()
  370. })
  371. it('Subscribe with param', (done) => {
  372. client['test'].subscribeWithParam("OK", noop).then(async (res) => {
  373. if (res.uuid === candy) {
  374. done()
  375. } else
  376. done(new Error("Results did not match " + res.uuid))
  377. })
  378. })
  379. let run = 0
  380. const expected = [yesCandy, noCandy, noCandy, noCandy]
  381. it('Unhook+unsubscribe should stop callbacks', (done) => {
  382. client['test'].subscribe(function myCallback(c) {
  383. if (run == 1)
  384. (myCallback as any).destroy()
  385. if (c !== expected[run++]) {
  386. done(new Error(`Wrong candy '${c}' in iteration '${run - 1}'`))
  387. }
  388. }).then(async function (res) {
  389. const r1 = await client['test'].publish()
  390. const r3 = await client['test'].unsubscribe()
  391. const r2 = await client['test'].publish()
  392. const r4 = await client['test'].publish()
  393. if (r1 === yesCandy && r3 === noCandy && r2 === noCandy && r4 === noCandy)
  394. done()
  395. else
  396. done(new Error("Results did not match: " + [r1, r2, r3, r4]))
  397. })
  398. })
  399. })
  400. type topicDTO = { topic: string; }
  401. type SesameTestIfc = {
  402. test: {
  403. checkCandy: () => Promise<string>
  404. subscribe: (callback: Function) => Promise<topicDTO>
  405. manyParams: <A = string, B = number, C = boolean, D = Object>(a: A, b: B, c: C, d: D) => Promise<[A, B, C, D]>
  406. }
  407. }
  408. describe('Sesame should unlock the socket', () => {
  409. let candy = "OK"
  410. let client: ConnectedSocket<SesameTestIfc>
  411. let server: RPCServer<SesameTestIfc>
  412. let cb: Function = (...args) => { }
  413. before((done) => {
  414. server = new RPCServer<SesameTestIfc>([{
  415. name: "test",
  416. RPCs: () => [
  417. {
  418. name: 'subscribe',
  419. hook: async (callback) => {
  420. cb = callback
  421. return {
  422. topic: 'test'
  423. }
  424. },
  425. onDestroy: noop
  426. },
  427. async function checkCandy() { cb(candy); cb = noop; return candy },
  428. async function manyParams(a, b, c, d) { return [a, b, c, d] }
  429. ],
  430. }], {
  431. sesame: (_sesame) => _sesame === 'sesame!'
  432. })
  433. server.listen(21004)
  434. const sock = new RPCSocket<SesameTestIfc>(21004, "localhost")
  435. sock.connect('sesame!').then(cli => {
  436. client = cli
  437. done()
  438. })
  439. })
  440. after(() => {
  441. client.close()
  442. server.close()
  443. })
  444. it('should work with sesame', (done) => {
  445. client.test.checkCandy().then(c => done())
  446. })
  447. it('should work with multiple params', (done) => {
  448. client.test['manyParams']('a', 'b', 'c', 'd').then(c => {
  449. if (c[0] == 'a' && c[1] === 'b' && c[2] === 'c' && c[3] === 'd')
  450. done()
  451. })
  452. })
  453. it('should not work without sesame', (done) => {
  454. const sock = new RPCSocket(21004, "localhost")
  455. sock.connect( /* no sesame */).then(async (cli) => {
  456. if (!cli.test)
  457. done()
  458. else {
  459. done(new Error("Function supposed to be removed without sesame"))
  460. }
  461. cli.close()
  462. sock.close()
  463. })
  464. })
  465. it('should fail with wrong sesame', (done) => {
  466. const sock = new RPCSocket(21004, "localhost")
  467. sock.connect('abasd').then(async (cli) => {
  468. if (!cli.test)
  469. done()
  470. else {
  471. done(new Error("Function supposed to be removed without sesame"))
  472. }
  473. cli.close()
  474. sock.close()
  475. })
  476. })
  477. it('callback should work with sesame', (done) => {
  478. client.test.subscribe((c) => {
  479. if (c === candy) {
  480. done()
  481. }
  482. }).then(d => {
  483. if (d.topic !== 'test')
  484. done('unexpected invalid response')
  485. client.test.checkCandy()
  486. })
  487. })
  488. })
  489. describe('Error handling', () => {
  490. const errtxt = "BAD BAD BAD"
  491. let createUser = async (user: { a: any, b: any }) => {
  492. throw new Error(errtxt)
  493. }
  494. it("RPC throws on client without handler", (done) => {
  495. let server = new RPCServer([{
  496. name: "createUser",
  497. RPCs: () => [{
  498. name: 'createUser' as 'createUser',
  499. call: createUser
  500. }]
  501. }])
  502. server.listen(21004)
  503. let sock = new RPCSocket(21004, 'localhost')
  504. sock.connect().then((cli) => {
  505. cli["createUser"]["createUser"]({
  506. a: 'a',
  507. b: 'b'
  508. })
  509. .then(r => {
  510. if (r != null)
  511. done(new Error("UNEXPECTED RESULT " + r))
  512. })
  513. .catch((e) => {
  514. if (e.message === errtxt)
  515. done()
  516. else
  517. done(e)
  518. })
  519. .finally(() => {
  520. cli.close()
  521. sock.close()
  522. server.close()
  523. })
  524. })
  525. })
  526. it("RPC throws on server with handler", (done) => {
  527. let server = new RPCServer([{
  528. name: "createUser",
  529. RPCs: () => [{
  530. name: 'createUser' as 'createUser',
  531. call: createUser
  532. }]
  533. }], {
  534. errorHandler: (socket, e, rpcName, args) => {
  535. done()
  536. }
  537. })
  538. server.listen(21004)
  539. let sock = new RPCSocket(21004, 'localhost')
  540. sock.connect().then((cli) => {
  541. cli["createUser"]["createUser"]({
  542. a: 'a',
  543. b: 'b'
  544. })
  545. .then(r => {
  546. if (r != null)
  547. done("UNEXPECTED RESULT " + r)
  548. })
  549. .catch((e) => {
  550. done("UNEXPECTED CLIENT ERROR " + e)
  551. done(e)
  552. })
  553. .finally(() => {
  554. cli.close()
  555. sock.close()
  556. server.close()
  557. })
  558. })
  559. })
  560. })
  561. describe("Errorhandler functionality", () => {
  562. const errtxt = "BAD BAD BAD"
  563. let createUser = async (user: { a: any, b: any }) => {
  564. throw new Error(errtxt)
  565. }
  566. it("correct values are passed to the handler", (done) => {
  567. let server = new RPCServer([{
  568. name: "createUser",
  569. RPCs: () => [{
  570. name: 'createUser' as 'createUser',
  571. call: createUser
  572. }]
  573. }], {
  574. errorHandler: (socket, e, rpcName, args) => {
  575. if (e.message === errtxt && rpcName === "createUser" && args[0]['a'] === 'a' && args[0]['b'] === 'b')
  576. done()
  577. }
  578. })
  579. server.listen(21004)
  580. let sock = new RPCSocket(21004, 'localhost')
  581. sock.connect().then((cli) => {
  582. cli["createUser"]["createUser"]({
  583. a: 'a',
  584. b: 'b'
  585. })
  586. .then(r => {
  587. if (r != null)
  588. done(new Error("UNEXPECTED RESULT " + r))
  589. })
  590. .catch((e) => {
  591. done(new Error("UNEXPECTED CLIENT ERROR " + e.message))
  592. })
  593. .finally(() => {
  594. cli.close()
  595. sock.close()
  596. server.close()
  597. })
  598. })
  599. })
  600. it("handler sees sesame", (done) => {
  601. let sesame = "AAAAAAAAAAAAAAA"
  602. let server = new RPCServer([{
  603. name: "createUser" as "createUser",
  604. RPCs: () => [{
  605. name: 'createUser' as 'createUser',
  606. call: createUser
  607. }]
  608. }], {
  609. sesame: sesame,
  610. errorHandler: (socket, e, rpcName, args) => {
  611. if (e.message === errtxt && rpcName === "createUser" && args[0] === sesame && args[1]['a'] === 'a' && args[1]['b'] === 'b')
  612. done()
  613. }
  614. })
  615. server.listen(21004)
  616. let sock = new RPCSocket(21004, 'localhost')
  617. sock.connect(sesame).then((cli) => {
  618. cli["createUser"]["createUser"]({
  619. a: 'a',
  620. b: 'b'
  621. })
  622. .then(r => {
  623. if (r != null)
  624. done(new Error("UNEXPECTED RESULT " + r))
  625. })
  626. .catch((e) => {
  627. done(new Error("UNEXPECTED CLIENT ERROR " + e))
  628. })
  629. .finally(() => {
  630. cli.close()
  631. sock.close()
  632. server.close()
  633. })
  634. })
  635. })
  636. })
  637. type myExporterIfc = {
  638. MyExporter: {
  639. myRPC: () => Promise<string>
  640. }
  641. }
  642. describe("Class binding", () => {
  643. let exporter1: MyExporter
  644. let serv: RPCServer<myExporterIfc>
  645. let sock: RPCSocket & myExporterIfc
  646. let allowed = true
  647. class MyExporter implements RPCExporter<myExporterIfc>{
  648. name = "MyExporter" as "MyExporter"
  649. RPCs = () => [
  650. this.myRPC
  651. ]
  652. myRPC = async () => {
  653. //serv.setExporters([new MyOtherExporter])
  654. return "Hello World"
  655. }
  656. }
  657. class MyOtherExporter implements RPCExporter<myExporterIfc>{
  658. name = "MyExporter" as "MyExporter"
  659. RPCs = () => [
  660. this.myRPC
  661. ]
  662. myRPC = async () => {
  663. return "Hello Borld"
  664. }
  665. }
  666. before(done => {
  667. exporter1 = new MyExporter()
  668. serv = new RPCServer<myExporterIfc>(
  669. [exporter1],
  670. {
  671. accessFilter: async (sesame, exporter) => {
  672. if (exporter.name === 'MyExporter') {
  673. if (!allowed) return false
  674. allowed = false
  675. return sesame === 'xxx';
  676. } else {
  677. return false
  678. }
  679. },
  680. sesame: "xxx"
  681. })
  682. serv.listen(21004)
  683. done()
  684. })
  685. beforeEach((done) => {
  686. const s = new RPCSocket<myExporterIfc>(21004, 'localhost')
  687. s.connect("xxx").then(conn => {
  688. sock = conn
  689. done()
  690. })
  691. })
  692. afterEach((done) => {
  693. sock.close()
  694. done()
  695. })
  696. after(() => {
  697. serv.close()
  698. })
  699. /* The server-side socket will enter a 30s timeout if destroyed by a RPC.
  700. to mitigate the impact on testing time these are not run.
  701. it("binds correctly", function(done){
  702. this.timeout(1000)
  703. sock['MyExporter'].myRPC().then((res) => {
  704. done(new Error(res))
  705. }).catch(e => {
  706. //job will time out because of setExporters
  707. allowed = true
  708. done()
  709. })
  710. })
  711. it("changes exporters", (done) => {
  712. sock['MyExporter'].myRPC().then((res) => {
  713. if (res === "Hello Borld")
  714. done()
  715. else
  716. done(new Error(res))
  717. })
  718. })
  719. */
  720. it("use sesameFilter for available", (done) => {
  721. if (sock['MyExporter']) {
  722. allowed = false
  723. done()
  724. }
  725. else done(new Error("RPC supposed to be here"))
  726. })
  727. it("use sesameFilter", (done) => {
  728. if (!sock['MyExporter']) done()
  729. else done(new Error("RPC supposed to be gone"))
  730. })
  731. })
  732. describe("attaching handlers before connecting", () => {
  733. it("fires error if server is unreachable", (done) => {
  734. const sock = new RPCSocket<myExporterIfc>(21004, 'localhost')
  735. let errorHandleCount = 0
  736. sock.on('error', (err) => {
  737. //attached listener fires first
  738. if (errorHandleCount != 0) {
  739. console.log("Error handler didn't fire first");
  740. } else {
  741. errorHandleCount++
  742. }
  743. })
  744. sock.connect().then(_ => {
  745. console.log("Unexpected successful connect")
  746. }).catch(e => {
  747. //catch clause fires second
  748. if (errorHandleCount != 1) {
  749. console.log("catch clause didn't fire second", errorHandleCount);
  750. } else {
  751. sock.close()
  752. done()
  753. }
  754. })
  755. })
  756. /*
  757. * ## 1.11.0 breaking ##
  758. *
  759. * API change: Move from bsock to socketio changes underlying API for when errors are thrown.
  760. * socketio does not throw on unknown listener. This behaviour is considered more consistent with the design
  761. * goals of RPClibrary and was thus adopted
  762. *
  763. it("fires error if call is unknown", (done) => {
  764. const serv = new RPCServer(21004)
  765. const sock = new RPCSocket(21004, 'localhost')
  766. sock.on('error', (err) => {
  767. sock.close()
  768. serv.close()
  769. done()
  770. })
  771. sock.connect().then(_ => {
  772. sock.call("unknownRPC123", "AAAAA").catch(e => { }).then(x => {
  773. console.log("X",x);
  774. })
  775. }).catch(e => {
  776. console.log("unexpected connect catch clause");
  777. done(e)
  778. })
  779. })
  780. it("demands catch on method invocation if call is unknown", (done) => {
  781. const serv = new RPCServer(21004)
  782. const sock = new RPCSocket(21004, 'localhost')
  783. sock.connect().then(_ => {
  784. sock.call("unknownRPC123", "AAAAA").catch(e => {
  785. sock.close()
  786. serv.close()
  787. done()
  788. })
  789. }).catch(e => {
  790. console.log("unexpected connect catch clause");
  791. done(e)
  792. })
  793. })
  794. */
  795. })
  796. describe('finally', () => {
  797. it('print open handles (Ignore `DNSCHANNEL` and `Immediate`)', () => {
  798. //log(console)
  799. })
  800. })