You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by dw...@apache.org on 2012/02/14 11:27:17 UTC

svn commit: r1243863 - in /lucene/dev/trunk: dev-tools/eclipse/ dev-tools/idea/.idea/libraries/ lucene/ lucene/contrib/misc/src/java/org/apache/lucene/store/ lucene/core/src/test/org/apache/lucene/index/ lucene/core/src/test/org/apache/lucene/util/fst/...

Author: dweiss
Date: Tue Feb 14 10:27:16 2012
New Revision: 1243863

URL: http://svn.apache.org/viewvc?rev=1243863&view=rev
Log:
LUCENE-3762: Upgrade JUnit to 4.10, refactor state-machine of detecting
setUp/tearDown call chaining.

Added:
    lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/util/junitcompat/
    lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/util/junitcompat/SorePoint.java
    lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/util/junitcompat/SoreType.java
    lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/util/junitcompat/TestJUnitRuleOrder.java
    lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/util/junitcompat/TestSetupTeardownChaining.java
    lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/util/junitcompat/TestSorePointsReported.java
    lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/util/junitcompat/WithNestedTests.java
    lucene/dev/trunk/lucene/lib/junit-4.10.jar
    lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/util/InternalAssumptionViolatedException.java
    lucene/dev/trunk/solr/lib/junit-4.10.jar
Removed:
    lucene/dev/trunk/lucene/lib/junit-4.7.jar
    lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/util/_TestIgnoredException.java
    lucene/dev/trunk/solr/lib/junit-4.7.jar
Modified:
    lucene/dev/trunk/dev-tools/eclipse/dot.classpath
    lucene/dev/trunk/dev-tools/idea/.idea/libraries/JUnit.xml
    lucene/dev/trunk/lucene/NOTICE.txt
    lucene/dev/trunk/lucene/common-build.xml
    lucene/dev/trunk/lucene/contrib/misc/src/java/org/apache/lucene/store/NativePosixUtil.cpp
    lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/index/Test2BTerms.java
    lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/util/fst/TestFSTs.java
    lucene/dev/trunk/lucene/lib/junit-NOTICE.txt
    lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/util/LuceneTestCase.java
    lucene/dev/trunk/solr/NOTICE.txt

Modified: lucene/dev/trunk/dev-tools/eclipse/dot.classpath
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/dev-tools/eclipse/dot.classpath?rev=1243863&r1=1243862&r2=1243863&view=diff
==============================================================================
--- lucene/dev/trunk/dev-tools/eclipse/dot.classpath (original)
+++ lucene/dev/trunk/dev-tools/eclipse/dot.classpath Tue Feb 14 10:27:16 2012
@@ -87,7 +87,7 @@
 	<classpathentry kind="src" path="solr/contrib/velocity/src/test-files"/>
 	<classpathentry kind="lib" path="lucene/lib/ant-1.7.1.jar"/>
 	<classpathentry kind="lib" path="lucene/lib/ant-junit-1.7.1.jar"/>
-	<classpathentry kind="lib" path="lucene/lib/junit-4.7.jar"/>
+	<classpathentry kind="lib" path="lucene/lib/junit-4.10.jar"/>
 	<classpathentry kind="lib" path="lucene/contrib/sandbox/lib/jakarta-regexp-1.4.jar"/>
 	<classpathentry kind="lib" path="modules/analysis/icu/lib/icu4j-4_8_1_1.jar"/>
 	<classpathentry kind="lib" path="modules/analysis/phonetic/lib/commons-codec-1.6.jar"/>
@@ -109,7 +109,7 @@
 	<classpathentry kind="lib" path="solr/lib/easymock-2.2.jar"/>
 	<classpathentry kind="lib" path="solr/lib/guava-r05.jar"/>
 	<classpathentry kind="lib" path="solr/lib/jcl-over-slf4j-1.6.1.jar"/>
-	<classpathentry kind="lib" path="solr/lib/junit-4.7.jar"/>
+	<classpathentry kind="lib" path="solr/lib/junit-4.10.jar"/>
 	<classpathentry kind="lib" path="solr/lib/log4j-over-slf4j-1.6.1.jar"/>
 	<classpathentry kind="lib" path="solr/lib/servlet-api-2.4.jar"/>
 	<classpathentry kind="lib" path="solr/lib/slf4j-api-1.6.1.jar"/>

Modified: lucene/dev/trunk/dev-tools/idea/.idea/libraries/JUnit.xml
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/dev-tools/idea/.idea/libraries/JUnit.xml?rev=1243863&r1=1243862&r2=1243863&view=diff
==============================================================================
--- lucene/dev/trunk/dev-tools/idea/.idea/libraries/JUnit.xml (original)
+++ lucene/dev/trunk/dev-tools/idea/.idea/libraries/JUnit.xml Tue Feb 14 10:27:16 2012
@@ -1,7 +1,7 @@
 <component name="libraryTable">
   <library name="JUnit">
     <CLASSES>
-      <root url="jar://$PROJECT_DIR$/lucene/lib/junit-4.7.jar!/" />
+      <root url="jar://$PROJECT_DIR$/lucene/lib/junit-4.10.jar!/" />
     </CLASSES>
     <JAVADOC />
     <SOURCES />

Modified: lucene/dev/trunk/lucene/NOTICE.txt
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/NOTICE.txt?rev=1243863&r1=1243862&r2=1243863&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/NOTICE.txt (original)
+++ lucene/dev/trunk/lucene/NOTICE.txt Tue Feb 14 10:27:16 2012
@@ -36,7 +36,7 @@ the Apache CXF project and is Apache Lic
 The Google Code Prettify is Apache License 2.0.
 See http://code.google.com/p/google-code-prettify/
 
-JUnit (under lib/junit-4.7.jar) is licensed under the Common Public License v. 1.0
+JUnit (under lib/junit-4.10.jar) is licensed under the Common Public License v. 1.0
 See http://junit.sourceforge.net/cpl-v10.html
 
 JLine (under contrib/lucli/lib/jline.jar) is licensed under the BSD License.

