Moved to google.golang.org/genproto/googleapis/api/annotations
Fixes #52
This commit is contained in:
225
vendor/google.golang.org/grpc/stats/grpc_testing/test.pb.go
generated
vendored
Normal file
225
vendor/google.golang.org/grpc/stats/grpc_testing/test.pb.go
generated
vendored
Normal file
@@ -0,0 +1,225 @@
|
||||
// Code generated by protoc-gen-go.
|
||||
// source: test.proto
|
||||
// DO NOT EDIT!
|
||||
|
||||
/*
|
||||
Package grpc_testing is a generated protocol buffer package.
|
||||
|
||||
It is generated from these files:
|
||||
test.proto
|
||||
|
||||
It has these top-level messages:
|
||||
SimpleRequest
|
||||
SimpleResponse
|
||||
*/
|
||||
package grpc_testing
|
||||
|
||||
import proto "github.com/golang/protobuf/proto"
|
||||
import fmt "fmt"
|
||||
import math "math"
|
||||
|
||||
import (
|
||||
context "golang.org/x/net/context"
|
||||
grpc "google.golang.org/grpc"
|
||||
)
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
|
||||
|
||||
// Unary request.
|
||||
type SimpleRequest struct {
|
||||
Id int32 `protobuf:"varint,2,opt,name=id" json:"id,omitempty"`
|
||||
}
|
||||
|
||||
func (m *SimpleRequest) Reset() { *m = SimpleRequest{} }
|
||||
func (m *SimpleRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*SimpleRequest) ProtoMessage() {}
|
||||
func (*SimpleRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
|
||||
|
||||
// Unary response, as configured by the request.
|
||||
type SimpleResponse struct {
|
||||
Id int32 `protobuf:"varint,3,opt,name=id" json:"id,omitempty"`
|
||||
}
|
||||
|
||||
func (m *SimpleResponse) Reset() { *m = SimpleResponse{} }
|
||||
func (m *SimpleResponse) String() string { return proto.CompactTextString(m) }
|
||||
func (*SimpleResponse) ProtoMessage() {}
|
||||
func (*SimpleResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} }
|
||||
|
||||
func init() {
|
||||
proto.RegisterType((*SimpleRequest)(nil), "grpc.testing.SimpleRequest")
|
||||
proto.RegisterType((*SimpleResponse)(nil), "grpc.testing.SimpleResponse")
|
||||
}
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ context.Context
|
||||
var _ grpc.ClientConn
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the grpc package it is being compiled against.
|
||||
const _ = grpc.SupportPackageIsVersion4
|
||||
|
||||
// Client API for TestService service
|
||||
|
||||
type TestServiceClient interface {
|
||||
// One request followed by one response.
|
||||
// The server returns the client id as-is.
|
||||
UnaryCall(ctx context.Context, in *SimpleRequest, opts ...grpc.CallOption) (*SimpleResponse, error)
|
||||
// A sequence of requests with each request served by the server immediately.
|
||||
// As one request could lead to multiple responses, this interface
|
||||
// demonstrates the idea of full duplexing.
|
||||
FullDuplexCall(ctx context.Context, opts ...grpc.CallOption) (TestService_FullDuplexCallClient, error)
|
||||
}
|
||||
|
||||
type testServiceClient struct {
|
||||
cc *grpc.ClientConn
|
||||
}
|
||||
|
||||
func NewTestServiceClient(cc *grpc.ClientConn) TestServiceClient {
|
||||
return &testServiceClient{cc}
|
||||
}
|
||||
|
||||
func (c *testServiceClient) UnaryCall(ctx context.Context, in *SimpleRequest, opts ...grpc.CallOption) (*SimpleResponse, error) {
|
||||
out := new(SimpleResponse)
|
||||
err := grpc.Invoke(ctx, "/grpc.testing.TestService/UnaryCall", in, out, c.cc, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *testServiceClient) FullDuplexCall(ctx context.Context, opts ...grpc.CallOption) (TestService_FullDuplexCallClient, error) {
|
||||
stream, err := grpc.NewClientStream(ctx, &_TestService_serviceDesc.Streams[0], c.cc, "/grpc.testing.TestService/FullDuplexCall", opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
x := &testServiceFullDuplexCallClient{stream}
|
||||
return x, nil
|
||||
}
|
||||
|
||||
type TestService_FullDuplexCallClient interface {
|
||||
Send(*SimpleRequest) error
|
||||
Recv() (*SimpleResponse, error)
|
||||
grpc.ClientStream
|
||||
}
|
||||
|
||||
type testServiceFullDuplexCallClient struct {
|
||||
grpc.ClientStream
|
||||
}
|
||||
|
||||
func (x *testServiceFullDuplexCallClient) Send(m *SimpleRequest) error {
|
||||
return x.ClientStream.SendMsg(m)
|
||||
}
|
||||
|
||||
func (x *testServiceFullDuplexCallClient) Recv() (*SimpleResponse, error) {
|
||||
m := new(SimpleResponse)
|
||||
if err := x.ClientStream.RecvMsg(m); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
// Server API for TestService service
|
||||
|
||||
type TestServiceServer interface {
|
||||
// One request followed by one response.
|
||||
// The server returns the client id as-is.
|
||||
UnaryCall(context.Context, *SimpleRequest) (*SimpleResponse, error)
|
||||
// A sequence of requests with each request served by the server immediately.
|
||||
// As one request could lead to multiple responses, this interface
|
||||
// demonstrates the idea of full duplexing.
|
||||
FullDuplexCall(TestService_FullDuplexCallServer) error
|
||||
}
|
||||
|
||||
func RegisterTestServiceServer(s *grpc.Server, srv TestServiceServer) {
|
||||
s.RegisterService(&_TestService_serviceDesc, srv)
|
||||
}
|
||||
|
||||
func _TestService_UnaryCall_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(SimpleRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(TestServiceServer).UnaryCall(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/grpc.testing.TestService/UnaryCall",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(TestServiceServer).UnaryCall(ctx, req.(*SimpleRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _TestService_FullDuplexCall_Handler(srv interface{}, stream grpc.ServerStream) error {
|
||||
return srv.(TestServiceServer).FullDuplexCall(&testServiceFullDuplexCallServer{stream})
|
||||
}
|
||||
|
||||
type TestService_FullDuplexCallServer interface {
|
||||
Send(*SimpleResponse) error
|
||||
Recv() (*SimpleRequest, error)
|
||||
grpc.ServerStream
|
||||
}
|
||||
|
||||
type testServiceFullDuplexCallServer struct {
|
||||
grpc.ServerStream
|
||||
}
|
||||
|
||||
func (x *testServiceFullDuplexCallServer) Send(m *SimpleResponse) error {
|
||||
return x.ServerStream.SendMsg(m)
|
||||
}
|
||||
|
||||
func (x *testServiceFullDuplexCallServer) Recv() (*SimpleRequest, error) {
|
||||
m := new(SimpleRequest)
|
||||
if err := x.ServerStream.RecvMsg(m); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
var _TestService_serviceDesc = grpc.ServiceDesc{
|
||||
ServiceName: "grpc.testing.TestService",
|
||||
HandlerType: (*TestServiceServer)(nil),
|
||||
Methods: []grpc.MethodDesc{
|
||||
{
|
||||
MethodName: "UnaryCall",
|
||||
Handler: _TestService_UnaryCall_Handler,
|
||||
},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{
|
||||
{
|
||||
StreamName: "FullDuplexCall",
|
||||
Handler: _TestService_FullDuplexCall_Handler,
|
||||
ServerStreams: true,
|
||||
ClientStreams: true,
|
||||
},
|
||||
},
|
||||
Metadata: "test.proto",
|
||||
}
|
||||
|
||||
func init() { proto.RegisterFile("test.proto", fileDescriptor0) }
|
||||
|
||||
var fileDescriptor0 = []byte{
|
||||
// 167 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0xe2, 0x2a, 0x49, 0x2d, 0x2e,
|
||||
0xd1, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0xe2, 0x49, 0x2f, 0x2a, 0x48, 0xd6, 0x03, 0x09, 0x64,
|
||||
0xe6, 0xa5, 0x2b, 0xc9, 0x73, 0xf1, 0x06, 0x67, 0xe6, 0x16, 0xe4, 0xa4, 0x06, 0xa5, 0x16, 0x96,
|
||||
0xa6, 0x16, 0x97, 0x08, 0xf1, 0x71, 0x31, 0x65, 0xa6, 0x48, 0x30, 0x29, 0x30, 0x6a, 0xb0, 0x06,
|
||||
0x31, 0x65, 0xa6, 0x28, 0x29, 0x70, 0xf1, 0xc1, 0x14, 0x14, 0x17, 0xe4, 0xe7, 0x15, 0xa7, 0x42,
|
||||
0x55, 0x30, 0xc3, 0x54, 0x18, 0x2d, 0x63, 0xe4, 0xe2, 0x0e, 0x49, 0x2d, 0x2e, 0x09, 0x4e, 0x2d,
|
||||
0x2a, 0xcb, 0x4c, 0x4e, 0x15, 0x72, 0xe3, 0xe2, 0x0c, 0xcd, 0x4b, 0x2c, 0xaa, 0x74, 0x4e, 0xcc,
|
||||
0xc9, 0x11, 0x92, 0xd6, 0x43, 0xb6, 0x4e, 0x0f, 0xc5, 0x2e, 0x29, 0x19, 0xec, 0x92, 0x50, 0x7b,
|
||||
0xfc, 0xb9, 0xf8, 0xdc, 0x4a, 0x73, 0x72, 0x5c, 0x4a, 0x0b, 0x72, 0x52, 0x2b, 0x28, 0x34, 0x4c,
|
||||
0x83, 0xd1, 0x80, 0x31, 0x89, 0x0d, 0x1c, 0x00, 0xc6, 0x80, 0x00, 0x00, 0x00, 0xff, 0xff, 0x8d,
|
||||
0x82, 0x5b, 0xdd, 0x0e, 0x01, 0x00, 0x00,
|
||||
}
|
||||
23
vendor/google.golang.org/grpc/stats/grpc_testing/test.proto
generated
vendored
Normal file
23
vendor/google.golang.org/grpc/stats/grpc_testing/test.proto
generated
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package grpc.testing;
|
||||
|
||||
message SimpleRequest {
|
||||
int32 id = 2;
|
||||
}
|
||||
|
||||
message SimpleResponse {
|
||||
int32 id = 3;
|
||||
}
|
||||
|
||||
// A simple test service.
|
||||
service TestService {
|
||||
// One request followed by one response.
|
||||
// The server returns the client id as-is.
|
||||
rpc UnaryCall(SimpleRequest) returns (SimpleResponse);
|
||||
|
||||
// A sequence of requests with each request served by the server immediately.
|
||||
// As one request could lead to multiple responses, this interface
|
||||
// demonstrates the idea of full duplexing.
|
||||
rpc FullDuplexCall(stream SimpleRequest) returns (stream SimpleResponse);
|
||||
}
|
||||
76
vendor/google.golang.org/grpc/stats/handlers.go
generated
vendored
Normal file
76
vendor/google.golang.org/grpc/stats/handlers.go
generated
vendored
Normal file
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2016, Google Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Google Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
package stats
|
||||
|
||||
import (
|
||||
"net"
|
||||
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
// ConnTagInfo defines the relevant information needed by connection context tagger.
|
||||
type ConnTagInfo struct {
|
||||
// RemoteAddr is the remote address of the corresponding connection.
|
||||
RemoteAddr net.Addr
|
||||
// LocalAddr is the local address of the corresponding connection.
|
||||
LocalAddr net.Addr
|
||||
// TODO add QOS related fields.
|
||||
}
|
||||
|
||||
// RPCTagInfo defines the relevant information needed by RPC context tagger.
|
||||
type RPCTagInfo struct {
|
||||
// FullMethodName is the RPC method in the format of /package.service/method.
|
||||
FullMethodName string
|
||||
}
|
||||
|
||||
// Handler defines the interface for the related stats handling (e.g., RPCs, connections).
|
||||
type Handler interface {
|
||||
// TagRPC can attach some information to the given context.
|
||||
// The returned context is used in the rest lifetime of the RPC.
|
||||
TagRPC(context.Context, *RPCTagInfo) context.Context
|
||||
// HandleRPC processes the RPC stats.
|
||||
HandleRPC(context.Context, RPCStats)
|
||||
|
||||
// TagConn can attach some information to the given context.
|
||||
// The returned context will be used for stats handling.
|
||||
// For conn stats handling, the context used in HandleConn for this
|
||||
// connection will be derived from the context returned.
|
||||
// For RPC stats handling,
|
||||
// - On server side, the context used in HandleRPC for all RPCs on this
|
||||
// connection will be derived from the context returned.
|
||||
// - On client side, the context is not derived from the context returned.
|
||||
TagConn(context.Context, *ConnTagInfo) context.Context
|
||||
// HandleConn processes the Conn stats.
|
||||
HandleConn(context.Context, ConnStats)
|
||||
}
|
||||
223
vendor/google.golang.org/grpc/stats/stats.go
generated
vendored
Normal file
223
vendor/google.golang.org/grpc/stats/stats.go
generated
vendored
Normal file
@@ -0,0 +1,223 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2016, Google Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Google Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
// Package stats is for collecting and reporting various network and RPC stats.
|
||||
// This package is for monitoring purpose only. All fields are read-only.
|
||||
// All APIs are experimental.
|
||||
package stats // import "google.golang.org/grpc/stats"
|
||||
|
||||
import (
|
||||
"net"
|
||||
"time"
|
||||
)
|
||||
|
||||
// RPCStats contains stats information about RPCs.
|
||||
type RPCStats interface {
|
||||
isRPCStats()
|
||||
// IsClient returns true if this RPCStats is from client side.
|
||||
IsClient() bool
|
||||
}
|
||||
|
||||
// Begin contains stats when an RPC begins.
|
||||
// FailFast are only valid if Client is true.
|
||||
type Begin struct {
|
||||
// Client is true if this Begin is from client side.
|
||||
Client bool
|
||||
// BeginTime is the time when the RPC begins.
|
||||
BeginTime time.Time
|
||||
// FailFast indicates if this RPC is failfast.
|
||||
FailFast bool
|
||||
}
|
||||
|
||||
// IsClient indicates if this is from client side.
|
||||
func (s *Begin) IsClient() bool { return s.Client }
|
||||
|
||||
func (s *Begin) isRPCStats() {}
|
||||
|
||||
// InPayload contains the information for an incoming payload.
|
||||
type InPayload struct {
|
||||
// Client is true if this InPayload is from client side.
|
||||
Client bool
|
||||
// Payload is the payload with original type.
|
||||
Payload interface{}
|
||||
// Data is the serialized message payload.
|
||||
Data []byte
|
||||
// Length is the length of uncompressed data.
|
||||
Length int
|
||||
// WireLength is the length of data on wire (compressed, signed, encrypted).
|
||||
WireLength int
|
||||
// RecvTime is the time when the payload is received.
|
||||
RecvTime time.Time
|
||||
}
|
||||
|
||||
// IsClient indicates if this is from client side.
|
||||
func (s *InPayload) IsClient() bool { return s.Client }
|
||||
|
||||
func (s *InPayload) isRPCStats() {}
|
||||
|
||||
// InHeader contains stats when a header is received.
|
||||
// FullMethod, addresses and Compression are only valid if Client is false.
|
||||
type InHeader struct {
|
||||
// Client is true if this InHeader is from client side.
|
||||
Client bool
|
||||
// WireLength is the wire length of header.
|
||||
WireLength int
|
||||
|
||||
// FullMethod is the full RPC method string, i.e., /package.service/method.
|
||||
FullMethod string
|
||||
// RemoteAddr is the remote address of the corresponding connection.
|
||||
RemoteAddr net.Addr
|
||||
// LocalAddr is the local address of the corresponding connection.
|
||||
LocalAddr net.Addr
|
||||
// Compression is the compression algorithm used for the RPC.
|
||||
Compression string
|
||||
}
|
||||
|
||||
// IsClient indicates if this is from client side.
|
||||
func (s *InHeader) IsClient() bool { return s.Client }
|
||||
|
||||
func (s *InHeader) isRPCStats() {}
|
||||
|
||||
// InTrailer contains stats when a trailer is received.
|
||||
type InTrailer struct {
|
||||
// Client is true if this InTrailer is from client side.
|
||||
Client bool
|
||||
// WireLength is the wire length of trailer.
|
||||
WireLength int
|
||||
}
|
||||
|
||||
// IsClient indicates if this is from client side.
|
||||
func (s *InTrailer) IsClient() bool { return s.Client }
|
||||
|
||||
func (s *InTrailer) isRPCStats() {}
|
||||
|
||||
// OutPayload contains the information for an outgoing payload.
|
||||
type OutPayload struct {
|
||||
// Client is true if this OutPayload is from client side.
|
||||
Client bool
|
||||
// Payload is the payload with original type.
|
||||
Payload interface{}
|
||||
// Data is the serialized message payload.
|
||||
Data []byte
|
||||
// Length is the length of uncompressed data.
|
||||
Length int
|
||||
// WireLength is the length of data on wire (compressed, signed, encrypted).
|
||||
WireLength int
|
||||
// SentTime is the time when the payload is sent.
|
||||
SentTime time.Time
|
||||
}
|
||||
|
||||
// IsClient indicates if this is from client side.
|
||||
func (s *OutPayload) IsClient() bool { return s.Client }
|
||||
|
||||
func (s *OutPayload) isRPCStats() {}
|
||||
|
||||
// OutHeader contains stats when a header is sent.
|
||||
// FullMethod, addresses and Compression are only valid if Client is true.
|
||||
type OutHeader struct {
|
||||
// Client is true if this OutHeader is from client side.
|
||||
Client bool
|
||||
// WireLength is the wire length of header.
|
||||
WireLength int
|
||||
|
||||
// FullMethod is the full RPC method string, i.e., /package.service/method.
|
||||
FullMethod string
|
||||
// RemoteAddr is the remote address of the corresponding connection.
|
||||
RemoteAddr net.Addr
|
||||
// LocalAddr is the local address of the corresponding connection.
|
||||
LocalAddr net.Addr
|
||||
// Compression is the compression algorithm used for the RPC.
|
||||
Compression string
|
||||
}
|
||||
|
||||
// IsClient indicates if this is from client side.
|
||||
func (s *OutHeader) IsClient() bool { return s.Client }
|
||||
|
||||
func (s *OutHeader) isRPCStats() {}
|
||||
|
||||
// OutTrailer contains stats when a trailer is sent.
|
||||
type OutTrailer struct {
|
||||
// Client is true if this OutTrailer is from client side.
|
||||
Client bool
|
||||
// WireLength is the wire length of trailer.
|
||||
WireLength int
|
||||
}
|
||||
|
||||
// IsClient indicates if this is from client side.
|
||||
func (s *OutTrailer) IsClient() bool { return s.Client }
|
||||
|
||||
func (s *OutTrailer) isRPCStats() {}
|
||||
|
||||
// End contains stats when an RPC ends.
|
||||
type End struct {
|
||||
// Client is true if this End is from client side.
|
||||
Client bool
|
||||
// EndTime is the time when the RPC ends.
|
||||
EndTime time.Time
|
||||
// Error is the error just happened. Its type is gRPC error.
|
||||
Error error
|
||||
}
|
||||
|
||||
// IsClient indicates if this is from client side.
|
||||
func (s *End) IsClient() bool { return s.Client }
|
||||
|
||||
func (s *End) isRPCStats() {}
|
||||
|
||||
// ConnStats contains stats information about connections.
|
||||
type ConnStats interface {
|
||||
isConnStats()
|
||||
// IsClient returns true if this ConnStats is from client side.
|
||||
IsClient() bool
|
||||
}
|
||||
|
||||
// ConnBegin contains the stats of a connection when it is established.
|
||||
type ConnBegin struct {
|
||||
// Client is true if this ConnBegin is from client side.
|
||||
Client bool
|
||||
}
|
||||
|
||||
// IsClient indicates if this is from client side.
|
||||
func (s *ConnBegin) IsClient() bool { return s.Client }
|
||||
|
||||
func (s *ConnBegin) isConnStats() {}
|
||||
|
||||
// ConnEnd contains the stats of a connection when it ends.
|
||||
type ConnEnd struct {
|
||||
// Client is true if this ConnEnd is from client side.
|
||||
Client bool
|
||||
}
|
||||
|
||||
// IsClient indicates if this is from client side.
|
||||
func (s *ConnEnd) IsClient() bool { return s.Client }
|
||||
|
||||
func (s *ConnEnd) isConnStats() {}
|
||||
981
vendor/google.golang.org/grpc/stats/stats_test.go
generated
vendored
Normal file
981
vendor/google.golang.org/grpc/stats/stats_test.go
generated
vendored
Normal file
@@ -0,0 +1,981 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2016, Google Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Google Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
package stats_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"reflect"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/golang/protobuf/proto"
|
||||
"golang.org/x/net/context"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/metadata"
|
||||
"google.golang.org/grpc/stats"
|
||||
testpb "google.golang.org/grpc/stats/grpc_testing"
|
||||
)
|
||||
|
||||
func init() {
|
||||
grpc.EnableTracing = false
|
||||
}
|
||||
|
||||
type connCtxKey struct{}
|
||||
type rpcCtxKey struct{}
|
||||
|
||||
var (
|
||||
// For headers:
|
||||
testMetadata = metadata.MD{
|
||||
"key1": []string{"value1"},
|
||||
"key2": []string{"value2"},
|
||||
}
|
||||
// For trailers:
|
||||
testTrailerMetadata = metadata.MD{
|
||||
"tkey1": []string{"trailerValue1"},
|
||||
"tkey2": []string{"trailerValue2"},
|
||||
}
|
||||
// The id for which the service handler should return error.
|
||||
errorID int32 = 32202
|
||||
)
|
||||
|
||||
type testServer struct{}
|
||||
|
||||
func (s *testServer) UnaryCall(ctx context.Context, in *testpb.SimpleRequest) (*testpb.SimpleResponse, error) {
|
||||
md, ok := metadata.FromContext(ctx)
|
||||
if ok {
|
||||
if err := grpc.SendHeader(ctx, md); err != nil {
|
||||
return nil, grpc.Errorf(grpc.Code(err), "grpc.SendHeader(_, %v) = %v, want <nil>", md, err)
|
||||
}
|
||||
if err := grpc.SetTrailer(ctx, testTrailerMetadata); err != nil {
|
||||
return nil, grpc.Errorf(grpc.Code(err), "grpc.SetTrailer(_, %v) = %v, want <nil>", testTrailerMetadata, err)
|
||||
}
|
||||
}
|
||||
|
||||
if in.Id == errorID {
|
||||
return nil, fmt.Errorf("got error id: %v", in.Id)
|
||||
}
|
||||
|
||||
return &testpb.SimpleResponse{Id: in.Id}, nil
|
||||
}
|
||||
|
||||
func (s *testServer) FullDuplexCall(stream testpb.TestService_FullDuplexCallServer) error {
|
||||
md, ok := metadata.FromContext(stream.Context())
|
||||
if ok {
|
||||
if err := stream.SendHeader(md); err != nil {
|
||||
return grpc.Errorf(grpc.Code(err), "%v.SendHeader(%v) = %v, want %v", stream, md, err, nil)
|
||||
}
|
||||
stream.SetTrailer(testTrailerMetadata)
|
||||
}
|
||||
for {
|
||||
in, err := stream.Recv()
|
||||
if err == io.EOF {
|
||||
// read done.
|
||||
return nil
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if in.Id == errorID {
|
||||
return fmt.Errorf("got error id: %v", in.Id)
|
||||
}
|
||||
|
||||
if err := stream.Send(&testpb.SimpleResponse{Id: in.Id}); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// test is an end-to-end test. It should be created with the newTest
|
||||
// func, modified as needed, and then started with its startServer method.
|
||||
// It should be cleaned up with the tearDown method.
|
||||
type test struct {
|
||||
t *testing.T
|
||||
compress string
|
||||
clientStatsHandler stats.Handler
|
||||
serverStatsHandler stats.Handler
|
||||
|
||||
testServer testpb.TestServiceServer // nil means none
|
||||
// srv and srvAddr are set once startServer is called.
|
||||
srv *grpc.Server
|
||||
srvAddr string
|
||||
|
||||
cc *grpc.ClientConn // nil until requested via clientConn
|
||||
}
|
||||
|
||||
func (te *test) tearDown() {
|
||||
if te.cc != nil {
|
||||
te.cc.Close()
|
||||
te.cc = nil
|
||||
}
|
||||
te.srv.Stop()
|
||||
}
|
||||
|
||||
type testConfig struct {
|
||||
compress string
|
||||
}
|
||||
|
||||
// newTest returns a new test using the provided testing.T and
|
||||
// environment. It is returned with default values. Tests should
|
||||
// modify it before calling its startServer and clientConn methods.
|
||||
func newTest(t *testing.T, tc *testConfig, ch stats.Handler, sh stats.Handler) *test {
|
||||
te := &test{
|
||||
t: t,
|
||||
compress: tc.compress,
|
||||
clientStatsHandler: ch,
|
||||
serverStatsHandler: sh,
|
||||
}
|
||||
return te
|
||||
}
|
||||
|
||||
// startServer starts a gRPC server listening. Callers should defer a
|
||||
// call to te.tearDown to clean up.
|
||||
func (te *test) startServer(ts testpb.TestServiceServer) {
|
||||
te.testServer = ts
|
||||
lis, err := net.Listen("tcp", "localhost:0")
|
||||
if err != nil {
|
||||
te.t.Fatalf("Failed to listen: %v", err)
|
||||
}
|
||||
var opts []grpc.ServerOption
|
||||
if te.compress == "gzip" {
|
||||
opts = append(opts,
|
||||
grpc.RPCCompressor(grpc.NewGZIPCompressor()),
|
||||
grpc.RPCDecompressor(grpc.NewGZIPDecompressor()),
|
||||
)
|
||||
}
|
||||
if te.serverStatsHandler != nil {
|
||||
opts = append(opts, grpc.StatsHandler(te.serverStatsHandler))
|
||||
}
|
||||
s := grpc.NewServer(opts...)
|
||||
te.srv = s
|
||||
if te.testServer != nil {
|
||||
testpb.RegisterTestServiceServer(s, te.testServer)
|
||||
}
|
||||
_, port, err := net.SplitHostPort(lis.Addr().String())
|
||||
if err != nil {
|
||||
te.t.Fatalf("Failed to parse listener address: %v", err)
|
||||
}
|
||||
addr := "127.0.0.1:" + port
|
||||
|
||||
go s.Serve(lis)
|
||||
te.srvAddr = addr
|
||||
}
|
||||
|
||||
func (te *test) clientConn() *grpc.ClientConn {
|
||||
if te.cc != nil {
|
||||
return te.cc
|
||||
}
|
||||
opts := []grpc.DialOption{grpc.WithInsecure(), grpc.WithBlock()}
|
||||
if te.compress == "gzip" {
|
||||
opts = append(opts,
|
||||
grpc.WithCompressor(grpc.NewGZIPCompressor()),
|
||||
grpc.WithDecompressor(grpc.NewGZIPDecompressor()),
|
||||
)
|
||||
}
|
||||
if te.clientStatsHandler != nil {
|
||||
opts = append(opts, grpc.WithStatsHandler(te.clientStatsHandler))
|
||||
}
|
||||
|
||||
var err error
|
||||
te.cc, err = grpc.Dial(te.srvAddr, opts...)
|
||||
if err != nil {
|
||||
te.t.Fatalf("Dial(%q) = %v", te.srvAddr, err)
|
||||
}
|
||||
return te.cc
|
||||
}
|
||||
|
||||
type rpcConfig struct {
|
||||
count int // Number of requests and responses for streaming RPCs.
|
||||
success bool // Whether the RPC should succeed or return error.
|
||||
failfast bool
|
||||
streaming bool // Whether the rpc should be a streaming RPC.
|
||||
}
|
||||
|
||||
func (te *test) doUnaryCall(c *rpcConfig) (*testpb.SimpleRequest, *testpb.SimpleResponse, error) {
|
||||
var (
|
||||
resp *testpb.SimpleResponse
|
||||
req *testpb.SimpleRequest
|
||||
err error
|
||||
)
|
||||
tc := testpb.NewTestServiceClient(te.clientConn())
|
||||
if c.success {
|
||||
req = &testpb.SimpleRequest{Id: errorID + 1}
|
||||
} else {
|
||||
req = &testpb.SimpleRequest{Id: errorID}
|
||||
}
|
||||
ctx := metadata.NewContext(context.Background(), testMetadata)
|
||||
|
||||
resp, err = tc.UnaryCall(ctx, req, grpc.FailFast(c.failfast))
|
||||
return req, resp, err
|
||||
}
|
||||
|
||||
func (te *test) doFullDuplexCallRoundtrip(c *rpcConfig) ([]*testpb.SimpleRequest, []*testpb.SimpleResponse, error) {
|
||||
var (
|
||||
reqs []*testpb.SimpleRequest
|
||||
resps []*testpb.SimpleResponse
|
||||
err error
|
||||
)
|
||||
tc := testpb.NewTestServiceClient(te.clientConn())
|
||||
stream, err := tc.FullDuplexCall(metadata.NewContext(context.Background(), testMetadata), grpc.FailFast(c.failfast))
|
||||
if err != nil {
|
||||
return reqs, resps, err
|
||||
}
|
||||
var startID int32
|
||||
if !c.success {
|
||||
startID = errorID
|
||||
}
|
||||
for i := 0; i < c.count; i++ {
|
||||
req := &testpb.SimpleRequest{
|
||||
Id: int32(i) + startID,
|
||||
}
|
||||
reqs = append(reqs, req)
|
||||
if err = stream.Send(req); err != nil {
|
||||
return reqs, resps, err
|
||||
}
|
||||
var resp *testpb.SimpleResponse
|
||||
if resp, err = stream.Recv(); err != nil {
|
||||
return reqs, resps, err
|
||||
}
|
||||
resps = append(resps, resp)
|
||||
}
|
||||
if err = stream.CloseSend(); err != nil && err != io.EOF {
|
||||
return reqs, resps, err
|
||||
}
|
||||
if _, err = stream.Recv(); err != io.EOF {
|
||||
return reqs, resps, err
|
||||
}
|
||||
|
||||
return reqs, resps, nil
|
||||
}
|
||||
|
||||
type expectedData struct {
|
||||
method string
|
||||
serverAddr string
|
||||
compression string
|
||||
reqIdx int
|
||||
requests []*testpb.SimpleRequest
|
||||
respIdx int
|
||||
responses []*testpb.SimpleResponse
|
||||
err error
|
||||
failfast bool
|
||||
}
|
||||
|
||||
type gotData struct {
|
||||
ctx context.Context
|
||||
client bool
|
||||
s interface{} // This could be RPCStats or ConnStats.
|
||||
}
|
||||
|
||||
const (
|
||||
begin int = iota
|
||||
end
|
||||
inPayload
|
||||
inHeader
|
||||
inTrailer
|
||||
outPayload
|
||||
outHeader
|
||||
outTrailer
|
||||
connbegin
|
||||
connend
|
||||
)
|
||||
|
||||
func checkBegin(t *testing.T, d *gotData, e *expectedData) {
|
||||
var (
|
||||
ok bool
|
||||
st *stats.Begin
|
||||
)
|
||||
if st, ok = d.s.(*stats.Begin); !ok {
|
||||
t.Fatalf("got %T, want Begin", d.s)
|
||||
}
|
||||
if d.ctx == nil {
|
||||
t.Fatalf("d.ctx = nil, want <non-nil>")
|
||||
}
|
||||
if st.BeginTime.IsZero() {
|
||||
t.Fatalf("st.BeginTime = %v, want <non-zero>", st.BeginTime)
|
||||
}
|
||||
if d.client {
|
||||
if st.FailFast != e.failfast {
|
||||
t.Fatalf("st.FailFast = %v, want %v", st.FailFast, e.failfast)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func checkInHeader(t *testing.T, d *gotData, e *expectedData) {
|
||||
var (
|
||||
ok bool
|
||||
st *stats.InHeader
|
||||
)
|
||||
if st, ok = d.s.(*stats.InHeader); !ok {
|
||||
t.Fatalf("got %T, want InHeader", d.s)
|
||||
}
|
||||
if d.ctx == nil {
|
||||
t.Fatalf("d.ctx = nil, want <non-nil>")
|
||||
}
|
||||
// TODO check real length, not just > 0.
|
||||
if st.WireLength <= 0 {
|
||||
t.Fatalf("st.Lenght = 0, want > 0")
|
||||
}
|
||||
if !d.client {
|
||||
if st.FullMethod != e.method {
|
||||
t.Fatalf("st.FullMethod = %s, want %v", st.FullMethod, e.method)
|
||||
}
|
||||
if st.LocalAddr.String() != e.serverAddr {
|
||||
t.Fatalf("st.LocalAddr = %v, want %v", st.LocalAddr, e.serverAddr)
|
||||
}
|
||||
if st.Compression != e.compression {
|
||||
t.Fatalf("st.Compression = %v, want %v", st.Compression, e.compression)
|
||||
}
|
||||
|
||||
if connInfo, ok := d.ctx.Value(connCtxKey{}).(*stats.ConnTagInfo); ok {
|
||||
if connInfo.RemoteAddr != st.RemoteAddr {
|
||||
t.Fatalf("connInfo.RemoteAddr = %v, want %v", connInfo.RemoteAddr, st.RemoteAddr)
|
||||
}
|
||||
if connInfo.LocalAddr != st.LocalAddr {
|
||||
t.Fatalf("connInfo.LocalAddr = %v, want %v", connInfo.LocalAddr, st.LocalAddr)
|
||||
}
|
||||
} else {
|
||||
t.Fatalf("got context %v, want one with connCtxKey", d.ctx)
|
||||
}
|
||||
if rpcInfo, ok := d.ctx.Value(rpcCtxKey{}).(*stats.RPCTagInfo); ok {
|
||||
if rpcInfo.FullMethodName != st.FullMethod {
|
||||
t.Fatalf("rpcInfo.FullMethod = %s, want %v", rpcInfo.FullMethodName, st.FullMethod)
|
||||
}
|
||||
} else {
|
||||
t.Fatalf("got context %v, want one with rpcCtxKey", d.ctx)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func checkInPayload(t *testing.T, d *gotData, e *expectedData) {
|
||||
var (
|
||||
ok bool
|
||||
st *stats.InPayload
|
||||
)
|
||||
if st, ok = d.s.(*stats.InPayload); !ok {
|
||||
t.Fatalf("got %T, want InPayload", d.s)
|
||||
}
|
||||
if d.ctx == nil {
|
||||
t.Fatalf("d.ctx = nil, want <non-nil>")
|
||||
}
|
||||
if d.client {
|
||||
b, err := proto.Marshal(e.responses[e.respIdx])
|
||||
if err != nil {
|
||||
t.Fatalf("failed to marshal message: %v", err)
|
||||
}
|
||||
if reflect.TypeOf(st.Payload) != reflect.TypeOf(e.responses[e.respIdx]) {
|
||||
t.Fatalf("st.Payload = %T, want %T", st.Payload, e.responses[e.respIdx])
|
||||
}
|
||||
e.respIdx++
|
||||
if string(st.Data) != string(b) {
|
||||
t.Fatalf("st.Data = %v, want %v", st.Data, b)
|
||||
}
|
||||
if st.Length != len(b) {
|
||||
t.Fatalf("st.Lenght = %v, want %v", st.Length, len(b))
|
||||
}
|
||||
} else {
|
||||
b, err := proto.Marshal(e.requests[e.reqIdx])
|
||||
if err != nil {
|
||||
t.Fatalf("failed to marshal message: %v", err)
|
||||
}
|
||||
if reflect.TypeOf(st.Payload) != reflect.TypeOf(e.requests[e.reqIdx]) {
|
||||
t.Fatalf("st.Payload = %T, want %T", st.Payload, e.requests[e.reqIdx])
|
||||
}
|
||||
e.reqIdx++
|
||||
if string(st.Data) != string(b) {
|
||||
t.Fatalf("st.Data = %v, want %v", st.Data, b)
|
||||
}
|
||||
if st.Length != len(b) {
|
||||
t.Fatalf("st.Lenght = %v, want %v", st.Length, len(b))
|
||||
}
|
||||
}
|
||||
// TODO check WireLength and ReceivedTime.
|
||||
if st.RecvTime.IsZero() {
|
||||
t.Fatalf("st.ReceivedTime = %v, want <non-zero>", st.RecvTime)
|
||||
}
|
||||
}
|
||||
|
||||
func checkInTrailer(t *testing.T, d *gotData, e *expectedData) {
|
||||
var (
|
||||
ok bool
|
||||
st *stats.InTrailer
|
||||
)
|
||||
if st, ok = d.s.(*stats.InTrailer); !ok {
|
||||
t.Fatalf("got %T, want InTrailer", d.s)
|
||||
}
|
||||
if d.ctx == nil {
|
||||
t.Fatalf("d.ctx = nil, want <non-nil>")
|
||||
}
|
||||
// TODO check real length, not just > 0.
|
||||
if st.WireLength <= 0 {
|
||||
t.Fatalf("st.Lenght = 0, want > 0")
|
||||
}
|
||||
}
|
||||
|
||||
func checkOutHeader(t *testing.T, d *gotData, e *expectedData) {
|
||||
var (
|
||||
ok bool
|
||||
st *stats.OutHeader
|
||||
)
|
||||
if st, ok = d.s.(*stats.OutHeader); !ok {
|
||||
t.Fatalf("got %T, want OutHeader", d.s)
|
||||
}
|
||||
if d.ctx == nil {
|
||||
t.Fatalf("d.ctx = nil, want <non-nil>")
|
||||
}
|
||||
// TODO check real length, not just > 0.
|
||||
if st.WireLength <= 0 {
|
||||
t.Fatalf("st.Lenght = 0, want > 0")
|
||||
}
|
||||
if d.client {
|
||||
if st.FullMethod != e.method {
|
||||
t.Fatalf("st.FullMethod = %s, want %v", st.FullMethod, e.method)
|
||||
}
|
||||
if st.RemoteAddr.String() != e.serverAddr {
|
||||
t.Fatalf("st.RemoteAddr = %v, want %v", st.RemoteAddr, e.serverAddr)
|
||||
}
|
||||
if st.Compression != e.compression {
|
||||
t.Fatalf("st.Compression = %v, want %v", st.Compression, e.compression)
|
||||
}
|
||||
|
||||
if rpcInfo, ok := d.ctx.Value(rpcCtxKey{}).(*stats.RPCTagInfo); ok {
|
||||
if rpcInfo.FullMethodName != st.FullMethod {
|
||||
t.Fatalf("rpcInfo.FullMethod = %s, want %v", rpcInfo.FullMethodName, st.FullMethod)
|
||||
}
|
||||
} else {
|
||||
t.Fatalf("got context %v, want one with rpcCtxKey", d.ctx)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func checkOutPayload(t *testing.T, d *gotData, e *expectedData) {
|
||||
var (
|
||||
ok bool
|
||||
st *stats.OutPayload
|
||||
)
|
||||
if st, ok = d.s.(*stats.OutPayload); !ok {
|
||||
t.Fatalf("got %T, want OutPayload", d.s)
|
||||
}
|
||||
if d.ctx == nil {
|
||||
t.Fatalf("d.ctx = nil, want <non-nil>")
|
||||
}
|
||||
if d.client {
|
||||
b, err := proto.Marshal(e.requests[e.reqIdx])
|
||||
if err != nil {
|
||||
t.Fatalf("failed to marshal message: %v", err)
|
||||
}
|
||||
if reflect.TypeOf(st.Payload) != reflect.TypeOf(e.requests[e.reqIdx]) {
|
||||
t.Fatalf("st.Payload = %T, want %T", st.Payload, e.requests[e.reqIdx])
|
||||
}
|
||||
e.reqIdx++
|
||||
if string(st.Data) != string(b) {
|
||||
t.Fatalf("st.Data = %v, want %v", st.Data, b)
|
||||
}
|
||||
if st.Length != len(b) {
|
||||
t.Fatalf("st.Lenght = %v, want %v", st.Length, len(b))
|
||||
}
|
||||
} else {
|
||||
b, err := proto.Marshal(e.responses[e.respIdx])
|
||||
if err != nil {
|
||||
t.Fatalf("failed to marshal message: %v", err)
|
||||
}
|
||||
if reflect.TypeOf(st.Payload) != reflect.TypeOf(e.responses[e.respIdx]) {
|
||||
t.Fatalf("st.Payload = %T, want %T", st.Payload, e.responses[e.respIdx])
|
||||
}
|
||||
e.respIdx++
|
||||
if string(st.Data) != string(b) {
|
||||
t.Fatalf("st.Data = %v, want %v", st.Data, b)
|
||||
}
|
||||
if st.Length != len(b) {
|
||||
t.Fatalf("st.Lenght = %v, want %v", st.Length, len(b))
|
||||
}
|
||||
}
|
||||
// TODO check WireLength and ReceivedTime.
|
||||
if st.SentTime.IsZero() {
|
||||
t.Fatalf("st.SentTime = %v, want <non-zero>", st.SentTime)
|
||||
}
|
||||
}
|
||||
|
||||
func checkOutTrailer(t *testing.T, d *gotData, e *expectedData) {
|
||||
var (
|
||||
ok bool
|
||||
st *stats.OutTrailer
|
||||
)
|
||||
if st, ok = d.s.(*stats.OutTrailer); !ok {
|
||||
t.Fatalf("got %T, want OutTrailer", d.s)
|
||||
}
|
||||
if d.ctx == nil {
|
||||
t.Fatalf("d.ctx = nil, want <non-nil>")
|
||||
}
|
||||
if st.Client {
|
||||
t.Fatalf("st IsClient = true, want false")
|
||||
}
|
||||
// TODO check real length, not just > 0.
|
||||
if st.WireLength <= 0 {
|
||||
t.Fatalf("st.Lenght = 0, want > 0")
|
||||
}
|
||||
}
|
||||
|
||||
func checkEnd(t *testing.T, d *gotData, e *expectedData) {
|
||||
var (
|
||||
ok bool
|
||||
st *stats.End
|
||||
)
|
||||
if st, ok = d.s.(*stats.End); !ok {
|
||||
t.Fatalf("got %T, want End", d.s)
|
||||
}
|
||||
if d.ctx == nil {
|
||||
t.Fatalf("d.ctx = nil, want <non-nil>")
|
||||
}
|
||||
if st.EndTime.IsZero() {
|
||||
t.Fatalf("st.EndTime = %v, want <non-zero>", st.EndTime)
|
||||
}
|
||||
if grpc.Code(st.Error) != grpc.Code(e.err) || grpc.ErrorDesc(st.Error) != grpc.ErrorDesc(e.err) {
|
||||
t.Fatalf("st.Error = %v, want %v", st.Error, e.err)
|
||||
}
|
||||
}
|
||||
|
||||
func checkConnBegin(t *testing.T, d *gotData, e *expectedData) {
|
||||
var (
|
||||
ok bool
|
||||
st *stats.ConnBegin
|
||||
)
|
||||
if st, ok = d.s.(*stats.ConnBegin); !ok {
|
||||
t.Fatalf("got %T, want ConnBegin", d.s)
|
||||
}
|
||||
if d.ctx == nil {
|
||||
t.Fatalf("d.ctx = nil, want <non-nil>")
|
||||
}
|
||||
st.IsClient() // TODO remove this.
|
||||
}
|
||||
|
||||
func checkConnEnd(t *testing.T, d *gotData, e *expectedData) {
|
||||
var (
|
||||
ok bool
|
||||
st *stats.ConnEnd
|
||||
)
|
||||
if st, ok = d.s.(*stats.ConnEnd); !ok {
|
||||
t.Fatalf("got %T, want ConnEnd", d.s)
|
||||
}
|
||||
if d.ctx == nil {
|
||||
t.Fatalf("d.ctx = nil, want <non-nil>")
|
||||
}
|
||||
st.IsClient() // TODO remove this.
|
||||
}
|
||||
|
||||
type statshandler struct {
|
||||
mu sync.Mutex
|
||||
gotRPC []*gotData
|
||||
gotConn []*gotData
|
||||
}
|
||||
|
||||
func (h *statshandler) TagConn(ctx context.Context, info *stats.ConnTagInfo) context.Context {
|
||||
return context.WithValue(ctx, connCtxKey{}, info)
|
||||
}
|
||||
|
||||
func (h *statshandler) TagRPC(ctx context.Context, info *stats.RPCTagInfo) context.Context {
|
||||
return context.WithValue(ctx, rpcCtxKey{}, info)
|
||||
}
|
||||
|
||||
func (h *statshandler) HandleConn(ctx context.Context, s stats.ConnStats) {
|
||||
h.mu.Lock()
|
||||
defer h.mu.Unlock()
|
||||
h.gotConn = append(h.gotConn, &gotData{ctx, s.IsClient(), s})
|
||||
}
|
||||
|
||||
func (h *statshandler) HandleRPC(ctx context.Context, s stats.RPCStats) {
|
||||
h.mu.Lock()
|
||||
defer h.mu.Unlock()
|
||||
h.gotRPC = append(h.gotRPC, &gotData{ctx, s.IsClient(), s})
|
||||
}
|
||||
|
||||
func checkConnStats(t *testing.T, got []*gotData) {
|
||||
if len(got) <= 0 || len(got)%2 != 0 {
|
||||
for i, g := range got {
|
||||
t.Errorf(" - %v, %T = %+v, ctx: %v", i, g.s, g.s, g.ctx)
|
||||
}
|
||||
t.Fatalf("got %v stats, want even positive number", len(got))
|
||||
}
|
||||
// The first conn stats must be a ConnBegin.
|
||||
checkConnBegin(t, got[0], nil)
|
||||
// The last conn stats must be a ConnEnd.
|
||||
checkConnEnd(t, got[len(got)-1], nil)
|
||||
}
|
||||
|
||||
func checkServerStats(t *testing.T, got []*gotData, expect *expectedData, checkFuncs []func(t *testing.T, d *gotData, e *expectedData)) {
|
||||
if len(got) != len(checkFuncs) {
|
||||
for i, g := range got {
|
||||
t.Errorf(" - %v, %T", i, g.s)
|
||||
}
|
||||
t.Fatalf("got %v stats, want %v stats", len(got), len(checkFuncs))
|
||||
}
|
||||
|
||||
var rpcctx context.Context
|
||||
for i := 0; i < len(got); i++ {
|
||||
if _, ok := got[i].s.(stats.RPCStats); ok {
|
||||
if rpcctx != nil && got[i].ctx != rpcctx {
|
||||
t.Fatalf("got different contexts with stats %T", got[i].s)
|
||||
}
|
||||
rpcctx = got[i].ctx
|
||||
}
|
||||
}
|
||||
|
||||
for i, f := range checkFuncs {
|
||||
f(t, got[i], expect)
|
||||
}
|
||||
}
|
||||
|
||||
func testServerStats(t *testing.T, tc *testConfig, cc *rpcConfig, checkFuncs []func(t *testing.T, d *gotData, e *expectedData)) {
|
||||
h := &statshandler{}
|
||||
te := newTest(t, tc, nil, h)
|
||||
te.startServer(&testServer{})
|
||||
defer te.tearDown()
|
||||
|
||||
var (
|
||||
reqs []*testpb.SimpleRequest
|
||||
resps []*testpb.SimpleResponse
|
||||
err error
|
||||
)
|
||||
if !cc.streaming {
|
||||
req, resp, e := te.doUnaryCall(cc)
|
||||
reqs = []*testpb.SimpleRequest{req}
|
||||
resps = []*testpb.SimpleResponse{resp}
|
||||
err = e
|
||||
} else {
|
||||
reqs, resps, err = te.doFullDuplexCallRoundtrip(cc)
|
||||
}
|
||||
if cc.success != (err == nil) {
|
||||
t.Fatalf("cc.success: %v, got error: %v", cc.success, err)
|
||||
}
|
||||
te.cc.Close()
|
||||
te.srv.GracefulStop() // Wait for the server to stop.
|
||||
|
||||
for {
|
||||
h.mu.Lock()
|
||||
if len(h.gotRPC) >= len(checkFuncs) {
|
||||
h.mu.Unlock()
|
||||
break
|
||||
}
|
||||
h.mu.Unlock()
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
}
|
||||
|
||||
for {
|
||||
h.mu.Lock()
|
||||
if _, ok := h.gotConn[len(h.gotConn)-1].s.(*stats.ConnEnd); ok {
|
||||
h.mu.Unlock()
|
||||
break
|
||||
}
|
||||
h.mu.Unlock()
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
}
|
||||
|
||||
expect := &expectedData{
|
||||
serverAddr: te.srvAddr,
|
||||
compression: tc.compress,
|
||||
requests: reqs,
|
||||
responses: resps,
|
||||
err: err,
|
||||
}
|
||||
if !cc.streaming {
|
||||
expect.method = "/grpc.testing.TestService/UnaryCall"
|
||||
} else {
|
||||
expect.method = "/grpc.testing.TestService/FullDuplexCall"
|
||||
}
|
||||
|
||||
checkConnStats(t, h.gotConn)
|
||||
checkServerStats(t, h.gotRPC, expect, checkFuncs)
|
||||
}
|
||||
|
||||
func TestServerStatsUnaryRPC(t *testing.T) {
|
||||
testServerStats(t, &testConfig{compress: ""}, &rpcConfig{success: true}, []func(t *testing.T, d *gotData, e *expectedData){
|
||||
checkInHeader,
|
||||
checkBegin,
|
||||
checkInPayload,
|
||||
checkOutHeader,
|
||||
checkOutPayload,
|
||||
checkOutTrailer,
|
||||
checkEnd,
|
||||
})
|
||||
}
|
||||
|
||||
func TestServerStatsUnaryRPCError(t *testing.T) {
|
||||
testServerStats(t, &testConfig{compress: ""}, &rpcConfig{success: false}, []func(t *testing.T, d *gotData, e *expectedData){
|
||||
checkInHeader,
|
||||
checkBegin,
|
||||
checkInPayload,
|
||||
checkOutHeader,
|
||||
checkOutTrailer,
|
||||
checkEnd,
|
||||
})
|
||||
}
|
||||
|
||||
func TestServerStatsStreamingRPC(t *testing.T) {
|
||||
count := 5
|
||||
checkFuncs := []func(t *testing.T, d *gotData, e *expectedData){
|
||||
checkInHeader,
|
||||
checkBegin,
|
||||
checkOutHeader,
|
||||
}
|
||||
ioPayFuncs := []func(t *testing.T, d *gotData, e *expectedData){
|
||||
checkInPayload,
|
||||
checkOutPayload,
|
||||
}
|
||||
for i := 0; i < count; i++ {
|
||||
checkFuncs = append(checkFuncs, ioPayFuncs...)
|
||||
}
|
||||
checkFuncs = append(checkFuncs,
|
||||
checkOutTrailer,
|
||||
checkEnd,
|
||||
)
|
||||
testServerStats(t, &testConfig{compress: "gzip"}, &rpcConfig{count: count, success: true, streaming: true}, checkFuncs)
|
||||
}
|
||||
|
||||
func TestServerStatsStreamingRPCError(t *testing.T) {
|
||||
count := 5
|
||||
testServerStats(t, &testConfig{compress: "gzip"}, &rpcConfig{count: count, success: false, streaming: true}, []func(t *testing.T, d *gotData, e *expectedData){
|
||||
checkInHeader,
|
||||
checkBegin,
|
||||
checkOutHeader,
|
||||
checkInPayload,
|
||||
checkOutTrailer,
|
||||
checkEnd,
|
||||
})
|
||||
}
|
||||
|
||||
type checkFuncWithCount struct {
|
||||
f func(t *testing.T, d *gotData, e *expectedData)
|
||||
c int // expected count
|
||||
}
|
||||
|
||||
func checkClientStats(t *testing.T, got []*gotData, expect *expectedData, checkFuncs map[int]*checkFuncWithCount) {
|
||||
var expectLen int
|
||||
for _, v := range checkFuncs {
|
||||
expectLen += v.c
|
||||
}
|
||||
if len(got) != expectLen {
|
||||
for i, g := range got {
|
||||
t.Errorf(" - %v, %T", i, g.s)
|
||||
}
|
||||
t.Fatalf("got %v stats, want %v stats", len(got), expectLen)
|
||||
}
|
||||
|
||||
var rpcctx context.Context
|
||||
for i := 0; i < len(got); i++ {
|
||||
if _, ok := got[i].s.(stats.RPCStats); ok {
|
||||
if rpcctx != nil && got[i].ctx != rpcctx {
|
||||
t.Fatalf("got different contexts with stats %T", got[i].s)
|
||||
}
|
||||
rpcctx = got[i].ctx
|
||||
}
|
||||
}
|
||||
|
||||
for _, s := range got {
|
||||
switch s.s.(type) {
|
||||
case *stats.Begin:
|
||||
if checkFuncs[begin].c <= 0 {
|
||||
t.Fatalf("unexpected stats: %T", s.s)
|
||||
}
|
||||
checkFuncs[begin].f(t, s, expect)
|
||||
checkFuncs[begin].c--
|
||||
case *stats.OutHeader:
|
||||
if checkFuncs[outHeader].c <= 0 {
|
||||
t.Fatalf("unexpected stats: %T", s.s)
|
||||
}
|
||||
checkFuncs[outHeader].f(t, s, expect)
|
||||
checkFuncs[outHeader].c--
|
||||
case *stats.OutPayload:
|
||||
if checkFuncs[outPayload].c <= 0 {
|
||||
t.Fatalf("unexpected stats: %T", s.s)
|
||||
}
|
||||
checkFuncs[outPayload].f(t, s, expect)
|
||||
checkFuncs[outPayload].c--
|
||||
case *stats.InHeader:
|
||||
if checkFuncs[inHeader].c <= 0 {
|
||||
t.Fatalf("unexpected stats: %T", s.s)
|
||||
}
|
||||
checkFuncs[inHeader].f(t, s, expect)
|
||||
checkFuncs[inHeader].c--
|
||||
case *stats.InPayload:
|
||||
if checkFuncs[inPayload].c <= 0 {
|
||||
t.Fatalf("unexpected stats: %T", s.s)
|
||||
}
|
||||
checkFuncs[inPayload].f(t, s, expect)
|
||||
checkFuncs[inPayload].c--
|
||||
case *stats.InTrailer:
|
||||
if checkFuncs[inTrailer].c <= 0 {
|
||||
t.Fatalf("unexpected stats: %T", s.s)
|
||||
}
|
||||
checkFuncs[inTrailer].f(t, s, expect)
|
||||
checkFuncs[inTrailer].c--
|
||||
case *stats.End:
|
||||
if checkFuncs[end].c <= 0 {
|
||||
t.Fatalf("unexpected stats: %T", s.s)
|
||||
}
|
||||
checkFuncs[end].f(t, s, expect)
|
||||
checkFuncs[end].c--
|
||||
case *stats.ConnBegin:
|
||||
if checkFuncs[connbegin].c <= 0 {
|
||||
t.Fatalf("unexpected stats: %T", s.s)
|
||||
}
|
||||
checkFuncs[connbegin].f(t, s, expect)
|
||||
checkFuncs[connbegin].c--
|
||||
case *stats.ConnEnd:
|
||||
if checkFuncs[connend].c <= 0 {
|
||||
t.Fatalf("unexpected stats: %T", s.s)
|
||||
}
|
||||
checkFuncs[connend].f(t, s, expect)
|
||||
checkFuncs[connend].c--
|
||||
default:
|
||||
t.Fatalf("unexpected stats: %T", s.s)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func testClientStats(t *testing.T, tc *testConfig, cc *rpcConfig, checkFuncs map[int]*checkFuncWithCount) {
|
||||
h := &statshandler{}
|
||||
te := newTest(t, tc, h, nil)
|
||||
te.startServer(&testServer{})
|
||||
defer te.tearDown()
|
||||
|
||||
var (
|
||||
reqs []*testpb.SimpleRequest
|
||||
resps []*testpb.SimpleResponse
|
||||
err error
|
||||
)
|
||||
if !cc.streaming {
|
||||
req, resp, e := te.doUnaryCall(cc)
|
||||
reqs = []*testpb.SimpleRequest{req}
|
||||
resps = []*testpb.SimpleResponse{resp}
|
||||
err = e
|
||||
} else {
|
||||
reqs, resps, err = te.doFullDuplexCallRoundtrip(cc)
|
||||
}
|
||||
if cc.success != (err == nil) {
|
||||
t.Fatalf("cc.success: %v, got error: %v", cc.success, err)
|
||||
}
|
||||
te.cc.Close()
|
||||
te.srv.GracefulStop() // Wait for the server to stop.
|
||||
|
||||
lenRPCStats := 0
|
||||
for _, v := range checkFuncs {
|
||||
lenRPCStats += v.c
|
||||
}
|
||||
for {
|
||||
h.mu.Lock()
|
||||
if len(h.gotRPC) >= lenRPCStats {
|
||||
h.mu.Unlock()
|
||||
break
|
||||
}
|
||||
h.mu.Unlock()
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
}
|
||||
|
||||
for {
|
||||
h.mu.Lock()
|
||||
if _, ok := h.gotConn[len(h.gotConn)-1].s.(*stats.ConnEnd); ok {
|
||||
h.mu.Unlock()
|
||||
break
|
||||
}
|
||||
h.mu.Unlock()
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
}
|
||||
|
||||
expect := &expectedData{
|
||||
serverAddr: te.srvAddr,
|
||||
compression: tc.compress,
|
||||
requests: reqs,
|
||||
responses: resps,
|
||||
failfast: cc.failfast,
|
||||
err: err,
|
||||
}
|
||||
if !cc.streaming {
|
||||
expect.method = "/grpc.testing.TestService/UnaryCall"
|
||||
} else {
|
||||
expect.method = "/grpc.testing.TestService/FullDuplexCall"
|
||||
}
|
||||
|
||||
checkConnStats(t, h.gotConn)
|
||||
checkClientStats(t, h.gotRPC, expect, checkFuncs)
|
||||
}
|
||||
|
||||
func TestClientStatsUnaryRPC(t *testing.T) {
|
||||
testClientStats(t, &testConfig{compress: ""}, &rpcConfig{success: true, failfast: false}, map[int]*checkFuncWithCount{
|
||||
begin: {checkBegin, 1},
|
||||
outHeader: {checkOutHeader, 1},
|
||||
outPayload: {checkOutPayload, 1},
|
||||
inHeader: {checkInHeader, 1},
|
||||
inPayload: {checkInPayload, 1},
|
||||
inTrailer: {checkInTrailer, 1},
|
||||
end: {checkEnd, 1},
|
||||
})
|
||||
}
|
||||
|
||||
func TestClientStatsUnaryRPCError(t *testing.T) {
|
||||
testClientStats(t, &testConfig{compress: ""}, &rpcConfig{success: false, failfast: false}, map[int]*checkFuncWithCount{
|
||||
begin: {checkBegin, 1},
|
||||
outHeader: {checkOutHeader, 1},
|
||||
outPayload: {checkOutPayload, 1},
|
||||
inHeader: {checkInHeader, 1},
|
||||
inTrailer: {checkInTrailer, 1},
|
||||
end: {checkEnd, 1},
|
||||
})
|
||||
}
|
||||
|
||||
func TestClientStatsStreamingRPC(t *testing.T) {
|
||||
count := 5
|
||||
testClientStats(t, &testConfig{compress: "gzip"}, &rpcConfig{count: count, success: true, failfast: false, streaming: true}, map[int]*checkFuncWithCount{
|
||||
begin: {checkBegin, 1},
|
||||
outHeader: {checkOutHeader, 1},
|
||||
outPayload: {checkOutPayload, count},
|
||||
inHeader: {checkInHeader, 1},
|
||||
inPayload: {checkInPayload, count},
|
||||
inTrailer: {checkInTrailer, 1},
|
||||
end: {checkEnd, 1},
|
||||
})
|
||||
}
|
||||
|
||||
func TestClientStatsStreamingRPCError(t *testing.T) {
|
||||
count := 5
|
||||
testClientStats(t, &testConfig{compress: "gzip"}, &rpcConfig{count: count, success: false, failfast: false, streaming: true}, map[int]*checkFuncWithCount{
|
||||
begin: {checkBegin, 1},
|
||||
outHeader: {checkOutHeader, 1},
|
||||
outPayload: {checkOutPayload, 1},
|
||||
inHeader: {checkInHeader, 1},
|
||||
inTrailer: {checkInTrailer, 1},
|
||||
end: {checkEnd, 1},
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user