You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
terraform/internal/rpcapi/grpc_testing.go

74 lines
2.2 KiB

// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: BUSL-1.1
package rpcapi
import (
"context"
"net"
"testing"
"go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc"
"google.golang.org/grpc"
"google.golang.org/grpc/test/bufconn"
"google.golang.org/protobuf/proto"
"google.golang.org/protobuf/types/known/anypb"
)
// grpcClientForTesting creates an in-memory-only gRPC server, offers the
// caller a chance to register services with it, and then returns a
// client connected to that fake server, with which the caller can construct
// service-specific client objects.
//
// When finished with the returned client, call the close callback given as
// the second return value or else you will leak some goroutines handling the
// server end of this fake connection.
func grpcClientForTesting(ctx context.Context, t *testing.T, registerServices func(srv *grpc.Server)) (conn grpc.ClientConnInterface, close func()) {
fakeListener := bufconn.Listen(1024 /* buffer size */)
srv := grpc.NewServer(
grpc.UnaryInterceptor(otelgrpc.UnaryServerInterceptor()),
grpc.StreamInterceptor(otelgrpc.StreamServerInterceptor()),
)
// Caller gets an opportunity to register specific services before
// we actually start "serving".
registerServices(srv)
go func() {
if err := srv.Serve(fakeListener); err != nil {
// We can't actually return an error here, but this should
// not arise with our fake listener anyway so we'll just panic.
panic(err)
}
}()
fakeDialer := func(ctx context.Context, fakeAddr string) (net.Conn, error) {
return fakeListener.DialContext(ctx)
}
realConn, err := grpc.DialContext(
ctx, "testfake",
grpc.WithContextDialer(fakeDialer),
grpc.WithInsecure(),
grpc.WithUnaryInterceptor(otelgrpc.UnaryClientInterceptor()),
grpc.WithStreamInterceptor(otelgrpc.StreamClientInterceptor()),
)
if err != nil {
t.Fatalf("failed to connect to the fake server: %s", err)
}
return realConn, func() {
realConn.Close()
srv.Stop()
fakeListener.Close()
}
}
func mustMarshalAnyPb(msg proto.Message) *anypb.Any {
var ret anypb.Any
err := anypb.MarshalFrom(&ret, msg, proto.MarshalOptions{})
if err != nil {
panic(err)
}
return &ret
}