Skip to content

Commit

Permalink
handler: add NewStrict function
Browse files Browse the repository at this point in the history
This acts as New, but enforce strict field checking on arguments of struct
type. Update the tests to add a case for this.
  • Loading branch information
creachadair committed Nov 14, 2021
1 parent ee7281e commit acd9e7e
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 11 deletions.
11 changes: 11 additions & 0 deletions handler/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,17 @@ func New(fn interface{}) Func {
return fi.Wrap()
}

// NewStrict acts as New, but enforces strict field checking on an argument of
// struct type.
func NewStrict(fn interface{}) Func {
fi, err := Check(fn)
if err != nil {
panic(err)
}
fi.strictFields = true
return fi.Wrap()
}

var (
ctxType = reflect.TypeOf((*context.Context)(nil)).Elem() // type context.Context
errType = reflect.TypeOf((*error)(nil)).Elem() // type error
Expand Down
48 changes: 37 additions & 11 deletions handler/handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"testing"

"github.com/creachadair/jrpc2"
"github.com/creachadair/jrpc2/code"
"github.com/creachadair/jrpc2/handler"
"github.com/google/go-cmp/cmp"
)
Expand Down Expand Up @@ -111,6 +112,26 @@ func TestPositional(t *testing.T) {
}
}

func TestNewStrict(t *testing.T) {
type arg struct {
A, B string
}
fn := handler.NewStrict(func(ctx context.Context, arg *arg) error { return nil })

req := mustParseRequest(t, `{
"jsonrpc": "2.0",
"id": 100,
"method": "f",
"params": {
"A": "foo",
"Z": 25
}}`)
rsp, err := fn(context.Background(), req)
if got := code.FromError(err); got != code.InvalidParams {
t.Errorf("Handler returned (%+v, %v), want InvalidParms", rsp, err)
}
}

// Verify that the handling of pointer-typed arguments does not incorrectly
// introduce another pointer indirection.
func TestNew_pointerRegression(t *testing.T) {
Expand All @@ -120,18 +141,15 @@ func TestNew_pointerRegression(t *testing.T) {
t.Logf("Got argument struct: %+v", got)
return nil
})
req, err := jrpc2.ParseRequests([]byte(`{
req := mustParseRequest(t, `{
"jsonrpc": "2.0",
"id": "foo",
"method": "bar",
"params":{
"alpha": "xyzzy",
"bravo": 23
}}`))
if err != nil {
t.Fatalf("Parse request failed: %v", err)
}
if _, err := call.Handle(context.Background(), req[0]); err != nil {
}}`)
if _, err := call.Handle(context.Background(), req); err != nil {
t.Errorf("Handle failed: %v", err)
}
want := argStruct{A: "xyzzy", B: 23}
Expand Down Expand Up @@ -165,11 +183,8 @@ func TestPositional_decode(t *testing.T) {
{`{"jsonrpc":"2.0","id":6,"method":"add","params":{"unknown":"field"}}`, 0, true},
}
for _, test := range tests {
req, err := jrpc2.ParseRequests([]byte(test.input))
if err != nil {
t.Fatalf("ParseRequests %#q: unexpected error: %v", test.input, err)
}
got, err := call(context.Background(), req[0])
req := mustParseRequest(t, test.input)
got, err := call(context.Background(), req)
if !test.bad {
if err != nil {
t.Errorf("Call %#q: unexpected error: %v", test.input, err)
Expand Down Expand Up @@ -360,3 +375,14 @@ func TestObjUnmarshal(t *testing.T) {
}
}
}

func mustParseRequest(t *testing.T, text string) *jrpc2.Request {
t.Helper()
req, err := jrpc2.ParseRequests([]byte(text))
if err != nil {
t.Fatalf("ParseRequests: %v", err)
} else if len(req) != 1 {
t.Fatalf("Wrong number of requests: got %d, want 1", len(req))
}
return req[0]
}

0 comments on commit acd9e7e

Please sign in to comment.