biz-a-cli 2.3.71 → 2.3.73

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/tests/hub.test.js CHANGED
@@ -11,6 +11,9 @@ import { Writable, pipeline } from "node:stream";
11
11
  import { text } from "node:stream/consumers";
12
12
  import { directHubEvent, createSocketServer } from "../bin/directHubEvent.js";
13
13
  import os from "node:os";
14
+ import { cliScriptWorkerPool } from "../worker/cliWorkerPool.js";
15
+ import workerpool from "workerpool";
16
+ import { isAsyncFunction } from "node:util/types";
14
17
 
15
18
  let socketsBySubdomain = {};
16
19
 
@@ -82,7 +85,9 @@ describe("Hub event tests", () => {
82
85
 
83
86
  test("request to cli", async () => {
84
87
  const logSpy = jest.spyOn(console, "log").mockImplementation();
85
- let mockedRequest = jest.spyOn(axios, "request").mockReturnValue({ data: "OK" });
88
+ let mockedRequest = jest
89
+ .spyOn(axios, "request")
90
+ .mockReturnValue({ data: "OK" });
86
91
 
87
92
  let socket;
88
93
  try {
@@ -103,8 +108,8 @@ describe("Hub event tests", () => {
103
108
  query: { subdomain: "abc" },
104
109
  body: { data: "xyz" },
105
110
  },
106
- (cb) => resolve(cb)
107
- )
111
+ (cb) => resolve(cb),
112
+ ),
108
113
  );
109
114
 
110
115
  expect(result).toStrictEqual("OK");
@@ -123,8 +128,8 @@ describe("Hub event tests", () => {
123
128
  query: { subdomain: "abc" },
124
129
  body: { data: "xyz" },
125
130
  },
126
- (cb) => resolve(cb)
127
- )
131
+ (cb) => resolve(cb),
132
+ ),
128
133
  );
129
134
 
130
135
  expect(result).toStrictEqual("OK");
@@ -166,7 +171,13 @@ describe("Hub event tests", () => {
166
171
  port: 212,
167
172
  serverport: 3002,
168
173
  cliAddress: () => {
169
- return { ip: "59.60.1.22", port: "3002", address: `59.60.1.22:3002`, publicUrl: "https://some.tunnel.url", hubUrl: "https://some.hub.url" };
174
+ return {
175
+ ip: "59.60.1.22",
176
+ port: "3002",
177
+ address: `59.60.1.22:3002`,
178
+ publicUrl: "https://some.tunnel.url",
179
+ hubUrl: "https://some.hub.url",
180
+ };
170
181
  },
171
182
  hubServer: "https://some.hub.url",
172
183
  });
@@ -174,10 +185,19 @@ describe("Hub event tests", () => {
174
185
  mockAPIServer = net.createServer((clientSocket) => {
175
186
  cliToAPISocket = clientSocket;
176
187
  clientSocket.on("data", (data) => {
177
- if (data.toString().toUpperCase() === "POST /SUCCESS HTTP/1.1") {
178
- clientSocket.write("HTTP/1.1 200 Ok\r\nServer: datasnapHTTPService\r\n\r\n");
179
- } else if (data.toString().toUpperCase() === "POST /FAIL HTTP/1.1") {
180
- clientSocket.write("HTTP/1.1 403 Forbidden\r\nServer: datasnapHTTPService\r\n\r\n");
188
+ if (
189
+ data.toString().toUpperCase() ===
190
+ "POST /SUCCESS HTTP/1.1"
191
+ ) {
192
+ clientSocket.write(
193
+ "HTTP/1.1 200 Ok\r\nServer: datasnapHTTPService\r\n\r\n",
194
+ );
195
+ } else if (
196
+ data.toString().toUpperCase() === "POST /FAIL HTTP/1.1"
197
+ ) {
198
+ clientSocket.write(
199
+ "HTTP/1.1 403 Forbidden\r\nServer: datasnapHTTPService\r\n\r\n",
200
+ );
181
201
  }
182
202
  });
183
203
  });
@@ -200,13 +220,19 @@ describe("Hub event tests", () => {
200
220
  },
201
221
  });
202
222
  tunnelStream = await toPromise((resolve) => {
203
- ss(socketsBySubdomain[subdomain]).once(uniqueId, (stream) => {
204
- pipeline(stream, outputStream, (err) => {
205
- if (err) console.error(err);
206
- });
207
- resolve(stream);
208
- });
209
- socketsBySubdomain[subdomain].emit("incomingClient", uniqueId);
223
+ ss(socketsBySubdomain[subdomain]).once(
224
+ uniqueId,
225
+ (stream) => {
226
+ pipeline(stream, outputStream, (err) => {
227
+ if (err) console.error(err);
228
+ });
229
+ resolve(stream);
230
+ },
231
+ );
232
+ socketsBySubdomain[subdomain].emit(
233
+ "incomingClient",
234
+ uniqueId,
235
+ );
210
236
  });
211
237
 
212
238
  tunnelStream.write(httpRawRequest);
@@ -224,10 +250,13 @@ describe("Hub event tests", () => {
224
250
  "Server: datasnapHTTPService\r\n" +
225
251
  "Access-Control-Expose-Headers: biza-cli-address, biza-hub-address\r\n" +
226
252
  "biza-cli-address: https://some.tunnel.url\r\n" +
227
- "biza-hub-address: https://some.hub.url\r\n\r\n"
253
+ "biza-hub-address: https://some.hub.url\r\n\r\n",
228
254
  );
229
255
 
230
- expect(await getResponse("POST /fail HTTP/1.1")).toBe("HTTP/1.1 403 Forbidden\r\n" + "Server: datasnapHTTPService\r\n\r\n");
256
+ expect(await getResponse("POST /fail HTTP/1.1")).toBe(
257
+ "HTTP/1.1 403 Forbidden\r\n" +
258
+ "Server: datasnapHTTPService\r\n\r\n",
259
+ );
231
260
  } finally {
232
261
  freeSocketClient(cliToBizAServerSocket);
233
262
  if (mockAPIServer) mockAPIServer.close();
@@ -255,16 +284,26 @@ describe("Hub event tests", () => {
255
284
  secure: false,
256
285
  dbindex: 2,
257
286
  cliAddress: () => {
258
- return { ip: "59.60.1.22", port: "3002", address: `59.60.1.22:3002`, publicUrl: "https://some.tunnel.url", hubUrl: "https://some.hub.url" };
287
+ return {
288
+ ip: "59.60.1.22",
289
+ port: "3002",
290
+ address: `59.60.1.22:3002`,
291
+ publicUrl: "https://some.tunnel.url",
292
+ hubUrl: "https://some.hub.url",
293
+ };
259
294
  },
260
295
  });
261
- clientToCliSocket = ioClient("http://localhost:9999", { query: { isClient: true } });
296
+ clientToCliSocket = ioClient("http://localhost:9999", {
297
+ query: { isClient: true },
298
+ });
262
299
  });
263
300
 
264
301
  afterAll(async () => {
265
302
  freeSocketClient(clientToCliSocket);
266
303
  if (cliSocketServer) {
267
- await cliSocketServer.of("").sockets.forEach((sock) => sock.removeAllListeners());
304
+ await cliSocketServer
305
+ .of("")
306
+ .sockets.forEach((sock) => sock.removeAllListeners());
268
307
  await cliSocketServer.close();
269
308
  }
270
309
  });
@@ -282,17 +321,28 @@ describe("Hub event tests", () => {
282
321
  const [error, response] = await toPromise((resolve) => {
283
322
  clientToCliSocket.emit(
284
323
  "apiRequest",
285
- { subDomain: subdomain, method: "POST", path: "/test", headers: { "req-header": "aa" }, body: "body of request", responseType: "json" },
324
+ {
325
+ subDomain: subdomain,
326
+ method: "POST",
327
+ path: "/test",
328
+ headers: { "req-header": "aa" },
329
+ body: "body of request",
330
+ responseType: "json",
331
+ },
286
332
  (err, res) => {
287
333
  resolve([err, res]);
288
- }
334
+ },
289
335
  );
290
336
  });
291
337
 
292
338
  expect(response).toStrictEqual({
293
339
  status: 200,
294
340
  statusText: "Success",
295
- headers: { "res-header": "aa", "biza-cli-address": "https://some.tunnel.url", "biza-hub-address": "https://some.hub.url" },
341
+ headers: {
342
+ "res-header": "aa",
343
+ "biza-cli-address": "https://some.tunnel.url",
344
+ "biza-hub-address": "https://some.hub.url",
345
+ },
296
346
  body: "body of response",
297
347
  url: `http://${apiAddress}:${port}/test`,
298
348
  });
@@ -337,7 +387,7 @@ describe("Hub event tests", () => {
337
387
  },
338
388
  (err, res) => {
339
389
  resolve([err, res]);
340
- }
390
+ },
341
391
  );
342
392
  });
