1 | import Piscina from '..';
|
---|
2 | import { test } from 'tap';
|
---|
3 | import { version } from '../package.json';
|
---|
4 | import { pathToFileURL } from 'url';
|
---|
5 | import { resolve } from 'path';
|
---|
6 | import { EventEmitter } from 'events';
|
---|
7 |
|
---|
8 | test('Piscina is exposed on export', async ({ equal }) => {
|
---|
9 | equal(Piscina.version, version);
|
---|
10 | });
|
---|
11 |
|
---|
12 | test('Piscina is exposed on itself', async ({ equal }) => {
|
---|
13 | equal(Piscina.Piscina, Piscina);
|
---|
14 | });
|
---|
15 |
|
---|
16 | test('Piscina.isWorkerThread has the correct value', async ({ equal }) => {
|
---|
17 | equal(Piscina.isWorkerThread, false);
|
---|
18 | });
|
---|
19 |
|
---|
20 | test('Piscina.isWorkerThread has the correct value (worker)', async ({ equal }) => {
|
---|
21 | const worker = new Piscina({
|
---|
22 | filename: resolve(__dirname, 'fixtures/simple-isworkerthread.ts')
|
---|
23 | });
|
---|
24 | const result = await worker.runTask(null);
|
---|
25 | equal(result, 'done');
|
---|
26 | });
|
---|
27 |
|
---|
28 | test('Piscina instance is an EventEmitter', async ({ ok }) => {
|
---|
29 | const piscina = new Piscina();
|
---|
30 | ok(piscina instanceof EventEmitter);
|
---|
31 | });
|
---|
32 |
|
---|
33 | test('Piscina constructor options are correctly set', async ({ equal }) => {
|
---|
34 | const piscina = new Piscina({
|
---|
35 | minThreads: 10,
|
---|
36 | maxThreads: 20,
|
---|
37 | maxQueue: 30
|
---|
38 | });
|
---|
39 |
|
---|
40 | equal(piscina.options.minThreads, 10);
|
---|
41 | equal(piscina.options.maxThreads, 20);
|
---|
42 | equal(piscina.options.maxQueue, 30);
|
---|
43 | });
|
---|
44 |
|
---|
45 | test('trivial eval() handler works', async ({ equal }) => {
|
---|
46 | const worker = new Piscina({
|
---|
47 | filename: resolve(__dirname, 'fixtures/eval.js')
|
---|
48 | });
|
---|
49 | const result = await worker.runTask('42');
|
---|
50 | equal(result, 42);
|
---|
51 | });
|
---|
52 |
|
---|
53 | test('async eval() handler works', async ({ equal }) => {
|
---|
54 | const worker = new Piscina({
|
---|
55 | filename: resolve(__dirname, 'fixtures/eval.js')
|
---|
56 | });
|
---|
57 | const result = await worker.runTask('Promise.resolve(42)');
|
---|
58 | equal(result, 42);
|
---|
59 | });
|
---|
60 |
|
---|
61 | test('filename can be provided while posting', async ({ equal }) => {
|
---|
62 | const worker = new Piscina();
|
---|
63 | const result = await worker.runTask(
|
---|
64 | 'Promise.resolve(42)',
|
---|
65 | resolve(__dirname, 'fixtures/eval.js'));
|
---|
66 | equal(result, 42);
|
---|
67 | });
|
---|
68 |
|
---|
69 | test('filename can be null when initially provided', async ({ equal }) => {
|
---|
70 | const worker = new Piscina({ filename: null });
|
---|
71 | const result = await worker.runTask(
|
---|
72 | 'Promise.resolve(42)',
|
---|
73 | resolve(__dirname, 'fixtures/eval.js'));
|
---|
74 | equal(result, 42);
|
---|
75 | });
|
---|
76 |
|
---|
77 | test('filename must be provided while posting', async ({ rejects }) => {
|
---|
78 | const worker = new Piscina();
|
---|
79 | rejects(worker.runTask('doesn’t matter'),
|
---|
80 | /filename must be provided to run\(\) or in options object/);
|
---|
81 | });
|
---|
82 |
|
---|
83 | test('passing env to workers works', async ({ same }) => {
|
---|
84 | const pool = new Piscina({
|
---|
85 | filename: resolve(__dirname, 'fixtures/eval.js'),
|
---|
86 | env: { A: 'foo' }
|
---|
87 | });
|
---|
88 |
|
---|
89 | const env = await pool.runTask('({...process.env})');
|
---|
90 | same(env, { A: 'foo' });
|
---|
91 | });
|
---|
92 |
|
---|
93 | test('passing argv to workers works', async ({ same }) => {
|
---|
94 | const pool = new Piscina({
|
---|
95 | filename: resolve(__dirname, 'fixtures/eval.js'),
|
---|
96 | argv: ['a', 'b', 'c']
|
---|
97 | });
|
---|
98 |
|
---|
99 | const env = await pool.runTask('process.argv.slice(2)');
|
---|
100 | same(env, ['a', 'b', 'c']);
|
---|
101 | });
|
---|
102 |
|
---|
103 | test('passing execArgv to workers works', async ({ same }) => {
|
---|
104 | const pool = new Piscina({
|
---|
105 | filename: resolve(__dirname, 'fixtures/eval.js'),
|
---|
106 | execArgv: ['--no-warnings']
|
---|
107 | });
|
---|
108 |
|
---|
109 | const env = await pool.runTask('process.execArgv');
|
---|
110 | same(env, ['--no-warnings']);
|
---|
111 | });
|
---|
112 |
|
---|
113 | test('passing valid workerData works', async ({ equal }) => {
|
---|
114 | const pool = new Piscina({
|
---|
115 | filename: resolve(__dirname, 'fixtures/simple-workerdata.ts'),
|
---|
116 | workerData: 'ABC'
|
---|
117 | });
|
---|
118 | equal(Piscina.workerData, undefined);
|
---|
119 |
|
---|
120 | await pool.runTask(null);
|
---|
121 | });
|
---|
122 |
|
---|
123 | test('passing invalid workerData does not work', async ({ throws }) => {
|
---|
124 | throws(() => new Piscina(({
|
---|
125 | filename: resolve(__dirname, 'fixtures/simple-workerdata.ts'),
|
---|
126 | workerData: process.env
|
---|
127 | }) as any), /Cannot transfer object of unsupported type./);
|
---|
128 | });
|
---|
129 |
|
---|
130 | test('filename can be a file:// URL', async ({ equal }) => {
|
---|
131 | const worker = new Piscina({
|
---|
132 | filename: pathToFileURL(resolve(__dirname, 'fixtures/eval.js')).href
|
---|
133 | });
|
---|
134 | const result = await worker.runTask('42');
|
---|
135 | equal(result, 42);
|
---|
136 | });
|
---|
137 |
|
---|
138 | test('filename can be a file:// URL to an ESM module', {}, async ({ equal }) => {
|
---|
139 | const worker = new Piscina({
|
---|
140 | filename: pathToFileURL(resolve(__dirname, 'fixtures/esm-export.mjs')).href
|
---|
141 | });
|
---|
142 | const result = await worker.runTask('42');
|
---|
143 | equal(result, 42);
|
---|
144 | });
|
---|
145 |
|
---|
146 | test('duration and utilization calculations work', async ({ equal, ok }) => {
|
---|
147 | const worker = new Piscina({
|
---|
148 | filename: resolve(__dirname, 'fixtures/eval.js')
|
---|
149 | });
|
---|
150 |
|
---|
151 | // Initial utilization is always 0
|
---|
152 | equal(worker.utilization, 0);
|
---|
153 |
|
---|
154 | await Promise.all([
|
---|
155 | worker.runTask('42'),
|
---|
156 | worker.runTask('41'),
|
---|
157 | worker.runTask('40')
|
---|
158 | ]);
|
---|
159 |
|
---|
160 | // utilization is going to be some non-deterministic value
|
---|
161 | // between 0 and 1. It should not be zero at this point
|
---|
162 | // because tasks have run, but it should also never be 1
|
---|
163 | ok(worker.utilization > 0);
|
---|
164 | ok(worker.utilization < 1);
|
---|
165 |
|
---|
166 | // Duration must be non-zero.
|
---|
167 | ok(worker.duration > 0);
|
---|
168 | });
|
---|
169 |
|
---|
170 | test('run works also', async () => {
|
---|
171 | const worker = new Piscina({
|
---|
172 | filename: resolve(__dirname, 'fixtures/eval.js')
|
---|
173 | });
|
---|
174 |
|
---|
175 | await worker.run(42);
|
---|
176 | });
|
---|
177 |
|
---|
178 | test('named tasks work', async ({ equal }) => {
|
---|
179 | const worker = new Piscina({
|
---|
180 | filename: resolve(__dirname, 'fixtures/multiple.js')
|
---|
181 | });
|
---|
182 |
|
---|
183 | equal(await worker.run({}, { name: 'a' }), 'a');
|
---|
184 | equal(await worker.run({}, { name: 'b' }), 'b');
|
---|
185 | equal(await worker.run({}), 'a');
|
---|
186 | });
|
---|
187 |
|
---|
188 | test('named tasks work', async ({ equal }) => {
|
---|
189 | const worker = new Piscina({
|
---|
190 | filename: resolve(__dirname, 'fixtures/multiple.js'),
|
---|
191 | name: 'b'
|
---|
192 | });
|
---|
193 |
|
---|
194 | equal(await worker.run({}, { name: 'a' }), 'a');
|
---|
195 | equal(await worker.run({}, { name: 'b' }), 'b');
|
---|
196 | equal(await worker.run({}), 'b');
|
---|
197 | });
|
---|