mirror your GitHub repos to tangled.org automatically
1

Configure Feed

Select the types of activity you want to include in your feed.

at main 3.8 kB View raw
1import { describe, expect, it } from 'vitest' 2import { encodePktLine, flushPkt, lineToString, PktLineReader } from '../../server/utils/git-wire/pkt-line' 3 4async function* chunks(...parts: (Buffer | string)[]): AsyncGenerator<Buffer> { 5 for (const p of parts) yield typeof p === 'string' ? Buffer.from(p) : p 6} 7 8describe('pkt-line', () => { 9 describe('encodePktLine', () => { 10 it('frames a payload with a 4-hex-digit length including the prefix', () => { 11 // "hello\n" is 6 bytes, +4 prefix = 10 = 0x000a. 12 expect(encodePktLine('hello\n').toString()).toBe('000ahello\n') 13 }) 14 15 it('frames an empty payload as length 4', () => { 16 expect(encodePktLine('').toString()).toBe('0004') 17 }) 18 19 it('does not append a trailing newline of its own', () => { 20 expect(encodePktLine('want abc').toString()).toBe('000cwant abc') 21 }) 22 23 it('rejects payloads larger than the max', () => { 24 expect(() => encodePktLine(Buffer.alloc(65517))).toThrow(/too large/) 25 }) 26 27 it('exposes the flush-pkt as 0000', () => { 28 expect(flushPkt.toString()).toBe('0000') 29 }) 30 }) 31 32 describe('PktLineReader', () => { 33 it('decodes consecutive lines', async () => { 34 const r = new PktLineReader(chunks('0006a\n0006b\n')) 35 expect(lineToString((await r.next() as { data: Buffer }).data)).toBe('a') 36 expect(lineToString((await r.next() as { data: Buffer }).data)).toBe('b') 37 expect(await r.next()).toBeNull() 38 }) 39 40 it('returns flush-pkts as a distinct type without ending iteration', async () => { 41 const r = new PktLineReader(chunks('0006a\n00000006b\n')) 42 expect((await r.next())!.type).toBe('line') 43 expect((await r.next())!.type).toBe('flush') 44 expect((await r.next())!.type).toBe('line') 45 expect(await r.next()).toBeNull() 46 }) 47 48 it('reassembles a line split across chunk boundaries', async () => { 49 const r = new PktLineReader(chunks('00', '0a', 'hel', 'lo\n')) 50 expect(lineToString((await r.next() as { data: Buffer }).data)).toBe('hello') 51 }) 52 53 it('readUntilFlush collects line payloads and stops at flush', async () => { 54 const r = new PktLineReader(chunks('0006a\n0006b\n0000')) 55 const lines = await r.readUntilFlush() 56 expect(lines!.map(l => lineToString(l))).toEqual(['a', 'b']) 57 }) 58 59 it('hands raw trailing bytes back via remaining(), including pre-buffered ones', async () => { 60 // One pkt-line "NAK\n" then raw pack bytes "PACK..." arriving in the 61 // same chunk: the reader must not swallow the pack head. 62 const r = new PktLineReader(chunks('0008NAK\nPACK\x00\x01\x02', 'more')) 63 const first = await r.next() 64 expect(lineToString((first as { data: Buffer }).data)).toBe('NAK') 65 66 let raw = Buffer.alloc(0) 67 for await (const c of r.remaining()) raw = Buffer.concat([raw, c]) 68 expect(raw.toString('binary')).toBe('PACK\x00\x01\x02more') 69 }) 70 71 it('throws on a truncated length prefix', async () => { 72 const r = new PktLineReader(chunks('00')) 73 await expect(r.next()).rejects.toThrow(/truncated pkt-line length/) 74 }) 75 76 it('throws on a truncated payload', async () => { 77 const r = new PktLineReader(chunks('000ahel')) 78 await expect(r.next()).rejects.toThrow(/wanted 10 bytes/) 79 }) 80 81 it('throws on a reserved length', async () => { 82 const r = new PktLineReader(chunks('0001')) 83 await expect(r.next()).rejects.toThrow(/reserved pkt-line length/) 84 }) 85 }) 86 87 describe('lineToString', () => { 88 it('strips a single trailing newline', () => { 89 expect(lineToString(Buffer.from('abc\n'))).toBe('abc') 90 }) 91 92 it('leaves a line without a trailing newline intact', () => { 93 expect(lineToString(Buffer.from('abc'))).toBe('abc') 94 }) 95 }) 96})