Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Additional test cleanups #1870

Merged
merged 5 commits into from
Aug 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
129 changes: 33 additions & 96 deletions packages/util/src/compact/toU8a.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand All @@ -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)))
);
});
});
Expand Down
110 changes: 29 additions & 81 deletions packages/util/src/float/toU8a.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 => {
Expand All @@ -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');
});
});
});
65 changes: 22 additions & 43 deletions packages/util/src/u8a/toU8a.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,21 @@

/// <reference types="@polkadot/dev-test/globals.d.ts" />

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(
Expand All @@ -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]);

Expand All @@ -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);
Expand Down