Modified: lucene/dev/trunk/lucene/common-build.xml
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/common-build.xml?rev=1243863&r1=1243862&r2=1243863&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/common-build.xml (original)
+++ lucene/dev/trunk/lucene/common-build.xml Tue Feb 14 10:27:16 2012
@@ -52,7 +52,7 @@
   <property name="year" value="2000-${current.year}"/>
   <property name="final.name" value="lucene-${name}-${version}"/>
 
-  <property name="junit.jar" value="junit-4.7.jar"/>
+  <property name="junit.jar" value="junit-4.10.jar"/>
   <property name="junit-location.jar" value="${common.dir}/lib/${junit.jar}"/>
   <path id="junit-path">
     <pathelement location="${junit-location.jar}"/>

Modified: lucene/dev/trunk/lucene/contrib/misc/src/java/org/apache/lucene/store/NativePosixUtil.cpp
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/contrib/misc/src/java/org/apache/lucene/store/NativePosixUtil.cpp?rev=1243863&r1=1243862&r2=1243863&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/contrib/misc/src/java/org/apache/lucene/store/NativePosixUtil.cpp (original)
+++ lucene/dev/trunk/lucene/contrib/misc/src/java/org/apache/lucene/store/NativePosixUtil.cpp Tue Feb 14 10:27:16 2012
@@ -34,7 +34,7 @@
 #include <sys/types.h>  // constants for open
 #include <sys/stat.h>  // constants for open
 
-// java -cp .:lib/junit-4.7.jar:./build/classes/test:./build/classes/java:./build/classes/demo -Dlucene.version=2.9-dev -DtempDir=build -ea org.junit.runner.JUnitCore org.apache.lucene.index.TestDoc
+// java -cp .:lib/junit-4.10.jar:./build/classes/test:./build/classes/java:./build/classes/demo -Dlucene.version=2.9-dev -DtempDir=build -ea org.junit.runner.JUnitCore org.apache.lucene.index.TestDoc
 
 #ifdef LINUX
 /*

Modified: lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/index/Test2BTerms.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/index/Test2BTerms.java?rev=1243863&r1=1243862&r2=1243863&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/index/Test2BTerms.java (original)
+++ lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/index/Test2BTerms.java Tue Feb 14 10:27:16 2012
@@ -43,7 +43,7 @@ import org.junit.Ignore;
 //
 //   ant test -Dtest.slow=true -Dtests.heapsize=8g
 //
-//   java -server -Xmx8g -d64 -cp .:lib/junit-4.7.jar:./build/classes/test:./build/classes/test-framework:./build/classes/java -Dlucene.version=4.0-dev -Dtests.directory=MMapDirectory -DtempDir=build -ea org.junit.runner.JUnitCore org.apache.lucene.index.Test2BTerms
+//   java -server -Xmx8g -d64 -cp .:lib/junit-4.10.jar:./build/classes/test:./build/classes/test-framework:./build/classes/java -Dlucene.version=4.0-dev -Dtests.directory=MMapDirectory -DtempDir=build -ea org.junit.runner.JUnitCore org.apache.lucene.index.Test2BTerms
 //
 @LuceneTestCase.UseNoMemoryExpensiveCodec
 public class Test2BTerms extends LuceneTestCase {

Modified: lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/util/fst/TestFSTs.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/util/fst/TestFSTs.java?rev=1243863&r1=1243862&r2=1243863&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/util/fst/TestFSTs.java (original)
+++ lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/util/fst/TestFSTs.java Tue Feb 14 10:27:16 2012
@@ -1383,7 +1383,7 @@ public class TestFSTs extends LuceneTest
     }
   }
 
-  // java -cp build/classes/test:build/classes/test-framework:build/classes/java:lib/junit-4.7.jar org.apache.lucene.util.fst.TestFSTs /x/tmp/allTerms3.txt out
+  // java -cp build/classes/test:build/classes/test-framework:build/classes/java:lib/junit-4.10.jar org.apache.lucene.util.fst.TestFSTs /x/tmp/allTerms3.txt out
   public static void main(String[] args) throws IOException {
     int prune = 0;
     int limit = Integer.MAX_VALUE;

Added: lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/util/junitcompat/SorePoint.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/util/junitcompat/SorePoint.java?rev=1243863&view=auto
==============================================================================
--- lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/util/junitcompat/SorePoint.java (added)
+++ lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/util/junitcompat/SorePoint.java Tue Feb 14 10:27:16 2012
@@ -0,0 +1,16 @@
+package org.apache.lucene.util.junitcompat;
+
+/**
+ * A pointcut-like definition where we should trigger
+ * an assumption or error.
+ */
+public enum SorePoint {
+  // STATIC_INITIALIZER, // I assume this will result in JUnit failure to load a suite.
+  BEFORE_CLASS,
+  INITIALIZER,
+  RULE,
+  BEFORE,
+  TEST,
+  AFTER,
+  AFTER_CLASS
+}
\ No newline at end of file

Added: lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/util/junitcompat/SoreType.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/util/junitcompat/SoreType.java?rev=1243863&view=auto
==============================================================================
--- lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/util/junitcompat/SoreType.java (added)
+++ lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/util/junitcompat/SoreType.java Tue Feb 14 10:27:16 2012
@@ -0,0 +1,7 @@
+package org.apache.lucene.util.junitcompat;
+
+public enum SoreType {
+  ASSUMPTION,
+  FAILURE,
+  ERROR
+}

