Move tests to their own folder
This commit is contained in:
195
test/parser.test.ts
Normal file
195
test/parser.test.ts
Normal file
@@ -0,0 +1,195 @@
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import { base64ToBytes, hexToBytes, BufferReader, BufferWriter } from '../src/parser';
|
||||
|
||||
describe('base64ToBytes', () => {
|
||||
it('decodes a simple base64 string', () => {
|
||||
const bytes = base64ToBytes('aGVsbG8=', 5); // "hello"
|
||||
expect(Array.from(bytes)).toEqual([104, 101, 108, 108, 111]);
|
||||
});
|
||||
|
||||
it('handles empty string', () => {
|
||||
const bytes = base64ToBytes('', 0);
|
||||
expect(bytes).toBeInstanceOf(Uint8Array);
|
||||
expect(bytes.length).toBe(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('BufferReader', () => {
|
||||
it('readByte and peekByte advance/inspect correctly', () => {
|
||||
const buf = new Uint8Array([1, 2, 3]);
|
||||
const r = new BufferReader(buf);
|
||||
expect(r.peekByte()).toBe(1);
|
||||
expect(r.readByte()).toBe(1);
|
||||
expect(r.peekByte()).toBe(2);
|
||||
});
|
||||
|
||||
it('readBytes with and without length', () => {
|
||||
const buf = new Uint8Array([10, 11, 12, 13]);
|
||||
const r = new BufferReader(buf);
|
||||
const a = r.readBytes(2);
|
||||
expect(Array.from(a)).toEqual([10, 11]);
|
||||
const b = r.readBytes();
|
||||
expect(Array.from(b)).toEqual([12, 13]);
|
||||
});
|
||||
|
||||
it('hasMore and remainingBytes reflect position', () => {
|
||||
const buf = new Uint8Array([5, 6]);
|
||||
const r = new BufferReader(buf);
|
||||
expect(r.hasMore()).toBe(true);
|
||||
expect(r.remainingBytes()).toBe(2);
|
||||
r.readByte();
|
||||
expect(r.remainingBytes()).toBe(1);
|
||||
r.readByte();
|
||||
expect(r.hasMore()).toBe(false);
|
||||
});
|
||||
|
||||
it('reads little-endian unsigned ints', () => {
|
||||
const r16 = new BufferReader(new Uint8Array([0x34, 0x12]));
|
||||
expect(r16.readUint16LE()).toBe(0x1234);
|
||||
|
||||
const r32 = new BufferReader(new Uint8Array([0x78, 0x56, 0x34, 0x12]));
|
||||
expect(r32.readUint32LE()).toBe(0x12345678);
|
||||
});
|
||||
|
||||
it('reads signed ints with two/four bytes (negative)', () => {
|
||||
const r16 = new BufferReader(new Uint8Array([0xff, 0xff]));
|
||||
expect(r16.readInt16LE()).toBe(-1);
|
||||
|
||||
const r32 = new BufferReader(new Uint8Array([0xff, 0xff, 0xff, 0xff]));
|
||||
expect(r32.readInt32LE()).toBe(-1);
|
||||
});
|
||||
|
||||
it('readTimestamp returns Date with seconds->ms conversion', () => {
|
||||
const r = new BufferReader(new Uint8Array([0x01, 0x00, 0x00, 0x00]));
|
||||
const d = r.readTimestamp();
|
||||
expect(d.getTime()).toBe(1000);
|
||||
});
|
||||
});
|
||||
describe('sizedStringToBytes', () => {
|
||||
it('decodes hex string of correct length', () => {
|
||||
// 4 bytes = 8 hex chars
|
||||
const hex = 'deadbeef';
|
||||
const result = hexToBytes(hex, 4);
|
||||
expect(Array.from(result)).toEqual([0xde, 0xad, 0xbe, 0xef]);
|
||||
});
|
||||
|
||||
it('decodes base64 string of correct length', () => {
|
||||
// 4 bytes = 8 hex chars, base64 for [0xde, 0xad, 0xbe, 0xef] is '3q2+7w=='
|
||||
const b64 = '3q2+7w==';
|
||||
const result = base64ToBytes(b64, 4);
|
||||
expect(Array.from(result)).toEqual([0xde, 0xad, 0xbe, 0xef]);
|
||||
});
|
||||
|
||||
it('throws on invalid string length', () => {
|
||||
expect(() => hexToBytes('abc', 4)).toThrow();
|
||||
expect(() => hexToBytes('deadbeef00', 4)).toThrow();
|
||||
});
|
||||
});
|
||||
|
||||
describe('BufferWriter', () => {
|
||||
it('writeByte and toBytes', () => {
|
||||
const w = new BufferWriter();
|
||||
w.writeByte(0x12);
|
||||
w.writeByte(0x34);
|
||||
expect(Array.from(w.toBytes())).toEqual([0x12, 0x34]);
|
||||
});
|
||||
|
||||
it('writeBytes appends bytes', () => {
|
||||
const w = new BufferWriter();
|
||||
w.writeBytes(new Uint8Array([1, 2, 3]));
|
||||
expect(Array.from(w.toBytes())).toEqual([1, 2, 3]);
|
||||
});
|
||||
|
||||
it('writeUint16LE writes little-endian', () => {
|
||||
const w = new BufferWriter();
|
||||
w.writeUint16LE(0x1234);
|
||||
expect(Array.from(w.toBytes())).toEqual([0x34, 0x12]);
|
||||
});
|
||||
|
||||
it('writeUint32LE writes little-endian', () => {
|
||||
const w = new BufferWriter();
|
||||
w.writeUint32LE(0x12345678);
|
||||
expect(Array.from(w.toBytes())).toEqual([0x78, 0x56, 0x34, 0x12]);
|
||||
});
|
||||
|
||||
it('writeInt16LE writes signed values', () => {
|
||||
const w = new BufferWriter();
|
||||
w.writeInt16LE(-1);
|
||||
expect(Array.from(w.toBytes())).toEqual([0xff, 0xff]);
|
||||
const w2 = new BufferWriter();
|
||||
w2.writeInt16LE(0x1234);
|
||||
expect(Array.from(w2.toBytes())).toEqual([0x34, 0x12]);
|
||||
});
|
||||
|
||||
it('writeInt32LE writes signed values', () => {
|
||||
const w = new BufferWriter();
|
||||
w.writeInt32LE(-1);
|
||||
expect(Array.from(w.toBytes())).toEqual([0xff, 0xff, 0xff, 0xff]);
|
||||
const w2 = new BufferWriter();
|
||||
w2.writeInt32LE(0x12345678);
|
||||
expect(Array.from(w2.toBytes())).toEqual([0x78, 0x56, 0x34, 0x12]);
|
||||
});
|
||||
|
||||
it('writeTimestamp writes seconds as uint32le', () => {
|
||||
const w = new BufferWriter();
|
||||
const date = new Date(1000); // 1 second
|
||||
w.writeTimestamp(date);
|
||||
expect(Array.from(w.toBytes())).toEqual([0x01, 0x00, 0x00, 0x00]);
|
||||
});
|
||||
|
||||
it('BufferWriter output can be read back by BufferReader', () => {
|
||||
const w = new BufferWriter();
|
||||
w.writeByte(0x42);
|
||||
w.writeUint16LE(0x1234);
|
||||
w.writeInt16LE(-2);
|
||||
w.writeUint32LE(0xdeadbeef);
|
||||
w.writeInt32LE(-123456);
|
||||
w.writeBytes(new Uint8Array([0x01, 0x02]));
|
||||
const date = new Date(5000); // 5 seconds
|
||||
w.writeTimestamp(date);
|
||||
|
||||
const bytes = w.toBytes();
|
||||
const r = new BufferReader(bytes);
|
||||
|
||||
expect(r.readByte()).toBe(0x42);
|
||||
expect(r.readUint16LE()).toBe(0x1234);
|
||||
expect(r.readInt16LE()).toBe(-2);
|
||||
expect(r.readUint32LE()).toBe(0xdeadbeef);
|
||||
expect(r.readInt32LE()).toBe(-123456);
|
||||
expect(Array.from(r.readBytes(2))).toEqual([0x01, 0x02]);
|
||||
const readDate = r.readTimestamp();
|
||||
expect(readDate.getTime()).toBe(5000);
|
||||
expect(r.hasMore()).toBe(false);
|
||||
});
|
||||
|
||||
it('BufferReader throws or returns undefined if reading past end', () => {
|
||||
const r = new BufferReader(new Uint8Array([1, 2]));
|
||||
r.readByte();
|
||||
r.readByte();
|
||||
expect(() => r.readByte()).toThrow();
|
||||
});
|
||||
|
||||
it('BufferWriter handles multiple writeBytes calls', () => {
|
||||
const w = new BufferWriter();
|
||||
w.writeBytes(new Uint8Array([1, 2]));
|
||||
w.writeBytes(new Uint8Array([3, 4]));
|
||||
expect(Array.from(w.toBytes())).toEqual([1, 2, 3, 4]);
|
||||
});
|
||||
|
||||
it('encodedStringToBytes decodes raw string', () => {
|
||||
const str = String.fromCharCode(0xde, 0xad, 0xbe, 0xef);
|
||||
const bytes = new Uint8Array(4);
|
||||
for (let i = 0; i < 4; i++) bytes[i] = str.charCodeAt(i) & 0xff;
|
||||
expect(Array.from(bytes)).toEqual([0xde, 0xad, 0xbe, 0xef]);
|
||||
});
|
||||
|
||||
it('hexToBytes returns different length for wrong-size hex', () => {
|
||||
expect(() => hexToBytes('deadbe', 4)).toThrow();
|
||||
});
|
||||
|
||||
it('base64ToBytes handles URL-safe base64', () => {
|
||||
// [0xde, 0xad, 0xbe, 0xef] in URL-safe base64: '3q2-7w=='
|
||||
const bytes = base64ToBytes('3q2-7w==', 4);
|
||||
expect(Array.from(bytes)).toEqual([0xde, 0xad, 0xbe, 0xef]);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user