77 lines
3.5 KiB
TypeScript
77 lines
3.5 KiB
TypeScript
import { describe, expect, it } from 'vitest'
|
||
import {
|
||
bytesToHex,
|
||
bytesToText,
|
||
decodeBase64,
|
||
encodeBase64,
|
||
formatBytes,
|
||
parseHex,
|
||
textToBytes,
|
||
textToBytesLimited,
|
||
} from '../src/lib/bytes'
|
||
|
||
describe('parseHex', () => {
|
||
it('accepts contiguous hex, separators and optional 0x prefixes', () => {
|
||
const expected = '00112233445566778899AABBCCDDEEFF'
|
||
expect(bytesToHex(parseHex(expected), '')).toBe(expected)
|
||
expect(bytesToHex(parseHex('00 11 22 33 44 55 66 77 88 99 AA BB CC DD EE FF'), '')).toBe(expected)
|
||
expect(bytesToHex(parseHex('00,11,22,33,44,55,66,77,88,99,AA,BB,CC,DD,EE,FF'), '')).toBe(expected)
|
||
expect(bytesToHex(parseHex('0x00 0x11 0x22 0x33 0x44 0x55 0x66 0x77 0x88 0x99 0xAA 0xBB 0xCC 0xDD 0xEE 0xFF'), '')).toBe(expected)
|
||
expect(bytesToHex(parseHex(`0x${expected}`), '')).toBe(expected)
|
||
})
|
||
|
||
it('reports invalid characters, odd length and exact byte count', () => {
|
||
expect(() => parseHex('GG')).toThrow('无效')
|
||
expect(() => parseHex('10x2')).toThrow('无效')
|
||
expect(() => parseHex('AA0xBB')).toThrow('无效')
|
||
expect(() => parseHex('ABC')).toThrow('偶数')
|
||
expect(() => parseHex('0011', 16)).toThrow('当前为 2 字节')
|
||
expect(() => parseHex(',AA')).toThrow('片段缺少')
|
||
expect(() => parseHex('AA,')).toThrow('片段缺少')
|
||
expect(() => parseHex('AA,,BB')).toThrow('片段缺少')
|
||
expect(() => parseHex('AA, ,BB')).toThrow('片段缺少')
|
||
})
|
||
|
||
it('supports bounded parsing without allocating oversized output', () => {
|
||
expect(parseHex('00 11', { maxBytes: 2 })).toEqual(Uint8Array.from([0, 0x11]))
|
||
expect(() => parseHex('00 11 22', { maxBytes: 2, limitLabel: '测试数据' })).toThrow('测试数据不能超过')
|
||
expect(() => parseHex('0'.repeat(2_000), { maxInputChars: 100 })).toThrow('输入不能超过')
|
||
})
|
||
|
||
it('encodes bounded UTF-8 text before allocating the result', () => {
|
||
expect(textToBytesLimited('你好', 6)).toEqual(textToBytes('你好'))
|
||
expect(() => textToBytesLimited('你好', 5)).toThrow('不能超过 5 字节')
|
||
expect(() => textToBytesLimited('abc', 10, 2, '测试数据')).toThrow('输入不能超过')
|
||
})
|
||
})
|
||
|
||
describe('UTF-8 and Base64', () => {
|
||
it('round-trips Unicode text', () => {
|
||
const source = '你好,Web Tools'
|
||
expect(bytesToText(textToBytes(source))).toBe(source)
|
||
expect(bytesToText(decodeBase64(encodeBase64(textToBytes(source))))).toBe(source)
|
||
})
|
||
|
||
it('formats decoded binary as continuous hex and source-code bytes', () => {
|
||
const bytes = decodeBase64('SJ87vWNeyh907uXD4bRteQ==')
|
||
expect(formatBytes(bytes)).toBe('489F3BBD635ECA1F74EEE5C3E1B46D79')
|
||
expect(formatBytes(bytes, { format: 'byte-array', uppercase: false })).toBe('0x48, 0x9f, 0x3b, 0xbd, 0x63, 0x5e, 0xca, 0x1f, 0x74, 0xee, 0xe5, 0xc3, 0xe1, 0xb4, 0x6d, 0x79')
|
||
})
|
||
|
||
it('supports URL-safe Base64 without padding', () => {
|
||
const bytes = Uint8Array.from([251, 255, 239])
|
||
expect(encodeBase64(bytes, true)).toBe('-__v')
|
||
expect(decodeBase64('-__v', true)).toEqual(bytes)
|
||
})
|
||
|
||
it('rejects invalid Base64', () => {
|
||
expect(() => decodeBase64('abcde')).toThrow('长度')
|
||
expect(() => decodeBase64('ab*c')).toThrow('无效')
|
||
expect(() => decodeBase64('TQ=')).toThrow('填充长度')
|
||
expect(() => decodeBase64('TWE==')).toThrow('填充长度')
|
||
expect(() => decodeBase64('T=Q=')).toThrow('填充位置')
|
||
expect(() => decodeBase64('Zh==')).toThrow('无效')
|
||
expect(() => decodeBase64('Zm9=')).toThrow('无效')
|
||
})
|
||
})
|