Added: lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/util/junitcompat/TestJUnitRuleOrder.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/util/junitcompat/TestJUnitRuleOrder.java?rev=1243863&view=auto
==============================================================================
--- lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/util/junitcompat/TestJUnitRuleOrder.java (added)
+++ lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/util/junitcompat/TestJUnitRuleOrder.java Tue Feb 14 10:27:16 2012
@@ -0,0 +1,75 @@
+package org.apache.lucene.util.junitcompat;
+
+import java.util.Arrays;
+import java.util.Stack;
+
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TestRule;
+import org.junit.runner.Description;
+import org.junit.runner.JUnitCore;
+import org.junit.runners.model.Statement;
+
+/**
+ * This verifies that JUnit {@link Rule}s are invoked before 
+ * {@link Before} and {@link  After} hooks. This should be the
+ * case from JUnit 4.10 on.
+ */
+public class TestJUnitRuleOrder extends WithNestedTests {
+  static Stack<String> stack;
+
+  public TestJUnitRuleOrder() {
+    super(true);
+  }
+  
+  public static class Nested extends WithNestedTests.AbstractNestedTest {
+    @Before
+    public void before() {
+      stack.push("@Before");
+    }
+    
+    @After
+    public void after() {
+      stack.push("@After");
+    }
+
+    @Rule
+    public TestRule testRule = new TestRule() {
+      @Override
+      public Statement apply(final Statement base, Description description) {
+        return new Statement() {
+          public void evaluate() throws Throwable {
+            stack.push("@Rule before");
+            base.evaluate();
+            stack.push("@Rule after");
+          }
+        };
+      }
+    };
+
+    @Test
+    public void test() {/* empty */}
+
+    @BeforeClass
+    public static void beforeClassCleanup() {
+      stack = new Stack<String>();
+    }
+
+    @AfterClass
+    public static void afterClassCheck() {
+      stack.push("@AfterClass");
+    }    
+  }
+
+  @Test
+  public void testRuleOrder() {
+    JUnitCore.runClasses(Nested.class);
+    Assert.assertEquals(
+        Arrays.toString(stack.toArray()), "[@Rule before, @Before, @After, @Rule after, @AfterClass]");
+  }
+}

Added: lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/util/junitcompat/TestSetupTeardownChaining.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/util/junitcompat/TestSetupTeardownChaining.java?rev=1243863&view=auto
==============================================================================
--- lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/util/junitcompat/TestSetupTeardownChaining.java (added)
+++ lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/util/junitcompat/TestSetupTeardownChaining.java Tue Feb 14 10:27:16 2012
@@ -0,0 +1,64 @@
+package org.apache.lucene.util.junitcompat;
+
+import org.apache.lucene.util.LuceneTestCase;
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.JUnitCore;
+import org.junit.runner.Result;
+import org.junit.runner.notification.Failure;
+
+/**
+ * Ensures proper functions of {@link LuceneTestCase#setUp()}
+ * and {@link LuceneTestCase#tearDown()}.
+ */
+public class TestSetupTeardownChaining extends WithNestedTests {
+  public static class NestedSetupChain extends AbstractNestedTest {
+    @Override
+    public void setUp() throws Exception {
+      // missing call.
+    }
+
+    @Test
+    public void testMe() {
+    }
+  }
+
+  public static class NestedTeardownChain extends AbstractNestedTest {
+    @Override
+    public void tearDown() throws Exception {
+      // missing call.
+    }
+
+    @Test
+    public void testMe() {
+    }
+  }
+
+  public TestSetupTeardownChaining() {
+    super(true);
+  }
+  
+  /**
+   * Verify super method calls on {@link LuceneTestCase#setUp()}.
+   */
+  @Test
+  public void testSetupChaining() {
+    Result result = JUnitCore.runClasses(NestedSetupChain.class);
+    Assert.assertEquals(1, result.getFailureCount());
+    Failure failure = result.getFailures().get(0);
+    Assert.assertTrue(failure.getMessage()
+        .contains("One of the overrides of setUp does not propagate the call."));
+  }
+  
+  /**
+   * Verify super method calls on {@link LuceneTestCase#tearDown()}.
+   */
+  @Test
+  public void testTeardownChaining() {
+    Result result = JUnitCore.runClasses(NestedTeardownChain.class);
+    Assert.assertEquals(1, result.getFailureCount());
+    Failure failure = result.getFailures().get(0);
+    Assert.assertTrue(failure.getMessage()
+        .contains("One of the overrides of tearDown does not propagate the call."));
+  }
+}

