blob: 905687d87b1ef3f6aabb675c2ada366a839b4b0b [file] [log] [blame]
Jonathan Amsterdamf9561772021-06-10 11:31:29 -04001// Copyright 2020 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.
4
5package jsonrpc2_test
6
7import (
8 "bytes"
9 "encoding/json"
10 "reflect"
11 "testing"
12
13 "golang.org/x/exp/jsonrpc2"
14)
15
16func TestWireMessage(t *testing.T) {
17 for _, test := range []struct {
18 name string
19 msg jsonrpc2.Message
20 encoded []byte
21 }{{
22 name: "notification",
23 msg: newNotification("alive", nil),
24 encoded: []byte(`{"jsonrpc":"2.0","method":"alive"}`),
25 }, {
26 name: "call",
27 msg: newCall("msg1", "ping", nil),
28 encoded: []byte(`{"jsonrpc":"2.0","id":"msg1","method":"ping"}`),
29 }, {
30 name: "response",
31 msg: newResponse("msg2", "pong", nil),
32 encoded: []byte(`{"jsonrpc":"2.0","id":"msg2","result":"pong"}`),
33 }, {
34 name: "numerical id",
35 msg: newCall(1, "poke", nil),
36 encoded: []byte(`{"jsonrpc":"2.0","id":1,"method":"poke"}`),
37 }, {
38 // originally reported in #39719, this checks that result is not present if
39 // it is an error response
40 name: "computing fix edits",
41 msg: newResponse(3, nil, jsonrpc2.NewError(0, "computing fix edits")),
42 encoded: []byte(`{
43 "jsonrpc":"2.0",
44 "id":3,
45 "error":{
46 "code":0,
47 "message":"computing fix edits"
48 }
49 }`),
50 }} {
51 b, err := jsonrpc2.EncodeMessage(test.msg)
52 if err != nil {
53 t.Fatal(err)
54 }
55 checkJSON(t, b, test.encoded)
56 msg, err := jsonrpc2.DecodeMessage(test.encoded)
57 if err != nil {
58 t.Fatal(err)
59 }
60 if !reflect.DeepEqual(msg, test.msg) {
61 t.Errorf("decoded message does not match\nGot:\n%+#v\nWant:\n%+#v", msg, test.msg)
62 }
63 }
64}
65
66func newNotification(method string, params interface{}) jsonrpc2.Message {
67 msg, err := jsonrpc2.NewNotification(method, params)
68 if err != nil {
69 panic(err)
70 }
71 return msg
72}
73
74func newID(id interface{}) jsonrpc2.ID {
75 switch v := id.(type) {
76 case nil:
77 return jsonrpc2.ID{}
78 case string:
79 return jsonrpc2.StringID(v)
80 case int:
81 return jsonrpc2.Int64ID(int64(v))
82 case int64:
83 return jsonrpc2.Int64ID(v)
84 default:
85 panic("invalid ID type")
86 }
87}
88
89func newCall(id interface{}, method string, params interface{}) jsonrpc2.Message {
90 msg, err := jsonrpc2.NewCall(newID(id), method, params)
91 if err != nil {
92 panic(err)
93 }
94 return msg
95}
96
97func newResponse(id interface{}, result interface{}, rerr error) jsonrpc2.Message {
98 msg, err := jsonrpc2.NewResponse(newID(id), result, rerr)
99 if err != nil {
100 panic(err)
101 }
102 return msg
103}
104
105func checkJSON(t *testing.T, got, want []byte) {
106 // compare the compact form, to allow for formatting differences
107 g := &bytes.Buffer{}
108 if err := json.Compact(g, []byte(got)); err != nil {
109 t.Fatal(err)
110 }
111 w := &bytes.Buffer{}
112 if err := json.Compact(w, []byte(want)); err != nil {
113 t.Fatal(err)
114 }
115 if g.String() != w.String() {
116 t.Errorf("encoded message does not match\nGot:\n%s\nWant:\n%s", g, w)
117 }
118}