Search in sources :

Example 11 with Metadata

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

the class ManagedChannelImplTest method callOptionsExecutor.

@Test
public void callOptionsExecutor() {
    Metadata headers = new Metadata();
    ClientStream mockStream = mock(ClientStream.class);
    FakeClock callExecutor = new FakeClock();
    createChannel(new FakeNameResolverFactory(true), NO_INTERCEPTOR);
    // Start a call with a call executor
    CallOptions options = CallOptions.DEFAULT.withExecutor(callExecutor.getScheduledExecutorService());
    ClientCall<String, Integer> call = channel.newCall(method, options);
    call.start(mockCallListener, headers);
    // Make the transport available
    Subchannel subchannel = helper.createSubchannel(addressGroup, Attributes.EMPTY);
    verify(mockTransportFactory, never()).newClientTransport(any(SocketAddress.class), any(String.class), any(String.class));
    subchannel.requestConnection();
    verify(mockTransportFactory).newClientTransport(any(SocketAddress.class), any(String.class), any(String.class));
    MockClientTransportInfo transportInfo = transports.poll();
    ConnectionClientTransport mockTransport = transportInfo.transport;
    ManagedClientTransport.Listener transportListener = transportInfo.listener;
    when(mockTransport.newStream(same(method), same(headers), any(CallOptions.class), any(StatsTraceContext.class))).thenReturn(mockStream);
    transportListener.transportReady();
    when(mockPicker.pickSubchannel(any(PickSubchannelArgs.class))).thenReturn(PickResult.withSubchannel(subchannel));
    assertEquals(0, callExecutor.numPendingTasks());
    helper.updatePicker(mockPicker);
    // Real streams are started in the call executor if they were previously buffered.
    assertEquals(1, callExecutor.runDueTasks());
    verify(mockTransport).newStream(same(method), same(headers), same(options), any(StatsTraceContext.class));
    verify(mockStream).start(streamListenerCaptor.capture());
    // Call listener callbacks are also run in the call executor
    ClientStreamListener streamListener = streamListenerCaptor.getValue();
    Metadata trailers = new Metadata();
    assertEquals(0, callExecutor.numPendingTasks());
    streamListener.closed(Status.CANCELLED, trailers);
    verify(mockCallListener, never()).onClose(same(Status.CANCELLED), same(trailers));
    assertEquals(1, callExecutor.runDueTasks());
    verify(mockCallListener).onClose(same(Status.CANCELLED), same(trailers));
}
Also used : Metadata(io.grpc.Metadata) MockClientTransportInfo(io.grpc.internal.TestUtils.MockClientTransportInfo) CallOptions(io.grpc.CallOptions) Matchers.anyString(org.mockito.Matchers.anyString) Subchannel(io.grpc.LoadBalancer.Subchannel) PickSubchannelArgs(io.grpc.LoadBalancer.PickSubchannelArgs) SocketAddress(java.net.SocketAddress) Test(org.junit.Test)

Example 12 with Metadata

use of io.grpc.Metadata 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 13 with Metadata

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

the class ManagedChannelImplTest method oobchannels.

