Search in sources :

Example 1 with ResolvedServerInfoGroup

use of io.grpc.ResolvedServerInfoGroup in project grpc-java by grpc.

the class ManagedChannelImplTest method informationPropagatedToNewStreamAndCallCredentials.

/**
   * Test that information such as the Call's context, MethodDescriptor, authority, executor are
   * propagated to newStream() and applyRequestMetadata().
   */
@Test
public void informationPropagatedToNewStreamAndCallCredentials() {
    ResolvedServerInfoGroup serverInfoGroup = ResolvedServerInfoGroup.builder().add(server).build();
    createChannel(new FakeNameResolverFactory(true), NO_INTERCEPTOR);
    CallOptions callOptions = CallOptions.DEFAULT.withCallCredentials(creds);
    final Context.Key<String> testKey = Context.key("testing");
    Context ctx = Context.current().withValue(testKey, "testValue");
    final LinkedList<Context> credsApplyContexts = new LinkedList<Context>();
    final LinkedList<Context> newStreamContexts = new LinkedList<Context>();
    doAnswer(new Answer<Void>() {

        @Override
        public Void answer(InvocationOnMock in) throws Throwable {
            credsApplyContexts.add(Context.current());
            return null;
        }
    }).when(creds).applyRequestMetadata(any(MethodDescriptor.class), any(Attributes.class), any(Executor.class), any(MetadataApplier.class));
    // First call will be on delayed transport.  Only newCall() is run within the expected context,
    // so that we can verify that the context is explicitly attached before calling newStream() and
    // applyRequestMetadata(), which happens after we detach the context from the thread.
    Context origCtx = ctx.attach();
    assertEquals("testValue", testKey.get());
    ClientCall<String, Integer> call = channel.newCall(method, callOptions);
    ctx.detach(origCtx);
    assertNull(testKey.get());
    call.start(mockCallListener, new Metadata());
    // Simulate name resolution results
    Subchannel subchannel = helper.createSubchannel(serverInfoGroup.toEquivalentAddressGroup(), Attributes.EMPTY);
    subchannel.requestConnection();
    verify(mockTransportFactory).newClientTransport(same(socketAddress), eq(authority), eq(userAgent));
    MockClientTransportInfo transportInfo = transports.poll();
    final ConnectionClientTransport transport = transportInfo.transport;
    when(transport.getAttributes()).thenReturn(Attributes.EMPTY);
    doAnswer(new Answer<ClientStream>() {

        @Override
        public ClientStream answer(InvocationOnMock in) throws Throwable {
            newStreamContexts.add(Context.current());
            return mock(ClientStream.class);
        }
    }).when(transport).newStream(any(MethodDescriptor.class), any(Metadata.class), any(CallOptions.class), any(StatsTraceContext.class));
    verify(creds, never()).applyRequestMetadata(any(MethodDescriptor.class), any(Attributes.class), any(Executor.class), any(MetadataApplier.class));
    // applyRequestMetadata() is called after the transport becomes ready.
    transportInfo.listener.transportReady();
    when(mockPicker.pickSubchannel(any(PickSubchannelArgs.class))).thenReturn(PickResult.withSubchannel(subchannel));
    helper.updatePicker(mockPicker);
    executor.runDueTasks();
    ArgumentCaptor<Attributes> attrsCaptor = ArgumentCaptor.forClass(Attributes.class);
    ArgumentCaptor<MetadataApplier> applierCaptor = ArgumentCaptor.forClass(MetadataApplier.class);
    verify(creds).applyRequestMetadata(same(method), attrsCaptor.capture(), same(executor.getScheduledExecutorService()), applierCaptor.capture());
    assertEquals("testValue", testKey.get(credsApplyContexts.poll()));
    assertEquals(authority, attrsCaptor.getValue().get(CallCredentials.ATTR_AUTHORITY));
    assertEquals(SecurityLevel.NONE, attrsCaptor.getValue().get(CallCredentials.ATTR_SECURITY_LEVEL));
    verify(transport, never()).newStream(any(MethodDescriptor.class), any(Metadata.class), any(CallOptions.class), any(StatsTraceContext.class));
    // newStream() is called after apply() is called
    applierCaptor.getValue().apply(new Metadata());
    verify(transport).newStream(same(method), any(Metadata.class), same(callOptions), any(StatsTraceContext.class));
    assertEquals("testValue", testKey.get(newStreamContexts.poll()));
    // The context should not live beyond the scope of newStream() and applyRequestMetadata()
    assertNull(testKey.get());
    // Second call will not be on delayed transport
    origCtx = ctx.attach();
    call = channel.newCall(method, callOptions);
    ctx.detach(origCtx);
    call.start(mockCallListener, new Metadata());
    verify(creds, times(2)).applyRequestMetadata(same(method), attrsCaptor.capture(), same(executor.getScheduledExecutorService()), applierCaptor.capture());
    assertEquals("testValue", testKey.get(credsApplyContexts.poll()));
    assertEquals(authority, attrsCaptor.getValue().get(CallCredentials.ATTR_AUTHORITY));
    assertEquals(SecurityLevel.NONE, attrsCaptor.getValue().get(CallCredentials.ATTR_SECURITY_LEVEL));
    // This is from the first call
    verify(transport).newStream(any(MethodDescriptor.class), any(Metadata.class), any(CallOptions.class), any(StatsTraceContext.class));
    // Still, newStream() is called after apply() is called
    applierCaptor.getValue().apply(new Metadata());
    verify(transport, times(2)).newStream(same(method), any(Metadata.class), same(callOptions), any(StatsTraceContext.class));
    assertEquals("testValue", testKey.get(newStreamContexts.poll()));
    assertNull(testKey.get());
}
Also used : Attributes(io.grpc.Attributes) Metadata(io.grpc.Metadata) ResolvedServerInfoGroup(io.grpc.ResolvedServerInfoGroup) CallOptions(io.grpc.CallOptions) Matchers.anyString(org.mockito.Matchers.anyString) Executor(java.util.concurrent.Executor) PickSubchannelArgs(io.grpc.LoadBalancer.PickSubchannelArgs) Context(io.grpc.Context) MetadataApplier(io.grpc.CallCredentials.MetadataApplier) MockClientTransportInfo(io.grpc.internal.TestUtils.MockClientTransportInfo) MethodDescriptor(io.grpc.MethodDescriptor) LinkedList(java.util.LinkedList) InvocationOnMock(org.mockito.invocation.InvocationOnMock) Subchannel(io.grpc.LoadBalancer.Subchannel) Test(org.junit.Test)