343
393
 
@@ -362,10 +412,16 @@ describe("Hub event tests", () => {
362
412
  const [error, response] = await toPromise((resolve) => {
363
413
  clientToCliSocket.emit(
364
414
  "apiRequest",
365
- { subDomain: "wrong subdomain", method: "POST", path: "/test", headers: { "req-header": "aa" }, body: "body of request" },
415
+ {
416
+ subDomain: "wrong subdomain",
417
+ method: "POST",
418
+ path: "/test",
419
+ headers: { "req-header": "aa" },
420
+ body: "body of request",
421
+ },
366
422
  (err, res) => {
367
423
  resolve([err, res]);
368
- }
424
+ },
369
425
  );
370
426
  });
371
427
 
@@ -385,15 +441,24 @@ describe("Hub event tests", () => {
385
441
  test("status", async () => {
386
442
  const runCommand = async (command) => {
387
443
  return await toPromise((resolve) => {
388
- clientToCliSocket.emit("cliCommand", { command }, (err, res) => {
389
- resolve([err, res]);
390
- });
444
+ clientToCliSocket.emit(
445
+ "cliCommand",
446
+ { command },
447
+ (err, res) => {
448
+ resolve([err, res]);
449
+ },
450
+ );
391
451
  });
392
452
  };
393
453
 
394
454
  let [error, response] = await runCommand("StAtus ");
395
455
  const cpuArchitecture = os.arch();
396
- const osArchitecture = ["x64", "arm64", "ppc64", "s390x"].includes(cpuArchitecture)
456
+ const osArchitecture = [
457
+ "x64",
458
+ "arm64",
459
+ "ppc64",
460
+ "s390x",
461
+ ].includes(cpuArchitecture)
397
462
  ? "64-bit"
398
463
  : ["ia32", "arm", "mips", "mipsel", "s390"].includes(cpuArchitecture)
399
464
  ? "32-bit"
@@ -413,6 +478,9 @@ describe("Hub event tests", () => {
413
478
  minutes: expect.any(Number),
414
479
  seconds: expect.any(Number),
415
480
  }),
481
+ workers: {
482
+ cliScript: cliScriptWorkerPool.stats(),
483
+ },
416
484
  },
417
485
  api: {
418
486
  address: `${apiAddress}:${port}`,
@@ -424,7 +492,10 @@ describe("Hub event tests", () => {
424
492
  platform: os.platform(),
425
493
  cpuCount: os.cpus().length,
426
494
  memory: {
427
- total: (os.totalmem / (1024 * 1024 * 1024)).toFixed(2) + " GB",
495
+ total:
496
+ (os.totalmem / (1024 * 1024 * 1024)).toFixed(
497
+ 2,
498
+ ) + " GB",
428
499
  free: expect.any(String),
429
500
  used: expect.any(String),
430
501
  },
@@ -436,6 +507,154 @@ describe("Hub event tests", () => {
436
507
  expect(response).toBe(null);
437
508
  expect(error).toBe("Unknown CLI command 'invalid command'");
438
509
  });
510
+
511
+ describe("runCLIScript", () => {
512
+ const runCommand = () =>
513
+ toPromise((resolve) => {
514
+ clientToCliSocket.emit(
515
+ "cliCommand",
516
+ {
517
+ command: "runCliScript",
518
+ scriptName: "sumScript",
519
+ scriptData: { x: 1, y: 2 },
520
+ },
521
+ (err, res) => {
522
+ resolve([err, res]);
523
+ },
524
+ );
525
+ });
526
+
527
+ test("shall used worker pool", async () => {
528
+ expect(cliScriptWorkerPool.workerType).toBe("thread"); // used node.js worker thread
529
+ expect(cliScriptWorkerPool.workerThreadOpts).toStrictEqual({
530
+ env: { NODE_ENV: process.env.NODE_ENV },
531
+ });
532
+
533
+ const execSpy = jest.spyOn(cliScriptWorkerPool, "exec");
534
+
535
+ execSpy.mockResolvedValueOnce("success");
536
+ await expect(runCommand()).resolves.toStrictEqual([
537
+ null,
538
+ "success",
539
+ ]);
540
+ expect(execSpy.mock.calls.length).toBe(1);
541
+ expect(execSpy).toHaveBeenCalledWith("run", [
542
+ {
543
+ dbindex: 2,
544
+ subdomain,
545
+ url: `http://${apiAddress}:${port}`,
546
+ },
547
+ "sumScript",
548
+ { x: 1, y: 2 },
549
+ ]);
550
+ execSpy.mockReset();
551
+
552
+ execSpy.mockRejectedValueOnce("fail");
553
+ await expect(runCommand()).resolves.toStrictEqual([
554
+ "fail",
555
+ null,
556
+ ]);
557
+ expect(execSpy.mock.calls.length).toBe(1);
558
+ expect(execSpy).toHaveBeenCalledWith("run", [
559
+ {
560
+ dbindex: 2,
561
+ subdomain,
562
+ url: `http://${apiAddress}:${port}`,
563
+ },
564
+ "sumScript",
565
+ { x: 1, y: 2 },
566
+ ]);
567
+ execSpy.mockReset();
568
+
569
+ // process beforeexit can not be reliably triggered or handled as expected within Jest's test environment, especially in worker thread scenario
570
+ // so we trigger the function directly
571
+ const workerpoolBeforeExit = process
572
+ .listeners("beforeexit")
573
+ .find(
574
+ (listener) =>
575
+ listener
576
+ .toString()
577
+ .toLowerCase()
578
+ .indexOf("cliscriptworkerpool") !== -1,
579
+ );
580
+ expect(isAsyncFunction(workerpoolBeforeExit)).toBeTruthy();
581
+ const terminateSpy = jest.spyOn(
582
+ cliScriptWorkerPool,
583
+ "terminate",
584
+ );
585
+ terminateSpy.mockReset();
586
+ workerpoolBeforeExit();
587
+ expect(terminateSpy.mock.calls.length).toBe(1);
588
+ });
589
+
590
+ test("shall used worker thread", async () => {
591
+ let mockAPIServer;
592
+ let scriptWorkerPool;
593
+ try {
594
+ // cannot used jest mocking because worker thread is running in different context.
595
+ // We must create http mock server, then direct worker request to the mock server
596
+ mockAPIServer = createServer((req, res) => {
597
+ res.writeHead(200, {
598
+ "Content-Type": "application/json",
599
+ });
600
+ res.end(
601
+ JSON.stringify([
602
+ {
603
+ "SYS$CLI_SCRIPT.SCRIPT": `get = function (lib) {
604
+ return {
605
+ functions: {
606
+ onInit: function (data) {
607
+ return (data.x + data.y);
608
+ }
609
+ }
610
+ }
611
+ }`,
612
+ },
613
+ ]),
614
+ );
615
+ });
616
+ await toPromise((resolve) => {
617
+ mockAPIServer.listen(
618
+ { host: "127.0.0.1", port: 0 },
619
+ () => {
620
+ resolve();
621
+ },
622
+ );
623
+ });
624
+ scriptWorkerPool = workerpool.pool(
625
+ "./worker/cliScriptWorker.js",
626
+ {
627
+ workerType: "thread",
628
+ workerThreadOpts: {
629
+ env: { NODE_ENV: "production" },
630
+ },
631
+ },
632
+ ); // set worker NODE_ENV, so logger will not print to console
633
+ const sumResult = await scriptWorkerPool
634
+ .exec("run", [
635
+ {
636
+ dbindex: 2,
637
+ subdomain,
638
+ url: `http://127.0.0.1:${mockAPIServer.address().port}`,
639
+ },
640
+ "sumScript",
641
+ { x: 1, y: 2 },
642
+ ])
643
+ .then(async (result) => {
644
+ await scriptWorkerPool.terminate();
645
+ return result;
646
+ })
647
+ .catch((err) => {
648
+ return err.message || err;
649
+ });
650
+ expect(sumResult).toBe(3);
651
+ } finally {
652
+ if (mockAPIServer) {
653
+ mockAPIServer.close();
654
+ }
655
+ }
656
+ });
657
+ });
439
658
  });
440
659
  });
441
660
 
@@ -472,9 +691,11 @@ describe("Hub event tests", () => {
472
691
  },
473
692
  (hubUrl) => {
474
693
  expect(hubUrl).toBe("https://some.hub.url");
475
- }
694
+ },
695
+ );
696
+ await toPromise((resolve) =>
697
+ cliToHubSocket.once("connect", () => resolve()),
476
698
  );
477
- await toPromise((resolve) => cliToHubSocket.once("connect", () => resolve()));
478
699
  });
