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 38 /** 39 * Base class for tests for emulated {@link AbstractFuture} that allow subclasses to swap in a 40 * different "source Future" for {@link AbstractFuture#setFuture} calls. 41 */ 42 @GwtCompatible(emulated = true) 43 abstract class AbstractAbstractFutureTest extends TestCase { 44 private TestedFuture<Integer> future; 45 private AbstractFuture<Integer> delegate; 46 newDelegate()47 abstract AbstractFuture<Integer> newDelegate(); 48 49 @Override setUp()50 protected void setUp() { 51 future = TestedFuture.create(); 52 delegate = newDelegate(); 53 } 54 testPending()55 public void testPending() { 56 assertPending(future); 57 } 58 testSuccessful()59 public void testSuccessful() throws Exception { 60 assertThat(future.set(1)).isTrue(); 61 assertSuccessful(future, 1); 62 } 63 testFailed()64 public void testFailed() throws Exception { 65 Exception cause = new Exception(); 66 assertThat(future.setException(cause)).isTrue(); 67 assertFailed(future, cause); 68 } 69 testCanceled()70 public void testCanceled() throws Exception { 71 assertThat(future.cancel(false /* mayInterruptIfRunning */)).isTrue(); 72 assertCancelled(future, false); 73 } 74 testInterrupted()75 public void testInterrupted() throws Exception { 76 assertThat(future.cancel(true /* mayInterruptIfRunning */)).isTrue(); 77 assertCancelled(future, true); 78 } 79 testSetFuturePending()80 public void testSetFuturePending() throws Exception { 81 assertThat(future.setFuture(delegate)).isTrue(); 82 assertSetAsynchronously(future); 83 } 84 testSetFutureThenCancel()85 public void testSetFutureThenCancel() throws Exception { 86 assertThat(future.setFuture(delegate)).isTrue(); 87 assertThat(future.cancel(false /* mayInterruptIfRunning */)).isTrue(); 88 assertCancelled(future, false); 89 assertCancelled(delegate, false); 90 } 91 testSetFutureThenInterrupt()92 public void testSetFutureThenInterrupt() throws Exception { 93 assertThat(future.setFuture(delegate)).isTrue(); 94 assertThat(future.cancel(true /* mayInterruptIfRunning */)).isTrue(); 95 assertCancelled(future, true); 96 assertCancelled(delegate, true); 97 } 98 testSetFutureDelegateAlreadySuccessful()99 public void testSetFutureDelegateAlreadySuccessful() throws Exception { 100 delegate.set(5); 101 assertThat(future.setFuture(delegate)).isTrue(); 102 assertSuccessful(future, 5); 103 } 104 testSetFutureDelegateLaterSuccessful()105 public void testSetFutureDelegateLaterSuccessful() throws Exception { 106 assertThat(future.setFuture(delegate)).isTrue(); 107 delegate.set(6); 108 assertSuccessful(future, 6); 109 } 110 testSetFutureDelegateAlreadyCancelled()111 public void testSetFutureDelegateAlreadyCancelled() throws Exception { 112 delegate.cancel( 113 false 114 /** mayInterruptIfRunning */ 115 ); 116 assertThat(future.setFuture(delegate)).isTrue(); 117 assertCancelled(future, false); 118 } 119 testSetFutureDelegateLaterCancelled()120 public void testSetFutureDelegateLaterCancelled() throws Exception { 121 assertThat(future.setFuture(delegate)).isTrue(); 122 delegate.cancel( 123 false 124 /** mayInterruptIfRunning */ 125 ); 126 assertCancelled(future, false); 127 } 128 testSetFutureDelegateAlreadyInterrupted()129 public void testSetFutureDelegateAlreadyInterrupted() throws Exception { 130 delegate.cancel( 131 true 132 /** mayInterruptIfRunning */ 133 ); 134 assertThat(future.setFuture(delegate)).isTrue(); 135 assertCancelled(future, /* expectWasInterrupted= */ false); 136 } 137 testSetFutureDelegateLaterInterrupted()138 public void testSetFutureDelegateLaterInterrupted() throws Exception { 139 assertThat(future.setFuture(delegate)).isTrue(); 140 delegate.cancel( 141 true 142 /** mayInterruptIfRunning */ 143 ); 144 assertCancelled(future, /* expectWasInterrupted= */ false); 145 } 146 testListenLaterSuccessful()147 public void testListenLaterSuccessful() { 148 CountingRunnable listener = new CountingRunnable(); 149 150 future.addListener(listener, directExecutor()); 151 listener.assertNotRun(); 152 153 future.set(1); 154 listener.assertRun(); 155 } 156 testListenLaterFailed()157 public void testListenLaterFailed() { 158 CountingRunnable listener = new CountingRunnable(); 159 160 future.addListener(listener, directExecutor()); 161 listener.assertNotRun(); 162 163 future.setException(new Exception()); 164 listener.assertRun(); 165 } 166 testListenLaterCancelled()167 public void testListenLaterCancelled() { 168 CountingRunnable listener = new CountingRunnable(); 169 170 future.addListener(listener, directExecutor()); 171 listener.assertNotRun(); 172 173 future.cancel(false); 174 listener.assertRun(); 175 } 176 testListenLaterInterrupted()177 public void testListenLaterInterrupted() { 178 CountingRunnable listener = new CountingRunnable(); 179 180 future.addListener(listener, directExecutor()); 181 listener.assertNotRun(); 182 183 future.cancel(true); 184 listener.assertRun(); 185 } 186 testListenLaterSetAsynchronously()187 public void testListenLaterSetAsynchronously() { 188 CountingRunnable listener = new CountingRunnable(); 189 190 future.addListener(listener, directExecutor()); 191 listener.assertNotRun(); 192 193 future.setFuture(delegate); 194 listener.assertNotRun(); 195 } 196 testListenLaterSetAsynchronouslyLaterDelegateSuccessful()197 public void testListenLaterSetAsynchronouslyLaterDelegateSuccessful() { 198 CountingRunnable before = new CountingRunnable(); 199 CountingRunnable inBetween = new CountingRunnable(); 200 CountingRunnable after = new CountingRunnable(); 201 202 future.addListener(before, directExecutor()); 203 future.setFuture(delegate); 204 future.addListener(inBetween, directExecutor()); 205 delegate.set(1); 206 future.addListener(after, directExecutor()); 207 208 before.assertRun(); 209 inBetween.assertRun(); 210 after.assertRun(); 211 } 212 testListenLaterSetAsynchronouslyLaterDelegateFailed()213 public void testListenLaterSetAsynchronouslyLaterDelegateFailed() { 214 CountingRunnable before = new CountingRunnable(); 215 CountingRunnable inBetween = new CountingRunnable(); 216 CountingRunnable after = new CountingRunnable(); 217 218 future.addListener(before, directExecutor()); 219 future.setFuture(delegate); 220 future.addListener(inBetween, directExecutor()); 221 delegate.setException(new Exception()); 222 future.addListener(after, directExecutor()); 223 224 before.assertRun(); 225 inBetween.assertRun(); 226 after.assertRun(); 227 } 228 testListenLaterSetAsynchronouslyLaterDelegateCancelled()229 public void testListenLaterSetAsynchronouslyLaterDelegateCancelled() { 230 CountingRunnable before = new CountingRunnable(); 231 CountingRunnable inBetween = new CountingRunnable(); 232 CountingRunnable after = new CountingRunnable(); 233 234 future.addListener(before, directExecutor()); 235 future.setFuture(delegate); 236 future.addListener(inBetween, directExecutor()); 237 delegate.cancel(false); 238 future.addListener(after, directExecutor()); 239 240 before.assertRun(); 241 inBetween.assertRun(); 242 after.assertRun(); 243 } 244 testListenLaterSetAsynchronouslyLaterDelegateInterrupted()245 public void testListenLaterSetAsynchronouslyLaterDelegateInterrupted() { 246 CountingRunnable before = new CountingRunnable(); 247 CountingRunnable inBetween = new CountingRunnable(); 248 CountingRunnable after = new CountingRunnable(); 249 250 future.addListener(before, directExecutor()); 251 future.setFuture(delegate); 252 future.addListener(inBetween, directExecutor()); 253 delegate.cancel(true); 254 future.addListener(after, directExecutor()); 255 256 before.assertRun(); 257 inBetween.assertRun(); 258 after.assertRun(); 259 } 260 testListenLaterSetAsynchronouslyLaterSelfCancelled()261 public void testListenLaterSetAsynchronouslyLaterSelfCancelled() { 262 CountingRunnable before = new CountingRunnable(); 263 CountingRunnable inBetween = new CountingRunnable(); 264 CountingRunnable after = new CountingRunnable(); 265 266 future.addListener(before, directExecutor()); 267 future.setFuture(delegate); 268 future.addListener(inBetween, directExecutor()); 269 future.cancel(false); 270 future.addListener(after, directExecutor()); 271 272 before.assertRun(); 273 inBetween.assertRun(); 274 after.assertRun(); 275 } 276 testListenLaterSetAsynchronouslyLaterSelfInterrupted()277 public void testListenLaterSetAsynchronouslyLaterSelfInterrupted() { 278 CountingRunnable before = new CountingRunnable(); 279 CountingRunnable inBetween = new CountingRunnable(); 280 CountingRunnable after = new CountingRunnable(); 281 282 future.addListener(before, directExecutor()); 283 future.setFuture(delegate); 284 future.addListener(inBetween, directExecutor()); 285 future.cancel(true); 286 future.addListener(after, directExecutor()); 287 288 before.assertRun(); 289 inBetween.assertRun(); 290 after.assertRun(); 291 } 292 testMisbehavingListenerAlreadyDone()293 public void testMisbehavingListenerAlreadyDone() { 294 class BadRunnableException extends RuntimeException {} 295 296 Runnable bad = 297 new Runnable() { 298 @Override 299 public void run() { 300 throw new BadRunnableException(); 301 } 302 }; 303 304 future.set(1); 305 future.addListener(bad, directExecutor()); // BadRunnableException must not propagate. 306 } 307 testMisbehavingListenerLaterDone()308 public void testMisbehavingListenerLaterDone() { 309 class BadRunnableException extends RuntimeException {} 310 311 CountingRunnable before = new CountingRunnable(); 312 Runnable bad = 313 new Runnable() { 314 @Override 315 public void run() { 316 throw new BadRunnableException(); 317 } 318 }; 319 CountingRunnable after = new CountingRunnable(); 320 321 future.addListener(before, directExecutor()); 322 future.addListener(bad, directExecutor()); 323 future.addListener(after, directExecutor()); 324 325 future.set(1); // BadRunnableException must not propagate. 326 327 before.assertRun(); 328 after.assertRun(); 329 } 330 testNullListener()331 public void testNullListener() { 332 try { 333 future.addListener(null, directExecutor()); 334 fail(); 335 } catch (NullPointerException expected) { 336 } 337 } 338 testNullExecutor()339 public void testNullExecutor() { 340 try { 341 future.addListener(doNothing(), null); 342 fail(); 343 } catch (NullPointerException expected) { 344 } 345 } 346 testNullTimeUnit()347 public void testNullTimeUnit() throws Exception { 348 future.set(1); 349 try { 350 future.get(0, null); 351 fail(); 352 } catch (NullPointerException expected) { 353 } 354 } 355 testNegativeTimeout()356 public void testNegativeTimeout() throws Exception { 357 future.set(1); 358 assertEquals(1, future.get(-1, SECONDS).intValue()); 359 } 360 361 @GwtIncompatible // threads 362 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, Integer expectedResult)447 private static void assertSuccessful(AbstractFuture<Integer> future, Integer expectedResult) 448 throws InterruptedException, TimeoutException, ExecutionException { 449 assertDone(future); 450 assertThat(future.isCancelled()).isFalse(); 451 452 assertThat(getDone(future)).isEqualTo(expectedResult); 453 assertThat(getDoneFromTimeoutOverload(future)).isEqualTo(expectedResult); 454 } 455 assertFailed(AbstractFuture<Integer> future, Throwable expectedException)456 private static void assertFailed(AbstractFuture<Integer> future, Throwable expectedException) 457 throws InterruptedException, TimeoutException { 458 assertDone(future); 459 assertThat(future.isCancelled()).isFalse(); 460 461 try { 462 getDone(future); 463 fail(); 464 } catch (ExecutionException e) { 465 assertThat(e.getCause()).isSameAs(expectedException); 466 } 467 468 try { 469 getDoneFromTimeoutOverload(future); 470 fail(); 471 } catch (ExecutionException e) { 472 assertThat(e).hasCauseThat().isSameAs(expectedException); 473 } 474 } 475 assertCancelled(AbstractFuture<Integer> future, boolean expectWasInterrupted)476 private static void assertCancelled(AbstractFuture<Integer> future, boolean expectWasInterrupted) 477 throws InterruptedException, TimeoutException, ExecutionException { 478 assertDone(future); 479 assertThat(future.isCancelled()).isTrue(); 480 assertThat(future.wasInterrupted()).isEqualTo(expectWasInterrupted); 481 482 try { 483 getDone(future); 484 fail(); 485 } catch (CancellationException expected) { 486 } 487 488 try { 489 getDoneFromTimeoutOverload(future); 490 fail(); 491 } catch (CancellationException expected) { 492 } 493 } 494 assertDone(AbstractFuture<Integer> future)495 private static void assertDone(AbstractFuture<Integer> future) { 496 CountingRunnable listener = new CountingRunnable(); 497 future.addListener(listener, directExecutor()); 498 listener.assertRun(); 499 500 assertThat(future.isDone()).isTrue(); 501 assertCannotSet(future); 502 assertCannotCancel(future); 503 } 504 assertCannotSet(AbstractFuture<Integer> future)505 private static void assertCannotSet(AbstractFuture<Integer> future) { 506 assertThat(future.set(99)).isFalse(); 507 assertThat(future.setException(new IndexOutOfBoundsException())).isFalse(); 508 assertThat(future.setFuture(new AbstractFuture<Integer>() {})).isFalse(); 509 assertThat(future.setFuture(immediateFuture(99))).isFalse(); 510 } 511 assertCannotCancel(AbstractFuture<Integer> future)512 private static void assertCannotCancel(AbstractFuture<Integer> future) { 513 assertThat(future.cancel(true)).isFalse(); 514 assertThat(future.cancel(false)).isFalse(); 515 } 516 } 517