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 7.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. import { describe, it } from "mocha";
  2. import { RPCServer } from '../src/Backend'
  3. import * as uuidv4 from "uuid/v4"
  4. import { RPCSocket } from "../src/Frontend";
  5. import { SubscriptionResponse } from "../src/Types";
  6. const add = (...args:number[]) => {return args.reduce((a,b)=>a+b, 0)}
  7. function makeServer(){
  8. let subcallback
  9. return new RPCServer<{ topic: string }>(20000, [{
  10. name: "test",
  11. exportRPCs: () => [
  12. {
  13. name: 'echo',
  14. call: async (s:string) => s,
  15. },{
  16. name: 'simpleSubscribe',
  17. hook: async(callback) => {
  18. subcallback = callback
  19. return {
  20. result: "Success",
  21. uuid: uuidv4(),
  22. topic: "test"
  23. }
  24. }
  25. },{
  26. name: 'subscribe',
  27. hook: async (callback) => {
  28. subcallback = callback
  29. return {
  30. result: "Success",
  31. uuid: uuidv4(),
  32. topic: "test"
  33. }
  34. },
  35. onClose: (res, rpc) => {
  36. console.log("onClose", rpc.name === 'subscribe' && res?"OK":"")
  37. subcallback = null
  38. },
  39. onCallback: (...args:any) => {
  40. console.log("onCallback", args[0] === "test" && args[1] === "callback"?"OK":"")
  41. }
  42. },
  43. add,
  44. function triggerCallback(...messages:any[]):number {return subcallback.apply({}, messages)},
  45. ]
  46. }],{
  47. connectionHandler: (socket) => { console.log("connectionHandler OK") },
  48. closeHandler: (socket) => { console.log("closeHandler OK") },
  49. errorHandler: (socket, err) => { console.error("errorHandler OK SO YOU SHOULDN'T SEE THIS"); throw err }
  50. })
  51. }
  52. describe('RPCServer', () => {
  53. let server: RPCServer<{ topic: string }, any>
  54. before((done) => {
  55. server = makeServer()
  56. done()
  57. })
  58. after(async() => {
  59. await server.destroy()
  60. })
  61. it('should be able to use all kinds of RPC definitions', (done) => {
  62. const echo = (x) => x
  63. const server = new RPCServer(20003, [{
  64. name: 'HelloWorldRPCGroup',
  65. exportRPCs: () => [
  66. echo, //named function variable
  67. function echof(x){ return x }, //named function
  68. {
  69. name: 'echoExplicit', //describing object
  70. call: async (x) => x
  71. }
  72. ]
  73. }])
  74. const client = new RPCSocket(20003, 'localhost')
  75. client.connect().then(async () => {
  76. const r0 = await client['HelloWorldRPCGroup'].echo('Hello')
  77. const r1 = await client['HelloWorldRPCGroup'].echof('World')
  78. const r2 = await client['HelloWorldRPCGroup'].echoExplicit('RPC!')
  79. if(r0 === 'Hello' && r1 === 'World' && r2 ==='RPC!'){
  80. client.destroy()
  81. server.destroy()
  82. done()
  83. }
  84. })
  85. })
  86. it('new RPCServer() should fail on bad RPC', (done) => {
  87. try{
  88. new RPCServer(20001, [{
  89. name: "bad",
  90. exportRPCs: () => [
  91. (aaa,bbb,ccc) => { return aaa+bbb+ccc }
  92. ]
  93. }])
  94. done(new Error("Didn't fail with bad RPC"))
  95. }catch(badRPCError){
  96. done()
  97. }
  98. })
  99. })
  100. describe('RPCSocket', () => {
  101. let client: RPCSocket
  102. let server: RPCServer<{topic: string}>
  103. before(async() => {
  104. server = makeServer()
  105. client = new RPCSocket(20000, "localhost")
  106. return await client.connect()
  107. })
  108. after(() => {
  109. client.destroy()
  110. server.destroy()
  111. })
  112. it('should have rpc echo', (done) => {
  113. client['test'].echo("x").then(x => {
  114. if(x === 'x')
  115. done()
  116. else
  117. done(new Error('echo RPC response did not match'))
  118. })
  119. })
  120. it('should add up to 6', (done) => {
  121. client['test'].add(1,2,3).then(x => {
  122. if(x === 6)
  123. done()
  124. else
  125. done(new Error('add RPC response did not match'))
  126. })
  127. })
  128. it('should subscribe with success', (done) => {
  129. client['test'].simpleSubscribe(console.log).then(res => {
  130. if(res.result === 'Success'){
  131. done()
  132. }else{
  133. console.error(res)
  134. done(new Error('Subscribe did not return success'))
  135. }
  136. })
  137. })
  138. it('subscribe should call back', (done) => {
  139. client['test'].subscribe((...args: any) => {
  140. if(args[0] === "test" && args[1] === "callback")
  141. done()
  142. else
  143. done(new Error("Bad callback value "+ args))
  144. }).then( async () => {
  145. await client['test'].triggerCallback("test", "callback")
  146. })
  147. })
  148. it('simpleSubscribe should call back', (done) => {
  149. client['test'].simpleSubscribe((...args: any) => {
  150. if(args[0] === "test_" && args[1] === "callback_")
  151. done()
  152. else
  153. done(new Error("Bad callback value "+ args))
  154. }).then( async () => {
  155. await client['test'].triggerCallback("test_", "callback_")
  156. })
  157. })
  158. })
  159. describe('It should do unhook', () => {
  160. let candy = "OK"
  161. let cb: Function
  162. let client: RPCSocket
  163. let server: RPCServer<{topic: string}>
  164. before(async() => {
  165. server = new RPCServer<{ topic: string }>(20000, [{
  166. name: "test",
  167. exportRPCs: () => [{
  168. name: 'subscribe',
  169. hook: async(callback):Promise<SubscriptionResponse<{topic:string}>> => {
  170. cb = <Function> callback
  171. return {
  172. result: "Success",
  173. uuid: uuidv4(),
  174. topic: "test"
  175. }
  176. }
  177. },
  178. function checkCandy():string { cb(candy); return candy },
  179. function stealCandy():string { candy = "_OK"; cb(candy); cb = (...any) => console.log.apply(console,["Server:", ...any]); return candy }
  180. ]
  181. }],{
  182. connectionHandler: (socket) => { console.log("connectionHandler OK") },
  183. closeHandler: (socket) => { console.log("closeHandler OK") },
  184. errorHandler: (socket, err) => { console.error("errorHandler OK SO YOU SHOULDN'T SEE THIS"); throw err }
  185. })
  186. client = new RPCSocket(20000, "localhost")
  187. return await client.connect()
  188. })
  189. after(() => {
  190. client.destroy()
  191. server.destroy()
  192. })
  193. it('Unhook+unsubscribe should stop callbacks', (done) => {
  194. client['test'].subscribe(c => console.log("Client: "+c)).then( async (res: SubscriptionResponse) => {
  195. const r1 = await client['test'].checkCandy()
  196. const r3 = await client['test'].stealCandy()
  197. client.unhook(res.uuid)
  198. console.log("---- No client output below this line")
  199. const r2 = await client['test'].checkCandy()
  200. const r4 = await client['test'].checkCandy()
  201. console.log("---- More output below")
  202. if(r1 === "OK" && r3 === "_OK" && r2 === "_OK" && r4 === "_OK")
  203. done()
  204. else
  205. done(new Error("Results did not match: "+[r1,r2,r3,r4]))
  206. })
  207. })
  208. })