Added: lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/util/junitcompat/TestSorePointsReported.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/util/junitcompat/TestSorePointsReported.java?rev=1243863&view=auto
==============================================================================
--- lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/util/junitcompat/TestSorePointsReported.java (added)
+++ lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/util/junitcompat/TestSorePointsReported.java Tue Feb 14 10:27:16 2012
@@ -0,0 +1,266 @@
+package org.apache.lucene.util.junitcompat;
+
+import org.apache.lucene.util.LuceneTestCase;
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Ignore;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TestRule;
+import org.junit.runner.Description;
+import org.junit.runner.JUnitCore;
+import org.junit.runners.model.Statement;
+
+/**
+ * Ensures proper functions of {@link LuceneTestCase#setUp()}
+ * and {@link LuceneTestCase#tearDown()}.
+ */
+public class TestSorePointsReported extends WithNestedTests {
+  public static SorePoint where;
+  public static SoreType  type;
+  
+  public static class Nested extends AbstractNestedTest {
+    @BeforeClass
+    public static void beforeClass() {
+      if (isRunningNested()) {
+        triggerOn(SorePoint.BEFORE_CLASS);
+      }
+    }
+
+    @Rule
+    public TestRule rule = new TestRule() {
+      @Override
+      public Statement apply(final Statement base, Description description) {
+        return new Statement() {
+          public void evaluate() throws Throwable {
+            if (isRunningNested()) {
+              triggerOn(SorePoint.RULE);
+            }
+            base.evaluate();
+          }
+        };
+      }
+    };
+
+    /** Class initializer block/ default constructor. */
+    public Nested() {
+      triggerOn(SorePoint.INITIALIZER);
+    }
+
+    @Before
+    public void before() {
+      if (isRunningNested()) {
+        triggerOn(SorePoint.BEFORE);
+      }
+    }    
+
+    @Test
+    public void test() {
+      triggerOn(SorePoint.TEST);
+    }
+    
+    @After
+    public void after() {
+      if (isRunningNested()) {
+        triggerOn(SorePoint.AFTER);
+      }
+    }    
+
+    @AfterClass
+    public static void afterClass() {
+      if (isRunningNested()) {
+        triggerOn(SorePoint.AFTER_CLASS);
+      }
+    }    
+
+    /** */
+    private static void triggerOn(SorePoint pt) {
+      if (pt == where) {
+        switch (type) {
+          case ASSUMPTION:
+            LuceneTestCase.assumeTrue(pt.toString(), false);
+            throw new RuntimeException("unreachable");
+          case ERROR:
+            throw new RuntimeException(pt.toString());
+          case FAILURE:
+            Assert.assertTrue(pt.toString(), false);
+            throw new RuntimeException("unreachable");
+        }
+      }
+    }
+  }
+
+  /*
+   * ASSUMPTIONS.
+   */
+  
+  public TestSorePointsReported() {
+    super(true);
+  }
+
+  @Test @Ignore
+  public void testAssumeBeforeClass() throws Exception { 
+    type = SoreType.ASSUMPTION; 
+    where = SorePoint.BEFORE_CLASS;
+    Assert.assertTrue(runAndReturnSyserr().contains("NOTE: Assume failed in"));
+  }
+
+  @Test @Ignore
+  public void testAssumeInitializer() throws Exception { 
+    type = SoreType.ASSUMPTION; 
+    where = SorePoint.INITIALIZER;
+    Assert.assertTrue(runAndReturnSyserr().contains("NOTE: Assume failed in"));
+  }
+
+  @Test
+  public void testAssumeRule() throws Exception { 
+    type = SoreType.ASSUMPTION; 
+    where = SorePoint.RULE;
+    Assert.assertTrue(runAndReturnSyserr().contains("NOTE: Assume failed in"));
+  }
+
+  @Test
+  public void testAssumeBefore() throws Exception { 
+    type = SoreType.ASSUMPTION; 
+    where = SorePoint.BEFORE;
+    Assert.assertTrue(runAndReturnSyserr().contains("NOTE: Assume failed in"));
+  }
+
+  @Test
+  public void testAssumeTest() throws Exception { 
+    type = SoreType.ASSUMPTION; 
+    where = SorePoint.TEST;
+    Assert.assertTrue(runAndReturnSyserr().contains("NOTE: Assume failed in"));
+  }
+
+  @Test
+  public void testAssumeAfter() throws Exception { 
+    type = SoreType.ASSUMPTION; 
+    where = SorePoint.AFTER;
+    Assert.assertTrue(runAndReturnSyserr().contains("NOTE: Assume failed in"));
+  }
+
+  @Test @Ignore
+  public void testAssumeAfterClass() throws Exception { 
+    type = SoreType.ASSUMPTION; 
+    where = SorePoint.AFTER_CLASS;
+    Assert.assertTrue(runAndReturnSyserr().contains("NOTE: Assume failed in"));
+  }
+
+  /*
+   * FAILURES
+   */
+  
+  @Test @Ignore
+  public void testFailureBeforeClass() throws Exception { 
+    type = SoreType.FAILURE; 
+    where = SorePoint.BEFORE_CLASS;
+    Assert.assertTrue(runAndReturnSyserr().contains("NOTE: reproduce with:"));
+  }
+
+  @Test @Ignore
+  public void testFailureInitializer() throws Exception { 
+    type = SoreType.FAILURE; 
+    where = SorePoint.INITIALIZER;
+    Assert.assertTrue(runAndReturnSyserr().contains("NOTE: reproduce with:"));
+  }
+
+  @Test
+  public void testFailureRule() throws Exception { 
+    type = SoreType.FAILURE; 
+    where = SorePoint.RULE;
+    Assert.assertTrue(runAndReturnSyserr().contains("NOTE: reproduce with:"));
+  }
+
+  @Test
+  public void testFailureBefore() throws Exception { 
+    type = SoreType.FAILURE; 
+    where = SorePoint.BEFORE;
+    Assert.assertTrue(runAndReturnSyserr().contains("NOTE: reproduce with:"));
+  }
+
+  @Test
+  public void testFailureTest() throws Exception { 
+    type = SoreType.FAILURE; 
+    where = SorePoint.TEST;
+    Assert.assertTrue(runAndReturnSyserr().contains("NOTE: reproduce with:"));
+  }
+
+  @Test
+  public void testFailureAfter() throws Exception { 
+    type = SoreType.FAILURE; 
+    where = SorePoint.AFTER;
+    Assert.assertTrue(runAndReturnSyserr().contains("NOTE: reproduce with:"));
+  }
+
+  @Test @Ignore
+  public void testFailureAfterClass() throws Exception { 
+    type = SoreType.FAILURE; 
+    where = SorePoint.AFTER_CLASS;
+    Assert.assertTrue(runAndReturnSyserr().contains("NOTE: reproduce with:"));
+  }
+
+  /*
+   * ERRORS
+   */
+  
+  @Test @Ignore
+  public void testErrorBeforeClass() throws Exception { 
+    type = SoreType.ERROR; 
+    where = SorePoint.BEFORE_CLASS;
+    Assert.assertTrue(runAndReturnSyserr().contains("NOTE: reproduce with:"));
+  }
+
+  @Test @Ignore
+  public void testErrorInitializer() throws Exception { 
+    type = SoreType.ERROR; 
+    where = SorePoint.INITIALIZER;
+    Assert.assertTrue(runAndReturnSyserr().contains("NOTE: reproduce with:"));
+  }
+
+  @Test
+  public void testErrorRule() throws Exception { 
+    type = SoreType.ERROR; 
+    where = SorePoint.RULE;
+    Assert.assertTrue(runAndReturnSyserr().contains("NOTE: reproduce with:"));
+  }
+
+  @Test
+  public void testErrorBefore() throws Exception { 
+    type = SoreType.ERROR; 
+    where = SorePoint.BEFORE;
+    Assert.assertTrue(runAndReturnSyserr().contains("NOTE: reproduce with:"));
+  }
+
+  @Test
+  public void testErrorTest() throws Exception { 
+    type = SoreType.ERROR; 
+    where = SorePoint.TEST;
+    Assert.assertTrue(runAndReturnSyserr().contains("NOTE: reproduce with:"));
+  }
+
+  @Test
+  public void testErrorAfter() throws Exception { 
+    type = SoreType.ERROR; 
+    where = SorePoint.AFTER;
+    Assert.assertTrue(runAndReturnSyserr().contains("NOTE: reproduce with:"));
+  }
+
+  @Test @Ignore
+  public void testErrorAfterClass() throws Exception { 
+    type = SoreType.ERROR; 
+    where = SorePoint.AFTER_CLASS;
+    Assert.assertTrue(runAndReturnSyserr().contains("NOTE: reproduce with:"));
+  }
+
+  private String runAndReturnSyserr() throws Exception {
+    JUnitCore.runClasses(Nested.class);
+
+    String err = getSysErr();
+    // syserr.println("Type: " + type + ", point: " + where + " resulted in:\n" + err);
+    return err;
+  }
+}

