test(Struct): Token

This commit is contained in:
2025-08-04 17:46:42 +03:00
parent ba9e1d1d31
commit f25af1b6ac
2 changed files with 56 additions and 20 deletions

View File

@ -1,5 +1,5 @@
import { describe, expect, test } from "vitest"; import { describe, expect, test } from "vitest";
import { parse, serialize, sizeof, Struct } from "../src"; import { ConstDataView, parse, serialize, sizeof, Struct } from "../src";
import { expectDataViewEqual, filledDataView, sizedDataView } from "."; import { expectDataViewEqual, filledDataView, sizedDataView } from ".";
describe(Struct.name, () => { describe(Struct.name, () => {
@ -7,10 +7,11 @@ describe(Struct.name, () => {
const User = Struct({ age: Number, name: String }) const User = Struct({ age: Number, name: String })
const user = { age: 1, name: 'hello' } const user = { age: 1, name: 'hello' }
const user_dv = filledDataView([ const user_dv = filledDataView([
0x3F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // age
0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x0C, // name_head
0x00, 0x00, 0x00, 0x05, // name
0x68, 0x65, 0x6C, 0x6C, 0x6F, 0x00, 0x00, 0x00, 0x05, // name.size
0x68, 0x65, 0x6C, 0x6C, 0x6F, // name.data
]) ])
test('serialize, headless', () => { test('serialize, headless', () => {
@ -30,8 +31,8 @@ describe(Struct.name, () => {
const Vector2 = Struct({ x: Number, y: Number }) const Vector2 = Struct({ x: Number, y: Number })
const vector2 = { x: 1, y: 2 } const vector2 = { x: 1, y: 2 }
const vector2_dv = filledDataView([ const vector2_dv = filledDataView([
0x3F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // x
0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // y
]) ])
test('serialize, non-headless', () => { test('serialize, non-headless', () => {
@ -49,13 +50,16 @@ describe(Struct.name, () => {
const Nested = Struct({ user: User, vector2: [Vector2] }) const Nested = Struct({ user: User, vector2: [Vector2] })
const nested = { user, vector2 } const nested = { user, vector2 }
const nested_dv = filledDataView([ const nested_dv = filledDataView([
0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x14, // user_head
0x3F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // vector2
0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // vector2.x
0x3F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // vector2.y
0x00, 0x00, 0x00, 0x0C, // user
0x00, 0x00, 0x00, 0x05, 0x3F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // user.age
0x68, 0x65, 0x6C, 0x6C, 0x6F, 0x00, 0x00, 0x00, 0x0C, // user.name_head
// user.name
0x00, 0x00, 0x00, 0x05, // user.name.size
0x68, 0x65, 0x6C, 0x6C, 0x6F, // user.name.data
]) ])
test('serialize, nested', () => { test('serialize, nested', () => {
@ -67,4 +71,36 @@ describe(Struct.name, () => {
test('parse, nested', () => { test('parse, nested', () => {
expectDataViewEqual(parse(nested_dv, Nested), nested) expectDataViewEqual(parse(nested_dv, Nested), nested)
}) })
const Token = Struct({
data: Struct({ name: String }),
header: Struct({ expires: Number }),
signature: ConstDataView(4),
})
const token = {
data: { name: 'sek1ro' },
header: { expires: 1 },
signature: sizedDataView(4),
}
const token_dv = filledDataView([
0x00, 0x00, 0x00, 0x10, // data_head
// header
0x3F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // header.expires
0x00, 0x00, 0x00, 0x00, // signature
// data
0x00, 0x00, 0x00, 0x04, // data.name_head
// data.name
0x00, 0x00, 0x00, 0x06,
0x73, 0x65, 0x6b, 0x31, 0x72, 0x6f,
])
test('serialize, Token', () => {
const dv = sizedDataView(sizeof(token, Token))
serialize(dv, token, Token)
expectDataViewEqual(dv, token_dv)
})
test('parse, Token', () => {
expectDataViewEqual(parse(token_dv, Token), token)
})
}) })

View File

@ -1,5 +1,3 @@
import { expect } from "vitest"
export function filledDataView(bytes) { export function filledDataView(bytes) {
const ab = new ArrayBuffer(bytes.length) const ab = new ArrayBuffer(bytes.length)
const dv = new DataView(ab) const dv = new DataView(ab)
@ -19,17 +17,19 @@ export function sizedDataView(length) {
export function expectDataViewEqual(actual, expected) { export function expectDataViewEqual(actual, expected) {
const actualBytes = new Uint8Array(actual.buffer, actual.byteOffset, actual.byteLength) const actualBytes = new Uint8Array(actual.buffer, actual.byteOffset, actual.byteLength)
const expectedBytes = new Uint8Array(expected.buffer, expected.byteOffset, expected.byteLength) const expectedBytes = new Uint8Array(expected.buffer, expected.byteOffset, expected.byteLength)
const arraysToString = () => {
return `actual: [${Array.from(actualBytes).map(byte => '0x' + byte.toString(16)).join(', ')}]\n` +
`expected: [${Array.from(expectedBytes).map(byte => '0x' + byte.toString(16)).join(', ')}]`
}
if (actualBytes.length !== expectedBytes.length) { if (actualBytes.length !== expectedBytes.length) {
throw new Error(`DataView length mismatch: ${actualBytes.length} !== ${expectedBytes.length}`) throw new Error(`DataView length mismatch: actual: ${actualBytes.length}, expected: ${expectedBytes.length}\n` + arraysToString())
} }
for (let i = 0; i < actualBytes.length; i++) { for (let i = 0; i < actualBytes.length; i++) {
if (actualBytes[i] !== expectedBytes[i]) { if (actualBytes[i] !== expectedBytes[i]) {
throw new Error( throw new Error(
`Byte mismatch at offset ${i}: 0x${actualBytes[i].toString(16)} !== 0x${expectedBytes[i].toString(16)}\n` + `Byte mismatch at offset ${i}: 0x${actualBytes[i].toString(16)} !== 0x${expectedBytes[i].toString(16)}\n` + arraysToString()
`actual: [${Array.from(actualBytes).map(byte => '0x' + byte.toString(16)).join(', ')}]\n` +
`expected: [${Array.from(expectedBytes).map(byte => '0x' + byte.toString(16)).join(', ')}]`
) )
} }
} }