Skip to content

Commit

Permalink
Adding more tests and fixing corresponding git user in pipeine
Browse files Browse the repository at this point in the history
  • Loading branch information
jdalrymple committed Dec 13, 2023
1 parent aa0c116 commit 2940b9b
Show file tree
Hide file tree
Showing 3 changed files with 107 additions and 59 deletions.
5 changes: 3 additions & 2 deletions .github/workflows/pipeline.yml
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,9 @@ jobs:
env:
GITHUB_TOKEN: ${{ secrets.GH_TOKEN }}
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
GH_USERNAME: ${{ github.actor }}
run: |
npm config set //registry.npmjs.org/:_authToken $NPM_TOKEN
git config --global user.name "Autobot"
git config --global user.email "ci@github.com"
git config --global user.email "${GH_USERNAME}@users.noreply.github.com"
git config --global user.name "${GH_USERNAME}"
yarn release
21 changes: 12 additions & 9 deletions src/Deque.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Deque is based on https://github.com/petkaantonov/deque/blob/master/js/deque.js

// Released under the MIT License: https://github.com/petkaantonov/deque/blob/6ef4b6400ad3ba82853fdcc6531a38eb4f78c18c/LICENSE
/*eslint-disable*/
function arrayMove(src: any[], srcIndex: number, dst: any[], dstIndex: number, len: number) {
export function arrayMove(src: any[], srcIndex: number, dst: any[], dstIndex: number, len: number) {
for (let j = 0; j < len; ++j) {
dst[j + dstIndex] = src[j + srcIndex];
src[j + srcIndex] = void 0;
Expand All @@ -16,15 +16,18 @@ function pow2AtLeast(n: number) {
n |= n >> 4;
n |= n >> 8;
n |= n >> 16;

return n + 1;
}

function getCapacity(capacity: number) {
return pow2AtLeast(Math.min(Math.max(16, capacity), 1073741824));
export const MIN_CAPACITY = 4;
export const MAX_CAPACITY = 1073741824;
export const RESIZE_MULTIPLER = 1;

export function getCapacity(capacity: number) {
return pow2AtLeast(Math.min(Math.max(MIN_CAPACITY, capacity), MAX_CAPACITY));
}

// Deque is based on https://github.com/petkaantonov/deque/blob/master/js/deque.js
// Released under the MIT License: https://github.com/petkaantonov/deque/blob/6ef4b6400ad3ba82853fdcc6531a38eb4f78c18c/LICENSE
export class Deque<T> {
private _capacity: number;

Expand All @@ -34,8 +37,8 @@ export class Deque<T> {

private arr: Array<T | void>;

constructor(capacity: number) {
this._capacity = getCapacity(capacity);
constructor(initialCapacity: number = 4) {
this._capacity = getCapacity(initialCapacity);
this._length = 0;
this._front = 0;
this.arr = [];
Expand Down Expand Up @@ -93,7 +96,7 @@ export class Deque<T> {

private checkCapacity(size: number) {
if (this._capacity < size) {
this.resizeTo(getCapacity(this._capacity * 1.5 + 16));
this.resizeTo(getCapacity(this._capacity * RESIZE_MULTIPLER + MIN_CAPACITY));
}
}

Expand Down
140 changes: 92 additions & 48 deletions test/Deque.ts
Original file line number Diff line number Diff line change
@@ -1,82 +1,126 @@
import { Sema } from '../src/Sema';
import { Deque, MAX_CAPACITY, getCapacity } from '../src/Deque';

import { createRateLimiter } from '../src/Utils';
describe('MAX_CAPACITY', () => {
it('should restrict max capacity to 1gb', () => {
expect(MAX_CAPACITY).toBe(1073741824);
});
});

jest.useFakeTimers();
jest.spyOn(global, 'setTimeout');
describe('getCapacity', () => {
it('should accept a initial capacity for the queue, with a default of 4 if passed value is less than 4', () => {
const d = getCapacity(2);

const acquireFn = jest.fn();
const releaseFn = jest.fn();
expect(d).toBe(4);
});

jest.mock('../src/Sema', () => {
return {
Sema: jest.fn(() => ({
acquire: acquireFn,
release: releaseFn,
})),
};
});
it('should increment the capacity through a bit shift for every value greater than the previous bit shift limit', () => {
const d1 = getCapacity(5);

describe('General', () => {
afterEach(() => {
jest.clearAllMocks();
});
expect(d1).toBe(8);

it('should create a Sema instance with one maxConcurrency if uniform distribution is true', () => {
createRateLimiter(3, { uniformDistribution: true });
const d2 = getCapacity(17);

expect(Sema).toHaveBeenCalledWith(1);
expect(d2).toBe(32);
});

it('should create a Sema instance with passed maxConcurrency if uniform distribution is false', () => {
createRateLimiter(3, { uniformDistribution: false });
it('should restrict capcity to max buffer size (MAX_CAPACITY)', () => {
const d1 = getCapacity(MAX_CAPACITY + 1);

expect(Sema).toHaveBeenCalledWith(3);
expect(d1).toBe(MAX_CAPACITY);
});
});

it('should create a Sema instance with passed maxConcurrency if a uniform distribution is not passed', () => {
createRateLimiter(3);
describe('Deque.constructor', () => {
it('should accept no arguments and default to a capacity of 4', () => {
const d = new Deque();

expect(Sema).toHaveBeenCalledWith(3);
});
/* eslint-disable @typescript-eslint/ban-ts-comment, no-underscore-dangle */

// @ts-expect-error
expect(d._capacity).toBe(4);

// @ts-expect-error
expect(d._length).toBe(0);

it('should create a timeout using default timeUnit as delay if uniformDistribution is not passed', async () => {
const limiter = createRateLimiter(3);
// @ts-expect-error
expect(d.arr.length).toBe(0);

await limiter();
// @ts-expect-error
expect(d._front).toBe(0);

expect(setTimeout).toHaveBeenCalledWith(expect.any(Function), 1000);
/* eslint-enable */
});

it('should create a timeout using passed timeUnit as delay if uniformDistribution is not passed', async () => {
const limiter = createRateLimiter(3, { timeUnit: 2000 });
it('should accept a capacity argument', () => {
const d = new Deque(32);

/* eslint-disable @typescript-eslint/ban-ts-comment, no-underscore-dangle */

// @ts-expect-error
expect(d._capacity).toBe(32);

await limiter();
// @ts-expect-error
expect(d._length).toBe(0);

expect(setTimeout).toHaveBeenCalledWith(expect.any(Function), 2000);
// @ts-expect-error
expect(d.arr.length).toBe(0);

// @ts-expect-error
expect(d._front).toBe(0);

/* eslint-enable */
});

it('should create a timeout using passed timeUnit as delay if uniformDistribution is false', async () => {
const limiter = createRateLimiter(3, { uniformDistribution: false, timeUnit: 2000 });
it('should default to 4 capacity if capacity passed is lesser', () => {
const d = new Deque(2);

/* eslint-disable @typescript-eslint/ban-ts-comment, no-underscore-dangle */

// @ts-expect-error
expect(d._capacity).toBe(4);

// @ts-expect-error
expect(d._length).toBe(0);

// @ts-expect-error
expect(d.arr.length).toBe(0);

await limiter();
// @ts-expect-error
expect(d._front).toBe(0);

expect(setTimeout).toHaveBeenCalledWith(expect.any(Function), 2000);
/* eslint-enable */
});
});

it('should create a timeout using passed timeUnit divided by requests per time unit if uniformDistribution is true', async () => {
const limiter = createRateLimiter(2, { uniformDistribution: true, timeUnit: 10000 });
describe('Deque.push', () => {
it('should accept an item to add to the queue and increment the length', () => {
const d = new Deque();

await limiter();
d.push(1);

expect(setTimeout).toHaveBeenCalledWith(expect.any(Function), 5000);
expect(d.length).toBe(1);
});

it('should call Sema.aquire in limiter function', async () => {
const limiter = createRateLimiter(2);
it('should update capacity if more than capacity items are added', () => {
const d = new Deque();

d.push(1);
d.push(1);
d.push(1);
d.push(1);
const finalLength = d.push(1);

expect(finalLength).toBe(5);
expect(d.length).toBe(5);

/* eslint-disable @typescript-eslint/ban-ts-comment, no-underscore-dangle */

// @ts-expect-error
expect(d._capacity).toBe(8);

await limiter();
// @ts-expect-error
expect(d.arr).toMatchObject([1, 1, 1, 1, 1]);

expect(acquireFn).toHaveBeenCalledTimes(1);
/* eslint-enable */
});
});

0 comments on commit 2940b9b

Please sign in to comment.