Home | History | Annotate | Download | only in testing
      1 // Copyright 2011 Google Inc. All Rights Reserved.
      2 
      3 package com.google.common.testing;
      4 
      5 import com.google.common.testing.GcFinalization.FinalizationPredicate;
      6 import com.google.common.util.concurrent.SettableFuture;
      7 
      8 import junit.framework.TestCase;
      9 
     10 import java.lang.ref.WeakReference;
     11 import java.util.WeakHashMap;
     12 import java.util.concurrent.CountDownLatch;
     13 import java.util.concurrent.atomic.AtomicBoolean;
     14 
     15 /**
     16  * Tests for {@link GcFinalization}.
     17  *
     18  * @author martinrb (at) google.com (Martin Buchholz)
     19  * @author schmoe (at) google.com (mike nonemacher)
     20  */
     21 
     22 public class GcFinalizationTest extends TestCase {
     23 
     24   //----------------------------------------------------------------
     25   // Ordinary tests of successful method execution
     26   //----------------------------------------------------------------
     27 
     28   public void testAwait_CountDownLatch() {
     29     final CountDownLatch latch = new CountDownLatch(1);
     30     Object x = new Object() {
     31       protected void finalize() { latch.countDown(); }
     32     };
     33     x = null;  // Hint to the JIT that x is unreachable
     34     GcFinalization.await(latch);
     35     assertEquals(0, latch.getCount());
     36   }
     37 
     38   public void testAwaitDone_Future() {
     39     final SettableFuture<Void> future = SettableFuture.create();
     40     Object x = new Object() {
     41       protected void finalize() { future.set(null); }
     42     };
     43     x = null;  // Hint to the JIT that x is unreachable
     44     GcFinalization.awaitDone(future);
     45     assertTrue(future.isDone());
     46     assertFalse(future.isCancelled());
     47   }
     48 
     49   public void testAwaitDone_Future_Cancel() {
     50     final SettableFuture<Void> future = SettableFuture.create();
     51     Object x = new Object() {
     52       protected void finalize() { future.cancel(false); }
     53     };
     54     x = null;  // Hint to the JIT that x is unreachable
     55     GcFinalization.awaitDone(future);
     56     assertTrue(future.isDone());
     57     assertTrue(future.isCancelled());
     58   }
     59 
     60   public void testAwaitClear() {
     61     final WeakReference<Object> ref = new WeakReference<Object>(new Object());
     62     GcFinalization.awaitClear(ref);
     63     assertNull(ref.get());
     64   }
     65 
     66   public void testAwaitDone_FinalizationPredicate() {
     67     final WeakHashMap<Object, Object> map = new WeakHashMap<Object, Object>();
     68     map.put(new Object(), Boolean.TRUE);
     69     GcFinalization.awaitDone(new FinalizationPredicate() {
     70       public boolean isDone() {
     71         return map.isEmpty();
     72       }
     73     });
     74     assertTrue(map.isEmpty());
     75   }
     76 
     77   //----------------------------------------------------------------
     78   // Test that interrupts result in RuntimeException, not InterruptedException.
     79   // Trickier than it looks, because runFinalization swallows interrupts.
     80   //----------------------------------------------------------------
     81 
     82   class Interruptenator extends Thread {
     83     final AtomicBoolean shutdown;
     84     Interruptenator(final Thread interruptee) {
     85       this(interruptee, new AtomicBoolean(false));
     86     }
     87     Interruptenator(final Thread interruptee,
     88                     final AtomicBoolean shutdown) {
     89       super(new Runnable() {
     90           public void run() {
     91             while (!shutdown.get()) {
     92               interruptee.interrupt();
     93               Thread.yield();
     94             }}});
     95       this.shutdown = shutdown;
     96       start();
     97     }
     98     void shutdown() {
     99       shutdown.set(true);
    100       while (this.isAlive()) {
    101         Thread.yield();
    102       }
    103     }
    104   }
    105 
    106   void assertWrapsInterruptedException(RuntimeException e) {
    107     assertTrue(e.getMessage().contains("Unexpected interrupt"));
    108     assertTrue(e.getCause() instanceof InterruptedException);
    109   }
    110 
    111   public void testAwait_CountDownLatch_Interrupted() {
    112     Interruptenator interruptenator = new Interruptenator(Thread.currentThread());
    113     try {
    114       final CountDownLatch latch = new CountDownLatch(1);
    115       try {
    116         GcFinalization.await(latch);
    117         fail("should throw");
    118       } catch (RuntimeException expected) {
    119         assertWrapsInterruptedException(expected);
    120       }
    121     } finally {
    122       interruptenator.shutdown();
    123       Thread.interrupted();
    124     }
    125   }
    126 
    127   public void testAwaitDone_Future_Interrupted_Interrupted() {
    128     Interruptenator interruptenator = new Interruptenator(Thread.currentThread());
    129     try {
    130       final SettableFuture<Void> future = SettableFuture.create();
    131       try {
    132         GcFinalization.awaitDone(future);
    133         fail("should throw");
    134       } catch (RuntimeException expected) {
    135         assertWrapsInterruptedException(expected);
    136       }
    137     } finally {
    138       interruptenator.shutdown();
    139       Thread.interrupted();
    140     }
    141   }
    142 
    143   public void testAwaitClear_Interrupted() {
    144     Interruptenator interruptenator = new Interruptenator(Thread.currentThread());
    145     try {
    146       final WeakReference<Object> ref = new WeakReference<Object>(Boolean.TRUE);
    147       try {
    148         GcFinalization.awaitClear(ref);
    149         fail("should throw");
    150       } catch (RuntimeException expected) {
    151         assertWrapsInterruptedException(expected);
    152       }
    153     } finally {
    154       interruptenator.shutdown();
    155       Thread.interrupted();
    156     }
    157   }
    158 
    159   public void testAwaitDone_FinalizationPredicate_Interrupted() {
    160     Interruptenator interruptenator = new Interruptenator(Thread.currentThread());
    161     try {
    162       try {
    163         GcFinalization.awaitDone(new FinalizationPredicate() {
    164             public boolean isDone() {
    165               return false;
    166             }
    167           });
    168         fail("should throw");
    169       } catch (RuntimeException expected) {
    170         assertWrapsInterruptedException(expected);
    171       }
    172     } finally {
    173       interruptenator.shutdown();
    174       Thread.interrupted();
    175     }
    176   }
    177 
    178 }
    179