/* * Copyright (C) 2007 The Guava Authors * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy * of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. */ package com.google.common.util.concurrent.testing; import com.google.common.annotations.Beta; import com.google.common.util.concurrent.CheckedFuture; import com.google.common.util.concurrent.ListenableFuture; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; /** * Test case to make sure the {@link CheckedFuture#checkedGet()} and * {@link CheckedFuture#checkedGet(long, TimeUnit)} methods work correctly. * * @author Sven Mawson * @since 10.0 */ @Beta public abstract class AbstractCheckedFutureTest extends AbstractListenableFutureTest { /** * More specific type for the create method. */ protected abstract <V> CheckedFuture<V, ?> createCheckedFuture(V value, Exception except, CountDownLatch waitOn); /** * Checks that the exception is the correct type of cancellation exception. */ protected abstract void checkCancelledException(Exception e); /** * Checks that the exception is the correct type of execution exception. */ protected abstract void checkExecutionException(Exception e); /** * Checks that the exception is the correct type of interruption exception. */ protected abstract void checkInterruptedException(Exception e); @Override protected <V> ListenableFuture<V> createListenableFuture(V value, Exception except, CountDownLatch waitOn) { return createCheckedFuture(value, except, waitOn); } /** * Tests that the {@link CheckedFuture#checkedGet()} method throws the correct * type of cancellation exception when it is cancelled. */ public void testCheckedGetThrowsApplicationExceptionOnCancellation() { final CheckedFuture<Boolean, ?> future = createCheckedFuture(Boolean.TRUE, null, latch); assertFalse(future.isDone()); assertFalse(future.isCancelled()); new Thread(new Runnable() { @Override public void run() { future.cancel(true); } }).start(); try { future.checkedGet(); fail("RPC Should have been cancelled."); } catch (Exception e) { checkCancelledException(e); } assertTrue(future.isDone()); assertTrue(future.isCancelled()); } public void testCheckedGetThrowsApplicationExceptionOnInterruption() throws InterruptedException { final CheckedFuture<Boolean, ?> future = createCheckedFuture(Boolean.TRUE, null, latch); final CountDownLatch startingGate = new CountDownLatch(1); final CountDownLatch successLatch = new CountDownLatch(1); assertFalse(future.isDone()); assertFalse(future.isCancelled()); Thread getThread = new Thread(new Runnable() { @Override public void run() { startingGate.countDown(); try { future.checkedGet(); } catch (Exception e) { checkInterruptedException(e); // This only gets hit if the original call throws an exception and // the check call above passes. successLatch.countDown(); } } }); getThread.start(); assertTrue(startingGate.await(500, TimeUnit.MILLISECONDS)); getThread.interrupt(); assertTrue(successLatch.await(500, TimeUnit.MILLISECONDS)); assertFalse(future.isDone()); assertFalse(future.isCancelled()); } public void testCheckedGetThrowsApplicationExceptionOnError() { final CheckedFuture<Boolean, ?> future = createCheckedFuture(Boolean.TRUE, new Exception("Error"), latch); assertFalse(future.isDone()); assertFalse(future.isCancelled()); new Thread(new Runnable() { @Override public void run() { latch.countDown(); } }).start(); try { future.checkedGet(); fail(); } catch (Exception e) { checkExecutionException(e); } assertTrue(future.isDone()); assertFalse(future.isCancelled()); } }