diff --git a/packages/util/src/compact/toU8a.spec.ts b/packages/util/src/compact/toU8a.spec.ts index e6b2f639fb..6052133b0b 100644 --- a/packages/util/src/compact/toU8a.spec.ts +++ b/packages/util/src/compact/toU8a.spec.ts @@ -6,101 +6,36 @@ import { BN } from '../bn/index.js'; import { compactToU8a } from './index.js'; -// Copied from https://github.com/paritytech/parity-codec/blob/master/src/codec.rs -const TESTS: { expected: string, value: BN }[] = [ - { expected: '00', value: new BN('0') }, - { expected: 'fc', value: new BN('63') }, - { expected: '01 01', value: new BN('64') }, - { expected: 'fd ff', value: new BN('16383') }, - { expected: '02 00 01 00', value: new BN('16384') }, - { expected: 'fe ff ff ff', value: new BN('1073741823') }, - { expected: '03 00 00 00 40', value: new BN('1073741824') }, - { expected: '03 ff ff ff ff', value: new BN(`${1}${'0'.repeat(32)}`, 2).subn(1) }, - { expected: '07 00 00 00 00 01', value: new BN(`${1}${'0'.repeat(32)}`, 2) }, - { expected: '0b 00 00 00 00 00 01', value: new BN(`${1}${'0'.repeat(40)}`, 2) }, - { expected: '0f 00 00 00 00 00 00 01', value: new BN(`${1}${'0'.repeat(48)}`, 2) }, - { expected: '0f ff ff ff ff ff ff ff', value: new BN(`${1}${'0'.repeat(56)}`, 2).subn(1) }, - { expected: '13 00 00 00 00 00 00 00 01', value: new BN(`${1}${'0'.repeat(56)}`, 2) }, - { expected: '13 ff ff ff ff ff ff ff ff', value: new BN(`${1}${'0'.repeat(64)}`, 2).subn(1) } +const TESTS: [output: string | Uint8Array, input: BN | number][] = [ + // Rust tests + // Copied from https://github.com/paritytech/parity-codec/blob/master/src/codec.rs + ['00', new BN('0')], + ['fc', new BN('63')], + ['01 01', new BN('64')], + ['fd ff', new BN('16383')], + ['02 00 01 00', new BN('16384')], + ['fe ff ff ff', new BN('1073741823')], + ['03 00 00 00 40', new BN('1073741824')], + ['03 ff ff ff ff', new BN(`${1}${'0'.repeat(32)}`, 2).subn(1)], + ['07 00 00 00 00 01', new BN(`${1}${'0'.repeat(32)}`, 2)], + ['0b 00 00 00 00 00 01', new BN(`${1}${'0'.repeat(40)}`, 2)], + ['0f 00 00 00 00 00 00 01', new BN(`${1}${'0'.repeat(48)}`, 2)], + ['0f ff ff ff ff ff ff ff', new BN(`${1}${'0'.repeat(56)}`, 2).subn(1)], + ['13 00 00 00 00 00 00 00 01', new BN(`${1}${'0'.repeat(56)}`, 2)], + ['13 ff ff ff ff ff ff ff ff', new BN(`${1}${'0'.repeat(64)}`, 2).subn(1)], + // own tests + [new Uint8Array([18 << 2]), 18], + [new Uint8Array([0b11111100]), 63], + [new Uint8Array([0xbd, 0x01]), 111], + [new Uint8Array([0b11111101, 0b00000111]), 511], + [new Uint8Array([253, 127]), 0x1fff], + [new Uint8Array([254, 255, 3, 0]), 0xffff], + [new Uint8Array([3 + ((4 - 4) << 2), 249, 255, 255, 255]), 0xfffffff9], + [new Uint8Array([3 + ((6 - 4) << 2), 0x00, 0x40, 0x7a, 0x10, 0xf3, 0x5a]), new BN('00005af3107a4000', 16)], + [new Uint8Array([23, 52, 0x40, 0x7a, 0x10, 0xf3, 0x5a, 0, 0, 18]), new BN('1200005af3107a4034', 16)] ]; describe('encode', (): void => { - it('encodes short u8', (): void => { - expect( - compactToU8a(18) - ).toEqual( - new Uint8Array([18 << 2]) - ); - }); - - it('encodes max u8 values', (): void => { - expect( - compactToU8a(new BN(63)) - ).toEqual( - new Uint8Array([0b11111100]) - ); - }); - - it('encodes basic u16 value', (): void => { - expect( - compactToU8a(511) - ).toEqual( - new Uint8Array([0b11111101, 0b00000111]) - ); - }); - - it('encodes basic u16 (not at edge)', (): void => { - expect( - compactToU8a(111) - ).toEqual( - new Uint8Array([0xbd, 0x01]) - ); - }); - - it('encodes basic u32 values (< 2^30)', (): void => { - expect( - compactToU8a(0x1fff) - ).toEqual( - new Uint8Array([253, 127]) - ); - }); - - it('encodes basic u32 values (short)', (): void => { - expect( - compactToU8a(0xffff) - ).toEqual( - new Uint8Array([254, 255, 3, 0]) - ); - }); - - it('encodes basic u32 values (full)', (): void => { - expect( - compactToU8a(0xfffffff9) - ).toEqual( - new Uint8Array([3 + ((4 - 4) << 2), 249, 255, 255, 255]) - ); - }); - - it('encodes a large value (6 bytes)', (): void => { - expect( - compactToU8a( - new BN('00005af3107a4000', 16) - ) - ).toEqual( - new Uint8Array([3 + ((6 - 4) << 2), 0x00, 0x40, 0x7a, 0x10, 0xf3, 0x5a]) - ); - }); - - it('encodes a large value (9 bytes)', (): void => { - expect( - compactToU8a( - new BN('1200005af3107a4034', 16) - ) - ).toEqual( - new Uint8Array([23, 52, 0x40, 0x7a, 0x10, 0xf3, 0x5a, 0, 0, 18]) - ); - }); - it('does not modify the original', (): void => { const original = new BN(123456); @@ -109,12 +44,14 @@ describe('encode', (): void => { }); describe('conversion tests', (): void => { - TESTS.forEach(({ expected, value }, i): void => { - it(`#${i}: encodes ${value.toString()}`, (): void => { + TESTS.forEach(([output, input], i): void => { + it(`#${i}: encodes ${input.toString()}`, (): void => { expect( - compactToU8a(value) + compactToU8a(input) ).toEqual( - Uint8Array.from(expected.split(' ').map((s) => parseInt(s, 16))) + output instanceof Uint8Array + ? output + : Uint8Array.from(output.split(' ').map((s) => parseInt(s, 16))) ); }); }); diff --git a/packages/util/src/float/toU8a.spec.ts b/packages/util/src/float/toU8a.spec.ts index 0d87b2048d..f7bd7068b1 100644 --- a/packages/util/src/float/toU8a.spec.ts +++ b/packages/util/src/float/toU8a.spec.ts @@ -6,8 +6,32 @@ import { u8aToHex } from '../u8a/index.js'; import { floatToU8a } from './index.js'; +class ExtNumber extends Number { + foo = 'bar'; +} + +class ExtString extends String { + foo = 'bar'; +} + // NOTE Hex value outputs created via online conversion tool: // https://www.h-schmidt.net/FloatConverter/IEEE754.html +// eslint-disable-next-line @typescript-eslint/ban-types +const TESTS: [isLe: boolean | undefined, bitLength: 32 | 64 | undefined, input: String | string | number | Number, output: string][] = [ + [undefined, undefined, +0.0, '0x00000000'], + [undefined, undefined, -0.0, '0x00000080'], + [undefined, undefined, 123.456, '0x79e9f642'], + [undefined, undefined, '123.456', '0x79e9f642'], + [undefined, undefined, new ExtNumber(123.456), '0x79e9f642'], + [undefined, undefined, new ExtString(123.456), '0x79e9f642'], + [true, 32, new ExtString(123.456), '0x79e9f642'], + [true, undefined, Number.NaN, '0x0000c07f'], + [false, undefined, -0.0, '0x80000000'], + [undefined, 64, +0.0, '0x0000000000000000'], + [true, 64, -0.0, '0x0000000000000080'], + [false, 64, -0.0, '0x8000000000000000'], + [undefined, 64, Number.NaN, '0x000000000000f87f'] +]; describe('floatToU8a', (): void => { it('throws on invalid bitLength', (): void => { @@ -16,89 +40,13 @@ describe('floatToU8a', (): void => { ).toThrow(); }); - describe('32-bit', (): void => { - it('correctly encodes +0.0', (): void => { - expect( - u8aToHex(floatToU8a(+0.0)) - ).toEqual('0x00000000'); - }); - - it('correctly encodes -0.0', (): void => { - expect( - u8aToHex(floatToU8a(-0.0)) - ).toEqual('0x00000080'); - }); - - it('correctly encodes -0.0 (BE)', (): void => { - expect( - u8aToHex(floatToU8a(-0.0, { isLe: false })) - ).toEqual('0x80000000'); - }); - - it('encodes NaN', (): void => { - expect( - u8aToHex(floatToU8a(Number.NaN, { isLe: true })) - ).toEqual('0x0000c07f'); - }); - - describe('equivalency', (): void => { - it('encodes number 123.456', (): void => { - expect( - u8aToHex(floatToU8a(123.456)) - ).toEqual('0x79e9f642'); - }); - - it('encodes string 123.456', (): void => { - expect( - u8aToHex(floatToU8a('123.456')) - ).toEqual('0x79e9f642'); - }); - - it('encodes Number 123.456', (): void => { - class Test extends Number { - foo = 'bar'; - } - - expect( - u8aToHex(floatToU8a(new Test(123.456))) - ).toEqual('0x79e9f642'); - }); - - it('encodes String 123.456', (): void => { - class Test extends String { - foo = 'bar'; - } - + describe('conversion tests', (): void => { + TESTS.forEach(([isLe, bitLength, input, output], i): void => { + it(`#${i}: correctly encodes ${typeof input === 'number' ? input : input.toString()} (typeof=${typeof input})`, (): void => { expect( - u8aToHex(floatToU8a(new Test('123.456'))) - ).toEqual('0x79e9f642'); + u8aToHex(floatToU8a(input, { bitLength, isLe })) + ).toEqual(output); }); }); }); - - describe('64-bit', (): void => { - it('correctly encodes +0.0', (): void => { - expect( - u8aToHex(floatToU8a(+0.0, { bitLength: 64 })) - ).toEqual('0x0000000000000000'); - }); - - it('correctly encodes -0.0', (): void => { - expect( - u8aToHex(floatToU8a(-0.0, { bitLength: 64, isLe: true })) - ).toEqual('0x0000000000000080'); - }); - - it('correctly encodes -0.0 (BE)', (): void => { - expect( - u8aToHex(floatToU8a(-0.0, { bitLength: 64, isLe: false })) - ).toEqual('0x8000000000000000'); - }); - - it('encodes NaN', (): void => { - expect( - u8aToHex(floatToU8a(Number.NaN, { bitLength: 64 })) - ).toEqual('0x000000000000f87f'); - }); - }); }); diff --git a/packages/util/src/u8a/toU8a.spec.ts b/packages/util/src/u8a/toU8a.spec.ts index 78241cd429..8a8676dfbc 100644 --- a/packages/util/src/u8a/toU8a.spec.ts +++ b/packages/util/src/u8a/toU8a.spec.ts @@ -3,9 +3,21 @@ /// +import type { U8aLike } from '../types.js'; + import { perf } from '../test/index.js'; import { u8aToU8a } from './index.js'; +const TESTS: [input: U8aLike | null | undefined, output: Uint8Array][] = [ + ['0x80000a', new Uint8Array([128, 0, 10])], + ['abcde fghij', new Uint8Array([97, 98, 99, 100, 101, 32, 102, 103, 104, 105, 106])], + [[128, 0, 10, 11, 12], new Uint8Array([128, 0, 10, 11, 12])], + [Buffer.from([1, 2, 3, 128, 0, 10, 11, 12]), new Uint8Array([1, 2, 3, 128, 0, 10, 11, 12])], + [Buffer.from('80000a', 'hex'), new Uint8Array([128, 0, 10])], + // this is where completely invalid data is being passed + [123 as unknown as Uint8Array, new Uint8Array([49, 50, 51])] +]; + describe('u8aToU8a', (): void => { it('returns an empty Uint8Array when null/undefined/"" provided', (): void => { expect( @@ -19,44 +31,6 @@ describe('u8aToU8a', (): void => { ).toHaveLength(0); }); - it('returns a Uint8Array (hex input)', (): void => { - expect( - u8aToU8a('0x80000a') - ).toEqual( - new Uint8Array([128, 0, 10]) - ); - }); - - it('returns Uint8Array (string input)', (): void => { - expect( - u8aToU8a('abcde fghij') - ).toEqual(new Uint8Array([97, 98, 99, 100, 101, 32, 102, 103, 104, 105, 106])); - }); - - it('creates from Array', (): void => { - expect( - u8aToU8a([128, 0, 10, 11, 12]) - ).toEqual( - new Uint8Array([128, 0, 10, 11, 12]) - ); - }); - - it('creates from a Buffer', (): void => { - expect( - u8aToU8a(Buffer.from([1, 2, 3, 128, 0, 10, 11, 12])).buffer - ).toEqual( - new Uint8Array([1, 2, 3, 128, 0, 10, 11, 12]).buffer - ); - }); - - it('creates from a Buffer (hex)', (): void => { - expect( - u8aToU8a(Buffer.from('80000a', 'hex')).buffer - ).toEqual( - new Uint8Array([128, 0, 10]).buffer - ); - }); - it('returns a Uint8Array as-is (u8a input)', (): void => { const input = new Uint8Array([128, 0, 10]); @@ -65,11 +39,16 @@ describe('u8aToU8a', (): void => { ).toEqual(true); }); - it('creates unknowns via string conversion', (): void => { - expect( - // this is where completely invalid data is being passed - u8aToU8a(123 as unknown as Uint8Array) - ).toEqual(new Uint8Array([49, 50, 51])); + describe('conversion tests', (): void => { + TESTS.forEach(([input, output], i): void => { + it(`#${i}: converts ${input as string} (typeof=${typeof input})`, (): void => { + expect( + u8aToU8a(input) + ).toEqual( + output + ); + }); + }); }); perf('u8aToU8a (hex)', 250_000, [['0x1234']], u8aToU8a);