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

Configure Feed

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

1package archive 2 3import ( 4 "archive/tar" 5 "archive/zip" 6 "compress/gzip" 7 "context" 8 "errors" 9 "flag" 10 "fmt" 11 "io" 12 "log" 13 "os" 14 "path/filepath" 15 "strings" 16 "testing" 17 "time" 18 19 "github.com/sourcegraph/zoekt" 20 "github.com/sourcegraph/zoekt/index" 21 "github.com/sourcegraph/zoekt/query" 22 "github.com/sourcegraph/zoekt/search" 23 "github.com/stretchr/testify/require" 24) 25 26func TestMain(m *testing.M) { 27 flag.Parse() 28 if !testing.Verbose() { 29 log.SetOutput(io.Discard) 30 } 31 os.Exit(m.Run()) 32} 33 34var modTime = time.Date(2024, 9, 26, 0, 0, 0, 0, time.UTC) 35 36func writeArchive(w io.Writer, format string, files map[string]string) (err error) { 37 if format == "zip" { 38 zw := zip.NewWriter(w) 39 for name, body := range files { 40 header := &zip.FileHeader{ 41 Name: name, 42 Method: zip.Deflate, 43 Modified: modTime, 44 } 45 f, err := zw.CreateHeader(header) 46 if err != nil { 47 return err 48 } 49 if _, err := f.Write([]byte(body)); err != nil { 50 return err 51 } 52 } 53 return zw.Close() 54 } 55 56 if format == "tgz" { 57 gw := gzip.NewWriter(w) 58 defer func() { 59 err2 := gw.Close() 60 if err == nil { 61 err = err2 62 } 63 }() 64 w = gw 65 format = "tar" 66 } 67 68 if format != "tar" { 69 return errors.New("expected tar") 70 } 71 72 tw := tar.NewWriter(w) 73 74 for name, body := range files { 75 hdr := &tar.Header{ 76 Name: name, 77 Mode: 0o600, 78 Size: int64(len(body)), 79 ModTime: modTime, 80 } 81 if err := tw.WriteHeader(hdr); err != nil { 82 return err 83 } 84 if _, err := tw.Write([]byte(body)); err != nil { 85 return err 86 } 87 } 88 if err := tw.Close(); err != nil { 89 return err 90 } 91 92 return nil 93} 94 95// TestIndexArg tests zoekt-archive-index by creating an archive and then 96// indexing and executing searches and checking we get expected results. 97// Additionally, we test that the index is properly updated with the 98// -incremental=true option changing the options between indexes and ensuring 99// the results change as expected. 100func TestIndexIncrementally(t *testing.T) { 101 for _, format := range []string{"tar", "tgz", "zip"} { 102 t.Run(format, func(t *testing.T) { 103 testIndexIncrementally(t, format) 104 }) 105 } 106} 107 108func testIndexIncrementally(t *testing.T, format string) { 109 indexDir := t.TempDir() 110 111 archive, err := os.CreateTemp("", "TestIndexArg-archive") 112 if err != nil { 113 t.Fatalf("TempFile: %v", err) 114 } 115 defer os.Remove(archive.Name()) 116 117 fileSize := 1000 118 119 files := map[string]string{} 120 for i := range 4 { 121 s := fmt.Sprintf("%d", i) 122 files["F"+s] = strings.Repeat("a", fileSize) 123 files["!F"+s] = strings.Repeat("a", fileSize) 124 } 125 126 err = writeArchive(archive, format, files) 127 if err != nil { 128 t.Fatalf("unable to create archive %v", err) 129 } 130 archive.Close() 131 132 // tests contain options used to build an index and the expected number of 133 // files in the result set based on the options. 134 tests := []struct { 135 largeFiles []string 136 wantNumFiles int 137 }{ 138 { 139 largeFiles: []string{}, 140 wantNumFiles: 0, 141 }, 142 { 143 largeFiles: []string{"F0", "F2"}, 144 wantNumFiles: 2, 145 }, 146 { 147 largeFiles: []string{"F?", "!F2"}, 148 wantNumFiles: 3, 149 }, 150 { 151 largeFiles: []string{"F?", "!F2", "\\!F0"}, 152 wantNumFiles: 4, 153 }, 154 { 155 largeFiles: []string{"F?", "!F2", "\\!F0", "F2"}, 156 wantNumFiles: 5, 157 }, 158 } 159 160 for _, test := range tests { 161 largeFiles, wantNumFiles := test.largeFiles, test.wantNumFiles 162 163 bopts := index.Options{ 164 SizeMax: fileSize - 1, 165 IndexDir: indexDir, 166 LargeFiles: largeFiles, 167 } 168 opts := Options{ 169 Incremental: true, 170 Archive: archive.Name(), 171 Name: "repo", 172 Branch: "master", 173 Commit: "cccccccccccccccccccccccccccccccccccccccc", 174 Strip: 0, 175 } 176 177 if err := Index(opts, bopts); err != nil { 178 t.Fatalf("error creating index: %v", err) 179 } 180 181 ss, err := search.NewDirectorySearcher(indexDir) 182 if err != nil { 183 t.Fatalf("NewDirectorySearcher(%s): %v", indexDir, err) 184 } 185 defer ss.Close() 186 187 q, err := query.Parse("aaa") 188 if err != nil { 189 t.Fatalf("Parse(aaa): %v", err) 190 } 191 192 var sOpts zoekt.SearchOptions 193 result, err := ss.Search(context.Background(), q, &sOpts) 194 if err != nil { 195 t.Fatalf("Search(%v): %v", q, err) 196 } 197 198 if len(result.Files) != wantNumFiles { 199 t.Errorf("got %v, want %d files.", result.Files, wantNumFiles) 200 } 201 } 202} 203 204// TestLatestCommitDate tests that the latest commit date is set correctly if 205// the mod time of the files has been set during the archive creation. 206func TestLatestCommitDate(t *testing.T) { 207 for _, format := range []string{"tar", "tgz", "zip"} { 208 t.Run(format, func(t *testing.T) { 209 testLatestCommitDate(t, format) 210 }) 211 } 212} 213 214func testLatestCommitDate(t *testing.T, format string) { 215 // Create an archive 216 archive, err := os.CreateTemp("", "TestLatestCommitDate") 217 require.NoError(t, err) 218 defer os.Remove(archive.Name()) 219 220 fileSize := 10 221 files := map[string]string{} 222 for i := range 4 { 223 s := fmt.Sprintf("%d", i) 224 files["F"+s] = strings.Repeat("a", fileSize) 225 files["!F"+s] = strings.Repeat("a", fileSize) 226 } 227 228 err = writeArchive(archive, format, files) 229 if err != nil { 230 t.Fatalf("unable to create archive %v", err) 231 } 232 archive.Close() 233 234 // Index 235 indexDir := t.TempDir() 236 bopts := index.Options{ 237 IndexDir: indexDir, 238 } 239 opts := Options{ 240 Archive: archive.Name(), 241 Name: "repo", 242 Branch: "master", 243 Commit: "cccccccccccccccccccccccccccccccccccccccc", 244 } 245 246 err = Index(opts, bopts) 247 require.NoError(t, err) 248 249 // Read the metadata of the index we just created and check the latest commit date. 250 f, err := os.Open(indexDir) 251 require.NoError(t, err) 252 253 indexFiles, err := f.Readdirnames(1) 254 require.Len(t, indexFiles, 1) 255 256 repos, _, err := index.ReadMetadataPath(filepath.Join(indexDir, indexFiles[0])) 257 require.NoError(t, err) 258 require.Len(t, repos, 1) 259 require.True(t, repos[0].LatestCommitDate.Equal(modTime)) 260}