package xapi.test.util; import org.junit.Assert; import org.junit.Test; import xapi.annotation.gc.OnGC; import xapi.test.AbstractInjectionTest; import xapi.time.X_Time; import xapi.util.X_GC; @OnGC( chainDeleteFields = true ,deleteInstanceFields = true ,staticGCMethods = "xapi.test.util.GCTest$Utils#destroy" ,instanceGCMethods = "destroy" ) public class GCTest extends AbstractInjectionTest{ //Won't get destroyed, but lets us check that it's fields were cleared private static final Utils TheUtils = new Utils(); // Some fields to destroy Utils util = TheUtils; // will be null int primitive = 10; // won't be touched (primitives) boolean destroyed = false; // ditto static boolean destroyed_static = false; // gets called in static destroy String str = "hasValue"; // will be null // Tests GC chaining @OnGC(deleteInstanceFields=true) static class Utils { // will be destroyed Object object = new Object(); // will get called first public static void destroy(final Object o) { destroyed_static = true; // make sure we get called first Assert.assertNotNull(((GCTest)o).util); X_Time.runLater(new Runnable() { @Override public void run() { // wait a bit, since run later can't promise how much later; // 10 millis is plenty to wait from static destroy 'til fields cleared. X_Time.trySleep(10, 0); Assert.assertNull(TheUtils.object); Assert.assertNull(((GCTest)o).util); } }); } } @Test public void testGC() { X_GC.destroy(GCTest.class, this); Assert.assertNull(str); Assert.assertTrue(destroyed); Assert.assertTrue(destroyed_static); // primitives don't get gc'd Assert.assertEquals(primitive, 10); // give time for Utils to run its assert X_Time.trySleep(500, 0); } public void destroy() { destroyed = true; } }