Skip to content

Commit be55cbd

Browse files
committed
interceptor can also see default call options setup by dial option; add test case
1 parent 927ff41 commit be55cbd

File tree

3 files changed

+119
-6
lines changed

3 files changed

+119
-6
lines changed

call.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@ import (
2727
//
2828
// All errors returned by Invoke are compatible with the status package.
2929
func (cc *ClientConn) Invoke(ctx context.Context, method string, args, reply interface{}, opts ...CallOption) error {
30+
// allow interceptor to see all applicable call options, which means those
31+
// configured as defaults from dial option as well as per-call options
32+
opts = append(cc.dopts.callOptions, opts...)
33+
3034
if cc.dopts.unaryInt != nil {
3135
return cc.dopts.unaryInt(ctx, method, args, reply, cc, invoke, opts...)
3236
}

stream.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,10 @@ type ClientStream interface {
9999
// NewStream creates a new Stream for the client side. This is typically
100100
// called by generated code.
101101
func (cc *ClientConn) NewStream(ctx context.Context, desc *StreamDesc, method string, opts ...CallOption) (ClientStream, error) {
102+
// allow interceptor to see all applicable call options, which means those
103+
// configured as defaults from dial option as well as per-call options
104+
opts = append(cc.dopts.callOptions, opts...)
105+
102106
if cc.dopts.streamInt != nil {
103107
return cc.dopts.streamInt(ctx, desc, cc, method, newClientStream, opts...)
104108
}
@@ -137,7 +141,6 @@ func newClientStream(ctx context.Context, desc *StreamDesc, cc *ClientConn, meth
137141
}
138142
}()
139143

140-
opts = append(cc.dopts.callOptions, opts...)
141144
for _, o := range opts {
142145
if err := o.before(c); err != nil {
143146
return nil, toRPCErr(err)

test/end2end_test.go

Lines changed: 111 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -627,14 +627,11 @@ func (d *nopDecompressor) Type() string {
627627
return "nop"
628628
}
629629

630-
func (te *test) clientConn() *grpc.ClientConn {
630+
func (te *test) clientConn(opts ...grpc.DialOption) *grpc.ClientConn {
631631
if te.cc != nil {
632632
return te.cc
633633
}
634-
opts := []grpc.DialOption{
635-
grpc.WithDialer(te.e.dialer),
636-
grpc.WithUserAgent(te.userAgent),
637-
}
634+
opts = append(opts, grpc.WithDialer(te.e.dialer), grpc.WithUserAgent(te.userAgent))
638635

639636
if te.sc != nil {
640637
opts = append(opts, grpc.WithServiceConfig(te.sc))
@@ -5887,6 +5884,115 @@ func TestMethodFromServerStream(t *testing.T) {
58875884
}
58885885
}
58895886

5887+
func TestInterceptorCanAccessCallOptions(t *testing.T) {
5888+
defer leakcheck.Check(t)
5889+
e := tcpClearRREnv
5890+
te := newTest(t, e)
5891+
te.startServer(&testServer{security: e.security})
5892+
defer te.tearDown()
5893+
5894+
type observedOptions struct {
5895+
headers []*metadata.MD
5896+
trailers []*metadata.MD
5897+
peer []*peer.Peer
5898+
creds []credentials.PerRPCCredentials
5899+
failFast []bool
5900+
maxRecvSize []int
5901+
maxSendSize []int
5902+
compressor []string
5903+
subtype []string
5904+
codec []grpc.Codec
5905+
}
5906+
var observedOpts observedOptions
5907+
populateOpts := func(opts []grpc.CallOption) {
5908+
for _, o := range opts {
5909+
switch o := o.(type) {
5910+
case grpc.HeaderCallOption:
5911+
observedOpts.headers = append(observedOpts.headers, o.HeaderAddr)
5912+
case grpc.TrailerCallOption:
5913+
observedOpts.trailers = append(observedOpts.trailers, o.TrailerAddr)
5914+
case grpc.PeerCallOption:
5915+
observedOpts.peer = append(observedOpts.peer, o.PeerAddr)
5916+
case grpc.PerRPCCredsCallOption:
5917+
observedOpts.creds = append(observedOpts.creds, o.Creds)
5918+
case grpc.FailFastCallOption:
5919+
observedOpts.failFast = append(observedOpts.failFast, o.FailFast)
5920+
case grpc.MaxRecvMsgSizeCallOption:
5921+
observedOpts.maxRecvSize = append(observedOpts.maxRecvSize, o.MaxRecvMsgSize)
5922+
case grpc.MaxSendMsgSizeCallOption:
5923+
observedOpts.maxSendSize = append(observedOpts.maxSendSize, o.MaxSendMsgSize)
5924+
case grpc.CompressorCallOption:
5925+
observedOpts.compressor = append(observedOpts.compressor, o.CompressorType)
5926+
case grpc.ContentSubtypeCallOption:
5927+
observedOpts.subtype = append(observedOpts.subtype, o.ContentSubtype)
5928+
case grpc.CustomCodecCallOption:
5929+
observedOpts.codec = append(observedOpts.codec, o.Codec)
5930+
}
5931+
}
5932+
}
5933+
5934+
te.unaryClientInt = func(ctx context.Context, method string, req, reply interface{}, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error {
5935+
populateOpts(opts)
5936+
return nil
5937+
}
5938+
te.streamClientInt = func(ctx context.Context, desc *grpc.StreamDesc, cc *grpc.ClientConn, method string, streamer grpc.Streamer, opts ...grpc.CallOption) (grpc.ClientStream, error) {
5939+
populateOpts(opts)
5940+
return nil, nil
5941+
}
5942+
5943+
defaults := []grpc.CallOption{
5944+
grpc.FailFast(false),
5945+
grpc.MaxCallRecvMsgSize(1010),
5946+
}
5947+
tc := testpb.NewTestServiceClient(te.clientConn(grpc.WithDefaultCallOptions(defaults...)))
5948+
5949+
var headers metadata.MD
5950+
var trailers metadata.MD
5951+
var pr peer.Peer
5952+
tc.UnaryCall(context.Background(), &testpb.SimpleRequest{},
5953+
grpc.MaxCallRecvMsgSize(100),
5954+
grpc.MaxCallSendMsgSize(200),
5955+
grpc.PerRPCCredentials(testPerRPCCredentials{}),
5956+
grpc.Header(&headers),
5957+
grpc.Trailer(&trailers),
5958+
grpc.Peer(&pr))
5959+
expected := observedOptions{
5960+
failFast: []bool{false},
5961+
maxRecvSize: []int{1010, 100},
5962+
maxSendSize: []int{200},
5963+
creds: []credentials.PerRPCCredentials{testPerRPCCredentials{}},
5964+
headers: []*metadata.MD{&headers},
5965+
trailers: []*metadata.MD{&trailers},
5966+
peer: []*peer.Peer{&pr},
5967+
}
5968+
5969+
if !reflect.DeepEqual(expected, observedOpts) {
5970+
t.Errorf("unary call did not observe expected options: expected %#v, got %#v", expected, observedOpts)
5971+
}
5972+
5973+
observedOpts = observedOptions{} // reset
5974+
5975+
var codec errCodec
5976+
tc.StreamingInputCall(context.Background(),
5977+
grpc.FailFast(true),
5978+
grpc.MaxCallSendMsgSize(2020),
5979+
grpc.UseCompressor("comp-type"),
5980+
grpc.CallContentSubtype("json"),
5981+
grpc.CallCustomCodec(&codec))
5982+
expected = observedOptions{
5983+
failFast: []bool{false, true},
5984+
maxRecvSize: []int{1010},
5985+
maxSendSize: []int{2020},
5986+
compressor: []string{"comp-type"},
5987+
subtype: []string{"json"},
5988+
codec: []grpc.Codec{&codec},
5989+
}
5990+
5991+
if !reflect.DeepEqual(expected, observedOpts) {
5992+
t.Errorf("streaming call did not observe expected options: expected %#v, got %#v", expected, observedOpts)
5993+
}
5994+
}
5995+
58905996
func TestCompressorRegister(t *testing.T) {
58915997
defer leakcheck.Check(t)
58925998
for _, e := range listTestEnv() {

0 commit comments

Comments
 (0)