Documentation ¶
Index ¶
- Constants
- Variables
- func CallOn[T any](v T, f func(v T)) T
- func CheckNumGoroutines(t TB, start int, increase bool, wait time.Duration)
- func CleanupCheckNumGoroutines(t TB, start int, increase bool, wait time.Duration)
- func Closers(closers ...io.Closer) io.Closer
- func DumpGoroutineStacktrace() string
- func TestConn[T1 TG, T2 interface{ ... }, ...](t T2, test func(t T1, mp T3), closeConns bool, init func(t T1) T3)
- func WaitNumGoroutines(wait time.Duration, fn func(n int) bool) (n int)
- type ClientConnCloser
- type ClientConnFactory
- type Closer
- type DepthLimiter
- type GRPCServer
- type GoroutineChecker
- type Hook
- type ListenerDialer
- type PipeClient
- type PipeClientOption
- type T
- type TB
- type TG
- type TestingT
- type Unwrapper
Examples ¶
Constants ¶
const (
// DefaultBufconnSize is an arbitrary default.
DefaultBufconnSize = 1024 * 1024
)
Variables ¶
var ( ClientConnFactories = map[string]ClientConnFactory{ `bufconn`: BufconnClientConnFactory, `grpchan`: GrpchanClientConnFactory, `netpipe`: NetpipeClientConnFactory, } )
Functions ¶
func CheckNumGoroutines ¶
func Closers ¶
Closers combines a set of closers, always calling them in order, and using the last as the result.
Note this is a copy of stream.Closers.
func DumpGoroutineStacktrace ¶
func DumpGoroutineStacktrace() string
func TestConn ¶
func TestConn[ T1 TG, T2 interface { TG Run(name string, f func(t T1)) bool }, T3 ~func() (c1, c2 net.Conn, stop func(), err error)]( t T2, test func(t T1, mp T3), closeConns bool, init func(t T1) T3, )
TestConn runs (an implementation of) nettest.TestConn multiple times, testing different permutations of conn order (swapping the roles of c1 and c2), and if closeConns is true, also the order of close (better at catching close-related deadlocks). If closeConns is false, then the caller must close the two conns as part of the stop closure. Any stop closure will be run before any auto-generated (closeConns) stop.
If the nested t, provided by t.Run, is *testing.T, then the number of goroutines will be validated, to test for leaks. Other types (presumably testutil.T or equivalent) should be capable of implementing the same functionality via wrappers / other custom behavior.
Types ¶
type ClientConnCloser ¶
type ClientConnCloser interface { grpc.ClientConnInterface io.Closer }
func BufconnClientConnFactory ¶
func BufconnClientConnFactory(fn func(h GRPCServer)) ClientConnCloser
func GrpchanClientConnFactory ¶
func GrpchanClientConnFactory(fn func(h GRPCServer)) ClientConnCloser
func NetpipeClientConnFactory ¶
func NetpipeClientConnFactory(fn func(h GRPCServer)) ClientConnCloser
type ClientConnFactory ¶
type ClientConnFactory func(fn func(h GRPCServer)) ClientConnCloser
type Closer ¶
type Closer func() error
Closer implements io.Closer, also supporting wrapping to be idempotent/cached, via the Once method.
Note this is a copy of stream.Closer.
func (Closer) Comparable ¶
Comparable wraps the receiver so that it is comparable.
type DepthLimiter ¶
type DepthLimiter = testing.DepthLimiter
type GRPCServer ¶
type GRPCServer = reflection.GRPCServer
type GoroutineChecker ¶
func (GoroutineChecker) Unwrap ¶
func (x GoroutineChecker) Unwrap() T
type ListenerDialer ¶
type PipeClient ¶
type PipeClient struct { *grpc.ClientConn Listener ListenerDialer Server *grpc.Server // contains filtered or unexported fields }
func NewBufconnClient ¶
func NewBufconnClient(size int, init func(lis *bufconn.Listener, srv *grpc.Server), options ...PipeClientOption) *PipeClient
NewBufconnClient initialises a new gRPC client for testing, using google.golang.org/grpc/test/bufconn. Size will default to DefaultBufconnSize if <= 0. The init func will be called prior to serving on the listener, which does not need to be implemented by the caller.
Example ¶
defer CheckNumGoroutines(nil, runtime.NumGoroutine(), false, 0) ctx, cancel := context.WithTimeout(context.Background(), time.Second*10) defer cancel() conn := NewBufconnClient(0, func(lis *bufconn.Listener, srv *grpc.Server) { if lis == nil || srv == nil { panic(`unexpected args`) } reflection.Register(srv) }) defer conn.Close() stream, err := refl.NewServerReflectionClient(conn).ServerReflectionInfo(ctx) if err != nil { panic(err) } //lint:ignore SA1019 v1 isnt completely released yet if err := stream.Send(&refl.ServerReflectionRequest{MessageRequest: &refl.ServerReflectionRequest_ListServices{}}); err != nil { panic(err) } if msg, err := stream.Recv(); err != nil { panic(err) } else { //lint:ignore SA1019 v1 isnt completely released yet services := make([]string, 0, len(msg.GetListServicesResponse().GetService())) //lint:ignore SA1019 v1 isnt completely released yet for _, v := range msg.GetListServicesResponse().GetService() { //lint:ignore SA1019 v1 isnt completely released yet services = append(services, v.GetName()) } fmt.Printf("there are %d available services: %q\n", len(services), services) } if err := conn.Close(); err != nil { panic(err) }
Output: there are 2 available services: ["grpc.reflection.v1.ServerReflection" "grpc.reflection.v1alpha.ServerReflection"]
func NewNetpipeClient ¶
func NewNetpipeClient(factory func() (c1, c2 net.Conn), init func(lis *pipelistener.PipeListener, srv *grpc.Server), options ...PipeClientOption) *PipeClient
func NewPipeClient ¶
func NewPipeClient(factory pipelistener.PipeFactory, init func(lis *pipelistener.PipeListener, srv *grpc.Server), options ...PipeClientOption) *PipeClient
NewPipeClient initialises a new gRPC client for testing, using a net.Pipe style implementation. Size will default to DefaultBufconnSize if <= 0. The init func will be called prior to serving on the listener, which does not need to be implemented by the caller.
func (*PipeClient) Close ¶
func (x *PipeClient) Close() error
type PipeClientOption ¶
type PipeClientOption func(c *pipeClientConfig)
func WithDialOptions ¶
func WithDialOptions(options ...grpc.DialOption) PipeClientOption
func WithServerOptions ¶
func WithServerOptions(options ...grpc.ServerOption) PipeClientOption