message_handler_spec.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365
  1. /**
  2. * @licstart The following is the entire license notice for the
  3. * Javascript code in this page
  4. *
  5. * Copyright 2020 Mozilla Foundation
  6. *
  7. * Licensed under the Apache License, Version 2.0 (the "License");
  8. * you may not use this file except in compliance with the License.
  9. * You may obtain a copy of the License at
  10. *
  11. * http://www.apache.org/licenses/LICENSE-2.0
  12. *
  13. * Unless required by applicable law or agreed to in writing, software
  14. * distributed under the License is distributed on an "AS IS" BASIS,
  15. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  16. * See the License for the specific language governing permissions and
  17. * limitations under the License.
  18. *
  19. * @licend The above is the entire license notice for the
  20. * Javascript code in this page
  21. */
  22. "use strict";
  23. var _util = require("../../shared/util.js");
  24. var _api = require("../../display/api.js");
  25. var _message_handler = require("../../shared/message_handler.js");
  26. describe("message_handler", function () {
  27. function sleep(ticks) {
  28. return Promise.resolve().then(() => {
  29. return ticks && sleep(ticks - 1);
  30. });
  31. }
  32. describe("sendWithStream", function () {
  33. it("should return a ReadableStream", function () {
  34. const port = new _api.LoopbackPort();
  35. const messageHandler1 = new _message_handler.MessageHandler("main", "worker", port);
  36. const readable = messageHandler1.sendWithStream("fakeHandler");
  37. expect(typeof readable).toEqual("object");
  38. expect(typeof readable.getReader).toEqual("function");
  39. });
  40. it("should read using a reader", function (done) {
  41. let log = "";
  42. const port = new _api.LoopbackPort();
  43. const messageHandler1 = new _message_handler.MessageHandler("main", "worker", port);
  44. const messageHandler2 = new _message_handler.MessageHandler("worker", "main", port);
  45. messageHandler2.on("fakeHandler", (data, sink) => {
  46. sink.onPull = function () {
  47. log += "p";
  48. };
  49. sink.onCancel = function (reason) {
  50. log += "c";
  51. };
  52. sink.ready.then(() => {
  53. sink.enqueue("hi");
  54. return sink.ready;
  55. }).then(() => {
  56. sink.close();
  57. });
  58. return sleep(5);
  59. });
  60. const readable = messageHandler1.sendWithStream("fakeHandler", {}, {
  61. highWaterMark: 1,
  62. size() {
  63. return 1;
  64. }
  65. });
  66. const reader = readable.getReader();
  67. sleep(10).then(() => {
  68. expect(log).toEqual("");
  69. return reader.read();
  70. }).then(result => {
  71. expect(log).toEqual("p");
  72. expect(result.value).toEqual("hi");
  73. expect(result.done).toEqual(false);
  74. return sleep(10);
  75. }).then(() => {
  76. return reader.read();
  77. }).then(result => {
  78. expect(result.value).toEqual(undefined);
  79. expect(result.done).toEqual(true);
  80. done();
  81. });
  82. });
  83. it("should not read any data when cancelled", function (done) {
  84. let log = "";
  85. const port = new _api.LoopbackPort();
  86. const messageHandler2 = new _message_handler.MessageHandler("worker", "main", port);
  87. messageHandler2.on("fakeHandler", (data, sink) => {
  88. sink.onPull = function () {
  89. log += "p";
  90. };
  91. sink.onCancel = function (reason) {
  92. log += "c";
  93. };
  94. log += "0";
  95. sink.ready.then(() => {
  96. log += "1";
  97. sink.enqueue([1, 2, 3, 4], 4);
  98. return sink.ready;
  99. }).then(() => {
  100. log += "2";
  101. sink.enqueue([5, 6, 7, 8], 4);
  102. return sink.ready;
  103. }).then(() => {
  104. log += "3";
  105. sink.close();
  106. }, () => {
  107. log += "4";
  108. });
  109. });
  110. const messageHandler1 = new _message_handler.MessageHandler("main", "worker", port);
  111. const readable = messageHandler1.sendWithStream("fakeHandler", {}, {
  112. highWaterMark: 4,
  113. size(arr) {
  114. return arr.length;
  115. }
  116. });
  117. const reader = readable.getReader();
  118. sleep(10).then(() => {
  119. expect(log).toEqual("01");
  120. return reader.read();
  121. }).then(result => {
  122. expect(result.value).toEqual([1, 2, 3, 4]);
  123. expect(result.done).toEqual(false);
  124. return sleep(10);
  125. }).then(() => {
  126. expect(log).toEqual("01p2");
  127. return reader.cancel(new _util.AbortException("reader cancelled."));
  128. }).then(() => {
  129. expect(log).toEqual("01p2c4");
  130. done();
  131. });
  132. });
  133. it("should not read when errored", function (done) {
  134. let log = "";
  135. const port = new _api.LoopbackPort();
  136. const messageHandler2 = new _message_handler.MessageHandler("worker", "main", port);
  137. messageHandler2.on("fakeHandler", (data, sink) => {
  138. sink.onPull = function () {
  139. log += "p";
  140. };
  141. sink.onCancel = function (reason) {
  142. log += "c";
  143. };
  144. log += "0";
  145. sink.ready.then(() => {
  146. log += "1";
  147. sink.enqueue([1, 2, 3, 4], 4);
  148. return sink.ready;
  149. }).then(() => {
  150. log += "e";
  151. sink.error(new Error("should not read when errored"));
  152. });
  153. });
  154. const messageHandler1 = new _message_handler.MessageHandler("main", "worker", port);
  155. const readable = messageHandler1.sendWithStream("fakeHandler", {}, {
  156. highWaterMark: 4,
  157. size(arr) {
  158. return arr.length;
  159. }
  160. });
  161. const reader = readable.getReader();
  162. sleep(10).then(() => {
  163. expect(log).toEqual("01");
  164. return reader.read();
  165. }).then(result => {
  166. expect(result.value).toEqual([1, 2, 3, 4]);
  167. expect(result.done).toEqual(false);
  168. return reader.read();
  169. }).catch(reason => {
  170. expect(log).toEqual("01pe");
  171. expect(reason instanceof _util.UnknownErrorException).toEqual(true);
  172. expect(reason.message).toEqual("should not read when errored");
  173. done();
  174. });
  175. });
  176. it("should read data with blocking promise", function (done) {
  177. let log = "";
  178. const port = new _api.LoopbackPort();
  179. const messageHandler2 = new _message_handler.MessageHandler("worker", "main", port);
  180. messageHandler2.on("fakeHandler", (data, sink) => {
  181. sink.onPull = function () {
  182. log += "p";
  183. };
  184. sink.onCancel = function (reason) {
  185. log += "c";
  186. };
  187. log += "0";
  188. sink.ready.then(() => {
  189. log += "1";
  190. sink.enqueue([1, 2, 3, 4], 4);
  191. return sink.ready;
  192. }).then(() => {
  193. log += "2";
  194. sink.enqueue([5, 6, 7, 8], 4);
  195. return sink.ready;
  196. }).then(() => {
  197. sink.close();
  198. });
  199. });
  200. const messageHandler1 = new _message_handler.MessageHandler("main", "worker", port);
  201. const readable = messageHandler1.sendWithStream("fakeHandler", {}, {
  202. highWaterMark: 4,
  203. size(arr) {
  204. return arr.length;
  205. }
  206. });
  207. const reader = readable.getReader();
  208. sleep(10).then(() => {
  209. expect(log).toEqual("01");
  210. return reader.read();
  211. }).then(result => {
  212. expect(result.value).toEqual([1, 2, 3, 4]);
  213. expect(result.done).toEqual(false);
  214. return sleep(10);
  215. }).then(() => {
  216. expect(log).toEqual("01p2");
  217. return reader.read();
  218. }).then(result => {
  219. expect(result.value).toEqual([5, 6, 7, 8]);
  220. expect(result.done).toEqual(false);
  221. return sleep(10);
  222. }).then(() => {
  223. expect(log).toEqual("01p2p");
  224. return reader.read();
  225. }).then(result => {
  226. expect(result.value).toEqual(undefined);
  227. expect(result.done).toEqual(true);
  228. done();
  229. });
  230. });
  231. it("should read data with blocking promise and buffer whole data" + " into stream", function (done) {
  232. let log = "";
  233. const port = new _api.LoopbackPort();
  234. const messageHandler2 = new _message_handler.MessageHandler("worker", "main", port);
  235. messageHandler2.on("fakeHandler", (data, sink) => {
  236. sink.onPull = function () {
  237. log += "p";
  238. };
  239. sink.onCancel = function (reason) {
  240. log += "c";
  241. };
  242. log += "0";
  243. sink.ready.then(() => {
  244. log += "1";
  245. sink.enqueue([1, 2, 3, 4], 4);
  246. return sink.ready;
  247. }).then(() => {
  248. log += "2";
  249. sink.enqueue([5, 6, 7, 8], 4);
  250. return sink.ready;
  251. }).then(() => {
  252. sink.close();
  253. });
  254. return sleep(10);
  255. });
  256. const messageHandler1 = new _message_handler.MessageHandler("main", "worker", port);
  257. const readable = messageHandler1.sendWithStream("fakeHandler", {}, {
  258. highWaterMark: 8,
  259. size(arr) {
  260. return arr.length;
  261. }
  262. });
  263. const reader = readable.getReader();
  264. sleep(10).then(() => {
  265. expect(log).toEqual("012");
  266. return reader.read();
  267. }).then(result => {
  268. expect(result.value).toEqual([1, 2, 3, 4]);
  269. expect(result.done).toEqual(false);
  270. return sleep(10);
  271. }).then(() => {
  272. expect(log).toEqual("012p");
  273. return reader.read();
  274. }).then(result => {
  275. expect(result.value).toEqual([5, 6, 7, 8]);
  276. expect(result.done).toEqual(false);
  277. return sleep(10);
  278. }).then(() => {
  279. expect(log).toEqual("012p");
  280. return reader.read();
  281. }).then(result => {
  282. expect(result.value).toEqual(undefined);
  283. expect(result.done).toEqual(true);
  284. done();
  285. });
  286. });
  287. it("should ignore any pull after close is called", function (done) {
  288. let log = "";
  289. const port = new _api.LoopbackPort();
  290. const capability = (0, _util.createPromiseCapability)();
  291. const messageHandler2 = new _message_handler.MessageHandler("worker", "main", port);
  292. messageHandler2.on("fakeHandler", (data, sink) => {
  293. sink.onPull = function () {
  294. log += "p";
  295. };
  296. sink.onCancel = function (reason) {
  297. log += "c";
  298. };
  299. log += "0";
  300. sink.ready.then(() => {
  301. log += "1";
  302. sink.enqueue([1, 2, 3, 4], 4);
  303. });
  304. return capability.promise.then(() => {
  305. sink.close();
  306. });
  307. });
  308. const messageHandler1 = new _message_handler.MessageHandler("main", "worker", port);
  309. const readable = messageHandler1.sendWithStream("fakeHandler", {}, {
  310. highWaterMark: 10,
  311. size(arr) {
  312. return arr.length;
  313. }
  314. });
  315. const reader = readable.getReader();
  316. sleep(10).then(() => {
  317. expect(log).toEqual("01");
  318. capability.resolve();
  319. return capability.promise.then(() => {
  320. return reader.read();
  321. });
  322. }).then(result => {
  323. expect(result.value).toEqual([1, 2, 3, 4]);
  324. expect(result.done).toEqual(false);
  325. return sleep(10);
  326. }).then(() => {
  327. expect(log).toEqual("01");
  328. return reader.read();
  329. }).then(result => {
  330. expect(result.value).toEqual(undefined);
  331. expect(result.done).toEqual(true);
  332. done();
  333. });
  334. });
  335. });
  336. });