mirror of
https://github.com/abhigyanpatwari/GitNexus.git
synced 2026-10-05 02:43:32 +00:00
test: add regression test for safePushAll stack-overflow boundary
Export safePushAll so it can be directly tested, and add a dedicated test file that: - Verifies element order and edge cases (empty source/target) - Drives a 200k-element accumulation to prove it doesn't overflow This ensures CI will catch any future reintroduction of the spread pattern in the chunk-accumulation path.
This commit is contained in:
parent
58885c1187
commit
6cbd3b9a7b
2 changed files with 52 additions and 2 deletions
|
|
@ -76,9 +76,11 @@ const isDev = process.env.NODE_ENV === 'development';
|
|||
* Append all elements from `source` into `target` without using the spread
|
||||
* operator. `target.push(...source)` converts every element into a function
|
||||
* argument which exceeds V8's call-stack limit when `source` has more than
|
||||
* ~65 000 entries (common in large Ruby/Rails monoliths).
|
||||
* ~65 000 entries (common in large monoliths with many symbols).
|
||||
*
|
||||
* Exported for regression testing — see safe-push-all.test.ts.
|
||||
*/
|
||||
function safePushAll<T>(target: T[], source: readonly T[]): void {
|
||||
export function safePushAll<T>(target: T[], source: readonly T[]): void {
|
||||
for (let i = 0; i < source.length; i++) {
|
||||
target.push(source[i]);
|
||||
}
|
||||
|
|
|
|||
48
gitnexus/test/unit/safe-push-all.test.ts
Normal file
48
gitnexus/test/unit/safe-push-all.test.ts
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
/**
|
||||
* Regression test for safePushAll — the helper introduced to replace
|
||||
* `array.push(...largeArray)` in the pipeline chunk-accumulation loop.
|
||||
*
|
||||
* The spread operator converts every element into a V8 call-stack argument.
|
||||
* At ~65k+ elements a single `push(...arr)` call overflows the stack.
|
||||
* This test ensures safePushAll handles that size without crashing and
|
||||
* will catch any future reintroduction of the spread pattern.
|
||||
*/
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import { safePushAll } from '../../src/core/ingestion/pipeline.js';
|
||||
|
||||
/** Size that reliably triggers the V8 stack overflow with push(...arr). */
|
||||
const OVERFLOW_SIZE = 200_000;
|
||||
|
||||
describe('safePushAll', () => {
|
||||
it('appends elements in order for a small array', () => {
|
||||
const target = [1, 2, 3];
|
||||
safePushAll(target, [4, 5, 6]);
|
||||
expect(target).toEqual([1, 2, 3, 4, 5, 6]);
|
||||
});
|
||||
|
||||
it('handles an empty source array', () => {
|
||||
const target = [1];
|
||||
safePushAll(target, []);
|
||||
expect(target).toEqual([1]);
|
||||
});
|
||||
|
||||
it('handles an empty target array', () => {
|
||||
const target: number[] = [];
|
||||
safePushAll(target, [1, 2]);
|
||||
expect(target).toEqual([1, 2]);
|
||||
});
|
||||
|
||||
it(`handles ${OVERFLOW_SIZE.toLocaleString()} elements without stack overflow`, () => {
|
||||
const source = new Array<number>(OVERFLOW_SIZE);
|
||||
for (let i = 0; i < OVERFLOW_SIZE; i++) source[i] = i;
|
||||
|
||||
const target: number[] = [];
|
||||
// This must not throw — push(...source) would RangeError here.
|
||||
safePushAll(target, source);
|
||||
|
||||
expect(target.length).toBe(OVERFLOW_SIZE);
|
||||
// Spot-check order is preserved at boundaries
|
||||
expect(target[0]).toBe(0);
|
||||
expect(target[OVERFLOW_SIZE - 1]).toBe(OVERFLOW_SIZE - 1);
|
||||
});
|
||||
});
|
||||
Loading…
Add table
Reference in a new issue