Files
googlevideo/tests/ump.reader.test.ts
2025-07-22 15:02:10 -03:00

156 lines
5.0 KiB
TypeScript

import { describe, it, expect, vi } from 'vitest';
import { Part } from '../src/types/shared.js';
import { concatenateChunks } from '../src/utils/shared.js';
import { CompositeBuffer, UmpReader, UmpWriter } from '../src/exports/ump.js';
describe('UmpReader', () => {
it('should read a single small part correctly', () => {
const buffer = new CompositeBuffer();
const writer = new UmpWriter(buffer);
const partType = 1;
const partData = new Uint8Array([ 10, 20, 30 ]);
writer.write(partType, partData);
const reader = new UmpReader(buffer);
const handlePart = vi.fn();
const incompletePart = reader.read(handlePart);
const receivedPart = handlePart.mock.calls[0][0];
expect(handlePart).toHaveBeenCalledOnce();
expect(receivedPart.type).toBe(partType);
expect(receivedPart.size).toBe(partData.length);
expect(concatenateChunks(receivedPart.data.chunks)).toEqual(partData);
expect(incompletePart).toBeUndefined();
});
it('should read multiple parts sequentially', () => {
const buffer = new CompositeBuffer();
const writer = new UmpWriter(buffer);
const partsToWrite = [
{ type: 20, data: new Uint8Array([ 1, 2 ]) },
{ type: 21, data: new Uint8Array([ 3, 4, 5 ]) },
{ type: 150, data: new Uint8Array([ 6, 7, 8, 9 ]) }
];
for (const part of partsToWrite) {
writer.write(part.type, part.data);
}
const reader = new UmpReader(buffer);
const receivedParts: Part[] = [];
const handlePart = (part: Part) => {
receivedParts.push(part);
};
const incompletePart = reader.read(handlePart);
expect(receivedParts.length).toBe(partsToWrite.length);
for (let i = 0; i < partsToWrite.length; i++) {
expect(receivedParts[i].type).toBe(partsToWrite[i].type);
expect(receivedParts[i].size).toBe(partsToWrite[i].data.length);
expect(concatenateChunks(receivedParts[i].data.chunks)).toEqual(partsToWrite[i].data);
}
expect(incompletePart).toBeUndefined();
});
it('should return an incomplete part if data is not fully available', () => {
const buffer = new CompositeBuffer();
const writer = new UmpWriter(buffer);
const partType = 5;
const partData = new Uint8Array(100);
writer.write(partType, partData);
const headerSize = 2;
const partialBuffer = buffer.split(headerSize + 50).extractedBuffer;
const reader = new UmpReader(partialBuffer);
const handlePart = vi.fn();
const incompletePart = reader.read(handlePart);
expect(handlePart).not.toHaveBeenCalled();
expect(incompletePart).toBeDefined();
expect(incompletePart?.type).toBe(partType);
expect(incompletePart?.size).toBe(partData.length);
});
it('should return undefined if the buffer is empty', () => {
const buffer = new CompositeBuffer();
const reader = new UmpReader(buffer);
const handlePart = vi.fn();
const incompletePart = reader.read(handlePart);
expect(handlePart).not.toHaveBeenCalled();
expect(incompletePart).toBeUndefined();
});
it('should return undefined if part header is incomplete', () => {
const buffer = new CompositeBuffer();
buffer.append(new Uint8Array([ 0x96 ]));
const reader = new UmpReader(buffer);
const handlePart = vi.fn();
const incompletePart = reader.read(handlePart);
expect(handlePart).not.toHaveBeenCalled();
expect(incompletePart).toBeUndefined();
});
it('should correctly read a part with a 5-byte VarInt size', () => {
const buffer = new CompositeBuffer();
const writer = new UmpWriter(buffer);
const partType = 15;
const partData = new Uint8Array(300000000);
writer.write(partType, partData);
const reader = new UmpReader(buffer);
const handlePart = vi.fn();
const incompletePart = reader.read(handlePart);
expect(handlePart).toHaveBeenCalledOnce();
const receivedPart = handlePart.mock.calls[0][0];
expect(receivedPart.type).toBe(partType);
expect(receivedPart.size).toBe(partData.length);
expect(incompletePart).toBeUndefined();
});
it('should handle reading from multiple chunks', () => {
const buffer = new CompositeBuffer();
const writer = new UmpWriter(buffer);
const partType = 1;
const partData = new Uint8Array([ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]);
writer.write(partType, partData);
// Re-create the buffer from multiple smaller chunks.
const chunk1 = new Uint8Array([ 1, 10, 1, 2, 3 ]); // type, size, data...
const chunk2 = new Uint8Array([ 4, 5, 6 ]); // ...data...
const chunk3 = new Uint8Array([ 7, 8, 9, 10 ]); // ...data
const chunkedBuffer = new CompositeBuffer([ chunk1, chunk2, chunk3 ]);
const reader = new UmpReader(chunkedBuffer);
const handlePart = vi.fn();
reader.read(handlePart);
expect(handlePart).toHaveBeenCalledOnce();
const receivedPart = handlePart.mock.calls[0][0];
expect(receivedPart.type).toBe(partType);
expect(receivedPart.size).toBe(partData.length);
expect(concatenateChunks(receivedPart.data.chunks)).toEqual(partData);
});
});