Added: lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/util/junitcompat/WithNestedTests.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/util/junitcompat/WithNestedTests.java?rev=1243863&view=auto
==============================================================================
--- lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/util/junitcompat/WithNestedTests.java (added)
+++ lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/util/junitcompat/WithNestedTests.java Tue Feb 14 10:27:16 2012
@@ -0,0 +1,106 @@
+package org.apache.lucene.util.junitcompat;
+
+import java.io.ByteArrayOutputStream;
+import java.io.PrintStream;
+import java.io.UnsupportedEncodingException;
+
+import org.apache.lucene.util.LuceneTestCase;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Assume;
+import org.junit.Before;
+
+/**
+ * An abstract test class that prepares nested test classes to run.
+ * A nested test class will assume it's executed under control of this
+ * class and be ignored otherwise. 
+ * 
+ * <p>The purpose of this is so that nested test suites don't run from
+ * IDEs like Eclipse (where they are automatically detected).
+ * 
+ * <p>This class cannot extend {@link LuceneTestCase} because in case
+ * there's a nested {@link LuceneTestCase} afterclass hooks run twice and
+ * cause havoc (static fields).
+ */
+public abstract class WithNestedTests {
+  public static ThreadLocal<Boolean> runsAsNested = new ThreadLocal<Boolean>() {
+    @Override
+    protected Boolean initialValue() {
+      return false;
+    }
+  };
+
+  public static abstract class AbstractNestedTest extends LuceneTestCase {
+    @Before
+    public void before() {
+      Assume.assumeTrue(isRunningNested());
+    }
+
+    protected static boolean isRunningNested() {
+      return runsAsNested.get() != null && runsAsNested.get();
+    }
+  }
+
+  private boolean suppressOutputStreams;
+
+  protected WithNestedTests(boolean suppressOutputStreams) {
+    this.suppressOutputStreams = suppressOutputStreams;
+  }
+  
+  protected PrintStream prevSysErr;
+  protected PrintStream prevSysOut;
+  protected ByteArrayOutputStream sysout;
+  protected ByteArrayOutputStream syserr;
+
+  @Before
+  public final void before() {
+    if (suppressOutputStreams) {
+      prevSysOut = System.out;
+      prevSysErr = System.err;
+
+      try {
+        sysout = new ByteArrayOutputStream();
+        System.setOut(new PrintStream(sysout, true, "UTF-8"));
+        syserr = new ByteArrayOutputStream();
+        System.setErr(new PrintStream(syserr, true, "UTF-8"));
+      } catch (UnsupportedEncodingException e) {
+        throw new RuntimeException(e);
+      }
+    }
+
+    runsAsNested.set(true);
+  }
+
+  @After
+  public final void after() {
+    runsAsNested.set(false);
+    
+    if (suppressOutputStreams) {
+      System.out.flush();
+      System.err.flush();
+
+      System.setOut(prevSysOut);
+      System.setErr(prevSysErr);
+    }
+  }
+
+  protected String getSysOut() {
+    Assert.assertTrue(suppressOutputStreams);
+    System.out.flush();
+    try {
+      return new String(sysout.toByteArray(), "UTF-8");
+    } catch (UnsupportedEncodingException e) {
+      throw new RuntimeException(e);
+    }
+  }
+
+  protected String getSysErr() {
+    Assert.assertTrue(suppressOutputStreams);
+    System.err.flush();
+    try {
+      return new String(syserr.toByteArray(), "UTF-8");
+    } catch (UnsupportedEncodingException e) {
+      throw new RuntimeException(e);
+    }
+  }  
+}

Added: lucene/dev/trunk/lucene/lib/junit-4.10.jar
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/lib/junit-4.10.jar?rev=1243863&view=auto
==============================================================================
Files lucene/dev/trunk/lucene/lib/junit-4.10.jar (added) and lucene/dev/trunk/lucene/lib/junit-4.10.jar Tue Feb 14 10:27:16 2012 differ

Modified: lucene/dev/trunk/lucene/lib/junit-NOTICE.txt
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/lib/junit-NOTICE.txt?rev=1243863&r1=1243862&r2=1243863&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/lib/junit-NOTICE.txt (original)
+++ lucene/dev/trunk/lucene/lib/junit-NOTICE.txt Tue Feb 14 10:27:16 2012
@@ -1,2 +1,2 @@
-JUnit (under lib/junit-4.7.jar) is licensed under the Common Public License v. 1.0
+JUnit (under lib/junit-4.10.jar) is licensed under the Common Public License v. 1.0
 See http://junit.sourceforge.net/cpl-v10.html
\ No newline at end of file

