90 lines
3.5 KiB
TypeScript
90 lines
3.5 KiB
TypeScript
|
|
import { expect, tap } from '@git.zone/tstest/tapbundle';
|
||
|
|
import { LineScanner } from '../ts/classes.linescanner.js';
|
||
|
|
|
||
|
|
const noopLogger = { log() {} };
|
||
|
|
|
||
|
|
tap.test('should parse a single complete line', async () => {
|
||
|
|
const scanner = new LineScanner(1024 * 1024, noopLogger);
|
||
|
|
const lines: string[] = [];
|
||
|
|
scanner.push(Buffer.from('{"hello":"world"}\n'), (line) => lines.push(line));
|
||
|
|
expect(lines.length).toEqual(1);
|
||
|
|
expect(lines[0]).toEqual('{"hello":"world"}');
|
||
|
|
});
|
||
|
|
|
||
|
|
tap.test('should parse multiple lines in one chunk', async () => {
|
||
|
|
const scanner = new LineScanner(1024 * 1024, noopLogger);
|
||
|
|
const lines: string[] = [];
|
||
|
|
scanner.push(Buffer.from('{"a":1}\n{"b":2}\n{"c":3}\n'), (line) => lines.push(line));
|
||
|
|
expect(lines.length).toEqual(3);
|
||
|
|
expect(lines[0]).toEqual('{"a":1}');
|
||
|
|
expect(lines[1]).toEqual('{"b":2}');
|
||
|
|
expect(lines[2]).toEqual('{"c":3}');
|
||
|
|
});
|
||
|
|
|
||
|
|
tap.test('should handle a line split across chunks', async () => {
|
||
|
|
const scanner = new LineScanner(1024 * 1024, noopLogger);
|
||
|
|
const lines: string[] = [];
|
||
|
|
scanner.push(Buffer.from('{"hel'), (line) => lines.push(line));
|
||
|
|
expect(lines.length).toEqual(0);
|
||
|
|
scanner.push(Buffer.from('lo":"world"}\n'), (line) => lines.push(line));
|
||
|
|
expect(lines.length).toEqual(1);
|
||
|
|
expect(lines[0]).toEqual('{"hello":"world"}');
|
||
|
|
});
|
||
|
|
|
||
|
|
tap.test('should drop oversized lines', async () => {
|
||
|
|
const scanner = new LineScanner(100, noopLogger);
|
||
|
|
const lines: string[] = [];
|
||
|
|
// Line is 200 chars + newline, exceeds maxPayloadSize of 100
|
||
|
|
const oversized = 'x'.repeat(200) + '\n';
|
||
|
|
scanner.push(Buffer.from(oversized), (line) => lines.push(line));
|
||
|
|
expect(lines.length).toEqual(0);
|
||
|
|
});
|
||
|
|
|
||
|
|
tap.test('should clear buffer on OOM (no newline, exceeds max)', async () => {
|
||
|
|
const scanner = new LineScanner(100, noopLogger);
|
||
|
|
const lines: string[] = [];
|
||
|
|
// Push 200 bytes without any newline — exceeds maxPayloadSize
|
||
|
|
scanner.push(Buffer.from('x'.repeat(200)), (line) => lines.push(line));
|
||
|
|
expect(lines.length).toEqual(0);
|
||
|
|
// After clearing, should work normally again
|
||
|
|
scanner.push(Buffer.from('{"ok":true}\n'), (line) => lines.push(line));
|
||
|
|
expect(lines.length).toEqual(1);
|
||
|
|
expect(lines[0]).toEqual('{"ok":true}');
|
||
|
|
});
|
||
|
|
|
||
|
|
tap.test('should skip empty lines', async () => {
|
||
|
|
const scanner = new LineScanner(1024 * 1024, noopLogger);
|
||
|
|
const lines: string[] = [];
|
||
|
|
scanner.push(Buffer.from('\n\n{"a":1}\n\n'), (line) => lines.push(line));
|
||
|
|
expect(lines.length).toEqual(1);
|
||
|
|
expect(lines[0]).toEqual('{"a":1}');
|
||
|
|
});
|
||
|
|
|
||
|
|
tap.test('should handle mixed complete and partial lines', async () => {
|
||
|
|
const scanner = new LineScanner(1024 * 1024, noopLogger);
|
||
|
|
const lines: string[] = [];
|
||
|
|
// First chunk: one complete line + start of second line
|
||
|
|
scanner.push(Buffer.from('{"first":1}\n{"sec'), (line) => lines.push(line));
|
||
|
|
expect(lines.length).toEqual(1);
|
||
|
|
// Second chunk: end of second line + complete third line
|
||
|
|
scanner.push(Buffer.from('ond":2}\n{"third":3}\n'), (line) => lines.push(line));
|
||
|
|
expect(lines.length).toEqual(3);
|
||
|
|
expect(lines[1]).toEqual('{"second":2}');
|
||
|
|
expect(lines[2]).toEqual('{"third":3}');
|
||
|
|
});
|
||
|
|
|
||
|
|
tap.test('clear should reset the buffer', async () => {
|
||
|
|
const scanner = new LineScanner(1024 * 1024, noopLogger);
|
||
|
|
const lines: string[] = [];
|
||
|
|
// Push partial data
|
||
|
|
scanner.push(Buffer.from('{"partial":'), (line) => lines.push(line));
|
||
|
|
// Clear
|
||
|
|
scanner.clear();
|
||
|
|
// Now push a complete new line — old partial should not affect it
|
||
|
|
scanner.push(Buffer.from('{"fresh":true}\n'), (line) => lines.push(line));
|
||
|
|
expect(lines.length).toEqual(1);
|
||
|
|
expect(lines[0]).toEqual('{"fresh":true}');
|
||
|
|
});
|
||
|
|
|
||
|
|
export default tap.start();
|