479
700
 
480
701
  afterAll(async () => {
@@ -489,10 +710,17 @@ describe("Hub event tests", () => {
489
710
  const [error, response] = await toPromise((resolve) => {
490
711
  hubToCLISocket.emit(
491
712
  "apiRequest",
492
- { subDomain: subdomain, method: "POST", path: "/test", headers: { "req-header": "aa" }, body: reqData, responseType: "json" },
713
+ {
714
+ subDomain: subdomain,
715
+ method: "POST",
716
+ path: "/test",
717
+ headers: { "req-header": "aa" },
718
+ body: reqData,
719
+ responseType: "json",
720
+ },
493
721
  (err, res) => {
494
722
  resolve([err, res]);
495
- }
723
+ },
496
724
  );
497
725
  });
498
726
  return { error, response };
@@ -513,7 +741,11 @@ describe("Hub event tests", () => {
513
741
  expect(result.response).toStrictEqual({
514
742
  status: 200,
515
743
  statusText: "Success",
516
- headers: { "res-header": "aa", "biza-cli-address": "https://some.tunnel.url", "biza-hub-address": "https://some.hub.url" },
744
+ headers: {
745
+ "res-header": "aa",
746
+ "biza-cli-address": "https://some.tunnel.url",
747
+ "biza-hub-address": "https://some.hub.url",
748
+ },
517
749
  body: "body of response",
518
750
  url: `http://127.0.0.1:${port}/test`,
519
751
  });
@@ -531,11 +763,20 @@ describe("Hub event tests", () => {
531
763
 
532
764
  // parameterize API address as String
533
765
  mockedRequest.mockClear();
534
- result = await emitApiRequest(JSON.stringify({ other: "data", apiAddress: "http://apiHost:apiPort" }));
766
+ result = await emitApiRequest(
767
+ JSON.stringify({
768
+ other: "data",
769
+ apiAddress: "http://apiHost:apiPort",
770
+ }),
771
+ );
535
772
  expect(result.response).toStrictEqual({
536
773
  status: 200,
537
774
  statusText: "Success",
538
- headers: { "res-header": "aa", "biza-cli-address": "https://some.tunnel.url", "biza-hub-address": "https://some.hub.url" },
775
+ headers: {
776
+ "res-header": "aa",
777
+ "biza-cli-address": "https://some.tunnel.url",
778
+ "biza-hub-address": "https://some.hub.url",
779
+ },
539
780
  body: "body of response",
540
781
  url: "http://apiHost:apiPort/test",
541
782
  });
@@ -553,11 +794,18 @@ describe("Hub event tests", () => {
553
794
 
554
795
  // parameterize API address as Object
555
796
  mockedRequest.mockClear();
556
- result = await emitApiRequest({ other: "data", apiAddress: "http://apiHost:apiPort" });
797
+ result = await emitApiRequest({
798
+ other: "data",
799
+ apiAddress: "http://apiHost:apiPort",
800
+ });
557
801
  expect(result.response).toStrictEqual({
558
802
  status: 200,
559
803
  statusText: "Success",
560
- headers: { "res-header": "aa", "biza-cli-address": "https://some.tunnel.url", "biza-hub-address": "https://some.hub.url" },
804
+ headers: {
805
+ "res-header": "aa",
806
+ "biza-cli-address": "https://some.tunnel.url",
807
+ "biza-hub-address": "https://some.hub.url",
808
+ },
561
809
  body: "body of response",
562
810
  url: "http://apiHost:apiPort/test",
563
811
  });
@@ -578,17 +826,28 @@ describe("Hub event tests", () => {
578
826
  test("status", async () => {
579
827
  const runCommand = async (command) => {
580
828
  return await toPromise((resolve) => {
581
- hubToCLISocket.emit("cliCommand", { command }, (err, res) => {
582
- resolve([err, res]);
583
- });
829
+ hubToCLISocket.emit(
830
+ "cliCommand",
831
+ { command },
832
+ (err, res) => {
833
+ resolve([err, res]);
834
+ },
835
+ );
584
836
  });
585
837
  };
586
838
 
587
839
  let [error, response] = await runCommand("StAtus ");
588
840
  const cpuArchitecture = os.arch();
589
- const osArchitecture = ["x64", "arm64", "ppc64", "s390x"].includes(cpuArchitecture)
841
+ const osArchitecture = [
842
+ "x64",
843
+ "arm64",
844
+ "ppc64",
845
+ "s390x",
846
+ ].includes(cpuArchitecture)
590
847
  ? "64-bit"
591
- : ["ia32", "arm", "mips", "mipsel", "s390"].includes(cpuArchitecture)
848
+ : ["ia32", "arm", "mips", "mipsel", "s390"].includes(
849
+ cpuArchitecture,
850
+ )
592
851
  ? "32-bit"
593
852
  : `Unknown CPU architecture: ${cpuArchitecture}`;
594
853
  expect(response).toMatchObject({
@@ -606,6 +865,9 @@ describe("Hub event tests", () => {
606
865
  minutes: expect.any(Number),
607
866
  seconds: expect.any(Number),
608
867
  }),
868
+ workers: {
869
+ cliScript: cliScriptWorkerPool.stats(),
870
+ },
609
871
  },
610
872
  api: {
611
873
  address: `${apiAddress}:${port}`,
@@ -617,7 +879,10 @@ describe("Hub event tests", () => {
617
879
  platform: os.platform(),
618
880
  cpuCount: os.cpus().length,
619
881
  memory: {
620
- total: (os.totalmem / (1024 * 1024 * 1024)).toFixed(2) + " GB",
882
+ total:
883
+ (os.totalmem / (1024 * 1024 * 1024)).toFixed(
884
+ 2,
885
+ ) + " GB",
621
886
  free: expect.any(String),
622
887
  used: expect.any(String),
623
888
  },
@@ -629,6 +894,82 @@ describe("Hub event tests", () => {
629
894
  expect(response).toBe(null);
630
895
  expect(error).toBe("Unknown CLI command 'invalid command'");
631
896
  });
897
+
898
+ describe("runCLIScript", () => {
899
+ test("shall used worker pool", async () => {
900
+ expect(cliScriptWorkerPool.workerType).toBe("thread"); // used node.js worker thread
901
+
902
+ const execSpy = jest.spyOn(cliScriptWorkerPool, "exec");
903
+ const runCommand = () =>
904
+ toPromise((resolve) => {
905
+ hubToCLISocket.emit(
906
+ "cliCommand",
907
+ {
908
+ command: "runCliScript",
909
+ scriptName: "sumScript",
910
+ scriptData: { x: 1, y: 2 },
911
+ },
912
+ (err, res) => {
913
+ resolve([err, res]);
914
+ },
915
+ );
916
+ });
917
+
918
+ execSpy.mockResolvedValueOnce("success");
919
+ await expect(runCommand()).resolves.toStrictEqual([
920
+ null,
921
+ "success",
922
+ ]);
923
+ expect(execSpy.mock.calls.length).toBe(1);
924
+ expect(execSpy).toHaveBeenCalledWith("run", [
925
+ {
926
+ dbindex: 2,
927
+ subdomain,
928
+ url: `http://${apiAddress}:${port}`,
929
+ },
930
+ "sumScript",
931
+ { x: 1, y: 2 },
932
+ ]);
933
+ execSpy.mockReset();
934
+
935
+ execSpy.mockRejectedValueOnce("fail");
936
+ await expect(runCommand()).resolves.toStrictEqual([
937
+ "fail",
938
+ null,
939
+ ]);
940
+ expect(execSpy.mock.calls.length).toBe(1);
941
+ expect(execSpy).toHaveBeenCalledWith("run", [
942
+ {
943
+ dbindex: 2,
944
+ subdomain,
945
+ url: `http://${apiAddress}:${port}`,
946
+ },
947
+ "sumScript",
948
+ { x: 1, y: 2 },
949
+ ]);
950
+ execSpy.mockReset();
951
+
952
+ // process beforeexit can not be reliably triggered or handled as expected within Jest's test environment, especially in worker thread scenario
953
+ // so we trigger the function directly
954
+ const terminateSpy = jest.spyOn(
955
+ cliScriptWorkerPool,
956
+ "terminate",
957
+ );
958
+ const workerpoolBeforeExit = process
959
+ .listeners("beforeexit")
960
+ .find(
961
+ (listener) =>
962
+ listener
963
+ .toString()
964
+ .toLowerCase()
965
+ .indexOf("cliscriptworkerpool") !== -1,
966
+ );
967
+ expect(isAsyncFunction(workerpoolBeforeExit)).toBeTruthy();
968
+ terminateSpy.mockReset();
969
+ workerpoolBeforeExit();
970
+ expect(terminateSpy.mock.calls.length).toBe(1);
971
+ });
972
+ });
632
973
  });
633
974
  });
634
975