001/*
002 * Copyright (C) 2007 The Guava Authors
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
005 * use this file except in compliance with the License.  You may obtain a copy
006 * of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
012 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
013 * License for the specific language governing permissions and limitations under
014 * the License.
015 */
016
017package com.google.common.util.concurrent.testing;
018
019import com.google.common.annotations.Beta;
020import com.google.common.annotations.GwtIncompatible;
021import com.google.common.util.concurrent.CheckedFuture;
022import com.google.common.util.concurrent.ListenableFuture;
023import java.util.concurrent.CountDownLatch;
024import java.util.concurrent.TimeUnit;
025
026/**
027 * Test case to make sure the {@link CheckedFuture#checkedGet()} and {@link
028 * CheckedFuture#checkedGet(long, TimeUnit)} methods work correctly.
029 *
030 * @author Sven Mawson
031 * @since 10.0
032 */
033@Beta
034@GwtIncompatible
035public abstract class AbstractCheckedFutureTest extends AbstractListenableFutureTest {
036
037  /** More specific type for the create method. */
038  protected abstract <V> CheckedFuture<V, ?> createCheckedFuture(
039      V value, Exception except, CountDownLatch waitOn);
040
041  /** Checks that the exception is the correct type of cancellation exception. */
042  protected abstract void checkCancelledException(Exception e);
043
044  /** Checks that the exception is the correct type of execution exception. */
045  protected abstract void checkExecutionException(Exception e);
046
047  /** Checks that the exception is the correct type of interruption exception. */
048  protected abstract void checkInterruptedException(Exception e);
049
050  @Override
051  protected <V> ListenableFuture<V> createListenableFuture(
052      V value, Exception except, CountDownLatch waitOn) {
053    return createCheckedFuture(value, except, waitOn);
054  }
055
056  /**
057   * Tests that the {@link CheckedFuture#checkedGet()} method throws the correct type of
058   * cancellation exception when it is cancelled.
059   */
060  public void testCheckedGetThrowsApplicationExceptionOnCancellation() {
061
062    final CheckedFuture<Boolean, ?> future = createCheckedFuture(Boolean.TRUE, null, latch);
063
064    assertFalse(future.isDone());
065    assertFalse(future.isCancelled());
066
067    new Thread(
068            new Runnable() {
069              @Override
070              public void run() {
071                future.cancel(true);
072              }
073            })
074        .start();
075
076    try {
077      future.checkedGet();
078      fail("RPC Should have been cancelled.");
079    } catch (Exception e) {
080      checkCancelledException(e);
081    }
082
083    assertTrue(future.isDone());
084    assertTrue(future.isCancelled());
085  }
086
087  public void testCheckedGetThrowsApplicationExceptionOnInterruption() throws InterruptedException {
088
089    final CheckedFuture<Boolean, ?> future = createCheckedFuture(Boolean.TRUE, null, latch);
090
091    final CountDownLatch startingGate = new CountDownLatch(1);
092    final CountDownLatch successLatch = new CountDownLatch(1);
093
094    assertFalse(future.isDone());
095    assertFalse(future.isCancelled());
096
097    Thread getThread =
098        new Thread(
099            new Runnable() {
100              @Override
101              public void run() {
102                startingGate.countDown();
103
104                try {
105                  future.checkedGet();
106                } catch (Exception e) {
107                  checkInterruptedException(e);
108
109                  // This only gets hit if the original call throws an exception and
110                  // the check call above passes.
111                  successLatch.countDown();
112                }
113              }
114            });
115    getThread.start();
116
117    assertTrue(startingGate.await(500, TimeUnit.MILLISECONDS));
118    getThread.interrupt();
119
120    assertTrue(successLatch.await(500, TimeUnit.MILLISECONDS));
121
122    assertFalse(future.isDone());
123    assertFalse(future.isCancelled());
124  }
125
126  public void testCheckedGetThrowsApplicationExceptionOnError() {
127    final CheckedFuture<Boolean, ?> future =
128        createCheckedFuture(Boolean.TRUE, new Exception("Error"), latch);
129
130    assertFalse(future.isDone());
131    assertFalse(future.isCancelled());
132
133    new Thread(
134            new Runnable() {
135              @Override
136              public void run() {
137                latch.countDown();
138              }
139            })
140        .start();
141
142    try {
143      future.checkedGet();
144      fail();
145    } catch (Exception e) {
146      checkExecutionException(e);
147    }
148
149    assertTrue(future.isDone());
150    assertFalse(future.isCancelled());
151  }
152}