internal/jsonrpc2: test WireError.Is and fix nil target panic (#1079)
# Problem WireError.Is backs errors.Is checks used across the SDK against sentinels such as ErrMethodNotFound, ErrRejected, and ErrClientClosing, but had no direct test. Add a table-driven test for it. While doing so, errors.Is(err, (*WireError)(nil)) was found to panic on a nil pointer dereference, because Is read w.Code without a nil check. Guard against a nil *WireError target so the comparison returns false. ```go errors.Is(err, (*WireError)(nil)) // panic: nil pointer dereference ``` # Approach Is read w.Code after a successful type assertion without checking whether w itself was nil. The fix guards against a nil *WireError target so the comparison returns false instead of panicking. # Test plan - go test ./internal/jsonrpc2/ passes. - The new typed nil WireError case panics without the one-line fix and passes with it, confirming the test exercises the guarded path. Co-authored-by: Yaroslav <yarolegovich@gmail.com>
This commit is contained in:
parent
ce0b198202
commit
b074c7f3af
2 changed files with 25 additions and 1 deletions
|
|
@ -87,7 +87,7 @@ func (err *WireError) Error() string {
|
|||
|
||||
func (err *WireError) Is(other error) bool {
|
||||
w, ok := other.(*WireError)
|
||||
if !ok {
|
||||
if !ok || w == nil {
|
||||
return false
|
||||
}
|
||||
return err.Code == w.Code
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ package jsonrpc2_test
|
|||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
|
|
@ -147,6 +148,29 @@ func TestDecodeIDOnlyMessageIsResponse(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
// TestWireErrorIs checks the errors.Is behavior of WireError, including that
|
||||
// comparing against a typed-nil *WireError does not panic.
|
||||
func TestWireErrorIs(t *testing.T) {
|
||||
err := jsonrpc2.NewError(-32600, "invalid request")
|
||||
for _, test := range []struct {
|
||||
name string
|
||||
target error
|
||||
want bool
|
||||
}{
|
||||
{name: "same code", target: jsonrpc2.NewError(-32600, "other message"), want: true},
|
||||
{name: "different code", target: jsonrpc2.NewError(-32601, "invalid request"), want: false},
|
||||
{name: "typed nil WireError", target: (*jsonrpc2.WireError)(nil), want: false},
|
||||
{name: "untyped nil", target: nil, want: false},
|
||||
{name: "other error type", target: errors.New("invalid request"), want: false},
|
||||
} {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
if got := errors.Is(err, test.target); got != test.want {
|
||||
t.Errorf("errors.Is(%v, %v) = %v, want %v", err, test.target, got, test.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func checkJSON(t *testing.T, got, want []byte) {
|
||||
// compare the compact form, to allow for formatting differences
|
||||
g := &bytes.Buffer{}
|
||||
|
|
|
|||
Loading…
Reference in a new issue