Added: lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/util/InternalAssumptionViolatedException.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/util/InternalAssumptionViolatedException.java?rev=1243863&view=auto
==============================================================================
--- lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/util/InternalAssumptionViolatedException.java (added)
+++ lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/util/InternalAssumptionViolatedException.java Tue Feb 14 10:27:16 2012
@@ -0,0 +1,57 @@
+package org.apache.lucene.util;
+
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.hamcrest.Description;
+import org.junit.internal.AssumptionViolatedException;
+
+/**
+ * We have our own "custom" assumption class because JUnit's {@link AssumptionViolatedException}
+ * does not allow a cause exception to be set.
+ * 
+ * <p>We currently subclass and substitute JUnit's internal AVE.
+ */
+@SuppressWarnings("serial") 
+final class InternalAssumptionViolatedException extends AssumptionViolatedException {
+  private final String message;
+
+  public InternalAssumptionViolatedException(String message) {
+    this(message, null);
+  }
+
+  public InternalAssumptionViolatedException(String message, Throwable t) {
+    super(t, /* no matcher. */ null);
+    if (getCause() != t) {
+      throw new Error("AssumptionViolationException not setting up getCause() properly? Panic.");
+    }
+    this.message = message;
+  }
+
+  @Override
+  public String getMessage() {
+    return super.getMessage();
+  }
+
+  @Override
+  public void describeTo(Description description) {
+    description.appendText("failed assumption: " + message);
+    if (getCause() != null) {
+      description.appendText("(throwable: " + getCause().toString() + ")");
+    }
+  }
+}
\ No newline at end of file

Modified: lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/util/LuceneTestCase.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/util/LuceneTestCase.java?rev=1243863&r1=1243862&r2=1243863&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/util/LuceneTestCase.java (original)
+++ lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/util/LuceneTestCase.java Tue Feb 14 10:27:16 2012
@@ -26,8 +26,20 @@ import java.lang.annotation.Inherited;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.lang.annotation.Target;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.IdentityHashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
 import java.util.Map.Entry;
+import java.util.Random;
+import java.util.Set;
+import java.util.TimeZone;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 import java.util.concurrent.TimeUnit;
@@ -41,12 +53,25 @@ import org.apache.lucene.codecs.lucene40
 import org.apache.lucene.codecs.simpletext.SimpleTextCodec;
 import org.apache.lucene.document.Field;
 import org.apache.lucene.document.FieldType;
-import org.apache.lucene.index.*;
+import org.apache.lucene.index.DirectoryReader;
+import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.IndexReader.ReaderClosedListener;
+import org.apache.lucene.index.IndexWriterConfig;
+import org.apache.lucene.index.LogByteSizeMergePolicy;
+import org.apache.lucene.index.LogDocMergePolicy;
+import org.apache.lucene.index.LogMergePolicy;
+import org.apache.lucene.index.MockRandomMergePolicy;
+import org.apache.lucene.index.RandomCodec;
+import org.apache.lucene.index.RandomDocumentsWriterPerThreadPool;
+import org.apache.lucene.index.SegmentReader;
+import org.apache.lucene.index.SerialMergeScheduler;
+import org.apache.lucene.index.SlowCompositeReaderWrapper;
+import org.apache.lucene.index.ThreadAffinityDocumentsWriterThreadPool;
+import org.apache.lucene.index.TieredMergePolicy;
+import org.apache.lucene.search.AssertingIndexSearcher;
 import org.apache.lucene.search.BooleanQuery;
 import org.apache.lucene.search.FieldCache;
 import org.apache.lucene.search.FieldCache.CacheEntry;
-import org.apache.lucene.search.AssertingIndexSearcher;
 import org.apache.lucene.search.IndexSearcher;
 import org.apache.lucene.search.RandomSimilarityProvider;
 import org.apache.lucene.search.similarities.DefaultSimilarity;
@@ -61,11 +86,18 @@ import org.apache.lucene.store.MockDirec
 import org.apache.lucene.store.MockDirectoryWrapper.Throttling;
 import org.apache.lucene.store.NRTCachingDirectory;
 import org.apache.lucene.util.FieldCacheSanityChecker.Insanity;
-import org.junit.*;
-import org.junit.rules.MethodRule;
-import org.junit.rules.TestWatchman;
-import org.junit.runner.RunWith;
-import org.junit.runners.model.FrameworkMethod;
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.Assume;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Ignore;
+import org.junit.Rule;
+import org.junit.internal.AssumptionViolatedException;
+import org.junit.rules.*;
+import org.junit.runner.*;
+import org.junit.runner.notification.RunListener;
 import org.junit.runners.model.Statement;
 
 /**
@@ -97,7 +129,6 @@ import org.junit.runners.model.Statement
 
 @RunWith(LuceneTestCaseRunner.class)
 public abstract class LuceneTestCase extends Assert {
-
   /**
    * true iff tests are run in verbose mode. Note: if it is false, tests are not
    * expected to print any messages.
@@ -172,20 +203,20 @@ public abstract class LuceneTestCase ext
   /** @lucene.internal */
   public static boolean PREFLEX_IMPERSONATION_IS_ACTIVE;
 
+  /**
+   * @see SubclassSetupTeardownRule  
+   */
+  private boolean setupCalled;
+
+  /**
+   * @see SubclassSetupTeardownRule
+   */
+  private boolean teardownCalled;
+
   private int savedBoolMaxClauseCount = BooleanQuery.getMaxClauseCount();
 
   private volatile Thread.UncaughtExceptionHandler savedUncaughtExceptionHandler = null;
 
-  /** Used to track if setUp and tearDown are called correctly from subclasses */
-  private static State state = State.INITIAL;
-
-  private static enum State {
-    INITIAL, // no tests ran yet
-    SETUP,   // test has called setUp()
-    RANTEST, // test is running
-    TEARDOWN // test has called tearDown()
-  }
-  
   /**
    * Some tests expect the directory to contain a single segment, and want to do tests on that segment's reader.
    * This is an utility method to help them.
@@ -240,7 +271,6 @@ public abstract class LuceneTestCase ext
   @BeforeClass
   public static void beforeClassLuceneTestCaseJ4() {
     initRandom();
-    state = State.INITIAL;
     tempDirs.clear();
     stores = Collections.synchronizedMap(new IdentityHashMap<MockDirectoryWrapper,StackTraceElement[]>());
     
@@ -337,18 +367,7 @@ public abstract class LuceneTestCase ext
 
   @AfterClass
   public static void afterClassLuceneTestCaseJ4() {
-    State oldState = state; // capture test execution state
-    state = State.INITIAL; // set the state for subsequent tests
-    
     Throwable problem = null;
-    try {
-      if (!testsFailed) {
-        assertTrue("ensure your setUp() calls super.setUp() and your tearDown() calls super.tearDown()!!!", 
-          oldState == State.INITIAL || oldState == State.TEARDOWN);
-      }
-    } catch (Throwable t) {
-      if (problem == null) problem = t;
-    }
     
     if (! "false".equals(TEST_CLEAN_THREADS)) {
       int rogueThreads = threadCleanup("test class");
@@ -469,77 +488,128 @@ public abstract class LuceneTestCase ext
 
   protected static boolean testsFailed; /* true if any tests failed */
 
