github.com/v2fly/tools@v0.100.0/internal/jsonrpc2_v2/wire_test.go (about)

     1  // 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  
     5  package jsonrpc2_test
     6  
     7  import (
     8  	"bytes"
     9  	"encoding/json"
    10  	"reflect"
    11  	"testing"
    12  
    13  	jsonrpc2 "github.com/v2fly/tools/internal/jsonrpc2_v2"
    14  )
    15  
    16  func 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  
    66  func 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  
    74  func 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  
    89  func 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  
    97  func 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  
   105  func 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  }