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