-  // This is how we get control when errors occur.
-  // Think of this as start/end/success/failed
-  // events.
-  @Rule
-  public final TestWatchman intercept = new TestWatchman() {
-
+  /**
+   * Control the outcome of each test's output status (failure, assumption-failure). This
+   * would ideally be handled by attaching a {@link RunListener} to a {@link Runner} (because
+   * then we would be notified about static block failures).
+   */
+  private class TestResultInterceptorRule implements TestRule {
     @Override
-    public void failed(Throwable e, FrameworkMethod method) {
-      // org.junit.internal.AssumptionViolatedException in older releases
-      // org.junit.Assume.AssumptionViolatedException in recent ones
-      if (e.getClass().getName().endsWith("AssumptionViolatedException")) {
-        if (e.getCause() instanceof _TestIgnoredException)
-          e = e.getCause();
-        System.err.print("NOTE: Assume failed in '" + method.getName() + "' (ignored):");
-        if (VERBOSE) {
-          System.err.println();
-          e.printStackTrace(System.err);
-        } else {
-          System.err.print(" ");
-          System.err.println(e.getMessage());
+    public Statement apply(final Statement base, final Description description) {
+      return new Statement() {
+        @Override
+        public void evaluate() throws Throwable {
+          starting(description);
+          try {
+            base.evaluate();
+          } catch (AssumptionViolatedException e) {
+            assumptionIgnored(e, description);
+            throw e;
+          } catch (Throwable t) {
+            failed(t, description);
+            throw t;
+          } finally {
+            ending(description);
+          }
         }
+      };
+    }
+
+    private void assumptionIgnored(AssumptionViolatedException e, Description description) {
+      System.err.print("NOTE: Assume failed in '" + description.getDisplayName() + "' (ignored):");
+      if (VERBOSE) {
+        System.err.println();
+        e.printStackTrace(System.err);
       } else {
-        testsFailed = true;
-        reportAdditionalFailureInfo();
+        System.err.print(" ");
+        System.err.println(e.getMessage());
       }
-      super.failed(e, method);
     }
 
-    @Override
-    public void starting(FrameworkMethod method) {
+    private void failed(Throwable e, Description description) {
+      testsFailed = true;
+      reportAdditionalFailureInfo();
+      assert !(e instanceof AssumptionViolatedException);
+    }
+
+    private void starting(Description description) {
       // set current method name for logging
-      LuceneTestCase.this.name = method.getName();
-      State s = state; // capture test execution state
-      state = State.RANTEST; // set the state for subsequent tests
-      if (!testsFailed) {
-        assertTrue("ensure your setUp() calls super.setUp()!!!", s == State.SETUP);
-      }
-      super.starting(method);
+      LuceneTestCase.this.name = description.getDisplayName();
+    }
+
+    private void ending(Description description) {
+      // clear the current method name.
+      LuceneTestCase.this.name = null;
     }
   };
-  
+
   /** 
    * The thread executing the current test case.
    * @see #isTestThread()
    */
   volatile Thread testCaseThread;
 
-  /** @see #testCaseThread */
-  @Rule
-  public final MethodRule setTestThread = new MethodRule() {
-    public Statement apply(final Statement s, FrameworkMethod fm, Object target) {
+  /** 
+   * @see LuceneTestCase#testCaseThread 
+   */
+  private class RememberThreadRule implements TestRule {
+    @Override
+    public Statement apply(final Statement base, Description description) {
       return new Statement() {
         public void evaluate() throws Throwable {
           try {
             LuceneTestCase.this.testCaseThread = Thread.currentThread();
-            s.evaluate();
+            base.evaluate();
           } finally {
             LuceneTestCase.this.testCaseThread = null;
           }
         }
       };
     }
-  };
+  }
 
-  @Before
-  public void setUp() throws Exception {
+  /**
+   * This controls how rules are nested. It is important that _all_ rules declared
+   * in {@link LuceneTestCase} are executed in proper order if they depend on each 
+   * other.
+   */
+  @Rule
+  public final TestRule ruleChain = RuleChain
+    .outerRule(new RememberThreadRule())
+    .around(new TestResultInterceptorRule())
+    .around(new InternalSetupTeardownRule())
+    .around(new SubclassSetupTeardownRule());
+
+  /**
+   * Internal {@link LuceneTestCase} setup before/after each test.
+   */
+  private class InternalSetupTeardownRule implements TestRule {
+    @Override
+    public Statement apply(final Statement base, Description description) {
+      return new Statement() {
+        @Override
+        public void evaluate() throws Throwable {
+          setUpInternal();
+          // We simulate the previous behavior of @Before in that
+          // if any statement below us fails, we just propagate the original
+          // exception and do not call tearDownInternal.
+
+          // TODO: [DW] should this really be this way? We could use
+          // JUnit's MultipleFailureException and propagate both?
+          base.evaluate();
+          tearDownInternal();
+        }
+      };
+    }
+  }
+  
+  /**
+   * Setup before the tests.
+   */
+  private final void setUpInternal() throws Exception {
     seed = "random".equals(TEST_SEED) ? seedRand.nextLong() : ThreeLongs.fromString(TEST_SEED).l2;
     random.setSeed(seed);
-    State s = state; // capture test execution state
-    state = State.SETUP; // set the state for subsequent tests
-   
+    
     savedUncaughtExceptionHandler = Thread.getDefaultUncaughtExceptionHandler();
     Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
       public void uncaughtException(Thread t, Throwable e) {
@@ -553,8 +623,6 @@ public abstract class LuceneTestCase ext
               break;
             }
           }
-          if (e.getCause() instanceof _TestIgnoredException)
-            e = e.getCause();
           System.err.print("NOTE: Assume failed at " + where + " (ignored):");
           if (VERBOSE) {
             System.err.println();
@@ -574,10 +642,6 @@ public abstract class LuceneTestCase ext
 
     savedBoolMaxClauseCount = BooleanQuery.getMaxClauseCount();
 
-    if (!testsFailed) {
-      assertTrue("ensure your tearDown() calls super.tearDown()!!!", (s == State.INITIAL || s == State.TEARDOWN));
-    }
-    
     if (useNoMemoryExpensiveCodec) {
       String defFormat = _TestUtil.getPostingsFormat("thisCodeMakesAbsolutelyNoSenseCanWeDeleteIt");
       // Stupid: assumeFalse in setUp() does not print any information, because
@@ -618,26 +682,57 @@ public abstract class LuceneTestCase ext
     return Thread.currentThread() == testCaseThread;
   }
 
+  /**
+   * Make sure {@link #setUp()} and {@link #tearDown()} were invoked even if they
+   * have been overriden. We assume nobody will call these out of non-overriden
+   * methods (they have to be public by contract, unfortunately). The top-level
+   * methods just set a flag that is checked upon successful execution of each test
+   * case.
+   */
+  private class SubclassSetupTeardownRule implements TestRule {
+    @Override
+    public Statement apply(final Statement base, Description description) {
+      return new Statement() {
+        @Override
+        public void evaluate() throws Throwable {
+          setupCalled = false;
+          teardownCalled = false;
+          base.evaluate();
+
+          // I assume we don't want to check teardown chaining if something happens in the
+          // test because this would obscure the original exception?
+          if (!setupCalled) { 
+            Assert.fail("One of the overrides of setUp does not propagate the call.");
+          }
+          if (!teardownCalled) { 
+            Assert.fail("One of the overrides of tearDown does not propagate the call.");
+          }
+        }
+      };
+    }
+  }
+
+  /**
+   * For subclassing only. Overrides must call {@code super.setUp()}.
+   */
+  @Before
+  public void setUp() throws Exception {
+    setupCalled = true;
+  }
+
+  /**
+   * For subclassing only. Overrides must call {@code super.tearDown()}.
+   */
   @After
   public void tearDown() throws Exception {
-    State oldState = state; // capture test execution state
-    state = State.TEARDOWN; // set the state for subsequent tests
-    
-    // NOTE: with junit 4.7, we don't get a reproduceWith because our Watchman
-    // does not know if something fails in tearDown. so we ensure this happens ourselves for now.
-    // we can remove this if we upgrade to 4.8
-    Throwable problem = null;
-    
-    try {
-      if (!testsFailed) {
-        // Note: we allow a test to go straight from SETUP -> TEARDOWN (without ever entering the RANTEST state)
-        // because if you assume() inside setUp(), it skips the test and the TestWatchman has no way to know...
-        assertTrue("ensure your setUp() calls super.setUp()!!!", oldState == State.RANTEST || oldState == State.SETUP);
-      }
-    } catch (Throwable t) {
-      if (problem == null) problem = t;
-    }
+    teardownCalled = true;
+  }
 
+  /**
+   * Clean up after tests.
+   */
+  private final void tearDownInternal() throws Exception {
+    Throwable problem = null;
     BooleanQuery.setMaxClauseCount(savedBoolMaxClauseCount);
 
     // this won't throw any exceptions or fail the test
@@ -673,8 +768,8 @@ public abstract class LuceneTestCase ext
     purgeFieldCache(FieldCache.DEFAULT);
     
     if (problem != null) {
-      testsFailed = true;
       reportAdditionalFailureInfo();
+      // TODO: simply rethrow problem, without wrapping?
       throw new RuntimeException(problem);
     }
   }
@@ -858,7 +953,7 @@ public abstract class LuceneTestCase ext
   }
 
   public static void assumeTrue(String msg, boolean b) {
-    Assume.assumeNoException(b ? null : new _TestIgnoredException(msg));
+    Assume.assumeNoException(b ? null : new InternalAssumptionViolatedException(msg));
   }
 
   public static void assumeFalse(String msg, boolean b) {
@@ -866,7 +961,7 @@ public abstract class LuceneTestCase ext
   }
 
   public static void assumeNoException(String msg, Exception e) {
-    Assume.assumeNoException(e == null ? null : new _TestIgnoredException(msg, e));
+    Assume.assumeNoException(e == null ? null : new InternalAssumptionViolatedException(msg, e));
   }
 
   public static <T> Set<T> asSet(T... args) {

Modified: lucene/dev/trunk/solr/NOTICE.txt
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/NOTICE.txt?rev=1243863&r1=1243862&r2=1243863&view=diff
==============================================================================
--- lucene/dev/trunk/solr/NOTICE.txt (original)
+++ lucene/dev/trunk/solr/NOTICE.txt Tue Feb 14 10:27:16 2012
@@ -75,7 +75,7 @@ the Apache CXF project and is Apache Lic
 The Google Code Prettify is Apache License 2.0.
 See http://code.google.com/p/google-code-prettify/
 
-JUnit (under lib/junit-4.7.jar) is licensed under the Common Public License v. 1.0
+JUnit (under lib/junit-4.10.jar) is licensed under the Common Public License v. 1.0
 See http://junit.sourceforge.net/cpl-v10.html
 
 JLine (under contrib/lucli/lib/jline.jar) is licensed under the BSD License.

Added: lucene/dev/trunk/solr/lib/junit-4.10.jar
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/lib/junit-4.10.jar?rev=1243863&view=auto
==============================================================================
Files lucene/dev/trunk/solr/lib/junit-4.10.jar (added) and lucene/dev/trunk/solr/lib/junit-4.10.jar Tue Feb 14 10:27:16 2012 differ