core: Inline AbstractManagedChannelImplBuilder
diff --git a/core/src/main/java/io/grpc/internal/AbstractManagedChannelImplBuilder.java b/core/src/main/java/io/grpc/internal/AbstractManagedChannelImplBuilder.java
deleted file mode 100644
index aac6c25..0000000
--- a/core/src/main/java/io/grpc/internal/AbstractManagedChannelImplBuilder.java
+++ /dev/null
@@ -1,670 +0,0 @@
-/*
- * Copyright 2014 The gRPC Authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package io.grpc.internal;
-
-import static com.google.common.base.Preconditions.checkArgument;
-
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Preconditions;
-import com.google.common.util.concurrent.MoreExecutors;
-import io.grpc.Attributes;
-import io.grpc.BinaryLog;
-import io.grpc.ClientInterceptor;
-import io.grpc.CompressorRegistry;
-import io.grpc.DecompressorRegistry;
-import io.grpc.EquivalentAddressGroup;
-import io.grpc.InternalChannelz;
-import io.grpc.ManagedChannel;
-import io.grpc.ManagedChannelBuilder;
-import io.grpc.NameResolver;
-import io.grpc.NameResolverRegistry;
-import io.grpc.ProxyDetector;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.net.SocketAddress;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.Executor;
-import java.util.concurrent.TimeUnit;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-import javax.annotation.Nullable;
-
-/**
- * Abstract base class for channel builders.
- *
- * @param <T> The concrete type of this builder.
- */
-public abstract class AbstractManagedChannelImplBuilder
- <T extends AbstractManagedChannelImplBuilder<T>> extends ManagedChannelBuilder<T> {
- private static final String DIRECT_ADDRESS_SCHEME = "directaddress";
-
- private static final Logger log =
- Logger.getLogger(AbstractManagedChannelImplBuilder.class.getName());
-
- public static ManagedChannelBuilder<?> forAddress(String name, int port) {
- throw new UnsupportedOperationException("Subclass failed to hide static factory");
- }
-
- public static ManagedChannelBuilder<?> forTarget(String target) {
- throw new UnsupportedOperationException("Subclass failed to hide static factory");
- }
-
- /**
- * An idle timeout larger than this would disable idle mode.
- */
- @VisibleForTesting
- static final long IDLE_MODE_MAX_TIMEOUT_DAYS = 30;
-
- /**
- * The default idle timeout.
- */
- @VisibleForTesting
- static final long IDLE_MODE_DEFAULT_TIMEOUT_MILLIS = TimeUnit.MINUTES.toMillis(30);
-
- /**
- * An idle timeout smaller than this would be capped to it.
- */
- static final long IDLE_MODE_MIN_TIMEOUT_MILLIS = TimeUnit.SECONDS.toMillis(1);
-
- private static final ObjectPool<? extends Executor> DEFAULT_EXECUTOR_POOL =
- SharedResourcePool.forResource(GrpcUtil.SHARED_CHANNEL_EXECUTOR);
-
- private static final DecompressorRegistry DEFAULT_DECOMPRESSOR_REGISTRY =
- DecompressorRegistry.getDefaultInstance();
-
- private static final CompressorRegistry DEFAULT_COMPRESSOR_REGISTRY =
- CompressorRegistry.getDefaultInstance();
-
- private static final long DEFAULT_RETRY_BUFFER_SIZE_IN_BYTES = 1L << 24; // 16M
- private static final long DEFAULT_PER_RPC_BUFFER_LIMIT_IN_BYTES = 1L << 20; // 1M
-
- ObjectPool<? extends Executor> executorPool = DEFAULT_EXECUTOR_POOL;
-
- ObjectPool<? extends Executor> offloadExecutorPool = DEFAULT_EXECUTOR_POOL;
-
- private final List<ClientInterceptor> interceptors = new ArrayList<>();
- final NameResolverRegistry nameResolverRegistry = NameResolverRegistry.getDefaultRegistry();
-
- // Access via getter, which may perform authority override as needed
- private NameResolver.Factory nameResolverFactory = nameResolverRegistry.asFactory();
-
- final String target;
-
- @Nullable
- private final SocketAddress directServerAddress;
-
- @Nullable
- String userAgent;
-
- @VisibleForTesting
- @Nullable
- String authorityOverride;
-
- String defaultLbPolicy = GrpcUtil.DEFAULT_LB_POLICY;
-
- boolean fullStreamDecompression;
-
- DecompressorRegistry decompressorRegistry = DEFAULT_DECOMPRESSOR_REGISTRY;
-
- CompressorRegistry compressorRegistry = DEFAULT_COMPRESSOR_REGISTRY;
-
- long idleTimeoutMillis = IDLE_MODE_DEFAULT_TIMEOUT_MILLIS;
-
- int maxRetryAttempts = 5;
- int maxHedgedAttempts = 5;
- long retryBufferSize = DEFAULT_RETRY_BUFFER_SIZE_IN_BYTES;
- long perRpcBufferLimit = DEFAULT_PER_RPC_BUFFER_LIMIT_IN_BYTES;
- boolean retryEnabled = false; // TODO(zdapeng): default to true
- // Temporarily disable retry when stats or tracing is enabled to avoid breakage, until we know
- // what should be the desired behavior for retry + stats/tracing.
- // TODO(zdapeng): delete me
- boolean temporarilyDisableRetry;
-
- InternalChannelz channelz = InternalChannelz.instance();
- int maxTraceEvents;
-
- @Nullable
- Map<String, ?> defaultServiceConfig;
- boolean lookUpServiceConfig = true;
-
- protected TransportTracer.Factory transportTracerFactory = TransportTracer.getDefaultFactory();
-
- private int maxInboundMessageSize = GrpcUtil.DEFAULT_MAX_MESSAGE_SIZE;
-
- @Nullable
- BinaryLog binlog;
-
- @Nullable
- ProxyDetector proxyDetector;
-
- /**
- * Sets the maximum message size allowed for a single gRPC frame. If an inbound messages
- * larger than this limit is received it will not be processed and the RPC will fail with
- * RESOURCE_EXHAUSTED.
- */
- // Can be overridden by subclasses.
- @Override
- public T maxInboundMessageSize(int max) {
- checkArgument(max >= 0, "negative max");
- maxInboundMessageSize = max;
- return thisT();
- }
-
- protected final int maxInboundMessageSize() {
- return maxInboundMessageSize;
- }
-
- private boolean statsEnabled = true;
- private boolean recordStartedRpcs = true;
- private boolean recordFinishedRpcs = true;
- private boolean recordRealTimeMetrics = false;
- private boolean tracingEnabled = true;
-
- protected AbstractManagedChannelImplBuilder(String target) {
- this.target = Preconditions.checkNotNull(target, "target");
- this.directServerAddress = null;
- }
-
- /**
- * Returns a target string for the SocketAddress. It is only used as a placeholder, because
- * DirectAddressNameResolverFactory will not actually try to use it. However, it must be a valid
- * URI.
- */
- @VisibleForTesting
- static String makeTargetStringForDirectAddress(SocketAddress address) {
- try {
- return new URI(DIRECT_ADDRESS_SCHEME, "", "/" + address, null).toString();
- } catch (URISyntaxException e) {
- // It should not happen.
- throw new RuntimeException(e);
- }
- }
-
- protected AbstractManagedChannelImplBuilder(SocketAddress directServerAddress, String authority) {
- this.target = makeTargetStringForDirectAddress(directServerAddress);
- this.directServerAddress = directServerAddress;
- this.nameResolverFactory = new DirectAddressNameResolverFactory(directServerAddress, authority);
- }
-
- @Override
- public final T directExecutor() {
- return executor(MoreExecutors.directExecutor());
- }
-
- @Override
- public final T executor(Executor executor) {
- if (executor != null) {
- this.executorPool = new FixedObjectPool<>(executor);
- } else {
- this.executorPool = DEFAULT_EXECUTOR_POOL;
- }
- return thisT();
- }
-
- @Override
- public final T offloadExecutor(Executor executor) {
- if (executor != null) {
- this.offloadExecutorPool = new FixedObjectPool<>(executor);
- } else {
- this.offloadExecutorPool = DEFAULT_EXECUTOR_POOL;
- }
- return thisT();
- }
-
- @Override
- public final T intercept(List<ClientInterceptor> interceptors) {
- this.interceptors.addAll(interceptors);
- return thisT();
- }
-
- @Override
- public final T intercept(ClientInterceptor... interceptors) {
- return intercept(Arrays.asList(interceptors));
- }
-
- @Deprecated
- @Override
- public final T nameResolverFactory(NameResolver.Factory resolverFactory) {
- Preconditions.checkState(directServerAddress == null,
- "directServerAddress is set (%s), which forbids the use of NameResolverFactory",
- directServerAddress);
- if (resolverFactory != null) {
- this.nameResolverFactory = resolverFactory;
- } else {
- this.nameResolverFactory = nameResolverRegistry.asFactory();
- }
- return thisT();
- }
-
- @Override
- public final T defaultLoadBalancingPolicy(String policy) {
- Preconditions.checkState(directServerAddress == null,
- "directServerAddress is set (%s), which forbids the use of load-balancing policy",
- directServerAddress);
- Preconditions.checkArgument(policy != null, "policy cannot be null");
- this.defaultLbPolicy = policy;
- return thisT();
- }
-
- @Override
- public final T enableFullStreamDecompression() {
- this.fullStreamDecompression = true;
- return thisT();
- }
-
- @Override
- public final T decompressorRegistry(DecompressorRegistry registry) {
- if (registry != null) {
- this.decompressorRegistry = registry;
- } else {
- this.decompressorRegistry = DEFAULT_DECOMPRESSOR_REGISTRY;
- }
- return thisT();
- }
-
- @Override
- public final T compressorRegistry(CompressorRegistry registry) {
- if (registry != null) {
- this.compressorRegistry = registry;
- } else {
- this.compressorRegistry = DEFAULT_COMPRESSOR_REGISTRY;
- }
- return thisT();
- }
-
- @Override
- public final T userAgent(@Nullable String userAgent) {
- this.userAgent = userAgent;
- return thisT();
- }
-
- @Override
- public final T overrideAuthority(String authority) {
- this.authorityOverride = checkAuthority(authority);
- return thisT();
- }
-
- @Override
- public final T idleTimeout(long value, TimeUnit unit) {
- checkArgument(value > 0, "idle timeout is %s, but must be positive", value);
- // We convert to the largest unit to avoid overflow
- if (unit.toDays(value) >= IDLE_MODE_MAX_TIMEOUT_DAYS) {
- // This disables idle mode
- this.idleTimeoutMillis = ManagedChannelImpl.IDLE_TIMEOUT_MILLIS_DISABLE;
- } else {
- this.idleTimeoutMillis = Math.max(unit.toMillis(value), IDLE_MODE_MIN_TIMEOUT_MILLIS);
- }
- return thisT();
- }
-
- @Override
- public final T maxRetryAttempts(int maxRetryAttempts) {
- this.maxRetryAttempts = maxRetryAttempts;
- return thisT();
- }
-
- @Override
- public final T maxHedgedAttempts(int maxHedgedAttempts) {
- this.maxHedgedAttempts = maxHedgedAttempts;
- return thisT();
- }
-
- @Override
- public final T retryBufferSize(long bytes) {
- checkArgument(bytes > 0L, "retry buffer size must be positive");
- retryBufferSize = bytes;
- return thisT();
- }
-
- @Override
- public final T perRpcBufferLimit(long bytes) {
- checkArgument(bytes > 0L, "per RPC buffer limit must be positive");
- perRpcBufferLimit = bytes;
- return thisT();
- }
-
- @Override
- public final T disableRetry() {
- retryEnabled = false;
- return thisT();
- }
-
- @Override
- public final T enableRetry() {
- retryEnabled = true;
- statsEnabled = false;
- tracingEnabled = false;
- return thisT();
- }
-
- @Override
- public final T setBinaryLog(BinaryLog binlog) {
- this.binlog = binlog;
- return thisT();
- }
-
- @Override
- public T maxTraceEvents(int maxTraceEvents) {
- checkArgument(maxTraceEvents >= 0, "maxTraceEvents must be non-negative");
- this.maxTraceEvents = maxTraceEvents;
- return thisT();
- }
-
- @Override
- public T proxyDetector(@Nullable ProxyDetector proxyDetector) {
- this.proxyDetector = proxyDetector;
- return thisT();
- }
-
- @Override
- public T defaultServiceConfig(@Nullable Map<String, ?> serviceConfig) {
- // TODO(notcarl): use real parsing
- defaultServiceConfig = checkMapEntryTypes(serviceConfig);
- return thisT();
- }
-
- @Nullable
- private static Map<String, ?> checkMapEntryTypes(@Nullable Map<?, ?> map) {
- if (map == null) {
- return null;
- }
- // Not using ImmutableMap.Builder because of extra guava dependency for Android.
- Map<String, Object> parsedMap = new LinkedHashMap<>();
- for (Map.Entry<?, ?> entry : map.entrySet()) {
- checkArgument(
- entry.getKey() instanceof String,
- "The key of the entry '%s' is not of String type", entry);
-
- String key = (String) entry.getKey();
- Object value = entry.getValue();
- if (value == null) {
- parsedMap.put(key, null);
- } else if (value instanceof Map) {
- parsedMap.put(key, checkMapEntryTypes((Map<?, ?>) value));
- } else if (value instanceof List) {
- parsedMap.put(key, checkListEntryTypes((List<?>) value));
- } else if (value instanceof String) {
- parsedMap.put(key, value);
- } else if (value instanceof Double) {
- parsedMap.put(key, value);
- } else if (value instanceof Boolean) {
- parsedMap.put(key, value);
- } else {
- throw new IllegalArgumentException(
- "The value of the map entry '" + entry + "' is of type '" + value.getClass()
- + "', which is not supported");
- }
- }
- return Collections.unmodifiableMap(parsedMap);
- }
-
- private static List<?> checkListEntryTypes(List<?> list) {
- List<Object> parsedList = new ArrayList<>(list.size());
- for (Object value : list) {
- if (value == null) {
- parsedList.add(null);
- } else if (value instanceof Map) {
- parsedList.add(checkMapEntryTypes((Map<?, ?>) value));
- } else if (value instanceof List) {
- parsedList.add(checkListEntryTypes((List<?>) value));
- } else if (value instanceof String) {
- parsedList.add(value);
- } else if (value instanceof Double) {
- parsedList.add(value);
- } else if (value instanceof Boolean) {
- parsedList.add(value);
- } else {
- throw new IllegalArgumentException(
- "The entry '" + value + "' is of type '" + value.getClass()
- + "', which is not supported");
- }
- }
- return Collections.unmodifiableList(parsedList);
- }
-
- @Override
- public T disableServiceConfigLookUp() {
- this.lookUpServiceConfig = false;
- return thisT();
- }
-
- /**
- * Disable or enable stats features. Enabled by default.
- *
- * <p>For the current release, calling {@code setStatsEnabled(true)} may have a side effect that
- * disables retry.
- */
- protected void setStatsEnabled(boolean value) {
- statsEnabled = value;
- }
-
- /**
- * Disable or enable stats recording for RPC upstarts. Effective only if {@link
- * #setStatsEnabled} is set to true. Enabled by default.
- */
- protected void setStatsRecordStartedRpcs(boolean value) {
- recordStartedRpcs = value;
- }
-
- /**
- * Disable or enable stats recording for RPC completions. Effective only if {@link
- * #setStatsEnabled} is set to true. Enabled by default.
- */
- protected void setStatsRecordFinishedRpcs(boolean value) {
- recordFinishedRpcs = value;
- }
-
- /**
- * Disable or enable real-time metrics recording. Effective only if {@link #setStatsEnabled} is
- * set to true. Disabled by default.
- */
- protected void setStatsRecordRealTimeMetrics(boolean value) {
- recordRealTimeMetrics = value;
- }
-
- /**
- * Disable or enable tracing features. Enabled by default.
- *
- * <p>For the current release, calling {@code setTracingEnabled(true)} may have a side effect that
- * disables retry.
- */
- protected void setTracingEnabled(boolean value) {
- tracingEnabled = value;
- }
-
- @VisibleForTesting
- final long getIdleTimeoutMillis() {
- return idleTimeoutMillis;
- }
-
- /**
- * Verifies the authority is valid. This method exists as an escape hatch for putting in an
- * authority that is valid, but would fail the default validation provided by this
- * implementation.
- */
- protected String checkAuthority(String authority) {
- return GrpcUtil.checkAuthority(authority);
- }
-
- @Override
- public ManagedChannel build() {
- return new ManagedChannelOrphanWrapper(new ManagedChannelImpl(
- this,
- buildTransportFactory(),
- new ExponentialBackoffPolicy.Provider(),
- SharedResourcePool.forResource(GrpcUtil.SHARED_CHANNEL_EXECUTOR),
- GrpcUtil.STOPWATCH_SUPPLIER,
- getEffectiveInterceptors(),
- TimeProvider.SYSTEM_TIME_PROVIDER));
- }
-
- // Temporarily disable retry when stats or tracing is enabled to avoid breakage, until we know
- // what should be the desired behavior for retry + stats/tracing.
- // TODO(zdapeng): FIX IT
- @VisibleForTesting
- final List<ClientInterceptor> getEffectiveInterceptors() {
- List<ClientInterceptor> effectiveInterceptors =
- new ArrayList<>(this.interceptors);
- temporarilyDisableRetry = false;
- if (statsEnabled) {
- temporarilyDisableRetry = true;
- ClientInterceptor statsInterceptor = null;
- try {
- Class<?> censusStatsAccessor =
- Class.forName("io.grpc.census.InternalCensusStatsAccessor");
- Method getClientInterceptorMethod =
- censusStatsAccessor.getDeclaredMethod(
- "getClientInterceptor",
- boolean.class,
- boolean.class,
- boolean.class);
- statsInterceptor =
- (ClientInterceptor) getClientInterceptorMethod
- .invoke(
- null,
- recordStartedRpcs,
- recordFinishedRpcs,
- recordRealTimeMetrics);
- } catch (ClassNotFoundException e) {
- // Replace these separate catch statements with multicatch when Android min-API >= 19
- log.log(Level.FINE, "Unable to apply census stats", e);
- } catch (NoSuchMethodException e) {
- log.log(Level.FINE, "Unable to apply census stats", e);
- } catch (IllegalAccessException e) {
- log.log(Level.FINE, "Unable to apply census stats", e);
- } catch (InvocationTargetException e) {
- log.log(Level.FINE, "Unable to apply census stats", e);
- }
- if (statsInterceptor != null) {
- // First interceptor runs last (see ClientInterceptors.intercept()), so that no
- // other interceptor can override the tracer factory we set in CallOptions.
- effectiveInterceptors.add(0, statsInterceptor);
- }
- }
- if (tracingEnabled) {
- temporarilyDisableRetry = true;
- ClientInterceptor tracingInterceptor = null;
- try {
- Class<?> censusTracingAccessor =
- Class.forName("io.grpc.census.InternalCensusTracingAccessor");
- Method getClientInterceptroMethod =
- censusTracingAccessor.getDeclaredMethod("getClientInterceptor");
- tracingInterceptor = (ClientInterceptor) getClientInterceptroMethod.invoke(null);
- } catch (ClassNotFoundException e) {
- // Replace these separate catch statements with multicatch when Android min-API >= 19
- log.log(Level.FINE, "Unable to apply census stats", e);
- } catch (NoSuchMethodException e) {
- log.log(Level.FINE, "Unable to apply census stats", e);
- } catch (IllegalAccessException e) {
- log.log(Level.FINE, "Unable to apply census stats", e);
- } catch (InvocationTargetException e) {
- log.log(Level.FINE, "Unable to apply census stats", e);
- }
- if (tracingInterceptor != null) {
- effectiveInterceptors.add(0, tracingInterceptor);
- }
- }
- return effectiveInterceptors;
- }
-
- /**
- * Subclasses should override this method to provide the {@link ClientTransportFactory}
- * appropriate for this channel. This method is meant for Transport implementors and should not
- * be used by normal users.
- */
- protected abstract ClientTransportFactory buildTransportFactory();
-
- /**
- * Subclasses can override this method to provide a default port to {@link NameResolver} for use
- * in cases where the target string doesn't include a port. The default implementation returns
- * {@link GrpcUtil#DEFAULT_PORT_SSL}.
- */
- protected int getDefaultPort() {
- return GrpcUtil.DEFAULT_PORT_SSL;
- }
-
- /**
- * Returns a {@link NameResolver.Factory} for the channel.
- */
- NameResolver.Factory getNameResolverFactory() {
- if (authorityOverride == null) {
- return nameResolverFactory;
- } else {
- return new OverrideAuthorityNameResolverFactory(nameResolverFactory, authorityOverride);
- }
- }
-
- private static class DirectAddressNameResolverFactory extends NameResolver.Factory {
- final SocketAddress address;
- final String authority;
-
- DirectAddressNameResolverFactory(SocketAddress address, String authority) {
- this.address = address;
- this.authority = authority;
- }
-
- @Override
- public NameResolver newNameResolver(URI notUsedUri, NameResolver.Args args) {
- return new NameResolver() {
- @Override
- public String getServiceAuthority() {
- return authority;
- }
-
- @Override
- public void start(Listener2 listener) {
- listener.onResult(
- ResolutionResult.newBuilder()
- .setAddresses(Collections.singletonList(new EquivalentAddressGroup(address)))
- .setAttributes(Attributes.EMPTY)
- .build());
- }
-
- @Override
- public void shutdown() {}
- };
- }
-
- @Override
- public String getDefaultScheme() {
- return DIRECT_ADDRESS_SCHEME;
- }
- }
-
- /**
- * Returns the correctly typed version of the builder.
- */
- private T thisT() {
- @SuppressWarnings("unchecked")
- T thisT = (T) this;
- return thisT;
- }
-
- /**
- * Returns the internal offload executor pool for offloading tasks.
- */
- protected ObjectPool<? extends Executor> getOffloadExecutorPool() {
- return this.offloadExecutorPool;
- }
-}
diff --git a/core/src/main/java/io/grpc/internal/ManagedChannelImpl.java b/core/src/main/java/io/grpc/internal/ManagedChannelImpl.java
index 1bd42c0..d2bc87c 100644
--- a/core/src/main/java/io/grpc/internal/ManagedChannelImpl.java
+++ b/core/src/main/java/io/grpc/internal/ManagedChannelImpl.java
@@ -44,6 +44,7 @@
import io.grpc.Context;
import io.grpc.DecompressorRegistry;
import io.grpc.EquivalentAddressGroup;
+import io.grpc.ForwardingChannelBuilder;
import io.grpc.InternalChannelz;
import io.grpc.InternalChannelz.ChannelStats;
import io.grpc.InternalChannelz.ChannelTrace;
@@ -72,6 +73,8 @@
import io.grpc.SynchronizationContext.ScheduledHandle;
import io.grpc.internal.AutoConfiguredLoadBalancerFactory.AutoConfiguredLoadBalancer;
import io.grpc.internal.ClientCallImpl.ClientStreamProvider;
+import io.grpc.internal.ManagedChannelImplBuilder.FixedPortProvider;
+import io.grpc.internal.ManagedChannelImplBuilder.UnsupportedClientTransportFactoryBuilder;
import io.grpc.internal.ManagedChannelServiceConfig.MethodInfo;
import io.grpc.internal.RetriableStream.ChannelBufferMeter;
import io.grpc.internal.RetriableStream.Throttle;
@@ -574,7 +577,7 @@
private final Rescheduler idleTimer;
ManagedChannelImpl(
- AbstractManagedChannelImplBuilder<?> builder,
+ ManagedChannelImplBuilder builder,
ClientTransportFactory clientTransportFactory,
BackoffPolicy.Provider backoffPolicyProvider,
ObjectPool<? extends Executor> balancerRpcExecutorPool,
@@ -661,7 +664,7 @@
} else {
checkArgument(
builder.idleTimeoutMillis
- >= AbstractManagedChannelImplBuilder.IDLE_MODE_MIN_TIMEOUT_MILLIS,
+ >= ManagedChannelImplBuilder.IDLE_MODE_MIN_TIMEOUT_MILLIS,
"invalid idleTimeoutMillis %s", builder.idleTimeoutMillis);
this.idleTimeoutMillis = builder.idleTimeoutMillis;
}
@@ -1446,28 +1449,27 @@
@Override
public ManagedChannelBuilder<?> createResolvingOobChannelBuilder(String target) {
final class ResolvingOobChannelBuilder
- extends AbstractManagedChannelImplBuilder<ResolvingOobChannelBuilder> {
- int defaultPort = -1;
+ extends ForwardingChannelBuilder<ResolvingOobChannelBuilder> {
+ private final ManagedChannelImplBuilder managedChannelImplBuilder;
ResolvingOobChannelBuilder(String target) {
- super(target);
+ managedChannelImplBuilder = new ManagedChannelImplBuilder(target,
+ new UnsupportedClientTransportFactoryBuilder(),
+ new FixedPortProvider(nameResolverArgs.getDefaultPort()));
+ managedChannelImplBuilder.executorPool = executorPool;
+ managedChannelImplBuilder.offloadExecutorPool = offloadExecutorHolder.pool;
}
@Override
- public int getDefaultPort() {
- return defaultPort;
- }
-
- @Override
- protected ClientTransportFactory buildTransportFactory() {
- throw new UnsupportedOperationException();
+ protected ManagedChannelBuilder<?> delegate() {
+ return managedChannelImplBuilder;
}
@Override
public ManagedChannel build() {
// TODO(creamsoup) prevent main channel to shutdown if oob channel is not terminated
return new ManagedChannelImpl(
- this,
+ managedChannelImplBuilder,
transportFactory,
backoffPolicyProvider,
balancerRpcExecutorPool,
@@ -1479,17 +1481,15 @@
checkState(!terminated, "Channel is terminated");
- ResolvingOobChannelBuilder builder = new ResolvingOobChannelBuilder(target);
- builder.offloadExecutorPool = offloadExecutorHolder.pool;
- builder.overrideAuthority(getAuthority());
@SuppressWarnings("deprecation")
- ResolvingOobChannelBuilder unused = builder.nameResolverFactory(nameResolverFactory);
- builder.executorPool = executorPool;
- builder.maxTraceEvents = maxTraceEvents;
- builder.proxyDetector = nameResolverArgs.getProxyDetector();
- builder.defaultPort = nameResolverArgs.getDefaultPort();
- builder.userAgent = userAgent;
- return builder;
+ ResolvingOobChannelBuilder builder = new ResolvingOobChannelBuilder(target)
+ .nameResolverFactory(nameResolverFactory);
+
+ return builder
+ .overrideAuthority(getAuthority())
+ .maxTraceEvents(maxTraceEvents)
+ .proxyDetector(nameResolverArgs.getProxyDetector())
+ .userAgent(userAgent);
}
@Override
diff --git a/core/src/main/java/io/grpc/internal/ManagedChannelImplBuilder.java b/core/src/main/java/io/grpc/internal/ManagedChannelImplBuilder.java
index d2807df..202055f 100644
--- a/core/src/main/java/io/grpc/internal/ManagedChannelImplBuilder.java
+++ b/core/src/main/java/io/grpc/internal/ManagedChannelImplBuilder.java
@@ -16,19 +16,148 @@
package io.grpc.internal;
+import static com.google.common.base.Preconditions.checkArgument;
+
+import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Preconditions;
+import com.google.common.util.concurrent.MoreExecutors;
+import io.grpc.Attributes;
+import io.grpc.BinaryLog;
+import io.grpc.ClientInterceptor;
+import io.grpc.CompressorRegistry;
+import io.grpc.DecompressorRegistry;
+import io.grpc.EquivalentAddressGroup;
+import io.grpc.InternalChannelz;
+import io.grpc.ManagedChannel;
import io.grpc.ManagedChannelBuilder;
+import io.grpc.NameResolver;
+import io.grpc.NameResolverRegistry;
+import io.grpc.ProxyDetector;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
import java.net.SocketAddress;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
import java.util.concurrent.Executor;
+import java.util.concurrent.TimeUnit;
+import java.util.logging.Level;
+import java.util.logging.Logger;
import javax.annotation.Nullable;
/**
* Default managed channel builder, for usage in Transport implementations.
*/
public final class ManagedChannelImplBuilder
- extends AbstractManagedChannelImplBuilder<ManagedChannelImplBuilder> {
+ extends ManagedChannelBuilder<ManagedChannelImplBuilder> {
+ private static final String DIRECT_ADDRESS_SCHEME = "directaddress";
+
+ private static final Logger log = Logger.getLogger(ManagedChannelImplBuilder.class.getName());
+
+ public static ManagedChannelBuilder<?> forAddress(String name, int port) {
+ throw new UnsupportedOperationException(
+ "ClientTransportFactoryBuilder is required, use a constructor");
+ }
+
+ public static ManagedChannelBuilder<?> forTarget(String target) {
+ throw new UnsupportedOperationException(
+ "ClientTransportFactoryBuilder is required, use a constructor");
+ }
+
+ /**
+ * An idle timeout larger than this would disable idle mode.
+ */
+ @VisibleForTesting
+ static final long IDLE_MODE_MAX_TIMEOUT_DAYS = 30;
+
+ /**
+ * The default idle timeout.
+ */
+ @VisibleForTesting
+ static final long IDLE_MODE_DEFAULT_TIMEOUT_MILLIS = TimeUnit.MINUTES.toMillis(30);
+
+ /**
+ * An idle timeout smaller than this would be capped to it.
+ */
+ static final long IDLE_MODE_MIN_TIMEOUT_MILLIS = TimeUnit.SECONDS.toMillis(1);
+
+ private static final ObjectPool<? extends Executor> DEFAULT_EXECUTOR_POOL =
+ SharedResourcePool.forResource(GrpcUtil.SHARED_CHANNEL_EXECUTOR);
+
+ private static final DecompressorRegistry DEFAULT_DECOMPRESSOR_REGISTRY =
+ DecompressorRegistry.getDefaultInstance();
+
+ private static final CompressorRegistry DEFAULT_COMPRESSOR_REGISTRY =
+ CompressorRegistry.getDefaultInstance();
+
+ private static final long DEFAULT_RETRY_BUFFER_SIZE_IN_BYTES = 1L << 24; // 16M
+ private static final long DEFAULT_PER_RPC_BUFFER_LIMIT_IN_BYTES = 1L << 20; // 1M
+
+ ObjectPool<? extends Executor> executorPool = DEFAULT_EXECUTOR_POOL;
+
+ ObjectPool<? extends Executor> offloadExecutorPool = DEFAULT_EXECUTOR_POOL;
+
+ private final List<ClientInterceptor> interceptors = new ArrayList<>();
+ final NameResolverRegistry nameResolverRegistry = NameResolverRegistry.getDefaultRegistry();
+
+ // Access via getter, which may perform authority override as needed
+ private NameResolver.Factory nameResolverFactory = nameResolverRegistry.asFactory();
+
+ final String target;
+
+ @Nullable
+ private final SocketAddress directServerAddress;
+
+ @Nullable
+ String userAgent;
+
+ @Nullable
+ private String authorityOverride;
+
+ String defaultLbPolicy = GrpcUtil.DEFAULT_LB_POLICY;
+
+ boolean fullStreamDecompression;
+
+ DecompressorRegistry decompressorRegistry = DEFAULT_DECOMPRESSOR_REGISTRY;
+
+ CompressorRegistry compressorRegistry = DEFAULT_COMPRESSOR_REGISTRY;
+
+ long idleTimeoutMillis = IDLE_MODE_DEFAULT_TIMEOUT_MILLIS;
+
+ int maxRetryAttempts = 5;
+ int maxHedgedAttempts = 5;
+ long retryBufferSize = DEFAULT_RETRY_BUFFER_SIZE_IN_BYTES;
+ long perRpcBufferLimit = DEFAULT_PER_RPC_BUFFER_LIMIT_IN_BYTES;
+ boolean retryEnabled = false; // TODO(zdapeng): default to true
+ // Temporarily disable retry when stats or tracing is enabled to avoid breakage, until we know
+ // what should be the desired behavior for retry + stats/tracing.
+ // TODO(zdapeng): delete me
+ boolean temporarilyDisableRetry;
+
+ InternalChannelz channelz = InternalChannelz.instance();
+ int maxTraceEvents;
+
+ @Nullable
+ Map<String, ?> defaultServiceConfig;
+ boolean lookUpServiceConfig = true;
+
+ @Nullable
+ BinaryLog binlog;
+
+ @Nullable
+ ProxyDetector proxyDetector;
private boolean authorityCheckerDisabled;
+ private boolean statsEnabled = true;
+ private boolean recordStartedRpcs = true;
+ private boolean recordFinishedRpcs = true;
+ private boolean recordRealTimeMetrics = false;
+ private boolean tracingEnabled = true;
/**
* An interface for Transport implementors to provide the {@link ClientTransportFactory}
@@ -39,6 +168,17 @@
}
/**
+ * Convenience ClientTransportFactoryBuilder, throws UnsupportedOperationException().
+ */
+ public static class UnsupportedClientTransportFactoryBuilder implements
+ ClientTransportFactoryBuilder {
+ @Override
+ public ClientTransportFactory buildClientTransportFactory() {
+ throw new UnsupportedOperationException();
+ }
+ }
+
+ /**
* An interface for Transport implementors to provide a default port to {@link
* io.grpc.NameResolver} for use in cases where the target string doesn't include a port. The
* default implementation returns {@link GrpcUtil#DEFAULT_PORT_SSL}.
@@ -63,11 +203,11 @@
}
}
- private final class ManagedChannelDefaultPortProvider implements
+ private static final class ManagedChannelDefaultPortProvider implements
ChannelBuilderDefaultPortProvider {
@Override
public int getDefaultPort() {
- return ManagedChannelImplBuilder.super.getDefaultPort();
+ return GrpcUtil.DEFAULT_PORT_SSL;
}
}
@@ -82,9 +222,10 @@
public ManagedChannelImplBuilder(String target,
ClientTransportFactoryBuilder clientTransportFactoryBuilder,
@Nullable ChannelBuilderDefaultPortProvider channelBuilderDefaultPortProvider) {
- super(target);
+ this.target = Preconditions.checkNotNull(target, "target");
this.clientTransportFactoryBuilder = Preconditions
.checkNotNull(clientTransportFactoryBuilder, "clientTransportFactoryBuilder");
+ this.directServerAddress = null;
if (channelBuilderDefaultPortProvider != null) {
this.channelBuilderDefaultPortProvider = channelBuilderDefaultPortProvider;
@@ -94,6 +235,21 @@
}
/**
+ * Returns a target string for the SocketAddress. It is only used as a placeholder, because
+ * DirectAddressNameResolverFactory will not actually try to use it. However, it must be a valid
+ * URI.
+ */
+ @VisibleForTesting
+ static String makeTargetStringForDirectAddress(SocketAddress address) {
+ try {
+ return new URI(DIRECT_ADDRESS_SCHEME, "", "/" + address, null).toString();
+ } catch (URISyntaxException e) {
+ // It should not happen.
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
* Creates a new managed channel builder with the given server address, authority string of the
* channel. Transport implementors must provide client transport factory builder, and may set
* custom channel default port provider.
@@ -101,9 +257,11 @@
public ManagedChannelImplBuilder(SocketAddress directServerAddress, String authority,
ClientTransportFactoryBuilder clientTransportFactoryBuilder,
@Nullable ChannelBuilderDefaultPortProvider channelBuilderDefaultPortProvider) {
- super(directServerAddress, authority);
+ this.target = makeTargetStringForDirectAddress(directServerAddress);
this.clientTransportFactoryBuilder = Preconditions
.checkNotNull(clientTransportFactoryBuilder, "clientTransportFactoryBuilder");
+ this.directServerAddress = directServerAddress;
+ this.nameResolverFactory = new DirectAddressNameResolverFactory(directServerAddress, authority);
if (channelBuilderDefaultPortProvider != null) {
this.channelBuilderDefaultPortProvider = channelBuilderDefaultPortProvider;
@@ -113,13 +271,306 @@
}
@Override
- protected ClientTransportFactory buildTransportFactory() {
- return clientTransportFactoryBuilder.buildClientTransportFactory();
+ public ManagedChannelImplBuilder directExecutor() {
+ return executor(MoreExecutors.directExecutor());
}
@Override
- protected int getDefaultPort() {
- return channelBuilderDefaultPortProvider.getDefaultPort();
+ public ManagedChannelImplBuilder executor(Executor executor) {
+ if (executor != null) {
+ this.executorPool = new FixedObjectPool<>(executor);
+ } else {
+ this.executorPool = DEFAULT_EXECUTOR_POOL;
+ }
+ return this;
+ }
+
+ @Override
+ public ManagedChannelImplBuilder offloadExecutor(Executor executor) {
+ if (executor != null) {
+ this.offloadExecutorPool = new FixedObjectPool<>(executor);
+ } else {
+ this.offloadExecutorPool = DEFAULT_EXECUTOR_POOL;
+ }
+ return this;
+ }
+
+ @Override
+ public ManagedChannelImplBuilder intercept(List<ClientInterceptor> interceptors) {
+ this.interceptors.addAll(interceptors);
+ return this;
+ }
+
+ @Override
+ public ManagedChannelImplBuilder intercept(ClientInterceptor... interceptors) {
+ return intercept(Arrays.asList(interceptors));
+ }
+
+ @Deprecated
+ @Override
+ public ManagedChannelImplBuilder nameResolverFactory(NameResolver.Factory resolverFactory) {
+ Preconditions.checkState(directServerAddress == null,
+ "directServerAddress is set (%s), which forbids the use of NameResolverFactory",
+ directServerAddress);
+ if (resolverFactory != null) {
+ this.nameResolverFactory = resolverFactory;
+ } else {
+ this.nameResolverFactory = nameResolverRegistry.asFactory();
+ }
+ return this;
+ }
+
+ @Override
+ public ManagedChannelImplBuilder defaultLoadBalancingPolicy(String policy) {
+ Preconditions.checkState(directServerAddress == null,
+ "directServerAddress is set (%s), which forbids the use of load-balancing policy",
+ directServerAddress);
+ Preconditions.checkArgument(policy != null, "policy cannot be null");
+ this.defaultLbPolicy = policy;
+ return this;
+ }
+
+ @Override
+ public ManagedChannelImplBuilder enableFullStreamDecompression() {
+ this.fullStreamDecompression = true;
+ return this;
+ }
+
+ @Override
+ public ManagedChannelImplBuilder decompressorRegistry(DecompressorRegistry registry) {
+ if (registry != null) {
+ this.decompressorRegistry = registry;
+ } else {
+ this.decompressorRegistry = DEFAULT_DECOMPRESSOR_REGISTRY;
+ }
+ return this;
+ }
+
+ @Override
+ public ManagedChannelImplBuilder compressorRegistry(CompressorRegistry registry) {
+ if (registry != null) {
+ this.compressorRegistry = registry;
+ } else {
+ this.compressorRegistry = DEFAULT_COMPRESSOR_REGISTRY;
+ }
+ return this;
+ }
+
+ @Override
+ public ManagedChannelImplBuilder userAgent(@Nullable String userAgent) {
+ this.userAgent = userAgent;
+ return this;
+ }
+
+ @Override
+ public ManagedChannelImplBuilder overrideAuthority(String authority) {
+ this.authorityOverride = checkAuthority(authority);
+ return this;
+ }
+
+ @Nullable
+ @VisibleForTesting
+ String getOverrideAuthority() {
+ return authorityOverride;
+ }
+
+ @Override
+ public ManagedChannelImplBuilder idleTimeout(long value, TimeUnit unit) {
+ checkArgument(value > 0, "idle timeout is %s, but must be positive", value);
+ // We convert to the largest unit to avoid overflow
+ if (unit.toDays(value) >= IDLE_MODE_MAX_TIMEOUT_DAYS) {
+ // This disables idle mode
+ this.idleTimeoutMillis = ManagedChannelImpl.IDLE_TIMEOUT_MILLIS_DISABLE;
+ } else {
+ this.idleTimeoutMillis = Math.max(unit.toMillis(value), IDLE_MODE_MIN_TIMEOUT_MILLIS);
+ }
+ return this;
+ }
+
+ @Override
+ public ManagedChannelImplBuilder maxRetryAttempts(int maxRetryAttempts) {
+ this.maxRetryAttempts = maxRetryAttempts;
+ return this;
+ }
+
+ @Override
+ public ManagedChannelImplBuilder maxHedgedAttempts(int maxHedgedAttempts) {
+ this.maxHedgedAttempts = maxHedgedAttempts;
+ return this;
+ }
+
+ @Override
+ public ManagedChannelImplBuilder retryBufferSize(long bytes) {
+ checkArgument(bytes > 0L, "retry buffer size must be positive");
+ retryBufferSize = bytes;
+ return this;
+ }
+
+ @Override
+ public ManagedChannelImplBuilder perRpcBufferLimit(long bytes) {
+ checkArgument(bytes > 0L, "per RPC buffer limit must be positive");
+ perRpcBufferLimit = bytes;
+ return this;
+ }
+
+ @Override
+ public ManagedChannelImplBuilder disableRetry() {
+ retryEnabled = false;
+ return this;
+ }
+
+ @Override
+ public ManagedChannelImplBuilder enableRetry() {
+ retryEnabled = true;
+ statsEnabled = false;
+ tracingEnabled = false;
+ return this;
+ }
+
+ @Override
+ public ManagedChannelImplBuilder setBinaryLog(BinaryLog binlog) {
+ this.binlog = binlog;
+ return this;
+ }
+
+ @Override
+ public ManagedChannelImplBuilder maxTraceEvents(int maxTraceEvents) {
+ checkArgument(maxTraceEvents >= 0, "maxTraceEvents must be non-negative");
+ this.maxTraceEvents = maxTraceEvents;
+ return this;
+ }
+
+ @Override
+ public ManagedChannelImplBuilder proxyDetector(@Nullable ProxyDetector proxyDetector) {
+ this.proxyDetector = proxyDetector;
+ return this;
+ }
+
+ @Override
+ public ManagedChannelImplBuilder defaultServiceConfig(@Nullable Map<String, ?> serviceConfig) {
+ // TODO(notcarl): use real parsing
+ defaultServiceConfig = checkMapEntryTypes(serviceConfig);
+ return this;
+ }
+
+ @Nullable
+ private static Map<String, ?> checkMapEntryTypes(@Nullable Map<?, ?> map) {
+ if (map == null) {
+ return null;
+ }
+ // Not using ImmutableMap.Builder because of extra guava dependency for Android.
+ Map<String, Object> parsedMap = new LinkedHashMap<>();
+ for (Map.Entry<?, ?> entry : map.entrySet()) {
+ checkArgument(
+ entry.getKey() instanceof String,
+ "The key of the entry '%s' is not of String type", entry);
+
+ String key = (String) entry.getKey();
+ Object value = entry.getValue();
+ if (value == null) {
+ parsedMap.put(key, null);
+ } else if (value instanceof Map) {
+ parsedMap.put(key, checkMapEntryTypes((Map<?, ?>) value));
+ } else if (value instanceof List) {
+ parsedMap.put(key, checkListEntryTypes((List<?>) value));
+ } else if (value instanceof String) {
+ parsedMap.put(key, value);
+ } else if (value instanceof Double) {
+ parsedMap.put(key, value);
+ } else if (value instanceof Boolean) {
+ parsedMap.put(key, value);
+ } else {
+ throw new IllegalArgumentException(
+ "The value of the map entry '" + entry + "' is of type '" + value.getClass()
+ + "', which is not supported");
+ }
+ }
+ return Collections.unmodifiableMap(parsedMap);
+ }
+
+ private static List<?> checkListEntryTypes(List<?> list) {
+ List<Object> parsedList = new ArrayList<>(list.size());
+ for (Object value : list) {
+ if (value == null) {
+ parsedList.add(null);
+ } else if (value instanceof Map) {
+ parsedList.add(checkMapEntryTypes((Map<?, ?>) value));
+ } else if (value instanceof List) {
+ parsedList.add(checkListEntryTypes((List<?>) value));
+ } else if (value instanceof String) {
+ parsedList.add(value);
+ } else if (value instanceof Double) {
+ parsedList.add(value);
+ } else if (value instanceof Boolean) {
+ parsedList.add(value);
+ } else {
+ throw new IllegalArgumentException(
+ "The entry '" + value + "' is of type '" + value.getClass()
+ + "', which is not supported");
+ }
+ }
+ return Collections.unmodifiableList(parsedList);
+ }
+
+ @Override
+ public ManagedChannelImplBuilder disableServiceConfigLookUp() {
+ this.lookUpServiceConfig = false;
+ return this;
+ }
+
+ /**
+ * Disable or enable stats features. Enabled by default.
+ *
+ * <p>For the current release, calling {@code setStatsEnabled(true)} may have a side effect that
+ * disables retry.
+ */
+ public void setStatsEnabled(boolean value) {
+ statsEnabled = value;
+ }
+
+ /**
+ * Disable or enable stats recording for RPC upstarts. Effective only if {@link
+ * #setStatsEnabled} is set to true. Enabled by default.
+ */
+ public void setStatsRecordStartedRpcs(boolean value) {
+ recordStartedRpcs = value;
+ }
+
+ /**
+ * Disable or enable stats recording for RPC completions. Effective only if {@link
+ * #setStatsEnabled} is set to true. Enabled by default.
+ */
+ public void setStatsRecordFinishedRpcs(boolean value) {
+ recordFinishedRpcs = value;
+ }
+
+ /**
+ * Disable or enable real-time metrics recording. Effective only if {@link #setStatsEnabled} is
+ * set to true. Disabled by default.
+ */
+ public void setStatsRecordRealTimeMetrics(boolean value) {
+ recordRealTimeMetrics = value;
+ }
+
+ /**
+ * Disable or enable tracing features. Enabled by default.
+ *
+ * <p>For the current release, calling {@code setTracingEnabled(true)} may have a side effect that
+ * disables retry.
+ */
+ public void setTracingEnabled(boolean value) {
+ tracingEnabled = value;
+ }
+
+ /**
+ * Verifies the authority is valid.
+ */
+ @VisibleForTesting
+ String checkAuthority(String authority) {
+ if (authorityCheckerDisabled) {
+ return authority;
+ }
+ return GrpcUtil.checkAuthority(authority);
}
/** Disable the check whether the authority is valid. */
@@ -135,48 +586,146 @@
}
@Override
- protected String checkAuthority(String authority) {
- if (authorityCheckerDisabled) {
- return authority;
+ public ManagedChannel build() {
+ return new ManagedChannelOrphanWrapper(new ManagedChannelImpl(
+ this,
+ clientTransportFactoryBuilder.buildClientTransportFactory(),
+ new ExponentialBackoffPolicy.Provider(),
+ SharedResourcePool.forResource(GrpcUtil.SHARED_CHANNEL_EXECUTOR),
+ GrpcUtil.STOPWATCH_SUPPLIER,
+ getEffectiveInterceptors(),
+ TimeProvider.SYSTEM_TIME_PROVIDER));
+ }
+
+ // Temporarily disable retry when stats or tracing is enabled to avoid breakage, until we know
+ // what should be the desired behavior for retry + stats/tracing.
+ // TODO(zdapeng): FIX IT
+ @VisibleForTesting
+ List<ClientInterceptor> getEffectiveInterceptors() {
+ List<ClientInterceptor> effectiveInterceptors =
+ new ArrayList<>(this.interceptors);
+ temporarilyDisableRetry = false;
+ if (statsEnabled) {
+ temporarilyDisableRetry = true;
+ ClientInterceptor statsInterceptor = null;
+ try {
+ Class<?> censusStatsAccessor =
+ Class.forName("io.grpc.census.InternalCensusStatsAccessor");
+ Method getClientInterceptorMethod =
+ censusStatsAccessor.getDeclaredMethod(
+ "getClientInterceptor",
+ boolean.class,
+ boolean.class,
+ boolean.class);
+ statsInterceptor =
+ (ClientInterceptor) getClientInterceptorMethod
+ .invoke(
+ null,
+ recordStartedRpcs,
+ recordFinishedRpcs,
+ recordRealTimeMetrics);
+ } catch (ClassNotFoundException e) {
+ // Replace these separate catch statements with multicatch when Android min-API >= 19
+ log.log(Level.FINE, "Unable to apply census stats", e);
+ } catch (NoSuchMethodException e) {
+ log.log(Level.FINE, "Unable to apply census stats", e);
+ } catch (IllegalAccessException e) {
+ log.log(Level.FINE, "Unable to apply census stats", e);
+ } catch (InvocationTargetException e) {
+ log.log(Level.FINE, "Unable to apply census stats", e);
+ }
+ if (statsInterceptor != null) {
+ // First interceptor runs last (see ClientInterceptors.intercept()), so that no
+ // other interceptor can override the tracer factory we set in CallOptions.
+ effectiveInterceptors.add(0, statsInterceptor);
+ }
}
- return super.checkAuthority(authority);
+ if (tracingEnabled) {
+ temporarilyDisableRetry = true;
+ ClientInterceptor tracingInterceptor = null;
+ try {
+ Class<?> censusTracingAccessor =
+ Class.forName("io.grpc.census.InternalCensusTracingAccessor");
+ Method getClientInterceptroMethod =
+ censusTracingAccessor.getDeclaredMethod("getClientInterceptor");
+ tracingInterceptor = (ClientInterceptor) getClientInterceptroMethod.invoke(null);
+ } catch (ClassNotFoundException e) {
+ // Replace these separate catch statements with multicatch when Android min-API >= 19
+ log.log(Level.FINE, "Unable to apply census stats", e);
+ } catch (NoSuchMethodException e) {
+ log.log(Level.FINE, "Unable to apply census stats", e);
+ } catch (IllegalAccessException e) {
+ log.log(Level.FINE, "Unable to apply census stats", e);
+ } catch (InvocationTargetException e) {
+ log.log(Level.FINE, "Unable to apply census stats", e);
+ }
+ if (tracingInterceptor != null) {
+ effectiveInterceptors.add(0, tracingInterceptor);
+ }
+ }
+ return effectiveInterceptors;
}
- @Override
- public void setStatsEnabled(boolean value) {
- super.setStatsEnabled(value);
+ /**
+ * Returns a default port to {@link NameResolver} for use in cases where the target string doesn't
+ * include a port. The default implementation returns {@link GrpcUtil#DEFAULT_PORT_SSL}.
+ */
+ int getDefaultPort() {
+ return channelBuilderDefaultPortProvider.getDefaultPort();
}
- @Override
- public void setStatsRecordStartedRpcs(boolean value) {
- super.setStatsRecordStartedRpcs(value);
+ /**
+ * Returns a {@link NameResolver.Factory} for the channel.
+ */
+ NameResolver.Factory getNameResolverFactory() {
+ if (authorityOverride == null) {
+ return nameResolverFactory;
+ } else {
+ return new OverrideAuthorityNameResolverFactory(nameResolverFactory, authorityOverride);
+ }
}
- @Override
- public void setStatsRecordFinishedRpcs(boolean value) {
- super.setStatsRecordFinishedRpcs(value);
+ private static class DirectAddressNameResolverFactory extends NameResolver.Factory {
+ final SocketAddress address;
+ final String authority;
+
+ DirectAddressNameResolverFactory(SocketAddress address, String authority) {
+ this.address = address;
+ this.authority = authority;
+ }
+
+ @Override
+ public NameResolver newNameResolver(URI notUsedUri, NameResolver.Args args) {
+ return new NameResolver() {
+ @Override
+ public String getServiceAuthority() {
+ return authority;
+ }
+
+ @Override
+ public void start(Listener2 listener) {
+ listener.onResult(
+ ResolutionResult.newBuilder()
+ .setAddresses(Collections.singletonList(new EquivalentAddressGroup(address)))
+ .setAttributes(Attributes.EMPTY)
+ .build());
+ }
+
+ @Override
+ public void shutdown() {}
+ };
+ }
+
+ @Override
+ public String getDefaultScheme() {
+ return DIRECT_ADDRESS_SCHEME;
+ }
}
- @Override
- public void setStatsRecordRealTimeMetrics(boolean value) {
- super.setStatsRecordRealTimeMetrics(value);
- }
-
- @Override
- public void setTracingEnabled(boolean value) {
- super.setTracingEnabled(value);
- }
-
- @Override
+ /**
+ * Returns the internal offload executor pool for offloading tasks.
+ */
public ObjectPool<? extends Executor> getOffloadExecutorPool() {
- return super.getOffloadExecutorPool();
- }
-
- public static ManagedChannelBuilder<?> forAddress(String name, int port) {
- throw new UnsupportedOperationException("ClientTransportFactoryBuilder is required");
- }
-
- public static ManagedChannelBuilder<?> forTarget(String target) {
- throw new UnsupportedOperationException("ClientTransportFactoryBuilder is required");
+ return this.offloadExecutorPool;
}
}
diff --git a/core/src/test/java/io/grpc/internal/AbstractManagedChannelImplBuilderTest.java b/core/src/test/java/io/grpc/internal/AbstractManagedChannelImplBuilderTest.java
deleted file mode 100644
index 2ac49c4..0000000
--- a/core/src/test/java/io/grpc/internal/AbstractManagedChannelImplBuilderTest.java
+++ /dev/null
@@ -1,482 +0,0 @@
-/*
- * Copyright 2016 The gRPC Authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package io.grpc.internal;
-
-import static com.google.common.truth.Truth.assertThat;
-import static junit.framework.TestCase.assertFalse;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-import static org.mockito.Mockito.mock;
-
-import com.google.common.util.concurrent.MoreExecutors;
-import io.grpc.CallOptions;
-import io.grpc.Channel;
-import io.grpc.ClientCall;
-import io.grpc.ClientInterceptor;
-import io.grpc.CompressorRegistry;
-import io.grpc.DecompressorRegistry;
-import io.grpc.MethodDescriptor;
-import io.grpc.NameResolver;
-import java.net.InetSocketAddress;
-import java.net.SocketAddress;
-import java.net.URI;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.Executor;
-import java.util.concurrent.TimeUnit;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
-
-/** Unit tests for {@link AbstractManagedChannelImplBuilder}. */
-@RunWith(JUnit4.class)
-public class AbstractManagedChannelImplBuilderTest {
-
- @Rule
- public final ExpectedException thrown = ExpectedException.none();
-
- private static final ClientInterceptor DUMMY_USER_INTERCEPTOR =
- new ClientInterceptor() {
- @Override
- public <ReqT, RespT> ClientCall<ReqT, RespT> interceptCall(
- MethodDescriptor<ReqT, RespT> method, CallOptions callOptions, Channel next) {
- return next.newCall(method, callOptions);
- }
- };
-
- private final Builder builder = new Builder("fake");
- private final Builder directAddressBuilder = new Builder(new SocketAddress(){}, "fake");
-
- @Test
- public void executor_default() {
- assertNotNull(builder.executorPool);
- }
-
- @Test
- public void executor_normal() {
- Executor executor = mock(Executor.class);
- assertEquals(builder, builder.executor(executor));
- assertEquals(executor, builder.executorPool.getObject());
- }
-
- @Test
- public void executor_null() {
- ObjectPool<? extends Executor> defaultValue = builder.executorPool;
- builder.executor(mock(Executor.class));
- assertEquals(builder, builder.executor(null));
- assertEquals(defaultValue, builder.executorPool);
- }
-
- @Test
- public void directExecutor() {
- assertEquals(builder, builder.directExecutor());
- assertEquals(MoreExecutors.directExecutor(), builder.executorPool.getObject());
- }
-
- @Test
- public void offloadExecutor_normal() {
- Executor executor = mock(Executor.class);
- assertEquals(builder, builder.offloadExecutor(executor));
- assertEquals(executor, builder.offloadExecutorPool.getObject());
- }
-
- @Test
- public void offloadExecutor_null() {
- ObjectPool<? extends Executor> defaultValue = builder.offloadExecutorPool;
- builder.offloadExecutor(mock(Executor.class));
- assertEquals(builder, builder.offloadExecutor(null));
- assertEquals(defaultValue, builder.offloadExecutorPool);
- }
-
- @Test
- public void nameResolverFactory_default() {
- assertNotNull(builder.getNameResolverFactory());
- }
-
- @Test
- @SuppressWarnings("deprecation")
- public void nameResolverFactory_normal() {
- NameResolver.Factory nameResolverFactory = mock(NameResolver.Factory.class);
- assertEquals(builder, builder.nameResolverFactory(nameResolverFactory));
- assertEquals(nameResolverFactory, builder.getNameResolverFactory());
- }
-
- @Test
- @SuppressWarnings("deprecation")
- public void nameResolverFactory_null() {
- NameResolver.Factory defaultValue = builder.getNameResolverFactory();
- builder.nameResolverFactory(mock(NameResolver.Factory.class));
- assertEquals(builder, builder.nameResolverFactory(null));
- assertEquals(defaultValue, builder.getNameResolverFactory());
- }
-
- @Test(expected = IllegalStateException.class)
- @SuppressWarnings("deprecation")
- public void nameResolverFactory_notAllowedWithDirectAddress() {
- directAddressBuilder.nameResolverFactory(mock(NameResolver.Factory.class));
- }
-
- @Test
- public void defaultLoadBalancingPolicy_default() {
- assertEquals("pick_first", builder.defaultLbPolicy);
- }
-
- @Test
- public void defaultLoadBalancingPolicy_normal() {
- assertEquals(builder, builder.defaultLoadBalancingPolicy("magic_balancer"));
- assertEquals("magic_balancer", builder.defaultLbPolicy);
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void defaultLoadBalancingPolicy_null() {
- builder.defaultLoadBalancingPolicy(null);
- }
-
- @Test(expected = IllegalStateException.class)
- public void defaultLoadBalancingPolicy_notAllowedWithDirectAddress() {
- directAddressBuilder.defaultLoadBalancingPolicy("magic_balancer");
- }
-
- @Test
- public void fullStreamDecompression_default() {
- assertFalse(builder.fullStreamDecompression);
- }
-
- @Test
- public void fullStreamDecompression_enabled() {
- assertEquals(builder, builder.enableFullStreamDecompression());
- assertTrue(builder.fullStreamDecompression);
- }
-
- @Test
- public void decompressorRegistry_default() {
- assertNotNull(builder.decompressorRegistry);
- }
-
- @Test
- public void decompressorRegistry_normal() {
- DecompressorRegistry decompressorRegistry = DecompressorRegistry.emptyInstance();
- assertNotEquals(decompressorRegistry, builder.decompressorRegistry);
- assertEquals(builder, builder.decompressorRegistry(decompressorRegistry));
- assertEquals(decompressorRegistry, builder.decompressorRegistry);
- }
-
- @Test
- public void decompressorRegistry_null() {
- DecompressorRegistry defaultValue = builder.decompressorRegistry;
- assertEquals(builder, builder.decompressorRegistry(DecompressorRegistry.emptyInstance()));
- assertNotEquals(defaultValue, builder.decompressorRegistry);
- builder.decompressorRegistry(null);
- assertEquals(defaultValue, builder.decompressorRegistry);
- }
-
- @Test
- public void compressorRegistry_default() {
- assertNotNull(builder.compressorRegistry);
- }
-
- @Test
- public void compressorRegistry_normal() {
- CompressorRegistry compressorRegistry = CompressorRegistry.newEmptyInstance();
- assertNotEquals(compressorRegistry, builder.compressorRegistry);
- assertEquals(builder, builder.compressorRegistry(compressorRegistry));
- assertEquals(compressorRegistry, builder.compressorRegistry);
- }
-
- @Test
- public void compressorRegistry_null() {
- CompressorRegistry defaultValue = builder.compressorRegistry;
- builder.compressorRegistry(CompressorRegistry.newEmptyInstance());
- assertNotEquals(defaultValue, builder.compressorRegistry);
- assertEquals(builder, builder.compressorRegistry(null));
- assertEquals(defaultValue, builder.compressorRegistry);
- }
-
- @Test
- public void userAgent_default() {
- assertNull(builder.userAgent);
- }
-
- @Test
- public void userAgent_normal() {
- String userAgent = "user-agent/1";
- assertEquals(builder, builder.userAgent(userAgent));
- assertEquals(userAgent, builder.userAgent);
- }
-
- @Test
- public void userAgent_null() {
- assertEquals(builder, builder.userAgent(null));
- assertNull(builder.userAgent);
-
- builder.userAgent("user-agent/1");
- builder.userAgent(null);
- assertNull(builder.userAgent);
- }
-
- @Test
- public void overrideAuthority_default() {
- assertNull(builder.authorityOverride);
- }
-
- @Test
- public void overrideAuthority_normal() {
- String overrideAuthority = "best-authority";
- assertEquals(builder, builder.overrideAuthority(overrideAuthority));
- assertEquals(overrideAuthority, builder.authorityOverride);
- }
-
- @Test(expected = NullPointerException.class)
- public void overrideAuthority_null() {
- builder.overrideAuthority(null);
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void overrideAuthority_invalid() {
- builder.overrideAuthority("not_allowed");
- }
-
- @Test
- public void overrideAuthority_getNameResolverFactory() {
- assertNull(builder.authorityOverride);
- assertFalse(builder.getNameResolverFactory() instanceof OverrideAuthorityNameResolverFactory);
- builder.overrideAuthority("google.com");
- assertTrue(builder.getNameResolverFactory() instanceof OverrideAuthorityNameResolverFactory);
- }
-
- @Test
- public void makeTargetStringForDirectAddress_scopedIpv6() throws Exception {
- InetSocketAddress address = new InetSocketAddress("0:0:0:0:0:0:0:0%0", 10005);
- assertEquals("/0:0:0:0:0:0:0:0%0:10005", address.toString());
- String target = AbstractManagedChannelImplBuilder.makeTargetStringForDirectAddress(address);
- URI uri = new URI(target);
- assertEquals("directaddress:////0:0:0:0:0:0:0:0%250:10005", target);
- assertEquals(target, uri.toString());
- }
-
- @Test
- public void getEffectiveInterceptors_default() {
- builder.intercept(DUMMY_USER_INTERCEPTOR);
- List<ClientInterceptor> effectiveInterceptors = builder.getEffectiveInterceptors();
- assertEquals(3, effectiveInterceptors.size());
- assertThat(effectiveInterceptors.get(0).getClass().getName())
- .isEqualTo("io.grpc.census.CensusTracingModule$TracingClientInterceptor");
- assertThat(effectiveInterceptors.get(1).getClass().getName())
- .isEqualTo("io.grpc.census.CensusStatsModule$StatsClientInterceptor");
- assertThat(effectiveInterceptors.get(2)).isSameInstanceAs(DUMMY_USER_INTERCEPTOR);
- }
-
- @Test
- public void getEffectiveInterceptors_disableStats() {
- builder.intercept(DUMMY_USER_INTERCEPTOR);
- builder.setStatsEnabled(false);
- List<ClientInterceptor> effectiveInterceptors = builder.getEffectiveInterceptors();
- assertEquals(2, effectiveInterceptors.size());
- assertThat(effectiveInterceptors.get(0).getClass().getName())
- .isEqualTo("io.grpc.census.CensusTracingModule$TracingClientInterceptor");
- assertThat(effectiveInterceptors.get(1)).isSameInstanceAs(DUMMY_USER_INTERCEPTOR);
- }
-
- @Test
- public void getEffectiveInterceptors_disableTracing() {
- builder.intercept(DUMMY_USER_INTERCEPTOR);
- builder.setTracingEnabled(false);
- List<ClientInterceptor> effectiveInterceptors = builder.getEffectiveInterceptors();
- assertEquals(2, effectiveInterceptors.size());
- assertThat(effectiveInterceptors.get(0).getClass().getName())
- .isEqualTo("io.grpc.census.CensusStatsModule$StatsClientInterceptor");
- assertThat(effectiveInterceptors.get(1)).isSameInstanceAs(DUMMY_USER_INTERCEPTOR);
- }
-
- @Test
- public void getEffectiveInterceptors_disableBoth() {
- builder.intercept(DUMMY_USER_INTERCEPTOR);
- builder.setStatsEnabled(false);
- builder.setTracingEnabled(false);
- List<ClientInterceptor> effectiveInterceptors = builder.getEffectiveInterceptors();
- assertThat(effectiveInterceptors).containsExactly(DUMMY_USER_INTERCEPTOR);
- }
-
- @Test
- public void idleTimeout() {
- assertEquals(AbstractManagedChannelImplBuilder.IDLE_MODE_DEFAULT_TIMEOUT_MILLIS,
- builder.getIdleTimeoutMillis());
-
- builder.idleTimeout(Long.MAX_VALUE, TimeUnit.DAYS);
- assertEquals(ManagedChannelImpl.IDLE_TIMEOUT_MILLIS_DISABLE, builder.getIdleTimeoutMillis());
-
- builder.idleTimeout(AbstractManagedChannelImplBuilder.IDLE_MODE_MAX_TIMEOUT_DAYS,
- TimeUnit.DAYS);
- assertEquals(ManagedChannelImpl.IDLE_TIMEOUT_MILLIS_DISABLE, builder.getIdleTimeoutMillis());
-
- try {
- builder.idleTimeout(0, TimeUnit.SECONDS);
- fail("Should throw");
- } catch (IllegalArgumentException e) {
- // expected
- }
-
- builder.idleTimeout(1, TimeUnit.NANOSECONDS);
- assertEquals(AbstractManagedChannelImplBuilder.IDLE_MODE_MIN_TIMEOUT_MILLIS,
- builder.getIdleTimeoutMillis());
-
- builder.idleTimeout(30, TimeUnit.SECONDS);
- assertEquals(TimeUnit.SECONDS.toMillis(30), builder.getIdleTimeoutMillis());
- }
-
- @Test
- public void maxRetryAttempts() {
- assertEquals(5, builder.maxRetryAttempts);
-
- builder.maxRetryAttempts(3);
- assertEquals(3, builder.maxRetryAttempts);
- }
-
- @Test
- public void maxHedgedAttempts() {
- assertEquals(5, builder.maxHedgedAttempts);
-
- builder.maxHedgedAttempts(3);
- assertEquals(3, builder.maxHedgedAttempts);
- }
-
- @Test
- public void retryBufferSize() {
- assertEquals(1L << 24, builder.retryBufferSize);
-
- builder.retryBufferSize(3456L);
- assertEquals(3456L, builder.retryBufferSize);
- }
-
- @Test
- public void perRpcBufferLimit() {
- assertEquals(1L << 20, builder.perRpcBufferLimit);
-
- builder.perRpcBufferLimit(3456L);
- assertEquals(3456L, builder.perRpcBufferLimit);
- }
-
- @Test
- public void retryBufferSizeInvalidArg() {
- thrown.expect(IllegalArgumentException.class);
- builder.retryBufferSize(0L);
- }
-
- @Test
- public void perRpcBufferLimitInvalidArg() {
- thrown.expect(IllegalArgumentException.class);
- builder.perRpcBufferLimit(0L);
- }
-
- @Test
- public void disableRetry() {
- builder.enableRetry();
- assertTrue(builder.retryEnabled);
-
- builder.disableRetry();
- assertFalse(builder.retryEnabled);
-
- builder.enableRetry();
- assertTrue(builder.retryEnabled);
-
- builder.disableRetry();
- assertFalse(builder.retryEnabled);
- }
-
- @Test
- public void defaultServiceConfig_nullKey() {
- Map<String, Object> config = new HashMap<>();
- config.put(null, "val");
-
- thrown.expect(IllegalArgumentException.class);
- builder.defaultServiceConfig(config);
- }
-
- @Test
- public void defaultServiceConfig_intKey() {
- Map<Integer, Object> subConfig = new HashMap<>();
- subConfig.put(3, "val");
- Map<String, Object> config = new HashMap<>();
- config.put("key", subConfig);
-
- thrown.expect(IllegalArgumentException.class);
- builder.defaultServiceConfig(config);
- }
-
- @Test
- public void defaultServiceConfig_intValue() {
- Map<String, Object> config = new HashMap<>();
- config.put("key", 3);
-
- thrown.expect(IllegalArgumentException.class);
- builder.defaultServiceConfig(config);
- }
-
- @Test
- public void defaultServiceConfig_nested() {
- Map<String, Object> config = new HashMap<>();
- List<Object> list1 = new ArrayList<>();
- list1.add(123D);
- list1.add(null);
- list1.add(true);
- list1.add("str");
- Map<String, Object> map2 = new HashMap<>();
- map2.put("key2", false);
- map2.put("key3", null);
- map2.put("key4", Collections.singletonList("v4"));
- map2.put("key4", 3.14D);
- map2.put("key5", new HashMap<String, Object>());
- list1.add(map2);
- config.put("key1", list1);
-
- builder.defaultServiceConfig(config);
-
- assertThat(builder.defaultServiceConfig).containsExactlyEntriesIn(config);
- }
-
- @Test
- public void disableNameResolverServiceConfig() {
- assertThat(builder.lookUpServiceConfig).isTrue();
-
- builder.disableServiceConfigLookUp();
- assertThat(builder.lookUpServiceConfig).isFalse();
- }
-
- static class Builder extends AbstractManagedChannelImplBuilder<Builder> {
- Builder(String target) {
- super(target);
- }
-
- Builder(SocketAddress directServerAddress, String authority) {
- super(directServerAddress, authority);
- }
-
- @Override
- protected ClientTransportFactory buildTransportFactory() {
- throw new UnsupportedOperationException();
- }
- }
-}
diff --git a/core/src/test/java/io/grpc/internal/ManagedChannelImplBuilderTest.java b/core/src/test/java/io/grpc/internal/ManagedChannelImplBuilderTest.java
index 5d3f4cf..dfe9d19 100644
--- a/core/src/test/java/io/grpc/internal/ManagedChannelImplBuilderTest.java
+++ b/core/src/test/java/io/grpc/internal/ManagedChannelImplBuilderTest.java
@@ -16,14 +16,43 @@
package io.grpc.internal;
+import static com.google.common.truth.Truth.assertThat;
+import static junit.framework.TestCase.assertFalse;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import com.google.common.util.concurrent.MoreExecutors;
+import io.grpc.CallOptions;
+import io.grpc.Channel;
+import io.grpc.ClientCall;
+import io.grpc.ClientInterceptor;
+import io.grpc.CompressorRegistry;
+import io.grpc.DecompressorRegistry;
+import io.grpc.ManagedChannel;
+import io.grpc.MethodDescriptor;
+import io.grpc.NameResolver;
import io.grpc.internal.ManagedChannelImplBuilder.ChannelBuilderDefaultPortProvider;
import io.grpc.internal.ManagedChannelImplBuilder.ClientTransportFactoryBuilder;
import io.grpc.internal.ManagedChannelImplBuilder.FixedPortProvider;
+import io.grpc.internal.ManagedChannelImplBuilder.UnsupportedClientTransportFactoryBuilder;
+import io.grpc.testing.GrpcCleanupRule;
+import java.net.InetSocketAddress;
+import java.net.SocketAddress;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.Executor;
+import java.util.concurrent.TimeUnit;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@@ -41,56 +70,295 @@
private static final String DUMMY_TARGET = "fake-target";
private static final String DUMMY_AUTHORITY_VALID = "valid:1234";
private static final String DUMMY_AUTHORITY_INVALID = "[ : : 1]";
+ private static final ClientInterceptor DUMMY_USER_INTERCEPTOR =
+ new ClientInterceptor() {
+ @Override
+ public <ReqT, RespT> ClientCall<ReqT, RespT> interceptCall(
+ MethodDescriptor<ReqT, RespT> method, CallOptions callOptions, Channel next) {
+ return next.newCall(method, callOptions);
+ }
+ };
@Rule public final MockitoRule mocks = MockitoJUnit.rule();
@Rule public final ExpectedException thrown = ExpectedException.none();
+ @Rule public final GrpcCleanupRule grpcCleanupRule = new GrpcCleanupRule();
+ @Mock private ClientTransportFactory mockClientTransportFactory;
@Mock private ClientTransportFactoryBuilder mockClientTransportFactoryBuilder;
- @Mock private ChannelBuilderDefaultPortProvider mockChannelBuilderDefaultPortProvider;
+
private ManagedChannelImplBuilder builder;
+ private ManagedChannelImplBuilder directAddressBuilder;
+ private final FakeClock clock = new FakeClock();
+
@Before
public void setUp() throws Exception {
builder = new ManagedChannelImplBuilder(
DUMMY_TARGET,
- mockClientTransportFactoryBuilder,
- mockChannelBuilderDefaultPortProvider);
- }
-
- /** Ensure buildTransportFactory() delegates to the custom implementation. */
- @Test
- public void buildTransportFactory() {
- final ClientTransportFactory clientTransportFactory = mock(ClientTransportFactory.class);
- when(mockClientTransportFactoryBuilder.buildClientTransportFactory())
- .thenReturn(clientTransportFactory);
- assertEquals(clientTransportFactory, builder.buildTransportFactory());
- verify(mockClientTransportFactoryBuilder).buildClientTransportFactory();
+ new UnsupportedClientTransportFactoryBuilder(),
+ new FixedPortProvider(DUMMY_PORT));
+ directAddressBuilder = new ManagedChannelImplBuilder(
+ new SocketAddress() {},
+ DUMMY_TARGET,
+ new UnsupportedClientTransportFactoryBuilder(),
+ new FixedPortProvider(DUMMY_PORT));
}
/** Ensure getDefaultPort() returns default port when no custom implementation provided. */
@Test
public void getDefaultPort_default() {
- final ManagedChannelImplBuilder builderNoPortProvider = new ManagedChannelImplBuilder(
- DUMMY_TARGET, mockClientTransportFactoryBuilder, null);
- assertEquals(GrpcUtil.DEFAULT_PORT_SSL, builderNoPortProvider.getDefaultPort());
+ builder = new ManagedChannelImplBuilder(DUMMY_TARGET,
+ new UnsupportedClientTransportFactoryBuilder(), null);
+ assertEquals(GrpcUtil.DEFAULT_PORT_SSL, builder.getDefaultPort());
}
/** Ensure getDefaultPort() delegates to the custom implementation. */
@Test
public void getDefaultPort_custom() {
- when(mockChannelBuilderDefaultPortProvider.getDefaultPort()).thenReturn(DUMMY_PORT);
- assertEquals(DUMMY_PORT, builder.getDefaultPort());
+ int customPort = 43;
+ ChannelBuilderDefaultPortProvider mockChannelBuilderDefaultPortProvider = mock(
+ ChannelBuilderDefaultPortProvider.class);
+ when(mockChannelBuilderDefaultPortProvider.getDefaultPort()).thenReturn(customPort);
+
+ builder = new ManagedChannelImplBuilder(DUMMY_TARGET,
+ new UnsupportedClientTransportFactoryBuilder(),
+ mockChannelBuilderDefaultPortProvider);
+ assertEquals(customPort, builder.getDefaultPort());
verify(mockChannelBuilderDefaultPortProvider).getDefaultPort();
}
/** Test FixedPortProvider(int port). */
@Test
public void getDefaultPort_fixedPortProvider() {
- final ManagedChannelImplBuilder builderFixedPortProvider = new ManagedChannelImplBuilder(
- DUMMY_TARGET,
- mockClientTransportFactoryBuilder,
- new FixedPortProvider(DUMMY_PORT));
- assertEquals(DUMMY_PORT, builderFixedPortProvider.getDefaultPort());
+ int fixedPort = 43;
+ builder = new ManagedChannelImplBuilder(DUMMY_TARGET,
+ new UnsupportedClientTransportFactoryBuilder(), new FixedPortProvider(fixedPort));
+ assertEquals(fixedPort, builder.getDefaultPort());
+ }
+
+ @Test
+ public void executor_default() {
+ assertNotNull(builder.executorPool);
+ }
+
+ @Test
+ public void executor_normal() {
+ Executor executor = mock(Executor.class);
+ assertEquals(builder, builder.executor(executor));
+ assertEquals(executor, builder.executorPool.getObject());
+ }
+
+ @Test
+ public void executor_null() {
+ ObjectPool<? extends Executor> defaultValue = builder.executorPool;
+ builder.executor(mock(Executor.class));
+ assertEquals(builder, builder.executor(null));
+ assertEquals(defaultValue, builder.executorPool);
+ }
+
+ @Test
+ public void directExecutor() {
+ assertEquals(builder, builder.directExecutor());
+ assertEquals(MoreExecutors.directExecutor(), builder.executorPool.getObject());
+ }
+
+ @Test
+ public void offloadExecutor_normal() {
+ Executor executor = mock(Executor.class);
+ assertEquals(builder, builder.offloadExecutor(executor));
+ assertEquals(executor, builder.offloadExecutorPool.getObject());
+ }
+
+ @Test
+ public void offloadExecutor_null() {
+ ObjectPool<? extends Executor> defaultValue = builder.offloadExecutorPool;
+ builder.offloadExecutor(mock(Executor.class));
+ assertEquals(builder, builder.offloadExecutor(null));
+ assertEquals(defaultValue, builder.offloadExecutorPool);
+ }
+
+ @Test
+ public void nameResolverFactory_default() {
+ assertNotNull(builder.getNameResolverFactory());
+ }
+
+ @Test
+ @SuppressWarnings("deprecation")
+ public void nameResolverFactory_normal() {
+ NameResolver.Factory nameResolverFactory = mock(NameResolver.Factory.class);
+ assertEquals(builder, builder.nameResolverFactory(nameResolverFactory));
+ assertEquals(nameResolverFactory, builder.getNameResolverFactory());
+ }
+
+ @Test
+ @SuppressWarnings("deprecation")
+ public void nameResolverFactory_null() {
+ NameResolver.Factory defaultValue = builder.getNameResolverFactory();
+ builder.nameResolverFactory(mock(NameResolver.Factory.class));
+ assertEquals(builder, builder.nameResolverFactory(null));
+ assertEquals(defaultValue, builder.getNameResolverFactory());
+ }
+
+ @Test(expected = IllegalStateException.class)
+ @SuppressWarnings("deprecation")
+ public void nameResolverFactory_notAllowedWithDirectAddress() {
+ directAddressBuilder.nameResolverFactory(mock(NameResolver.Factory.class));
+ }
+
+ @Test
+ public void defaultLoadBalancingPolicy_default() {
+ assertEquals("pick_first", builder.defaultLbPolicy);
+ }
+
+ @Test
+ public void defaultLoadBalancingPolicy_normal() {
+ assertEquals(builder, builder.defaultLoadBalancingPolicy("magic_balancer"));
+ assertEquals("magic_balancer", builder.defaultLbPolicy);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void defaultLoadBalancingPolicy_null() {
+ builder.defaultLoadBalancingPolicy(null);
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void defaultLoadBalancingPolicy_notAllowedWithDirectAddress() {
+ directAddressBuilder.defaultLoadBalancingPolicy("magic_balancer");
+ }
+
+ @Test
+ public void fullStreamDecompression_default() {
+ assertFalse(builder.fullStreamDecompression);
+ }
+
+ @Test
+ public void fullStreamDecompression_enabled() {
+ assertEquals(builder, builder.enableFullStreamDecompression());
+ assertTrue(builder.fullStreamDecompression);
+ }
+
+ @Test
+ public void decompressorRegistry_default() {
+ assertNotNull(builder.decompressorRegistry);
+ }
+
+ @Test
+ public void decompressorRegistry_normal() {
+ DecompressorRegistry decompressorRegistry = DecompressorRegistry.emptyInstance();
+ assertNotEquals(decompressorRegistry, builder.decompressorRegistry);
+ assertEquals(builder, builder.decompressorRegistry(decompressorRegistry));
+ assertEquals(decompressorRegistry, builder.decompressorRegistry);
+ }
+
+ @Test
+ public void decompressorRegistry_null() {
+ DecompressorRegistry defaultValue = builder.decompressorRegistry;
+ assertEquals(builder, builder.decompressorRegistry(DecompressorRegistry.emptyInstance()));
+ assertNotEquals(defaultValue, builder.decompressorRegistry);
+ builder.decompressorRegistry(null);
+ assertEquals(defaultValue, builder.decompressorRegistry);
+ }
+
+ @Test
+ public void compressorRegistry_default() {
+ assertNotNull(builder.compressorRegistry);
+ }
+
+ @Test
+ public void compressorRegistry_normal() {
+ CompressorRegistry compressorRegistry = CompressorRegistry.newEmptyInstance();
+ assertNotEquals(compressorRegistry, builder.compressorRegistry);
+ assertEquals(builder, builder.compressorRegistry(compressorRegistry));
+ assertEquals(compressorRegistry, builder.compressorRegistry);
+ }
+
+ @Test
+ public void compressorRegistry_null() {
+ CompressorRegistry defaultValue = builder.compressorRegistry;
+ builder.compressorRegistry(CompressorRegistry.newEmptyInstance());
+ assertNotEquals(defaultValue, builder.compressorRegistry);
+ assertEquals(builder, builder.compressorRegistry(null));
+ assertEquals(defaultValue, builder.compressorRegistry);
+ }
+
+ @Test
+ public void userAgent_default() {
+ assertNull(builder.userAgent);
+ }
+
+ @Test
+ public void userAgent_normal() {
+ String userAgent = "user-agent/1";
+ assertEquals(builder, builder.userAgent(userAgent));
+ assertEquals(userAgent, builder.userAgent);
+ }
+
+ @Test
+ public void userAgent_null() {
+ assertEquals(builder, builder.userAgent(null));
+ assertNull(builder.userAgent);
+
+ builder.userAgent("user-agent/1");
+ builder.userAgent(null);
+ assertNull(builder.userAgent);
+ }
+
+ @Test
+ public void authorityIsReadable_default() {
+ when(mockClientTransportFactory.getScheduledExecutorService())
+ .thenReturn(clock.getScheduledExecutorService());
+ when(mockClientTransportFactoryBuilder.buildClientTransportFactory())
+ .thenReturn(mockClientTransportFactory);
+
+ builder = new ManagedChannelImplBuilder(DUMMY_AUTHORITY_VALID,
+ mockClientTransportFactoryBuilder, new FixedPortProvider(DUMMY_PORT));
+ ManagedChannel channel = grpcCleanupRule.register(builder.build());
+ assertEquals(DUMMY_AUTHORITY_VALID, channel.authority());
+ }
+
+ @Test
+ public void authorityIsReadable_overrideAuthority() {
+ String overrideAuthority = "best-authority";
+ when(mockClientTransportFactory.getScheduledExecutorService())
+ .thenReturn(clock.getScheduledExecutorService());
+ when(mockClientTransportFactoryBuilder.buildClientTransportFactory())
+ .thenReturn(mockClientTransportFactory);
+
+ builder = new ManagedChannelImplBuilder(DUMMY_TARGET,
+ mockClientTransportFactoryBuilder, new FixedPortProvider(DUMMY_PORT))
+ .overrideAuthority(overrideAuthority);
+ ManagedChannel channel = grpcCleanupRule.register(builder.build());
+ assertEquals(overrideAuthority, channel.authority());
+ }
+
+ @Test
+ public void overrideAuthority_default() {
+ assertNull(builder.getOverrideAuthority());
+ }
+
+ @Test
+ public void overrideAuthority_normal() {
+ String overrideAuthority = "best-authority";
+ assertEquals(builder, builder.overrideAuthority(overrideAuthority));
+ assertEquals(overrideAuthority, builder.getOverrideAuthority());
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void overrideAuthority_null() {
+ builder.overrideAuthority(null);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void overrideAuthority_invalid() {
+ builder.overrideAuthority("not_allowed");
+ }
+
+ @Test
+ public void overrideAuthority_getNameResolverFactory() {
+ assertNull(builder.getOverrideAuthority());
+ assertFalse(builder.getNameResolverFactory() instanceof OverrideAuthorityNameResolverFactory);
+ builder.overrideAuthority("google.com");
+ assertTrue(builder.getNameResolverFactory() instanceof OverrideAuthorityNameResolverFactory);
}
@Test
@@ -132,4 +400,202 @@
builder.disableCheckAuthority().enableCheckAuthority();
builder.checkAuthority(DUMMY_AUTHORITY_INVALID);
}
+
+ @Test
+ public void makeTargetStringForDirectAddress_scopedIpv6() throws Exception {
+ InetSocketAddress address = new InetSocketAddress("0:0:0:0:0:0:0:0%0", 10005);
+ assertEquals("/0:0:0:0:0:0:0:0%0:10005", address.toString());
+ String target = ManagedChannelImplBuilder.makeTargetStringForDirectAddress(address);
+ URI uri = new URI(target);
+ assertEquals("directaddress:////0:0:0:0:0:0:0:0%250:10005", target);
+ assertEquals(target, uri.toString());
+ }
+
+ @Test
+ public void getEffectiveInterceptors_default() {
+ builder.intercept(DUMMY_USER_INTERCEPTOR);
+ List<ClientInterceptor> effectiveInterceptors = builder.getEffectiveInterceptors();
+ assertEquals(3, effectiveInterceptors.size());
+ assertThat(effectiveInterceptors.get(0).getClass().getName())
+ .isEqualTo("io.grpc.census.CensusTracingModule$TracingClientInterceptor");
+ assertThat(effectiveInterceptors.get(1).getClass().getName())
+ .isEqualTo("io.grpc.census.CensusStatsModule$StatsClientInterceptor");
+ assertThat(effectiveInterceptors.get(2)).isSameInstanceAs(DUMMY_USER_INTERCEPTOR);
+ }
+
+ @Test
+ public void getEffectiveInterceptors_disableStats() {
+ builder.intercept(DUMMY_USER_INTERCEPTOR);
+ builder.setStatsEnabled(false);
+ List<ClientInterceptor> effectiveInterceptors = builder.getEffectiveInterceptors();
+ assertEquals(2, effectiveInterceptors.size());
+ assertThat(effectiveInterceptors.get(0).getClass().getName())
+ .isEqualTo("io.grpc.census.CensusTracingModule$TracingClientInterceptor");
+ assertThat(effectiveInterceptors.get(1)).isSameInstanceAs(DUMMY_USER_INTERCEPTOR);
+ }
+
+ @Test
+ public void getEffectiveInterceptors_disableTracing() {
+ builder.intercept(DUMMY_USER_INTERCEPTOR);
+ builder.setTracingEnabled(false);
+ List<ClientInterceptor> effectiveInterceptors = builder.getEffectiveInterceptors();
+ assertEquals(2, effectiveInterceptors.size());
+ assertThat(effectiveInterceptors.get(0).getClass().getName())
+ .isEqualTo("io.grpc.census.CensusStatsModule$StatsClientInterceptor");
+ assertThat(effectiveInterceptors.get(1)).isSameInstanceAs(DUMMY_USER_INTERCEPTOR);
+ }
+
+ @Test
+ public void getEffectiveInterceptors_disableBoth() {
+ builder.intercept(DUMMY_USER_INTERCEPTOR);
+ builder.setStatsEnabled(false);
+ builder.setTracingEnabled(false);
+ List<ClientInterceptor> effectiveInterceptors = builder.getEffectiveInterceptors();
+ assertThat(effectiveInterceptors).containsExactly(DUMMY_USER_INTERCEPTOR);
+ }
+
+ @Test
+ public void idleTimeout() {
+ assertEquals(ManagedChannelImplBuilder.IDLE_MODE_DEFAULT_TIMEOUT_MILLIS,
+ builder.idleTimeoutMillis);
+
+ builder.idleTimeout(Long.MAX_VALUE, TimeUnit.DAYS);
+ assertEquals(ManagedChannelImpl.IDLE_TIMEOUT_MILLIS_DISABLE, builder.idleTimeoutMillis);
+
+ builder.idleTimeout(ManagedChannelImplBuilder.IDLE_MODE_MAX_TIMEOUT_DAYS,
+ TimeUnit.DAYS);
+ assertEquals(ManagedChannelImpl.IDLE_TIMEOUT_MILLIS_DISABLE, builder.idleTimeoutMillis);
+
+ try {
+ builder.idleTimeout(0, TimeUnit.SECONDS);
+ fail("Should throw");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+
+ builder.idleTimeout(1, TimeUnit.NANOSECONDS);
+ assertEquals(ManagedChannelImplBuilder.IDLE_MODE_MIN_TIMEOUT_MILLIS,
+ builder.idleTimeoutMillis);
+
+ builder.idleTimeout(30, TimeUnit.SECONDS);
+ assertEquals(TimeUnit.SECONDS.toMillis(30), builder.idleTimeoutMillis);
+ }
+
+ @Test
+ public void maxRetryAttempts() {
+ assertEquals(5, builder.maxRetryAttempts);
+
+ builder.maxRetryAttempts(3);
+ assertEquals(3, builder.maxRetryAttempts);
+ }
+
+ @Test
+ public void maxHedgedAttempts() {
+ assertEquals(5, builder.maxHedgedAttempts);
+
+ builder.maxHedgedAttempts(3);
+ assertEquals(3, builder.maxHedgedAttempts);
+ }
+
+ @Test
+ public void retryBufferSize() {
+ assertEquals(1L << 24, builder.retryBufferSize);
+
+ builder.retryBufferSize(3456L);
+ assertEquals(3456L, builder.retryBufferSize);
+ }
+
+ @Test
+ public void perRpcBufferLimit() {
+ assertEquals(1L << 20, builder.perRpcBufferLimit);
+
+ builder.perRpcBufferLimit(3456L);
+ assertEquals(3456L, builder.perRpcBufferLimit);
+ }
+
+ @Test
+ public void retryBufferSizeInvalidArg() {
+ thrown.expect(IllegalArgumentException.class);
+ builder.retryBufferSize(0L);
+ }
+
+ @Test
+ public void perRpcBufferLimitInvalidArg() {
+ thrown.expect(IllegalArgumentException.class);
+ builder.perRpcBufferLimit(0L);
+ }
+
+ @Test
+ public void disableRetry() {
+ builder.enableRetry();
+ assertTrue(builder.retryEnabled);
+
+ builder.disableRetry();
+ assertFalse(builder.retryEnabled);
+
+ builder.enableRetry();
+ assertTrue(builder.retryEnabled);
+
+ builder.disableRetry();
+ assertFalse(builder.retryEnabled);
+ }
+
+ @Test
+ public void defaultServiceConfig_nullKey() {
+ Map<String, Object> config = new HashMap<>();
+ config.put(null, "val");
+
+ thrown.expect(IllegalArgumentException.class);
+ builder.defaultServiceConfig(config);
+ }
+
+ @Test
+ public void defaultServiceConfig_intKey() {
+ Map<Integer, Object> subConfig = new HashMap<>();
+ subConfig.put(3, "val");
+ Map<String, Object> config = new HashMap<>();
+ config.put("key", subConfig);
+
+ thrown.expect(IllegalArgumentException.class);
+ builder.defaultServiceConfig(config);
+ }
+
+ @Test
+ public void defaultServiceConfig_intValue() {
+ Map<String, Object> config = new HashMap<>();
+ config.put("key", 3);
+
+ thrown.expect(IllegalArgumentException.class);
+ builder.defaultServiceConfig(config);
+ }
+
+ @Test
+ public void defaultServiceConfig_nested() {
+ Map<String, Object> config = new HashMap<>();
+ List<Object> list1 = new ArrayList<>();
+ list1.add(123D);
+ list1.add(null);
+ list1.add(true);
+ list1.add("str");
+ Map<String, Object> map2 = new HashMap<>();
+ map2.put("key2", false);
+ map2.put("key3", null);
+ map2.put("key4", Collections.singletonList("v4"));
+ map2.put("key4", 3.14D);
+ map2.put("key5", new HashMap<String, Object>());
+ list1.add(map2);
+ config.put("key1", list1);
+
+ builder.defaultServiceConfig(config);
+
+ assertThat(builder.defaultServiceConfig).containsExactlyEntriesIn(config);
+ }
+
+ @Test
+ public void disableNameResolverServiceConfig() {
+ assertThat(builder.lookUpServiceConfig).isTrue();
+
+ builder.disableServiceConfigLookUp();
+ assertThat(builder.lookUpServiceConfig).isFalse();
+ }
}
diff --git a/core/src/test/java/io/grpc/internal/ManagedChannelImplIdlenessTest.java b/core/src/test/java/io/grpc/internal/ManagedChannelImplIdlenessTest.java
index c551d26..a2a2925 100644
--- a/core/src/test/java/io/grpc/internal/ManagedChannelImplIdlenessTest.java
+++ b/core/src/test/java/io/grpc/internal/ManagedChannelImplIdlenessTest.java
@@ -62,7 +62,7 @@
import io.grpc.Status;
import io.grpc.StringMarshaller;
import io.grpc.internal.FakeClock.ScheduledTask;
-import io.grpc.internal.ManagedChannelImplBuilder.ClientTransportFactoryBuilder;
+import io.grpc.internal.ManagedChannelImplBuilder.UnsupportedClientTransportFactoryBuilder;
import io.grpc.internal.TestUtils.MockClientTransportInfo;
import java.net.SocketAddress;
import java.net.URI;
@@ -161,12 +161,7 @@
.thenReturn(timer.getScheduledExecutorService());
ManagedChannelImplBuilder builder = new ManagedChannelImplBuilder("fake://target",
- new ClientTransportFactoryBuilder() {
- @Override public ClientTransportFactory buildClientTransportFactory() {
- throw new UnsupportedOperationException();
- }
- },
- null);
+ new UnsupportedClientTransportFactoryBuilder(), null);
builder
.nameResolverFactory(mockNameResolverFactory)
diff --git a/core/src/test/java/io/grpc/internal/ManagedChannelImplTest.java b/core/src/test/java/io/grpc/internal/ManagedChannelImplTest.java
index 5a7933e..97208ae 100644
--- a/core/src/test/java/io/grpc/internal/ManagedChannelImplTest.java
+++ b/core/src/test/java/io/grpc/internal/ManagedChannelImplTest.java
@@ -109,6 +109,7 @@
import io.grpc.internal.ManagedChannelImpl.ScParser;
import io.grpc.internal.ManagedChannelImplBuilder.ClientTransportFactoryBuilder;
import io.grpc.internal.ManagedChannelImplBuilder.FixedPortProvider;
+import io.grpc.internal.ManagedChannelImplBuilder.UnsupportedClientTransportFactoryBuilder;
import io.grpc.internal.ServiceConfigUtil.PolicySelection;
import io.grpc.internal.TestUtils.MockClientTransportInfo;
import io.grpc.stub.ClientCalls;
@@ -328,13 +329,8 @@
.thenReturn(balancerRpcExecutor.getScheduledExecutorService());
channelBuilder = new ManagedChannelImplBuilder(TARGET,
- new ClientTransportFactoryBuilder() {
- @Override
- public ClientTransportFactory buildClientTransportFactory() {
- throw new UnsupportedOperationException();
- }
- },
- new FixedPortProvider(DEFAULT_PORT));
+ new UnsupportedClientTransportFactoryBuilder(), new FixedPortProvider(DEFAULT_PORT));
+
channelBuilder
.nameResolverFactory(new FakeNameResolverFactory.Builder(expectedUri).build())
.defaultLoadBalancingPolicy(MOCK_POLICY_NAME)
diff --git a/core/src/test/java/io/grpc/internal/ServiceConfigErrorHandlingTest.java b/core/src/test/java/io/grpc/internal/ServiceConfigErrorHandlingTest.java
index 49f094a..16c6f3b 100644
--- a/core/src/test/java/io/grpc/internal/ServiceConfigErrorHandlingTest.java
+++ b/core/src/test/java/io/grpc/internal/ServiceConfigErrorHandlingTest.java
@@ -46,8 +46,8 @@
import io.grpc.NameResolver;
import io.grpc.NameResolver.ConfigOrError;
import io.grpc.Status;
-import io.grpc.internal.ManagedChannelImplBuilder.ClientTransportFactoryBuilder;
import io.grpc.internal.ManagedChannelImplBuilder.FixedPortProvider;
+import io.grpc.internal.ManagedChannelImplBuilder.UnsupportedClientTransportFactoryBuilder;
import java.net.SocketAddress;
import java.net.URI;
import java.util.ArrayList;
@@ -200,13 +200,7 @@
when(executorPool.getObject()).thenReturn(executor.getScheduledExecutorService());
channelBuilder = new ManagedChannelImplBuilder(TARGET,
- new ClientTransportFactoryBuilder() {
- @Override
- public ClientTransportFactory buildClientTransportFactory() {
- throw new UnsupportedOperationException();
- }
- },
- new FixedPortProvider(DEFAULT_PORT));
+ new UnsupportedClientTransportFactoryBuilder(), new FixedPortProvider(DEFAULT_PORT));
channelBuilder
.nameResolverFactory(new FakeNameResolverFactory.Builder(expectedUri).build())