159 lines
5.1 KiB
TypeScript
159 lines
5.1 KiB
TypeScript
import { describe, it, expect } from 'vitest';
|
|
import { BlockHeader } from '~/src/block-header';
|
|
import { Bytes } from '~/src/bytes';
|
|
|
|
describe('Success cases', () => {
|
|
// Test cases with different block header representations
|
|
type BlockHeaderCase = {
|
|
raw: {
|
|
version: number;
|
|
previousBlockHash: Uint8Array;
|
|
merkleRoot: Uint8Array;
|
|
timestamp: number;
|
|
bits: number;
|
|
nonce: number;
|
|
};
|
|
representations: {
|
|
bytes: Uint8Array;
|
|
hex: string;
|
|
};
|
|
};
|
|
|
|
const testCases: BlockHeaderCase[] = [
|
|
{
|
|
raw: {
|
|
version: 592633856,
|
|
previousBlockHash: Bytes.fromHex(
|
|
'df4da87b838b2dde9aaf26cb08380f15a57f32d99f2007000000000000000000',
|
|
).toBytes(),
|
|
merkleRoot: Bytes.fromHex(
|
|
'5e8a3ccc570da3eddb5c67853385e72aad4c830b2eedb4f23943d09513a0b476',
|
|
).toBytes(),
|
|
timestamp: 1737338908,
|
|
bits: 402807112,
|
|
nonce: 3478133258,
|
|
},
|
|
representations: {
|
|
bytes: Bytes.fromHex(
|
|
'00e05223df4da87b838b2dde9aaf26cb08380f15a57f32d99f20070000000000000000005e8a3ccc570da3eddb5c67853385e72aad4c830b2eedb4f23943d09513a0b4761cb08d67485902180a1a50cf',
|
|
).toBytes(),
|
|
hex: '00e05223df4da87b838b2dde9aaf26cb08380f15a57f32d99f20070000000000000000005e8a3ccc570da3eddb5c67853385e72aad4c830b2eedb4f23943d09513a0b4761cb08d67485902180a1a50cf',
|
|
},
|
|
},
|
|
];
|
|
|
|
// Test from methods with their respective types
|
|
const fromMethods = [
|
|
{ name: 'fromBytes', key: 'bytes' },
|
|
{ name: 'fromHex', key: 'hex' },
|
|
] as const;
|
|
|
|
fromMethods.forEach(({ name, key }) => {
|
|
it.each(testCases)(`${name}()`, ({ raw, representations }) => {
|
|
const blockHeader = BlockHeader[name](representations[key]);
|
|
expect(blockHeader.toRaw()).toStrictEqual(raw);
|
|
});
|
|
});
|
|
|
|
// Test generic from method
|
|
it.each(testCases)('from(Uint8Array)', ({ raw, representations }) => {
|
|
const blockHeader = BlockHeader.from(representations.bytes);
|
|
expect(blockHeader.toRaw()).toStrictEqual(raw);
|
|
});
|
|
|
|
it.each(testCases)('from(string)', ({ raw, representations }) => {
|
|
const blockHeader = BlockHeader.from(representations.hex);
|
|
expect(blockHeader.toRaw()).toStrictEqual(raw);
|
|
});
|
|
|
|
// Test to methods with their respective types
|
|
const toMethods = [
|
|
{ name: 'toBytes', key: 'bytes' },
|
|
{ name: 'toHex', key: 'hex' },
|
|
] as const;
|
|
|
|
toMethods.forEach(({ name, key }) => {
|
|
it.each(testCases)(`${name}()`, ({ raw, representations }) => {
|
|
const blockHeader = BlockHeader.fromRaw(raw);
|
|
expect(blockHeader[name]()).toStrictEqual(representations[key]);
|
|
});
|
|
});
|
|
|
|
// Test getter methods
|
|
it.each(testCases)('getter methods return correct values', ({ raw }) => {
|
|
const blockHeader = BlockHeader.fromRaw(raw);
|
|
expect(blockHeader.getVersion()).toBe(raw.version);
|
|
expect(blockHeader.getPreviousBlockHash()).toStrictEqual(
|
|
raw.previousBlockHash,
|
|
);
|
|
expect(blockHeader.getMerkleRoot()).toStrictEqual(raw.merkleRoot);
|
|
expect(blockHeader.getTimestamp()).toBe(raw.timestamp);
|
|
expect(blockHeader.getBits()).toBe(raw.bits);
|
|
expect(blockHeader.getNonce()).toBe(raw.nonce);
|
|
});
|
|
|
|
// Test hex getter methods
|
|
it.each(testCases)('hex getter methods return correct values', ({ raw }) => {
|
|
const blockHeader = BlockHeader.fromRaw(raw);
|
|
expect(blockHeader.getPreviousBlockHashHex()).toBe(
|
|
Bytes.fromBytes(raw.previousBlockHash).toHex(),
|
|
);
|
|
expect(blockHeader.getMerkleRootHex()).toBe(
|
|
Bytes.fromBytes(raw.merkleRoot).toHex(),
|
|
);
|
|
});
|
|
|
|
// Test hash methods
|
|
it.each(testCases)('getHash() returns correct hash', ({ raw }) => {
|
|
const blockHeader = BlockHeader.fromRaw(raw);
|
|
const hash = blockHeader.getHash();
|
|
expect(hash).toBeInstanceOf(Uint8Array);
|
|
expect(hash.length).toBe(32);
|
|
});
|
|
|
|
it.each(testCases)('getHashHex() returns correct hash hex', ({ raw }) => {
|
|
const blockHeader = BlockHeader.fromRaw(raw);
|
|
const hashHex = blockHeader.getHashHex();
|
|
expect(typeof hashHex).toBe('string');
|
|
expect(hashHex.length).toBe(64);
|
|
});
|
|
|
|
// Test validation method
|
|
it.each(testCases)(
|
|
'isValid() returns true for valid inputs',
|
|
({ representations }) => {
|
|
expect(BlockHeader.isValid(representations.bytes)).toBe(true);
|
|
expect(BlockHeader.isValid(representations.hex)).toBe(true);
|
|
},
|
|
);
|
|
});
|
|
|
|
describe('Error cases', () => {
|
|
const invalidCases = [
|
|
{
|
|
method: 'fromBytes',
|
|
input: new Uint8Array(79), // Wrong length (should be 80 bytes)
|
|
},
|
|
{
|
|
method: 'fromHex',
|
|
input: 'invalid_hex',
|
|
},
|
|
{
|
|
method: 'fromHex',
|
|
input: '00'.repeat(79), // Wrong length (should be 80 bytes / 160 hex chars)
|
|
},
|
|
];
|
|
|
|
invalidCases.forEach(({ method, input }) => {
|
|
it(`${method}() throws on invalid input`, () => {
|
|
expect(() => BlockHeader[method](input)).toThrow();
|
|
});
|
|
});
|
|
|
|
it('isValid() returns false for invalid inputs', () => {
|
|
expect(BlockHeader.isValid(new Uint8Array(79))).toBe(false);
|
|
expect(BlockHeader.isValid('invalid_hex')).toBe(false);
|
|
expect(BlockHeader.isValid('00'.repeat(79))).toBe(false);
|
|
});
|
|
});
|