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