From e8ed39cb01d8410412e00e625cb3d92652c591ed Mon Sep 17 00:00:00 2001 From: Dawid Weiss Date: Wed, 12 Sep 2012 08:20:32 +0000 Subject: [PATCH] LUCENE-4252: Detect/Fail tests when they leak RAM in static fields. git-svn-id: https://svn.apache.org/repos/asf/lucene/dev/trunk@1383841 13f79535-47bb-0310-9956-ffa450edef68 --- lucene/CHANGES.txt | 3 +++ .../apache/lucene/util/LuceneTestCase.java | 21 +++++++++++++++++++ .../util/TestRuleAssertionsRequired.java | 5 ++++- 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/lucene/CHANGES.txt b/lucene/CHANGES.txt index 44b1c477bfd..f7ea4e1614f 100644 --- a/lucene/CHANGES.txt +++ b/lucene/CHANGES.txt @@ -165,6 +165,9 @@ Optimizations Build +* LUCENE-4252: Detect/Fail tests when they leak RAM in static fields + (Robert Muir, Dawid Weiss) + * LUCENE-4360: Support running the same test suite multiple times in parallel (Dawid Weiss) diff --git a/lucene/test-framework/src/java/org/apache/lucene/util/LuceneTestCase.java b/lucene/test-framework/src/java/org/apache/lucene/util/LuceneTestCase.java index c0c9bc48471..03187a25e1f 100644 --- a/lucene/test-framework/src/java/org/apache/lucene/util/LuceneTestCase.java +++ b/lucene/test-framework/src/java/org/apache/lucene/util/LuceneTestCase.java @@ -52,6 +52,7 @@ import com.carrotsearch.randomizedtesting.annotations.ThreadLeakZombies.Conseque import com.carrotsearch.randomizedtesting.generators.RandomPicks; import com.carrotsearch.randomizedtesting.rules.NoClassHooksShadowingRule; import com.carrotsearch.randomizedtesting.rules.NoInstanceHooksOverridesRule; +import com.carrotsearch.randomizedtesting.rules.StaticFieldsInvariantRule; import com.carrotsearch.randomizedtesting.rules.SystemPropertiesInvariantRule; import static com.carrotsearch.randomizedtesting.RandomizedTest.systemPropertyAsBoolean; @@ -364,6 +365,18 @@ public abstract class LuceneTestCase extends Assert { ignoreAfterMaxFailures = new TestRuleIgnoreAfterMaxFailures(maxFailures); } + /** + * Max 10mb of static data stored in a test suite class after the suite is complete. + * Prevents static data structures leaking and causing OOMs in subsequent tests. + */ + private final static long STATIC_LEAK_THRESHOLD = 10 * 1024 * 1024; + + /** By-name list of ignored types like loggers etc. */ + private final static Set STATIC_LEAK_IGNORED_TYPES = + Collections.unmodifiableSet(new HashSet(Arrays.asList( + "org.slf4j.Logger", + "org.apache.solr.SolrLogFormatter"))); + /** * This controls how suite-level rules are nested. It is important that _all_ rules declared * in {@link LuceneTestCase} are executed in proper order if they depend on each @@ -375,6 +388,14 @@ public abstract class LuceneTestCase extends Assert { .around(ignoreAfterMaxFailures) .around(suiteFailureMarker) .around(new TestRuleAssertionsRequired()) + .around(new StaticFieldsInvariantRule(STATIC_LEAK_THRESHOLD, true) { + protected boolean accept(java.lang.reflect.Field field) { + if (STATIC_LEAK_IGNORED_TYPES.contains(field.getType().getName())) { + return false; + } + return super.accept(field); + } + }) .around(new NoClassHooksShadowingRule()) .around(new NoInstanceHooksOverridesRule() { @Override diff --git a/lucene/test-framework/src/java/org/apache/lucene/util/TestRuleAssertionsRequired.java b/lucene/test-framework/src/java/org/apache/lucene/util/TestRuleAssertionsRequired.java index 48223630a7f..42dd64b4768 100644 --- a/lucene/test-framework/src/java/org/apache/lucene/util/TestRuleAssertionsRequired.java +++ b/lucene/test-framework/src/java/org/apache/lucene/util/TestRuleAssertionsRequired.java @@ -32,7 +32,10 @@ public class TestRuleAssertionsRequired implements TestRule { public void evaluate() throws Throwable { try { assert false; - throw new Exception("Test class requires assertions, enable assertions globally (-ea) or for Solr/Lucene subpackages only."); + String msg = "Test class requires enabled assertions, enable globally (-ea)" + + " or for Solr/Lucene subpackages only: " + description.getClassName(); + System.err.println(msg); + throw new Exception(msg); } catch (AssertionError e) { // Ok, enabled. }