fork of https://github.com/sourcegraph/zoekt
1package index
2
3import (
4 "os"
5 "path/filepath"
6 "testing"
7
8 "github.com/google/go-cmp/cmp"
9
10 "github.com/sourcegraph/zoekt"
11)
12
13// We compare 2 simple shards before and after the transformation
14// explode(merge(shard1, shard2)). We expect the input and output shards to be
15// identical.
16func TestExplode(t *testing.T) {
17 simpleShards := []string{
18 ".././testdata/shards/repo_v16.00000.zoekt",
19 ".././testdata/shards/repo2_v16.00000.zoekt",
20 }
21
22 // repo name -> IndexMetadata
23 m := make(map[string]*zoekt.IndexMetadata, 2)
24
25 // merge
26 var files []IndexFile
27 for _, fn := range simpleShards {
28 f, err := os.Open(fn)
29 if err != nil {
30 t.Fatal(err)
31 }
32 defer f.Close()
33
34 indexFile, err := NewIndexFile(f)
35 if err != nil {
36 t.Fatal(err)
37 }
38 defer indexFile.Close()
39
40 // We save indexMeta because the fields ID and IndexTime are the 2 sources of
41 // non-determinism when building a new shard.
42 repoMeta, indexMeta, err := ReadMetadata(indexFile)
43 if err != nil {
44 t.Fatal(err)
45 }
46 if len(repoMeta) != 1 {
47 t.Fatal("this test assumes that indexFile contains only 1 repo")
48 }
49 m[repoMeta[0].Name] = indexMeta
50
51 files = append(files, indexFile)
52 }
53
54 tmpDir := t.TempDir()
55 tmpName, dstName, err := Merge(tmpDir, files...)
56 if err != nil {
57 t.Fatal(err)
58 }
59 err = os.Rename(tmpName, dstName)
60 if err != nil {
61 t.Fatal(err)
62 }
63
64 // explode
65 f, err := os.Open(dstName)
66 if err != nil {
67 t.Fatal(err)
68 }
69 defer f.Close()
70
71 indexFile, err := NewIndexFile(f)
72 if err != nil {
73 t.Fatal(err)
74 }
75 defer indexFile.Close()
76
77 overwriteIndexTimeAndID := func(ib *ShardBuilder) {
78 ib.ID = m[ib.repoList[0].Name].ID
79 ib.IndexTime = m[ib.repoList[0].Name].IndexTime
80 }
81 exploded, err := explode(tmpDir, indexFile, overwriteIndexTimeAndID)
82 if err != nil {
83 t.Fatal(err)
84 }
85 for tmp, final := range exploded {
86 err = os.Rename(tmp, final)
87 if err != nil {
88 t.Fatal(err)
89 }
90 }
91
92 for _, s := range simpleShards {
93 checkSameShards(t, s, filepath.Join(tmpDir, filepath.Base(s)))
94 }
95}
96
97// checkSameShards compares 2 shards byte by byte. The shards are expected to be
98// small enough to be read in all at once.
99func checkSameShards(t *testing.T, shard1, shard2 string) {
100 t.Helper()
101 b1, err := os.ReadFile(shard1)
102 if err != nil {
103 t.Fatal(err)
104 }
105
106 b2, err := os.ReadFile(shard2)
107 if err != nil {
108 t.Fatal(err)
109 }
110
111 // We could also use bytes.Equal, but the output of cmd.Diff is very helpful for
112 // differences in metadata.
113 d := cmp.Diff(b1, b2)
114 if d == "" {
115 return
116 }
117
118 if *update {
119 t.Logf("updating %s", shard1)
120 err := os.WriteFile(shard1, b2, 0o600)
121 if err != nil {
122 t.Fatal(err)
123 }
124 return
125 }
126
127 t.Fatalf("-%s\n+%s:\n%s", shard1, shard2, d)
128}