chore(tests): add tests for worker-executor
This commit is contained in:
committed by
mrugesh mohapatra
parent
845b966bda
commit
80eaccc467
237
client/src/templates/Challenges/utils/worker-executor.test.js
Normal file
237
client/src/templates/Challenges/utils/worker-executor.test.js
Normal file
@@ -0,0 +1,237 @@
|
||||
/* global expect, jest */
|
||||
|
||||
import createWorker from './worker-executor';
|
||||
|
||||
function mockWorker({ init, postMessage, terminate } = {}) {
|
||||
global.Worker = jest.fn(function() {
|
||||
setImmediate(
|
||||
(init && init(this)) ||
|
||||
(() =>
|
||||
this.onmessage && this.onmessage({ data: { type: 'contentLoaded' } }))
|
||||
);
|
||||
this.onmessage = null;
|
||||
this.postMessage =
|
||||
postMessage ||
|
||||
function(data) {
|
||||
setImmediate(
|
||||
() => this.onmessage && this.onmessage({ data: `${data} processed` })
|
||||
);
|
||||
};
|
||||
this.terminate = terminate || (() => {});
|
||||
return this;
|
||||
});
|
||||
}
|
||||
|
||||
afterEach(() => {
|
||||
delete global.Worker;
|
||||
});
|
||||
|
||||
it('Worker executor should successfully execute one task', async () => {
|
||||
const terminateHandler = jest.fn();
|
||||
mockWorker({ terminate: terminateHandler });
|
||||
const testWorker = createWorker('test');
|
||||
expect(testWorker).not.toBeUndefined();
|
||||
|
||||
const task = testWorker.execute('test');
|
||||
expect(task).not.toBeUndefined();
|
||||
expect(task.done).not.toBeUndefined();
|
||||
const handler = jest.fn();
|
||||
task.on('done', handler);
|
||||
const errorHandler = jest.fn();
|
||||
task.on('error', errorHandler);
|
||||
|
||||
await expect(task.done).resolves.toBe('test processed');
|
||||
|
||||
expect(handler).toBeCalledTimes(1);
|
||||
expect(handler).toBeCalledWith('test processed');
|
||||
|
||||
expect(errorHandler).not.toBeCalled();
|
||||
expect(terminateHandler).not.toBeCalled();
|
||||
|
||||
expect(global.Worker).toBeCalledTimes(1);
|
||||
expect(global.Worker).toBeCalledWith('/js/test.js');
|
||||
});
|
||||
|
||||
// eslint-disable-next-line max-len
|
||||
it('Worker executor should successfully execute two tasks in parallel', async () => {
|
||||
const terminateHandler = jest.fn();
|
||||
mockWorker({ terminate: terminateHandler });
|
||||
const testWorker = createWorker('test');
|
||||
|
||||
const task1 = testWorker.execute('test1');
|
||||
const handler1 = jest.fn();
|
||||
task1.on('done', handler1);
|
||||
const errorHandler1 = jest.fn();
|
||||
task1.on('error', errorHandler1);
|
||||
|
||||
const task2 = testWorker.execute('test2');
|
||||
const handler2 = jest.fn();
|
||||
task2.on('done', handler2);
|
||||
const errorHandler2 = jest.fn();
|
||||
task2.on('error', errorHandler2);
|
||||
|
||||
await expect(Promise.all([task1.done, task2.done])).resolves.toEqual([
|
||||
'test1 processed',
|
||||
'test2 processed'
|
||||
]);
|
||||
|
||||
expect(handler1).toBeCalledTimes(1);
|
||||
expect(handler1).toBeCalledWith('test1 processed');
|
||||
expect(errorHandler1).not.toBeCalled();
|
||||
|
||||
expect(handler2).toBeCalledTimes(1);
|
||||
expect(handler2).toBeCalledWith('test2 processed');
|
||||
expect(errorHandler2).not.toBeCalled();
|
||||
expect(terminateHandler).not.toBeCalled();
|
||||
|
||||
expect(global.Worker).toBeCalledTimes(2);
|
||||
});
|
||||
|
||||
// eslint-disable-next-line max-len
|
||||
it('Worker executor should successfully execute 3 tasks in parallel and use two workers', async () => {
|
||||
mockWorker();
|
||||
const testWorker = createWorker('test');
|
||||
|
||||
const task1 = testWorker.execute('test1');
|
||||
const task2 = testWorker.execute('test2');
|
||||
const task3 = testWorker.execute('test3');
|
||||
await expect(
|
||||
Promise.all([task1.done, task2.done, task3.done])
|
||||
).resolves.toEqual(['test1 processed', 'test2 processed', 'test3 processed']);
|
||||
|
||||
expect(global.Worker).toBeCalledTimes(2);
|
||||
});
|
||||
|
||||
// eslint-disable-next-line max-len
|
||||
it('Worker executor should successfully execute 3 tasks, use 3 workers and terminate each worker', async () => {
|
||||
const terminateHandler = jest.fn();
|
||||
mockWorker({ terminate: terminateHandler });
|
||||
const testWorker = createWorker('test', { terminateWorker: true });
|
||||
|
||||
const task1 = testWorker.execute('test1');
|
||||
const task2 = testWorker.execute('test2');
|
||||
const task3 = testWorker.execute('test3');
|
||||
await expect(
|
||||
Promise.all([task1.done, task2.done, task3.done])
|
||||
).resolves.toEqual(['test1 processed', 'test2 processed', 'test3 processed']);
|
||||
|
||||
expect(terminateHandler).toBeCalledTimes(3);
|
||||
expect(global.Worker).toBeCalledTimes(3);
|
||||
});
|
||||
|
||||
// eslint-disable-next-line max-len
|
||||
it('Worker executor should successfully execute 3 tasks in parallel and use 3 workers', async () => {
|
||||
mockWorker();
|
||||
const testWorker = createWorker('test', { concurrency: 3 });
|
||||
|
||||
const task1 = testWorker.execute('test1');
|
||||
const task2 = testWorker.execute('test2');
|
||||
const task3 = testWorker.execute('test3');
|
||||
await expect(
|
||||
Promise.all([task1.done, task2.done, task3.done])
|
||||
).resolves.toEqual(['test1 processed', 'test2 processed', 'test3 processed']);
|
||||
|
||||
expect(global.Worker).toBeCalledTimes(3);
|
||||
});
|
||||
|
||||
// eslint-disable-next-line max-len
|
||||
it('Worker executor should successfully execute 3 tasks and use 1 worker', async () => {
|
||||
mockWorker();
|
||||
const testWorker = createWorker('test', { concurrency: 1 });
|
||||
|
||||
const task1 = testWorker.execute('test1');
|
||||
const task2 = testWorker.execute('test2');
|
||||
const task3 = testWorker.execute('test3');
|
||||
await expect(
|
||||
Promise.all([task1.done, task2.done, task3.done])
|
||||
).resolves.toEqual(['test1 processed', 'test2 processed', 'test3 processed']);
|
||||
|
||||
expect(global.Worker).toBeCalledTimes(1);
|
||||
});
|
||||
|
||||
it('Worker executor should reject task', async () => {
|
||||
const error = { message: 'Error on init worker' };
|
||||
mockWorker({
|
||||
init: () => {
|
||||
throw error;
|
||||
}
|
||||
});
|
||||
const testWorker = createWorker('test');
|
||||
|
||||
const task = testWorker.execute('test');
|
||||
const errorHandler = jest.fn();
|
||||
task.on('error', errorHandler);
|
||||
await expect(task.done).rejects.toBe(error.message);
|
||||
|
||||
expect(errorHandler).toBeCalledTimes(1);
|
||||
expect(errorHandler).toBeCalledWith(error);
|
||||
});
|
||||
|
||||
it('Worker executor should emit LOG events', async () => {
|
||||
mockWorker({
|
||||
postMessage: function(data) {
|
||||
setImmediate(() => {
|
||||
for (let i = 0; i < 3; i++) {
|
||||
// eslint-disable-next-line no-unused-expressions
|
||||
this.onmessage && this.onmessage({ data: { type: 'LOG', data: i } });
|
||||
}
|
||||
// eslint-disable-next-line no-unused-expressions
|
||||
this.onmessage && this.onmessage({ data: `${data} processed` });
|
||||
setImmediate(
|
||||
() =>
|
||||
this.onmessage && this.onmessage({ data: { type: 'LOG', data: 3 } })
|
||||
);
|
||||
});
|
||||
}
|
||||
});
|
||||
const testWorker = createWorker('test');
|
||||
|
||||
const task = testWorker.execute('test');
|
||||
const handler = jest.fn();
|
||||
task.on('done', handler);
|
||||
const errorHandler = jest.fn();
|
||||
task.on('error', errorHandler);
|
||||
const logHandler = jest.fn();
|
||||
task.on('LOG', logHandler);
|
||||
|
||||
await expect(task.done).resolves.toBe('test processed');
|
||||
|
||||
expect(handler).toBeCalledTimes(1);
|
||||
expect(handler).toBeCalledWith('test processed');
|
||||
expect(errorHandler).not.toBeCalled();
|
||||
|
||||
expect(logHandler).toBeCalledTimes(3);
|
||||
for (let i = 0; i < 3; i++) {
|
||||
expect(logHandler.mock.calls[i][0]).toBe(i);
|
||||
}
|
||||
});
|
||||
|
||||
it('Worker executor should reject task on timeout', async () => {
|
||||
const terminateHandler = jest.fn();
|
||||
mockWorker({
|
||||
postMessage: () => {},
|
||||
terminate: terminateHandler
|
||||
});
|
||||
const testWorker = createWorker('test');
|
||||
|
||||
const task = testWorker.execute('test', 0);
|
||||
const errorHandler = jest.fn();
|
||||
task.on('error', errorHandler);
|
||||
await expect(task.done).rejects.toBe('timeout');
|
||||
|
||||
expect(errorHandler).toBeCalledTimes(1);
|
||||
expect(errorHandler.mock.calls[0][0]).toEqual({ message: 'timeout' });
|
||||
|
||||
expect(terminateHandler).toBeCalledTimes(1);
|
||||
});
|
||||
|
||||
it('Worker executor should get worker from specified location', async () => {
|
||||
mockWorker();
|
||||
const testWorker = createWorker('test', { location: '/other/location/' });
|
||||
|
||||
const task = testWorker.execute('test');
|
||||
await expect(task.done).resolves.toBe('test processed');
|
||||
|
||||
expect(global.Worker).toBeCalledTimes(1);
|
||||
expect(global.Worker).toBeCalledWith('/other/location/test.js');
|
||||
});
|
Reference in New Issue
Block a user