simple-test.ts 5.5 KB

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