11d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert// Copyright 2011 Google Inc. All Rights Reserved. 21d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 31d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertpackage com.google.common.testing; 41d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 51d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.testing.GcFinalization.FinalizationPredicate; 61d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.util.concurrent.SettableFuture; 71d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 81d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport junit.framework.TestCase; 91d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.lang.ref.WeakReference; 111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.WeakHashMap; 121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.concurrent.CountDownLatch; 131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.concurrent.atomic.AtomicBoolean; 141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert/** 161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Tests for {@link GcFinalization}. 171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @author martinrb@google.com (Martin Buchholz) 191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @author schmoe@google.com (mike nonemacher) 201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertpublic class GcFinalizationTest extends TestCase { 231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert //---------------------------------------------------------------- 251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // Ordinary tests of successful method execution 261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert //---------------------------------------------------------------- 271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public void testAwait_CountDownLatch() { 291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert final CountDownLatch latch = new CountDownLatch(1); 301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Object x = new Object() { 311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert protected void finalize() { latch.countDown(); } 321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert }; 331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert x = null; // Hint to the JIT that x is unreachable 341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert GcFinalization.await(latch); 351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals(0, latch.getCount()); 361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public void testAwaitDone_Future() { 391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert final SettableFuture<Void> future = SettableFuture.create(); 401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Object x = new Object() { 411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert protected void finalize() { future.set(null); } 421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert }; 431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert x = null; // Hint to the JIT that x is unreachable 441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert GcFinalization.awaitDone(future); 451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertTrue(future.isDone()); 461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertFalse(future.isCancelled()); 471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public void testAwaitDone_Future_Cancel() { 501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert final SettableFuture<Void> future = SettableFuture.create(); 511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Object x = new Object() { 521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert protected void finalize() { future.cancel(false); } 531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert }; 541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert x = null; // Hint to the JIT that x is unreachable 551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert GcFinalization.awaitDone(future); 561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertTrue(future.isDone()); 571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertTrue(future.isCancelled()); 581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public void testAwaitClear() { 611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert final WeakReference<Object> ref = new WeakReference<Object>(new Object()); 621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert GcFinalization.awaitClear(ref); 631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertNull(ref.get()); 641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public void testAwaitDone_FinalizationPredicate() { 671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert final WeakHashMap<Object, Object> map = new WeakHashMap<Object, Object>(); 681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert map.put(new Object(), Boolean.TRUE); 691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert GcFinalization.awaitDone(new FinalizationPredicate() { 701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public boolean isDone() { 711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return map.isEmpty(); 721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert }); 741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertTrue(map.isEmpty()); 751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert //---------------------------------------------------------------- 781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // Test that interrupts result in RuntimeException, not InterruptedException. 791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // Trickier than it looks, because runFinalization swallows interrupts. 801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert //---------------------------------------------------------------- 811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert class Interruptenator extends Thread { 831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert final AtomicBoolean shutdown; 841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Interruptenator(final Thread interruptee) { 851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert this(interruptee, new AtomicBoolean(false)); 861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Interruptenator(final Thread interruptee, 881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert final AtomicBoolean shutdown) { 891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert super(new Runnable() { 901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public void run() { 911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert while (!shutdown.get()) { 921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert interruptee.interrupt(); 931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Thread.yield(); 941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert }}}); 951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert this.shutdown = shutdown; 961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert start(); 971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert void shutdown() { 991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert shutdown.set(true); 1001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert while (this.isAlive()) { 1011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Thread.yield(); 1021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert void assertWrapsInterruptedException(RuntimeException e) { 1071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertTrue(e.getMessage().contains("Unexpected interrupt")); 1081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertTrue(e.getCause() instanceof InterruptedException); 1091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public void testAwait_CountDownLatch_Interrupted() { 1121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Interruptenator interruptenator = new Interruptenator(Thread.currentThread()); 1131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert try { 1141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert final CountDownLatch latch = new CountDownLatch(1); 1151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert try { 1161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert GcFinalization.await(latch); 1171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert fail("should throw"); 1181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } catch (RuntimeException expected) { 1191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertWrapsInterruptedException(expected); 1201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } finally { 1221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert interruptenator.shutdown(); 1231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Thread.interrupted(); 1241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public void testAwaitDone_Future_Interrupted_Interrupted() { 1281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Interruptenator interruptenator = new Interruptenator(Thread.currentThread()); 1291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert try { 1301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert final SettableFuture<Void> future = SettableFuture.create(); 1311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert try { 1321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert GcFinalization.awaitDone(future); 1331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert fail("should throw"); 1341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } catch (RuntimeException expected) { 1351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertWrapsInterruptedException(expected); 1361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } finally { 1381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert interruptenator.shutdown(); 1391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Thread.interrupted(); 1401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public void testAwaitClear_Interrupted() { 1441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Interruptenator interruptenator = new Interruptenator(Thread.currentThread()); 1451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert try { 1461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert final WeakReference<Object> ref = new WeakReference<Object>(Boolean.TRUE); 1471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert try { 1481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert GcFinalization.awaitClear(ref); 1491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert fail("should throw"); 1501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } catch (RuntimeException expected) { 1511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertWrapsInterruptedException(expected); 1521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } finally { 1541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert interruptenator.shutdown(); 1551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Thread.interrupted(); 1561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public void testAwaitDone_FinalizationPredicate_Interrupted() { 1601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Interruptenator interruptenator = new Interruptenator(Thread.currentThread()); 1611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert try { 1621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert try { 1631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert GcFinalization.awaitDone(new FinalizationPredicate() { 1641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public boolean isDone() { 1651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return false; 1661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert }); 1681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert fail("should throw"); 1691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } catch (RuntimeException expected) { 1701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertWrapsInterruptedException(expected); 1711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } finally { 1731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert interruptenator.shutdown(); 1741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Thread.interrupted(); 1751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert} 179