@Test
public void oobchannels() {
    createChannel(new FakeNameResolverFactory(true), NO_INTERCEPTOR);
    ManagedChannel oob1 = helper.createOobChannel(addressGroup, "oob1authority");
    ManagedChannel oob2 = helper.createOobChannel(addressGroup, "oob2authority");
    verify(oobExecutorPool, times(2)).getObject();
    assertEquals("oob1authority", oob1.authority());
    assertEquals("oob2authority", oob2.authority());
    // OOB channels create connections lazily.  A new call will initiate the connection.
    Metadata headers = new Metadata();
    ClientCall<String, Integer> call = oob1.newCall(method, CallOptions.DEFAULT);
    call.start(mockCallListener, headers);
    verify(mockTransportFactory).newClientTransport(socketAddress, "oob1authority", userAgent);
    MockClientTransportInfo transportInfo = transports.poll();
    assertNotNull(transportInfo);
    assertEquals(0, oobExecutor.numPendingTasks());
    transportInfo.listener.transportReady();
    assertEquals(1, oobExecutor.runDueTasks());
    verify(transportInfo.transport).newStream(same(method), same(headers), same(CallOptions.DEFAULT), any(StatsTraceContext.class));
    // The transport goes away
    transportInfo.listener.transportShutdown(Status.UNAVAILABLE);
    transportInfo.listener.transportTerminated();
    // A new call will trigger a new transport
    ClientCall<String, Integer> call2 = oob1.newCall(method, CallOptions.DEFAULT);
    call2.start(mockCallListener2, headers);
    ClientCall<String, Integer> call3 = oob1.newCall(method, CallOptions.DEFAULT.withWaitForReady());
    call3.start(mockCallListener3, headers);
    verify(mockTransportFactory, times(2)).newClientTransport(socketAddress, "oob1authority", userAgent);
    transportInfo = transports.poll();
    assertNotNull(transportInfo);
    // This transport fails
    Status transportError = Status.UNAVAILABLE.withDescription("Connection refused");
    assertEquals(0, oobExecutor.numPendingTasks());
    transportInfo.listener.transportShutdown(transportError);
    assertTrue(oobExecutor.runDueTasks() > 0);
    // Fail-fast RPC will fail, while wait-for-ready RPC will still be pending
    verify(mockCallListener2).onClose(same(transportError), any(Metadata.class));
    verify(mockCallListener3, never()).onClose(any(Status.class), any(Metadata.class));
    // Shutdown
    assertFalse(oob1.isShutdown());
    assertFalse(oob2.isShutdown());
    oob1.shutdown();
    verify(oobExecutorPool, never()).returnObject(anyObject());
    oob2.shutdownNow();
    assertTrue(oob1.isShutdown());
    assertTrue(oob2.isShutdown());
    assertTrue(oob2.isTerminated());
    verify(oobExecutorPool).returnObject(oobExecutor.getScheduledExecutorService());
    // New RPCs will be rejected.
    assertEquals(0, oobExecutor.numPendingTasks());
    ClientCall<String, Integer> call4 = oob1.newCall(method, CallOptions.DEFAULT);
    ClientCall<String, Integer> call5 = oob2.newCall(method, CallOptions.DEFAULT);
    call4.start(mockCallListener4, headers);
    call5.start(mockCallListener5, headers);
    assertTrue(oobExecutor.runDueTasks() > 0);
    verify(mockCallListener4).onClose(statusCaptor.capture(), any(Metadata.class));
    Status status4 = statusCaptor.getValue();
    assertEquals(Status.Code.UNAVAILABLE, status4.getCode());
    verify(mockCallListener5).onClose(statusCaptor.capture(), any(Metadata.class));
    Status status5 = statusCaptor.getValue();
    assertEquals(Status.Code.UNAVAILABLE, status5.getCode());
    // The pending RPC will still be pending
    verify(mockCallListener3, never()).onClose(any(Status.class), any(Metadata.class));
    // This will shutdownNow() the delayed transport, terminating the pending RPC
    assertEquals(0, oobExecutor.numPendingTasks());
    oob1.shutdownNow();
    assertTrue(oobExecutor.runDueTasks() > 0);
    verify(mockCallListener3).onClose(any(Status.class), any(Metadata.class));
    // Shut down the channel, and it will not terminated because OOB channel has not.
    channel.shutdown();
    assertFalse(channel.isTerminated());
    // Delayed transport has already terminated.  Terminating the transport terminates the
    // subchannel, which in turn terimates the OOB channel, which terminates the channel.
    assertFalse(oob1.isTerminated());
    verify(oobExecutorPool).returnObject(oobExecutor.getScheduledExecutorService());
    transportInfo.listener.transportTerminated();
    assertTrue(oob1.isTerminated());
    assertTrue(channel.isTerminated());
    verify(oobExecutorPool, times(2)).returnObject(oobExecutor.getScheduledExecutorService());
}
Also used : Status(io.grpc.Status) Metadata(io.grpc.Metadata) ManagedChannel(io.grpc.ManagedChannel) MockClientTransportInfo(io.grpc.internal.TestUtils.MockClientTransportInfo) Matchers.anyString(org.mockito.Matchers.anyString) Test(org.junit.Test)

Example 14 with Metadata

use of io.grpc.Metadata 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 15 with Metadata

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

the class ManagedChannelImplIdlenessTest method delayedTransportHoldsOffIdleness.

@Test
public void delayedTransportHoldsOffIdleness() throws Exception {
    ClientCall<String, Integer> call = channel.newCall(method, CallOptions.DEFAULT);
    call.start(mockCallListener, new Metadata());
    assertTrue(channel.inUseStateAggregator.isInUse());
    // As long as the delayed transport is in-use (by the pending RPC), the channel won't go idle.
    timer.forwardTime(IDLE_TIMEOUT_SECONDS * 2, TimeUnit.SECONDS);
    assertTrue(channel.inUseStateAggregator.isInUse());
    // Cancelling the only RPC will reset the in-use state.
    assertEquals(0, executor.numPendingTasks());
    call.cancel("In test", null);
    assertEquals(1, executor.runDueTasks());
    assertFalse(channel.inUseStateAggregator.isInUse());
    // And allow the channel to go idle.
    timer.forwardTime(IDLE_TIMEOUT_SECONDS - 1, TimeUnit.SECONDS);
    verify(mockLoadBalancer, never()).shutdown();
    timer.forwardTime(1, TimeUnit.SECONDS);
    verify(mockLoadBalancer).shutdown();
}
Also used : Metadata(io.grpc.Metadata) Matchers.anyString(org.mockito.Matchers.anyString) Test(org.junit.Test)

Aggregations

Metadata (io.grpc.Metadata)283 Test (org.junit.Test)229 Status (io.grpc.Status)78 ByteArrayInputStream (java.io.ByteArrayInputStream)25 ClientStream (io.grpc.internal.ClientStream)20 InputStream (java.io.InputStream)19 Buffer (okio.Buffer)16 ClientCall (io.grpc.ClientCall)14 AtomicInteger (java.util.concurrent.atomic.AtomicInteger)14 ServerStreamListener (io.grpc.internal.ServerStreamListener)13 AtomicReference (java.util.concurrent.atomic.AtomicReference)13 ServerCall (io.grpc.ServerCall)12 StatsContext (com.google.instrumentation.stats.StatsContext)11 CallOptions (io.grpc.CallOptions)11 IOException (java.io.IOException)11 Context (io.grpc.Context)10 StatusRuntimeException (io.grpc.StatusRuntimeException)10 Matchers.anyString (org.mockito.Matchers.anyString)10 ServerStream (io.grpc.internal.ServerStream)9 ServiceDescriptor (io.grpc.ServiceDescriptor)8