fork of https://github.com/sourcegraph/zoekt
0

Configure Feed

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

1package gitindex 2 3import ( 4 "io" 5 "os" 6 "os/exec" 7 "path/filepath" 8 "testing" 9 10 "github.com/go-git/go-git/v5/plumbing" 11) 12 13// createTestRepo creates a git repo with various test files and returns 14// the repo path and a map of filename -> blob SHA. 15func createTestRepo(t *testing.T) (string, map[string]plumbing.Hash) { 16 t.Helper() 17 dir := t.TempDir() 18 repoDir := filepath.Join(dir, "repo") 19 20 script := ` 21set -e 22git init -b main repo 23cd repo 24git config user.email "test@test.com" 25git config user.name "Test" 26 27# Normal text file 28echo "hello world" > hello.txt 29 30# Empty file 31touch empty.txt 32 33# Binary file with newlines embedded 34printf '\x00\x01\x02\nhello\nworld\n\x03\x04' > binary.bin 35 36# Large-ish file (64KB of data) 37dd if=/dev/urandom bs=1024 count=64 of=large.bin 2>/dev/null 38 39git add -A 40git commit -m "initial" 41` 42 cmd := exec.Command("/bin/sh", "-c", script) 43 cmd.Dir = dir 44 cmd.Stderr = os.Stderr 45 if err := cmd.Run(); err != nil { 46 t.Fatalf("create test repo: %v", err) 47 } 48 49 // Get blob SHAs for each file. 50 blobs := map[string]plumbing.Hash{} 51 for _, name := range []string{"hello.txt", "empty.txt", "binary.bin", "large.bin"} { 52 out, err := exec.Command("git", "-C", repoDir, "rev-parse", "HEAD:"+name).Output() 53 if err != nil { 54 t.Fatalf("rev-parse %s: %v", name, err) 55 } 56 sha := string(out[:len(out)-1]) // trim newline 57 blobs[name] = plumbing.NewHash(sha) 58 } 59 60 return repoDir, blobs 61} 62 63func TestCatfileReader(t *testing.T) { 64 repoDir, blobs := createTestRepo(t) 65 66 ids := []plumbing.Hash{ 67 blobs["hello.txt"], 68 blobs["empty.txt"], 69 blobs["binary.bin"], 70 blobs["large.bin"], 71 } 72 73 cr, err := newCatfileReader(repoDir, ids) 74 if err != nil { 75 t.Fatalf("newCatfileReader: %v", err) 76 } 77 defer cr.Close() 78 79 // hello.txt 80 size, missing, err := cr.Next() 81 if err != nil { 82 t.Fatalf("Next hello.txt: %v", err) 83 } 84 if missing { 85 t.Fatal("hello.txt unexpectedly missing") 86 } 87 if size != 12 { 88 t.Errorf("hello.txt size = %d, want 12", size) 89 } 90 content := make([]byte, size) 91 if _, err := io.ReadFull(cr, content); err != nil { 92 t.Fatalf("ReadFull hello.txt: %v", err) 93 } 94 if string(content) != "hello world\n" { 95 t.Errorf("hello.txt content = %q", content) 96 } 97 98 // empty.txt 99 size, missing, err = cr.Next() 100 if err != nil { 101 t.Fatalf("Next empty.txt: %v", err) 102 } 103 if size != 0 { 104 t.Errorf("empty.txt size = %d, want 0", size) 105 } 106 107 // binary.bin — read content and verify binary data survives. 108 size, missing, err = cr.Next() 109 if err != nil { 110 t.Fatalf("Next binary.bin: %v", err) 111 } 112 binContent := make([]byte, size) 113 if _, err := io.ReadFull(cr, binContent); err != nil { 114 t.Fatalf("ReadFull binary.bin: %v", err) 115 } 116 if binContent[0] != 0x00 || binContent[3] != '\n' { 117 t.Errorf("binary.bin unexpected leading bytes: %x", binContent[:5]) 118 } 119 120 // large.bin 121 size, missing, err = cr.Next() 122 if err != nil { 123 t.Fatalf("Next large.bin: %v", err) 124 } 125 if size != 64*1024 { 126 t.Errorf("large.bin size = %d, want %d", size, 64*1024) 127 } 128 largeContent := make([]byte, size) 129 if _, err := io.ReadFull(cr, largeContent); err != nil { 130 t.Fatalf("ReadFull large.bin: %v", err) 131 } 132 133 // EOF after all entries. 134 _, _, err = cr.Next() 135 if err != io.EOF { 136 t.Errorf("expected io.EOF after last entry, got %v", err) 137 } 138} 139 140func TestCatfileReader_Skip(t *testing.T) { 141 repoDir, blobs := createTestRepo(t) 142 143 ids := []plumbing.Hash{ 144 blobs["hello.txt"], 145 blobs["large.bin"], 146 blobs["binary.bin"], 147 } 148 149 cr, err := newCatfileReader(repoDir, ids) 150 if err != nil { 151 t.Fatalf("newCatfileReader: %v", err) 152 } 153 defer cr.Close() 154 155 // Skip hello.txt by calling Next again without reading. 156 _, _, err = cr.Next() 157 if err != nil { 158 t.Fatalf("Next hello.txt: %v", err) 159 } 160 161 // Skip large.bin too. 162 size, _, err := cr.Next() 163 if err != nil { 164 t.Fatalf("Next large.bin: %v", err) 165 } 166 if size != 64*1024 { 167 t.Errorf("large.bin size = %d, want %d", size, 64*1024) 168 } 169 170 // Read binary.bin after skipping two entries. 171 size, _, err = cr.Next() 172 if err != nil { 173 t.Fatalf("Next binary.bin: %v", err) 174 } 175 content := make([]byte, size) 176 if _, err := io.ReadFull(cr, content); err != nil { 177 t.Fatalf("ReadFull binary.bin: %v", err) 178 } 179 if content[0] != 0x00 { 180 t.Errorf("binary.bin first byte = %x, want 0x00", content[0]) 181 } 182} 183 184func TestCatfileReader_Missing(t *testing.T) { 185 repoDir, blobs := createTestRepo(t) 186 187 fakeHash := plumbing.NewHash("deadbeefdeadbeefdeadbeefdeadbeefdeadbeef") 188 ids := []plumbing.Hash{ 189 blobs["hello.txt"], 190 fakeHash, 191 blobs["empty.txt"], 192 } 193 194 cr, err := newCatfileReader(repoDir, ids) 195 if err != nil { 196 t.Fatalf("newCatfileReader: %v", err) 197 } 198 defer cr.Close() 199 200 // hello.txt — read normally. 201 size, missing, err := cr.Next() 202 if err != nil || missing { 203 t.Fatalf("Next hello.txt: err=%v missing=%v", err, missing) 204 } 205 content := make([]byte, size) 206 if _, err := io.ReadFull(cr, content); err != nil { 207 t.Fatalf("ReadFull hello.txt: %v", err) 208 } 209 if string(content) != "hello world\n" { 210 t.Errorf("hello.txt = %q", content) 211 } 212 213 // fakeHash — missing. 214 _, missing, err = cr.Next() 215 if err != nil { 216 t.Fatalf("Next fakeHash: %v", err) 217 } 218 if !missing { 219 t.Error("expected fakeHash to be missing") 220 } 221 222 // empty.txt — still works after missing entry. 223 size, missing, err = cr.Next() 224 if err != nil || missing { 225 t.Fatalf("Next empty.txt: err=%v missing=%v", err, missing) 226 } 227 if size != 0 { 228 t.Errorf("empty.txt size = %d, want 0", size) 229 } 230}