Пример #1
0
 @Test
 public void immediateDeadlineExceeded() {
   ClientCall<String, Integer> call =
       channel.newCall(method, CallOptions.DEFAULT.withDeadlineNanoTime(System.nanoTime()));
   call.start(mockCallListener, new Metadata.Headers());
   verify(mockCallListener, timeout(1000))
       .onClose(same(Status.DEADLINE_EXCEEDED), any(Metadata.Trailers.class));
 }
Пример #2
0
  @Test
  public void testNoDeadlockOnShutdown() {
    // Force creation of transport
    ClientCall<String, Integer> call = channel.newCall(method, CallOptions.DEFAULT);
    call.start(mockCallListener, new Metadata.Headers());
    call.cancel();

    verify(mockTransport).start(transportListenerCaptor.capture());
    final ClientTransport.Listener transportListener = transportListenerCaptor.getValue();
    final Object lock = new Object();
    final CyclicBarrier barrier = new CyclicBarrier(2);
    new Thread() {
      @Override
      public void run() {
        synchronized (lock) {
          try {
            barrier.await();
          } catch (Exception ex) {
            throw new AssertionError(ex);
          }
          // To deadlock, a lock would be needed for this call to proceed.
          transportListener.transportShutdown(Status.CANCELLED);
        }
      }
    }.start();
    doAnswer(
            new Answer<Void>() {
              @Override
              public Void answer(InvocationOnMock invocation) {
                // To deadlock, a lock would need to be held while this method is in progress.
                try {
                  barrier.await();
                } catch (Exception ex) {
                  throw new AssertionError(ex);
                }
                // If deadlock is possible with this setup, this sychronization completes the loop
                // because
                // the transportShutdown needs a lock that Channel is holding while calling this
                // method.
                synchronized (lock) {
                }
                return null;
              }
            })
        .when(mockTransport)
        .shutdown();
    channel.shutdown();

    transportListener.transportTerminated();
  }
Пример #3
0
  @Test
  public void transportFailsOnStart() {
    Status goldenStatus = Status.INTERNAL.withDescription("wanted it to fail");

    // Have transport throw exception on start
    ClientCall<String, Integer> call = channel.newCall(method, CallOptions.DEFAULT);
    ClientTransport mockTransport = mock(ClientTransport.class);
    when(mockTransportFactory.newClientTransport()).thenReturn(mockTransport);
    doThrow(goldenStatus.asRuntimeException())
        .when(mockTransport)
        .start(any(ClientTransport.Listener.class));
    call.start(mockCallListener, new Metadata.Headers());
    verify(mockTransportFactory).newClientTransport();
    verify(mockTransport).start(any(ClientTransport.Listener.class));
    ArgumentCaptor<Status> statusCaptor = ArgumentCaptor.forClass(Status.class);
    verify(mockCallListener, timeout(1000))
        .onClose(statusCaptor.capture(), any(Metadata.Trailers.class));
    assertSame(goldenStatus, statusCaptor.getValue());

    // Have transport shutdown immediately during start
    call = channel.newCall(method, CallOptions.DEFAULT);
    ClientTransport mockTransport2 = mock(ClientTransport.class);
    ClientStream mockStream2 = mock(ClientStream.class);
    Metadata.Headers headers2 = new Metadata.Headers();
    when(mockTransportFactory.newClientTransport()).thenReturn(mockTransport2);
    doAnswer(
            new Answer<Void>() {
              @Override
              public Void answer(InvocationOnMock invocation) {
                ClientTransport.Listener listener =
                    (ClientTransport.Listener) invocation.getArguments()[0];
                listener.transportShutdown(Status.INTERNAL);
                listener.transportTerminated();
                return null;
              }
            })
        .when(mockTransport2)
        .start(any(ClientTransport.Listener.class));
    when(mockTransport2.newStream(same(method), same(headers2), any(ClientStreamListener.class)))
        .thenReturn(mockStream2);
    call.start(mockCallListener2, headers2);
    verify(mockTransportFactory, times(2)).newClientTransport();
    verify(mockTransport2).start(any(ClientTransport.Listener.class));
    verify(mockTransport2).newStream(same(method), same(headers2), streamListenerCaptor.capture());
    Metadata.Trailers trailers2 = new Metadata.Trailers();
    streamListenerCaptor.getValue().closed(Status.CANCELLED, trailers2);
    verify(mockCallListener2, timeout(1000)).onClose(Status.CANCELLED, trailers2);

    // Make sure the Channel can still handle new calls
    call = channel.newCall(method, CallOptions.DEFAULT);
    ClientTransport mockTransport3 = mock(ClientTransport.class);
    ClientStream mockStream3 = mock(ClientStream.class);
    Metadata.Headers headers3 = new Metadata.Headers();
    when(mockTransportFactory.newClientTransport()).thenReturn(mockTransport3);
    when(mockTransport3.newStream(same(method), same(headers3), any(ClientStreamListener.class)))
        .thenReturn(mockStream3);
    call.start(mockCallListener3, headers3);
    verify(mockTransportFactory, times(3)).newClientTransport();
    verify(mockTransport3).start(transportListenerCaptor.capture());
    verify(mockTransport3).newStream(same(method), same(headers3), streamListenerCaptor.capture());
    Metadata.Trailers trailers3 = new Metadata.Trailers();
    streamListenerCaptor.getValue().closed(Status.CANCELLED, trailers3);
    verify(mockCallListener3, timeout(1000)).onClose(Status.CANCELLED, trailers3);

    // Make sure shutdown still works
    channel.shutdown();
    assertTrue(channel.isShutdown());
    assertFalse(channel.isTerminated());
    verify(mockTransport3).shutdown();
    transportListenerCaptor.getValue().transportShutdown(Status.CANCELLED);
    assertFalse(channel.isTerminated());

    transportListenerCaptor.getValue().transportTerminated();
    assertTrue(channel.isTerminated());

    verifyNoMoreInteractions(mockTransportFactory);
    verifyNoMoreInteractions(mockTransport);
    verifyNoMoreInteractions(mockTransport2);
    verifyNoMoreInteractions(mockTransport3);
    verifyNoMoreInteractions(mockStream2);
    verifyNoMoreInteractions(mockStream3);
  }
