aboutsummaryrefslogtreecommitdiff
path: root/test/dotty/tools/ContextEscapeDetector.java
diff options
context:
space:
mode:
authorFelix Mulder <felix.mulder@gmail.com>2016-11-01 18:34:29 +0100
committerGuillaume Martres <smarter@ubuntu.com>2016-11-22 01:35:07 +0100
commit6a455fe6da5ff9c741d91279a2dc6fe2fb1b472f (patch)
treefe7729ddb03a84728687d5a3068f520b0bc1c297 /test/dotty/tools/ContextEscapeDetector.java
parentb3855424280a821601f126b6b4c6a731b72540ea (diff)
downloaddotty-6a455fe6da5ff9c741d91279a2dc6fe2fb1b472f.tar.gz
dotty-6a455fe6da5ff9c741d91279a2dc6fe2fb1b472f.tar.bz2
dotty-6a455fe6da5ff9c741d91279a2dc6fe2fb1b472f.zip
Move (most) unit tests to correct locations
Should still perhaps move `test/dotc/tests.scala` and the others in the same directory to a better more cohesive location. Would like to delete the worksheets as well - but maybe they hold sentimental value...
Diffstat (limited to 'test/dotty/tools/ContextEscapeDetector.java')
-rw-r--r--test/dotty/tools/ContextEscapeDetector.java108
1 files changed, 108 insertions, 0 deletions
diff --git a/test/dotty/tools/ContextEscapeDetector.java b/test/dotty/tools/ContextEscapeDetector.java
new file mode 100644
index 000000000..e19fc5a64
--- /dev/null
+++ b/test/dotty/tools/ContextEscapeDetector.java
@@ -0,0 +1,108 @@
+package dotty.tools;
+
+import org.junit.runner.Result;
+import org.junit.runner.notification.RunListener;
+import org.junit.Assert;
+import java.lang.ref.WeakReference;
+
+public class ContextEscapeDetector extends RunListener {
+
+ //context can be captured by objects, eg NoDenotation
+ public static final int CONTEXTS_ALLOWED = 1;
+
+ @Override
+ public void testRunFinished(Result result) throws Exception {
+ if (contextsAlive() > CONTEXTS_ALLOWED) {
+ forceGCHeuristic0();
+ if (contextsAlive() > CONTEXTS_ALLOWED) {
+ forceGCHeuristic1();
+ if (contextsAlive() > CONTEXTS_ALLOWED) {
+ forceGCHeuristic2();
+ forceGCHeuristic1();
+ int contextAlive = contextsAlive();
+ if (contextAlive > CONTEXTS_ALLOWED) {
+ StringBuilder names = new StringBuilder();
+ for (ContextEscapeDetection.TestContext ref : ContextEscapeDetection.contexts) {
+ if (ref.context.get() != null) names.append(ref.testName).append(' ');
+ }
+ Assert.fail("Multiple contexts survived test suite: " + names.toString());
+ }
+ }
+ }
+ }
+ super.testRunFinished(result);
+ }
+
+ private static synchronized int contextsAlive() {
+ int count = 0;
+ for (ContextEscapeDetection.TestContext ref : ContextEscapeDetection.contexts) {
+ if (ref.context.get() != null) count++;
+ }
+ return count;
+ }
+
+ @SuppressWarnings("unused")
+ private static volatile Object o = null;
+
+ private static synchronized void forceGCHeuristic0() {
+ System.gc();
+ Runtime.getRuntime().gc();
+ System.gc();
+ Runtime.getRuntime().gc();
+ System.gc();
+ Runtime.getRuntime().gc();
+ System.gc();
+ Runtime.getRuntime().gc();
+ System.gc();
+ }
+
+ private static synchronized void forceGCHeuristic1() {
+ Object obj = new Object();
+ WeakReference<Object> ref = new WeakReference<>(obj);
+ obj = null;
+ while (ref.get() != null) {
+ System.gc();
+ }
+ }
+
+ private static synchronized void forceGCHeuristic2() {
+ try {
+ Object[] arr = new Object[1024]; // upto 8 GB
+ WeakReference<Object> ref = new WeakReference<>(arr);
+ o = arr; // make sure array isn't optimized away
+
+ Runtime runtime = Runtime.getRuntime();
+ // allocate memory until no more that 64MB is left
+ for (int i = 0; i < 1024 &&
+ runtime.totalMemory() != runtime.maxMemory() ||
+ runtime.freeMemory() < 1024 * 1024 * 64; i++) {
+ int[] data = new int[1024 * 1024]; // 8MB
+ for (int j = 0; j < 1024 * 1024; j++) {
+ data[j] = j; // force actual pages allocation
+ }
+ arr[i] = data;
+ }
+ o = null;
+ arr = new Object[128];
+ o = arr;
+ // allocate 1 more GB
+ for (int i = 0; i < 128; i++) {
+ int[] data = new int[1024 * 1024]; // 8MB
+ for (int j = 0; j < 1024 * 1024; j++) {
+ data[j] = j; // force actual pages allocation
+ }
+ arr[i] = data;
+ }
+ o = null;
+ arr = null;
+
+ forceGCHeuristic0();
+ while (ref.get() != null) {
+ System.gc();
+ }
+ } catch (OutOfMemoryError e) {
+ o = null;
+ // just swallow
+ }
+ }
+}