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