import { describe, expect, it } from 'vitest' import { DEFAULT_MAX_INTEL_HEX_RECORDS, MAX_UINT32_ADDRESS, parseIntelHex, } from '../src/lib/intelHex' function record(address: number, type: number, data: number[]): string { const bytes = [data.length, Math.floor(address / 0x100) & 0xff, address & 0xff, type, ...data] const checksum = (-bytes.reduce((sum, byte) => sum + byte, 0)) & 0xff return `:${[...bytes, checksum].map((byte) => byte.toString(16).padStart(2, '0')).join('').toUpperCase()}` } const eof = record(0, 1, []) describe('Intel HEX 32-bit boundaries', () => { it('accepts a single byte at the highest uint32 address', () => { const parsed = parseIntelHex([ record(0, 4, [0xff, 0xff]), record(0xffff, 0, [0xaa]), eof, ].join('\n')) expect(parsed.blocks).toEqual([{ startAddress: MAX_UINT32_ADDRESS, data: Uint8Array.of(0xaa) }]) }) it('merges adjacent records ending exactly at the address-space boundary', () => { const parsed = parseIntelHex([ record(0, 4, [0xff, 0xff]), record(0xfffd, 0, [0x11, 0x22]), record(0xffff, 0, [0x33]), eof, ].join('\n')) expect(parsed.blocks).toEqual([{ startAddress: 0xfffffffd, data: Uint8Array.of(0x11, 0x22, 0x33), }]) }) it('rejects a data record that extends beyond the uint32 address space', () => { expect(() => parseIntelHex([ record(0, 4, [0xff, 0xff]), record(0xffff, 0, [0xaa, 0xbb]), eof, ].join('\n'))).toThrow('地址范围超出 32 位空间') }) it('calculates segment and linear base addresses without signed bitwise overflow', () => { const segment = parseIntelHex([record(0, 2, [0xff, 0xff]), record(0xffff, 0, [1]), eof].join('\n')) const linear = parseIntelHex([record(0, 4, [0x80, 0x00]), record(0, 0, [2]), eof].join('\n')) expect(segment.blocks[0].startAddress).toBe(0x0010ffef) expect(linear.blocks[0].startAddress).toBe(0x80000000) }) }) describe('Intel HEX structural limits', () => { it('counts all non-empty records, including control records', () => { expect(DEFAULT_MAX_INTEL_HEX_RECORDS).toBeGreaterThan(0) expect(() => parseIntelHex([record(0, 0, [1]), eof].join('\n'), { maxRecords: 1 })).toThrow('记录不能超过 1 条') }) it('rejects invalid limits before parsing', () => { expect(() => parseIntelHex(record(0, 0, [1]), { maxRecords: 0 })).toThrow('正整数') expect(() => parseIntelHex(record(0, 0, [1]), { maxRecords: 1.5 })).toThrow('正整数') expect(() => parseIntelHex(record(0, 0, [1]), { maxRecords: Number.POSITIVE_INFINITY })).toThrow('正整数') expect(() => parseIntelHex(record(0, 0, [1]), { maxRecords: Number.MAX_SAFE_INTEGER + 1 })).toThrow('正整数') }) it('rejects records after EOF and malformed control records', () => { expect(() => parseIntelHex([record(0, 0, [1]), eof, record(1, 0, [2])].join('\n'))).toThrow('EOF 记录之后') expect(() => parseIntelHex([record(1, 1, []), record(0, 0, [1])].join('\n'))).toThrow('EOF 记录格式无效') expect(() => parseIntelHex([record(0, 4, [0]), record(0, 0, [1]), eof].join('\n'))).toThrow('扩展线性地址记录格式无效') expect(() => parseIntelHex([record(0, 6, []), record(0, 0, [1]), eof].join('\n'))).toThrow('不支持的记录类型') }) it('rejects files without effective data and lines with inconsistent declared lengths', () => { expect(() => parseIntelHex(eof)).toThrow('不包含有效数据记录') expect(() => parseIntelHex(':0200000001FC')).toThrow('数据长度与记录声明不一致') }) })