func getCredentialOpts(opts []option.ClientOption) []option.ClientOption { if ts := config.TokenSource; ts != nil { opts = append(opts, option.WithTokenSource(ts)) } if tlsCreds := config.TLSCreds; tlsCreds != nil { opts = append(opts, option.WithGRPCDialOption(grpc.WithTransportCredentials(tlsCreds))) } return opts }
func TestMain(m *testing.M) { flag.Parse() // needed for testing.Short() ctx := context.Background() testProjectID = testutil.ProjID() if testProjectID == "" || testing.Short() { integrationTest = false if testProjectID != "" { log.Print("Integration tests skipped in short mode (using fake instead)") } testProjectID = "PROJECT_ID" addr, err := ltesting.NewServer() if err != nil { log.Fatalf("creating fake server: %v", err) } newClient = func(ctx context.Context, projectID string) *Client { conn, err := grpc.Dial(addr, grpc.WithInsecure(), grpc.WithBlock()) if err != nil { log.Fatalf("dialing %q: %v", addr, err) } c, err := NewClient(ctx, projectID, option.WithGRPCConn(conn)) if err != nil { log.Fatalf("creating client for fake at %q: %v", addr, err) } return c } } else { integrationTest = true ts := testutil.TokenSource(ctx, logging.AdminScope) if ts == nil { log.Fatal("The project key must be set. See CONTRIBUTING.md for details") } log.Printf("running integration tests with project %s", testProjectID) newClient = func(ctx context.Context, projectID string) *Client { c, err := NewClient(ctx, projectID, option.WithTokenSource(ts), option.WithGRPCDialOption(grpc.WithBlock())) if err != nil { log.Fatalf("creating prod client: %v", err) } return c } } client = newClient(ctx, testProjectID) initMetrics(ctx) cleanup := initSinks(ctx) exit := m.Run() cleanup() client.Close() os.Exit(exit) }
// Check that user optioned grpc.WithDialer option overrides the App Engine hook. func TestGRPCHook(t *testing.T) { ctx, cancel := context.WithTimeout(context.Background(), 10*time.Millisecond) expected := false appengineDialerHook = (func(ctx context.Context) grpc.DialOption { return grpc.WithDialer(func(addr string, timeout time.Duration) (net.Conn, error) { t.Error("did not expect a call to notExpected dialer, got one") cancel() return nil, errors.New("not expected") }) }) defer func() { appengineDialerHook = nil }() expectedDialer := grpc.WithDialer(func(addr string, timeout time.Duration) (net.Conn, error) { expected = true cancel() return nil, errors.New("expected") }) conn, err := DialGRPC(ctx, option.WithTokenSource(oauth2.StaticTokenSource(nil)), // No creds. option.WithGRPCDialOption(expectedDialer), option.WithEndpoint("example.google.com:443")) if err != nil { t.Errorf("DialGRPC: error %v, want nil", err) } // gRPC doesn't connect before the first call. grpc.Invoke(ctx, "foo", nil, nil, conn) conn.Close() if !expected { t.Error("expected a call to expected dialer, didn't get one") } }
// WithGRPCDialOption returns a ClientOption that appends a new grpc.DialOption // to an underlying gRPC dial. It does not work with WithBaseGRPC. func WithGRPCDialOption(o grpc.DialOption) ClientOption { return wrapOpt{option.WithGRPCDialOption(o)} }
span.Finish(WithResponse(resp)) } else { span.Finish() } } } // EnableGRPCTracingDialOption enables tracing of requests that are sent over a // gRPC connection. // The functionality in gRPC that this relies on is currently experimental. var EnableGRPCTracingDialOption grpc.DialOption = grpc.WithUnaryInterceptor(grpc.UnaryClientInterceptor(grpcUnaryInterceptor)) // EnableGRPCTracing enables tracing of requests for clients that use gRPC // connections. // The functionality in gRPC that this relies on is currently experimental. var EnableGRPCTracing option.ClientOption = option.WithGRPCDialOption(EnableGRPCTracingDialOption) func grpcUnaryInterceptor(ctx context.Context, method string, req, reply interface{}, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error { // TODO: also intercept streams. span := FromContext(ctx).NewChild(method) err := invoker(ctx, method, req, reply, cc, opts...) if err != nil { // TODO: standardize gRPC label names? span.SetLabel("error", err.Error()) } span.Finish() return err } // nextSpanID returns a new span ID. It will never return zero. func nextSpanID() uint64 {