Example 2 with ResolvedServerInfoGroup

use of io.grpc.ResolvedServerInfoGroup in project grpc-java by grpc.

the class ManagedChannelImplTest method firstResolvedServerFailedToConnect.

/**
   * Verify that if the first resolved address points to a server that cannot be connected, the call
   * will end up with the second address which works.
   */
@Test
public void firstResolvedServerFailedToConnect() throws Exception {
    final SocketAddress goodAddress = new SocketAddress() {

        @Override
        public String toString() {
            return "goodAddress";
        }
    };
    final SocketAddress badAddress = new SocketAddress() {

        @Override
        public String toString() {
            return "badAddress";
        }
    };
    final ResolvedServerInfo goodServer = new ResolvedServerInfo(goodAddress, Attributes.EMPTY);
    final ResolvedServerInfo badServer = new ResolvedServerInfo(badAddress, Attributes.EMPTY);
    InOrder inOrder = inOrder(mockLoadBalancer);
    ResolvedServerInfoGroup serverInfoGroup = ResolvedServerInfoGroup.builder().add(badServer).add(goodServer).build();
    FakeNameResolverFactory nameResolverFactory = new FakeNameResolverFactory(serverInfoGroup.getResolvedServerInfoList());
    createChannel(nameResolverFactory, NO_INTERCEPTOR);
    // Start the call
    ClientCall<String, Integer> call = channel.newCall(method, CallOptions.DEFAULT);
    Metadata headers = new Metadata();
    call.start(mockCallListener, headers);
    executor.runDueTasks();
    // Simulate name resolution results
    inOrder.verify(mockLoadBalancer).handleResolvedAddresses(eq(Arrays.asList(serverInfoGroup)), eq(Attributes.EMPTY));
    Subchannel subchannel = helper.createSubchannel(serverInfoGroup.toEquivalentAddressGroup(), Attributes.EMPTY);
    when(mockPicker.pickSubchannel(any(PickSubchannelArgs.class))).thenReturn(PickResult.withSubchannel(subchannel));
    subchannel.requestConnection();
    inOrder.verify(mockLoadBalancer).handleSubchannelState(same(subchannel), stateInfoCaptor.capture());
    assertEquals(CONNECTING, stateInfoCaptor.getValue().getState());
    // The channel will starts with the first address (badAddress)
    verify(mockTransportFactory).newClientTransport(same(badAddress), any(String.class), any(String.class));
    verify(mockTransportFactory, times(0)).newClientTransport(same(goodAddress), any(String.class), any(String.class));
    MockClientTransportInfo badTransportInfo = transports.poll();
    // Which failed to connect
    badTransportInfo.listener.transportShutdown(Status.UNAVAILABLE);
    inOrder.verifyNoMoreInteractions();
    // The channel then try the second address (goodAddress)
    verify(mockTransportFactory).newClientTransport(same(goodAddress), any(String.class), any(String.class));
    MockClientTransportInfo goodTransportInfo = transports.poll();
    when(goodTransportInfo.transport.newStream(any(MethodDescriptor.class), any(Metadata.class), any(CallOptions.class), any(StatsTraceContext.class))).thenReturn(mock(ClientStream.class));
    goodTransportInfo.listener.transportReady();
    inOrder.verify(mockLoadBalancer).handleSubchannelState(same(subchannel), stateInfoCaptor.capture());
    assertEquals(READY, stateInfoCaptor.getValue().getState());
    // A typical LoadBalancer will call this once the subchannel becomes READY
    helper.updatePicker(mockPicker);
    // Delayed transport uses the app executor to create real streams.
    executor.runDueTasks();
    verify(goodTransportInfo.transport).newStream(same(method), same(headers), same(CallOptions.DEFAULT), any(StatsTraceContext.class));
    // The bad transport was never used.
    verify(badTransportInfo.transport, times(0)).newStream(any(MethodDescriptor.class), any(Metadata.class), any(CallOptions.class), any(StatsTraceContext.class));
}
Also used : InOrder(org.mockito.InOrder) Metadata(io.grpc.Metadata) MockClientTransportInfo(io.grpc.internal.TestUtils.MockClientTransportInfo) ResolvedServerInfo(io.grpc.ResolvedServerInfo) ResolvedServerInfoGroup(io.grpc.ResolvedServerInfoGroup) Matchers.anyString(org.mockito.Matchers.anyString) CallOptions(io.grpc.CallOptions) MethodDescriptor(io.grpc.MethodDescriptor) Subchannel(io.grpc.LoadBalancer.Subchannel) PickSubchannelArgs(io.grpc.LoadBalancer.PickSubchannelArgs) SocketAddress(java.net.SocketAddress) Test(org.junit.Test)

