package jsonrpc2 import ( "bytes" "encoding/json" "reflect" "testing" ) func TestAnyMessage(t *testing.T) { tests := map[string]struct { request, response, invalid bool }{ // Single messages `{}`: {invalid: true}, `{"foo":"bar"}`: {invalid: true}, `{"method":"m"}`: {request: true}, `{"result":123}`: {response: true}, `{"result":null}`: {response: true}, `{"error":{"code":456,"message":"m"}}`: {response: true}, } for s, want := range tests { var m anyMessage if err := json.Unmarshal([]byte(s), &m); err != nil { if !want.invalid { t.Errorf("%s: error: %v", s, err) } continue } if (m.request != nil) != want.request { t.Errorf("%s: got request %v, want %v", s, m.request != nil, want.request) } if (m.response != nil) != want.response { t.Errorf("%s: got response %v, want %v", s, m.response != nil, want.response) } } } func TestRequest_MarshalUnmarshalJSON(t *testing.T) { null := json.RawMessage("null") obj := json.RawMessage(`{"foo":"bar"}`) tests := []struct { data []byte want Request }{ { data: []byte(`{"method":"m","params":{"foo":"bar"},"id":123,"jsonrpc":"2.0"}`), want: Request{ID: ID{Num: 123}, Method: "m", Params: &obj}, }, { data: []byte(`{"method":"m","params":null,"id":123,"jsonrpc":"2.0"}`), want: Request{ID: ID{Num: 123}, Method: "m", Params: &null}, }, { data: []byte(`{"method":"m","id":123,"jsonrpc":"2.0"}`), want: Request{ID: ID{Num: 123}, Method: "m", Params: nil}, }, } for _, test := range tests { var got Request if err := json.Unmarshal(test.data, &got); err != nil { t.Error(err) continue } if !reflect.DeepEqual(got, test.want) { t.Errorf("%q: got %+v, want %+v", test.data, got, test.want) continue } data, err := json.Marshal(got) if err != nil { t.Error(err) continue } if !bytes.Equal(data, test.data) { t.Errorf("got JSON %q, want %q", data, test.data) } } } func TestResponse_MarshalUnmarshalJSON(t *testing.T) { null := json.RawMessage("null") obj := json.RawMessage(`{"foo":"bar"}`) tests := []struct { data []byte want Response error bool }{ { data: []byte(`{"id":123,"result":{"foo":"bar"},"jsonrpc":"2.0"}`), want: Response{ID: ID{Num: 123}, Result: &obj}, }, { data: []byte(`{"id":123,"result":null,"jsonrpc":"2.0"}`), want: Response{ID: ID{Num: 123}, Result: &null}, }, { data: []byte(`{"id":123,"jsonrpc":"2.0"}`), want: Response{ID: ID{Num: 123}, Result: nil}, error: true, // either result or error field must be set }, } for _, test := range tests { var got Response if err := json.Unmarshal(test.data, &got); err != nil { t.Error(err) continue } if !reflect.DeepEqual(got, test.want) { t.Errorf("%q: got %+v, want %+v", test.data, got, test.want) continue } data, err := json.Marshal(got) if err != nil { if test.error { continue } t.Error(err) continue } if test.error { t.Errorf("%q: expected error", test.data) continue } if !bytes.Equal(data, test.data) { t.Errorf("got JSON %q, want %q", data, test.data) } } }