this repo has no description
1import { test, describe } from 'node:test'
2import assert from 'node:assert'
3import { cborEncode, createCid, cidToString, base32Encode, createTid } from '../src/pds.js'
4
5describe('CBOR Encoding', () => {
6 test('encodes simple map', () => {
7 const encoded = cborEncode({ hello: 'world', num: 42 })
8 // Expected: a2 65 68 65 6c 6c 6f 65 77 6f 72 6c 64 63 6e 75 6d 18 2a
9 const expected = new Uint8Array([
10 0xa2, 0x65, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x65, 0x77, 0x6f, 0x72, 0x6c, 0x64,
11 0x63, 0x6e, 0x75, 0x6d, 0x18, 0x2a
12 ])
13 assert.deepStrictEqual(encoded, expected)
14 })
15
16 test('encodes null', () => {
17 const encoded = cborEncode(null)
18 assert.deepStrictEqual(encoded, new Uint8Array([0xf6]))
19 })
20
21 test('encodes booleans', () => {
22 assert.deepStrictEqual(cborEncode(true), new Uint8Array([0xf5]))
23 assert.deepStrictEqual(cborEncode(false), new Uint8Array([0xf4]))
24 })
25
26 test('encodes small integers', () => {
27 assert.deepStrictEqual(cborEncode(0), new Uint8Array([0x00]))
28 assert.deepStrictEqual(cborEncode(1), new Uint8Array([0x01]))
29 assert.deepStrictEqual(cborEncode(23), new Uint8Array([0x17]))
30 })
31
32 test('encodes integers >= 24', () => {
33 assert.deepStrictEqual(cborEncode(24), new Uint8Array([0x18, 0x18]))
34 assert.deepStrictEqual(cborEncode(255), new Uint8Array([0x18, 0xff]))
35 })
36
37 test('encodes negative integers', () => {
38 assert.deepStrictEqual(cborEncode(-1), new Uint8Array([0x20]))
39 assert.deepStrictEqual(cborEncode(-10), new Uint8Array([0x29]))
40 })
41
42 test('encodes strings', () => {
43 const encoded = cborEncode('hello')
44 // 0x65 = text string of length 5
45 assert.deepStrictEqual(encoded, new Uint8Array([0x65, 0x68, 0x65, 0x6c, 0x6c, 0x6f]))
46 })
47
48 test('encodes byte strings', () => {
49 const bytes = new Uint8Array([1, 2, 3])
50 const encoded = cborEncode(bytes)
51 // 0x43 = byte string of length 3
52 assert.deepStrictEqual(encoded, new Uint8Array([0x43, 1, 2, 3]))
53 })
54
55 test('encodes arrays', () => {
56 const encoded = cborEncode([1, 2, 3])
57 // 0x83 = array of length 3
58 assert.deepStrictEqual(encoded, new Uint8Array([0x83, 0x01, 0x02, 0x03]))
59 })
60
61 test('sorts map keys deterministically', () => {
62 const encoded1 = cborEncode({ z: 1, a: 2 })
63 const encoded2 = cborEncode({ a: 2, z: 1 })
64 assert.deepStrictEqual(encoded1, encoded2)
65 // First key should be 'a' (0x61)
66 assert.strictEqual(encoded1[1], 0x61)
67 })
68})
69
70describe('Base32 Encoding', () => {
71 test('encodes bytes to base32lower', () => {
72 const bytes = new Uint8Array([0x01, 0x71, 0x12, 0x20])
73 const encoded = base32Encode(bytes)
74 assert.strictEqual(typeof encoded, 'string')
75 assert.match(encoded, /^[a-z2-7]+$/)
76 })
77})
78
79describe('CID Generation', () => {
80 test('creates CIDv1 with dag-cbor codec', async () => {
81 const data = cborEncode({ test: 'data' })
82 const cid = await createCid(data)
83
84 assert.strictEqual(cid.length, 36) // 2 prefix + 2 multihash header + 32 hash
85 assert.strictEqual(cid[0], 0x01) // CIDv1
86 assert.strictEqual(cid[1], 0x71) // dag-cbor
87 assert.strictEqual(cid[2], 0x12) // sha-256
88 assert.strictEqual(cid[3], 0x20) // 32 bytes
89 })
90
91 test('cidToString returns base32lower with b prefix', async () => {
92 const data = cborEncode({ test: 'data' })
93 const cid = await createCid(data)
94 const cidStr = cidToString(cid)
95
96 assert.strictEqual(cidStr[0], 'b')
97 assert.match(cidStr, /^b[a-z2-7]+$/)
98 })
99
100 test('same input produces same CID', async () => {
101 const data1 = cborEncode({ test: 'data' })
102 const data2 = cborEncode({ test: 'data' })
103 const cid1 = cidToString(await createCid(data1))
104 const cid2 = cidToString(await createCid(data2))
105
106 assert.strictEqual(cid1, cid2)
107 })
108
109 test('different input produces different CID', async () => {
110 const cid1 = cidToString(await createCid(cborEncode({ a: 1 })))
111 const cid2 = cidToString(await createCid(cborEncode({ a: 2 })))
112
113 assert.notStrictEqual(cid1, cid2)
114 })
115})
116
117describe('TID Generation', () => {
118 test('creates 13-character TIDs', () => {
119 const tid = createTid()
120 assert.strictEqual(tid.length, 13)
121 })
122
123 test('uses valid base32-sort characters', () => {
124 const tid = createTid()
125 assert.match(tid, /^[234567abcdefghijklmnopqrstuvwxyz]+$/)
126 })
127
128 test('generates monotonically increasing TIDs', () => {
129 const tid1 = createTid()
130 const tid2 = createTid()
131 const tid3 = createTid()
132
133 assert.ok(tid1 < tid2, `${tid1} should be less than ${tid2}`)
134 assert.ok(tid2 < tid3, `${tid2} should be less than ${tid3}`)
135 })
136
137 test('generates unique TIDs', () => {
138 const tids = new Set()
139 for (let i = 0; i < 100; i++) {
140 tids.add(createTid())
141 }
142 assert.strictEqual(tids.size, 100)
143 })
144})