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