// Copyright 2020 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package jsonrpc2_test import ( "bytes" "encoding/json" "reflect" "testing" "golang.org/x/exp/jsonrpc2" ) func TestWireMessage(t *testing.T) { for _, test := range []struct { name string msg jsonrpc2.Message encoded []byte }{{ name: "notification", msg: newNotification("alive", nil), encoded: []byte(`{"jsonrpc":"2.0","method":"alive"}`), }, { name: "call", msg: newCall("msg1", "ping", nil), encoded: []byte(`{"jsonrpc":"2.0","id":"msg1","method":"ping"}`), }, { name: "response", msg: newResponse("msg2", "pong", nil), encoded: []byte(`{"jsonrpc":"2.0","id":"msg2","result":"pong"}`), }, { name: "numerical id", msg: newCall(1, "poke", nil), encoded: []byte(`{"jsonrpc":"2.0","id":1,"method":"poke"}`), }, { // originally reported in #39719, this checks that result is not present if // it is an error response name: "computing fix edits", msg: newResponse(3, nil, jsonrpc2.NewError(0, "computing fix edits")), encoded: []byte(`{ "jsonrpc":"2.0", "id":3, "error":{ "code":0, "message":"computing fix edits" } }`), }} { b, err := jsonrpc2.EncodeMessage(test.msg) if err != nil { t.Fatal(err) } checkJSON(t, b, test.encoded) msg, err := jsonrpc2.DecodeMessage(test.encoded) if err != nil { t.Fatal(err) } if !reflect.DeepEqual(msg, test.msg) { t.Errorf("decoded message does not match\nGot:\n%+#v\nWant:\n%+#v", msg, test.msg) } } } func newNotification(method string, params interface{}) jsonrpc2.Message { msg, err := jsonrpc2.NewNotification(method, params) if err != nil { panic(err) } return msg } func newID(id interface{}) jsonrpc2.ID { switch v := id.(type) { case nil: return jsonrpc2.ID{} case string: return jsonrpc2.StringID(v) case int: return jsonrpc2.Int64ID(int64(v)) case int64: return jsonrpc2.Int64ID(v) default: panic("invalid ID type") } } func newCall(id interface{}, method string, params interface{}) jsonrpc2.Message { msg, err := jsonrpc2.NewCall(newID(id), method, params) if err != nil { panic(err) } return msg } func newResponse(id interface{}, result interface{}, rerr error) jsonrpc2.Message { msg, err := jsonrpc2.NewResponse(newID(id), result, rerr) if err != nil { panic(err) } return msg } func checkJSON(t *testing.T, got, want []byte) { // compare the compact form, to allow for formatting differences g := &bytes.Buffer{} if err := json.Compact(g, []byte(got)); err != nil { t.Fatal(err) } w := &bytes.Buffer{} if err := json.Compact(w, []byte(want)); err != nil { t.Fatal(err) } if g.String() != w.String() { t.Errorf("encoded message does not match\nGot:\n%s\nWant:\n%s", g, w) } }