rpcProvider.ts 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. /// <reference path="../typings/index.d.ts"/>
  2. import * as assert from 'assert';
  3. import RpcProvider from '../src/RpcProvider';
  4. suite('RPC provider', function() {
  5. let local: RpcProvider,
  6. remote: RpcProvider,
  7. transferLocalToRemote: Array<any>,
  8. transferRemoteToLocal: Array<any>,
  9. errorLocal: Error,
  10. errorRemote: Error;
  11. setup(function() {
  12. local = new RpcProvider(
  13. (message, transfer) => (transferLocalToRemote = transfer, remote.dispatch(message)),
  14. 50
  15. );
  16. local.error.addHandler(err => errorLocal = err);
  17. remote = new RpcProvider(
  18. (message, transfer) => (transferRemoteToLocal = transfer, local.dispatch(message)),
  19. 50
  20. );
  21. remote.error.addHandler(err => errorRemote = err);
  22. transferLocalToRemote = transferRemoteToLocal = undefined;
  23. errorRemote = errorLocal = undefined
  24. });
  25. suite('signals', function() {
  26. test('Signals are propagated', function() {
  27. let x = -1;
  28. remote.registerSignalHandler('action', (value: number) => x = value);
  29. local.signal('action', 5);
  30. assert(!errorLocal);
  31. assert(!errorRemote);
  32. assert.strictEqual(x, 5);
  33. });
  34. test('Unregistered signals raise an error', function() {
  35. local.signal('action', 10);
  36. assert(errorLocal);
  37. assert(errorRemote);
  38. });
  39. test('Multiple signals do not interfere', function() {
  40. let x = -1, y = -1;
  41. remote.registerSignalHandler('setx', (value: number) => x = value);
  42. remote.registerSignalHandler('sety', (value: number) => y = value);
  43. local.signal('setx', 5);
  44. local.signal('sety', 6);
  45. assert(!errorLocal);
  46. assert(!errorRemote);
  47. assert.strictEqual(x, 5);
  48. assert.strictEqual(y, 6);
  49. });
  50. test('Multiple handlers can be bound to one signal', function() {
  51. let x = -1;
  52. remote.registerSignalHandler('action', (value: number) => x = value);
  53. local.signal('action', 1);
  54. local.signal('action', 2);
  55. assert(!errorLocal);
  56. assert(!errorRemote);
  57. assert.strictEqual(x, 2);
  58. });
  59. test('Handlers can be deregistered', function() {
  60. let x = -1;
  61. const handler = (value: number) => x = value;
  62. remote.registerSignalHandler('action', handler);
  63. remote.deregisterSignalHandler('action', handler);
  64. local.signal('action', 5);
  65. assert(!errorLocal);
  66. assert(!errorRemote);
  67. assert.strictEqual(x, -1);
  68. });
  69. test('Transfer is honored', function() {
  70. let x = -1;
  71. const transfer = [1, 2, 3];
  72. remote.registerSignalHandler('action', (value: number) => x = value);
  73. local.signal('action', 2, transfer);
  74. assert(!errorLocal);
  75. assert(!errorRemote);
  76. assert.strictEqual(x, 2);
  77. assert.strictEqual(transferLocalToRemote, transfer);
  78. assert(!transferRemoteToLocal);
  79. });
  80. });
  81. suite('RPC', function() {
  82. test('RPC handlers can return values', function() {
  83. remote.registerRpcHandler('action', () => 10);
  84. return local
  85. .rpc('action')
  86. .then(result => (
  87. assert.strictEqual(result, 10),
  88. assert(!errorLocal),
  89. assert(!errorRemote)
  90. ));
  91. });
  92. test('RPC handlers can return promises', function() {
  93. remote.registerRpcHandler('action', () => new Promise(r => setTimeout(() => r(10), 15)));
  94. return local
  95. .rpc('action')
  96. .then(result => (
  97. assert.strictEqual(result, 10),
  98. assert(!errorLocal),
  99. assert(!errorRemote)
  100. ));
  101. })
  102. test('Promise rejection is transferred', function() {
  103. remote.registerRpcHandler('action', () => new Promise((resolve, reject) => setTimeout(() => reject(10), 15)));
  104. return local
  105. .rpc('action')
  106. .then(
  107. () => Promise.reject('should have been rejected'),
  108. result => (
  109. assert.strictEqual(result, 10),
  110. assert(!errorLocal),
  111. assert(!errorRemote)
  112. )
  113. );
  114. });
  115. test('Invalid RPC calls are rejected', function() {
  116. return local
  117. .rpc('action')
  118. .then(
  119. () => Promise.reject('should have been rejected'),
  120. () => undefined
  121. );
  122. });
  123. test('Invalid RPC calls throw on both ends', function() {
  124. return local
  125. .rpc('action')
  126. .then(
  127. () => Promise.reject('should have been rejected'),
  128. () => undefined
  129. )
  130. .then(() => (
  131. assert(errorLocal),
  132. assert(errorRemote)
  133. ));
  134. });
  135. test('RPC calls time out', function() {
  136. remote.registerRpcHandler('action', () => new Promise(r => setTimeout(() => r(10), 100)));
  137. return local
  138. .rpc('action')
  139. .then(
  140. () => Promise.reject('should have been rejected'),
  141. () => (assert(errorLocal), new Promise(r => setTimeout(r, 100)))
  142. )
  143. .then(() => assert(errorRemote));
  144. });
  145. test('Multiple RPC handlers do not interfere', function() {
  146. remote.registerRpcHandler('a1', (value: number) => new Promise(r => setTimeout(() => r(value), 30)));
  147. remote.registerRpcHandler('a2', (value: number) => 2 * value);
  148. return Promise
  149. .all([
  150. local.rpc('a1', 10),
  151. local.rpc('a2', 20)
  152. ])
  153. .then(([r1, r2]) => (
  154. assert.strictEqual(r1, 10),
  155. assert.strictEqual(r2, 40),
  156. assert(!errorLocal),
  157. assert(!errorRemote)
  158. ));
  159. });
  160. test('RPC handler can be deregistered', function() {
  161. const handler = () => 10;
  162. remote.registerRpcHandler('action', handler);
  163. remote.deregisterRpcHandler('action', handler);
  164. return local
  165. .rpc('action')
  166. .then(
  167. () => Promise.reject('should have been rejected'),
  168. () => (
  169. assert(errorLocal),
  170. assert(errorRemote)
  171. )
  172. );
  173. });
  174. test('Transfer is honored', function() {
  175. const transfer = [1, 2, 3];
  176. remote.registerRpcHandler('action', () => 10);
  177. return local
  178. .rpc('action', undefined, transfer)
  179. .then(x => (
  180. assert.strictEqual(transferLocalToRemote, transfer),
  181. assert.strictEqual(x, 10),
  182. assert(!errorLocal),
  183. assert(!errorRemote)
  184. ));
  185. });
  186. });
  187. });