115 lines · 3.6 KB
1 import { describe, it, expect } from 'vitest';
2 import {
3 serializeGitObject,
4 parseRawGitObject,
5 parseTree,
6 serializeTree,
7 parseCommit,
8 PACK_OBJECT_TYPE,
9 packTypeToString,
10 stringToPackType,
11 } from '../object.js';
12
13 const encoder = new TextEncoder();
14
15 describe('git object serialization', () => {
16 it('should round-trip serialize/parse a blob', () => {
17 const content = encoder.encode('file content here');
18 const serialized = serializeGitObject('blob', content);
19 const parsed = parseRawGitObject(serialized);
20 expect(parsed.type).toBe('blob');
21 expect(parsed.content).toEqual(content);
22 });
23
24 it('should round-trip serialize/parse a commit', () => {
25 const content = encoder.encode(
26 'tree aaaa\nparent bbbb\nauthor Test\ncommitter Test\n\ncommit message'
27 );
28 const serialized = serializeGitObject('commit', content);
29 const parsed = parseRawGitObject(serialized);
30 expect(parsed.type).toBe('commit');
31 expect(parsed.content).toEqual(content);
32 });
33
34 it('should throw on invalid object (no NUL)', () => {
35 expect(() => parseRawGitObject(encoder.encode('blob 5hello'))).toThrow();
36 });
37 });
38
39 describe('tree parsing', () => {
40 it('should round-trip tree entries', () => {
41 const entries = [
42 { mode: '100644', name: 'file.txt', sha: 'a'.repeat(40) },
43 { mode: '040000', name: 'dir', sha: 'b'.repeat(40) },
44 { mode: '120000', name: 'link', sha: 'c'.repeat(40) },
45 ];
46
47 const serialized = serializeTree(entries);
48 const parsed = parseTree(serialized);
49
50 expect(parsed).toHaveLength(3);
51 for (let i = 0; i < entries.length; i++) {
52 expect(parsed[i].mode).toBe(entries[i].mode);
53 expect(parsed[i].name).toBe(entries[i].name);
54 expect(parsed[i].sha).toBe(entries[i].sha);
55 }
56 });
57 });
58
59 describe('commit parsing', () => {
60 it('should parse a commit with parents', () => {
61 const commitContent = [
62 'tree ' + 'a'.repeat(40),
63 'parent ' + 'b'.repeat(40),
64 'parent ' + 'c'.repeat(40),
65 'author Test User <test@example.com> 1234567890 +0000',
66 'committer Test User <test@example.com> 1234567890 +0000',
67 '',
68 'Initial commit',
69 '',
70 'More details here.',
71 ].join('\n');
72
73 const parsed = parseCommit(encoder.encode(commitContent));
74
75 expect(parsed.tree).toBe('a'.repeat(40));
76 expect(parsed.parents).toEqual(['b'.repeat(40), 'c'.repeat(40)]);
77 expect(parsed.author).toBe('Test User <test@example.com> 1234567890 +0000');
78 expect(parsed.committer).toBe('Test User <test@example.com> 1234567890 +0000');
79 expect(parsed.message).toBe('Initial commit\n\nMore details here.');
80 });
81
82 it('should parse a root commit (no parents)', () => {
83 const commitContent = [
84 'tree ' + 'a'.repeat(40),
85 'author Test <test@test.com> 1000 +0000',
86 'committer Test <test@test.com> 1000 +0000',
87 '',
88 'root commit',
89 ].join('\n');
90
91 const parsed = parseCommit(encoder.encode(commitContent));
92 expect(parsed.parents).toEqual([]);
93 });
94 });
95
96 describe('pack type conversions', () => {
97 it('should convert type numbers to strings', () => {
98 expect(packTypeToString(1)).toBe('commit');
99 expect(packTypeToString(2)).toBe('tree');
100 expect(packTypeToString(3)).toBe('blob');
101 expect(packTypeToString(4)).toBe('tag');
102 });
103
104 it('should convert strings to type numbers', () => {
105 expect(stringToPackType('commit')).toBe(1);
106 expect(stringToPackType('tree')).toBe(2);
107 expect(stringToPackType('blob')).toBe(3);
108 expect(stringToPackType('tag')).toBe(4);
109 });
110
111 it('should throw for unknown type number', () => {
112 expect(() => packTypeToString(5)).toThrow();
113 });
114 });
115