1 /* 2 * Copyright (C) 2015 The Guava Authors 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.google.common.util.concurrent; 18 19 import static com.google.common.truth.Truth.assertThat; 20 import static com.google.common.util.concurrent.Futures.getDone; 21 import static com.google.common.util.concurrent.Futures.immediateFuture; 22 import static com.google.common.util.concurrent.MoreExecutors.directExecutor; 23 import static com.google.common.util.concurrent.Runnables.doNothing; 24 import static com.google.common.util.concurrent.TestPlatform.getDoneFromTimeoutOverload; 25 import static com.google.common.util.concurrent.TestPlatform.verifyGetOnPendingFuture; 26 import static com.google.common.util.concurrent.TestPlatform.verifyTimedGetOnPendingFuture; 27 import static java.util.concurrent.TimeUnit.NANOSECONDS; 28 import static java.util.concurrent.TimeUnit.SECONDS; 29 30 import com.google.common.annotations.GwtCompatible; 31 import com.google.common.annotations.GwtIncompatible; 32 import com.google.common.util.concurrent.AbstractFutureTest.TimedWaiterThread; 33 import java.util.concurrent.CancellationException; 34 import java.util.concurrent.ExecutionException; 35 import java.util.concurrent.TimeoutException; 36 import junit.framework.TestCase; 37 import org.checkerframework.checker.nullness.qual.Nullable; 38 39 /** 40 * Base class for tests for emulated {@link AbstractFuture} that allow subclasses to swap in a 41 * different "source Future" for {@link AbstractFuture#setFuture} calls. 42 */ 43 @GwtCompatible(emulated = true) 44 abstract class AbstractAbstractFutureTest extends TestCase { 45 private TestedFuture<Integer> future; 46 private AbstractFuture<Integer> delegate; 47 newDelegate()48 abstract AbstractFuture<Integer> newDelegate(); 49 50 @Override setUp()51 protected void setUp() { 52 future = TestedFuture.create(); 53 delegate = newDelegate(); 54 } 55 testPending()56 public void testPending() { 57 assertPending(future); 58 } 59 testSuccessful()60 public void testSuccessful() throws Exception { 61 assertThat(future.set(1)).isTrue(); 62 assertSuccessful(future, 1); 63 } 64 testFailed()65 public void testFailed() throws Exception { 66 Exception cause = new Exception(); 67 assertThat(future.setException(cause)).isTrue(); 68 assertFailed(future, cause); 69 } 70 testCanceled()71 public void testCanceled() throws Exception { 72 assertThat(future.cancel(false /* mayInterruptIfRunning */)).isTrue(); 73 assertCancelled(future, false); 74 } 75 testInterrupted()76 public void testInterrupted() throws Exception { 77 assertThat(future.cancel(true /* mayInterruptIfRunning */)).isTrue(); 78 assertCancelled(future, true); 79 } 80 testSetFuturePending()81 public void testSetFuturePending() throws Exception { 82 assertThat(future.setFuture(delegate)).isTrue(); 83 assertSetAsynchronously(future); 84 } 85 testSetFutureThenCancel()86 public void testSetFutureThenCancel() throws Exception { 87 assertThat(future.setFuture(delegate)).isTrue(); 88 assertThat(future.cancel(false /* mayInterruptIfRunning */)).isTrue(); 89 assertCancelled(future, false); 90 assertCancelled(delegate, false); 91 } 92 testSetFutureThenInterrupt()93 public void testSetFutureThenInterrupt() throws Exception { 94 assertThat(future.setFuture(delegate)).isTrue(); 95 assertThat(future.cancel(true /* mayInterruptIfRunning */)).isTrue(); 96 assertCancelled(future, true); 97 assertCancelled(delegate, true); 98 } 99 testSetFutureDelegateAlreadySuccessful()100 public void testSetFutureDelegateAlreadySuccessful() throws Exception { 101 delegate.set(5); 102 assertThat(future.setFuture(delegate)).isTrue(); 103 assertSuccessful(future, 5); 104 } 105 testSetFutureDelegateLaterSuccessful()106 public void testSetFutureDelegateLaterSuccessful() throws Exception { 107 assertThat(future.setFuture(delegate)).isTrue(); 108 delegate.set(6); 109 assertSuccessful(future, 6); 110 } 111 testSetFutureDelegateAlreadyCancelled()112 public void testSetFutureDelegateAlreadyCancelled() throws Exception { 113 delegate.cancel( 114 false 115 /** mayInterruptIfRunning */ 116 ); 117 assertThat(future.setFuture(delegate)).isTrue(); 118 assertCancelled(future, false); 119 } 120 testSetFutureDelegateLaterCancelled()121 public void testSetFutureDelegateLaterCancelled() throws Exception { 122 assertThat(future.setFuture(delegate)).isTrue(); 123 delegate.cancel( 124 false 125 /** mayInterruptIfRunning */ 126 ); 127 assertCancelled(future, false); 128 } 129 testSetFutureDelegateAlreadyInterrupted()130 public void testSetFutureDelegateAlreadyInterrupted() throws Exception { 131 delegate.cancel( 132 true 133 /** mayInterruptIfRunning */ 134 ); 135 assertThat(future.setFuture(delegate)).isTrue(); 136 assertCancelled(future, /* expectWasInterrupted= */ false); 137 } 138 testSetFutureDelegateLaterInterrupted()139 public void testSetFutureDelegateLaterInterrupted() throws Exception { 140 assertThat(future.setFuture(delegate)).isTrue(); 141 delegate.cancel( 142 true 143 /** mayInterruptIfRunning */ 144 ); 145 assertCancelled(future, /* expectWasInterrupted= */ false); 146 } 147 testListenLaterSuccessful()148 public void testListenLaterSuccessful() { 149 CountingRunnable listener = new CountingRunnable(); 150 151 future.addListener(listener, directExecutor()); 152 listener.assertNotRun(); 153 154 future.set(1); 155 listener.assertRun(); 156 } 157 testListenLaterFailed()158 public void testListenLaterFailed() { 159 CountingRunnable listener = new CountingRunnable(); 160 161 future.addListener(listener, directExecutor()); 162 listener.assertNotRun(); 163 164 future.setException(new Exception()); 165 listener.assertRun(); 166 } 167 testListenLaterCancelled()168 public void testListenLaterCancelled() { 169 CountingRunnable listener = new CountingRunnable(); 170 171 future.addListener(listener, directExecutor()); 172 listener.assertNotRun(); 173 174 future.cancel(false); 175 listener.assertRun(); 176 } 177 testListenLaterInterrupted()178 public void testListenLaterInterrupted() { 179 CountingRunnable listener = new CountingRunnable(); 180 181 future.addListener(listener, directExecutor()); 182 listener.assertNotRun(); 183 184 future.cancel(true); 185 listener.assertRun(); 186 } 187 testListenLaterSetAsynchronously()188 public void testListenLaterSetAsynchronously() { 189 CountingRunnable listener = new CountingRunnable(); 190 191 future.addListener(listener, directExecutor()); 192 listener.assertNotRun(); 193 194 future.setFuture(delegate); 195 listener.assertNotRun(); 196 } 197 testListenLaterSetAsynchronouslyLaterDelegateSuccessful()198 public void testListenLaterSetAsynchronouslyLaterDelegateSuccessful() { 199 CountingRunnable before = new CountingRunnable(); 200 CountingRunnable inBetween = new CountingRunnable(); 201 CountingRunnable after = new CountingRunnable(); 202 203 future.addListener(before, directExecutor()); 204 future.setFuture(delegate); 205 future.addListener(inBetween, directExecutor()); 206 delegate.set(1); 207 future.addListener(after, directExecutor()); 208 209 before.assertRun(); 210 inBetween.assertRun(); 211 after.assertRun(); 212 } 213 testListenLaterSetAsynchronouslyLaterDelegateFailed()214 public void testListenLaterSetAsynchronouslyLaterDelegateFailed() { 215 CountingRunnable before = new CountingRunnable(); 216 CountingRunnable inBetween = new CountingRunnable(); 217 CountingRunnable after = new CountingRunnable(); 218 219 future.addListener(before, directExecutor()); 220 future.setFuture(delegate); 221 future.addListener(inBetween, directExecutor()); 222 delegate.setException(new Exception()); 223 future.addListener(after, directExecutor()); 224 225 before.assertRun(); 226 inBetween.assertRun(); 227 after.assertRun(); 228 } 229 testListenLaterSetAsynchronouslyLaterDelegateCancelled()230 public void testListenLaterSetAsynchronouslyLaterDelegateCancelled() { 231 CountingRunnable before = new CountingRunnable(); 232 CountingRunnable inBetween = new CountingRunnable(); 233 CountingRunnable after = new CountingRunnable(); 234 235 future.addListener(before, directExecutor()); 236 future.setFuture(delegate); 237 future.addListener(inBetween, directExecutor()); 238 delegate.cancel(false); 239 future.addListener(after, directExecutor()); 240 241 before.assertRun(); 242 inBetween.assertRun(); 243 after.assertRun(); 244 } 245 testListenLaterSetAsynchronouslyLaterDelegateInterrupted()246 public void testListenLaterSetAsynchronouslyLaterDelegateInterrupted() { 247 CountingRunnable before = new CountingRunnable(); 248 CountingRunnable inBetween = new CountingRunnable(); 249 CountingRunnable after = new CountingRunnable(); 250 251 future.addListener(before, directExecutor()); 252 future.setFuture(delegate); 253 future.addListener(inBetween, directExecutor()); 254 delegate.cancel(true); 255 future.addListener(after, directExecutor()); 256 257 before.assertRun(); 258 inBetween.assertRun(); 259 after.assertRun(); 260 } 261 testListenLaterSetAsynchronouslyLaterSelfCancelled()262 public void testListenLaterSetAsynchronouslyLaterSelfCancelled() { 263 CountingRunnable before = new CountingRunnable(); 264 CountingRunnable inBetween = new CountingRunnable(); 265 CountingRunnable after = new CountingRunnable(); 266 267 future.addListener(before, directExecutor()); 268 future.setFuture(delegate); 269 future.addListener(inBetween, directExecutor()); 270 future.cancel(false); 271 future.addListener(after, directExecutor()); 272 273 before.assertRun(); 274 inBetween.assertRun(); 275 after.assertRun(); 276 } 277 testListenLaterSetAsynchronouslyLaterSelfInterrupted()278 public void testListenLaterSetAsynchronouslyLaterSelfInterrupted() { 279 CountingRunnable before = new CountingRunnable(); 280 CountingRunnable inBetween = new CountingRunnable(); 281 CountingRunnable after = new CountingRunnable(); 282 283 future.addListener(before, directExecutor()); 284 future.setFuture(delegate); 285 future.addListener(inBetween, directExecutor()); 286 future.cancel(true); 287 future.addListener(after, directExecutor()); 288 289 before.assertRun(); 290 inBetween.assertRun(); 291 after.assertRun(); 292 } 293 testMisbehavingListenerAlreadyDone()294 public void testMisbehavingListenerAlreadyDone() { 295 class BadRunnableException extends RuntimeException {} 296 297 Runnable bad = 298 new Runnable() { 299 @Override 300 public void run() { 301 throw new BadRunnableException(); 302 } 303 }; 304 305 future.set(1); 306 future.addListener(bad, directExecutor()); // BadRunnableException must not propagate. 307 } 308 testMisbehavingListenerLaterDone()309 public void testMisbehavingListenerLaterDone() { 310 class BadRunnableException extends RuntimeException {} 311 312 CountingRunnable before = new CountingRunnable(); 313 Runnable bad = 314 new Runnable() { 315 @Override 316 public void run() { 317 throw new BadRunnableException(); 318 } 319 }; 320 CountingRunnable after = new CountingRunnable(); 321 322 future.addListener(before, directExecutor()); 323 future.addListener(bad, directExecutor()); 324 future.addListener(after, directExecutor()); 325 326 future.set(1); // BadRunnableException must not propagate. 327 328 before.assertRun(); 329 after.assertRun(); 330 } 331 testNullListener()332 public void testNullListener() { 333 try { 334 future.addListener(null, directExecutor()); 335 fail(); 336 } catch (NullPointerException expected) { 337 } 338 } 339 testNullExecutor()340 public void testNullExecutor() { 341 try { 342 future.addListener(doNothing(), null); 343 fail(); 344 } catch (NullPointerException expected) { 345 } 346 } 347 testNullTimeUnit()348 public void testNullTimeUnit() throws Exception { 349 future.set(1); 350 try { 351 future.get(0, null); 352 fail(); 353 } catch (NullPointerException expected) { 354 } 355 } 356 testNegativeTimeout()357 public void testNegativeTimeout() throws Exception { 358 future.set(1); 359 assertEquals(1, future.get(-1, SECONDS).intValue()); 360 } 361 362 @GwtIncompatible // threads testOverflowTimeout()363 public void testOverflowTimeout() throws Exception { 364 // First, sanity check that naive multiplication would really overflow to a negative number: 365 long nanosPerSecond = NANOSECONDS.convert(1, SECONDS); 366 assertThat(nanosPerSecond * Long.MAX_VALUE).isLessThan(0L); 367 368 // Check that we wait long enough anyway (presumably as long as MAX_VALUE nanos): 369 TimedWaiterThread waiter = new TimedWaiterThread(future, Long.MAX_VALUE, SECONDS); 370 waiter.start(); 371 waiter.awaitWaiting(); 372 373 future.set(1); 374 waiter.join(); 375 } 376 testSetNull()377 public void testSetNull() throws Exception { 378 future.set(null); 379 assertSuccessful(future, null); 380 } 381 testSetExceptionNull()382 public void testSetExceptionNull() throws Exception { 383 try { 384 future.setException(null); 385 fail(); 386 } catch (NullPointerException expected) { 387 } 388 389 assertThat(future.isDone()).isFalse(); 390 assertThat(future.set(1)).isTrue(); 391 assertSuccessful(future, 1); 392 } 393 testSetFutureNull()394 public void testSetFutureNull() throws Exception { 395 try { 396 future.setFuture(null); 397 fail(); 398 } catch (NullPointerException expected) { 399 } 400 401 assertThat(future.isDone()).isFalse(); 402 assertThat(future.set(1)).isTrue(); 403 assertSuccessful(future, 1); 404 } 405 406 /** Concrete subclass for testing. */ 407 private static class TestedFuture<V> extends AbstractFuture<V> { create()408 private static <V> TestedFuture<V> create() { 409 return new TestedFuture<V>(); 410 } 411 } 412 413 private static final class CountingRunnable implements Runnable { 414 int count; 415 416 @Override run()417 public void run() { 418 count++; 419 } 420 assertNotRun()421 void assertNotRun() { 422 assertEquals(0, count); 423 } 424 assertRun()425 void assertRun() { 426 assertEquals(1, count); 427 } 428 } 429 assertSetAsynchronously(AbstractFuture<Integer> future)430 private static void assertSetAsynchronously(AbstractFuture<Integer> future) { 431 assertCannotSet(future); 432 assertPending(future); 433 } 434 assertPending(AbstractFuture<Integer> future)435 private static void assertPending(AbstractFuture<Integer> future) { 436 assertThat(future.isDone()).isFalse(); 437 assertThat(future.isCancelled()).isFalse(); 438 439 CountingRunnable listener = new CountingRunnable(); 440 future.addListener(listener, directExecutor()); 441 listener.assertNotRun(); 442 443 verifyGetOnPendingFuture(future); 444 verifyTimedGetOnPendingFuture(future); 445 } 446 assertSuccessful( AbstractFuture<Integer> future, @Nullable Integer expectedResult)447 private static void assertSuccessful( 448 AbstractFuture<Integer> future, @Nullable Integer expectedResult) 449 throws InterruptedException, TimeoutException, ExecutionException { 450 assertDone(future); 451 assertThat(future.isCancelled()).isFalse(); 452 453 assertThat(getDone(future)).isEqualTo(expectedResult); 454 assertThat(getDoneFromTimeoutOverload(future)).isEqualTo(expectedResult); 455 } 456 assertFailed(AbstractFuture<Integer> future, Throwable expectedException)457 private static void assertFailed(AbstractFuture<Integer> future, Throwable expectedException) 458 throws InterruptedException, TimeoutException { 459 assertDone(future); 460 assertThat(future.isCancelled()).isFalse(); 461 462 try { 463 getDone(future); 464 fail(); 465 } catch (ExecutionException e) { 466 assertThat(e.getCause()).isSameInstanceAs(expectedException); 467 } 468 469 try { 470 getDoneFromTimeoutOverload(future); 471 fail(); 472 } catch (ExecutionException e) { 473 assertThat(e).hasCauseThat().isSameInstanceAs(expectedException); 474 } 475 } 476 assertCancelled(AbstractFuture<Integer> future, boolean expectWasInterrupted)477 private static void assertCancelled(AbstractFuture<Integer> future, boolean expectWasInterrupted) 478 throws InterruptedException, TimeoutException, ExecutionException { 479 assertDone(future); 480 assertThat(future.isCancelled()).isTrue(); 481 assertThat(future.wasInterrupted()).isEqualTo(expectWasInterrupted); 482 483 try { 484 getDone(future); 485 fail(); 486 } catch (CancellationException expected) { 487 } 488 489 try { 490 getDoneFromTimeoutOverload(future); 491 fail(); 492 } catch (CancellationException expected) { 493 } 494 } 495 assertDone(AbstractFuture<Integer> future)496 private static void assertDone(AbstractFuture<Integer> future) { 497 CountingRunnable listener = new CountingRunnable(); 498 future.addListener(listener, directExecutor()); 499 listener.assertRun(); 500 501 assertThat(future.isDone()).isTrue(); 502 assertCannotSet(future); 503 assertCannotCancel(future); 504 } 505 assertCannotSet(AbstractFuture<Integer> future)506 private static void assertCannotSet(AbstractFuture<Integer> future) { 507 assertThat(future.set(99)).isFalse(); 508 assertThat(future.setException(new IndexOutOfBoundsException())).isFalse(); 509 assertThat(future.setFuture(new AbstractFuture<Integer>() {})).isFalse(); 510 assertThat(future.setFuture(immediateFuture(99))).isFalse(); 511 } 512 assertCannotCancel(AbstractFuture<Integer> future)513 private static void assertCannotCancel(AbstractFuture<Integer> future) { 514 assertThat(future.cancel(true)).isFalse(); 515 assertThat(future.cancel(false)).isFalse(); 516 } 517 } 518