Example 3 with ResolvedServerInfoGroup

use of io.grpc.ResolvedServerInfoGroup in project grpc-java by grpc.

the class ManagedChannelImplTest method loadBalancerThrowsInHandleResolvedAddresses.

@Test
public void loadBalancerThrowsInHandleResolvedAddresses() {
    RuntimeException ex = new RuntimeException("simulated");
    // Delay the success of name resolution until allResolved() is called
    FakeNameResolverFactory nameResolverFactory = new FakeNameResolverFactory(false);
    createChannel(nameResolverFactory, NO_INTERCEPTOR);
    verify(mockLoadBalancerFactory).newLoadBalancer(any(Helper.class));
    doThrow(ex).when(mockLoadBalancer).handleResolvedAddresses(Matchers.<List<ResolvedServerInfoGroup>>anyObject(), any(Attributes.class));
    // NameResolver returns addresses.
    nameResolverFactory.allResolved();
    // The LoadBalancer will receive the error that it has thrown.
    verify(mockLoadBalancer).handleNameResolutionError(statusCaptor.capture());
    Status status = statusCaptor.getValue();
    assertSame(Status.Code.INTERNAL, status.getCode());
    assertSame(ex, status.getCause());
}
Also used : Helper(io.grpc.LoadBalancer.Helper) Status(io.grpc.Status) Attributes(io.grpc.Attributes) ResolvedServerInfoGroup(io.grpc.ResolvedServerInfoGroup) Test(org.junit.Test)

