예제 #1
0
 private static void assertCodeEquals(io.grpc.Status expected, io.grpc.Status actual) {
   if (expected == null) {
     fail("expected should not be null");
   }
   if (actual == null || !expected.getCode().equals(actual.getCode())) {
     assertEquals(expected, actual);
   }
 }
예제 #2
0
  @Test
  public void cancelInOnMessageShouldInvokeStreamCancel() throws Exception {
    final ClientCallImpl<Void, Void> call =
        new ClientCallImpl<Void, Void>(
            DESCRIPTOR,
            MoreExecutors.directExecutor(),
            CallOptions.DEFAULT,
            provider,
            deadlineCancellationExecutor);
    final Exception cause = new Exception();
    ClientCall.Listener<Void> callListener =
        new ClientCall.Listener<Void>() {
          @Override
          public void onMessage(Void message) {
            call.cancel("foo", cause);
          }
        };

    call.start(callListener, new Metadata());
    call.halfClose();
    call.request(1);

    verify(stream).start(listenerArgumentCaptor.capture());
    ClientStreamListener streamListener = listenerArgumentCaptor.getValue();
    streamListener.onReady();
    streamListener.headersRead(new Metadata());
    streamListener.messageRead(new ByteArrayInputStream(new byte[0]));
    verify(stream).cancel(statusCaptor.capture());
    Status status = statusCaptor.getValue();
    assertEquals(Status.CANCELLED.getCode(), status.getCode());
    assertEquals("foo", status.getDescription());
    assertSame(cause, status.getCause());
  }
예제 #3
0
 @Override
 public void closed(Status status, Metadata trailers) {
   Deadline deadline = context.getDeadline();
   if (status.getCode() == Status.Code.CANCELLED && deadline != null) {
     // When the server's deadline expires, it can only reset the stream with CANCEL and no
     // description. Since our timer may be delayed in firing, we double-check the deadline and
     // turn the failure into the likely more helpful DEADLINE_EXCEEDED status.
     if (deadline.isExpired()) {
       status = DEADLINE_EXCEEDED;
       // Replace trailers to prevent mixing sources of status and trailers.
       trailers = new Metadata();
     }
   }
   final Status savedStatus = status;
   final Metadata savedTrailers = trailers;
   callExecutor.execute(
       new ContextRunnable(context) {
         @Override
         public final void runInContext() {
           try {
             closed = true;
             contextListenerShouldBeRemoved = true;
             observer.onClose(savedStatus, savedTrailers);
           } finally {
             context.removeListener(ClientCallImpl.this);
           }
         }
       });
 }
예제 #4
0
 @Test
 public void statusFromCancelled_returnCancelledIfCauseIsNull() {
   Context.CancellableContext cancellableContext = Context.current().withCancellation();
   cancellableContext.cancel(null);
   assertTrue(cancellableContext.isCancelled());
   Status status = statusFromCancelled(cancellableContext);
   assertNotNull(status);
   assertEquals(Status.Code.CANCELLED, status.getCode());
 }
예제 #5
0
 @Test
 public void statusFromCancelled_returnStatusAsSetOnCtx() {
   Context.CancellableContext cancellableContext = Context.current().withCancellation();
   cancellableContext.cancel(Status.DEADLINE_EXCEEDED.withDescription("foo bar").asException());
   Status status = statusFromCancelled(cancellableContext);
   assertNotNull(status);
   assertEquals(Status.Code.DEADLINE_EXCEEDED, status.getCode());
   assertEquals("foo bar", status.getDescription());
 }
예제 #6
0
 @Test
 public void statusFromCancelled_shouldReturnStatusWithCauseAttached() {
   Context.CancellableContext cancellableContext = Context.current().withCancellation();
   Throwable t = new Throwable();
   cancellableContext.cancel(t);
   Status status = statusFromCancelled(cancellableContext);
   assertNotNull(status);
   assertEquals(Status.Code.CANCELLED, status.getCode());
   assertSame(t, status.getCause());
 }
예제 #7
0
 static {
   TreeMap<Integer, Status> canonicalizer = new TreeMap<Integer, Status>();
   for (Code code : Code.values()) {
     Status replaced = canonicalizer.put(code.value(), new Status(code));
     if (replaced != null) {
       throw new IllegalStateException(
           "Code value duplication between " + replaced.getCode().name() + " & " + code.name());
     }
   }
   STATUS_LIST = new ArrayList<Status>(canonicalizer.values());
 }
예제 #8
0
  /** This is a whitebox test, to verify a special case of the implementation. */
  @Test
  public void statusFromCancelled_StatusUnknownShouldWork() {
    Context.CancellableContext cancellableContext = Context.current().withCancellation();
    Exception e = Status.UNKNOWN.asException();
    cancellableContext.cancel(e);
    assertTrue(cancellableContext.isCancelled());

    Status status = statusFromCancelled(cancellableContext);
    assertNotNull(status);
    assertEquals(Status.Code.UNKNOWN, status.getCode());
    assertSame(e, status.getCause());
  }
예제 #9
0
  @Test
  public void contextAlreadyCancelledNotifiesImmediately() throws Exception {
    // Attach the context which is recorded when the call is created
    Context.CancellableContext cancellableContext = Context.current().withCancellation();
    Throwable cause = new Throwable();
    cancellableContext.cancel(cause);
    Context previous = cancellableContext.attach();

    ClientCallImpl<Void, Void> call =
        new ClientCallImpl<Void, Void>(
                DESCRIPTOR,
                new SerializingExecutor(Executors.newSingleThreadExecutor()),
                CallOptions.DEFAULT,
                provider,
                deadlineCancellationExecutor)
            .setDecompressorRegistry(decompressorRegistry);

    previous.attach();

    final SettableFuture<Status> statusFuture = SettableFuture.create();
    call.start(
        new ClientCall.Listener<Void>() {
          @Override
          public void onClose(Status status, Metadata trailers) {
            statusFuture.set(status);
          }
        },
        new Metadata());

    // Caller should receive onClose callback.
    Status status = statusFuture.get(5, TimeUnit.SECONDS);
    assertEquals(Status.Code.CANCELLED, status.getCode());
    assertSame(cause, status.getCause());

    // Following operations should be no-op.
    call.request(1);
    call.sendMessage(null);
    call.halfClose();

    // Stream should never be created.
    verifyZeroInteractions(transport);

    try {
      call.sendMessage(null);
      fail("Call has been cancelled");
    } catch (IllegalStateException ise) {
      // expected
    }
  }
예제 #10
0
  @Test
  public void statusFromCancelled_TimeoutExceptionShouldMapToDeadlineExceeded() {
    FakeClock fakeClock = new FakeClock();
    Context.CancellableContext cancellableContext =
        Context.current()
            .withDeadlineAfter(100, TimeUnit.MILLISECONDS, fakeClock.scheduledExecutorService);
    fakeClock.forwardTime(System.nanoTime(), TimeUnit.NANOSECONDS);
    fakeClock.forwardMillis(100);

    assertTrue(cancellableContext.isCancelled());
    assertThat(cancellableContext.cancellationCause(), instanceOf(TimeoutException.class));

    Status status = statusFromCancelled(cancellableContext);
    assertNotNull(status);
    assertEquals(Status.Code.DEADLINE_EXCEEDED, status.getCode());
    assertEquals("context timed out", status.getDescription());
  }
예제 #11
0
 @Override
 public String toAsciiString(Status status) {
   return status.getCode().valueAscii();
 }