morphit/node_modules/cborg/test/test-encodeInto.js

246 lines
7 KiB
JavaScript

/* eslint-env mocha */
import * as chai from 'chai'
import { encode, encodeInto } from '../cborg.js'
import { toHex } from '../lib/byte-utils.js'
const { assert } = chai
describe('encodeInto', () => {
describe('basic functionality', () => {
it('should encode into provided buffer and return { written }', () => {
const dest = new Uint8Array(100)
const result = encodeInto({ a: 1, b: [2, 3] }, dest)
// Result should be { written: number } matching TextEncoder.encodeInto pattern
assert.isObject(result)
assert.property(result, 'written')
assert.isNumber(result.written)
// Should match normal encode output
const expected = encode({ a: 1, b: [2, 3] })
assert.strictEqual(result.written, expected.length)
assert.strictEqual(toHex(dest.subarray(0, result.written)), toHex(expected))
})
it('should return correct written count', () => {
const dest = new Uint8Array(100)
const { written } = encodeInto(42, dest)
const expected = encode(42)
assert.strictEqual(written, expected.length)
assert.strictEqual(toHex(dest.subarray(0, written)), toHex(expected))
})
})
describe('quickEncodeToken bypass bug', () => {
// These tests verify that simple values that would normally be handled
// by quickEncodeToken still write to the destination buffer
it('should write small integers (0-23) to destination buffer', () => {
const dest = new Uint8Array(10)
dest.fill(0xff) // Fill with sentinel value
const { written } = encodeInto(5, dest)
// Verify the value was actually written to dest
assert.strictEqual(written, 1)
assert.strictEqual(dest[0], 0x05, 'value should be written to dest[0]')
})
it('should write integer 0 to destination buffer', () => {
const dest = new Uint8Array(10)
dest.fill(0xff)
const { written } = encodeInto(0, dest)
assert.strictEqual(written, 1)
assert.strictEqual(dest[0], 0x00)
})
it('should write integer 23 to destination buffer', () => {
const dest = new Uint8Array(10)
dest.fill(0xff)
const { written } = encodeInto(23, dest)
assert.strictEqual(written, 1)
assert.strictEqual(dest[0], 0x17)
})
it('should write true to destination buffer', () => {
const dest = new Uint8Array(10)
dest.fill(0xff)
const { written } = encodeInto(true, dest)
assert.strictEqual(written, 1)
assert.strictEqual(dest[0], 0xf5) // CBOR true
})
it('should write false to destination buffer', () => {
const dest = new Uint8Array(10)
dest.fill(0xff)
const { written } = encodeInto(false, dest)
assert.strictEqual(written, 1)
assert.strictEqual(dest[0], 0xf4) // CBOR false
})
it('should write null to destination buffer', () => {
const dest = new Uint8Array(10)
dest.fill(0xff)
const { written } = encodeInto(null, dest)
assert.strictEqual(written, 1)
assert.strictEqual(dest[0], 0xf6) // CBOR null
})
it('should write empty string to destination buffer', () => {
const dest = new Uint8Array(10)
dest.fill(0xff)
const { written } = encodeInto('', dest)
assert.strictEqual(written, 1)
assert.strictEqual(dest[0], 0x60) // CBOR empty string
})
it('should write empty array to destination buffer', () => {
const dest = new Uint8Array(10)
dest.fill(0xff)
const { written } = encodeInto([], dest)
assert.strictEqual(written, 1)
assert.strictEqual(dest[0], 0x80) // CBOR empty array
})
it('should write empty object to destination buffer', () => {
const dest = new Uint8Array(10)
dest.fill(0xff)
const { written } = encodeInto({}, dest)
assert.strictEqual(written, 1)
assert.strictEqual(dest[0], 0xa0) // CBOR empty map
})
it('should write negative integers (-1 to -24) to destination buffer', () => {
const dest = new Uint8Array(10)
dest.fill(0xff)
const { written } = encodeInto(-1, dest)
assert.strictEqual(written, 1)
assert.strictEqual(dest[0], 0x20) // CBOR -1
})
})
describe('buffer overflow', () => {
it('should throw when destination buffer is too small', () => {
const dest = new Uint8Array(1) // Too small for { a: 1 }
assert.throws(
() => encodeInto({ a: 1 }, dest),
/write out of bounds|destination buffer is too small/
)
})
it('should throw when destination buffer is empty', () => {
const dest = new Uint8Array(0)
assert.throws(
() => encodeInto(1, dest),
/write out of bounds|destination buffer is too small/
)
})
it('should throw when destination is exactly one byte too small', () => {
const data = { key: 'value' }
const needed = encode(data).length
const dest = new Uint8Array(needed - 1)
assert.throws(
() => encodeInto(data, dest),
/write out of bounds|destination buffer is too small/
)
})
it('should succeed when destination is exactly the right size', () => {
const data = { key: 'value' }
const needed = encode(data).length
const dest = new Uint8Array(needed)
const { written } = encodeInto(data, dest)
assert.strictEqual(written, needed)
assert.strictEqual(toHex(dest.subarray(0, written)), toHex(encode(data)))
})
})
describe('data integrity', () => {
it('should produce identical output to encode()', () => {
const testCases = [
0,
1,
23,
24,
255,
256,
65535,
65536,
-1,
-24,
-25,
-256,
true,
false,
null,
'',
'hello',
'a'.repeat(100),
[],
[1, 2, 3],
{},
{ a: 1 },
{ nested: { deeply: { value: [1, 2, 3] } } },
new Uint8Array([1, 2, 3]),
1.5,
-1.5,
Math.PI
]
for (const data of testCases) {
const expected = encode(data)
const dest = new Uint8Array(expected.length + 10)
const { written } = encodeInto(data, dest)
assert.strictEqual(written, expected.length,
`encodeInto should return correct written count for: ${JSON.stringify(data)}`)
assert.strictEqual(toHex(dest.subarray(0, written)), toHex(expected),
`encodeInto should match encode for: ${JSON.stringify(data)}`)
}
})
})
describe('buffer reuse pattern', () => {
it('should support reusing the same buffer for multiple encodes', () => {
const dest = new Uint8Array(100)
// First encode
const { written: written1 } = encodeInto({ a: 1 }, dest)
const hex1 = toHex(dest.subarray(0, written1))
// Second encode into same buffer (overwrites from start)
const { written: written2 } = encodeInto({ b: 2 }, dest)
const hex2 = toHex(dest.subarray(0, written2))
// Both should be correct
assert.strictEqual(hex1, toHex(encode({ a: 1 })))
assert.strictEqual(hex2, toHex(encode({ b: 2 })))
})
})
})