Example 4 with ResolvedServerInfoGroup

use of io.grpc.ResolvedServerInfoGroup in project grpc-java by grpc.

the class ManagedChannelImplTest method allServersFailedToConnect.

/**
   * Verify that if all resolved addresses failed to connect, a fail-fast call will fail, while a
   * wait-for-ready call will still be buffered.
   */
@Test
public void allServersFailedToConnect() throws Exception {
    final SocketAddress addr1 = new SocketAddress() {

        @Override
        public String toString() {
            return "addr1";
        }
    };
    final SocketAddress addr2 = new SocketAddress() {

        @Override
        public String toString() {
            return "addr2";
        }
    };
    final ResolvedServerInfo server1 = new ResolvedServerInfo(addr1, Attributes.EMPTY);
    final ResolvedServerInfo server2 = new ResolvedServerInfo(addr2, Attributes.EMPTY);
    InOrder inOrder = inOrder(mockLoadBalancer);
    ResolvedServerInfoGroup serverInfoGroup = ResolvedServerInfoGroup.builder().add(server1).add(server2).build();
    FakeNameResolverFactory nameResolverFactory = new FakeNameResolverFactory(serverInfoGroup.getResolvedServerInfoList());
    createChannel(nameResolverFactory, NO_INTERCEPTOR);
    // Start a wait-for-ready call
    ClientCall<String, Integer> call = channel.newCall(method, CallOptions.DEFAULT.withWaitForReady());
    Metadata headers = new Metadata();
    call.start(mockCallListener, headers);
    // ... and a fail-fast call
    ClientCall<String, Integer> call2 = channel.newCall(method, CallOptions.DEFAULT.withoutWaitForReady());
    call2.start(mockCallListener2, headers);
    executor.runDueTasks();
    // Simulate name resolution results
    inOrder.verify(mockLoadBalancer).handleResolvedAddresses(eq(Arrays.asList(serverInfoGroup)), eq(Attributes.EMPTY));
    Subchannel subchannel = helper.createSubchannel(serverInfoGroup.toEquivalentAddressGroup(), Attributes.EMPTY);
    when(mockPicker.pickSubchannel(any(PickSubchannelArgs.class))).thenReturn(PickResult.withSubchannel(subchannel));
    subchannel.requestConnection();
    inOrder.verify(mockLoadBalancer).handleSubchannelState(same(subchannel), stateInfoCaptor.capture());
    assertEquals(CONNECTING, stateInfoCaptor.getValue().getState());
    // Connecting to server1, which will fail
    verify(mockTransportFactory).newClientTransport(same(addr1), any(String.class), any(String.class));
    verify(mockTransportFactory, times(0)).newClientTransport(same(addr2), any(String.class), any(String.class));
    MockClientTransportInfo transportInfo1 = transports.poll();
    transportInfo1.listener.transportShutdown(Status.UNAVAILABLE);
    // Connecting to server2, which will fail too
    verify(mockTransportFactory).newClientTransport(same(addr2), any(String.class), any(String.class));
    MockClientTransportInfo transportInfo2 = transports.poll();
    Status server2Error = Status.UNAVAILABLE.withDescription("Server2 failed to connect");
    transportInfo2.listener.transportShutdown(server2Error);
    // ... which makes the subchannel enter TRANSIENT_FAILURE. The last error Status is propagated
    // to LoadBalancer.
    inOrder.verify(mockLoadBalancer).handleSubchannelState(same(subchannel), stateInfoCaptor.capture());
    assertEquals(TRANSIENT_FAILURE, stateInfoCaptor.getValue().getState());
    assertSame(server2Error, stateInfoCaptor.getValue().getStatus());
    // A typical LoadBalancer would create a picker with error
    SubchannelPicker picker2 = mock(SubchannelPicker.class);
    when(picker2.pickSubchannel(any(PickSubchannelArgs.class))).thenReturn(PickResult.withError(server2Error));
    helper.updatePicker(picker2);
    executor.runDueTasks();
    // ... which fails the fail-fast call
    verify(mockCallListener2).onClose(same(server2Error), any(Metadata.class));
    // ... while the wait-for-ready call stays
    verifyNoMoreInteractions(mockCallListener);
    // No real stream was ever created
    verify(transportInfo1.transport, times(0)).newStream(any(MethodDescriptor.class), any(Metadata.class));
    verify(transportInfo2.transport, times(0)).newStream(any(MethodDescriptor.class), any(Metadata.class));
}
Also used : Status(io.grpc.Status) InOrder(org.mockito.InOrder) Metadata(io.grpc.Metadata) MockClientTransportInfo(io.grpc.internal.TestUtils.MockClientTransportInfo) ResolvedServerInfo(io.grpc.ResolvedServerInfo) ResolvedServerInfoGroup(io.grpc.ResolvedServerInfoGroup) Matchers.anyString(org.mockito.Matchers.anyString) MethodDescriptor(io.grpc.MethodDescriptor) SubchannelPicker(io.grpc.LoadBalancer.SubchannelPicker) Subchannel(io.grpc.LoadBalancer.Subchannel) PickSubchannelArgs(io.grpc.LoadBalancer.PickSubchannelArgs) SocketAddress(java.net.SocketAddress) Test(org.junit.Test)

