fork of https://github.com/sourcegraph/zoekt
1package main
2
3import (
4 "context"
5 "io"
6 "os"
7 "path/filepath"
8 "sort"
9 "testing"
10
11 "github.com/sourcegraph/zoekt/search"
12 "github.com/stretchr/testify/require"
13
14 "github.com/sourcegraph/zoekt"
15 "github.com/sourcegraph/zoekt/index"
16 "github.com/sourcegraph/zoekt/query"
17)
18
19func TestMerge(t *testing.T) {
20 v16Shards, err := filepath.Glob("../../testdata/shards/*_v16.*.zoekt")
21 require.NoError(t, err)
22 sort.Strings(v16Shards)
23
24 testShards, err := copyTestShards(t.TempDir(), v16Shards)
25 require.NoError(t, err)
26 t.Log(testShards)
27
28 dir := t.TempDir()
29 cs, err := merge(dir, testShards)
30 require.NoError(t, err)
31 // The name of the compound shard is based on the merged repos, so it should be
32 // stable
33 require.Equal(t, filepath.Base(cs), "compound-ea9613e2ffba7d7361856aebfca75fb714856509_v17.00000.zoekt")
34
35 ss, err := search.NewDirectorySearcher(dir)
36 require.NoError(t, err)
37 defer ss.Close()
38
39 q, err := query.Parse("hello")
40 require.NoError(t, err)
41
42 var sOpts zoekt.SearchOptions
43 ctx := context.Background()
44 result, err := ss.Search(ctx, q, &sOpts)
45 require.NoError(t, err)
46
47 // we are merging the same shard twice, so we expect the same file twice.
48 require.Len(t, result.Files, 2)
49}
50
51// Merge 2 simple shards and then explode them.
52func TestExplode(t *testing.T) {
53 v16Shards, err := filepath.Glob("../../testdata/shards/repo*_v16.*.zoekt")
54 require.NoError(t, err)
55 sort.Strings(v16Shards)
56
57 testShards, err := copyTestShards(t.TempDir(), v16Shards)
58 require.NoError(t, err)
59 t.Log(testShards)
60
61 dir := t.TempDir()
62 _, err = merge(dir, testShards)
63 require.NoError(t, err)
64
65 cs, err := filepath.Glob(filepath.Join(dir, "compound-*.zoekt"))
66 require.NoError(t, err)
67 err = index.Explode(dir, cs[0])
68 require.NoError(t, err)
69
70 cs, err = filepath.Glob(filepath.Join(dir, "compound-*.zoekt"))
71 require.NoError(t, err)
72
73 if len(cs) != 0 {
74 t.Fatalf("explode should have deleted the compound shard if it returned without error")
75 }
76
77 exploded, err := filepath.Glob(filepath.Join(dir, "*.zoekt"))
78 require.NoError(t, err)
79
80 if len(exploded) != len(testShards) {
81 t.Fatalf("the number of simple shards before %d and after %d should be the same", len(testShards), len(exploded))
82 }
83
84 ss, err := search.NewDirectorySearcher(dir)
85 require.NoError(t, err)
86 defer ss.Close()
87
88 var sOpts zoekt.SearchOptions
89 ctx := context.Background()
90
91 cases := []struct {
92 searchLiteral string
93 wantResults int
94 }{
95 {
96 searchLiteral: "apple",
97 wantResults: 1,
98 },
99 {
100 searchLiteral: "hello",
101 wantResults: 1,
102 },
103 {
104 searchLiteral: "main",
105 wantResults: 2,
106 },
107 }
108
109 for _, c := range cases {
110 t.Run(c.searchLiteral, func(t *testing.T) {
111 q, err := query.Parse(c.searchLiteral)
112 require.NoError(t, err)
113 result, err := ss.Search(ctx, q, &sOpts)
114 require.NoError(t, err)
115 require.Len(t, result.Files, c.wantResults)
116 })
117 }
118}
119
120func copyTestShards(dstDir string, srcShards []string) ([]string, error) {
121 var tmpShards []string
122 for _, s := range srcShards {
123 dst := filepath.Join(dstDir, filepath.Base(s))
124 tmpShards = append(tmpShards, dst)
125 if err := copyFile(s, dst); err != nil {
126 return nil, err
127 }
128 }
129 return tmpShards, nil
130}
131
132func copyFile(src, dst string) (err error) {
133 s, err := os.Open(src)
134 if err != nil {
135 return err
136 }
137 defer s.Close()
138
139 d, err := os.Create(dst)
140 if err != nil {
141 return err
142 }
143 if _, err := io.Copy(d, s); err != nil {
144 d.Close()
145 return err
146 }
147 return d.Close()
148}