Skip to content

Commit a087bee

Browse files

File tree

1 file changed

+142
-0
lines changed

1 file changed

+142
-0
lines changed

jsonrpc2_test.go

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
// Copyright 2019 The go-language-server 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.
4+
5+
package jsonrpc2_test
6+
7+
import (
8+
"context"
9+
"encoding/json"
10+
"flag"
11+
"fmt"
12+
"io"
13+
"path"
14+
"reflect"
15+
"testing"
16+
17+
"go.uber.org/zap"
18+
19+
"github.com/go-language-server/jsonrpc2"
20+
)
21+
22+
var logRPC = flag.Bool("logrpc", false, "Enable jsonrpc2 communication logging")
23+
24+
type callTest struct {
25+
method string
26+
params interface{}
27+
expect interface{}
28+
}
29+
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
36+
}
37+
38+
func (test *callTest) newResults() interface{} {
39+
switch e := test.expect.(type) {
40+
case []interface{}:
41+
var r []interface{}
42+
for _, v := range e {
43+
r = append(r, reflect.New(reflect.TypeOf(v)).Interface())
44+
}
45+
return r
46+
case nil:
47+
return nil
48+
default:
49+
return reflect.New(reflect.TypeOf(test.expect)).Interface()
50+
}
51+
}
52+
53+
func (test *callTest) verifyResults(t *testing.T, results interface{}) {
54+
if results == nil {
55+
return
56+
}
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)
60+
}
61+
}
62+
63+
func prepare(ctx context.Context, t *testing.T) (*jsonrpc2.Conn, *jsonrpc2.Conn) {
64+
aR, bW := io.Pipe()
65+
bR, aW := io.Pipe()
66+
a := run(ctx, t, aR, aW)
67+
b := run(ctx, t, bR, bW)
68+
return a, b
69+
}
70+
71+
func run(ctx context.Context, t *testing.T, r io.ReadCloser, w io.WriteCloser) *jsonrpc2.Conn {
72+
stream := jsonrpc2.NewStream(r, w)
73+
conn := jsonrpc2.NewConn(stream)
74+
conn.Handler = handle
75+
76+
if *logRPC {
77+
conn.Logger, _ = zap.NewDevelopment()
78+
}
79+
80+
go func() {
81+
defer func() {
82+
r.Close()
83+
w.Close()
84+
}()
85+
86+
if err := conn.Run(ctx); err != nil {
87+
t.Fatalf("Stream failed: %v", err)
88+
}
89+
}()
90+
91+
return conn
92+
}
93+
94+
func handle(ctx context.Context, c *jsonrpc2.Conn, r *jsonrpc2.Request) {
95+
switch r.Method {
96+
case "no_args":
97+
if r.Params != nil {
98+
c.Reply(ctx, r, nil, jsonrpc2.Errorf(jsonrpc2.CodeInvalidParams, "Expected no params"))
99+
return
100+
}
101+
c.Reply(ctx, r, true, nil)
102+
case "one_string":
103+
var v string
104+
if err := json.Unmarshal(*r.Params, &v); err != nil {
105+
c.Reply(ctx, r, nil, jsonrpc2.Errorf(jsonrpc2.CodeParseError, "%v", err.Error()))
106+
return
107+
}
108+
c.Reply(ctx, r, "got:"+v, nil)
109+
case "one_number":
110+
var v int
111+
if err := json.Unmarshal(*r.Params, &v); err != nil {
112+
c.Reply(ctx, r, nil, jsonrpc2.Errorf(jsonrpc2.CodeParseError, "%v", err.Error()))
113+
return
114+
}
115+
c.Reply(ctx, r, fmt.Sprintf("got:%d", v), nil)
116+
case "join":
117+
var v []string
118+
if err := json.Unmarshal(*r.Params, &v); err != nil {
119+
c.Reply(ctx, r, nil, jsonrpc2.Errorf(jsonrpc2.CodeParseError, "%v", err.Error()))
120+
return
121+
}
122+
c.Reply(ctx, r, path.Join(v...), nil)
123+
default:
124+
c.Reply(ctx, r, nil, jsonrpc2.Errorf(jsonrpc2.CodeMethodNotFound, "method %q not found", r.Method))
125+
}
126+
}
127+
128+
func TestCall(t *testing.T) {
129+
ctx := context.Background()
130+
a, b := prepare(ctx, t)
131+
for _, test := range callTests {
132+
results := test.newResults()
133+
if err := a.Call(ctx, test.method, test.params, results); err != nil {
134+
t.Fatalf("%v:Call failed: %v", test.method, err)
135+
}
136+
test.verifyResults(t, results)
137+
if err := b.Call(ctx, test.method, test.params, results); err != nil {
138+
t.Fatalf("%v:Call failed: %v", test.method, err)
139+
}
140+
test.verifyResults(t, results)
141+
}
142+
}

0 commit comments

Comments
 (0)