Example 5 with ResolvedServerInfoGroup

use of io.grpc.ResolvedServerInfoGroup in project grpc-java by grpc.

the class GrpclbLoadBalancerTest method delegatingPickFirstThenNameResolutionFails.

@Test
public void delegatingPickFirstThenNameResolutionFails() {
    List<ResolvedServerInfoGroup> resolvedServers = createResolvedServerInfoGroupList(false);
    Attributes resolutionAttrs = Attributes.newBuilder().set(RESOLUTION_ATTR, "yeah").build();
    deliverResolvedAddresses(resolvedServers, resolutionAttrs);
    verify(pickFirstBalancerFactory).newLoadBalancer(helper);
    verify(pickFirstBalancer).handleResolvedAddresses(eq(resolvedServers), eq(resolutionAttrs));
    // Then let name resolution fail.  The error will be passed directly to the delegate.
    Status error = Status.NOT_FOUND.withDescription("www.google.com not found");
    deliverNameResolutionError(error);
    verify(pickFirstBalancer).handleNameResolutionError(error);
    verify(helper, never()).updatePicker(any(SubchannelPicker.class));
    verifyNoMoreInteractions(roundRobinBalancerFactory);
    verifyNoMoreInteractions(roundRobinBalancer);
}
Also used : Status(io.grpc.Status) SubchannelPicker(io.grpc.LoadBalancer.SubchannelPicker) Attributes(io.grpc.Attributes) ResolvedServerInfoGroup(io.grpc.ResolvedServerInfoGroup) Test(org.junit.Test)

Aggregations

ResolvedServerInfoGroup (io.grpc.ResolvedServerInfoGroup)16 Test (org.junit.Test)13 Attributes (io.grpc.Attributes)12 Status (io.grpc.Status)9 EquivalentAddressGroup (io.grpc.EquivalentAddressGroup)7 InOrder (org.mockito.InOrder)6 Subchannel (io.grpc.LoadBalancer.Subchannel)5 ResolvedServerInfo (io.grpc.ResolvedServerInfo)5 ErrorPicker (io.grpc.grpclb.GrpclbLoadBalancer.ErrorPicker)5 SubchannelPicker (io.grpc.LoadBalancer.SubchannelPicker)4 SocketAddress (java.net.SocketAddress)4 Helper (io.grpc.LoadBalancer.Helper)3 PickSubchannelArgs (io.grpc.LoadBalancer.PickSubchannelArgs)3 ManagedChannel (io.grpc.ManagedChannel)3 Metadata (io.grpc.Metadata)3 MethodDescriptor (io.grpc.MethodDescriptor)3 MockClientTransportInfo (io.grpc.internal.TestUtils.MockClientTransportInfo)3 Matchers.anyString (org.mockito.Matchers.anyString)3 CallOptions (io.grpc.CallOptions)2 ArrayList (java.util.ArrayList)2