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