Skip to content

Commit

Permalink
Add test covering withFilter memory leak fix
Browse files Browse the repository at this point in the history
  • Loading branch information
urossmolnik committed Feb 11, 2021
1 parent 58ac8a3 commit b7c7472
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 20 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
"posttest": "npm run lint",
"lint": "tslint --project ./tsconfig.json ./src/**/*.ts",
"watch": "tsc -w",
"testonly": "mocha --reporter spec --full-trace ./dist/test/tests.js ./dist/test/asyncIteratorSubscription.js",
"testonly": "mocha --expose-gc --reporter spec --full-trace ./dist/test/tests.js ./dist/test/asyncIteratorSubscription.js",
"coverage": "node ./node_modules/istanbul/lib/cli.js cover _mocha -- --full-trace ./dist/test/tests.js ./dist/test/asyncIteratorSubscription.js",
"postcoverage": "remap-istanbul --input coverage/coverage.raw.json --type lcovonly --output coverage/lcov.info",
"prepublishOnly": "npm run clean && npm run compile"
Expand Down
75 changes: 56 additions & 19 deletions src/test/asyncIteratorSubscription.ts
Original file line number Diff line number Diff line change
Expand Up @@ -172,35 +172,72 @@ describe('GraphQL-JS asyncIterator', () => {
});
});

function isEven(x: number) {
if (x === undefined) {
throw Error('Undefined value passed to filterFn');
}
return x % 2 === 0;
}

let testFiniteAsyncIterator: AsyncIterator<number> = createAsyncIterator([1, 2, 3, 4, 5, 6, 7, 8]);
// Work around https://github.com/leebyron/iterall/issues/48
(testFiniteAsyncIterator as any).throw = function (error) {
return Promise.reject(error);
};
(testFiniteAsyncIterator as any).return = function () {
return { value: undefined, done: true };
};

describe('withFilter', () => {

it('works properly with finite asyncIterators', async () => {
let filteredAsyncIterator = withFilter(() => testFiniteAsyncIterator, isEven)();
const isEven = (x: number) => x % 2 === 0;

const testFiniteAsyncIterator: AsyncIterator<number> = createAsyncIterator([1, 2, 3, 4, 5, 6, 7, 8]);
// Work around https://github.com/leebyron/iterall/issues/48
testFiniteAsyncIterator.throw = function (error) {
return Promise.reject(error);
};
testFiniteAsyncIterator.return = function () {
return Promise.resolve({ value: undefined, done: true });
};

const filteredAsyncIterator = withFilter(() => testFiniteAsyncIterator, isEven)();

for (let i = 1; i <= 4; i++) {
let result = await filteredAsyncIterator.next();
const result = await filteredAsyncIterator.next();
expect(result).to.not.be.undefined;
expect(result.value).to.equal(i * 2);
expect(result.done).to.be.false;
}
let doneResult = await filteredAsyncIterator.next();
const doneResult = await filteredAsyncIterator.next();
expect(doneResult).to.not.be.undefined;
expect(doneResult.value).to.be.undefined;
expect(doneResult.done).to.be.true;
});

// Old implementation of with-filter was leaking memory with was visible
// in case with long lived subscriptions where filter is skipping most of messages
// https://github.com/apollographql/graphql-subscriptions/issues/212
it('does not leak memory with promise chain #memory', async function () {
this.timeout(5000);
let stopped = false;

let index = 0;
const asyncIterator: AsyncIterator<any> = {
next() {
if (stopped) {
return Promise.resolve({done: true, value: undefined});
}
index += 1;
return new Promise(resolve => setImmediate(resolve))
.then(() => ({done: false, value: index}));
},
return() {
return Promise.resolve({ value: undefined, done: true });
},
throw(error) {
return Promise.reject(error);
},
};

const filteredAsyncIterator = withFilter(() => asyncIterator, () => stopped)();

global.gc();
const heapUsed = process.memoryUsage().heapUsed;
const nextPromise = filteredAsyncIterator.next();
await new Promise(resolve => setTimeout(resolve, 3000));
global.gc();
const heapUsed2 = process.memoryUsage().heapUsed;
stopped = true;
await nextPromise;

// Heap memory goes up for less than 1%
expect(Math.max(0, heapUsed2 - heapUsed) / heapUsed).to.be.lessThan(0.01);
});

});

0 comments on commit b7c7472

Please sign in to comment.