Пример #4
0
  @Test
  public void twoCallsAndGracefulShutdown() {
    verifyNoMoreInteractions(mockTransportFactory);
    ClientCall<String, Integer> call = channel.newCall(method, CallOptions.DEFAULT);
    verifyNoMoreInteractions(mockTransportFactory);

    // Create transport and call
    ClientTransport mockTransport = mock(ClientTransport.class);
    ClientStream mockStream = mock(ClientStream.class);
    Metadata.Headers headers = new Metadata.Headers();
    when(mockTransportFactory.newClientTransport()).thenReturn(mockTransport);
    when(mockTransport.newStream(same(method), same(headers), any(ClientStreamListener.class)))
        .thenReturn(mockStream);
    call.start(mockCallListener, headers);
    verify(mockTransportFactory).newClientTransport();
    verify(mockTransport).start(transportListenerCaptor.capture());
    ClientTransport.Listener transportListener = transportListenerCaptor.getValue();
    verify(mockTransport).newStream(same(method), same(headers), streamListenerCaptor.capture());
    ClientStreamListener streamListener = streamListenerCaptor.getValue();

    // Second call
    ClientCall<String, Integer> call2 = channel.newCall(method, CallOptions.DEFAULT);
    ClientStream mockStream2 = mock(ClientStream.class);
    Metadata.Headers headers2 = new Metadata.Headers();
    when(mockTransport.newStream(same(method), same(headers2), any(ClientStreamListener.class)))
        .thenReturn(mockStream2);
    call2.start(mockCallListener2, headers2);
    verify(mockTransport).newStream(same(method), same(headers2), streamListenerCaptor.capture());
    ClientStreamListener streamListener2 = streamListenerCaptor.getValue();
    Metadata.Trailers trailers = new Metadata.Trailers();
    streamListener2.closed(Status.CANCELLED, trailers);
    verify(mockCallListener2, timeout(1000)).onClose(Status.CANCELLED, trailers);

    // Shutdown
    channel.shutdown();
    assertTrue(channel.isShutdown());
    assertFalse(channel.isTerminated());
    verify(mockTransport).shutdown();

    // Further calls should fail without going to the transport
    ClientCall<String, Integer> call3 = channel.newCall(method, CallOptions.DEFAULT);
    call3.start(mockCallListener3, new Metadata.Headers());
    ArgumentCaptor<Status> statusCaptor = ArgumentCaptor.forClass(Status.class);
    verify(mockCallListener3, timeout(1000))
        .onClose(statusCaptor.capture(), any(Metadata.Trailers.class));
    assertSame(Status.Code.UNAVAILABLE, statusCaptor.getValue().getCode());

    // Finish shutdown
    transportListener.transportShutdown(Status.CANCELLED);
    assertFalse(channel.isTerminated());
    streamListener.closed(Status.CANCELLED, trailers);
    verify(mockCallListener, timeout(1000)).onClose(Status.CANCELLED, trailers);
    assertFalse(channel.isTerminated());

    transportListener.transportTerminated();
    assertTrue(channel.isTerminated());

    verifyNoMoreInteractions(mockTransportFactory);
    verifyNoMoreInteractions(mockTransport);
    verifyNoMoreInteractions(mockStream);
  }