···103103 }
104104 }
105105}
106106+107107+// WithSearcher returns Streamer composed of s and the streaming client. All
108108+// non-streaming calls will go via s, while streaming calls will go via the
109109+// streaming client.
110110+func (c *Client) WithSearcher(s zoekt.Searcher) zoekt.Streamer {
111111+ return &streamer{
112112+ Searcher: s,
113113+ Client: c,
114114+ }
115115+}
116116+117117+type streamer struct {
118118+ zoekt.Searcher
119119+ *Client
120120+}
+76
web/e2e_test.go
···2424 "net/http"
2525 "net/http/httptest"
2626 "reflect"
2727+ "sort"
2728 "strings"
2829 "testing"
2930 "time"
···3132 "github.com/google/go-cmp/cmp"
3233 "github.com/sourcegraph/zoekt"
3334 "github.com/sourcegraph/zoekt/query"
3535+ "github.com/sourcegraph/zoekt/rpc"
3636+ "github.com/sourcegraph/zoekt/stream"
3437)
35383639// TODO(hanwen): cut & paste from ../ . Should create internal test
···955958 t.Fatal("empty result in response")
956959 }
957960}
961961+962962+func TestRPC(t *testing.T) {
963963+ b, err := zoekt.NewIndexBuilder(&zoekt.Repository{
964964+ Name: "name",
965965+ URL: "repo-url",
966966+ CommitURLTemplate: "{{.Version}}",
967967+ FileURLTemplate: "file-url",
968968+ LineFragmentTemplate: "#line",
969969+ Branches: []zoekt.RepositoryBranch{{Name: "master", Version: "1234"}},
970970+ })
971971+ if err != nil {
972972+ t.Fatalf("NewIndexBuilder: %v", err)
973973+ }
974974+ if err := b.Add(zoekt.Document{
975975+ Name: "f2",
976976+ Content: []byte("to carry water in the no later bla"),
977977+ // --------------0123456789012345678901234567890123
978978+ // --------------0 1 2 3
979979+ Branches: []string{"master"},
980980+ }); err != nil {
981981+ t.Fatalf("Add: %v", err)
982982+ }
983983+984984+ s := searcherForTest(t, b)
985985+ srv := Server{
986986+ Searcher: s,
987987+ RPC: true,
988988+ Top: Top,
989989+ }
990990+991991+ mux, err := NewMux(&srv)
992992+ if err != nil {
993993+ t.Fatalf("NewMux: %v", err)
994994+ }
995995+996996+ ts := httptest.NewServer(mux)
997997+ defer ts.Close()
998998+999999+ endpoint := ts.Listener.Addr().String()
10001000+10011001+ client := stream.NewClient("http://"+endpoint, nil).WithSearcher(rpc.Client(endpoint))
10021002+10031003+ ctx := context.Background()
10041004+ q := &query.Substring{Pattern: "water"}
10051005+ opts := &zoekt.SearchOptions{ChunkMatches: true}
10061006+ opts.SetDefaults()
10071007+ results, err := client.Search(ctx, q, opts)
10081008+ if err != nil {
10091009+ t.Fatal(err)
10101010+ }
10111011+10121012+ assertResults(t, results.Files, "f2: to carry water in the no later bla")
10131013+10141014+ // TODO grpc, List, StreamSearch
10151015+}
10161016+10171017+func assertResults(t *testing.T, files []zoekt.FileMatch, want string) {
10181018+ t.Helper()
10191019+10201020+ var lines []string
10211021+ for _, fm := range files {
10221022+ for _, cm := range fm.ChunkMatches {
10231023+ lines = append(lines, fmt.Sprintf("%s: %s", fm.FileName, string(cm.Content)))
10241024+ }
10251025+ }
10261026+ sort.Strings(lines)
10271027+ got := strings.TrimSpace(strings.Join(lines, "\n"))
10281028+ want = strings.TrimSpace(want)
10291029+10301030+ if d := cmp.Diff(want, got); d != "" {
10311031+ t.Fatalf("unexpected results (-want, +got):\n%s", d)
10321032+ }
10331033+}