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

Configure Feed

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

at main 7.0 kB View raw
1package gitindex 2 3import ( 4 "bytes" 5 "io" 6 "os" 7 "os/exec" 8 "path/filepath" 9 "strings" 10 "testing" 11 12 "github.com/go-git/go-git/v5/plumbing" 13) 14 15// createTestRepo creates a git repo with various test files and returns 16// the repo path and a map of filename -> blob SHA. 17func createTestRepo(t *testing.T) (string, map[string]plumbing.Hash) { 18 t.Helper() 19 dir := t.TempDir() 20 repoDir := filepath.Join(dir, "repo") 21 22 runGit(t, dir, "init", "-b", "main", "repo") 23 24 files := []struct { 25 name string 26 content []byte 27 }{ 28 {name: "hello.txt", content: []byte("hello world\n")}, 29 {name: "empty.txt"}, 30 {name: "binary.bin", content: []byte{0x00, 0x01, 0x02, '\n', 'h', 'e', 'l', 'l', 'o', '\n', 'w', 'o', 'r', 'l', 'd', '\n', 0x03, 0x04}}, 31 {name: "large.bin", content: bytes.Repeat([]byte("0123456789abcdef"), 4096)}, 32 } 33 34 for _, file := range files { 35 if err := os.WriteFile(filepath.Join(repoDir, file.name), file.content, 0o644); err != nil { 36 t.Fatalf("WriteFile(%q): %v", file.name, err) 37 } 38 } 39 40 runGit(t, repoDir, "add", ".") 41 runGit(t, repoDir, "commit", "-m", "initial") 42 43 // Get blob SHAs for each file. 44 blobs := map[string]plumbing.Hash{} 45 for _, file := range files { 46 name := file.name 47 out, err := exec.Command("git", "-C", repoDir, "rev-parse", "HEAD:"+name).Output() 48 if err != nil { 49 t.Fatalf("rev-parse %s: %v", name, err) 50 } 51 sha := strings.TrimSpace(string(out)) 52 blobs[name] = plumbing.NewHash(sha) 53 } 54 55 return repoDir, blobs 56} 57 58func TestCatfileReader(t *testing.T) { 59 t.Parallel() 60 61 repoDir, blobs := createTestRepo(t) 62 63 ids := []plumbing.Hash{ 64 blobs["hello.txt"], 65 blobs["empty.txt"], 66 blobs["binary.bin"], 67 blobs["large.bin"], 68 } 69 70 cr, err := newCatfileReader(repoDir, ids, catfileReaderOptions{}) 71 if err != nil { 72 t.Fatalf("newCatfileReader: %v", err) 73 } 74 defer cr.Close() 75 76 // hello.txt 77 size, missing, excluded, err := cr.Next() 78 if err != nil { 79 t.Fatalf("Next hello.txt: %v", err) 80 } 81 if missing || excluded { 82 t.Fatal("hello.txt unexpectedly missing") 83 } 84 if size != 12 { 85 t.Errorf("hello.txt size = %d, want 12", size) 86 } 87 content := make([]byte, size) 88 if _, err := io.ReadFull(cr, content); err != nil { 89 t.Fatalf("ReadFull hello.txt: %v", err) 90 } 91 if string(content) != "hello world\n" { 92 t.Errorf("hello.txt content = %q", content) 93 } 94 95 // empty.txt 96 size, missing, excluded, err = cr.Next() 97 if err != nil { 98 t.Fatalf("Next empty.txt: %v", err) 99 } 100 if missing || excluded { 101 t.Fatal("empty.txt unexpectedly missing") 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, excluded, err = cr.Next() 109 if err != nil { 110 t.Fatalf("Next binary.bin: %v", err) 111 } 112 if missing || excluded { 113 t.Fatal("binary.bin unexpectedly missing") 114 } 115 binContent := make([]byte, size) 116 if _, err := io.ReadFull(cr, binContent); err != nil { 117 t.Fatalf("ReadFull binary.bin: %v", err) 118 } 119 if binContent[0] != 0x00 || binContent[3] != '\n' { 120 t.Errorf("binary.bin unexpected leading bytes: %x", binContent[:5]) 121 } 122 123 // large.bin 124 size, missing, excluded, err = cr.Next() 125 if err != nil { 126 t.Fatalf("Next large.bin: %v", err) 127 } 128 if missing || excluded { 129 t.Fatal("large.bin unexpectedly missing") 130 } 131 if size != 64*1024 { 132 t.Errorf("large.bin size = %d, want %d", size, 64*1024) 133 } 134 largeContent := make([]byte, size) 135 if _, err := io.ReadFull(cr, largeContent); err != nil { 136 t.Fatalf("ReadFull large.bin: %v", err) 137 } 138 139 // EOF after all entries. 140 _, _, _, err = cr.Next() 141 if err != io.EOF { 142 t.Errorf("expected io.EOF after last entry, got %v", err) 143 } 144} 145 146func TestCatfileReader_Skip(t *testing.T) { 147 t.Parallel() 148 149 repoDir, blobs := createTestRepo(t) 150 151 ids := []plumbing.Hash{ 152 blobs["hello.txt"], 153 blobs["large.bin"], 154 blobs["binary.bin"], 155 } 156 157 cr, err := newCatfileReader(repoDir, ids, catfileReaderOptions{}) 158 if err != nil { 159 t.Fatalf("newCatfileReader: %v", err) 160 } 161 defer cr.Close() 162 163 // Skip hello.txt by calling Next again without reading. 164 _, _, _, err = cr.Next() 165 if err != nil { 166 t.Fatalf("Next hello.txt: %v", err) 167 } 168 169 // Skip large.bin too. 170 size, _, _, err := cr.Next() 171 if err != nil { 172 t.Fatalf("Next large.bin: %v", err) 173 } 174 if size != 64*1024 { 175 t.Errorf("large.bin size = %d, want %d", size, 64*1024) 176 } 177 178 // Read binary.bin after skipping two entries. 179 size, _, _, err = cr.Next() 180 if err != nil { 181 t.Fatalf("Next binary.bin: %v", err) 182 } 183 content := make([]byte, size) 184 if _, err := io.ReadFull(cr, content); err != nil { 185 t.Fatalf("ReadFull binary.bin: %v", err) 186 } 187 if content[0] != 0x00 { 188 t.Errorf("binary.bin first byte = %x, want 0x00", content[0]) 189 } 190} 191 192func TestCatfileReader_Missing(t *testing.T) { 193 t.Parallel() 194 195 repoDir, blobs := createTestRepo(t) 196 197 fakeHash := plumbing.NewHash("deadbeefdeadbeefdeadbeefdeadbeefdeadbeef") 198 ids := []plumbing.Hash{ 199 blobs["hello.txt"], 200 fakeHash, 201 blobs["empty.txt"], 202 } 203 204 cr, err := newCatfileReader(repoDir, ids, catfileReaderOptions{}) 205 if err != nil { 206 t.Fatalf("newCatfileReader: %v", err) 207 } 208 defer cr.Close() 209 210 // hello.txt — read normally. 211 size, missing, excluded, err := cr.Next() 212 if err != nil || missing || excluded { 213 t.Fatalf("Next hello.txt: err=%v missing=%v excluded=%v", err, missing, excluded) 214 } 215 content := make([]byte, size) 216 if _, err := io.ReadFull(cr, content); err != nil { 217 t.Fatalf("ReadFull hello.txt: %v", err) 218 } 219 if string(content) != "hello world\n" { 220 t.Errorf("hello.txt = %q", content) 221 } 222 223 // fakeHash — missing. 224 _, missing, excluded, err = cr.Next() 225 if err != nil { 226 t.Fatalf("Next fakeHash: %v", err) 227 } 228 if excluded { 229 t.Error("expected fakeHash to be missing, not excluded") 230 } 231 if !missing { 232 t.Error("expected fakeHash to be missing") 233 } 234 235 // empty.txt — still works after missing entry. 236 size, missing, excluded, err = cr.Next() 237 if err != nil || missing || excluded { 238 t.Fatalf("Next empty.txt: err=%v missing=%v excluded=%v", err, missing, excluded) 239 } 240 if size != 0 { 241 t.Errorf("empty.txt size = %d, want 0", size) 242 } 243} 244 245func TestCatfileReader_Excluded(t *testing.T) { 246 t.Parallel() 247 248 repoDir, blobs := createTestRepo(t) 249 250 ids := []plumbing.Hash{ 251 blobs["large.bin"], 252 blobs["hello.txt"], 253 } 254 255 cr, err := newCatfileReader(repoDir, ids, catfileReaderOptions{filterSpec: "blob:limit=1k"}) 256 if err != nil { 257 t.Fatalf("newCatfileReader: %v", err) 258 } 259 defer cr.Close() 260 261 _, missing, excluded, err := cr.Next() 262 if err != nil { 263 t.Fatalf("Next large.bin: %v", err) 264 } 265 if missing { 266 t.Fatal("large.bin unexpectedly missing") 267 } 268 if !excluded { 269 t.Fatal("large.bin unexpectedly included") 270 } 271 272 size, missing, excluded, err := cr.Next() 273 if err != nil { 274 t.Fatalf("Next hello.txt: %v", err) 275 } 276 if missing || excluded { 277 t.Fatalf("hello.txt unexpectedly skipped: missing=%v excluded=%v", missing, excluded) 278 } 279 content := make([]byte, size) 280 if _, err := io.ReadFull(cr, content); err != nil { 281 t.Fatalf("ReadFull hello.txt: %v", err) 282 } 283 if string(content) != "hello world\n" { 284 t.Errorf("hello.txt = %q", content) 285 } 286}