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, catfileReaderOptions{}) 74 if err != nil { 75 t.Fatalf("newCatfileReader: %v", err) 76 } 77 defer cr.Close() 78 79 // hello.txt 80 size, missing, excluded, err := cr.Next() 81 if err != nil { 82 t.Fatalf("Next hello.txt: %v", err) 83 } 84 if missing || excluded { 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, excluded, err = cr.Next() 100 if err != nil { 101 t.Fatalf("Next empty.txt: %v", err) 102 } 103 if missing || excluded { 104 t.Fatal("empty.txt unexpectedly missing") 105 } 106 if size != 0 { 107 t.Errorf("empty.txt size = %d, want 0", size) 108 } 109 110 // binary.bin — read content and verify binary data survives. 111 size, missing, excluded, err = cr.Next() 112 if err != nil { 113 t.Fatalf("Next binary.bin: %v", err) 114 } 115 if missing || excluded { 116 t.Fatal("binary.bin unexpectedly missing") 117 } 118 binContent := make([]byte, size) 119 if _, err := io.ReadFull(cr, binContent); err != nil { 120 t.Fatalf("ReadFull binary.bin: %v", err) 121 } 122 if binContent[0] != 0x00 || binContent[3] != '\n' { 123 t.Errorf("binary.bin unexpected leading bytes: %x", binContent[:5]) 124 } 125 126 // large.bin 127 size, missing, excluded, err = cr.Next() 128 if err != nil { 129 t.Fatalf("Next large.bin: %v", err) 130 } 131 if missing || excluded { 132 t.Fatal("large.bin unexpectedly missing") 133 } 134 if size != 64*1024 { 135 t.Errorf("large.bin size = %d, want %d", size, 64*1024) 136 } 137 largeContent := make([]byte, size) 138 if _, err := io.ReadFull(cr, largeContent); err != nil { 139 t.Fatalf("ReadFull large.bin: %v", err) 140 } 141 142 // EOF after all entries. 143 _, _, _, err = cr.Next() 144 if err != io.EOF { 145 t.Errorf("expected io.EOF after last entry, got %v", err) 146 } 147} 148 149func TestCatfileReader_Skip(t *testing.T) { 150 repoDir, blobs := createTestRepo(t) 151 152 ids := []plumbing.Hash{ 153 blobs["hello.txt"], 154 blobs["large.bin"], 155 blobs["binary.bin"], 156 } 157 158 cr, err := newCatfileReader(repoDir, ids, catfileReaderOptions{}) 159 if err != nil { 160 t.Fatalf("newCatfileReader: %v", err) 161 } 162 defer cr.Close() 163 164 // Skip hello.txt by calling Next again without reading. 165 _, _, _, err = cr.Next() 166 if err != nil { 167 t.Fatalf("Next hello.txt: %v", err) 168 } 169 170 // Skip large.bin too. 171 size, _, _, err := cr.Next() 172 if err != nil { 173 t.Fatalf("Next large.bin: %v", err) 174 } 175 if size != 64*1024 { 176 t.Errorf("large.bin size = %d, want %d", size, 64*1024) 177 } 178 179 // Read binary.bin after skipping two entries. 180 size, _, _, err = cr.Next() 181 if err != nil { 182 t.Fatalf("Next binary.bin: %v", err) 183 } 184 content := make([]byte, size) 185 if _, err := io.ReadFull(cr, content); err != nil { 186 t.Fatalf("ReadFull binary.bin: %v", err) 187 } 188 if content[0] != 0x00 { 189 t.Errorf("binary.bin first byte = %x, want 0x00", content[0]) 190 } 191} 192 193func TestCatfileReader_Missing(t *testing.T) { 194 repoDir, blobs := createTestRepo(t) 195 196 fakeHash := plumbing.NewHash("deadbeefdeadbeefdeadbeefdeadbeefdeadbeef") 197 ids := []plumbing.Hash{ 198 blobs["hello.txt"], 199 fakeHash, 200 blobs["empty.txt"], 201 } 202 203 cr, err := newCatfileReader(repoDir, ids, catfileReaderOptions{}) 204 if err != nil { 205 t.Fatalf("newCatfileReader: %v", err) 206 } 207 defer cr.Close() 208 209 // hello.txt — read normally. 210 size, missing, excluded, err := cr.Next() 211 if err != nil || missing || excluded { 212 t.Fatalf("Next hello.txt: err=%v missing=%v excluded=%v", err, missing, excluded) 213 } 214 content := make([]byte, size) 215 if _, err := io.ReadFull(cr, content); err != nil { 216 t.Fatalf("ReadFull hello.txt: %v", err) 217 } 218 if string(content) != "hello world\n" { 219 t.Errorf("hello.txt = %q", content) 220 } 221 222 // fakeHash — missing. 223 _, missing, excluded, err = cr.Next() 224 if err != nil { 225 t.Fatalf("Next fakeHash: %v", err) 226 } 227 if excluded { 228 t.Error("expected fakeHash to be missing, not excluded") 229 } 230 if !missing { 231 t.Error("expected fakeHash to be missing") 232 } 233 234 // empty.txt — still works after missing entry. 235 size, missing, excluded, err = cr.Next() 236 if err != nil || missing || excluded { 237 t.Fatalf("Next empty.txt: err=%v missing=%v excluded=%v", err, missing, excluded) 238 } 239 if size != 0 { 240 t.Errorf("empty.txt size = %d, want 0", size) 241 } 242} 243 244func TestCatfileReader_Excluded(t *testing.T) { 245 repoDir, blobs := createTestRepo(t) 246 247 ids := []plumbing.Hash{ 248 blobs["large.bin"], 249 blobs["hello.txt"], 250 } 251 252 cr, err := newCatfileReader(repoDir, ids, catfileReaderOptions{filterSpec: "blob:limit=1k"}) 253 if err != nil { 254 t.Fatalf("newCatfileReader: %v", err) 255 } 256 defer cr.Close() 257 258 _, missing, excluded, err := cr.Next() 259 if err != nil { 260 t.Fatalf("Next large.bin: %v", err) 261 } 262 if missing { 263 t.Fatal("large.bin unexpectedly missing") 264 } 265 if !excluded { 266 t.Fatal("large.bin unexpectedly included") 267 } 268 269 size, missing, excluded, err := cr.Next() 270 if err != nil { 271 t.Fatalf("Next hello.txt: %v", err) 272 } 273 if missing || excluded { 274 t.Fatalf("hello.txt unexpectedly skipped: missing=%v excluded=%v", missing, excluded) 275 } 276 content := make([]byte, size) 277 if _, err := io.ReadFull(cr, content); err != nil { 278 t.Fatalf("ReadFull hello.txt: %v", err) 279 } 280 if string(content) != "hello world\n" { 281 t.Errorf("hello.txt = %q", content) 282 } 283}