|  | // 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" | 
|  | "fmt" | 
|  | "testing" | 
|  |  | 
|  | "golang.org/x/tools/internal/jsonrpc2" | 
|  | ) | 
|  |  | 
|  | var wireIDTestData = []struct { | 
|  | name    string | 
|  | id      jsonrpc2.ID | 
|  | encoded []byte | 
|  | plain   string | 
|  | quoted  string | 
|  | }{ | 
|  | { | 
|  | name:    `empty`, | 
|  | encoded: []byte(`0`), | 
|  | plain:   `0`, | 
|  | quoted:  `#0`, | 
|  | }, { | 
|  | name:    `number`, | 
|  | id:      jsonrpc2.NewIntID(43), | 
|  | encoded: []byte(`43`), | 
|  | plain:   `43`, | 
|  | quoted:  `#43`, | 
|  | }, { | 
|  | name:    `string`, | 
|  | id:      jsonrpc2.NewStringID("life"), | 
|  | encoded: []byte(`"life"`), | 
|  | plain:   `life`, | 
|  | quoted:  `"life"`, | 
|  | }, | 
|  | } | 
|  |  | 
|  | func TestIDFormat(t *testing.T) { | 
|  | for _, test := range wireIDTestData { | 
|  | t.Run(test.name, func(t *testing.T) { | 
|  | if got := fmt.Sprint(test.id); got != test.plain { | 
|  | t.Errorf("got %s expected %s", got, test.plain) | 
|  | } | 
|  | if got := fmt.Sprintf("%q", test.id); got != test.quoted { | 
|  | t.Errorf("got %s want %s", got, test.quoted) | 
|  | } | 
|  | }) | 
|  | } | 
|  | } | 
|  |  | 
|  | func TestIDEncode(t *testing.T) { | 
|  | for _, test := range wireIDTestData { | 
|  | t.Run(test.name, func(t *testing.T) { | 
|  | data, err := json.Marshal(&test.id) | 
|  | if err != nil { | 
|  | t.Fatal(err) | 
|  | } | 
|  | checkJSON(t, data, test.encoded) | 
|  | }) | 
|  | } | 
|  | } | 
|  |  | 
|  | func TestIDDecode(t *testing.T) { | 
|  | for _, test := range wireIDTestData { | 
|  | t.Run(test.name, func(t *testing.T) { | 
|  | var got *jsonrpc2.ID | 
|  | if err := json.Unmarshal(test.encoded, &got); err != nil { | 
|  | t.Fatal(err) | 
|  | } | 
|  | if got == nil { | 
|  | t.Errorf("got nil want %s", test.id) | 
|  | } else if *got != test.id { | 
|  | t.Errorf("got %s want %s", got, test.id) | 
|  | } | 
|  | }) | 
|  | } | 
|  | } | 
|  |  | 
|  | func TestErrorEncode(t *testing.T) { | 
|  | b, err := json.Marshal(jsonrpc2.NewError(0, "")) | 
|  | if err != nil { | 
|  | t.Fatal(err) | 
|  | } | 
|  | checkJSON(t, b, []byte(`{ | 
|  | "code": 0, | 
|  | "message": "" | 
|  | }`)) | 
|  | } | 
|  |  | 
|  | func TestErrorResponse(t *testing.T) { | 
|  | // originally reported in #39719, this checks that result is not present if | 
|  | // it is an error response | 
|  | r, _ := jsonrpc2.NewResponse(jsonrpc2.NewIntID(3), nil, fmt.Errorf("computing fix edits")) | 
|  | data, err := json.Marshal(r) | 
|  | if err != nil { | 
|  | t.Fatal(err) | 
|  | } | 
|  | checkJSON(t, data, []byte(`{ | 
|  | "jsonrpc":"2.0", | 
|  | "error":{ | 
|  | "code":0, | 
|  | "message":"computing fix edits" | 
|  | }, | 
|  | "id":3 | 
|  | }`)) | 
|  | } | 
|  |  | 
|  | 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.Fatalf("Got:\n%s\nWant:\n%s", g, w) | 
|  | } | 
|  | } |