1 // Copyright 2018 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
17 "golang.org/x/tools/internal/event/export/eventtest"
18 "golang.org/x/tools/internal/jsonrpc2"
19 "golang.org/x/tools/internal/stack/stacktest"
22 var logRPC = flag.Bool("logrpc", false, "Enable jsonrpc2 communication logging")
24 type callTest struct {
30 var callTests = []callTest{
31 {"no_args", nil, true},
32 {"one_string", "fish", "got:fish"},
33 {"one_number", 10, "got:10"},
34 {"join", []string{"a", "b", "c"}, "a/b/c"},
35 //TODO: expand the test cases
38 func (test *callTest) newResults() interface{} {
39 switch e := test.expect.(type) {
43 r = append(r, reflect.New(reflect.TypeOf(v)).Interface())
49 return reflect.New(reflect.TypeOf(test.expect)).Interface()
53 func (test *callTest) verifyResults(t *testing.T, results interface{}) {
57 val := reflect.Indirect(reflect.ValueOf(results)).Interface()
58 if !reflect.DeepEqual(val, test.expect) {
59 t.Errorf("%v:Results are incorrect, got %+v expect %+v", test.method, val, test.expect)
63 func TestCall(t *testing.T) {
65 ctx := eventtest.NewContext(context.Background(), t)
66 for _, headers := range []bool{false, true} {
71 t.Run(name, func(t *testing.T) {
72 ctx := eventtest.NewContext(ctx, t)
73 a, b, done := prepare(ctx, t, headers)
75 for _, test := range callTests {
76 t.Run(test.method, func(t *testing.T) {
77 ctx := eventtest.NewContext(ctx, t)
78 results := test.newResults()
79 if _, err := a.Call(ctx, test.method, test.params, results); err != nil {
80 t.Fatalf("%v:Call failed: %v", test.method, err)
82 test.verifyResults(t, results)
83 if _, err := b.Call(ctx, test.method, test.params, results); err != nil {
84 t.Fatalf("%v:Call failed: %v", test.method, err)
86 test.verifyResults(t, results)
93 func prepare(ctx context.Context, t *testing.T, withHeaders bool) (jsonrpc2.Conn, jsonrpc2.Conn, func()) {
94 // make a wait group that can be used to wait for the system to shut down
95 aPipe, bPipe := net.Pipe()
96 a := run(ctx, withHeaders, aPipe)
97 b := run(ctx, withHeaders, bPipe)
106 func run(ctx context.Context, withHeaders bool, nc net.Conn) jsonrpc2.Conn {
107 var stream jsonrpc2.Stream
109 stream = jsonrpc2.NewHeaderStream(nc)
111 stream = jsonrpc2.NewRawStream(nc)
113 conn := jsonrpc2.NewConn(stream)
114 conn.Go(ctx, testHandler(*logRPC))
118 func testHandler(log bool) jsonrpc2.Handler {
119 return func(ctx context.Context, reply jsonrpc2.Replier, req jsonrpc2.Request) error {
120 switch req.Method() {
122 if len(req.Params()) > 0 {
123 return reply(ctx, nil, fmt.Errorf("%w: expected no params", jsonrpc2.ErrInvalidParams))
125 return reply(ctx, true, nil)
128 if err := json.Unmarshal(req.Params(), &v); err != nil {
129 return reply(ctx, nil, fmt.Errorf("%w: %s", jsonrpc2.ErrParse, err))
131 return reply(ctx, "got:"+v, nil)
134 if err := json.Unmarshal(req.Params(), &v); err != nil {
135 return reply(ctx, nil, fmt.Errorf("%w: %s", jsonrpc2.ErrParse, err))
137 return reply(ctx, fmt.Sprintf("got:%d", v), nil)
140 if err := json.Unmarshal(req.Params(), &v); err != nil {
141 return reply(ctx, nil, fmt.Errorf("%w: %s", jsonrpc2.ErrParse, err))
143 return reply(ctx, path.Join(v...), nil)
145 return jsonrpc2.MethodNotFound(ctx, reply, req)