Skip to content

Commit

Permalink
executor will no longer accept duplicate ids
Browse files Browse the repository at this point in the history
  • Loading branch information
Idrinth committed Aug 16, 2020
1 parent 6865f46 commit c76f044
Show file tree
Hide file tree
Showing 6 changed files with 231 additions and 68 deletions.
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "@idrinth/api-bench",
"description": "A library to benchmark apis, no matter if rest or soap",
"license": "MIT",
"version": "1.2.2",
"version": "1.2.3",
"homepage": "https://github.com/Idrinth/api-bench",
"repository": {
"type": "git",
Expand Down
5 changes: 2 additions & 3 deletions src/executor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import {
} from './logger/logger';
import Reporter from './reporter/reporter';
import * as Progress from 'cli-progress';
import validateTasks from './validate-tasks';

const EMPTY = 0;

Expand All @@ -43,9 +44,7 @@ const executor = (
logger: Logger,
Worker: WorkerConstructor,
): void => {
if (tasks.length === 0 || repetitions < 1 || threads < 1) {
throw new Error("Can't measure no tasks.");
}
validateTasks(repetitions, threads, tasks,);
const validator: Thread = new Worker('./worker/validator.js',);
const calculator: Thread = new Worker('./worker/calculator.js',);
const bar = new Progress.SingleBar({
Expand Down
33 changes: 33 additions & 0 deletions src/validate-tasks.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import {
Task,
} from './task';

const EMPTY = 0;

const noDuplicateIDs = (tasks: Array<Task>,) => {
const ids: Array<string> = [];
for (const task of tasks) {
if (ids.includes(task.id,)) {
throw new Error(`The id ${ task.id } is shared.`,);
}
ids.push(task.id,);
}
};
const executableAmount = (
repetitions: number,
threads: number,
tasks: Array<Task>,
): void => {
if (tasks.length === EMPTY || repetitions <= EMPTY || threads <= EMPTY) {
throw new Error('Can\'t measure no tasks.',);
}
};

export default function validateTasks(
repetitions: number,
threads: number,
tasks: Array<Task>,
): void {
executableAmount(repetitions, threads, tasks,);
noDuplicateIDs(tasks,);
}
203 changes: 140 additions & 63 deletions test/executor.ts
Original file line number Diff line number Diff line change
@@ -1,97 +1,174 @@
import executor, { Thread } from '../src/executor';
import executor, {
Thread,
} from '../src/executor';
import {
expect,
} from 'chai';
import 'mocha';
import { NullLogger } from '../src/logger/null-logger';
import { Result } from '../src/result';
import { ResultSet } from '../src/result-set';
import { FinishedSet } from '../src/finished-set';
import { PinoWrapper } from '../src/logger/pino-wrapper';
import { Task } from '../src/task';
const pino = require('pino',);

class FakeResult implements Result,ResultSet,FinishedSet {
import {
NullLogger,
} from '../src/logger/null-logger';
import {
Result,
} from '../src/result';
import {
FinishedSet,
} from '../src/finished-set';
import {
Task,
} from '../src/task';
import {
ValidationResult,
} from '../src/validation-result';

// eslint-disable-next-line @typescript-eslint/no-empty-function
const NOOP = () => {};
const NONE = 0;

class FakeResult implements Result, ValidationResult, FinishedSet {

public duration;

public id = 'some-id';
public errors = 1;
public count = 0;
public avg100 = 9;
public median100 = 9;
public max100 = 9;
public min100 = 9;
public avg80 = 9;
public median80 = 9;
public max80 = 9;
public min80 = 9;
public duration = 9;

public errors: number;

public count: number;

public avg100: number;

public median100: number;

public max100: number;

public min100: number;

public avg80: number;

public median80: number;

public max80: number;

public min80: number;

public response = {
headers: {},
cookies: {},
body: '',
uri: '',
status: 202,
};

public validators = [];
public durations = [9];

public durations;

public msgs = {};

success = true;

public constructor() {
const requests = 1;
this.errors = requests;
this.count = requests;
const duration = 9;
this.duration = duration;
this.avg100 = duration;
this.avg80 = duration;
this.durations = [ duration, ];
this.max100 = duration;
this.max80 = duration;
this.min100 = duration;
this.min80 = duration;
this.median100 = duration;
this.median80 = duration;
}

public add() {
this.count++;
};
};
this.count ++;
}
}
class FakeWorker implements Thread {
private handler;

public static built = {};

public static terminated = {};

private result = new FakeResult();
public constructor(private path: string)
{
FakeWorker.built[path] = FakeWorker.built[path] || 0;
FakeWorker.built[path]++;

public constructor(private path: string,) {
FakeWorker.built[path] = FakeWorker.built[path] || NONE;
FakeWorker.built[path] ++;
}
public on(type: string, callable: (a: unknown)=>void): void
{

public on(type: string, callable: (a: unknown)=>void,): void {
this.handler = callable;
}
public postMessage(a: unknown): void {

// eslint-disable-next-line @typescript-eslint/no-unused-vars
public postMessage(a: unknown,): void {
const c = this.handler;
const result = this.result;
setTimeout(() => c(result), 1);
const next = 1;
setTimeout(() => c(result,), next,);
}
public terminate(): void
{
FakeWorker.terminated[this.path] = FakeWorker.terminated[this.path] || 0;
FakeWorker.terminated[this.path]++;

public terminate(): void {
FakeWorker.terminated[this.path] = FakeWorker.terminated[this.path] || NONE;
FakeWorker.terminated[this.path] ++;
}
}

describe('executor', () => {
const repeats = 2;
const threads = 3;
const tasks = [ <Task> {
id: 'test',
}, ];
const once = 1;
it('should be a function', () => {
expect(executor,).to.be.a('function',);
},);
it ('should not try to execute no tasks(0 tasks)', () => {
expect(() => executor(3, 2, [], () => {}, new NullLogger(), FakeWorker)).to.throw("Can't measure no tasks.");
});
it ('should not try to execute no tasks(0 repeats)', () => {
expect(() => executor(0, 2, [<Task> {id: 'test'}], () => {}, new NullLogger(), FakeWorker)).to.throw("Can't measure no tasks.");
});
it ('should not try to execute no tasks (0 threads)', () => {
expect(() => executor(3, 0, [<Task> {id: 'test'}], () => {}, new NullLogger(), FakeWorker)).to.throw("Can't measure no tasks.");
});
it ('should execute all tasks', (done) => {
executor(3, 2, [<Task> {id: 'test'}], () => done(), new NullLogger(), FakeWorker);
});
it ('should have build the right workers', () => {
expect(FakeWorker.built).to.deep.equal({
"./worker/calculator.js": 1,
"./worker/validator.js": 1,
"./worker/webrequest.js": 3,
});
});
it ('should have shut down the right workers', () => {
expect(FakeWorker.terminated).to.deep.equal({
"./worker/calculator.js": 1,
"./worker/validator.js": 1,
"./worker/webrequest.js": 3,
});
});
it('should not try to execute no tasks(0 tasks)', () => {
expect(
() => executor(threads, repeats, [], NOOP, new NullLogger(), FakeWorker,),
).to.throw('Can\'t measure no tasks.',);
},);
it('should not try to execute no tasks(0 threads)', () => {
expect(
() => executor(NONE, repeats, tasks, NOOP, new NullLogger(), FakeWorker,),
).to.throw('Can\'t measure no tasks.',);
},);
it('should not try to execute no tasks (0 repeats)', () => {
expect(
() => executor(threads, NONE, tasks, NOOP, new NullLogger(), FakeWorker,),
).to.throw('Can\'t measure no tasks.',);
},);
it('should execute all tasks', (done,) => {
expect(
() => executor(
threads,
repeats,
tasks,
() => done(),
new NullLogger(),
FakeWorker,
),
).to.not.throw();
},);
it('should have build the right workers', () => {
expect(FakeWorker.built,).to.deep.equal({
'./worker/calculator.js': once,
'./worker/validator.js': once,
'./worker/webrequest.js': threads,
},);
},);
it('should have shut down the right workers', () => {
expect(FakeWorker.terminated,).to.deep.equal({
'./worker/calculator.js': once,
'./worker/validator.js': once,
'./worker/webrequest.js': threads,
},);
},);
},);
54 changes: 54 additions & 0 deletions test/validate-tasks.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import 'mocha';
import {
expect,
} from 'chai';
import validateTasks from '../src/validate-tasks';
import {
Task,
} from '../src/task';

describe('validateTasks', () => {
it('should be a function', () => {
expect(validateTasks,).to.be.a('function',);
},);
const threads = 33;
const repetitions = 100;
const tasks = [ <Task>{
id: 'test',
}, ];
const repeatedIdTasks = [
<Task>{
id: 'test',
},
<Task>{
id: '2.',
},
<Task>{
id: 'test',
},
];
const none = 0;
it('it should throw if none executlable is given (0 threads)', () => {
expect(() => validateTasks(repetitions, none, tasks,),).to.throw(
'Can\'t measure no tasks.'
);
},);
it('it should throw if none executlable is given (0 repetitions)', () => {
expect(() => validateTasks(none, threads, tasks,),).to.throw(
'Can\'t measure no tasks.'
);
},);
it('it should throw if none executlable is given (0 tasks)', () => {
expect(() => validateTasks(repetitions, threads, [],),).to.throw(
'Can\'t measure no tasks.'
);
},);
it('it should throw if task ids are duplicated', () => {
expect(
() => validateTasks(repetitions, threads, repeatedIdTasks,),
).to.throw(`The id test is shared.`,);
},);
it('it should not throw if given valid arguments', () => {
expect(() => validateTasks(repetitions, threads, tasks,),).to.not.throw();
},);
},);

0 comments on commit c76f044

Please sign in to comment.