Snap for 7266504 from ccf3392c728ec1231b91d1b6ef3f8fe47d471944 to mainline-networkstack-release

Change-Id: I81517db68a649ec94f385421b965ef8e38c9c567
diff --git a/README.version b/README.version
index fd9d421..430e5e8 100644
--- a/README.version
+++ b/README.version
@@ -1,8 +1,9 @@
-URL: https://github.com/junit-team/junit/archive/r4.12.tar.gz
-Version: 4.12
+URL: https://github.com/junit-team/junit/archive/r4.13.2.tar.gz
+Version: 4.13.2
 BugComponent: 40416
 
 Local Changes:
+    Extra generic type information to aid certain javacs.
     Remove DisableOnDebug (new in 4.12) as it is not supported on Android
     Remove support for stuck threads
-    Extra generic type information to aid certain javacs.
+    Don't convert assumption failures into errors in rules/ErrorCollector
diff --git a/src/main/java/junit/extensions/ActiveTestSuite.java b/src/main/java/junit/extensions/ActiveTestSuite.java
index 95c5e2e..6f0f99d 100644
--- a/src/main/java/junit/extensions/ActiveTestSuite.java
+++ b/src/main/java/junit/extensions/ActiveTestSuite.java
@@ -63,7 +63,7 @@
         }
     }
 
-    synchronized public void runFinished() {
+    public synchronized void runFinished() {
         fActiveTestDeathCount++;
         notifyAll();
     }
diff --git a/src/main/java/junit/extensions/TestDecorator.java b/src/main/java/junit/extensions/TestDecorator.java
index 2b74f30..a3c5e08 100644
--- a/src/main/java/junit/extensions/TestDecorator.java
+++ b/src/main/java/junit/extensions/TestDecorator.java
@@ -9,6 +9,7 @@
  * test decorators. Test decorator subclasses can be introduced to add behaviour
  * before or after a test is run.
  */
+@SuppressWarnings("deprecation")
 public class TestDecorator extends Assert implements Test {
     protected Test fTest;
 
diff --git a/src/main/java/junit/framework/Assert.java b/src/main/java/junit/framework/Assert.java
index 663461c..43482a1 100644
--- a/src/main/java/junit/framework/Assert.java
+++ b/src/main/java/junit/framework/Assert.java
@@ -17,7 +17,7 @@
      * Asserts that a condition is true. If it isn't it throws
      * an AssertionFailedError with the given message.
      */
-    static public void assertTrue(String message, boolean condition) {
+    public static void assertTrue(String message, boolean condition) {
         if (!condition) {
             fail(message);
         }
@@ -27,7 +27,7 @@
      * Asserts that a condition is true. If it isn't it throws
      * an AssertionFailedError.
      */
-    static public void assertTrue(boolean condition) {
+    public static void assertTrue(boolean condition) {
         assertTrue(null, condition);
     }
 
@@ -35,7 +35,7 @@
      * Asserts that a condition is false. If it isn't it throws
      * an AssertionFailedError with the given message.
      */
-    static public void assertFalse(String message, boolean condition) {
+    public static void assertFalse(String message, boolean condition) {
         assertTrue(message, !condition);
     }
 
@@ -43,14 +43,14 @@
      * Asserts that a condition is false. If it isn't it throws
      * an AssertionFailedError.
      */
-    static public void assertFalse(boolean condition) {
+    public static void assertFalse(boolean condition) {
         assertFalse(null, condition);
     }
 
     /**
      * Fails a test with the given message.
      */
-    static public void fail(String message) {
+    public static void fail(String message) {
         if (message == null) {
             throw new AssertionFailedError();
         }
@@ -60,7 +60,7 @@
     /**
      * Fails a test with no message.
      */
-    static public void fail() {
+    public static void fail() {
         fail(null);
     }
 
@@ -68,7 +68,7 @@
      * Asserts that two objects are equal. If they are not
      * an AssertionFailedError is thrown with the given message.
      */
-    static public void assertEquals(String message, Object expected, Object actual) {
+    public static void assertEquals(String message, Object expected, Object actual) {
         if (expected == null && actual == null) {
             return;
         }
@@ -82,14 +82,14 @@
      * Asserts that two objects are equal. If they are not
      * an AssertionFailedError is thrown.
      */
-    static public void assertEquals(Object expected, Object actual) {
+    public static void assertEquals(Object expected, Object actual) {
         assertEquals(null, expected, actual);
     }
 
     /**
      * Asserts that two Strings are equal.
      */
-    static public void assertEquals(String message, String expected, String actual) {
+    public static void assertEquals(String message, String expected, String actual) {
         if (expected == null && actual == null) {
             return;
         }
@@ -103,7 +103,7 @@
     /**
      * Asserts that two Strings are equal.
      */
-    static public void assertEquals(String expected, String actual) {
+    public static void assertEquals(String expected, String actual) {
         assertEquals(null, expected, actual);
     }
 
@@ -112,12 +112,12 @@
      * an AssertionFailedError is thrown with the given message.  If the expected
      * value is infinity then the delta value is ignored.
      */
-    static public void assertEquals(String message, double expected, double actual, double delta) {
+    public static void assertEquals(String message, double expected, double actual, double delta) {
         if (Double.compare(expected, actual) == 0) {
             return;
         }
         if (!(Math.abs(expected - actual) <= delta)) {
-            failNotEquals(message, new Double(expected), new Double(actual));
+            failNotEquals(message, Double.valueOf(expected), Double.valueOf(actual));
         }
     }
 
@@ -125,7 +125,7 @@
      * Asserts that two doubles are equal concerning a delta. If the expected
      * value is infinity then the delta value is ignored.
      */
-    static public void assertEquals(double expected, double actual, double delta) {
+    public static void assertEquals(double expected, double actual, double delta) {
         assertEquals(null, expected, actual, delta);
     }
 
@@ -134,12 +134,12 @@
      * are not an AssertionFailedError is thrown with the given message. If the
      * expected value is infinity then the delta value is ignored.
      */
-    static public void assertEquals(String message, float expected, float actual, float delta) {
+    public static void assertEquals(String message, float expected, float actual, float delta) {
         if (Float.compare(expected, actual) == 0) {
             return;
         }
         if (!(Math.abs(expected - actual) <= delta)) {
-            failNotEquals(message, new Float(expected), new Float(actual));
+            failNotEquals(message, Float.valueOf(expected), Float.valueOf(actual));
         }
     }
 
@@ -147,7 +147,7 @@
      * Asserts that two floats are equal concerning a delta. If the expected
      * value is infinity then the delta value is ignored.
      */
-    static public void assertEquals(float expected, float actual, float delta) {
+    public static void assertEquals(float expected, float actual, float delta) {
         assertEquals(null, expected, actual, delta);
     }
 
@@ -155,14 +155,14 @@
      * Asserts that two longs are equal. If they are not
      * an AssertionFailedError is thrown with the given message.
      */
-    static public void assertEquals(String message, long expected, long actual) {
+    public static void assertEquals(String message, long expected, long actual) {
         assertEquals(message, Long.valueOf(expected), Long.valueOf(actual));
     }
 
     /**
      * Asserts that two longs are equal.
      */
-    static public void assertEquals(long expected, long actual) {
+    public static void assertEquals(long expected, long actual) {
         assertEquals(null, expected, actual);
     }
 
@@ -170,14 +170,14 @@
      * Asserts that two booleans are equal. If they are not
      * an AssertionFailedError is thrown with the given message.
      */
-    static public void assertEquals(String message, boolean expected, boolean actual) {
+    public static void assertEquals(String message, boolean expected, boolean actual) {
         assertEquals(message, Boolean.valueOf(expected), Boolean.valueOf(actual));
     }
 
     /**
      * Asserts that two booleans are equal.
      */
-    static public void assertEquals(boolean expected, boolean actual) {
+    public static void assertEquals(boolean expected, boolean actual) {
         assertEquals(null, expected, actual);
     }
 
@@ -185,14 +185,14 @@
      * Asserts that two bytes are equal. If they are not
      * an AssertionFailedError is thrown with the given message.
      */
-    static public void assertEquals(String message, byte expected, byte actual) {
+    public static void assertEquals(String message, byte expected, byte actual) {
         assertEquals(message, Byte.valueOf(expected), Byte.valueOf(actual));
     }
 
     /**
      * Asserts that two bytes are equal.
      */
-    static public void assertEquals(byte expected, byte actual) {
+    public static void assertEquals(byte expected, byte actual) {
         assertEquals(null, expected, actual);
     }
 
@@ -200,14 +200,14 @@
      * Asserts that two chars are equal. If they are not
      * an AssertionFailedError is thrown with the given message.
      */
-    static public void assertEquals(String message, char expected, char actual) {
+    public static void assertEquals(String message, char expected, char actual) {
         assertEquals(message, Character.valueOf(expected), Character.valueOf(actual));
     }
 
     /**
      * Asserts that two chars are equal.
      */
-    static public void assertEquals(char expected, char actual) {
+    public static void assertEquals(char expected, char actual) {
         assertEquals(null, expected, actual);
     }
 
@@ -215,14 +215,14 @@
      * Asserts that two shorts are equal. If they are not
      * an AssertionFailedError is thrown with the given message.
      */
-    static public void assertEquals(String message, short expected, short actual) {
+    public static void assertEquals(String message, short expected, short actual) {
         assertEquals(message, Short.valueOf(expected), Short.valueOf(actual));
     }
 
     /**
      * Asserts that two shorts are equal.
      */
-    static public void assertEquals(short expected, short actual) {
+    public static void assertEquals(short expected, short actual) {
         assertEquals(null, expected, actual);
     }
 
@@ -230,21 +230,21 @@
      * Asserts that two ints are equal. If they are not
      * an AssertionFailedError is thrown with the given message.
      */
-    static public void assertEquals(String message, int expected, int actual) {
+    public static void assertEquals(String message, int expected, int actual) {
         assertEquals(message, Integer.valueOf(expected), Integer.valueOf(actual));
     }
 
     /**
      * Asserts that two ints are equal.
      */
-    static public void assertEquals(int expected, int actual) {
+    public static void assertEquals(int expected, int actual) {
         assertEquals(null, expected, actual);
     }
 
     /**
      * Asserts that an object isn't null.
      */
-    static public void assertNotNull(Object object) {
+    public static void assertNotNull(Object object) {
         assertNotNull(null, object);
     }
 
@@ -252,7 +252,7 @@
      * Asserts that an object isn't null. If it is
      * an AssertionFailedError is thrown with the given message.
      */
-    static public void assertNotNull(String message, Object object) {
+    public static void assertNotNull(String message, Object object) {
         assertTrue(message, object != null);
     }
 
@@ -263,7 +263,7 @@
      *
      * @param object Object to check or <code>null</code>
      */
-    static public void assertNull(Object object) {
+    public static void assertNull(Object object) {
         if (object != null) {
             assertNull("Expected: <null> but was: " + object.toString(), object);
         }
@@ -273,7 +273,7 @@
      * Asserts that an object is null.  If it is not
      * an AssertionFailedError is thrown with the given message.
      */
-    static public void assertNull(String message, Object object) {
+    public static void assertNull(String message, Object object) {
         assertTrue(message, object == null);
     }
 
@@ -281,7 +281,7 @@
      * Asserts that two objects refer to the same object. If they are not
      * an AssertionFailedError is thrown with the given message.
      */
-    static public void assertSame(String message, Object expected, Object actual) {
+    public static void assertSame(String message, Object expected, Object actual) {
         if (expected == actual) {
             return;
         }
@@ -292,7 +292,7 @@
      * Asserts that two objects refer to the same object. If they are not
      * the same an AssertionFailedError is thrown.
      */
-    static public void assertSame(Object expected, Object actual) {
+    public static void assertSame(Object expected, Object actual) {
         assertSame(null, expected, actual);
     }
 
@@ -301,7 +301,7 @@
      * refer to the same object an AssertionFailedError is thrown with the
      * given message.
      */
-    static public void assertNotSame(String message, Object expected, Object actual) {
+    public static void assertNotSame(String message, Object expected, Object actual) {
         if (expected == actual) {
             failSame(message);
         }
@@ -311,21 +311,21 @@
      * Asserts that two objects do not refer to the same object. If they do
      * refer to the same object an AssertionFailedError is thrown.
      */
-    static public void assertNotSame(Object expected, Object actual) {
+    public static void assertNotSame(Object expected, Object actual) {
         assertNotSame(null, expected, actual);
     }
 
-    static public void failSame(String message) {
+    public static void failSame(String message) {
         String formatted = (message != null) ? message + " " : "";
         fail(formatted + "expected not same");
     }
 
-    static public void failNotSame(String message, Object expected, Object actual) {
+    public static void failNotSame(String message, Object expected, Object actual) {
         String formatted = (message != null) ? message + " " : "";
         fail(formatted + "expected same:<" + expected + "> was not:<" + actual + ">");
     }
 
-    static public void failNotEquals(String message, Object expected, Object actual) {
+    public static void failNotEquals(String message, Object expected, Object actual) {
         fail(format(message, expected, actual));
     }
 
diff --git a/src/main/java/junit/framework/ComparisonCompactor.java b/src/main/java/junit/framework/ComparisonCompactor.java
index fa20a8e..81ddd5b 100644
--- a/src/main/java/junit/framework/ComparisonCompactor.java
+++ b/src/main/java/junit/framework/ComparisonCompactor.java
@@ -18,6 +18,7 @@
         fActual = actual;
     }
 
+    @SuppressWarnings("deprecation")
     public String compact(String message) {
         if (fExpected == null || fActual == null || areStringsEqual()) {
             return Assert.format(message, fExpected, fActual);
diff --git a/src/main/java/junit/framework/JUnit4TestAdapter.java b/src/main/java/junit/framework/JUnit4TestAdapter.java
index cbb66db..9d32031 100644
--- a/src/main/java/junit/framework/JUnit4TestAdapter.java
+++ b/src/main/java/junit/framework/JUnit4TestAdapter.java
@@ -9,11 +9,23 @@
 import org.junit.runner.Runner;
 import org.junit.runner.manipulation.Filter;
 import org.junit.runner.manipulation.Filterable;
+import org.junit.runner.manipulation.Orderer;
+import org.junit.runner.manipulation.InvalidOrderingException;
 import org.junit.runner.manipulation.NoTestsRemainException;
-import org.junit.runner.manipulation.Sortable;
+import org.junit.runner.manipulation.Orderable;
 import org.junit.runner.manipulation.Sorter;
 
-public class JUnit4TestAdapter implements Test, Filterable, Sortable, Describable {
+/**
+ * The JUnit4TestAdapter enables running JUnit-4-style tests using a JUnit-3-style test runner.
+ *
+ * <p> To use it, add the following to a test class:
+ * <pre>
+      public static Test suite() {
+        return new JUnit4TestAdapter(<em>YourJUnit4TestClass</em>.class);
+      }
+</pre>
+ */
+public class JUnit4TestAdapter implements Test, Filterable, Orderable, Describable {
     private final Class<?> fNewTestClass;
 
     private final Runner fRunner;
@@ -83,4 +95,13 @@
     public void sort(Sorter sorter) {
         sorter.apply(fRunner);
     }
+
+    /**
+     * {@inheritDoc}
+     *
+     * @since 4.13
+     */
+    public void order(Orderer orderer) throws InvalidOrderingException {
+        orderer.apply(fRunner);
+    }
 }
\ No newline at end of file
diff --git a/src/main/java/junit/framework/Protectable.java b/src/main/java/junit/framework/Protectable.java
index 9f30b10..c5ceb16 100644
--- a/src/main/java/junit/framework/Protectable.java
+++ b/src/main/java/junit/framework/Protectable.java
@@ -8,7 +8,7 @@
 public interface Protectable {
 
     /**
-     * Run the the following method protected.
+     * Run the following method protected.
      */
     public abstract void protect() throws Throwable;
-}
\ No newline at end of file
+}
diff --git a/src/main/java/junit/framework/TestCase.java b/src/main/java/junit/framework/TestCase.java
index b89ce71..e474a64 100644
--- a/src/main/java/junit/framework/TestCase.java
+++ b/src/main/java/junit/framework/TestCase.java
@@ -73,6 +73,7 @@
  * @see TestResult
  * @see TestSuite
  */
+@SuppressWarnings("deprecation")
 public abstract class TestCase extends Assert implements Test {
     /**
      * the name of the test case
@@ -102,7 +103,7 @@
     }
 
     /**
-     * Creates a default TestResult object
+     * Creates a default TestResult object.
      *
      * @see TestResult
      */
@@ -187,7 +188,6 @@
      * Asserts that a condition is true. If it isn't it throws
      * an AssertionFailedError with the given message.
      */
-    @SuppressWarnings("deprecation")
     public static void assertTrue(String message, boolean condition) {
         Assert.assertTrue(message, condition);
     }
@@ -196,7 +196,6 @@
      * Asserts that a condition is true. If it isn't it throws
      * an AssertionFailedError.
      */
-    @SuppressWarnings("deprecation")
     public static void assertTrue(boolean condition) {
         Assert.assertTrue(condition);
     }
@@ -205,7 +204,6 @@
      * Asserts that a condition is false. If it isn't it throws
      * an AssertionFailedError with the given message.
      */
-    @SuppressWarnings("deprecation")
     public static void assertFalse(String message, boolean condition) {
         Assert.assertFalse(message, condition);
     }
@@ -214,7 +212,6 @@
      * Asserts that a condition is false. If it isn't it throws
      * an AssertionFailedError.
      */
-    @SuppressWarnings("deprecation")
     public static void assertFalse(boolean condition) {
         Assert.assertFalse(condition);
     }
@@ -222,7 +219,6 @@
     /**
      * Fails a test with the given message.
      */
-    @SuppressWarnings("deprecation")
     public static void fail(String message) {
         Assert.fail(message);
     }
@@ -230,7 +226,6 @@
     /**
      * Fails a test with no message.
      */
-    @SuppressWarnings("deprecation")
     public static void fail() {
         Assert.fail();
     }
@@ -239,7 +234,6 @@
      * Asserts that two objects are equal. If they are not
      * an AssertionFailedError is thrown with the given message.
      */
-    @SuppressWarnings("deprecation")
     public static void assertEquals(String message, Object expected, Object actual) {
         Assert.assertEquals(message, expected, actual);
     }
@@ -248,7 +242,6 @@
      * Asserts that two objects are equal. If they are not
      * an AssertionFailedError is thrown.
      */
-    @SuppressWarnings("deprecation")
     public static void assertEquals(Object expected, Object actual) {
         Assert.assertEquals(expected, actual);
     }
@@ -256,7 +249,6 @@
     /**
      * Asserts that two Strings are equal.
      */
-    @SuppressWarnings("deprecation")
     public static void assertEquals(String message, String expected, String actual) {
         Assert.assertEquals(message, expected, actual);
     }
@@ -264,7 +256,6 @@
     /**
      * Asserts that two Strings are equal.
      */
-    @SuppressWarnings("deprecation")
     public static void assertEquals(String expected, String actual) {
         Assert.assertEquals(expected, actual);
     }
@@ -274,7 +265,6 @@
      * an AssertionFailedError is thrown with the given message.  If the expected
      * value is infinity then the delta value is ignored.
      */
-    @SuppressWarnings("deprecation")
     public static void assertEquals(String message, double expected, double actual, double delta) {
         Assert.assertEquals(message, expected, actual, delta);
     }
@@ -283,7 +273,6 @@
      * Asserts that two doubles are equal concerning a delta. If the expected
      * value is infinity then the delta value is ignored.
      */
-    @SuppressWarnings("deprecation")
     public static void assertEquals(double expected, double actual, double delta) {
         Assert.assertEquals(expected, actual, delta);
     }
@@ -293,7 +282,6 @@
      * are not an AssertionFailedError is thrown with the given message. If the
      * expected value is infinity then the delta value is ignored.
      */
-    @SuppressWarnings("deprecation")
     public static void assertEquals(String message, float expected, float actual, float delta) {
         Assert.assertEquals(message, expected, actual, delta);
     }
@@ -302,7 +290,6 @@
      * Asserts that two floats are equal concerning a delta. If the expected
      * value is infinity then the delta value is ignored.
      */
-    @SuppressWarnings("deprecation")
     public static void assertEquals(float expected, float actual, float delta) {
         Assert.assertEquals(expected, actual, delta);
     }
@@ -311,7 +298,6 @@
      * Asserts that two longs are equal. If they are not
      * an AssertionFailedError is thrown with the given message.
      */
-    @SuppressWarnings("deprecation")
     public static void assertEquals(String message, long expected, long actual) {
         Assert.assertEquals(message, expected, actual);
     }
@@ -319,7 +305,6 @@
     /**
      * Asserts that two longs are equal.
      */
-    @SuppressWarnings("deprecation")
     public static void assertEquals(long expected, long actual) {
         Assert.assertEquals(expected, actual);
     }
@@ -328,7 +313,6 @@
      * Asserts that two booleans are equal. If they are not
      * an AssertionFailedError is thrown with the given message.
      */
-    @SuppressWarnings("deprecation")
     public static void assertEquals(String message, boolean expected, boolean actual) {
         Assert.assertEquals(message, expected, actual);
     }
@@ -336,7 +320,6 @@
     /**
      * Asserts that two booleans are equal.
      */
-    @SuppressWarnings("deprecation")
     public static void assertEquals(boolean expected, boolean actual) {
         Assert.assertEquals(expected, actual);
     }
@@ -345,7 +328,6 @@
      * Asserts that two bytes are equal. If they are not
      * an AssertionFailedError is thrown with the given message.
      */
-    @SuppressWarnings("deprecation")
     public static void assertEquals(String message, byte expected, byte actual) {
         Assert.assertEquals(message, expected, actual);
     }
@@ -353,7 +335,6 @@
     /**
      * Asserts that two bytes are equal.
      */
-    @SuppressWarnings("deprecation")
     public static void assertEquals(byte expected, byte actual) {
         Assert.assertEquals(expected, actual);
     }
@@ -362,7 +343,6 @@
      * Asserts that two chars are equal. If they are not
      * an AssertionFailedError is thrown with the given message.
      */
-    @SuppressWarnings("deprecation")
     public static void assertEquals(String message, char expected, char actual) {
         Assert.assertEquals(message, expected, actual);
     }
@@ -370,7 +350,6 @@
     /**
      * Asserts that two chars are equal.
      */
-    @SuppressWarnings("deprecation")
     public static void assertEquals(char expected, char actual) {
         Assert.assertEquals(expected, actual);
     }
@@ -379,7 +358,6 @@
      * Asserts that two shorts are equal. If they are not
      * an AssertionFailedError is thrown with the given message.
      */
-    @SuppressWarnings("deprecation")
     public static void assertEquals(String message, short expected, short actual) {
         Assert.assertEquals(message, expected, actual);
     }
@@ -387,7 +365,6 @@
     /**
      * Asserts that two shorts are equal.
      */
-    @SuppressWarnings("deprecation")
     public static void assertEquals(short expected, short actual) {
         Assert.assertEquals(expected, actual);
     }
@@ -396,7 +373,6 @@
      * Asserts that two ints are equal. If they are not
      * an AssertionFailedError is thrown with the given message.
      */
-    @SuppressWarnings("deprecation")
     public static void assertEquals(String message, int expected, int actual) {
         Assert.assertEquals(message, expected, actual);
     }
@@ -404,7 +380,6 @@
     /**
      * Asserts that two ints are equal.
      */
-    @SuppressWarnings("deprecation")
     public static void assertEquals(int expected, int actual) {
         Assert.assertEquals(expected, actual);
     }
@@ -412,7 +387,6 @@
     /**
      * Asserts that an object isn't null.
      */
-    @SuppressWarnings("deprecation")
     public static void assertNotNull(Object object) {
         Assert.assertNotNull(object);
     }
@@ -421,7 +395,6 @@
      * Asserts that an object isn't null. If it is
      * an AssertionFailedError is thrown with the given message.
      */
-    @SuppressWarnings("deprecation")
     public static void assertNotNull(String message, Object object) {
         Assert.assertNotNull(message, object);
     }
@@ -433,7 +406,6 @@
      *
      * @param object Object to check or <code>null</code>
      */
-    @SuppressWarnings("deprecation")
     public static void assertNull(Object object) {
         Assert.assertNull(object);
     }
@@ -442,7 +414,6 @@
      * Asserts that an object is null.  If it is not
      * an AssertionFailedError is thrown with the given message.
      */
-    @SuppressWarnings("deprecation")
     public static void assertNull(String message, Object object) {
         Assert.assertNull(message, object);
     }
@@ -451,7 +422,6 @@
      * Asserts that two objects refer to the same object. If they are not
      * an AssertionFailedError is thrown with the given message.
      */
-    @SuppressWarnings("deprecation")
     public static void assertSame(String message, Object expected, Object actual) {
         Assert.assertSame(message, expected, actual);
     }
@@ -460,7 +430,6 @@
      * Asserts that two objects refer to the same object. If they are not
      * the same an AssertionFailedError is thrown.
      */
-    @SuppressWarnings("deprecation")
     public static void assertSame(Object expected, Object actual) {
         Assert.assertSame(expected, actual);
     }
@@ -470,7 +439,6 @@
      * refer to the same object an AssertionFailedError is thrown with the
      * given message.
      */
-    @SuppressWarnings("deprecation")
     public static void assertNotSame(String message, Object expected, Object actual) {
         Assert.assertNotSame(message, expected, actual);
     }
@@ -479,27 +447,22 @@
      * Asserts that two objects do not refer to the same object. If they do
      * refer to the same object an AssertionFailedError is thrown.
      */
-    @SuppressWarnings("deprecation")
     public static void assertNotSame(Object expected, Object actual) {
         Assert.assertNotSame(expected, actual);
     }
 
-    @SuppressWarnings("deprecation")
     public static void failSame(String message) {
         Assert.failSame(message);
     }
 
-    @SuppressWarnings("deprecation")
     public static void failNotSame(String message, Object expected, Object actual) {
         Assert.failNotSame(message, expected, actual);
     }
 
-    @SuppressWarnings("deprecation")
     public static void failNotEquals(String message, Object expected, Object actual) {
         Assert.failNotEquals(message, expected, actual);
     }
 
-    @SuppressWarnings("deprecation")
     public static String format(String message, Object expected, Object actual) {
         return Assert.format(message, expected, actual);
     }
@@ -519,7 +482,7 @@
     }
 
     /**
-     * Returns a string representation of the test case
+     * Returns a string representation of the test case.
      */
     @Override
     public String toString() {
@@ -527,7 +490,7 @@
     }
 
     /**
-     * Gets the name of a TestCase
+     * Gets the name of a TestCase.
      *
      * @return the name of the TestCase
      */
@@ -536,7 +499,7 @@
     }
 
     /**
-     * Sets the name of a TestCase
+     * Sets the name of a TestCase.
      *
      * @param name the name to set
      */
diff --git a/src/main/java/junit/framework/TestFailure.java b/src/main/java/junit/framework/TestFailure.java
index 6168b58..d1ddfbc 100644
--- a/src/main/java/junit/framework/TestFailure.java
+++ b/src/main/java/junit/framework/TestFailure.java
@@ -1,7 +1,6 @@
 package junit.framework;
 
-import java.io.PrintWriter;
-import java.io.StringWriter;
+import org.junit.internal.Throwables;
 
 
 /**
@@ -49,10 +48,7 @@
      * thrown by TestFailure.
      */
     public String trace() {
-        StringWriter stringWriter = new StringWriter();
-        PrintWriter writer = new PrintWriter(stringWriter);
-        thrownException().printStackTrace(writer);
-        return stringWriter.toString();
+        return Throwables.getStacktrace(thrownException());
     }
 
     /**
diff --git a/src/main/java/junit/framework/TestResult.java b/src/main/java/junit/framework/TestResult.java
index 8332542..e01a2b0 100644
--- a/src/main/java/junit/framework/TestResult.java
+++ b/src/main/java/junit/framework/TestResult.java
@@ -52,14 +52,14 @@
     }
 
     /**
-     * Registers a TestListener
+     * Registers a TestListener.
      */
     public synchronized void addListener(TestListener listener) {
         fListeners.add(listener);
     }
 
     /**
-     * Unregisters a TestListener
+     * Unregisters a TestListener.
      */
     public synchronized void removeListener(TestListener listener) {
         fListeners.remove(listener);
@@ -91,7 +91,7 @@
     }
 
     /**
-     * Returns an Enumeration for the errors
+     * Returns an Enumeration for the errors.
      */
     public synchronized Enumeration<TestFailure> errors() {
         return Collections.enumeration(fErrors);
@@ -106,7 +106,7 @@
     }
 
     /**
-     * Returns an Enumeration for the failures
+     * Returns an Enumeration for the failures.
      */
     public synchronized Enumeration<TestFailure> failures() {
         return Collections.enumeration(fFailures);
@@ -150,7 +150,7 @@
     }
 
     /**
-     * Checks whether the test run should stop
+     * Checks whether the test run should stop.
      */
     public synchronized boolean shouldStop() {
         return fStop;
diff --git a/src/main/java/junit/framework/TestSuite.java b/src/main/java/junit/framework/TestSuite.java
index 366f1cf..50cd5f8 100644
--- a/src/main/java/junit/framework/TestSuite.java
+++ b/src/main/java/junit/framework/TestSuite.java
@@ -1,7 +1,5 @@
 package junit.framework;
 
-import java.io.PrintWriter;
-import java.io.StringWriter;
 import java.lang.reflect.Constructor;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
@@ -12,6 +10,7 @@
 import java.util.Vector;
 
 import org.junit.internal.MethodSorter;
+import org.junit.internal.Throwables;
 
 /**
  * A <code>TestSuite</code> is a <code>Composite</code> of Tests.
@@ -35,7 +34,7 @@
  * <p>
  * A final option is to do the same for a large array of test classes.
  * <pre>
- * Class[] testClasses = { MathTest.class, AnotherTest.class }
+ * Class[] testClasses = { MathTest.class, AnotherTest.class };
  * TestSuite suite= new TestSuite(testClasses);
  * </pre>
  *
@@ -65,11 +64,11 @@
                 test = constructor.newInstance(new Object[]{name});
             }
         } catch (InstantiationException e) {
-            return (warning("Cannot instantiate test case: " + name + " (" + exceptionToString(e) + ")"));
+            return (warning("Cannot instantiate test case: " + name + " (" + Throwables.getStacktrace(e) + ")"));
         } catch (InvocationTargetException e) {
-            return (warning("Exception in constructor: " + name + " (" + exceptionToString(e.getTargetException()) + ")"));
+            return (warning("Exception in constructor: " + name + " (" + Throwables.getStacktrace(e.getTargetException()) + ")"));
         } catch (IllegalAccessException e) {
-            return (warning("Cannot access test case: " + name + " (" + exceptionToString(e) + ")"));
+            return (warning("Cannot access test case: " + name + " (" + Throwables.getStacktrace(e) + ")"));
         }
         return (Test) test;
     }
@@ -99,16 +98,6 @@
         };
     }
 
-    /**
-     * Converts the stack trace into a string
-     */
-    private static String exceptionToString(Throwable e) {
-        StringWriter stringWriter = new StringWriter();
-        PrintWriter writer = new PrintWriter(stringWriter);
-        e.printStackTrace(writer);
-        return stringWriter.toString();
-    }
-
     private String fName;
 
     private Vector<Test> fTests = new Vector<Test>(10); // Cannot convert this to List because it is used directly by some test runners
@@ -210,7 +199,7 @@
     }
 
     /**
-     * Adds the tests from the given class to the suite
+     * Adds the tests from the given class to the suite.
      */
     public void addTestSuite(Class<? extends TestCase> testClass) {
         addTest(new TestSuite(testClass));
@@ -262,21 +251,21 @@
     }
 
     /**
-     * Returns the test at the given index
+     * Returns the test at the given index.
      */
     public Test testAt(int index) {
         return fTests.get(index);
     }
 
     /**
-     * Returns the number of tests in this suite
+     * Returns the number of tests in this suite.
      */
     public int testCount() {
         return fTests.size();
     }
 
     /**
-     * Returns the tests as an enumeration
+     * Returns the tests as an enumeration.
      */
     public Enumeration<Test> tests() {
         return fTests.elements();
diff --git a/src/main/java/junit/runner/BaseTestRunner.java b/src/main/java/junit/runner/BaseTestRunner.java
index 8268323..d63fae7 100644
--- a/src/main/java/junit/runner/BaseTestRunner.java
+++ b/src/main/java/junit/runner/BaseTestRunner.java
@@ -20,6 +20,8 @@
 import junit.framework.TestListener;
 import junit.framework.TestSuite;
 
+import org.junit.internal.Throwables;
+
 /**
  * Base class for all test runners.
  * This class was born live on stage in Sardinia during XP2000.
@@ -233,6 +235,7 @@
             setPreferences(new Properties(getPreferences()));
             getPreferences().load(is);
         } catch (IOException ignored) {
+        } catch (SecurityException ignored) {
         } finally {
             try {
                 if (is != null) {
@@ -264,11 +267,7 @@
      * Returns a filtered stack trace
      */
     public static String getFilteredTrace(Throwable e) {
-        StringWriter stringWriter = new StringWriter();
-        PrintWriter writer = new PrintWriter(stringWriter);
-        e.printStackTrace(writer);
-        String trace = stringWriter.toString();
-        return BaseTestRunner.getFilteredTrace(trace);
+        return BaseTestRunner.getFilteredTrace(Throwables.getStacktrace(e));
     }
 
     /**
diff --git a/src/main/java/junit/runner/TestRunListener.java b/src/main/java/junit/runner/TestRunListener.java
index b5e22f5..ce5b3d5 100644
--- a/src/main/java/junit/runner/TestRunListener.java
+++ b/src/main/java/junit/runner/TestRunListener.java
@@ -8,18 +8,18 @@
  */
 public interface TestRunListener {
     /* test status constants*/
-    public static final int STATUS_ERROR = 1;
-    public static final int STATUS_FAILURE = 2;
+    int STATUS_ERROR = 1;
+    int STATUS_FAILURE = 2;
 
-    public void testRunStarted(String testSuiteName, int testCount);
+    void testRunStarted(String testSuiteName, int testCount);
 
-    public void testRunEnded(long elapsedTime);
+    void testRunEnded(long elapsedTime);
 
-    public void testRunStopped(long elapsedTime);
+    void testRunStopped(long elapsedTime);
 
-    public void testStarted(String testName);
+    void testStarted(String testName);
 
-    public void testEnded(String testName);
+    void testEnded(String testName);
 
-    public void testFailed(int status, String testName, String trace);
+    void testFailed(int status, String testName, String trace);
 }
diff --git a/src/main/java/junit/runner/Version.java b/src/main/java/junit/runner/Version.java
index eaf3db7..6c7862e 100644
--- a/src/main/java/junit/runner/Version.java
+++ b/src/main/java/junit/runner/Version.java
@@ -9,7 +9,7 @@
 	}
 
 	public static String id() {
-		return "4.12-SNAPSHOT";
+		return "4.13.3-SNAPSHOT";
 	}
 	
 	public static void main(String[] args) {
diff --git a/src/main/java/junit/textui/TestRunner.java b/src/main/java/junit/textui/TestRunner.java
index 4d78f77..913020a 100644
--- a/src/main/java/junit/textui/TestRunner.java
+++ b/src/main/java/junit/textui/TestRunner.java
@@ -131,7 +131,7 @@
         }
     }
 
-    public static void main(String args[]) {
+    public static void main(String[] args) {
         TestRunner aTestRunner = new TestRunner();
         try {
             TestResult r = aTestRunner.start(args);
@@ -149,7 +149,7 @@
      * Starts a test run. Analyzes the command line arguments and runs the given
      * test suite.
      */
-    public TestResult start(String args[]) throws Exception {
+    public TestResult start(String[] args) throws Exception {
         String testCase = "";
         String method = "";
         boolean wait = false;
diff --git a/src/main/java/org/junit/Assert.java b/src/main/java/org/junit/Assert.java
old mode 100755
new mode 100644
index d7deb06..65bbc9d
--- a/src/main/java/org/junit/Assert.java
+++ b/src/main/java/org/junit/Assert.java
@@ -2,6 +2,7 @@
 
 import org.hamcrest.Matcher;
 import org.hamcrest.MatcherAssert;
+import org.junit.function.ThrowingRunnable;
 import org.junit.internal.ArrayComparisonFailure;
 import org.junit.internal.ExactComparisonCriteria;
 import org.junit.internal.InexactComparisonCriteria;
@@ -36,7 +37,7 @@
      * okay)
      * @param condition condition to be checked
      */
-    static public void assertTrue(String message, boolean condition) {
+    public static void assertTrue(String message, boolean condition) {
         if (!condition) {
             fail(message);
         }
@@ -48,7 +49,7 @@
      *
      * @param condition condition to be checked
      */
-    static public void assertTrue(boolean condition) {
+    public static void assertTrue(boolean condition) {
         assertTrue(null, condition);
     }
 
@@ -60,7 +61,7 @@
      * okay)
      * @param condition condition to be checked
      */
-    static public void assertFalse(String message, boolean condition) {
+    public static void assertFalse(String message, boolean condition) {
         assertTrue(message, !condition);
     }
 
@@ -70,7 +71,7 @@
      *
      * @param condition condition to be checked
      */
-    static public void assertFalse(boolean condition) {
+    public static void assertFalse(boolean condition) {
         assertFalse(null, condition);
     }
 
@@ -81,7 +82,7 @@
      * okay)
      * @see AssertionError
      */
-    static public void fail(String message) {
+    public static void fail(String message) {
         if (message == null) {
             throw new AssertionError();
         }
@@ -91,7 +92,7 @@
     /**
      * Fails a test with no message.
      */
-    static public void fail() {
+    public static void fail() {
         fail(null);
     }
 
@@ -106,11 +107,12 @@
      * @param expected expected value
      * @param actual actual value
      */
-    static public void assertEquals(String message, Object expected,
+    public static void assertEquals(String message, Object expected,
             Object actual) {
         if (equalsRegardingNull(expected, actual)) {
             return;
-        } else if (expected instanceof String && actual instanceof String) {
+        }
+        if (expected instanceof String && actual instanceof String) {
             String cleanMessage = message == null ? "" : message;
             throw new ComparisonFailure(cleanMessage, (String) expected,
                     (String) actual);
@@ -140,7 +142,7 @@
      * @param expected expected value
      * @param actual the value to check against <code>expected</code>
      */
-    static public void assertEquals(Object expected, Object actual) {
+    public static void assertEquals(Object expected, Object actual) {
         assertEquals(null, expected, actual);
     }
 
@@ -155,7 +157,7 @@
      * @param unexpected unexpected value to check
      * @param actual the value to check against <code>unexpected</code>
      */
-    static public void assertNotEquals(String message, Object unexpected,
+    public static void assertNotEquals(String message, Object unexpected,
             Object actual) {
         if (equalsRegardingNull(unexpected, actual)) {
             failEquals(message, actual);
@@ -171,7 +173,7 @@
      * @param unexpected unexpected value to check
      * @param actual the value to check against <code>unexpected</code>
      */
-    static public void assertNotEquals(Object unexpected, Object actual) {
+    public static void assertNotEquals(Object unexpected, Object actual) {
         assertNotEquals(null, unexpected, actual);
     }
 
@@ -194,7 +196,7 @@
      * @param unexpected unexpected value to check
      * @param actual the value to check against <code>unexpected</code>
      */
-    static public void assertNotEquals(String message, long unexpected, long actual) {
+    public static void assertNotEquals(String message, long unexpected, long actual) {
         if (unexpected == actual) {
             failEquals(message, Long.valueOf(actual));
         }
@@ -207,7 +209,7 @@
      * @param unexpected unexpected value to check
      * @param actual the value to check against <code>unexpected</code>
      */
-    static public void assertNotEquals(long unexpected, long actual) {
+    public static void assertNotEquals(long unexpected, long actual) {
         assertNotEquals(null, unexpected, actual);
     }
 
@@ -226,7 +228,7 @@
      * <code>actual</code> for which both numbers are still
      * considered equal.
      */
-    static public void assertNotEquals(String message, double unexpected,
+    public static void assertNotEquals(String message, double unexpected,
             double actual, double delta) {
         if (!doubleIsDifferent(unexpected, actual, delta)) {
             failEquals(message, Double.valueOf(actual));
@@ -245,7 +247,7 @@
      * <code>actual</code> for which both numbers are still
      * considered equal.
      */
-    static public void assertNotEquals(double unexpected, double actual, double delta) {
+    public static void assertNotEquals(double unexpected, double actual, double delta) {
         assertNotEquals(null, unexpected, actual, delta);
     }
 
@@ -261,7 +263,7 @@
      * <code>actual</code> for which both numbers are still
      * considered equal.
      */
-    static public void assertNotEquals(float unexpected, float actual, float delta) {
+    public static void assertNotEquals(float unexpected, float actual, float delta) {
         assertNotEquals(null, unexpected, actual, delta);
     }
 
@@ -297,7 +299,7 @@
     public static void assertArrayEquals(Object[] expecteds, Object[] actuals) {
         assertArrayEquals(null, expecteds, actuals);
     }
-    
+
     /**
      * Asserts that two boolean arrays are equal. If they are not, an
      * {@link AssertionError} is thrown with the given message. If
@@ -312,8 +314,8 @@
     public static void assertArrayEquals(String message, boolean[] expecteds,
             boolean[] actuals) throws ArrayComparisonFailure {
         internalArrayEquals(message, expecteds, actuals);
-    }    
-    
+    }
+
     /**
      * Asserts that two boolean arrays are equal. If they are not, an
      * {@link AssertionError} is thrown. If <code>expected</code> and
@@ -547,7 +549,7 @@
      * <code>actual</code> for which both numbers are still
      * considered equal.
      */
-    static public void assertEquals(String message, double expected,
+    public static void assertEquals(String message, double expected,
             double actual, double delta) {
         if (doubleIsDifferent(expected, actual, delta)) {
             failNotEquals(message, Double.valueOf(expected), Double.valueOf(actual));
@@ -569,7 +571,7 @@
      * <code>actual</code> for which both numbers are still
      * considered equal.
      */
-    static public void assertEquals(String message, float expected,
+    public static void assertEquals(String message, float expected,
             float actual, float delta) {
         if (floatIsDifferent(expected, actual, delta)) {
             failNotEquals(message, Float.valueOf(expected), Float.valueOf(actual));
@@ -591,14 +593,14 @@
      * <code>actual</code> for which both numbers are still
      * considered equal.
      */
-    static public void assertNotEquals(String message, float unexpected,
+    public static void assertNotEquals(String message, float unexpected,
             float actual, float delta) {
         if (!floatIsDifferent(unexpected, actual, delta)) {
             failEquals(message, Float.valueOf(actual));
         }
     }
 
-    static private boolean doubleIsDifferent(double d1, double d2, double delta) {
+    private static boolean doubleIsDifferent(double d1, double d2, double delta) {
         if (Double.compare(d1, d2) == 0) {
             return false;
         }
@@ -609,7 +611,7 @@
         return true;
     }
 
-    static private boolean floatIsDifferent(float f1, float f2, float delta) {
+    private static boolean floatIsDifferent(float f1, float f2, float delta) {
         if (Float.compare(f1, f2) == 0) {
             return false;
         }
@@ -627,7 +629,7 @@
      * @param expected expected long value.
      * @param actual actual long value
      */
-    static public void assertEquals(long expected, long actual) {
+    public static void assertEquals(long expected, long actual) {
         assertEquals(null, expected, actual);
     }
 
@@ -640,7 +642,7 @@
      * @param expected long expected value.
      * @param actual long actual value
      */
-    static public void assertEquals(String message, long expected, long actual) {
+    public static void assertEquals(String message, long expected, long actual) {
         if (expected != actual) {
             failNotEquals(message, Long.valueOf(expected), Long.valueOf(actual));
         }
@@ -652,7 +654,7 @@
      *             instead
      */
     @Deprecated
-    static public void assertEquals(double expected, double actual) {
+    public static void assertEquals(double expected, double actual) {
         assertEquals(null, expected, actual);
     }
 
@@ -662,7 +664,7 @@
      *             instead
      */
     @Deprecated
-    static public void assertEquals(String message, double expected,
+    public static void assertEquals(String message, double expected,
             double actual) {
         fail("Use assertEquals(expected, actual, delta) to compare floating-point numbers");
     }
@@ -679,7 +681,7 @@
      * <code>actual</code> for which both numbers are still
      * considered equal.
      */
-    static public void assertEquals(double expected, double actual, double delta) {
+    public static void assertEquals(double expected, double actual, double delta) {
         assertEquals(null, expected, actual, delta);
     }
 
@@ -695,8 +697,7 @@
      * <code>actual</code> for which both numbers are still
      * considered equal.
      */
-
-    static public void assertEquals(float expected, float actual, float delta) {
+    public static void assertEquals(float expected, float actual, float delta) {
         assertEquals(null, expected, actual, delta);
     }
 
@@ -708,7 +709,7 @@
      * okay)
      * @param object Object to check or <code>null</code>
      */
-    static public void assertNotNull(String message, Object object) {
+    public static void assertNotNull(String message, Object object) {
         assertTrue(message, object != null);
     }
 
@@ -718,7 +719,7 @@
      *
      * @param object Object to check or <code>null</code>
      */
-    static public void assertNotNull(Object object) {
+    public static void assertNotNull(Object object) {
         assertNotNull(null, object);
     }
 
@@ -730,7 +731,7 @@
      * okay)
      * @param object Object to check or <code>null</code>
      */
-    static public void assertNull(String message, Object object) {
+    public static void assertNull(String message, Object object) {
         if (object == null) {
             return;
         }
@@ -743,11 +744,11 @@
      *
      * @param object Object to check or <code>null</code>
      */
-    static public void assertNull(Object object) {
+    public static void assertNull(Object object) {
         assertNull(null, object);
     }
 
-    static private void failNotNull(String message, Object actual) {
+    private static void failNotNull(String message, Object actual) {
         String formatted = "";
         if (message != null) {
             formatted = message + " ";
@@ -764,7 +765,7 @@
      * @param expected the expected object
      * @param actual the object to compare to <code>expected</code>
      */
-    static public void assertSame(String message, Object expected, Object actual) {
+    public static void assertSame(String message, Object expected, Object actual) {
         if (expected == actual) {
             return;
         }
@@ -778,7 +779,7 @@
      * @param expected the expected object
      * @param actual the object to compare to <code>expected</code>
      */
-    static public void assertSame(Object expected, Object actual) {
+    public static void assertSame(Object expected, Object actual) {
         assertSame(null, expected, actual);
     }
 
@@ -792,7 +793,7 @@
      * @param unexpected the object you don't expect
      * @param actual the object to compare to <code>unexpected</code>
      */
-    static public void assertNotSame(String message, Object unexpected,
+    public static void assertNotSame(String message, Object unexpected,
             Object actual) {
         if (unexpected == actual) {
             failSame(message);
@@ -807,11 +808,11 @@
      * @param unexpected the object you don't expect
      * @param actual the object to compare to <code>unexpected</code>
      */
-    static public void assertNotSame(Object unexpected, Object actual) {
+    public static void assertNotSame(Object unexpected, Object actual) {
         assertNotSame(null, unexpected, actual);
     }
 
-    static private void failSame(String message) {
+    private static void failSame(String message) {
         String formatted = "";
         if (message != null) {
             formatted = message + " ";
@@ -819,7 +820,7 @@
         fail(formatted + "expected not same");
     }
 
-    static private void failNotSame(String message, Object expected,
+    private static void failNotSame(String message, Object expected,
             Object actual) {
         String formatted = "";
         if (message != null) {
@@ -829,19 +830,19 @@
                 + ">");
     }
 
-    static private void failNotEquals(String message, Object expected,
+    private static void failNotEquals(String message, Object expected,
             Object actual) {
         fail(format(message, expected, actual));
     }
 
     static String format(String message, Object expected, Object actual) {
         String formatted = "";
-        if (message != null && !message.equals("")) {
+        if (message != null && !"".equals(message)) {
             formatted = message + " ";
         }
         String expectedString = String.valueOf(expected);
         String actualString = String.valueOf(actual);
-        if (expectedString.equals(actualString)) {
+        if (equalsRegardingNull(expectedString, actualString)) {
             return formatted + "expected: "
                     + formatClassAndValue(expected, expectedString)
                     + " but was: " + formatClassAndValue(actual, actualString);
@@ -851,6 +852,11 @@
         }
     }
 
+    private static String formatClass(Class<?> value) {
+        String className = value.getCanonicalName();
+        return className == null ? value.getName() : className;
+    }
+
     private static String formatClassAndValue(Object value, String valueString) {
         String className = value == null ? "null" : value.getClass().getName();
         return className + "<" + valueString + ">";
@@ -917,8 +923,9 @@
      * @param matcher an expression, built of {@link Matcher}s, specifying allowed
      * values
      * @see org.hamcrest.CoreMatchers
-     * @see org.hamcrest.MatcherAssert
+     * @deprecated use {@code org.hamcrest.MatcherAssert.assertThat()}
      */
+    @Deprecated
     public static <T> void assertThat(T actual, Matcher<? super T> matcher) {
         assertThat("", actual, matcher);
     }
@@ -949,10 +956,79 @@
      * @param matcher an expression, built of {@link Matcher}s, specifying allowed
      * values
      * @see org.hamcrest.CoreMatchers
-     * @see org.hamcrest.MatcherAssert
+     * @deprecated use {@code org.hamcrest.MatcherAssert.assertThat()}
      */
+    @Deprecated
     public static <T> void assertThat(String reason, T actual,
             Matcher<? super T> matcher) {
         MatcherAssert.assertThat(reason, actual, matcher);
     }
+
+    /**
+     * Asserts that {@code runnable} throws an exception of type {@code expectedThrowable} when
+     * executed. If it does, the exception object is returned. If it does not throw an exception, an
+     * {@link AssertionError} is thrown. If it throws the wrong type of exception, an {@code
+     * AssertionError} is thrown describing the mismatch; the exception that was actually thrown can
+     * be obtained by calling {@link AssertionError#getCause}.
+     *
+     * @param expectedThrowable the expected type of the exception
+     * @param runnable       a function that is expected to throw an exception when executed
+     * @return the exception thrown by {@code runnable}
+     * @since 4.13
+     */
+    public static <T extends Throwable> T assertThrows(Class<T> expectedThrowable,
+            ThrowingRunnable runnable) {
+        return assertThrows(null, expectedThrowable, runnable);
+    }
+
+    /**
+     * Asserts that {@code runnable} throws an exception of type {@code expectedThrowable} when
+     * executed. If it does, the exception object is returned. If it does not throw an exception, an
+     * {@link AssertionError} is thrown. If it throws the wrong type of exception, an {@code
+     * AssertionError} is thrown describing the mismatch; the exception that was actually thrown can
+     * be obtained by calling {@link AssertionError#getCause}.
+     *
+     * @param message the identifying message for the {@link AssertionError} (<code>null</code>
+     * okay)
+     * @param expectedThrowable the expected type of the exception
+     * @param runnable a function that is expected to throw an exception when executed
+     * @return the exception thrown by {@code runnable}
+     * @since 4.13
+     */
+    public static <T extends Throwable> T assertThrows(String message, Class<T> expectedThrowable,
+            ThrowingRunnable runnable) {
+        try {
+            runnable.run();
+        } catch (Throwable actualThrown) {
+            if (expectedThrowable.isInstance(actualThrown)) {
+                @SuppressWarnings("unchecked") T retVal = (T) actualThrown;
+                return retVal;
+            } else {
+                String expected = formatClass(expectedThrowable);
+                Class<? extends Throwable> actualThrowable = actualThrown.getClass();
+                String actual = formatClass(actualThrowable);
+                if (expected.equals(actual)) {
+                    // There must be multiple class loaders. Add the identity hash code so the message
+                    // doesn't say "expected: java.lang.String<my.package.MyException> ..."
+                    expected += "@" + Integer.toHexString(System.identityHashCode(expectedThrowable));
+                    actual += "@" + Integer.toHexString(System.identityHashCode(actualThrowable));
+                }
+                String mismatchMessage = buildPrefix(message)
+                        + format("unexpected exception type thrown;", expected, actual);
+
+                // The AssertionError(String, Throwable) ctor is only available on JDK7.
+                AssertionError assertionError = new AssertionError(mismatchMessage);
+                assertionError.initCause(actualThrown);
+                throw assertionError;
+            }
+        }
+        String notThrownMessage = buildPrefix(message) + String
+                .format("expected %s to be thrown, but nothing was thrown",
+                        formatClass(expectedThrowable));
+        throw new AssertionError(notThrownMessage);
+    }
+
+    private static String buildPrefix(String message) {
+        return message != null && message.length() != 0 ? message + ": " : "";
+    }
 }
diff --git a/src/main/java/org/junit/Assume.java b/src/main/java/org/junit/Assume.java
index b7687f7..29b705b 100644
--- a/src/main/java/org/junit/Assume.java
+++ b/src/main/java/org/junit/Assume.java
@@ -14,7 +14,7 @@
  * basically means "don't run this test if these conditions don't apply". The default JUnit runner skips tests with
  * failing assumptions. Custom runners may behave differently.
  * <p>
- *     A good example of using assumptions is in <a href="https://github.com/junit-team/junit/wiki/Theories">Theories</a> where they are needed to exclude certain datapoints that aren't suitable or allowed for a certain test case.
+ *     A good example of using assumptions is in <a href="https://github.com/junit-team/junit4/wiki/Theories">Theories</a> where they are needed to exclude certain datapoints that aren't suitable or allowed for a certain test case.
  * </p>
  * Failed assumptions are usually not logged, because there may be many tests that don't apply to certain
  * configurations.
@@ -29,11 +29,20 @@
  * </pre>
  * </p>
  *
- * @see <a href="https://github.com/junit-team/junit/wiki/Theories">Theories</a>
+ * @see <a href="https://github.com/junit-team/junit4/wiki/Theories">Theories</a>
  *
  * @since 4.4
  */
 public class Assume {
+
+    /**
+     * Do not instantiate.
+     * @deprecated since 4.13.
+     */
+    @Deprecated
+    public Assume() {
+    }
+
     /**
      * If called with an expression evaluating to {@code false}, the test will halt and be ignored.
      */
@@ -45,7 +54,7 @@
      * The inverse of {@link #assumeTrue(boolean)}.
      */
     public static void assumeFalse(boolean b) {
-        assumeTrue(!b);
+        assumeThat(b, is(false));
     }
 
     /**
@@ -67,9 +76,11 @@
     }
 
     /**
-     * If called with one or more null elements in <code>objects</code>, the test will halt and be ignored.
+     * If called with a {@code null} array or one or more {@code null} elements in {@code objects},
+     * the test will halt and be ignored.
      */
     public static void assumeNotNull(Object... objects) {
+        assumeThat(objects, notNullValue());
         assumeThat(asList(objects), everyItem(notNullValue()));
     }
 
diff --git a/src/main/java/org/junit/AssumptionViolatedException.java b/src/main/java/org/junit/AssumptionViolatedException.java
index e48ddf0..1d62190 100644
--- a/src/main/java/org/junit/AssumptionViolatedException.java
+++ b/src/main/java/org/junit/AssumptionViolatedException.java
@@ -40,7 +40,7 @@
     /**
      * An assumption exception with the given message and a cause.
      */
-    public AssumptionViolatedException(String assumption, Throwable t) {
-        super(assumption, t);
+    public AssumptionViolatedException(String message, Throwable t) {
+        super(message, t);
     }
 }
diff --git a/src/main/java/org/junit/ClassRule.java b/src/main/java/org/junit/ClassRule.java
index 02c40a7..94ee29f 100644
--- a/src/main/java/org/junit/ClassRule.java
+++ b/src/main/java/org/junit/ClassRule.java
@@ -28,7 +28,10 @@
  * annotated {@link ClassRule}s on a class, they will be applied in an order
  * that depends on your JVM's implementation of the reflection API, which is
  * undefined, in general. However, Rules defined by fields will always be applied
- * before Rules defined by methods.
+ * after Rules defined by methods, i.e. the Statements returned by the former will
+ * be executed around those returned by the latter.
+ *
+ * <h3>Usage</h3>
  * <p>
  * For example, here is a test suite that connects to a server once before
  * all the test classes run, and disconnects after they are finished:
@@ -79,9 +82,37 @@
  * <p>
  * For more information and more examples, see {@link org.junit.rules.TestRule}.
  *
+ * <h3>Ordering</h3>
+ * <p>
+ * You can use {@link #order()} if you want to have control over the order in
+ * which the Rules are applied.
+ *
+ * <pre>
+ * public class ThreeClassRules {
+ *     &#064;ClassRule(order = 0)
+ *     public static LoggingRule outer = new LoggingRule("outer rule");
+ *
+ *     &#064;ClassRule(order = 1)
+ *     public static LoggingRule middle = new LoggingRule("middle rule");
+ *
+ *     &#064;ClassRule(order = 2)
+ *     public static LoggingRule inner = new LoggingRule("inner rule");
+ *
+ *     // ...
+ * }
+ * </pre>
+ *
  * @since 4.9
  */
 @Retention(RetentionPolicy.RUNTIME)
 @Target({ElementType.FIELD, ElementType.METHOD})
 public @interface ClassRule {
+
+    /**
+     * Specifies the order in which rules are applied. The rules with a higher value are inner.
+     *
+     * @since 4.13
+     */
+    int order() default Rule.DEFAULT_ORDER;
+
 }
diff --git a/src/main/java/org/junit/ComparisonFailure.java b/src/main/java/org/junit/ComparisonFailure.java
index 9563e61..d1daa86 100644
--- a/src/main/java/org/junit/ComparisonFailure.java
+++ b/src/main/java/org/junit/ComparisonFailure.java
@@ -21,7 +21,7 @@
     /*
      * We have to use the f prefix until the next major release to ensure
      * serialization compatibility. 
-     * See https://github.com/junit-team/junit/issues/976
+     * See https://github.com/junit-team/junit4/issues/976
      */
     private String fExpected;
     private String fActual;
diff --git a/src/main/java/org/junit/Rule.java b/src/main/java/org/junit/Rule.java
index 711235c..9370e94 100644
--- a/src/main/java/org/junit/Rule.java
+++ b/src/main/java/org/junit/Rule.java
@@ -16,12 +16,14 @@
  * to the {@link org.junit.rules.TestRule} will run any {@link Before} methods,
  * then the {@link Test} method, and finally any {@link After} methods,
  * throwing an exception if any of these fail.  If there are multiple
- * annotated {@link Rule}s on a class, they will be applied in order of fields first, then methods.
+ * annotated {@link Rule}s on a class, they will be applied in order of methods first, then fields.
  * However, if there are multiple fields (or methods) they will be applied in an order
  * that depends on your JVM's implementation of the reflection API, which is
  * undefined, in general. Rules defined by fields will always be applied
- * before Rules defined by methods. You can use a {@link org.junit.rules.RuleChain} if you want
- * to have control over the order in which the Rules are applied.
+ * after Rules defined by methods, i.e. the Statements returned by the former will
+ * be executed around those returned by the latter.
+ *
+ * <h3>Usage</h3>
  * <p>
  * For example, here is a test class that creates a temporary folder before
  * each test method, and deletes it after each:
@@ -61,10 +63,39 @@
  * For more information and more examples, see
  * {@link org.junit.rules.TestRule}.
  *
+ * <h3>Ordering</h3>
+ * <p>
+ * You can use {@link #order()} if you want to have control over the order in
+ * which the Rules are applied.
+ *
+ * <pre>
+ * public class ThreeRules {
+ *     &#064;Rule(order = 0)
+ *     public LoggingRule outer = new LoggingRule("outer rule");
+ *
+ *     &#064;Rule(order = 1)
+ *     public LoggingRule middle = new LoggingRule("middle rule");
+ *
+ *     &#064;Rule(order = 2)
+ *     public LoggingRule inner = new LoggingRule("inner rule");
+ *
+ *     // ...
+ * }
+ * </pre>
+ *
  * @since 4.7
  */
 @Retention(RetentionPolicy.RUNTIME)
 @Target({ElementType.FIELD, ElementType.METHOD})
 public @interface Rule {
 
-}
\ No newline at end of file
+    int DEFAULT_ORDER = -1;
+
+    /**
+     * Specifies the order in which rules are applied. The rules with a higher value are inner.
+     *
+     * @since 4.13
+     */
+    int order() default DEFAULT_ORDER;
+
+}
diff --git a/src/main/java/org/junit/Test.java b/src/main/java/org/junit/Test.java
index 71ac428..1db6fc7 100644
--- a/src/main/java/org/junit/Test.java
+++ b/src/main/java/org/junit/Test.java
@@ -1,5 +1,7 @@
 package org.junit;
 
+import org.junit.function.ThrowingRunnable;
+
 import java.lang.annotation.ElementType;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -23,24 +25,40 @@
  * }
  * </pre>
  * <p>
- * The <code>Test</code> annotation supports two optional parameters.
- * The first, <code>expected</code>, declares that a test method should throw
+ * The <code>Test</code> annotation supports two optional parameters for
+ * exception testing and for limiting test execution time.
+ *
+ * <h3>Exception Testing</h3>
+ * <p>
+ * The parameter <code>expected</code> declares that a test method should throw
  * an exception. If it doesn't throw an exception or if it throws a different exception
  * than the one declared, the test fails. For example, the following test succeeds:
  * <pre>
- *    &#064;Test(<b>expected=IndexOutOfBoundsException.class</b>) public void outOfBounds() {
+ *    &#064;Test(<b>expected=IndexOutOfBoundsException.class</b>)
+ *    public void outOfBounds() {
  *       new ArrayList&lt;Object&gt;().get(1);
  *    }
  * </pre>
- * If the exception's message or one of its properties should be verified, the
- * {@link org.junit.rules.ExpectedException ExpectedException} rule can be used. Further
+ *
+ * Using the parameter <code>expected</code> for exception testing comes with
+ * some limitations: only the exception's type can be checked and it is not
+ * possible to precisely specify the code that throws the exception. Therefore
+ * JUnit 4 has improved its support for exception testing with
+ * {@link Assert#assertThrows(Class, ThrowingRunnable)} and the
+ * {@link org.junit.rules.ExpectedException ExpectedException} rule.
+ * With <code>assertThrows</code> the code that throws the exception can be
+ * precisely specified. If the exception's message or one of its properties
+ * should be verified, the <code>ExpectedException</code> rule can be used. Further
  * information about exception testing can be found at the
- * <a href="https://github.com/junit-team/junit/wiki/Exception-testing">JUnit Wiki</a>.
+ * <a href="https://github.com/junit-team/junit4/wiki/Exception-testing">JUnit Wiki</a>.
+ *
+ * <h3>Timeout</h3>
  * <p>
- * The second optional parameter, <code>timeout</code>, causes a test to fail if it takes
+ * The parameter <code>timeout</code> causes a test to fail if it takes
  * longer than a specified amount of clock time (measured in milliseconds). The following test fails:
  * <pre>
- *    &#064;Test(<b>timeout=100</b>) public void infinity() {
+ *    &#064;Test(<b>timeout=100</b>)
+ *    public void infinity() {
  *       while(true);
  *    }
  * </pre>
@@ -49,7 +67,8 @@
  * following test may or may not fail depending on how the operating system
  * schedules threads:
  * <pre>
- *    &#064;Test(<b>timeout=100</b>) public void sleep100() {
+ *    &#064;Test(<b>timeout=100</b>)
+ *    public void sleep100() {
  *       Thread.sleep(100);
  *    }
  * </pre>
@@ -66,7 +85,7 @@
 public @interface Test {
 
     /**
-     * Default empty exception
+     * Default empty exception.
      */
     static class None extends Throwable {
         private static final long serialVersionUID = 1L;
diff --git a/src/main/java/org/junit/TestCouldNotBeSkippedException.java b/src/main/java/org/junit/TestCouldNotBeSkippedException.java
new file mode 100644
index 0000000..4804493
--- /dev/null
+++ b/src/main/java/org/junit/TestCouldNotBeSkippedException.java
@@ -0,0 +1,19 @@
+package org.junit;
+
+/**
+ * Indicates that a test that indicated that it should be skipped could not be skipped.
+ * This can be thrown if a test uses the methods in {@link Assume} to indicate that
+ * it should be skipped, but before processing of the test was completed, other failures
+ * occured.
+ *
+ * @see org.junit.Assume
+ * @since 4.13
+ */
+public class TestCouldNotBeSkippedException extends RuntimeException {
+    private static final long serialVersionUID = 1L;
+
+    /** Creates an instance using the given assumption failure. */
+    public TestCouldNotBeSkippedException(org.junit.internal.AssumptionViolatedException cause) {
+        super("Test could not be skipped due to other failures", cause);
+    }
+}
diff --git a/src/main/java/org/junit/experimental/categories/Categories.java b/src/main/java/org/junit/experimental/categories/Categories.java
index 290c180..0c73ed8 100644
--- a/src/main/java/org/junit/experimental/categories/Categories.java
+++ b/src/main/java/org/junit/experimental/categories/Categories.java
@@ -2,8 +2,10 @@
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashSet;
+import java.util.LinkedHashSet;
 import java.util.Set;
 
 import org.junit.runner.Description;
@@ -76,7 +78,7 @@
  * </pre>
  *
  * @version 4.12
- * @see <a href="https://github.com/junit-team/junit/wiki/Categories">Categories at JUnit wiki</a>
+ * @see <a href="https://github.com/junit-team/junit4/wiki/Categories">Categories at JUnit wiki</a>
  */
 public class Categories extends Suite {
 
@@ -86,13 +88,13 @@
          * Determines the tests to run that are annotated with categories specified in
          * the value of this annotation or their subtypes unless excluded with {@link ExcludeCategory}.
          */
-        public Class<?>[] value() default {};
+        Class<?>[] value() default {};
 
         /**
          * If <tt>true</tt>, runs tests annotated with <em>any</em> of the categories in
          * {@link IncludeCategory#value()}. Otherwise, runs tests only if annotated with <em>all</em> of the categories.
          */
-        public boolean matchAny() default true;
+        boolean matchAny() default true;
     }
 
     @Retention(RetentionPolicy.RUNTIME)
@@ -101,13 +103,13 @@
          * Determines the tests which do not run if they are annotated with categories specified in the
          * value of this annotation or their subtypes regardless of being included in {@link IncludeCategory#value()}.
          */
-        public Class<?>[] value() default {};
+        Class<?>[] value() default {};
 
         /**
          * If <tt>true</tt>, the tests annotated with <em>any</em> of the categories in {@link ExcludeCategory#value()}
          * do not run. Otherwise, the tests do not run if and only if annotated with <em>all</em> categories.
          */
-        public boolean matchAny() default true;
+        boolean matchAny() default true;
     }
 
     public static class CategoryFilter extends Filter {
@@ -117,10 +119,7 @@
         private final boolean excludedAny;
 
         public static CategoryFilter include(boolean matchAny, Class<?>... categories) {
-            if (hasNull(categories)) {
-                throw new NullPointerException("has null category");
-            }
-            return categoryFilter(matchAny, createSet(categories), true, null);
+            return new CategoryFilter(matchAny, categories, true, null);
         }
 
         public static CategoryFilter include(Class<?> category) {
@@ -132,10 +131,7 @@
         }
 
         public static CategoryFilter exclude(boolean matchAny, Class<?>... categories) {
-            if (hasNull(categories)) {
-                throw new NullPointerException("has null category");
-            }
-            return categoryFilter(true, null, matchAny, createSet(categories));
+            return new CategoryFilter(true, null, matchAny, categories);
         }
 
         public static CategoryFilter exclude(Class<?> category) {
@@ -151,14 +147,30 @@
             return new CategoryFilter(matchAnyInclusions, inclusions, matchAnyExclusions, exclusions);
         }
 
+        @Deprecated
+        public CategoryFilter(Class<?> includedCategory, Class<?> excludedCategory) {
+            includedAny = true;
+            excludedAny = true;
+            included = nullableClassToSet(includedCategory);
+            excluded = nullableClassToSet(excludedCategory);
+        }
+
         protected CategoryFilter(boolean matchAnyIncludes, Set<Class<?>> includes,
-                               boolean matchAnyExcludes, Set<Class<?>> excludes) {
+                                 boolean matchAnyExcludes, Set<Class<?>> excludes) {
             includedAny = matchAnyIncludes;
             excludedAny = matchAnyExcludes;
             included = copyAndRefine(includes);
             excluded = copyAndRefine(excludes);
         }
 
+        private CategoryFilter(boolean matchAnyIncludes, Class<?>[] inclusions,
+                               boolean matchAnyExcludes, Class<?>[] exclusions) {
+            includedAny = matchAnyIncludes; 
+            excludedAny = matchAnyExcludes;
+            included = createSet(inclusions);
+            excluded = createSet(exclusions);
+        }
+
         /**
          * @see #toString()
          */
@@ -284,23 +296,13 @@
         }
 
         private static Set<Class<?>> copyAndRefine(Set<Class<?>> classes) {
-            HashSet<Class<?>> c= new HashSet<Class<?>>();
+            Set<Class<?>> c= new LinkedHashSet<Class<?>>();
             if (classes != null) {
                 c.addAll(classes);
             }
             c.remove(null);
             return c;
         }
-
-        private static boolean hasNull(Class<?>... classes) {
-            if (classes == null) return false;
-            for (Class<?> clazz : classes) {
-                if (clazz == null) {
-                    return true;
-                }
-            }
-            return false;
-        }
     }
 
     public Categories(Class<?> klass, RunnerBuilder builder) throws InitializationError {
@@ -315,7 +317,6 @@
         } catch (NoTestsRemainException e) {
             throw new InitializationError(e);
         }
-        assertNoCategorizedDescendentsOfUncategorizeableParents(getDescription());
     }
 
     private static Set<Class<?>> getIncludedCategory(Class<?> klass) {
@@ -338,34 +339,6 @@
         return annotation == null || annotation.matchAny();
     }
 
-    private static void assertNoCategorizedDescendentsOfUncategorizeableParents(Description description) throws InitializationError {
-        if (!canHaveCategorizedChildren(description)) {
-            assertNoDescendantsHaveCategoryAnnotations(description);
-        }
-        for (Description each : description.getChildren()) {
-            assertNoCategorizedDescendentsOfUncategorizeableParents(each);
-        }
-    }
-
-    private static void assertNoDescendantsHaveCategoryAnnotations(Description description) throws InitializationError {
-        for (Description each : description.getChildren()) {
-            if (each.getAnnotation(Category.class) != null) {
-                throw new InitializationError("Category annotations on Parameterized classes are not supported on individual methods.");
-            }
-            assertNoDescendantsHaveCategoryAnnotations(each);
-        }
-    }
-
-    // If children have names like [0], our current magical category code can't determine their parentage.
-    private static boolean canHaveCategorizedChildren(Description description) {
-        for (Description each : description.getChildren()) {
-            if (each.getTestClass() == null) {
-                return false;
-            }
-        }
-        return true;
-    }
-
     private static boolean hasAssignableTo(Set<Class<?>> assigns, Class<?> to) {
         for (final Class<?> from : assigns) {
             if (to.isAssignableFrom(from)) {
@@ -375,11 +348,28 @@
         return false;
     }
 
-    private static Set<Class<?>> createSet(Class<?>... t) {
-        final Set<Class<?>> set= new HashSet<Class<?>>();
-        if (t != null) {
-            Collections.addAll(set, t);
+    private static Set<Class<?>> createSet(Class<?>[] classes) {
+        // Not throwing a NPE if t is null is a bad idea, but it's the behavior from JUnit 4.12
+        // for include(boolean, Class<?>...) and exclude(boolean, Class<?>...)
+        if (classes == null || classes.length == 0) {
+            return Collections.emptySet();
         }
-        return set;
+        for (Class<?> category : classes) {
+            if (category == null) {
+                throw new NullPointerException("has null category");
+            }
+        }
+
+        return classes.length == 1
+            ? Collections.<Class<?>>singleton(classes[0])
+            : new LinkedHashSet<Class<?>>(Arrays.asList(classes));
+    }
+
+    private static Set<Class<?>> nullableClassToSet(Class<?> nullableClass) {
+        // Not throwing a NPE if t is null is a bad idea, but it's the behavior from JUnit 4.11
+        // for CategoryFilter(Class<?> includedCategory, Class<?> excludedCategory)
+        return nullableClass == null
+                ? Collections.<Class<?>>emptySet()
+                : Collections.<Class<?>>singleton(nullableClass);
     }
 }
diff --git a/src/main/java/org/junit/experimental/categories/CategoryFilterFactory.java b/src/main/java/org/junit/experimental/categories/CategoryFilterFactory.java
index cee1ae7..e9bdab7 100644
--- a/src/main/java/org/junit/experimental/categories/CategoryFilterFactory.java
+++ b/src/main/java/org/junit/experimental/categories/CategoryFilterFactory.java
@@ -37,7 +37,11 @@
         List<Class<?>> categoryClasses = new ArrayList<Class<?>>();

 

         for (String category : categories.split(",")) {

-            Class<?> categoryClass = Classes.getClass(category);

+            /*

+             * Load the category class using the context class loader.

+             * If there is no context class loader, use the class loader for this class.

+             */

+            Class<?> categoryClass = Classes.getClass(category, getClass());

 

             categoryClasses.add(categoryClass);

         }

diff --git a/src/main/java/org/junit/experimental/max/MaxHistory.java b/src/main/java/org/junit/experimental/max/MaxHistory.java
index 45a4033..ab7443f 100644
--- a/src/main/java/org/junit/experimental/max/MaxHistory.java
+++ b/src/main/java/org/junit/experimental/max/MaxHistory.java
@@ -64,7 +64,7 @@
     /*
      * We have to use the f prefix until the next major release to ensure
      * serialization compatibility. 
-     * See https://github.com/junit-team/junit/issues/976
+     * See https://github.com/junit-team/junit4/issues/976
      */
     private final Map<String, Long> fDurations = new HashMap<String, Long>();
     private final Map<String, Long> fFailureTimestamps = new HashMap<String, Long>();
@@ -75,10 +75,15 @@
     }
 
     private void save() throws IOException {
-        ObjectOutputStream stream = new ObjectOutputStream(new FileOutputStream(
-                fHistoryStore));
-        stream.writeObject(this);
-        stream.close();
+        ObjectOutputStream stream = null;
+        try {
+            stream = new ObjectOutputStream(new FileOutputStream(fHistoryStore));
+            stream.writeObject(this);
+        } finally {
+            if (stream != null) {
+                stream.close();
+            }
+        }
     }
 
     Long getFailureTimestamp(Description key) {
diff --git a/src/main/java/org/junit/experimental/results/PrintableResult.java b/src/main/java/org/junit/experimental/results/PrintableResult.java
index ffe22f0..0f67766 100644
--- a/src/main/java/org/junit/experimental/results/PrintableResult.java
+++ b/src/main/java/org/junit/experimental/results/PrintableResult.java
@@ -54,6 +54,15 @@
         return result.getFailures().size();
     }
 
+    /**
+     * Returns the failures in this result.
+     *
+     * @since 4.13
+     */
+    public List<Failure> failures() {
+        return result.getFailures();
+    }
+
     @Override
     public String toString() {
         ByteArrayOutputStream stream = new ByteArrayOutputStream();
diff --git a/src/main/java/org/junit/experimental/results/ResultMatchers.java b/src/main/java/org/junit/experimental/results/ResultMatchers.java
index cf58f1b..92f2e6b 100644
--- a/src/main/java/org/junit/experimental/results/ResultMatchers.java
+++ b/src/main/java/org/junit/experimental/results/ResultMatchers.java
@@ -14,6 +14,15 @@
  * </pre>
  */
 public class ResultMatchers {
+
+    /**
+     * Do not instantiate.
+     * @deprecated will be private soon.
+     */
+    @Deprecated
+    public ResultMatchers() {
+    }
+
     /**
      * Matches if the tests are all successful
      */
@@ -53,13 +62,33 @@
     }
 
     /**
+     * Matches if the result has exactly one failure matching the given matcher.
+     *
+     * @since 4.13
+     */
+    public static Matcher<PrintableResult> hasSingleFailureMatching(final Matcher<Throwable> matcher) {
+        return new TypeSafeMatcher<PrintableResult>() {
+            @Override
+            public boolean matchesSafely(PrintableResult item) {
+                return item.failureCount() == 1 && matcher.matches(item.failures().get(0).getException());
+            }
+
+            public void describeTo(Description description) {
+                description.appendText("has failure with exception matching ");
+                matcher.describeTo(description);
+            }
+        };
+    }
+
+    /**
      * Matches if the result has one or more failures, and at least one of them
      * contains {@code string}
      */
     public static Matcher<PrintableResult> hasFailureContaining(final String string) {
-        return new BaseMatcher<PrintableResult>() {
-            public boolean matches(Object item) {
-                return item.toString().contains(string);
+        return new TypeSafeMatcher<PrintableResult>() {
+            @Override
+            public boolean matchesSafely(PrintableResult item) {
+                return item.failureCount() > 0 && item.toString().contains(string);
             }
 
             public void describeTo(Description description) {
diff --git a/src/main/java/org/junit/experimental/theories/ParametersSuppliedBy.java b/src/main/java/org/junit/experimental/theories/ParametersSuppliedBy.java
index 15b5d95..846a39e 100644
--- a/src/main/java/org/junit/experimental/theories/ParametersSuppliedBy.java
+++ b/src/main/java/org/junit/experimental/theories/ParametersSuppliedBy.java
@@ -17,7 +17,7 @@
  * 
  * In addition, annotations themselves can be annotated with
  * &#064;ParametersSuppliedBy, and then used similarly. ParameterSuppliedBy
- * annotations on parameters are detected by searching up this heirarchy such
+ * annotations on parameters are detected by searching up this hierarchy such
  * that these act as syntactic sugar, making:
  * 
  * <pre>
diff --git a/src/main/java/org/junit/experimental/theories/Theories.java b/src/main/java/org/junit/experimental/theories/Theories.java
index 817f553..ac88a36 100644
--- a/src/main/java/org/junit/experimental/theories/Theories.java
+++ b/src/main/java/org/junit/experimental/theories/Theories.java
@@ -51,11 +51,11 @@
  *      }
  * }
  * </pre>
- * This makes it clear that the user's filename should be included in the config file name,
+ * This makes it clear that the username should be included in the config file name,
  * only if it doesn't contain a slash. Another test or theory might define what happens when a username does contain
  * a slash. <code>UserTest</code> will attempt to run <code>filenameIncludesUsername</code> on every compatible data
  * point defined in the class. If any of the assumptions fail, the data point is silently ignored. If all of the
- * assumptions pass, but an assertion fails, the test fails.
+ * assumptions pass, but an assertion fails, the test fails. If no parameters can be found that satisfy all assumptions, the test fails.
  * <p>
  * Defining general statements as theories allows data point reuse across a bunch of functionality tests and also
  * allows automated tools to search for new, unexpected data points that expose bugs.
@@ -73,6 +73,11 @@
         super(klass);
     }
 
+    /** @since 4.13 */
+    protected Theories(TestClass testClass) throws InitializationError {
+        super(testClass);
+    }
+
     @Override
     protected void collectInitializationErrors(List<Throwable> errors) {
         super.collectInitializationErrors(errors);
@@ -215,7 +220,7 @@
 
         protected void runWithCompleteAssignment(final Assignments complete)
                 throws Throwable {
-            new BlockJUnit4ClassRunner(getTestClass().getJavaClass()) {
+            new BlockJUnit4ClassRunner(getTestClass()) {
                 @Override
                 protected void collectInitializationErrors(
                         List<Throwable> errors) {
diff --git a/src/main/java/org/junit/experimental/theories/internal/Assignments.java b/src/main/java/org/junit/experimental/theories/internal/Assignments.java
index a94c8a5..6626797 100644
--- a/src/main/java/org/junit/experimental/theories/internal/Assignments.java
+++ b/src/main/java/org/junit/experimental/theories/internal/Assignments.java
@@ -47,7 +47,7 @@
     }
 
     public boolean isComplete() {
-        return unassigned.size() == 0;
+        return unassigned.isEmpty();
     }
 
     public ParameterSignature nextUnassigned() {
@@ -55,11 +55,10 @@
     }
 
     public Assignments assignNext(PotentialAssignment source) {
-        List<PotentialAssignment> assigned = new ArrayList<PotentialAssignment>(
-                this.assigned);
-        assigned.add(source);
+        List<PotentialAssignment> potentialAssignments = new ArrayList<PotentialAssignment>(assigned);
+        potentialAssignments.add(source);
 
-        return new Assignments(assigned, unassigned.subList(1,
+        return new Assignments(potentialAssignments, unassigned.subList(1,
                 unassigned.size()), clazz);
     }
 
@@ -77,7 +76,7 @@
         ParameterSignature unassigned = nextUnassigned();
         List<PotentialAssignment> assignments = getSupplier(unassigned).getValueSources(unassigned);
         
-        if (assignments.size() == 0) {
+        if (assignments.isEmpty()) {
             assignments = generateAssignmentsFromTypeAlone(unassigned);
         }
         
diff --git a/src/main/java/org/junit/function/ThrowingRunnable.java b/src/main/java/org/junit/function/ThrowingRunnable.java
new file mode 100644
index 0000000..d0eb782
--- /dev/null
+++ b/src/main/java/org/junit/function/ThrowingRunnable.java
@@ -0,0 +1,14 @@
+package org.junit.function;
+
+/**
+ * This interface facilitates the use of
+ * {@link org.junit.Assert#assertThrows(Class, ThrowingRunnable)} from Java 8. It allows method
+ * references to void methods (that declare checked exceptions) to be passed directly into
+ * {@code assertThrows}
+ * without wrapping. It is not meant to be implemented directly.
+ *
+ * @since 4.13
+ */
+public interface ThrowingRunnable {
+    void run() throws Throwable;
+}
diff --git a/src/main/java/org/junit/internal/ArrayComparisonFailure.java b/src/main/java/org/junit/internal/ArrayComparisonFailure.java
index 8627d6e..d300e7e 100644
--- a/src/main/java/org/junit/internal/ArrayComparisonFailure.java
+++ b/src/main/java/org/junit/internal/ArrayComparisonFailure.java
@@ -16,11 +16,12 @@
 
     /*
      * We have to use the f prefix until the next major release to ensure
-     * serialization compatibility. 
-     * See https://github.com/junit-team/junit/issues/976
+     * serialization compatibility.
+     * See https://github.com/junit-team/junit4/issues/976
      */
     private final List<Integer> fIndices = new ArrayList<Integer>();
     private final String fMessage;
+    private final AssertionError fCause;
 
     /**
      * Construct a new <code>ArrayComparisonFailure</code> with an error text and the array's
@@ -32,7 +33,8 @@
      */
     public ArrayComparisonFailure(String message, AssertionError cause, int index) {
         this.fMessage = message;
-        initCause(cause);
+        this.fCause = cause;
+        initCause(fCause);
         addDimension(index);
     }
 
@@ -41,6 +43,11 @@
     }
 
     @Override
+    public synchronized Throwable getCause() {
+        return super.getCause() == null ? fCause : super.getCause();
+    }
+
+    @Override
     public String getMessage() {
         StringBuilder sb = new StringBuilder();
         if (fMessage != null) {
diff --git a/src/main/java/org/junit/internal/AssumptionViolatedException.java b/src/main/java/org/junit/internal/AssumptionViolatedException.java
index 880d73f..0e79b56 100644
--- a/src/main/java/org/junit/internal/AssumptionViolatedException.java
+++ b/src/main/java/org/junit/internal/AssumptionViolatedException.java
@@ -1,5 +1,8 @@
 package org.junit.internal;
 
+import java.io.IOException;
+import java.io.ObjectOutputStream;
+
 import org.hamcrest.Description;
 import org.hamcrest.Matcher;
 import org.hamcrest.SelfDescribing;
@@ -18,7 +21,7 @@
     /*
      * We have to use the f prefix until the next major release to ensure
      * serialization compatibility. 
-     * See https://github.com/junit-team/junit/issues/976
+     * See https://github.com/junit-team/junit4/issues/976
      */
     private final String fAssumption;
     private final boolean fValueMatcher;
@@ -108,4 +111,29 @@
             }
         }
     }
+
+    /**
+     * Override default Java object serialization to correctly deal with potentially unserializable matchers or values.
+     * By not implementing readObject, we assure ourselves of backwards compatibility and compatibility with the
+     * standard way of Java serialization.
+     *
+     * @param objectOutputStream The outputStream to write our representation to
+     * @throws IOException When serialization fails
+     */
+    private void writeObject(ObjectOutputStream objectOutputStream) throws IOException {
+        ObjectOutputStream.PutField putField = objectOutputStream.putFields();
+        putField.put("fAssumption", fAssumption);
+        putField.put("fValueMatcher", fValueMatcher);
+
+        // We have to wrap the matcher into a serializable form.
+        putField.put("fMatcher", SerializableMatcherDescription.asSerializableMatcher(fMatcher));
+
+        // We have to wrap the value inside a non-String class (instead of serializing the String value directly) as
+        // A Description will handle a String and non-String object differently (1st is surrounded by '"' while the
+        // latter will be surrounded by '<' '>'. Wrapping it makes sure that the description of a serialized and
+        // non-serialized instance produce the exact same description
+        putField.put("fValue", SerializableValueDescription.asSerializableValue(fValue));
+
+        objectOutputStream.writeFields();
+    }
 }
diff --git a/src/main/java/org/junit/internal/Checks.java b/src/main/java/org/junit/internal/Checks.java
new file mode 100644
index 0000000..9724947
--- /dev/null
+++ b/src/main/java/org/junit/internal/Checks.java
@@ -0,0 +1,37 @@
+package org.junit.internal;
+
+/** @since 4.13 */
+public final class Checks {
+
+    private Checks() {}
+
+    /**
+     * Checks that the given value is not {@code null}.
+     *
+     * @param value object reference to check
+     * @return the passed-in value, if not {@code null}
+     * @throws NullPointerException if {@code value} is {@code null}
+     */
+    public static <T> T notNull(T value) {
+        if (value == null) {
+            throw new NullPointerException();
+        }
+        return value;
+    }
+
+    /**
+     * Checks that the given value is not {@code null}, using the given message
+     * as the exception message if an exception is thrown.
+     *
+     * @param value object reference to check
+     * @param message message to use if {@code value} is {@code null}
+     * @return the passed-in value, if not {@code null}
+     * @throws NullPointerException if {@code value} is {@code null}
+     */
+    public static <T> T notNull(T value, String message) {
+        if (value == null) {
+            throw new NullPointerException(message);
+        }
+        return value;
+    }
+}
diff --git a/src/main/java/org/junit/internal/Classes.java b/src/main/java/org/junit/internal/Classes.java
index 154603d..e8404f6 100644
--- a/src/main/java/org/junit/internal/Classes.java
+++ b/src/main/java/org/junit/internal/Classes.java
@@ -6,13 +6,39 @@
  * Miscellaneous functions dealing with classes.

  */

 public class Classes {

+

+    /**

+     * Do not instantiate.

+     * @deprecated will be private soon.

+     */

+    @Deprecated

+    public Classes() {

+    }

+

     /**

      * Returns Class.forName for {@code className} using the current thread's class loader.

+     * If the current thread does not have a class loader, falls back to the class loader for

+     * {@link Classes}.

      *

      * @param className Name of the class.

      * @throws ClassNotFoundException

      */

     public static Class<?> getClass(String className) throws ClassNotFoundException {

-        return Class.forName(className, true, currentThread().getContextClassLoader());

+        return getClass(className, Classes.class);

+    }

+

+    /**

+     * Returns Class.forName for {@code className} using the current thread's class loader.

+     * If the current thread does not have a class loader, falls back to the class loader for the

+     * passed-in class.

+     *

+     * @param className Name of the class.

+     * @param callingClass Class that is requesting a the class

+     * @throws ClassNotFoundException

+     * @since 4.13

+     */

+    public static Class<?> getClass(String className, Class<?> callingClass) throws ClassNotFoundException {

+        ClassLoader classLoader = currentThread().getContextClassLoader();

+        return Class.forName(className, true, classLoader == null ? callingClass.getClassLoader() : classLoader);

     }

 }

diff --git a/src/main/java/org/junit/internal/ComparisonCriteria.java b/src/main/java/org/junit/internal/ComparisonCriteria.java
index e6d49a4..ed1c674 100644
--- a/src/main/java/org/junit/internal/ComparisonCriteria.java
+++ b/src/main/java/org/junit/internal/ComparisonCriteria.java
@@ -25,6 +25,11 @@
      */
     public void arrayEquals(String message, Object expecteds, Object actuals)
             throws ArrayComparisonFailure {
+        arrayEquals(message, expecteds, actuals, true);
+    }
+
+    private void arrayEquals(String message, Object expecteds, Object actuals, boolean outer)
+            throws ArrayComparisonFailure {
         if (expecteds == actuals
             || Arrays.deepEquals(new Object[] {expecteds}, new Object[] {actuals})) {
             // The reflection-based loop below is potentially very slow, especially for primitive
@@ -34,19 +39,37 @@
         }
         String header = message == null ? "" : message + ": ";
 
-        int expectedsLength = assertArraysAreSameLength(expecteds,
-                actuals, header);
+        // Only include the user-provided message in the outer exception.
+        String exceptionMessage = outer ? header : "";
 
-        for (int i = 0; i < expectedsLength; i++) {
+        if (expecteds == null) {
+            Assert.fail(exceptionMessage + "expected array was null");
+        }
+        if (actuals == null) {
+            Assert.fail(exceptionMessage + "actual array was null");
+        }
+
+        int actualsLength = Array.getLength(actuals);
+        int expectedsLength = Array.getLength(expecteds);
+        if (actualsLength != expectedsLength) {
+            header += "array lengths differed, expected.length="
+                    + expectedsLength + " actual.length=" + actualsLength + "; ";
+        }
+        int prefixLength = Math.min(actualsLength, expectedsLength);
+
+        for (int i = 0; i < prefixLength; i++) {
             Object expected = Array.get(expecteds, i);
             Object actual = Array.get(actuals, i);
 
             if (isArray(expected) && isArray(actual)) {
                 try {
-                    arrayEquals(message, expected, actual);
+                    arrayEquals(message, expected, actual, false);
                 } catch (ArrayComparisonFailure e) {
                     e.addDimension(i);
                     throw e;
+                } catch (AssertionError e) {
+                    // Array lengths differed.
+                    throw new ArrayComparisonFailure(header, e, i);
                 }
             } else {
                 try {
@@ -56,28 +79,54 @@
                 }
             }
         }
+
+        if (actualsLength != expectedsLength) {
+            Object expected = getToStringableArrayElement(expecteds, expectedsLength, prefixLength);
+            Object actual = getToStringableArrayElement(actuals, actualsLength, prefixLength);
+            try {
+                Assert.assertEquals(expected, actual);
+            } catch (AssertionError e) {
+                throw new ArrayComparisonFailure(header, e, prefixLength);
+            }
+        }
+    }
+
+    private static final Object END_OF_ARRAY_SENTINEL = objectWithToString("end of array");
+
+    private Object getToStringableArrayElement(Object array, int length, int index) {
+        if (index < length) {
+            Object element = Array.get(array, index);
+            if (isArray(element)) {
+                return objectWithToString(componentTypeName(element.getClass()) + "[" + Array.getLength(element) + "]");
+            } else {
+                return element;
+            }
+        } else {
+            return END_OF_ARRAY_SENTINEL;
+        }
+    }
+
+    private static Object objectWithToString(final String string) {
+        return new Object() {
+            @Override
+            public String toString() {
+                return string;
+            }
+        };
+    }
+
+    private String componentTypeName(Class<?> arrayClass) {
+        Class<?> componentType = arrayClass.getComponentType();
+        if (componentType.isArray()) {
+            return componentTypeName(componentType) + "[]";
+        } else {
+            return componentType.getName();
+        }
     }
 
     private boolean isArray(Object expected) {
         return expected != null && expected.getClass().isArray();
     }
 
-    private int assertArraysAreSameLength(Object expecteds,
-            Object actuals, String header) {
-        if (expecteds == null) {
-            Assert.fail(header + "expected array was null");
-        }
-        if (actuals == null) {
-            Assert.fail(header + "actual array was null");
-        }
-        int actualsLength = Array.getLength(actuals);
-        int expectedsLength = Array.getLength(expecteds);
-        if (actualsLength != expectedsLength) {
-            Assert.fail(header + "array lengths differed, expected.length="
-                    + expectedsLength + " actual.length=" + actualsLength);
-        }
-        return expectedsLength;
-    }
-
     protected abstract void assertElementsEqual(Object expected, Object actual);
 }
diff --git a/src/main/java/org/junit/internal/SerializableMatcherDescription.java b/src/main/java/org/junit/internal/SerializableMatcherDescription.java
new file mode 100644
index 0000000..e036557
--- /dev/null
+++ b/src/main/java/org/junit/internal/SerializableMatcherDescription.java
@@ -0,0 +1,47 @@
+package org.junit.internal;
+
+import java.io.Serializable;
+
+import org.hamcrest.BaseMatcher;
+import org.hamcrest.Description;
+import org.hamcrest.Matcher;
+import org.hamcrest.StringDescription;
+
+/**
+ * This class exists solely to provide a serializable description of a matcher to be serialized as a field in
+ * {@link AssumptionViolatedException}. Being a {@link Throwable}, it is required to be {@link Serializable}, but most
+ * implementations of {@link Matcher} are not. This class works around that limitation as
+ * {@link AssumptionViolatedException} only every uses the description of the {@link Matcher}, while still retaining
+ * backwards compatibility with classes compiled against its class signature before 4.14 and/or deserialization of
+ * previously serialized instances.
+ */
+class SerializableMatcherDescription<T> extends BaseMatcher<T> implements Serializable {
+
+    private final String matcherDescription;
+
+    private SerializableMatcherDescription(Matcher<T> matcher) {
+        matcherDescription = StringDescription.asString(matcher);
+    }
+
+    public boolean matches(Object o) {
+        throw new UnsupportedOperationException("This Matcher implementation only captures the description");
+    }
+
+    public void describeTo(Description description) {
+        description.appendText(matcherDescription);
+    }
+
+    /**
+     * Factory method that checks to see if the matcher is already serializable.
+     * @param matcher the matcher to make serializable
+     * @return The provided matcher if it is null or already serializable,
+     * the SerializableMatcherDescription representation of it if it is not.
+     */
+    static <T> Matcher<T> asSerializableMatcher(Matcher<T> matcher) {
+        if (matcher == null || matcher instanceof Serializable) {
+            return matcher;
+        } else {
+            return new SerializableMatcherDescription<T>(matcher);
+        }
+    }
+}
diff --git a/src/main/java/org/junit/internal/SerializableValueDescription.java b/src/main/java/org/junit/internal/SerializableValueDescription.java
new file mode 100644
index 0000000..4d055d7
--- /dev/null
+++ b/src/main/java/org/junit/internal/SerializableValueDescription.java
@@ -0,0 +1,38 @@
+package org.junit.internal;
+
+import java.io.Serializable;
+
+/**
+ * This class exists solely to provide a serializable description of a value to be serialized as a field in
+ * {@link AssumptionViolatedException}. Being a {@link Throwable}, it is required to be {@link Serializable}, but a
+ * value of type Object provides no guarantee to be serializable. This class works around that limitation as
+ * {@link AssumptionViolatedException} only every uses the string representation of the value, while still retaining
+ * backwards compatibility with classes compiled against its class signature before 4.14 and/or deserialization of
+ * previously serialized instances.
+ */
+class SerializableValueDescription implements Serializable {
+    private final String value;
+
+    private SerializableValueDescription(Object value) {
+        this.value = String.valueOf(value);
+    }
+
+    /**
+     * Factory method that checks to see if the value is already serializable.
+     * @param value the value to make serializable
+     * @return The provided value if it is null or already serializable,
+     * the SerializableValueDescription representation of it if it is not.
+     */
+    static Object asSerializableValue(Object value) {
+        if (value == null || value instanceof Serializable) {
+            return value;
+        } else {
+            return new SerializableValueDescription(value);
+        }
+    }
+
+    @Override
+    public String toString() {
+        return value;
+    }
+}
diff --git a/src/main/java/org/junit/internal/TextListener.java b/src/main/java/org/junit/internal/TextListener.java
index 9aa56c7..d548aeb 100644
--- a/src/main/java/org/junit/internal/TextListener.java
+++ b/src/main/java/org/junit/internal/TextListener.java
@@ -58,7 +58,7 @@
 
     protected void printFailures(Result result) {
         List<Failure> failures = result.getFailures();
-        if (failures.size() == 0) {
+        if (failures.isEmpty()) {
             return;
         }
         if (failures.size() == 1) {
@@ -74,7 +74,7 @@
 
     protected void printFailure(Failure each, String prefix) {
         getWriter().println(prefix + ") " + each.getTestHeader());
-        getWriter().print(each.getTrace());
+        getWriter().print(each.getTrimmedTrace());
     }
 
     protected void printFooter(Result result) {
diff --git a/src/main/java/org/junit/internal/Throwables.java b/src/main/java/org/junit/internal/Throwables.java
index 86dceef..3f0f7a3 100644
--- a/src/main/java/org/junit/internal/Throwables.java
+++ b/src/main/java/org/junit/internal/Throwables.java
@@ -1,5 +1,17 @@
 package org.junit.internal;
 
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.lang.reflect.Method;
+import java.util.AbstractList;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
 /**
  * Miscellaneous functions dealing with {@code Throwable}.
  *
@@ -39,4 +51,223 @@
     private static <T extends Throwable> void rethrow(Throwable e) throws T {
         throw (T) e;
     }
+
+    /**
+     * Returns the stacktrace of the given Throwable as a String.
+     *
+     * @since 4.13
+     */
+    public static String getStacktrace(Throwable exception) {
+        StringWriter stringWriter = new StringWriter();
+        PrintWriter writer = new PrintWriter(stringWriter);
+        exception.printStackTrace(writer);
+        return stringWriter.toString();
+    }
+
+    /**
+     * Gets a trimmed version of the stack trace of the given exception. Stack trace
+     * elements that are below the test method are filtered out.
+     *
+     * @return a trimmed stack trace, or the original trace if trimming wasn't possible
+     */
+    public static String getTrimmedStackTrace(Throwable exception) {
+        List<String> trimmedStackTraceLines = getTrimmedStackTraceLines(exception);
+        if (trimmedStackTraceLines.isEmpty()) {
+            return getFullStackTrace(exception);
+        }
+
+        StringBuilder result = new StringBuilder(exception.toString());
+        appendStackTraceLines(trimmedStackTraceLines, result);
+        appendStackTraceLines(getCauseStackTraceLines(exception), result);
+        return result.toString();
+    }
+
+    private static List<String> getTrimmedStackTraceLines(Throwable exception) {
+        List<StackTraceElement> stackTraceElements = Arrays.asList(exception.getStackTrace());
+        int linesToInclude = stackTraceElements.size();
+
+        State state = State.PROCESSING_OTHER_CODE;
+        for (StackTraceElement stackTraceElement : asReversedList(stackTraceElements)) {
+            state = state.processStackTraceElement(stackTraceElement);
+            if (state == State.DONE) {
+                List<String> trimmedLines = new ArrayList<String>(linesToInclude + 2);
+                trimmedLines.add("");
+                for (StackTraceElement each : stackTraceElements.subList(0, linesToInclude)) {
+                    trimmedLines.add("\tat " + each);
+                }
+                if (exception.getCause() != null) {
+                    trimmedLines.add("\t... " + (stackTraceElements.size() - trimmedLines.size()) + " trimmed");
+                }
+                return trimmedLines;
+            }
+            linesToInclude--;
+        }
+        return Collections.emptyList();
+    }
+
+    private static final Method getSuppressed = initGetSuppressed();
+
+    private static Method initGetSuppressed() {
+        try {
+            return Throwable.class.getMethod("getSuppressed");
+        } catch (Throwable e) {
+            return null;
+        }
+    }
+
+    private static boolean hasSuppressed(Throwable exception) {
+        if (getSuppressed == null) {
+            return false;
+        }
+        try {
+            Throwable[] suppressed = (Throwable[]) getSuppressed.invoke(exception);
+            return suppressed.length != 0;
+        } catch (Throwable e) {
+            return false;
+        }
+    }
+
+    private static List<String> getCauseStackTraceLines(Throwable exception) {
+        if (exception.getCause() != null || hasSuppressed(exception)) {
+            String fullTrace = getFullStackTrace(exception);
+            BufferedReader reader = new BufferedReader(
+                    new StringReader(fullTrace.substring(exception.toString().length())));
+            List<String> causedByLines = new ArrayList<String>();
+    
+            try {
+                String line;
+                while ((line = reader.readLine()) != null) {
+                    if (line.startsWith("Caused by: ") || line.trim().startsWith("Suppressed: ")) {
+                        causedByLines.add(line);
+                        while ((line = reader.readLine()) != null) {
+                            causedByLines.add(line);
+                        }
+                        return causedByLines;
+                    }
+                }
+            } catch (IOException e) {
+                // We should never get here, because we are reading from a StringReader
+            }
+        }
+
+        return Collections.emptyList();
+    }
+
+    private static String getFullStackTrace(Throwable exception) {
+        StringWriter stringWriter = new StringWriter();
+        PrintWriter writer = new PrintWriter(stringWriter);
+        exception.printStackTrace(writer);
+        return stringWriter.toString();
+    }
+
+    private static void appendStackTraceLines(
+            List<String> stackTraceLines, StringBuilder destBuilder) {
+        for (String stackTraceLine : stackTraceLines) {
+            destBuilder.append(String.format("%s%n", stackTraceLine));
+        }
+    }
+
+    private static <T> List<T> asReversedList(final List<T> list) {
+        return new AbstractList<T>() {
+
+            @Override
+            public T get(int index) {
+                return list.get(list.size() - index - 1);
+            }
+
+            @Override
+            public int size() {
+                return list.size();
+            }
+        };
+    }
+
+    private enum State {
+        PROCESSING_OTHER_CODE {
+            @Override public State processLine(String methodName) {
+                if (isTestFrameworkMethod(methodName)) {
+                    return PROCESSING_TEST_FRAMEWORK_CODE;
+                }
+                return this;
+            }
+        },
+        PROCESSING_TEST_FRAMEWORK_CODE {
+            @Override public State processLine(String methodName) {
+                if (isReflectionMethod(methodName)) {
+                    return PROCESSING_REFLECTION_CODE;
+                } else if (isTestFrameworkMethod(methodName)) {
+                    return this;
+                }
+                return PROCESSING_OTHER_CODE;
+            } 
+        },
+        PROCESSING_REFLECTION_CODE {
+            @Override public State processLine(String methodName) {
+                if (isReflectionMethod(methodName)) {
+                    return this;
+                } else if (isTestFrameworkMethod(methodName)) {
+                    // This is here to handle TestCase.runBare() calling TestCase.runTest().
+                    return PROCESSING_TEST_FRAMEWORK_CODE;
+                }
+                return DONE;
+            } 
+        },
+        DONE {
+            @Override public State processLine(String methodName) {
+                return this;
+            } 
+        };
+
+        /** Processes a stack trace element method name, possibly moving to a new state. */
+        protected abstract State processLine(String methodName);
+        
+        /** Processes a stack trace element, possibly moving to a new state. */
+        public final State processStackTraceElement(StackTraceElement element) {
+            return processLine(element.getClassName() + "." + element.getMethodName() + "()");
+        }
+    }
+
+    private static final String[] TEST_FRAMEWORK_METHOD_NAME_PREFIXES = {
+        "org.junit.runner.",
+        "org.junit.runners.",
+        "org.junit.experimental.runners.",
+        "org.junit.internal.",
+        "junit.extensions",
+        "junit.framework",
+        "junit.runner",
+        "junit.textui",
+    };
+
+    private static final String[] TEST_FRAMEWORK_TEST_METHOD_NAME_PREFIXES = {
+        "org.junit.internal.StackTracesTest",
+    };
+
+    private static boolean isTestFrameworkMethod(String methodName) {
+        return isMatchingMethod(methodName, TEST_FRAMEWORK_METHOD_NAME_PREFIXES) &&
+                !isMatchingMethod(methodName, TEST_FRAMEWORK_TEST_METHOD_NAME_PREFIXES);
+    }
+    
+    private static final String[] REFLECTION_METHOD_NAME_PREFIXES = {
+        "sun.reflect.",
+        "java.lang.reflect.",
+        "jdk.internal.reflect.",
+        "org.junit.rules.RunRules.<init>(",
+        "org.junit.rules.RunRules.applyAll(", // calls TestRules
+        "org.junit.runners.RuleContainer.apply(", // calls MethodRules & TestRules
+        "junit.framework.TestCase.runBare(", // runBare() directly calls setUp() and tearDown()
+   };
+    
+    private static boolean isReflectionMethod(String methodName) {
+        return isMatchingMethod(methodName, REFLECTION_METHOD_NAME_PREFIXES);
+    }
+
+    private static boolean isMatchingMethod(String methodName, String[] methodNamePrefixes) {
+        for (String methodNamePrefix : methodNamePrefixes) {
+            if (methodName.startsWith(methodNamePrefix)) {
+                return true;
+            }
+        }
+        
+        return false;
+    }
 }
diff --git a/src/main/java/org/junit/internal/builders/AllDefaultPossibilitiesBuilder.java b/src/main/java/org/junit/internal/builders/AllDefaultPossibilitiesBuilder.java
index d86ec95..8704a54 100644
--- a/src/main/java/org/junit/internal/builders/AllDefaultPossibilitiesBuilder.java
+++ b/src/main/java/org/junit/internal/builders/AllDefaultPossibilitiesBuilder.java
@@ -9,6 +9,17 @@
 public class AllDefaultPossibilitiesBuilder extends RunnerBuilder {
     private final boolean canUseSuiteMethod;
 
+    /**
+     * @since 4.13
+     */
+    public AllDefaultPossibilitiesBuilder() {
+        canUseSuiteMethod = true;
+    }
+
+    /**
+     * @deprecated used {@link #AllDefaultPossibilitiesBuilder()}.
+     */
+    @Deprecated
     public AllDefaultPossibilitiesBuilder(boolean canUseSuiteMethod) {
         this.canUseSuiteMethod = canUseSuiteMethod;
     }
diff --git a/src/main/java/org/junit/internal/builders/JUnit4Builder.java b/src/main/java/org/junit/internal/builders/JUnit4Builder.java
index 6a00678..7959e75 100644
--- a/src/main/java/org/junit/internal/builders/JUnit4Builder.java
+++ b/src/main/java/org/junit/internal/builders/JUnit4Builder.java
@@ -1,12 +1,12 @@
 package org.junit.internal.builders;
 
 import org.junit.runner.Runner;
-import org.junit.runners.BlockJUnit4ClassRunner;
+import org.junit.runners.JUnit4;
 import org.junit.runners.model.RunnerBuilder;
 
 public class JUnit4Builder extends RunnerBuilder {
     @Override
     public Runner runnerForClass(Class<?> testClass) throws Throwable {
-        return new BlockJUnit4ClassRunner(testClass);
+        return new JUnit4(testClass);
     }
-}
\ No newline at end of file
+}
diff --git a/src/main/java/org/junit/internal/management/FakeRuntimeMXBean.java b/src/main/java/org/junit/internal/management/FakeRuntimeMXBean.java
new file mode 100644
index 0000000..477b150
--- /dev/null
+++ b/src/main/java/org/junit/internal/management/FakeRuntimeMXBean.java
@@ -0,0 +1,21 @@
+package org.junit.internal.management;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * No-op implementation of RuntimeMXBean when the platform doesn't provide it.
+ */
+class FakeRuntimeMXBean implements RuntimeMXBean {
+
+  /**
+   * {@inheritDoc}
+   *
+   * <p>Always returns an empty list.
+   */
+  public List<String> getInputArguments() {
+    return Collections.emptyList();
+  }
+
+}
+
diff --git a/src/main/java/org/junit/internal/management/FakeThreadMXBean.java b/src/main/java/org/junit/internal/management/FakeThreadMXBean.java
new file mode 100644
index 0000000..893f2e3
--- /dev/null
+++ b/src/main/java/org/junit/internal/management/FakeThreadMXBean.java
@@ -0,0 +1,27 @@
+package org.junit.internal.management;
+
+/**
+ * No-op implementation of ThreadMXBean when the platform doesn't provide it.
+ */
+final class FakeThreadMXBean implements ThreadMXBean {
+
+  /**
+   * {@inheritDoc}
+   *
+   * <p>Always throws an {@link UnsupportedOperationException}
+   */
+  public long getThreadCpuTime(long id) {
+    throw new UnsupportedOperationException();
+  }
+
+  /**
+   * {@inheritDoc}
+   *
+   * <p>Always returns false.
+   */
+  public boolean isThreadCpuTimeSupported() {
+    return false;
+  }
+
+}
+
diff --git a/src/main/java/org/junit/internal/management/ManagementFactory.java b/src/main/java/org/junit/internal/management/ManagementFactory.java
new file mode 100644
index 0000000..5be1447
--- /dev/null
+++ b/src/main/java/org/junit/internal/management/ManagementFactory.java
@@ -0,0 +1,77 @@
+package org.junit.internal.management;
+
+import org.junit.internal.Classes;
+
+import java.lang.reflect.InvocationTargetException;
+
+/**
+ * Reflective wrapper around {@link java.lang.management.ManagementFactory}
+ */
+public class ManagementFactory {
+  private static final class FactoryHolder {
+    private static final Class<?> MANAGEMENT_FACTORY_CLASS;
+
+    static {
+      Class<?> managementFactoryClass = null;
+      try {
+        managementFactoryClass = Classes.getClass("java.lang.management.ManagementFactory");
+      } catch (ClassNotFoundException e) {
+        // do nothing, managementFactoryClass will be none on failure
+      }
+      MANAGEMENT_FACTORY_CLASS = managementFactoryClass;
+    }
+
+    static Object getBeanObject(String methodName) {
+      if (MANAGEMENT_FACTORY_CLASS != null) {
+        try {
+          return MANAGEMENT_FACTORY_CLASS.getMethod(methodName).invoke(null);
+        } catch (IllegalAccessException e) {
+          // fallthrough
+        } catch (IllegalArgumentException e) {
+          // fallthrough
+        } catch (InvocationTargetException e) {
+          // fallthrough
+        } catch (NoSuchMethodException e) {
+          // fallthrough
+        } catch (SecurityException e) {
+          // fallthrough
+        }
+      }
+      return null;
+    }
+  }
+
+  private static final class RuntimeHolder {
+    private static final RuntimeMXBean RUNTIME_MX_BEAN =
+        getBean(FactoryHolder.getBeanObject("getRuntimeMXBean"));
+
+    private static final RuntimeMXBean getBean(Object runtimeMxBean) {
+      return runtimeMxBean != null
+          ? new ReflectiveRuntimeMXBean(runtimeMxBean) : new FakeRuntimeMXBean();
+    }
+  }
+
+  private static final class ThreadHolder {
+    private static final ThreadMXBean THREAD_MX_BEAN =
+        getBean(FactoryHolder.getBeanObject("getThreadMXBean"));
+
+    private static final ThreadMXBean getBean(Object threadMxBean) {
+      return threadMxBean != null
+          ? new ReflectiveThreadMXBean(threadMxBean) : new FakeThreadMXBean();
+    }
+  }
+
+  /**
+   * @see java.lang.management.ManagementFactory#getRuntimeMXBean()
+   */
+  public static RuntimeMXBean getRuntimeMXBean() {
+    return RuntimeHolder.RUNTIME_MX_BEAN;
+  }
+
+  /**
+   * @see java.lang.management.ManagementFactory#getThreadMXBean()
+   */
+  public static ThreadMXBean getThreadMXBean() {
+    return ThreadHolder.THREAD_MX_BEAN;
+  }
+}
diff --git a/src/main/java/org/junit/internal/management/ReflectiveRuntimeMXBean.java b/src/main/java/org/junit/internal/management/ReflectiveRuntimeMXBean.java
new file mode 100644
index 0000000..289587a
--- /dev/null
+++ b/src/main/java/org/junit/internal/management/ReflectiveRuntimeMXBean.java
@@ -0,0 +1,61 @@
+package org.junit.internal.management;
+
+import org.junit.internal.Classes;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Implementation of {@link RuntimeMXBean} using the JVM reflectively.
+ */
+final class ReflectiveRuntimeMXBean implements RuntimeMXBean {
+  private final Object runtimeMxBean;
+
+  private static final class Holder {
+    private static final Method getInputArgumentsMethod;
+    static {
+      Method inputArguments = null;
+      try {
+        Class<?> threadMXBeanClass = Classes.getClass("java.lang.management.RuntimeMXBean");
+        inputArguments = threadMXBeanClass.getMethod("getInputArguments");
+      } catch (ClassNotFoundException e) {
+        // do nothing, input arguments will be null on failure
+      } catch (NoSuchMethodException e) {
+        // do nothing, input arguments will be null on failure
+      } catch (SecurityException e) {
+        // do nothing, input arguments will be null on failure
+      }
+      getInputArgumentsMethod = inputArguments;
+    }
+  }
+
+  ReflectiveRuntimeMXBean(Object runtimeMxBean) {
+    super();
+    this.runtimeMxBean = runtimeMxBean;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @SuppressWarnings("unchecked")
+  public List<String> getInputArguments() {
+    if (Holder.getInputArgumentsMethod != null) {
+      try {
+        return (List<String>) Holder.getInputArgumentsMethod.invoke(runtimeMxBean);
+      } catch (ClassCastException e) { // no multi-catch with source level 6
+        // fallthrough
+      } catch (IllegalAccessException e) {
+        // fallthrough
+      } catch (IllegalArgumentException e) {
+        // fallthrough
+      } catch (InvocationTargetException e) {
+        // fallthrough
+      }
+    }
+    return Collections.emptyList();
+  }
+
+}
+
diff --git a/src/main/java/org/junit/internal/management/ReflectiveThreadMXBean.java b/src/main/java/org/junit/internal/management/ReflectiveThreadMXBean.java
new file mode 100644
index 0000000..bc741be
--- /dev/null
+++ b/src/main/java/org/junit/internal/management/ReflectiveThreadMXBean.java
@@ -0,0 +1,92 @@
+package org.junit.internal.management;
+
+import org.junit.internal.Classes;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+/**
+ * Implementation of {@link ThreadMXBean} using the JVM reflectively.
+ */
+final class ReflectiveThreadMXBean implements ThreadMXBean {
+  private final Object threadMxBean;
+
+
+  private static final class Holder {
+    static final Method getThreadCpuTimeMethod;
+    static final Method isThreadCpuTimeSupportedMethod;
+
+    private static final String FAILURE_MESSAGE = "Unable to access ThreadMXBean";
+
+    static {
+      Method threadCpuTime = null;
+      Method threadCpuTimeSupported = null;
+      try {
+        Class<?> threadMXBeanClass = Classes.getClass("java.lang.management.ThreadMXBean");
+        threadCpuTime = threadMXBeanClass.getMethod("getThreadCpuTime", long.class);
+        threadCpuTimeSupported = threadMXBeanClass.getMethod("isThreadCpuTimeSupported");
+      } catch (ClassNotFoundException e) {
+        // do nothing, the methods will be null on failure
+      } catch (NoSuchMethodException e) {
+        // do nothing, the methods will be null on failure
+      } catch (SecurityException e) {
+        // do nothing, the methods will be null on failure
+      }
+      getThreadCpuTimeMethod = threadCpuTime;
+      isThreadCpuTimeSupportedMethod = threadCpuTimeSupported;
+    }
+  }
+
+  ReflectiveThreadMXBean(Object threadMxBean) {
+    super();
+    this.threadMxBean = threadMxBean;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  public long getThreadCpuTime(long id) {
+    if (Holder.getThreadCpuTimeMethod != null) {
+      Exception error = null;
+      try {
+        return (Long) Holder.getThreadCpuTimeMethod.invoke(threadMxBean, id);
+      } catch (ClassCastException e) {
+        error = e;
+        // fallthrough
+      } catch (IllegalAccessException e) {
+        error = e;
+        // fallthrough
+      } catch (IllegalArgumentException e) {
+        error = e;
+        // fallthrough
+      } catch (InvocationTargetException e) {
+        error = e;
+        // fallthrough
+      }
+      throw new UnsupportedOperationException(Holder.FAILURE_MESSAGE, error);
+    }
+    throw new UnsupportedOperationException(Holder.FAILURE_MESSAGE);
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  public boolean isThreadCpuTimeSupported() {
+    if (Holder.isThreadCpuTimeSupportedMethod != null) {
+      try {
+        return (Boolean) Holder.isThreadCpuTimeSupportedMethod.invoke(threadMxBean);
+      } catch (ClassCastException e) {
+        // fallthrough
+      } catch (IllegalAccessException e) {
+        // fallthrough
+      } catch (IllegalArgumentException e) {
+        // fallthrough
+      } catch (InvocationTargetException e) {
+        // fallthrough
+      }
+    }
+    return false;
+  }
+
+}
+
diff --git a/src/main/java/org/junit/internal/management/RuntimeMXBean.java b/src/main/java/org/junit/internal/management/RuntimeMXBean.java
new file mode 100644
index 0000000..84f8861
--- /dev/null
+++ b/src/main/java/org/junit/internal/management/RuntimeMXBean.java
@@ -0,0 +1,14 @@
+package org.junit.internal.management;
+
+import java.util.List;
+
+/**
+ * Wrapper for {@link java.lang.management.RuntimeMXBean}.
+ */
+public interface RuntimeMXBean {
+
+  /**
+   * @see java.lang.management.RuntimeMXBean#getInputArguments()
+   */
+  List<String> getInputArguments();
+}
diff --git a/src/main/java/org/junit/internal/management/ThreadMXBean.java b/src/main/java/org/junit/internal/management/ThreadMXBean.java
new file mode 100644
index 0000000..f9225c9
--- /dev/null
+++ b/src/main/java/org/junit/internal/management/ThreadMXBean.java
@@ -0,0 +1,17 @@
+package org.junit.internal.management;
+
+/**
+ * Wrapper for {@link java.lang.management.ThreadMXBean}.
+ */
+public interface ThreadMXBean {
+  /**
+   * @see java.lang.management.ThreadMXBean#getThreadCpuTime(long)
+   */
+  long getThreadCpuTime(long id);
+
+  /**
+   * @see java.lang.management.ThreadMXBean#isThreadCpuTimeSupported()
+   */
+  boolean isThreadCpuTimeSupported();
+}
+
diff --git a/src/main/java/org/junit/internal/matchers/StacktracePrintingMatcher.java b/src/main/java/org/junit/internal/matchers/StacktracePrintingMatcher.java
index 5d45ba3..93a6827 100644
--- a/src/main/java/org/junit/internal/matchers/StacktracePrintingMatcher.java
+++ b/src/main/java/org/junit/internal/matchers/StacktracePrintingMatcher.java
@@ -1,12 +1,11 @@
 package org.junit.internal.matchers;
 
-import java.io.PrintWriter;
-import java.io.StringWriter;
-
 import org.hamcrest.Description;
 import org.hamcrest.Factory;
 import org.hamcrest.Matcher;
 
+import org.junit.internal.Throwables;
+
 /**
  * A matcher that delegates to throwableMatcher and in addition appends the
  * stacktrace of the actual Throwable in case of a mismatch.
@@ -37,9 +36,7 @@
     }
 
     private String readStacktrace(Throwable throwable) {
-        StringWriter stringWriter = new StringWriter();
-        throwable.printStackTrace(new PrintWriter(stringWriter));
-        return stringWriter.toString();
+        return Throwables.getStacktrace(throwable);
     }
 
     @Factory
diff --git a/src/main/java/org/junit/internal/matchers/ThrowableCauseMatcher.java b/src/main/java/org/junit/internal/matchers/ThrowableCauseMatcher.java
index 22ce8bd..6e2ff5e 100644
--- a/src/main/java/org/junit/internal/matchers/ThrowableCauseMatcher.java
+++ b/src/main/java/org/junit/internal/matchers/ThrowableCauseMatcher.java
@@ -14,9 +14,9 @@
 public class ThrowableCauseMatcher<T extends Throwable> extends
         TypeSafeMatcher<T> {
 
-    private final Matcher<? extends Throwable> causeMatcher;
+    private final Matcher<?> causeMatcher;
 
-    public ThrowableCauseMatcher(Matcher<? extends Throwable> causeMatcher) {
+    public ThrowableCauseMatcher(Matcher<?> causeMatcher) {
         this.causeMatcher = causeMatcher;
     }
 
@@ -44,7 +44,7 @@
      * @param <T> type of the outer exception
      */
     @Factory
-    public static <T extends Throwable> Matcher<T> hasCause(final Matcher<? extends Throwable> matcher) {
+    public static <T extends Throwable> Matcher<T> hasCause(final Matcher<?> matcher) {
         return new ThrowableCauseMatcher<T>(matcher);
     }
 }
\ No newline at end of file
diff --git a/src/main/java/org/junit/internal/matchers/TypeSafeMatcher.java b/src/main/java/org/junit/internal/matchers/TypeSafeMatcher.java
index 4e2cc12..fb25982 100644
--- a/src/main/java/org/junit/internal/matchers/TypeSafeMatcher.java
+++ b/src/main/java/org/junit/internal/matchers/TypeSafeMatcher.java
@@ -40,7 +40,7 @@
     }
 
     private static boolean isMatchesSafelyMethod(Method method) {
-        return method.getName().equals("matchesSafely")
+        return "matchesSafely".equals(method.getName())
                 && method.getParameterTypes().length == 1
                 && !method.isSynthetic();
     }
diff --git a/src/main/java/org/junit/internal/requests/ClassRequest.java b/src/main/java/org/junit/internal/requests/ClassRequest.java
index 3d6b100..d60e360 100644
--- a/src/main/java/org/junit/internal/requests/ClassRequest.java
+++ b/src/main/java/org/junit/internal/requests/ClassRequest.java
@@ -1,20 +1,18 @@
 package org.junit.internal.requests;
 
 import org.junit.internal.builders.AllDefaultPossibilitiesBuilder;
-import org.junit.runner.Request;
+import org.junit.internal.builders.SuiteMethodBuilder;
 import org.junit.runner.Runner;
+import org.junit.runners.model.RunnerBuilder;
 
-public class ClassRequest extends Request {
-    private final Object runnerLock = new Object();
-
+public class ClassRequest extends MemoizingRequest {
     /*
      * We have to use the f prefix, because IntelliJ's JUnit4IdeaTestRunner uses
      * reflection to access this field. See
-     * https://github.com/junit-team/junit/issues/960
+     * https://github.com/junit-team/junit4/issues/960
      */
     private final Class<?> fTestClass;
     private final boolean canUseSuiteMethod;
-    private volatile Runner runner;
 
     public ClassRequest(Class<?> testClass, boolean canUseSuiteMethod) {
         this.fTestClass = testClass;
@@ -26,14 +24,31 @@
     }
 
     @Override
-    public Runner getRunner() {
-        if (runner == null) {
-            synchronized (runnerLock) {
-                if (runner == null) {
-                    runner = new AllDefaultPossibilitiesBuilder(canUseSuiteMethod).safeRunnerForClass(fTestClass);
-                }
-            }
+    protected Runner createRunner() {
+        return new CustomAllDefaultPossibilitiesBuilder().safeRunnerForClass(fTestClass);
+    }
+
+    private class CustomAllDefaultPossibilitiesBuilder extends AllDefaultPossibilitiesBuilder {
+
+        @Override
+        protected RunnerBuilder suiteMethodBuilder() {
+            return new CustomSuiteMethodBuilder();
         }
-        return runner;
+    }
+
+    /*
+     * Customization of {@link SuiteMethodBuilder} that prevents use of the
+     * suite method when creating a runner for fTestClass when canUseSuiteMethod
+     * is false.
+     */
+    private class CustomSuiteMethodBuilder extends SuiteMethodBuilder {
+
+        @Override
+        public Runner runnerForClass(Class<?> testClass) throws Throwable {
+            if (testClass == fTestClass && !canUseSuiteMethod) {
+                return null;
+            }
+            return super.runnerForClass(testClass);
+        }
     }
 }
\ No newline at end of file
diff --git a/src/main/java/org/junit/internal/requests/FilterRequest.java b/src/main/java/org/junit/internal/requests/FilterRequest.java
index 066cba3..5f00399 100644
--- a/src/main/java/org/junit/internal/requests/FilterRequest.java
+++ b/src/main/java/org/junit/internal/requests/FilterRequest.java
@@ -14,7 +14,7 @@
     /*
      * We have to use the f prefix, because IntelliJ's JUnit4IdeaTestRunner uses
      * reflection to access this field. See
-     * https://github.com/junit-team/junit/issues/960
+     * https://github.com/junit-team/junit4/issues/960
      */
     private final Filter fFilter;
 
diff --git a/src/main/java/org/junit/internal/requests/MemoizingRequest.java b/src/main/java/org/junit/internal/requests/MemoizingRequest.java
new file mode 100644
index 0000000..191c230
--- /dev/null
+++ b/src/main/java/org/junit/internal/requests/MemoizingRequest.java
@@ -0,0 +1,30 @@
+package org.junit.internal.requests;
+
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+
+import org.junit.runner.Request;
+import org.junit.runner.Runner;
+
+abstract class MemoizingRequest extends Request {
+    private final Lock runnerLock = new ReentrantLock();
+    private volatile Runner runner;
+
+    @Override
+    public final Runner getRunner() {
+        if (runner == null) {
+            runnerLock.lock();
+            try {
+                if (runner == null) {
+                    runner = createRunner();
+                }
+            } finally {
+                runnerLock.unlock();
+            }
+        }
+        return runner;
+    }
+
+    /** Creates the {@link Runner} to return from {@link #getRunner()}. Called at most once. */
+    protected abstract Runner createRunner();
+}
diff --git a/src/main/java/org/junit/internal/requests/OrderingRequest.java b/src/main/java/org/junit/internal/requests/OrderingRequest.java
new file mode 100644
index 0000000..441e595
--- /dev/null
+++ b/src/main/java/org/junit/internal/requests/OrderingRequest.java
@@ -0,0 +1,29 @@
+package org.junit.internal.requests;
+
+import org.junit.internal.runners.ErrorReportingRunner;
+import org.junit.runner.Request;
+import org.junit.runner.Runner;
+import org.junit.runner.manipulation.InvalidOrderingException;
+import org.junit.runner.manipulation.Ordering;
+
+/** @since 4.13 */
+public class OrderingRequest extends MemoizingRequest {
+    private final Request request;
+    private final Ordering ordering;
+
+    public OrderingRequest(Request request, Ordering ordering) {
+        this.request = request;
+        this.ordering = ordering;
+    }
+
+    @Override
+    protected Runner createRunner() {
+        Runner runner = request.getRunner();
+        try {
+            ordering.apply(runner);
+        } catch (InvalidOrderingException e) {
+            return new ErrorReportingRunner(ordering.getClass(), e);
+        }
+        return runner;
+    }
+}
diff --git a/src/main/java/org/junit/internal/runners/ErrorReportingRunner.java b/src/main/java/org/junit/internal/runners/ErrorReportingRunner.java
index 1d32beb..f52abab 100644
--- a/src/main/java/org/junit/internal/runners/ErrorReportingRunner.java
+++ b/src/main/java/org/junit/internal/runners/ErrorReportingRunner.java
@@ -1,33 +1,44 @@
 package org.junit.internal.runners;
 
 import java.lang.reflect.InvocationTargetException;
-import java.util.Arrays;
 import java.util.List;
 
 import org.junit.runner.Description;
 import org.junit.runner.Runner;
 import org.junit.runner.notification.Failure;
 import org.junit.runner.notification.RunNotifier;
+import org.junit.runners.model.InvalidTestClassError;
 import org.junit.runners.model.InitializationError;
 
+import static java.util.Collections.singletonList;
+
 public class ErrorReportingRunner extends Runner {
     private final List<Throwable> causes;
 
-    private final Class<?> testClass;
+    private final String classNames;
 
     public ErrorReportingRunner(Class<?> testClass, Throwable cause) {
-        if (testClass == null) {
-            throw new NullPointerException("Test class cannot be null");
+        this(cause, testClass);
+    }
+    
+    public ErrorReportingRunner(Throwable cause, Class<?>... testClasses) {
+        if (testClasses == null || testClasses.length == 0) {
+            throw new NullPointerException("Test classes cannot be null or empty");
         }
-        this.testClass = testClass;
+        for (Class<?> testClass : testClasses) {
+            if (testClass == null) {
+                throw new NullPointerException("Test class cannot be null");
+            }
+        }
+        classNames = getClassNames(testClasses);
         causes = getCauses(cause);
     }
-
+    
     @Override
     public Description getDescription() {
-        Description description = Description.createSuiteDescription(testClass);
+        Description description = Description.createSuiteDescription(classNames);
         for (Throwable each : causes) {
-            description.addChild(describeCause(each));
+            description.addChild(describeCause());
         }
         return description;
     }
@@ -39,11 +50,25 @@
         }
     }
 
+    private String getClassNames(Class<?>... testClasses) {
+        final StringBuilder builder = new StringBuilder();
+        for (Class<?> testClass : testClasses) {
+            if (builder.length() != 0) {
+                builder.append(", ");
+            }
+            builder.append(testClass.getName());
+        }
+        return builder.toString();
+    }
+
     @SuppressWarnings("deprecation")
     private List<Throwable> getCauses(Throwable cause) {
         if (cause instanceof InvocationTargetException) {
             return getCauses(cause.getCause());
         }
+        if (cause instanceof InvalidTestClassError) {
+            return singletonList(cause);
+        }
         if (cause instanceof InitializationError) {
             return ((InitializationError) cause).getCauses();
         }
@@ -51,16 +76,15 @@
             return ((org.junit.internal.runners.InitializationError) cause)
                     .getCauses();
         }
-        return Arrays.asList(cause);
+        return singletonList(cause);
     }
 
-    private Description describeCause(Throwable child) {
-        return Description.createTestDescription(testClass,
-                "initializationError");
+    private Description describeCause() {
+        return Description.createTestDescription(classNames, "initializationError");
     }
 
     private void runCause(Throwable child, RunNotifier notifier) {
-        Description description = describeCause(child);
+        Description description = describeCause();
         notifier.fireTestStarted(description);
         notifier.fireTestFailure(new Failure(description, child));
         notifier.fireTestFinished(description);
diff --git a/src/main/java/org/junit/internal/runners/InitializationError.java b/src/main/java/org/junit/internal/runners/InitializationError.java
index 52065ec..484f58d 100644
--- a/src/main/java/org/junit/internal/runners/InitializationError.java
+++ b/src/main/java/org/junit/internal/runners/InitializationError.java
@@ -15,7 +15,7 @@
     /*
      * We have to use the f prefix until the next major release to ensure
      * serialization compatibility. 
-     * See https://github.com/junit-team/junit/issues/976
+     * See https://github.com/junit-team/junit4/issues/976
      */
     private final List<Throwable> fErrors;
 
diff --git a/src/main/java/org/junit/internal/runners/JUnit38ClassRunner.java b/src/main/java/org/junit/internal/runners/JUnit38ClassRunner.java
index 631fcf2..0d51541 100644
--- a/src/main/java/org/junit/internal/runners/JUnit38ClassRunner.java
+++ b/src/main/java/org/junit/internal/runners/JUnit38ClassRunner.java
@@ -1,5 +1,8 @@
 package org.junit.internal.runners;
 
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
+
 import junit.extensions.TestDecorator;
 import junit.framework.AssertionFailedError;
 import junit.framework.Test;
@@ -12,15 +15,16 @@
 import org.junit.runner.Runner;
 import org.junit.runner.manipulation.Filter;
 import org.junit.runner.manipulation.Filterable;
+import org.junit.runner.manipulation.Orderer;
+import org.junit.runner.manipulation.InvalidOrderingException;
 import org.junit.runner.manipulation.NoTestsRemainException;
+import org.junit.runner.manipulation.Orderable;
 import org.junit.runner.manipulation.Sortable;
 import org.junit.runner.manipulation.Sorter;
 import org.junit.runner.notification.Failure;
 import org.junit.runner.notification.RunNotifier;
-import java.lang.annotation.Annotation;
-import java.lang.reflect.Method;
 
-public class JUnit38ClassRunner extends Runner implements Filterable, Sortable {
+public class JUnit38ClassRunner extends Runner implements Filterable, Orderable {
     private static final class OldTestClassAdaptingListener implements
             TestListener {
         private final RunNotifier notifier;
@@ -170,6 +174,18 @@
         }
     }
 
+    /**
+     * {@inheritDoc}
+     *
+     * @since 4.13
+     */
+    public void order(Orderer orderer) throws InvalidOrderingException {
+        if (getTest() instanceof Orderable) {
+            Orderable adapter = (Orderable) getTest();
+            adapter.order(orderer);
+        }
+    }
+
     private void setTest(Test test) {
         this.test = test;
     }
diff --git a/src/main/java/org/junit/internal/runners/MethodValidator.java b/src/main/java/org/junit/internal/runners/MethodValidator.java
index ba9c9d1..e656ee5 100644
--- a/src/main/java/org/junit/internal/runners/MethodValidator.java
+++ b/src/main/java/org/junit/internal/runners/MethodValidator.java
@@ -86,7 +86,7 @@
             }
             if (each.getReturnType() != Void.TYPE) {
                 errors.add(new Exception("Method " + each.getName()
-						+ " should be void"));
+						+ "should have a return type of void"));
             }
             if (each.getParameterTypes().length != 0) {
                 errors.add(new Exception("Method " + each.getName()
diff --git a/src/main/java/org/junit/internal/runners/TestClass.java b/src/main/java/org/junit/internal/runners/TestClass.java
index 1abaeea..6d24f4f 100644
--- a/src/main/java/org/junit/internal/runners/TestClass.java
+++ b/src/main/java/org/junit/internal/runners/TestClass.java
@@ -85,7 +85,7 @@
     }
 
     private List<Class<?>> getSuperClasses(Class<?> testClass) {
-        ArrayList<Class<?>> results = new ArrayList<Class<?>>();
+        List<Class<?>> results = new ArrayList<Class<?>>();
         Class<?> current = testClass;
         while (current != null) {
             results.add(current);
diff --git a/src/main/java/org/junit/internal/runners/model/EachTestNotifier.java b/src/main/java/org/junit/internal/runners/model/EachTestNotifier.java
index e094809..c5a0764 100644
--- a/src/main/java/org/junit/internal/runners/model/EachTestNotifier.java
+++ b/src/main/java/org/junit/internal/runners/model/EachTestNotifier.java
@@ -45,4 +45,27 @@
     public void fireTestIgnored() {
         notifier.fireTestIgnored(description);
     }
+
+    /**
+     * Calls {@link RunNotifier#fireTestSuiteStarted(Description)}, passing the
+     * {@link Description} that was passed to the {@code EachTestNotifier} constructor.
+     * This should be called when a test suite is about to be started.
+     * @see RunNotifier#fireTestSuiteStarted(Description)
+     * @since 4.13
+     */
+    public void fireTestSuiteStarted() {
+        notifier.fireTestSuiteStarted(description);
+    }
+
+    /**
+     * Calls {@link RunNotifier#fireTestSuiteFinished(Description)}, passing the
+     * {@link Description} that was passed to the {@code EachTestNotifier} constructor.
+     * This should be called when a test suite has finished, whether the test suite succeeds
+     * or fails.
+     * @see RunNotifier#fireTestSuiteFinished(Description)
+     * @since 4.13
+     */
+    public void fireTestSuiteFinished() {
+        notifier.fireTestSuiteFinished(description);
+    }
 }
\ No newline at end of file
diff --git a/src/main/java/org/junit/internal/runners/rules/ValidationError.java b/src/main/java/org/junit/internal/runners/rules/ValidationError.java
index d1af8ae..31bd660 100644
--- a/src/main/java/org/junit/internal/runners/rules/ValidationError.java
+++ b/src/main/java/org/junit/internal/runners/rules/ValidationError.java
@@ -5,6 +5,9 @@
 import java.lang.annotation.Annotation;
 
 class ValidationError extends Exception {
+
+    private static final long serialVersionUID = 3176511008672645574L;
+
     public ValidationError(FrameworkMember<?> member, Class<? extends Annotation> annotation, String suffix) {
         super(String.format("The @%s '%s' %s", annotation.getSimpleName(), member.getName(), suffix));
     }
diff --git a/src/main/java/org/junit/internal/runners/statements/ExpectException.java b/src/main/java/org/junit/internal/runners/statements/ExpectException.java
index d0636bd..9a2a952 100644
--- a/src/main/java/org/junit/internal/runners/statements/ExpectException.java
+++ b/src/main/java/org/junit/internal/runners/statements/ExpectException.java
@@ -19,7 +19,9 @@
             next.evaluate();
             complete = true;
         } catch (AssumptionViolatedException e) {
-            throw e;
+            if (!expected.isAssignableFrom(e.getClass())) {
+                throw e;
+            }
         } catch (Throwable e) {
             if (!expected.isAssignableFrom(e.getClass())) {
                 String message = "Unexpected exception, expected<"
diff --git a/src/main/java/org/junit/internal/runners/statements/RunAfters.java b/src/main/java/org/junit/internal/runners/statements/RunAfters.java
index 7512a7d..5e56c33 100644
--- a/src/main/java/org/junit/internal/runners/statements/RunAfters.java
+++ b/src/main/java/org/junit/internal/runners/statements/RunAfters.java
@@ -30,7 +30,7 @@
         } finally {
             for (FrameworkMethod each : afters) {
                 try {
-                    each.invokeExplosively(target);
+                    invokeMethod(each);
                 } catch (Throwable e) {
                     errors.add(e);
                 }
@@ -38,4 +38,11 @@
         }
         MultipleFailureException.assertEmpty(errors);
     }
+
+    /**
+     * @since 4.13
+     */
+    protected void invokeMethod(FrameworkMethod method) throws Throwable {
+        method.invokeExplosively(target);
+    }
 }
\ No newline at end of file
diff --git a/src/main/java/org/junit/internal/runners/statements/RunBefores.java b/src/main/java/org/junit/internal/runners/statements/RunBefores.java
index 238fbe7..bd835c7 100644
--- a/src/main/java/org/junit/internal/runners/statements/RunBefores.java
+++ b/src/main/java/org/junit/internal/runners/statements/RunBefores.java
@@ -21,8 +21,15 @@
     @Override
     public void evaluate() throws Throwable {
         for (FrameworkMethod before : befores) {
-            before.invokeExplosively(target);
+            invokeMethod(before);
         }
         next.evaluate();
     }
+
+    /**
+     * @since 4.13
+     */
+    protected void invokeMethod(FrameworkMethod method) throws Throwable {
+        method.invokeExplosively(target);
+    }
 }
\ No newline at end of file
diff --git a/src/main/java/org/junit/matchers/JUnitMatchers.java b/src/main/java/org/junit/matchers/JUnitMatchers.java
index 5bb48d7..37e3d68 100644
--- a/src/main/java/org/junit/matchers/JUnitMatchers.java
+++ b/src/main/java/org/junit/matchers/JUnitMatchers.java
@@ -57,7 +57,7 @@
      */
     @Deprecated
     public static <T> Matcher<Iterable<T>> everyItem(final Matcher<T> elementMatcher) {
-        return CoreMatchers.everyItem((Matcher) elementMatcher);
+      return CoreMatchers.everyItem((Matcher) elementMatcher);
     }
 
     /**
diff --git a/src/main/java/org/junit/rules/ErrorCollector.java b/src/main/java/org/junit/rules/ErrorCollector.java
index 8c6600e..18d94b8 100644
--- a/src/main/java/org/junit/rules/ErrorCollector.java
+++ b/src/main/java/org/junit/rules/ErrorCollector.java
@@ -1,11 +1,14 @@
 package org.junit.rules;
 
 import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertThrows;
 
 import java.util.ArrayList;
 import java.util.List;
 import java.util.concurrent.Callable;
 
+import org.junit.function.ThrowingRunnable;
+import org.junit.internal.AssumptionViolatedException;
 import org.hamcrest.Matcher;
 import org.junit.runners.model.MultipleFailureException;
 
@@ -43,6 +46,21 @@
      * Adds a Throwable to the table.  Execution continues, but the test will fail at the end.
      */
     public void addError(Throwable error) {
+        if (error == null) {
+            throw new NullPointerException("Error cannot be null");
+        }
+        // BEGIN Android-changed: Don't convert assumption failures to errors. b/181123057
+        // Submitted upstream: https://github.com/junit-team/junit4/issues/1703
+        /*
+        if (error instanceof AssumptionViolatedException) {
+            AssertionError e = new AssertionError(error.getMessage());
+            e.initCause(error);
+            errors.add(e);
+        } else {
+            errors.add(error);
+        }
+        */
+        // END Android-changed: Don't convert assumption failures to errors. b/181123057
         errors.add(error);
     }
 
@@ -76,9 +94,33 @@
     public <T> T checkSucceeds(Callable<T> callable) {
         try {
             return callable.call();
+        } catch (AssumptionViolatedException e) {
+            AssertionError error = new AssertionError("Callable threw AssumptionViolatedException");
+            error.initCause(e);
+            addError(error);
+            return null;
         } catch (Throwable e) {
             addError(e);
             return null;
         }
     }
+
+    /**
+     * Adds a failure to the table if {@code runnable} does not throw an
+     * exception of type {@code expectedThrowable} when executed.
+     * Execution continues, but the test will fail at the end if the runnable
+     * does not throw an exception, or if it throws a different exception.
+     *
+     * @param expectedThrowable the expected type of the exception
+     * @param runnable       a function that is expected to throw an exception when executed
+     * @since 4.13
+     */
+    public void checkThrows(Class<? extends Throwable> expectedThrowable, ThrowingRunnable runnable) {
+        try {
+            assertThrows(expectedThrowable, runnable);
+        } catch (AssertionError e) {
+            addError(e);
+        }
+    }
+
 }
diff --git a/src/main/java/org/junit/rules/ExpectedException.java b/src/main/java/org/junit/rules/ExpectedException.java
index 4d61712..431ad49 100644
--- a/src/main/java/org/junit/rules/ExpectedException.java
+++ b/src/main/java/org/junit/rules/ExpectedException.java
@@ -7,7 +7,6 @@
 import static org.junit.Assert.fail;
 import static org.junit.internal.matchers.ThrowableCauseMatcher.hasCause;
 import static org.junit.internal.matchers.ThrowableMessageMatcher.hasMessage;
-
 import org.hamcrest.Matcher;
 import org.hamcrest.StringDescription;
 import org.junit.AssumptionViolatedException;
@@ -21,7 +20,7 @@
  *
  * <pre> public class SimpleExpectedExceptionTest {
  *     &#064;Rule
- *     public ExpectedException thrown= ExpectedException.none();
+ *     public ExpectedException thrown = ExpectedException.none();
  *
  *     &#064;Test
  *     public void throwsNothing() {
@@ -35,16 +34,19 @@
  *     }
  * }</pre>
  * 
- * <p>
- * You have to add the {@code ExpectedException} rule to your test.
+ * <p>You have to add the {@code ExpectedException} rule to your test.
  * This doesn't affect your existing tests (see {@code throwsNothing()}).
- * After specifiying the type of the expected exception your test is
+ * After specifying the type of the expected exception your test is
  * successful when such an exception is thrown and it fails if a
  * different or no exception is thrown.
  *
- * <p>
- * Instead of specifying the exception's type you can characterize the
- * expected exception based on other criterias, too:
+ * <p>This rule does not perform any special magic to make execution continue
+ * as if the exception had not been thrown. So it is nearly always a mistake
+ * for a test method to have statements after the one that is expected to
+ * throw the exception.
+ *
+ * <p>Instead of specifying the exception's type you can characterize the
+ * expected exception based on other criteria, too:
  *
  * <ul>
  *   <li>The exception's message contains a specific text: {@link #expectMessage(String)}</li>
@@ -53,8 +55,7 @@
  *   <li>The exception itself complies with a Hamcrest matcher: {@link #expect(Matcher)}</li>
  * </ul>
  *
- * <p>
- * You can combine any of the presented expect-methods. The test is
+ * <p>You can combine any of the presented expect-methods. The test is
  * successful if all specifications are met.
  * <pre> &#064;Test
  * public void throwsException() {
@@ -63,9 +64,15 @@
  *     throw new NullPointerException(&quot;What happened?&quot;);
  * }</pre>
  *
+ * <p>It is recommended to set the {@link org.junit.Rule#order() order} of the
+ * {@code ExpectedException} to {@code Integer.MAX_VALUE} if it is used together
+ * with another rule that handles exceptions, e.g. {@link ErrorCollector}.
+ * Otherwise failing tests may be successful.
+ * <pre> &#064;Rule(order = Integer.MAX_VALUE)
+ * public ExpectedException thrown = ExpectedException.none();</pre>
+ *
  * <h3>AssumptionViolatedExceptions</h3>
- * <p>
- * JUnit uses {@link AssumptionViolatedException}s for indicating that a test
+ * <p>JUnit uses {@link AssumptionViolatedException}s for indicating that a test
  * provides no useful information. (See {@link org.junit.Assume} for more
  * information.) You have to call {@code assume} methods before you set
  * expectations of the {@code ExpectedException} rule. In this case the rule
@@ -80,8 +87,7 @@
  *
  * <h3>AssertionErrors</h3>
  *
- * <p>
- * JUnit uses {@link AssertionError}s for indicating that a test is failing. You
+ * <p>JUnit uses {@link AssertionError}s for indicating that a test is failing. You
  * have to call {@code assert} methods before you set expectations of the
  * {@code ExpectedException} rule, if they should be handled by the framework.
  * E.g. the following test fails because of the {@code assertTrue} statement.
@@ -93,8 +99,7 @@
  * }</pre>
  *
  * <h3>Missing Exceptions</h3>
- * <p>
- * By default missing exceptions are reported with an error message
+ * <p>By default missing exceptions are reported with an error message
  * like "Expected test to throw an instance of foo". You can configure a different
  * message by means of {@link #reportMissingExceptionWithMessage(String)}. You
  * can use a {@code %s} placeholder for the description of the expected
@@ -107,7 +112,13 @@
     /**
      * Returns a {@linkplain TestRule rule} that expects no exception to
      * be thrown (identical to behavior without this rule).
+     *
+     * @deprecated Since 4.13
+     * {@link org.junit.Assert#assertThrows(Class, org.junit.function.ThrowingRunnable)
+     * Assert.assertThrows} can be used to verify that your code throws a specific
+     * exception.
      */
+    @Deprecated
     public static ExpectedException none() {
         return new ExpectedException();
     }
@@ -222,10 +233,18 @@
      *     throw new IllegalArgumentException(&quot;What happened?&quot;, cause);
      * }</pre>
      */
-    public void expectCause(Matcher<? extends Throwable> expectedCause) {
+    public void expectCause(Matcher<?> expectedCause) {
         expect(hasCause(expectedCause));
     }
 
+    /**
+     * Check if any Exception is expected.
+     * @since 4.13
+     */
+    public final boolean isAnyExceptionExpected() {
+        return matcherBuilder.expectsThrowable();
+    }
+
     private class ExpectedExceptionStatement extends Statement {
         private final Statement next;
 
@@ -255,10 +274,6 @@
         }
     }
 
-    private boolean isAnyExceptionExpected() {
-        return matcherBuilder.expectsThrowable();
-    }
-
     private void failDueToMissingException() throws AssertionError {
         fail(missingExceptionMessage());
     }
diff --git a/src/main/java/org/junit/rules/ExternalResource.java b/src/main/java/org/junit/rules/ExternalResource.java
index 71ca287..71fc842 100644
--- a/src/main/java/org/junit/rules/ExternalResource.java
+++ b/src/main/java/org/junit/rules/ExternalResource.java
@@ -1,6 +1,10 @@
 package org.junit.rules;
 
+import java.util.ArrayList;
+import java.util.List;
+
 import org.junit.runner.Description;
+import org.junit.runners.model.MultipleFailureException;
 import org.junit.runners.model.Statement;
 
 /**
@@ -44,11 +48,20 @@
             @Override
             public void evaluate() throws Throwable {
                 before();
+
+                List<Throwable> errors = new ArrayList<Throwable>();
                 try {
                     base.evaluate();
+                } catch (Throwable t) {
+                    errors.add(t);
                 } finally {
-                    after();
+                    try {
+                        after();
+                    } catch (Throwable t) {
+                        errors.add(t);
+                    }
                 }
+                MultipleFailureException.assertEmpty(errors);
             }
         };
     }
diff --git a/src/main/java/org/junit/rules/MethodRule.java b/src/main/java/org/junit/rules/MethodRule.java
index 823ee78..94608f5 100644
--- a/src/main/java/org/junit/rules/MethodRule.java
+++ b/src/main/java/org/junit/rules/MethodRule.java
@@ -10,21 +10,9 @@
  * {@link Statement} that executes the method is passed to each annotated
  * {@link Rule} in turn, and each may return a substitute or modified
  * {@link Statement}, which is passed to the next {@link Rule}, if any. For
- * examples of how this can be useful, see these provided MethodRules,
- * or write your own:
+ * an example of how this can be useful, see {@link TestWatchman}.
  *
- * <ul>
- *   <li>{@link ErrorCollector}: collect multiple errors in one test method</li>
- *   <li>{@link ExpectedException}: make flexible assertions about thrown exceptions</li>
- *   <li>{@link ExternalResource}: start and stop a server, for example</li>
- *   <li>{@link TemporaryFolder}: create fresh files, and delete after test</li>
- *   <li>{@link TestName}: remember the test name for use during the method</li>
- *   <li>{@link TestWatchman}: add logic at events during method execution</li>
- *   <li>{@link Timeout}: cause test to fail after a set time</li>
- *   <li>{@link Verifier}: fail test if object state ends up incorrect</li>
- * </ul>
- *
- * Note that {@link MethodRule} has been replaced by {@link TestRule},
+ * <p>Note that {@link MethodRule} has been replaced by {@link TestRule},
  * which has the added benefit of supporting class rules.
  *
  * @since 4.7
diff --git a/src/main/java/org/junit/rules/RuleChain.java b/src/main/java/org/junit/rules/RuleChain.java
index f43d8f5..bf93aae 100644
--- a/src/main/java/org/junit/rules/RuleChain.java
+++ b/src/main/java/org/junit/rules/RuleChain.java
@@ -4,26 +4,34 @@
 import java.util.Collections;
 import java.util.List;
 
+import org.junit.Rule;
 import org.junit.runner.Description;
 import org.junit.runners.model.Statement;
 
 /**
- * The RuleChain rule allows ordering of TestRules. You create a
+ * The {@code RuleChain} can be used for creating composite rules. You create a
  * {@code RuleChain} with {@link #outerRule(TestRule)} and subsequent calls of
  * {@link #around(TestRule)}:
  *
  * <pre>
- * public static class UseRuleChain {
- * 	&#064;Rule
- * 	public RuleChain chain= RuleChain
- * 	                       .outerRule(new LoggingRule("outer rule")
- * 	                       .around(new LoggingRule("middle rule")
- * 	                       .around(new LoggingRule("inner rule");
+ * public abstract class CompositeRules {
+ *   public static TestRule extendedLogging() {
+ *     return RuleChain.outerRule(new LoggingRule("outer rule"))
+ *                     .around(new LoggingRule("middle rule"))
+ *                     .around(new LoggingRule("inner rule"));
+ *   }
+ * }
+ * </pre>
  *
- * 	&#064;Test
- * 	public void example() {
- * 		assertTrue(true);
- *     }
+ * <pre>
+ * public class UseRuleChain {
+ *   &#064;Rule
+ *   public final TestRule extendedLogging = CompositeRules.extendedLogging();
+ *
+ *   &#064;Test
+ *   public void example() {
+ *     assertTrue(true);
+ *   }
  * }
  * </pre>
  *
@@ -38,6 +46,13 @@
  * finished outer rule
  * </pre>
  *
+ * In older versions of JUnit (before 4.13) {@code RuleChain} was used for
+ * ordering rules. We recommend to not use it for this purpose anymore. You can
+ * use the attribute {@code order} of the annotation {@link Rule#order() Rule}
+ * or {@link org.junit.ClassRule#order() ClassRule} for ordering rules.
+ *
+ * @see org.junit.Rule#order()
+ * @see org.junit.ClassRule#order()
  * @since 4.10
  */
 public class RuleChain implements TestRule {
@@ -72,13 +87,17 @@
     }
 
     /**
-     * Create a new {@code RuleChain}, which encloses the {@code nextRule} with
+     * Create a new {@code RuleChain}, which encloses the given {@link TestRule} with
      * the rules of the current {@code RuleChain}.
      *
-     * @param enclosedRule the rule to enclose.
+     * @param enclosedRule the rule to enclose; must not be {@code null}.
      * @return a new {@code RuleChain}.
+     * @throws NullPointerException if the argument {@code enclosedRule} is {@code null}
      */
     public RuleChain around(TestRule enclosedRule) {
+        if (enclosedRule == null) {
+            throw new NullPointerException("The enclosed rule must not be null");
+        }
         List<TestRule> rulesOfNewChain = new ArrayList<TestRule>();
         rulesOfNewChain.add(enclosedRule);
         rulesOfNewChain.addAll(rulesStartingWithInnerMost);
@@ -89,9 +108,6 @@
      * {@inheritDoc}
      */
     public Statement apply(Statement base, Description description) {
-        for (TestRule each : rulesStartingWithInnerMost) {
-            base = each.apply(base, description);
-        }
-        return base;
+        return new RunRules(base, rulesStartingWithInnerMost, description);
     }
 }
\ No newline at end of file
diff --git a/src/main/java/org/junit/rules/Stopwatch.java b/src/main/java/org/junit/rules/Stopwatch.java
index 5d34e7f..6900a48 100644
--- a/src/main/java/org/junit/rules/Stopwatch.java
+++ b/src/main/java/org/junit/rules/Stopwatch.java
@@ -76,7 +76,7 @@
  * @author tibor17
  * @since 4.12
  */
-public abstract class Stopwatch implements TestRule {
+public class Stopwatch implements TestRule {
     private final Clock clock;
     private volatile long startNanos;
     private volatile long endNanos;
diff --git a/src/main/java/org/junit/rules/TemporaryFolder.java b/src/main/java/org/junit/rules/TemporaryFolder.java
index dc75c93..a726c66 100644
--- a/src/main/java/org/junit/rules/TemporaryFolder.java
+++ b/src/main/java/org/junit/rules/TemporaryFolder.java
@@ -1,15 +1,20 @@
 package org.junit.rules;
 
+import static org.junit.Assert.fail;
+
 import java.io.File;
 import java.io.IOException;
+import java.lang.reflect.Array;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
 
 import org.junit.Rule;
 
 /**
  * The TemporaryFolder Rule allows creation of files and folders that should
  * be deleted when the test method finishes (whether it passes or
- * fails). Whether the deletion is successful or not is not checked by this rule.
- * No exception will be thrown in case the deletion fails.
+ * fails).
+ * By default no exception will be thrown in case the deletion fails.
  *
  * <p>Example of usage:
  * <pre>
@@ -26,18 +31,104 @@
  * }
  * </pre>
  *
+ * <p>TemporaryFolder rule supports assured deletion mode, which
+ * will fail the test in case deletion fails with {@link AssertionError}.
+ *
+ * <p>Creating TemporaryFolder with assured deletion:
+ * <pre>
+ *  &#064;Rule
+ *  public TemporaryFolder folder= TemporaryFolder.builder().assureDeletion().build();
+ * </pre>
+ *
  * @since 4.7
  */
 public class TemporaryFolder extends ExternalResource {
     private final File parentFolder;
+    private final boolean assureDeletion;
     private File folder;
 
+    private static final int TEMP_DIR_ATTEMPTS = 10000;
+    private static final String TMP_PREFIX = "junit";
+
+    /**
+     * Create a temporary folder which uses system default temporary-file 
+     * directory to create temporary resources.
+     */
     public TemporaryFolder() {
-        this(null);
+        this((File) null);
     }
 
+    /**
+     * Create a temporary folder which uses the specified directory to create
+     * temporary resources.
+     *
+     * @param parentFolder folder where temporary resources will be created.
+     * If {@code null} then system default temporary-file directory is used.
+     */
     public TemporaryFolder(File parentFolder) {
         this.parentFolder = parentFolder;
+        this.assureDeletion = false;
+    }
+
+    /**
+     * Create a {@link TemporaryFolder} initialized with
+     * values from a builder.
+     */
+    protected TemporaryFolder(Builder builder) {
+        this.parentFolder = builder.parentFolder;
+        this.assureDeletion = builder.assureDeletion;
+    }
+
+    /**
+     * Returns a new builder for building an instance of {@link TemporaryFolder}.
+     *
+     * @since 4.13
+     */
+    public static Builder builder() {
+        return new Builder();
+    }
+
+    /**
+     * Builds an instance of {@link TemporaryFolder}.
+     * 
+     * @since 4.13
+     */
+    public static class Builder {
+        private File parentFolder;
+        private boolean assureDeletion;
+
+        protected Builder() {}
+
+        /**
+         * Specifies which folder to use for creating temporary resources.
+         * If {@code null} then system default temporary-file directory is
+         * used.
+         *
+         * @return this
+         */
+        public Builder parentFolder(File parentFolder) {
+            this.parentFolder = parentFolder;
+            return this;
+        }
+
+        /**
+         * Setting this flag assures that no resources are left undeleted. Failure
+         * to fulfill the assurance results in failure of tests with an
+         * {@link AssertionError}.
+         *
+         * @return this
+         */
+        public Builder assureDeletion() {
+            this.assureDeletion = true;
+            return this;
+        }
+
+        /**
+         * Builds a {@link TemporaryFolder} instance using the values in this builder.
+         */
+        public TemporaryFolder build() {
+            return new TemporaryFolder(this);
+        }
     }
 
     @Override
@@ -75,52 +166,63 @@
      * Returns a new fresh file with a random name under the temporary folder.
      */
     public File newFile() throws IOException {
-        return File.createTempFile("junit", null, getRoot());
+        return File.createTempFile(TMP_PREFIX, null, getRoot());
     }
 
     /**
-     * Returns a new fresh folder with the given name under the temporary
+     * Returns a new fresh folder with the given path under the temporary
      * folder.
      */
-    public File newFolder(String folder) throws IOException {
-        return newFolder(new String[]{folder});
+    public File newFolder(String path) throws IOException {
+        return newFolder(new String[]{path});
     }
 
     /**
-     * Returns a new fresh folder with the given name(s) under the temporary
-     * folder.
+     * Returns a new fresh folder with the given paths under the temporary
+     * folder. For example, if you pass in the strings {@code "parent"} and {@code "child"}
+     * then a directory named {@code "parent"} will be created under the temporary folder
+     * and a directory named {@code "child"} will be created under the newly-created
+     * {@code "parent"} directory.
      */
-    public File newFolder(String... folderNames) throws IOException {
-        File file = getRoot();
-        for (int i = 0; i < folderNames.length; i++) {
-            String folderName = folderNames[i];
-            validateFolderName(folderName);
-            file = new File(file, folderName);
-            if (!file.mkdir() && isLastElementInArray(i, folderNames)) {
-                throw new IOException(
-                        "a folder with the name \'" + folderName + "\' already exists");
+    public File newFolder(String... paths) throws IOException {
+        if (paths.length == 0) {
+            throw new IllegalArgumentException("must pass at least one path");
+        }
+
+        /*
+         * Before checking if the paths are absolute paths, check if create() was ever called,
+         * and if it wasn't, throw IllegalStateException.
+         */
+        File root = getRoot();
+        for (String path : paths) {
+            if (new File(path).isAbsolute()) {
+                throw new IOException("folder path \'" + path + "\' is not a relative path");
             }
         }
-        return file;
-    }
-    
-    /**
-     * Validates if multiple path components were used while creating a folder.
-     * 
-     * @param folderName
-     *            Name of the folder being created
-     */
-    private void validateFolderName(String folderName) throws IOException {
-        File tempFile = new File(folderName);
-        if (tempFile.getParent() != null) {
-            String errorMsg = "Folder name cannot consist of multiple path components separated by a file separator."
-                    + " Please use newFolder('MyParentFolder','MyFolder') to create hierarchies of folders";
-            throw new IOException(errorMsg);
-        }
-    }
 
-    private boolean isLastElementInArray(int index, String[] array) {
-        return index == array.length - 1;
+        File relativePath = null;
+        File file = root;
+        boolean lastMkdirsCallSuccessful = true;
+        for (String path : paths) {
+            relativePath = new File(relativePath, path);
+            file = new File(root, relativePath.getPath());
+
+            lastMkdirsCallSuccessful = file.mkdirs();
+            if (!lastMkdirsCallSuccessful && !file.isDirectory()) {
+                if (file.exists()) {
+                    throw new IOException(
+                            "a file with the path \'" + relativePath.getPath() + "\' exists");
+                } else {
+                    throw new IOException(
+                            "could not create a folder with the path \'" + relativePath.getPath() + "\'");
+                }
+            }
+        }
+        if (!lastMkdirsCallSuccessful) {
+            throw new IOException(
+                    "a folder with the path \'" + relativePath.getPath() + "\' already exists");
+        }
+        return file;
     }
 
     /**
@@ -130,11 +232,63 @@
         return createTemporaryFolderIn(getRoot());
     }
 
-    private File createTemporaryFolderIn(File parentFolder) throws IOException {
-        File createdFolder = File.createTempFile("junit", "", parentFolder);
-        createdFolder.delete();
-        createdFolder.mkdir();
-        return createdFolder;
+    private static File createTemporaryFolderIn(File parentFolder) throws IOException {
+        try {
+            return createTemporaryFolderWithNioApi(parentFolder);
+        } catch (ClassNotFoundException ignore) {
+            // Fallback for Java 5 and 6
+            return createTemporaryFolderWithFileApi(parentFolder);
+        } catch (InvocationTargetException e) {
+            Throwable cause = e.getCause();
+            if (cause instanceof IOException) {
+                throw (IOException) cause;
+            }
+            if (cause instanceof RuntimeException) {
+                throw (RuntimeException) cause;
+            }
+            IOException exception = new IOException("Failed to create temporary folder in " + parentFolder);
+            exception.initCause(cause);
+            throw exception;
+        } catch (Exception e) {
+            throw new RuntimeException("Failed to create temporary folder in " + parentFolder, e);
+        }
+    }
+
+    private static File createTemporaryFolderWithNioApi(File parentFolder) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
+        Class<?> filesClass = Class.forName("java.nio.file.Files");
+        Object fileAttributeArray = Array.newInstance(Class.forName("java.nio.file.attribute.FileAttribute"), 0);
+        Class<?> pathClass = Class.forName("java.nio.file.Path");
+        Object tempDir;
+        if (parentFolder != null) {
+            Method createTempDirectoryMethod = filesClass.getDeclaredMethod("createTempDirectory", pathClass, String.class, fileAttributeArray.getClass());
+            Object parentPath = File.class.getDeclaredMethod("toPath").invoke(parentFolder);
+            tempDir = createTempDirectoryMethod.invoke(null, parentPath, TMP_PREFIX, fileAttributeArray);
+        } else {
+            Method createTempDirectoryMethod = filesClass.getDeclaredMethod("createTempDirectory", String.class, fileAttributeArray.getClass());
+            tempDir = createTempDirectoryMethod.invoke(null, TMP_PREFIX, fileAttributeArray);
+        }
+        return (File) pathClass.getDeclaredMethod("toFile").invoke(tempDir);
+    }
+
+    private static File createTemporaryFolderWithFileApi(File parentFolder) throws IOException {
+        File createdFolder = null;
+        for (int i = 0; i < TEMP_DIR_ATTEMPTS; ++i) {
+            // Use createTempFile to get a suitable folder name.
+            String suffix = ".tmp";
+            File tmpFile = File.createTempFile(TMP_PREFIX, suffix, parentFolder);
+            String tmpName = tmpFile.toString();
+            // Discard .tmp suffix of tmpName.
+            String folderName = tmpName.substring(0, tmpName.length() - suffix.length());
+            createdFolder = new File(folderName);
+            if (createdFolder.mkdir()) {
+                tmpFile.delete();
+                return createdFolder;
+            }
+            tmpFile.delete();
+        }
+        throw new IOException("Unable to create temporary directory in: "
+            + parentFolder.toString() + ". Tried " + TEMP_DIR_ATTEMPTS + " times. "
+            + "Last attempted to create: " + createdFolder.toString());
     }
 
     /**
@@ -150,21 +304,48 @@
 
     /**
      * Delete all files and folders under the temporary folder. Usually not
-     * called directly, since it is automatically applied by the {@link Rule}
+     * called directly, since it is automatically applied by the {@link Rule}.
+     *
+     * @throws AssertionError if unable to clean up resources
+     * and deletion of resources is assured.
      */
     public void delete() {
-        if (folder != null) {
-            recursiveDelete(folder);
+        if (!tryDelete()) {
+            if (assureDeletion) {
+                fail("Unable to clean up temporary folder " + folder);
+            }
         }
     }
 
-    private void recursiveDelete(File file) {
+    /**
+     * Tries to delete all files and folders under the temporary folder and
+     * returns whether deletion was successful or not.
+     *
+     * @return {@code true} if all resources are deleted successfully,
+     *         {@code false} otherwise.
+     */
+    private boolean tryDelete() {
+        if (folder == null) {
+            return true;
+        }
+        
+        return recursiveDelete(folder);
+    }
+
+    private boolean recursiveDelete(File file) {
+        // Try deleting file before assuming file is a directory
+        // to prevent following symbolic links.
+        if (file.delete()) {
+            return true;
+        }
         File[] files = file.listFiles();
         if (files != null) {
             for (File each : files) {
-                recursiveDelete(each);
+                if (!recursiveDelete(each)) {
+                    return false;
+                }
             }
         }
-        file.delete();
+        return file.delete();
     }
 }
diff --git a/src/main/java/org/junit/rules/TestName.java b/src/main/java/org/junit/rules/TestName.java
index bf72602..e2ebc2e 100644
--- a/src/main/java/org/junit/rules/TestName.java
+++ b/src/main/java/org/junit/rules/TestName.java
@@ -25,7 +25,7 @@
  * @since 4.7
  */
 public class TestName extends TestWatcher {
-    private String name;
+    private volatile String name;
 
     @Override
     protected void starting(Description d) {
diff --git a/src/main/java/org/junit/rules/TestWatcher.java b/src/main/java/org/junit/rules/TestWatcher.java
index 5492b6b..a28514d 100644
--- a/src/main/java/org/junit/rules/TestWatcher.java
+++ b/src/main/java/org/junit/rules/TestWatcher.java
@@ -4,6 +4,7 @@
 import java.util.List;
 
 import org.junit.AssumptionViolatedException;
+import org.junit.Rule;
 import org.junit.runner.Description;
 import org.junit.runners.model.MultipleFailureException;
 import org.junit.runners.model.Statement;
@@ -17,7 +18,7 @@
  * public static class WatchmanTest {
  *  private static String watchedLog;
  *
- *  &#064;Rule
+ *  &#064;Rule(order = Integer.MIN_VALUE)
  *  public TestWatcher watchman= new TestWatcher() {
  *      &#064;Override
  *      protected void failed(Throwable e, Description description) {
@@ -40,6 +41,11 @@
  *     }
  * }
  * </pre>
+ * <p>It is recommended to always set the {@link Rule#order() order} of the
+ * {@code TestWatcher} to {@code Integer.MIN_VALUE} so that it encloses all
+ * other rules. Otherwise it may see failed tests as successful and vice versa
+ * if some rule changes the result of a test (e.g. {@link ErrorCollector} or
+ * {@link ExpectedException}).
  *
  * @since 4.9
  */
@@ -54,7 +60,7 @@
                 try {
                     base.evaluate();
                     succeededQuietly(description, errors);
-                } catch (@SuppressWarnings("deprecation") org.junit.internal.AssumptionViolatedException  e) {
+                } catch (org.junit.internal.AssumptionViolatedException  e) {
                     errors.add(e);
                     skippedQuietly(e, description, errors);
                 } catch (Throwable e) {
@@ -87,7 +93,6 @@
         }
     }
 
-    @SuppressWarnings("deprecation")
     private void skippedQuietly(
             org.junit.internal.AssumptionViolatedException e, Description description,
             List<Throwable> errors) {
@@ -135,7 +140,6 @@
     /**
      * Invoked when a test is skipped due to a failed assumption.
      */
-    @SuppressWarnings("deprecation")
     protected void skipped(AssumptionViolatedException e, Description description) {
         // For backwards compatibility with JUnit 4.11 and earlier, call the legacy version
         org.junit.internal.AssumptionViolatedException asInternalException = e;
diff --git a/src/main/java/org/junit/rules/Timeout.java b/src/main/java/org/junit/rules/Timeout.java
index 8d382df..5cf905a 100644
--- a/src/main/java/org/junit/rules/Timeout.java
+++ b/src/main/java/org/junit/rules/Timeout.java
@@ -12,7 +12,7 @@
  * public static class HasGlobalLongTimeout {
  *
  *  &#064;Rule
- *  public Timeout globalTimeout= new Timeout(20);
+ *  public Timeout globalTimeout = Timeout.millis(20);
  *
  *  &#064;Test
  *  public void run1() throws InterruptedException {
@@ -82,7 +82,7 @@
     }
 
     /**
-     * Create a {@code Timeout} instance initialized with values form
+     * Create a {@code Timeout} instance initialized with values from
      * a builder.
      *
      * @since 4.12
diff --git a/src/main/java/org/junit/runner/Computer.java b/src/main/java/org/junit/runner/Computer.java
index 8bb4b20..18d0d31 100644
--- a/src/main/java/org/junit/runner/Computer.java
+++ b/src/main/java/org/junit/runner/Computer.java
@@ -30,7 +30,17 @@
             public Runner runnerForClass(Class<?> testClass) throws Throwable {
                 return getRunner(builder, testClass);
             }
-        }, classes);
+        }, classes) {
+            @Override
+            protected String getName() {
+                /*
+                 * #1320 The generated suite is not based on a real class so
+                 * only a 'null' description can be generated from it. This name
+                 * will be overridden here.
+                 */
+                return "classes";
+            }
+        };
     }
 
     /**
diff --git a/src/main/java/org/junit/runner/Describable.java b/src/main/java/org/junit/runner/Describable.java
index 1514141..293fdb3 100644
--- a/src/main/java/org/junit/runner/Describable.java
+++ b/src/main/java/org/junit/runner/Describable.java
@@ -10,5 +10,5 @@
     /**
      * @return a {@link Description} showing the tests to be run by the receiver
      */
-    public abstract Description getDescription();
+    Description getDescription();
 }
\ No newline at end of file
diff --git a/src/main/java/org/junit/runner/Description.java b/src/main/java/org/junit/runner/Description.java
index fe47eac..0846a1e 100644
--- a/src/main/java/org/junit/runner/Description.java
+++ b/src/main/java/org/junit/runner/Description.java
@@ -125,6 +125,17 @@
     }
 
     /**
+     * Create a <code>Description</code> named after <code>testClass</code>
+     *
+     * @param testClass A not null {@link Class} containing tests
+     * @param annotations meta-data about the test, for downstream interpreters
+     * @return a <code>Description</code> of <code>testClass</code>
+     */
+    public static Description createSuiteDescription(Class<?> testClass, Annotation... annotations) {
+        return new Description(testClass, testClass.getName(), annotations);
+    }
+
+    /**
      * Describes a Runner which runs no tests
      */
     public static final Description EMPTY = new Description(null, "No Tests");
@@ -139,7 +150,7 @@
     /*
      * We have to use the f prefix until the next major release to ensure
      * serialization compatibility. 
-     * See https://github.com/junit-team/junit/issues/976
+     * See https://github.com/junit-team/junit4/issues/976
      */
     private final Collection<Description> fChildren = new ConcurrentLinkedQueue<Description>();
     private final String fDisplayName;
diff --git a/src/main/java/org/junit/runner/FilterFactory.java b/src/main/java/org/junit/runner/FilterFactory.java
index 57b4eaa..e2bfb73 100644
--- a/src/main/java/org/junit/runner/FilterFactory.java
+++ b/src/main/java/org/junit/runner/FilterFactory.java
@@ -16,7 +16,8 @@
     /**

      * Exception thrown if the {@link Filter} cannot be created.

      */

-    public static class FilterNotCreatedException extends Exception {

+    @SuppressWarnings("serial")

+    class FilterNotCreatedException extends Exception {

         public FilterNotCreatedException(Exception exception) {

             super(exception.getMessage(), exception);

         }

diff --git a/src/main/java/org/junit/runner/JUnitCommandLineParseResult.java b/src/main/java/org/junit/runner/JUnitCommandLineParseResult.java
index 434157c..3383407 100644
--- a/src/main/java/org/junit/runner/JUnitCommandLineParseResult.java
+++ b/src/main/java/org/junit/runner/JUnitCommandLineParseResult.java
@@ -85,13 +85,11 @@
     }

 

     private String[] copyArray(String[] args, int from, int to) {

-        ArrayList<String> result = new ArrayList<String>();

-

+        String[] result = new String[to - from];

         for (int j = from; j != to; ++j) {

-            result.add(args[j]);

+            result[j - from] = args[j];

         }

-

-        return result.toArray(new String[result.size()]);

+        return result;

     }

 

     void parseParameters(String[] args) {

diff --git a/src/main/java/org/junit/runner/OrderWith.java b/src/main/java/org/junit/runner/OrderWith.java
new file mode 100644
index 0000000..e8470c9
--- /dev/null
+++ b/src/main/java/org/junit/runner/OrderWith.java
@@ -0,0 +1,28 @@
+package org.junit.runner;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import org.junit.runner.manipulation.Ordering;
+import org.junit.validator.ValidateWith;
+
+/**
+ * When a test class is annotated with <code>&#064;OrderWith</code> or extends a class annotated
+ * with <code>&#064;OrderWith</code>, JUnit will order the tests in the test class (and child
+ * test classes, if any) using the ordering defined by the {@link Ordering} class.
+ *
+ * @since 4.13
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.TYPE)
+@Inherited
+@ValidateWith(OrderWithValidator.class)
+public @interface OrderWith {
+    /**
+     * Gets a class that extends {@link Ordering}. The class must have a public no-arg constructor.
+     */
+    Class<? extends Ordering.Factory> value();
+}
diff --git a/src/main/java/org/junit/runner/OrderWithValidator.java b/src/main/java/org/junit/runner/OrderWithValidator.java
new file mode 100644
index 0000000..f8eab25
--- /dev/null
+++ b/src/main/java/org/junit/runner/OrderWithValidator.java
@@ -0,0 +1,38 @@
+package org.junit.runner;
+
+import static java.util.Collections.emptyList;
+import static java.util.Collections.singletonList;
+
+import java.util.List;
+
+import org.junit.FixMethodOrder;
+import org.junit.runners.model.TestClass;
+import org.junit.validator.AnnotationValidator;
+
+/**
+ * Validates that there are no errors in the use of the {@code OrderWith}
+ * annotation. If there is, a {@code Throwable} object will be added to the list
+ * of errors.
+ *
+ * @since 4.13
+ */
+public final class OrderWithValidator extends AnnotationValidator {
+
+    /**
+     * Adds to {@code errors} a throwable for each problem detected. Looks for
+     * {@code FixMethodOrder} annotations.
+     *
+     * @param testClass that is being validated
+     * @return A list of exceptions detected
+     *
+     * @since 4.13
+     */
+    @Override
+    public List<Exception> validateAnnotatedClass(TestClass testClass) {
+        if (testClass.getAnnotation(FixMethodOrder.class) != null) {
+            return singletonList(
+                    new Exception("@FixMethodOrder cannot be combined with @OrderWith"));
+        }
+        return emptyList();
+    }
+}
diff --git a/src/main/java/org/junit/runner/Request.java b/src/main/java/org/junit/runner/Request.java
index 79c0f1e..7b9a990 100644
--- a/src/main/java/org/junit/runner/Request.java
+++ b/src/main/java/org/junit/runner/Request.java
@@ -5,9 +5,11 @@
 import org.junit.internal.builders.AllDefaultPossibilitiesBuilder;
 import org.junit.internal.requests.ClassRequest;
 import org.junit.internal.requests.FilterRequest;
+import org.junit.internal.requests.OrderingRequest;
 import org.junit.internal.requests.SortingRequest;
 import org.junit.internal.runners.ErrorReportingRunner;
 import org.junit.runner.manipulation.Filter;
+import org.junit.runner.manipulation.Ordering;
 import org.junit.runners.model.InitializationError;
 
 /**
@@ -71,12 +73,11 @@
      */
     public static Request classes(Computer computer, Class<?>... classes) {
         try {
-            AllDefaultPossibilitiesBuilder builder = new AllDefaultPossibilitiesBuilder(true);
+            AllDefaultPossibilitiesBuilder builder = new AllDefaultPossibilitiesBuilder();
             Runner suite = computer.getSuite(builder, classes);
             return runner(suite);
         } catch (InitializationError e) {
-            throw new RuntimeException(
-                    "Bug in saff's brain: Suite constructor, called as above, should always complete");
+            return runner(new ErrorReportingRunner(e, classes));
         }
     }
 
@@ -132,13 +133,16 @@
     }
 
     /**
-     * Returns a Request that only runs contains tests whose {@link Description}
-     * equals <code>desiredDescription</code>
+     * Returns a Request that only runs tests whose {@link Description}
+     * matches the given description.
      *
-     * @param desiredDescription {@link Description} of those tests that should be run
+     * <p>Returns an empty {@code Request} if {@code desiredDescription} is not a single test and filters all but the single
+     * test if {@code desiredDescription} is a single test.</p>
+     *
+     * @param desiredDescription {@code Description} of those tests that should be run
      * @return the filtered Request
      */
-    public Request filterWith(final Description desiredDescription) {
+    public Request filterWith(Description desiredDescription) {
         return filterWith(Filter.matchMethodDescription(desiredDescription));
     }
 
@@ -149,15 +153,15 @@
      * For example, here is code to run a test suite in alphabetical order:
      * <pre>
      * private static Comparator&lt;Description&gt; forward() {
-     * return new Comparator&lt;Description&gt;() {
-     * public int compare(Description o1, Description o2) {
-     * return o1.getDisplayName().compareTo(o2.getDisplayName());
-     * }
-     * };
+     *   return new Comparator&lt;Description&gt;() {
+     *     public int compare(Description o1, Description o2) {
+     *       return o1.getDisplayName().compareTo(o2.getDisplayName());
+     *     }
+     *   };
      * }
      *
      * public static main() {
-     * new JUnitCore().run(Request.aClass(AllTests.class).sortWith(forward()));
+     *   new JUnitCore().run(Request.aClass(AllTests.class).sortWith(forward()));
      * }
      * </pre>
      *
@@ -167,4 +171,32 @@
     public Request sortWith(Comparator<Description> comparator) {
         return new SortingRequest(this, comparator);
     }
+
+    /**
+     * Returns a Request whose Tests can be run in a certain order, defined by
+     * <code>ordering</code>
+     * <p>
+     * For example, here is code to run a test suite in reverse order:
+     * <pre>
+     * private static Ordering reverse() {
+     *   return new Ordering() {
+     *     public List&lt;Description&gt; orderItems(Collection&lt;Description&gt; descriptions) {
+     *       List&lt;Description&gt; ordered = new ArrayList&lt;&gt;(descriptions);
+     *       Collections.reverse(ordered);
+     *       return ordered;
+     *     }
+     *   }
+     * }
+     *     
+     * public static main() {
+     *   new JUnitCore().run(Request.aClass(AllTests.class).orderWith(reverse()));
+     * }
+     * </pre>
+     *
+     * @return a Request with ordered Tests
+     * @since 4.13
+     */
+    public Request orderWith(Ordering ordering) {
+        return new OrderingRequest(this, ordering);
+    }
 }
diff --git a/src/main/java/org/junit/runner/Result.java b/src/main/java/org/junit/runner/Result.java
index 73ad059..4b5f4a4 100644
--- a/src/main/java/org/junit/runner/Result.java
+++ b/src/main/java/org/junit/runner/Result.java
@@ -28,6 +28,7 @@
             ObjectStreamClass.lookup(SerializedForm.class).getFields();
     private final AtomicInteger count;
     private final AtomicInteger ignoreCount;
+    private final AtomicInteger assumptionFailureCount;
     private final CopyOnWriteArrayList<Failure> failures;
     private final AtomicLong runTime;
     private final AtomicLong startTime;
@@ -38,6 +39,7 @@
     public Result() {
         count = new AtomicInteger();
         ignoreCount = new AtomicInteger();
+        assumptionFailureCount = new AtomicInteger();
         failures = new CopyOnWriteArrayList<Failure>();
         runTime = new AtomicLong();
         startTime = new AtomicLong();
@@ -46,34 +48,35 @@
     private Result(SerializedForm serializedForm) {
         count = serializedForm.fCount;
         ignoreCount = serializedForm.fIgnoreCount;
+        assumptionFailureCount = serializedForm.assumptionFailureCount;
         failures = new CopyOnWriteArrayList<Failure>(serializedForm.fFailures);
         runTime = new AtomicLong(serializedForm.fRunTime);
         startTime = new AtomicLong(serializedForm.fStartTime);
     }
 
     /**
-     * @return the number of tests run
+     * Returns the number of tests run
      */
     public int getRunCount() {
         return count.get();
     }
 
     /**
-     * @return the number of tests that failed during the run
+     * Returns the number of tests that failed during the run
      */
     public int getFailureCount() {
         return failures.size();
     }
 
     /**
-     * @return the number of milliseconds it took to run the entire suite to run
+     * Returns the number of milliseconds it took to run the entire suite to run
      */
     public long getRunTime() {
         return runTime.get();
     }
 
     /**
-     * @return the {@link Failure}s describing tests that failed and the problems they encountered
+     * Returns the {@link Failure}s describing tests that failed and the problems they encountered
      */
     public List<Failure> getFailures() {
         return failures;
@@ -87,6 +90,20 @@
     }
 
     /**
+     * Returns the number of tests skipped because of an assumption failure
+     *
+     * @throws UnsupportedOperationException if the result was serialized in a version before JUnit 4.13
+     * @since 4.13
+     */
+    public int getAssumptionFailureCount() {
+        if (assumptionFailureCount == null) {
+            throw new UnsupportedOperationException(
+                    "Result was serialized from a version of JUnit that doesn't support this method");
+        }
+        return assumptionFailureCount.get();
+    }
+
+    /**
      * @return <code>true</code> if all tests succeeded
      */
     public boolean wasSuccessful() {
@@ -137,7 +154,7 @@
 
         @Override
         public void testAssumptionFailure(Failure failure) {
-            // do nothing: same as passing (for 4.5; may change in 4.6)
+            assumptionFailureCount.getAndIncrement();
         }
     }
 
@@ -156,6 +173,7 @@
         private static final long serialVersionUID = 1L;
         private final AtomicInteger fCount;
         private final AtomicInteger fIgnoreCount;
+        private final AtomicInteger assumptionFailureCount;
         private final List<Failure> fFailures;
         private final long fRunTime;
         private final long fStartTime;
@@ -163,6 +181,7 @@
         public SerializedForm(Result result) {
             fCount = result.count;
             fIgnoreCount = result.ignoreCount;
+            assumptionFailureCount = result.assumptionFailureCount;
             fFailures = Collections.synchronizedList(new ArrayList<Failure>(result.failures));
             fRunTime = result.runTime.longValue();
             fStartTime = result.startTime.longValue();
@@ -172,6 +191,7 @@
         private SerializedForm(ObjectInputStream.GetField fields) throws IOException {
             fCount = (AtomicInteger) fields.get("fCount", null);
             fIgnoreCount = (AtomicInteger) fields.get("fIgnoreCount", null);
+            assumptionFailureCount = (AtomicInteger) fields.get("assumptionFailureCount", null);
             fFailures = (List<Failure>) fields.get("fFailures", null);
             fRunTime = fields.get("fRunTime", 0L);
             fStartTime = fields.get("fStartTime", 0L);
@@ -184,6 +204,7 @@
             fields.put("fFailures", fFailures);
             fields.put("fRunTime", fRunTime);
             fields.put("fStartTime", fStartTime);
+            fields.put("assumptionFailureCount", assumptionFailureCount);
             s.writeFields();
         }
 
diff --git a/src/main/java/org/junit/runner/manipulation/Alphanumeric.java b/src/main/java/org/junit/runner/manipulation/Alphanumeric.java
new file mode 100644
index 0000000..8388d21
--- /dev/null
+++ b/src/main/java/org/junit/runner/manipulation/Alphanumeric.java
@@ -0,0 +1,27 @@
+package org.junit.runner.manipulation;
+
+import java.util.Comparator;
+
+import org.junit.runner.Description;
+
+/**
+ * A sorter that orders tests alphanumerically by test name.
+ *
+ * @since 4.13
+ */
+public final class Alphanumeric extends Sorter implements Ordering.Factory {
+
+    public Alphanumeric() {
+        super(COMPARATOR);
+    }
+
+    public Ordering create(Context context) {
+        return this;
+    }
+
+    private static final Comparator<Description> COMPARATOR = new Comparator<Description>() {
+        public int compare(Description o1, Description o2) {
+            return o1.getDisplayName().compareTo(o2.getDisplayName());
+        }
+    };
+}
diff --git a/src/main/java/org/junit/runner/manipulation/InvalidOrderingException.java b/src/main/java/org/junit/runner/manipulation/InvalidOrderingException.java
new file mode 100644
index 0000000..d9d60f7
--- /dev/null
+++ b/src/main/java/org/junit/runner/manipulation/InvalidOrderingException.java
@@ -0,0 +1,21 @@
+package org.junit.runner.manipulation;
+
+/**
+ * Thrown when an ordering does something invalid (like remove or add children)
+ *
+ * @since 4.13
+ */
+public class InvalidOrderingException extends Exception {
+    private static final long serialVersionUID = 1L;
+
+    public InvalidOrderingException() {
+    }
+
+    public InvalidOrderingException(String message) {
+        super(message);
+    }
+
+    public InvalidOrderingException(String message, Throwable cause) {
+        super(message, cause);
+    }
+}
diff --git a/src/main/java/org/junit/runner/manipulation/Orderable.java b/src/main/java/org/junit/runner/manipulation/Orderable.java
new file mode 100644
index 0000000..9a12a3b
--- /dev/null
+++ b/src/main/java/org/junit/runner/manipulation/Orderable.java
@@ -0,0 +1,21 @@
+package org.junit.runner.manipulation;
+
+/**
+ * Interface for runners that allow ordering of tests.
+ *
+ * <p>Beware of using this interface to cope with order dependencies between tests.
+ * Tests that are isolated from each other are less expensive to maintain and
+ * can be run individually.
+ *
+ * @since 4.13
+ */
+public interface Orderable extends Sortable {
+
+    /**
+     * Orders the tests using <code>orderer</code>
+     *
+     * @throws InvalidOrderingException if orderer does something invalid (like remove or add
+     * children)
+     */
+    void order(Orderer orderer) throws InvalidOrderingException;
+}
diff --git a/src/main/java/org/junit/runner/manipulation/Orderer.java b/src/main/java/org/junit/runner/manipulation/Orderer.java
new file mode 100644
index 0000000..eb13054
--- /dev/null
+++ b/src/main/java/org/junit/runner/manipulation/Orderer.java
@@ -0,0 +1,62 @@
+package org.junit.runner.manipulation;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.junit.runner.Description;
+
+/**
+ * Orders tests.
+ *
+ * @since 4.13
+ */
+public final class Orderer  {
+    private final Ordering ordering;
+
+    Orderer(Ordering delegate) {
+        this.ordering = delegate;
+    }
+
+    /**
+     * Orders the descriptions.
+     *
+     * @return descriptions in order
+     */
+    public List<Description> order(Collection<Description> descriptions)
+            throws InvalidOrderingException {
+        List<Description> inOrder = ordering.orderItems(
+                Collections.unmodifiableCollection(descriptions));
+        if (!ordering.validateOrderingIsCorrect()) {
+            return inOrder;
+        }
+
+        Set<Description> uniqueDescriptions = new HashSet<Description>(descriptions);
+        if (!uniqueDescriptions.containsAll(inOrder)) {
+            throw new InvalidOrderingException("Ordering added items");
+        }
+        Set<Description> resultAsSet = new HashSet<Description>(inOrder);
+        if (resultAsSet.size() != inOrder.size()) {
+            throw new InvalidOrderingException("Ordering duplicated items");
+        } else if (!resultAsSet.containsAll(uniqueDescriptions)) {
+            throw new InvalidOrderingException("Ordering removed items");
+        }
+
+        return inOrder;
+    }
+
+    /**
+     * Order the tests in <code>target</code>.
+     *
+     * @throws InvalidOrderingException if ordering does something invalid (like remove or add
+     * children)
+     */
+    public void apply(Object target) throws InvalidOrderingException {
+        if (target instanceof Orderable) {
+            Orderable orderable = (Orderable) target;
+            orderable.order(this);
+        }
+    }
+}
diff --git a/src/main/java/org/junit/runner/manipulation/Ordering.java b/src/main/java/org/junit/runner/manipulation/Ordering.java
new file mode 100644
index 0000000..0d0ce93
--- /dev/null
+++ b/src/main/java/org/junit/runner/manipulation/Ordering.java
@@ -0,0 +1,172 @@
+package org.junit.runner.manipulation;
+
+import java.lang.reflect.Constructor;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Random;
+
+import org.junit.runner.Description;
+import org.junit.runner.OrderWith;
+
+/**
+ * Reorders tests. An {@code Ordering} can reverse the order of tests, sort the
+ * order or even shuffle the order.
+ *
+ * <p>In general you will not need to use a <code>Ordering</code> directly.
+ * Instead, use {@link org.junit.runner.Request#orderWith(Ordering)}.
+ *
+ * @since 4.13
+ */
+public abstract class Ordering {
+    private static final String CONSTRUCTOR_ERROR_FORMAT
+            = "Ordering class %s should have a public constructor with signature "
+                    + "%s(Ordering.Context context)";
+
+    /**
+     * Creates an {@link Ordering} that shuffles the items using the given
+     * {@link Random} instance.
+     */
+    public static Ordering shuffledBy(final Random random) {
+        return new Ordering() {
+            @Override
+            boolean validateOrderingIsCorrect() {
+                return false;
+            }
+
+            @Override
+            protected List<Description> orderItems(Collection<Description> descriptions) {
+                List<Description> shuffled = new ArrayList<Description>(descriptions);
+                Collections.shuffle(shuffled, random);
+                return shuffled;
+            }
+        };
+    }
+
+    /**
+     * Creates an {@link Ordering} from the given factory class. The class must have a public no-arg
+     * constructor.
+     *
+     * @param factoryClass class to use to create the ordering
+     * @param annotatedTestClass test class that is annotated with {@link OrderWith}.
+     * @throws InvalidOrderingException if the instance could not be created
+     */
+    public static Ordering definedBy(
+            Class<? extends Ordering.Factory> factoryClass, Description annotatedTestClass)
+            throws InvalidOrderingException {
+        if (factoryClass == null) {
+            throw new NullPointerException("factoryClass cannot be null");
+        }
+        if (annotatedTestClass == null) {
+            throw new NullPointerException("annotatedTestClass cannot be null");
+        }
+
+        Ordering.Factory factory;
+        try {
+            Constructor<? extends Ordering.Factory> constructor = factoryClass.getConstructor();
+            factory = constructor.newInstance();
+        } catch (NoSuchMethodException e) {
+            throw new InvalidOrderingException(String.format(
+                    CONSTRUCTOR_ERROR_FORMAT,
+                    getClassName(factoryClass),
+                    factoryClass.getSimpleName()));
+        } catch (Exception e) {
+            throw new InvalidOrderingException(
+                    "Could not create ordering for " + annotatedTestClass, e);
+        }
+        return definedBy(factory, annotatedTestClass);
+    }
+
+    /**
+     * Creates an {@link Ordering} from the given factory.
+     *
+     * @param factory factory to use to create the ordering
+     * @param annotatedTestClass test class that is annotated with {@link OrderWith}.
+     * @throws InvalidOrderingException if the instance could not be created
+     */
+    public static Ordering definedBy(
+            Ordering.Factory factory, Description annotatedTestClass)
+            throws InvalidOrderingException {
+        if (factory == null) {
+            throw new NullPointerException("factory cannot be null");
+        }
+        if (annotatedTestClass == null) {
+            throw new NullPointerException("annotatedTestClass cannot be null");
+        }
+
+        return factory.create(new Ordering.Context(annotatedTestClass));
+    }
+
+    private static String getClassName(Class<?> clazz) {
+        String name = clazz.getCanonicalName();
+        if (name == null) {
+            return clazz.getName();
+        }
+        return name;
+    }
+
+    /**
+     * Order the tests in <code>target</code> using this ordering.
+     *
+     * @throws InvalidOrderingException if ordering does something invalid (like remove or add
+     * children)
+     */
+    public void apply(Object target) throws InvalidOrderingException {
+        /*
+         * Note that some subclasses of Ordering override apply(). The Sorter
+         * subclass of Ordering overrides apply() to apply the sort (this is
+         * done because sorting is more efficient than ordering).
+         */
+        if (target instanceof Orderable) {
+            Orderable orderable = (Orderable) target;
+            orderable.order(new Orderer(this));
+        }
+    }
+
+    /**
+     * Returns {@code true} if this ordering could produce invalid results (i.e.
+     * if it could add or remove values).
+     */
+    boolean validateOrderingIsCorrect() {
+        return true;
+    }
+
+    /**
+     * Implemented by sub-classes to order the descriptions.
+     *
+     * @return descriptions in order
+     */
+    protected abstract List<Description> orderItems(Collection<Description> descriptions);
+
+    /** Context about the ordering being applied. */
+    public static class Context {
+        private final Description description;
+
+        /**
+         * Gets the description for the top-level target being ordered.
+         */
+        public Description getTarget() {
+            return description;
+        }
+
+        private Context(Description description) {
+            this.description = description;
+        }
+    }
+
+    /**
+     * Factory for creating {@link Ordering} instances.
+     *
+     * <p>For a factory to be used with {@code @OrderWith} it needs to have a public no-arg
+     * constructor.
+     */
+    public interface Factory {
+        /**
+         * Creates an Ordering instance using the given context. Implementations
+         * of this method that do not need to use the context can return the
+         * same instance every time.
+         */
+        Ordering create(Context context);
+    }
+}
diff --git a/src/main/java/org/junit/runner/manipulation/Sortable.java b/src/main/java/org/junit/runner/manipulation/Sortable.java
index 9ac864c..0c59f33 100644
--- a/src/main/java/org/junit/runner/manipulation/Sortable.java
+++ b/src/main/java/org/junit/runner/manipulation/Sortable.java
@@ -15,6 +15,6 @@
      *
      * @param sorter the {@link Sorter} to use for sorting the tests
      */
-    public void sort(Sorter sorter);
+    void sort(Sorter sorter);
 
 }
diff --git a/src/main/java/org/junit/runner/manipulation/Sorter.java b/src/main/java/org/junit/runner/manipulation/Sorter.java
index 20192d0..4b5274c 100644
--- a/src/main/java/org/junit/runner/manipulation/Sorter.java
+++ b/src/main/java/org/junit/runner/manipulation/Sorter.java
@@ -1,16 +1,21 @@
 package org.junit.runner.manipulation;
 
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
 import java.util.Comparator;
+import java.util.List;
 
 import org.junit.runner.Description;
 
 /**
  * A <code>Sorter</code> orders tests. In general you will not need
- * to use a <code>Sorter</code> directly. Instead, use {@link org.junit.runner.Request#sortWith(Comparator)}.
+ * to use a <code>Sorter</code> directly. Instead, use
+ * {@link org.junit.runner.Request#sortWith(Comparator)}.
  *
  * @since 4.0
  */
-public class Sorter implements Comparator<Description> {
+public class Sorter extends Ordering implements Comparator<Description> {
     /**
      * NULL is a <code>Sorter</code> that leaves elements in an undefined order
      */
@@ -27,17 +32,26 @@
      * to sort tests
      *
      * @param comparator the {@link Comparator} to use when sorting tests
+     * @since 4.0
      */
     public Sorter(Comparator<Description> comparator) {
         this.comparator = comparator;
     }
 
     /**
-     * Sorts the test in <code>runner</code> using <code>comparator</code>
+     * Sorts the tests in <code>target</code> using <code>comparator</code>.
+     *
+     * @since 4.0
      */
-    public void apply(Object object) {
-        if (object instanceof Sortable) {
-            Sortable sortable = (Sortable) object;
+    @Override
+    public void apply(Object target) {
+        /*
+         * Note that all runners that are Orderable are also Sortable (because
+         * Orderable extends Sortable). Sorting is more efficient than ordering,
+         * so we override the parent behavior so we sort instead.
+         */
+        if (target instanceof Sortable) {
+            Sortable sortable = (Sortable) target;
             sortable.sort(this);
         }
     }
@@ -45,4 +59,32 @@
     public int compare(Description o1, Description o2) {
         return comparator.compare(o1, o2);
     }
+ 
+    /**
+     * {@inheritDoc}
+     *
+     * @since 4.13
+     */
+    @Override
+    protected final List<Description> orderItems(Collection<Description> descriptions) {
+        /*
+         * In practice, we will never get here--Sorters do their work in the
+         * compare() method--but the Liskov substitution principle demands that
+         * we obey the general contract of Orderable. Luckily, it's trivial to
+         * implement.
+         */
+        List<Description> sorted = new ArrayList<Description>(descriptions);
+        Collections.sort(sorted, this); // Note: it would be incorrect to pass in "comparator"
+        return sorted;
+    }
+
+    /**
+     * {@inheritDoc}
+     *
+     * @since 4.13
+     */
+    @Override
+    boolean validateOrderingIsCorrect() {
+        return false;
+    }
 }
diff --git a/src/main/java/org/junit/runner/notification/Failure.java b/src/main/java/org/junit/runner/notification/Failure.java
index c03b4c1..4551302 100644
--- a/src/main/java/org/junit/runner/notification/Failure.java
+++ b/src/main/java/org/junit/runner/notification/Failure.java
@@ -1,9 +1,8 @@
 package org.junit.runner.notification;
 
-import java.io.PrintWriter;
 import java.io.Serializable;
-import java.io.StringWriter;
 
+import org.junit.internal.Throwables;
 import org.junit.runner.Description;
 
 /**
@@ -21,7 +20,7 @@
     /*
      * We have to use the f prefix until the next major release to ensure
      * serialization compatibility. 
-     * See https://github.com/junit-team/junit/issues/976
+     * See https://github.com/junit-team/junit4/issues/976
      */
     private final Description fDescription;
     private final Throwable fThrownException;
@@ -65,15 +64,19 @@
     }
 
     /**
-     * Convenience method
-     *
-     * @return the printed form of the exception
+     * Gets the printed form of the exception and its stack trace.
      */
     public String getTrace() {
-        StringWriter stringWriter = new StringWriter();
-        PrintWriter writer = new PrintWriter(stringWriter);
-        getException().printStackTrace(writer);
-        return stringWriter.toString();
+        return Throwables.getStacktrace(getException());
+    }
+
+    /**
+     * Gets a the printed form of the exception, with a trimmed version of the stack trace.
+     * This method will attempt to filter out frames of the stack trace that are below
+     * the test method call.
+     */
+    public String getTrimmedTrace() {
+        return Throwables.getTrimmedStackTrace(getException());
     }
 
     /**
diff --git a/src/main/java/org/junit/runner/notification/RunListener.java b/src/main/java/org/junit/runner/notification/RunListener.java
index db9d8c1..d7cac00 100644
--- a/src/main/java/org/junit/runner/notification/RunListener.java
+++ b/src/main/java/org/junit/runner/notification/RunListener.java
@@ -70,6 +70,34 @@
     }
 
     /**
+     * Called when a test suite is about to be started. If this method is
+     * called for a given {@link Description}, then {@link #testSuiteFinished(Description)}
+     * will also be called for the same {@code Description}.
+     *
+     * <p>Note that not all runners will call this method, so runners should
+     * be prepared to handle {@link #testStarted(Description)} calls for tests
+     * where there was no corresponding {@code testSuiteStarted()} call for
+     * the parent {@code Description}.
+     *
+     * @param description the description of the test suite that is about to be run
+     *                    (generally a class name)
+     * @since 4.13
+     */
+    public void testSuiteStarted(Description description) throws Exception {
+    }
+
+    /**
+     * Called when a test suite has finished, whether the test suite succeeds or fails.
+     * This method will not be called for a given {@link Description} unless
+     * {@link #testSuiteStarted(Description)} was called for the same @code Description}.
+     *
+     * @param description the description of the test suite that just ran
+     * @since 4.13
+     */
+    public void testSuiteFinished(Description description) throws Exception {
+    }
+
+    /**
      * Called when an atomic test is about to be started.
      *
      * @param description the description of the test that is about to be run
diff --git a/src/main/java/org/junit/runner/notification/RunNotifier.java b/src/main/java/org/junit/runner/notification/RunNotifier.java
index 6875f76..752fa3b 100644
--- a/src/main/java/org/junit/runner/notification/RunNotifier.java
+++ b/src/main/java/org/junit/runner/notification/RunNotifier.java
@@ -65,8 +65,8 @@
 
         void run() {
             int capacity = currentListeners.size();
-            ArrayList<RunListener> safeListeners = new ArrayList<RunListener>(capacity);
-            ArrayList<Failure> failures = new ArrayList<Failure>(capacity);
+            List<RunListener> safeListeners = new ArrayList<RunListener>(capacity);
+            List<Failure> failures = new ArrayList<Failure>(capacity);
             for (RunListener listener : currentListeners) {
                 try {
                     notifyListener(listener);
@@ -78,7 +78,7 @@
             fireTestFailures(safeListeners, failures);
         }
 
-        abstract protected void notifyListener(RunListener each) throws Exception;
+        protected abstract void notifyListener(RunListener each) throws Exception;
     }
 
     /**
@@ -106,6 +106,41 @@
     }
 
     /**
+     * Invoke to tell listeners that a test suite is about to start. Runners are strongly
+     * encouraged--but not required--to call this method. If this method is called for
+     * a given {@link Description} then {@link #fireTestSuiteFinished(Description)} MUST
+     * be called for the same {@code Description}.
+     *
+     * @param description the description of the suite test (generally a class name)
+     * @since 4.13
+     */
+    public void fireTestSuiteStarted(final Description description) {
+        new SafeNotifier() {
+            @Override
+            protected void notifyListener(RunListener each) throws Exception {
+                each.testSuiteStarted(description);
+            }
+        }.run();
+    }
+
+    /**
+     * Invoke to tell listeners that a test suite is about to finish. Always invoke
+     * this method if you invoke {@link #fireTestSuiteStarted(Description)}
+     * as listeners are likely to expect them to come in pairs.
+     *
+     * @param description the description of the suite test (generally a class name)
+     * @since 4.13
+     */
+    public void fireTestSuiteFinished(final Description description) {
+        new SafeNotifier() {
+            @Override
+            protected void notifyListener(RunListener each) throws Exception {
+                each.testSuiteFinished(description);
+            }
+        }.run();
+    }
+
+    /**
      * Invoke to tell listeners that an atomic test is about to start.
      *
      * @param description the description of the atomic test (generally a class and method name)
diff --git a/src/main/java/org/junit/runner/notification/SynchronizedRunListener.java b/src/main/java/org/junit/runner/notification/SynchronizedRunListener.java
index c53c1ee..400fed8 100644
--- a/src/main/java/org/junit/runner/notification/SynchronizedRunListener.java
+++ b/src/main/java/org/junit/runner/notification/SynchronizedRunListener.java
@@ -10,7 +10,7 @@
  * <p>This class synchronizes all listener calls on a RunNotifier instance. This is done because
  * prior to JUnit 4.12, all listeners were called in a synchronized block in RunNotifier,
  * so no two listeners were ever called concurrently. If we instead made the methods here
- * sychronized, clients that added multiple listeners that called common code might see
+ * synchronized, clients that added multiple listeners that called common code might see
  * issues due to the reduced synchronization.
  *
  * @author Tibor Digana (tibor17)
@@ -43,6 +43,37 @@
         }
     }
 
+    /**
+     * {@inheritDoc}
+     * <p/>
+     * Synchronized decorator for {@link RunListener#testSuiteStarted(Description)}.
+     * @param description the description of the test suite that is about to be run
+     *                    (generally a class name).
+     * @throws Exception if any occurs.
+     * @since 4.13
+     */
+    @Override
+    public void testSuiteStarted(Description description) throws Exception {
+        synchronized (monitor) {
+            listener.testSuiteStarted(description);
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     * <p/>
+     * Synchronized decorator for {@link RunListener#testSuiteFinished(Description)}.
+     * @param description the description of the test suite that just ran.
+     * @throws Exception
+     * @since 4.13
+     */
+    @Override
+    public void testSuiteFinished(Description description) throws Exception {
+        synchronized (monitor) {
+            listener.testSuiteFinished(description);
+        }
+    }
+
     @Override
     public void testStarted(Description description) throws Exception {
         synchronized (monitor) {
diff --git a/src/main/java/org/junit/runners/BlockJUnit4ClassRunner.java b/src/main/java/org/junit/runners/BlockJUnit4ClassRunner.java
index 4d06199..455341a 100644
--- a/src/main/java/org/junit/runners/BlockJUnit4ClassRunner.java
+++ b/src/main/java/org/junit/runners/BlockJUnit4ClassRunner.java
@@ -3,8 +3,10 @@
 import static org.junit.internal.runners.rules.RuleMemberValidator.RULE_METHOD_VALIDATOR;
 import static org.junit.internal.runners.rules.RuleMemberValidator.RULE_VALIDATOR;
 
+import java.util.ArrayList;
 import java.util.List;
 import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
 import java.util.concurrent.TimeUnit;
 
 import org.junit.After;
@@ -21,14 +23,18 @@
 import org.junit.internal.runners.statements.RunAfters;
 import org.junit.internal.runners.statements.RunBefores;
 import org.junit.rules.MethodRule;
-import org.junit.rules.RunRules;
 import org.junit.rules.TestRule;
 import org.junit.runner.Description;
 import org.junit.runner.notification.RunNotifier;
+import org.junit.runners.model.FrameworkMember;
 import org.junit.runners.model.FrameworkMethod;
 import org.junit.runners.model.InitializationError;
+import org.junit.runners.model.MemberValueConsumer;
 import org.junit.runners.model.MultipleFailureException;
 import org.junit.runners.model.Statement;
+import org.junit.runners.model.TestClass;
+import org.junit.validator.PublicClassValidator;
+import org.junit.validator.TestClassValidator;
 
 /**
  * Implements the JUnit 4 standard test case class model, as defined by the
@@ -55,14 +61,27 @@
  * @since 4.5
  */
 public class BlockJUnit4ClassRunner extends ParentRunner<FrameworkMethod> {
-    private final ConcurrentHashMap<FrameworkMethod, Description> methodDescriptions = new ConcurrentHashMap<FrameworkMethod, Description>();
+    private static TestClassValidator PUBLIC_CLASS_VALIDATOR = new PublicClassValidator();
+
+    private final ConcurrentMap<FrameworkMethod, Description> methodDescriptions = new ConcurrentHashMap<FrameworkMethod, Description>();
+
     /**
-     * Creates a BlockJUnit4ClassRunner to run {@code klass}
+     * Creates a BlockJUnit4ClassRunner to run {@code testClass}
      *
      * @throws InitializationError if the test class is malformed.
      */
-    public BlockJUnit4ClassRunner(Class<?> klass) throws InitializationError {
-        super(klass);
+    public BlockJUnit4ClassRunner(Class<?> testClass) throws InitializationError {
+        super(testClass);
+    }
+
+    /**
+     * Creates a BlockJUnit4ClassRunner to run {@code testClass}.
+     *
+     * @throws InitializationError if the test class is malformed.
+     * @since 4.13
+     */
+    protected BlockJUnit4ClassRunner(TestClass testClass) throws InitializationError {
+        super(testClass);
     }
 
     //
@@ -75,10 +94,16 @@
         if (isIgnored(method)) {
             notifier.fireTestIgnored(description);
         } else {
-            runLeaf(methodBlock(method), description, notifier);
+            Statement statement = new Statement() {
+                @Override
+                public void evaluate() throws Throwable {
+                    methodBlock(method).evaluate();
+                }
+            };
+            runLeaf(statement, description, notifier);
         }
     }
-    
+
     /**
      * Evaluates whether {@link FrameworkMethod}s are ignored based on the
      * {@link Ignore} annotation.
@@ -123,6 +148,7 @@
     protected void collectInitializationErrors(List<Throwable> errors) {
         super.collectInitializationErrors(errors);
 
+        validatePublicConstructor(errors);
         validateNoNonStaticInnerClass(errors);
         validateConstructor(errors);
         validateInstanceMethods(errors);
@@ -130,6 +156,12 @@
         validateMethods(errors);
     }
 
+    private void validatePublicConstructor(List<Throwable> errors) {
+        if (getTestClass().getJavaClass() != null) {
+            errors.addAll(PUBLIC_CLASS_VALIDATOR.validateTestClass(getTestClass()));
+        }
+    }
+
     protected void validateNoNonStaticInnerClass(List<Throwable> errors) {
         if (getTestClass().isANonStaticInnerClass()) {
             String gripe = "The inner class " + getTestClass().getName()
@@ -180,6 +212,7 @@
      * Adds to {@code errors} for each method annotated with {@code @Test},
      * {@code @Before}, or {@code @After} that is not a public, void instance
      * method with no arguments.
+     * @deprecated
      */
     @Deprecated
     protected void validateInstanceMethods(List<Throwable> errors) {
@@ -187,7 +220,7 @@
         validatePublicVoidNoArgMethods(Before.class, false, errors);
         validateTestMethods(errors);
 
-        if (computeTestMethods().size() == 0) {
+        if (computeTestMethods().isEmpty()) {
             errors.add(new Exception("No runnable methods"));
         }
     }
@@ -218,6 +251,16 @@
     }
 
     /**
+     * Returns a new fixture to run a particular test {@code method} against.
+     * Default implementation executes the no-argument {@link #createTest()} method.
+     *
+     * @since 4.13
+     */
+    protected Object createTest(FrameworkMethod method) throws Exception {
+        return createTest();
+    }
+
+    /**
      * Returns the name that describes {@code method} for {@link Description}s.
      * Default implementation is the method's name
      */
@@ -232,10 +275,10 @@
      * Here is an outline of the default implementation:
      *
      * <ul>
-     * <li>Invoke {@code method} on the result of {@code createTest()}, and
+     * <li>Invoke {@code method} on the result of {@link #createTest(org.junit.runners.model.FrameworkMethod)}, and
      * throw any exceptions thrown by either operation.
-     * <li>HOWEVER, if {@code method}'s {@code @Test} annotation has the {@code
-     * expecting} attribute, return normally only if the previous step threw an
+     * <li>HOWEVER, if {@code method}'s {@code @Test} annotation has the {@link Test#expected()}
+     * attribute, return normally only if the previous step threw an
      * exception of the correct type, and throw an exception otherwise.
      * <li>HOWEVER, if {@code method}'s {@code @Test} annotation has the {@code
      * timeout} attribute, throw an exception if the previous step takes more
@@ -257,13 +300,13 @@
      * This can be overridden in subclasses, either by overriding this method,
      * or the implementations creating each sub-statement.
      */
-    protected Statement methodBlock(FrameworkMethod method) {
+    protected Statement methodBlock(final FrameworkMethod method) {
         Object test;
         try {
             test = new ReflectiveCallable() {
                 @Override
                 protected Object runReflectiveCall() throws Throwable {
-                    return createTest();
+                    return createTest(method);
                 }
             }.run();
         } catch (Throwable e) {
@@ -276,6 +319,7 @@
         statement = withBefores(method, test, statement);
         statement = withAfters(method, test, statement);
         statement = withRules(method, test, statement);
+        statement = withInterruptIsolation(statement);
         return statement;
     }
 
@@ -292,21 +336,22 @@
 
     /**
      * Returns a {@link Statement}: if {@code method}'s {@code @Test} annotation
-     * has the {@code expecting} attribute, return normally only if {@code next}
+     * has the {@link Test#expected()} attribute, return normally only if {@code next}
      * throws an exception of the correct type, and throw an exception
      * otherwise.
      */
     protected Statement possiblyExpectingExceptions(FrameworkMethod method,
             Object test, Statement next) {
         Test annotation = method.getAnnotation(Test.class);
-        return expectsException(annotation) ? new ExpectException(next,
-                getExpectedException(annotation)) : next;
+        Class<? extends Throwable> expectedExceptionClass = getExpectedException(annotation);
+        return expectedExceptionClass != null ? new ExpectException(next, expectedExceptionClass) : next;
     }
 
     /**
      * Returns a {@link Statement}: if {@code method}'s {@code @Test} annotation
      * has the {@code timeout} attribute, throw an exception if {@code next}
      * takes more than the specified number of milliseconds.
+     * @deprecated
      */
     @Deprecated
     protected Statement withPotentialTimeout(FrameworkMethod method,
@@ -348,28 +393,23 @@
                 target);
     }
 
-    private Statement withRules(FrameworkMethod method, Object target,
-            Statement statement) {
-        List<TestRule> testRules = getTestRules(target);
-        Statement result = statement;
-        result = withMethodRules(method, testRules, target, result);
-        result = withTestRules(method, testRules, result);
-
-        return result;
-    }
-
-    private Statement withMethodRules(FrameworkMethod method, List<TestRule> testRules,
-            Object target, Statement result) {
-        for (org.junit.rules.MethodRule each : getMethodRules(target)) {
-            if (!testRules.contains(each)) {
-                result = each.apply(result, method, target);
+    private Statement withRules(FrameworkMethod method, Object target, Statement statement) {
+        RuleContainer ruleContainer = new RuleContainer();
+        CURRENT_RULE_CONTAINER.set(ruleContainer);
+        try {
+            List<TestRule> testRules = getTestRules(target);
+            for (MethodRule each : rules(target)) {
+                if (!(each instanceof TestRule && testRules.contains(each))) {
+                    ruleContainer.add(each);
+                }
             }
+            for (TestRule rule : testRules) {
+                ruleContainer.add(rule);
+            }
+        } finally {
+            CURRENT_RULE_CONTAINER.remove();
         }
-        return result;
-    }
-
-    private List<org.junit.rules.MethodRule> getMethodRules(Object target) {
-        return rules(target);
+        return ruleContainer.apply(method, describeChild(method), target, statement);
     }
 
     /**
@@ -378,27 +418,12 @@
      *         test
      */
     protected List<MethodRule> rules(Object target) {
-        List<MethodRule> rules = getTestClass().getAnnotatedMethodValues(target, 
-                Rule.class, MethodRule.class);
-        
-        rules.addAll(getTestClass().getAnnotatedFieldValues(target,
-                Rule.class, MethodRule.class));
-        
-        return rules;
-    }
-
-    /**
-     * Returns a {@link Statement}: apply all non-static fields
-     * annotated with {@link Rule}.
-     *
-     * @param statement The base statement
-     * @return a RunRules statement if any class-level {@link Rule}s are
-     *         found, or the base statement
-     */
-    private Statement withTestRules(FrameworkMethod method, List<TestRule> testRules,
-            Statement statement) {
-        return testRules.isEmpty() ? statement :
-                new RunRules(statement, testRules, describeChild(method));
+        RuleCollector<MethodRule> collector = new RuleCollector<MethodRule>();
+        getTestClass().collectAnnotatedMethodValues(target, Rule.class, MethodRule.class,
+                collector);
+        getTestClass().collectAnnotatedFieldValues(target, Rule.class, MethodRule.class,
+                collector);
+        return collector.result;
     }
 
     /**
@@ -407,13 +432,10 @@
      *         test
      */
     protected List<TestRule> getTestRules(Object target) {
-        List<TestRule> result = getTestClass().getAnnotatedMethodValues(target,
-                Rule.class, TestRule.class);
-
-        result.addAll(getTestClass().getAnnotatedFieldValues(target,
-                Rule.class, TestRule.class));
-
-        return result;
+        RuleCollector<TestRule> collector = new RuleCollector<TestRule>();
+        getTestClass().collectAnnotatedMethodValues(target, Rule.class, TestRule.class, collector);
+        getTestClass().collectAnnotatedFieldValues(target, Rule.class, TestRule.class, collector);
+        return collector.result;
     }
 
     private Class<? extends Throwable> getExpectedException(Test annotation) {
@@ -424,14 +446,28 @@
         }
     }
 
-    private boolean expectsException(Test annotation) {
-        return getExpectedException(annotation) != null;
-    }
-
     private long getTimeout(Test annotation) {
         if (annotation == null) {
             return 0;
         }
         return annotation.timeout();
     }
+
+    private static final ThreadLocal<RuleContainer> CURRENT_RULE_CONTAINER =
+            new ThreadLocal<RuleContainer>();
+
+    private static class RuleCollector<T> implements MemberValueConsumer<T> {
+        final List<T> result = new ArrayList<T>();
+
+        public void accept(FrameworkMember<?> member, T value) {
+            Rule rule = member.getAnnotation(Rule.class);
+            if (rule != null) {
+                RuleContainer container = CURRENT_RULE_CONTAINER.get();
+                if (container != null) {
+                    container.setOrder(value, rule.order());
+                }
+            }
+            result.add(value);
+        }
+    }
 }
diff --git a/src/main/java/org/junit/runners/JUnit4.java b/src/main/java/org/junit/runners/JUnit4.java
index 6ba28c2..28eafb3 100644
--- a/src/main/java/org/junit/runners/JUnit4.java
+++ b/src/main/java/org/junit/runners/JUnit4.java
@@ -1,6 +1,7 @@
 package org.junit.runners;
 
 import org.junit.runners.model.InitializationError;
+import org.junit.runners.model.TestClass;
 
 /**
  * Aliases the current default JUnit 4 class runner, for future-proofing. If
@@ -19,6 +20,6 @@
      * Constructs a new instance of the default runner
      */
     public JUnit4(Class<?> klass) throws InitializationError {
-        super(klass);
+        super(new TestClass(klass));
     }
 }
diff --git a/src/main/java/org/junit/runners/Parameterized.java b/src/main/java/org/junit/runners/Parameterized.java
index 829c8f0..d11b66a 100644
--- a/src/main/java/org/junit/runners/Parameterized.java
+++ b/src/main/java/org/junit/runners/Parameterized.java
@@ -1,5 +1,6 @@
 package org.junit.runners;
 
+import java.lang.annotation.Annotation;
 import java.lang.annotation.ElementType;
 import java.lang.annotation.Inherited;
 import java.lang.annotation.Retention;
@@ -8,12 +9,18 @@
 import java.text.MessageFormat;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
 
+import org.junit.internal.AssumptionViolatedException;
+import org.junit.runner.Description;
+import org.junit.runner.Result;
 import org.junit.runner.Runner;
+import org.junit.runner.notification.Failure;
+import org.junit.runner.notification.RunNotifier;
 import org.junit.runners.model.FrameworkMethod;
-import org.junit.runners.model.InitializationError;
+import org.junit.runners.model.InvalidTestClassError;
 import org.junit.runners.model.TestClass;
 import org.junit.runners.parameterized.BlockJUnit4ClassRunnerWithParametersFactory;
 import org.junit.runners.parameterized.ParametersRunnerFactory;
@@ -24,34 +31,37 @@
  * When running a parameterized test class, instances are created for the
  * cross-product of the test methods and the test data elements.
  * <p>
- * For example, to test a Fibonacci function, write:
+ * For example, to test the <code>+</code> operator, write:
  * <pre>
  * &#064;RunWith(Parameterized.class)
- * public class FibonacciTest {
- *     &#064;Parameters(name= &quot;{index}: fib[{0}]={1}&quot;)
+ * public class AdditionTest {
+ *     &#064;Parameters(name = &quot;{index}: {0} + {1} = {2}&quot;)
  *     public static Iterable&lt;Object[]&gt; data() {
- *         return Arrays.asList(new Object[][] { { 0, 0 }, { 1, 1 }, { 2, 1 },
- *                 { 3, 2 }, { 4, 3 }, { 5, 5 }, { 6, 8 } });
+ *         return Arrays.asList(new Object[][] { { 0, 0, 0 }, { 1, 1, 2 },
+ *                 { 3, 2, 5 }, { 4, 3, 7 } });
  *     }
  *
- *     private int fInput;
+ *     private int firstSummand;
  *
- *     private int fExpected;
+ *     private int secondSummand;
  *
- *     public FibonacciTest(int input, int expected) {
- *         fInput= input;
- *         fExpected= expected;
+ *     private int sum;
+ *
+ *     public AdditionTest(int firstSummand, int secondSummand, int sum) {
+ *         this.firstSummand = firstSummand;
+ *         this.secondSummand = secondSummand;
+ *         this.sum = sum;
  *     }
  *
  *     &#064;Test
  *     public void test() {
- *         assertEquals(fExpected, Fibonacci.compute(fInput));
+ *         assertEquals(sum, firstSummand + secondSummand);
  *     }
  * }
  * </pre>
  * <p>
- * Each instance of <code>FibonacciTest</code> will be constructed using the
- * two-argument constructor and the data values in the
+ * Each instance of <code>AdditionTest</code> will be constructed using the
+ * three-argument constructor and the data values in the
  * <code>&#064;Parameters</code> method.
  * <p>
  * In order that you can easily identify the individual tests, you may provide a
@@ -69,33 +79,36 @@
  * </dl>
  * <p>
  * In the example given above, the <code>Parameterized</code> runner creates
- * names like <code>[1: fib(3)=2]</code>. If you don't use the name parameter,
+ * names like <code>[2: 3 + 2 = 5]</code>. If you don't use the name parameter,
  * then the current parameter index is used as name.
  * <p>
  * You can also write:
  * <pre>
  * &#064;RunWith(Parameterized.class)
- * public class FibonacciTest {
- *  &#064;Parameters
- *  public static Iterable&lt;Object[]&gt; data() {
- *      return Arrays.asList(new Object[][] { { 0, 0 }, { 1, 1 }, { 2, 1 },
- *                 { 3, 2 }, { 4, 3 }, { 5, 5 }, { 6, 8 } });
- *  }
- *  
- *  &#064;Parameter(0)
- *  public int fInput;
+ * public class AdditionTest {
+ *     &#064;Parameters(name = &quot;{index}: {0} + {1} = {2}&quot;)
+ *     public static Iterable&lt;Object[]&gt; data() {
+ *         return Arrays.asList(new Object[][] { { 0, 0, 0 }, { 1, 1, 2 },
+ *                 { 3, 2, 5 }, { 4, 3, 7 } });
+ *     }
  *
- *  &#064;Parameter(1)
- *  public int fExpected;
+ *     &#064;Parameter(0)
+ *     public int firstSummand;
  *
- *  &#064;Test
- *  public void test() {
- *      assertEquals(fExpected, Fibonacci.compute(fInput));
- *  }
+ *     &#064;Parameter(1)
+ *     public int secondSummand;
+ *
+ *     &#064;Parameter(2)
+ *     public int sum;
+ *
+ *     &#064;Test
+ *     public void test() {
+ *         assertEquals(sum, firstSummand + secondSummand);
+ *     }
  * }
  * </pre>
  * <p>
- * Each instance of <code>FibonacciTest</code> will be constructed with the default constructor
+ * Each instance of <code>AdditionTest</code> will be constructed with the default constructor
  * and fields annotated by <code>&#064;Parameter</code>  will be initialized
  * with the data values in the <code>&#064;Parameters</code> method.
  *
@@ -105,8 +118,7 @@
  * <pre>
  * &#064;Parameters
  * public static Object[][] data() {
- * 	return new Object[][] { { 0, 0 }, { 1, 1 }, { 2, 1 }, { 3, 2 }, { 4, 3 },
- * 			{ 5, 5 }, { 6, 8 } };
+ * 	return new Object[][] { { 0, 0, 0 }, { 1, 1, 2 }, { 3, 2, 5 }, { 4, 3, 7 } } };
  * }
  * </pre>
  * 
@@ -130,6 +142,19 @@
  * }
  * </pre>
  *
+ * <h3>Executing code before/after executing tests for specific parameters</h3>
+ * <p>
+ * If your test needs to perform some preparation or cleanup based on the
+ * parameters, this can be done by adding public static methods annotated with
+ * {@code @BeforeParam}/{@code @AfterParam}. Such methods should either have no
+ * parameters or the same parameters as the test.
+ * <pre>
+ * &#064;BeforeParam
+ * public static void beforeTestsForParameter(String onlyParameter) {
+ *     System.out.println("Testing " + onlyParameter);
+ * }
+ * </pre>
+ *
  * <h3>Create different runners</h3>
  * <p>
  * By default the {@code Parameterized} runner creates a slightly modified
@@ -141,7 +166,7 @@
  * The factory must have a public zero-arg constructor.
  *
  * <pre>
- * public class YourRunnerFactory implements ParameterizedRunnerFactory {
+ * public class YourRunnerFactory implements ParametersRunnerFactory {
  *     public Runner createRunnerForTestWithParameters(TestWithParameters test)
  *             throws InitializationError {
  *         return YourRunner(test);
@@ -160,6 +185,21 @@
  * }
  * </pre>
  *
+ * <h3>Avoid creating parameters</h3>
+ * <p>With {@link org.junit.Assume assumptions} you can dynamically skip tests.
+ * Assumptions are also supported by the <code>&#064;Parameters</code> method.
+ * Creating parameters is stopped when the assumption fails and none of the
+ * tests in the test class is executed. JUnit reports a
+ * {@link Result#getAssumptionFailureCount() single assumption failure} for the
+ * whole test class in this case.
+ * <pre>
+ * &#064;Parameters
+ * public static Iterable&lt;? extends Object&gt; data() {
+ * 	String os = System.getProperty("os.name").toLowerCase()
+ * 	Assume.assumeTrue(os.contains("win"));
+ * 	return Arrays.asList(&quot;first test&quot;, &quot;second test&quot;);
+ * }
+ * </pre>
  * @since 4.0
  */
 public class Parameterized extends Suite {
@@ -170,7 +210,7 @@
      */
     @Retention(RetentionPolicy.RUNTIME)
     @Target(ElementType.METHOD)
-    public static @interface Parameters {
+    public @interface Parameters {
         /**
          * Optional pattern to derive the test's name from the parameters. Use
          * numbers in braces to refer to the parameters or the additional data
@@ -201,7 +241,7 @@
      */
     @Retention(RetentionPolicy.RUNTIME)
     @Target(ElementType.FIELD)
-    public static @interface Parameter {
+    public @interface Parameter {
         /**
          * Method that returns the index of the parameter in the array
          * returned by the method annotated by <code>Parameters</code>.
@@ -230,122 +270,235 @@
         Class<? extends ParametersRunnerFactory> value() default BlockJUnit4ClassRunnerWithParametersFactory.class;
     }
 
-    private static final ParametersRunnerFactory DEFAULT_FACTORY = new BlockJUnit4ClassRunnerWithParametersFactory();
+    /**
+     * Annotation for {@code public static void} methods which should be executed before
+     * evaluating tests with particular parameters.
+     *
+     * @see org.junit.BeforeClass
+     * @see org.junit.Before
+     * @since 4.13
+     */
+    @Retention(RetentionPolicy.RUNTIME)
+    @Target(ElementType.METHOD)
+    public @interface BeforeParam {
+    }
 
-    private static final List<Runner> NO_RUNNERS = Collections.<Runner>emptyList();
-
-    private final List<Runner> runners;
+    /**
+     * Annotation for {@code public static void} methods which should be executed after
+     * evaluating tests with particular parameters.
+     *
+     * @see org.junit.AfterClass
+     * @see org.junit.After
+     * @since 4.13
+     */
+    @Retention(RetentionPolicy.RUNTIME)
+    @Target(ElementType.METHOD)
+    public @interface AfterParam {
+    }
 
     /**
      * Only called reflectively. Do not use programmatically.
      */
     public Parameterized(Class<?> klass) throws Throwable {
-        super(klass, NO_RUNNERS);
-        ParametersRunnerFactory runnerFactory = getParametersRunnerFactory(
-                klass);
-        Parameters parameters = getParametersMethod().getAnnotation(
-                Parameters.class);
-        runners = Collections.unmodifiableList(createRunnersForParameters(
-                allParameters(), parameters.name(), runnerFactory));
+        this(klass, new RunnersFactory(klass));
     }
 
-    private ParametersRunnerFactory getParametersRunnerFactory(Class<?> klass)
-            throws InstantiationException, IllegalAccessException {
-        UseParametersRunnerFactory annotation = klass
-                .getAnnotation(UseParametersRunnerFactory.class);
-        if (annotation == null) {
-            return DEFAULT_FACTORY;
-        } else {
-            Class<? extends ParametersRunnerFactory> factoryClass = annotation
-                    .value();
-            return factoryClass.newInstance();
+    private Parameterized(Class<?> klass, RunnersFactory runnersFactory) throws Exception {
+        super(klass, runnersFactory.createRunners());
+        validateBeforeParamAndAfterParamMethods(runnersFactory.parameterCount);
+    }
+
+    private void validateBeforeParamAndAfterParamMethods(Integer parameterCount)
+            throws InvalidTestClassError {
+        List<Throwable> errors = new ArrayList<Throwable>();
+        validatePublicStaticVoidMethods(Parameterized.BeforeParam.class, parameterCount, errors);
+        validatePublicStaticVoidMethods(Parameterized.AfterParam.class, parameterCount, errors);
+        if (!errors.isEmpty()) {
+            throw new InvalidTestClassError(getTestClass().getJavaClass(), errors);
         }
     }
 
-    @Override
-    protected List<Runner> getChildren() {
-        return runners;
-    }
-
-    private TestWithParameters createTestWithNotNormalizedParameters(
-            String pattern, int index, Object parametersOrSingleParameter) {
-        Object[] parameters= (parametersOrSingleParameter instanceof Object[]) ? (Object[]) parametersOrSingleParameter
-            : new Object[] { parametersOrSingleParameter };
-        return createTestWithParameters(getTestClass(), pattern, index,
-                parameters);
-    }
-
-    @SuppressWarnings("unchecked")
-    private Iterable<Object> allParameters() throws Throwable {
-        Object parameters = getParametersMethod().invokeExplosively(null);
-        if (parameters instanceof Iterable) {
-            return (Iterable<Object>) parameters;
-        } else if (parameters instanceof Object[]) {
-            return Arrays.asList((Object[]) parameters);
-        } else {
-            throw parametersMethodReturnedWrongType();
+    private void validatePublicStaticVoidMethods(
+            Class<? extends Annotation> annotation, Integer parameterCount,
+            List<Throwable> errors) {
+        List<FrameworkMethod> methods = getTestClass().getAnnotatedMethods(annotation);
+        for (FrameworkMethod fm : methods) {
+            fm.validatePublicVoid(true, errors);
+            if (parameterCount != null) {
+                int methodParameterCount = fm.getMethod().getParameterTypes().length;
+                if (methodParameterCount != 0 && methodParameterCount != parameterCount) {
+                    errors.add(new Exception("Method " + fm.getName()
+                            + "() should have 0 or " + parameterCount + " parameter(s)"));
+                }
+            }
         }
     }
 
-    private FrameworkMethod getParametersMethod() throws Exception {
-        List<FrameworkMethod> methods = getTestClass().getAnnotatedMethods(
-                Parameters.class);
-        for (FrameworkMethod each : methods) {
-            if (each.isStatic() && each.isPublic()) {
-                return each;
+    private static class AssumptionViolationRunner extends Runner {
+        private final Description description;
+        private final AssumptionViolatedException exception;
+
+        AssumptionViolationRunner(TestClass testClass, String methodName,
+                AssumptionViolatedException exception) {
+            this.description = Description
+                    .createTestDescription(testClass.getJavaClass(),
+                            methodName + "() assumption violation");
+            this.exception = exception;
+        }
+
+        @Override
+        public Description getDescription() {
+            return description;
+        }
+
+        @Override
+        public void run(RunNotifier notifier) {
+            notifier.fireTestAssumptionFailed(new Failure(description, exception));
+        }
+    }
+
+    private static class RunnersFactory {
+        private static final ParametersRunnerFactory DEFAULT_FACTORY = new BlockJUnit4ClassRunnerWithParametersFactory();
+
+        private final TestClass testClass;
+        private final FrameworkMethod parametersMethod;
+        private final List<Object> allParameters;
+        private final int parameterCount;
+        private final Runner runnerOverride;
+
+        private RunnersFactory(Class<?> klass) throws Throwable {
+            testClass = new TestClass(klass);
+            parametersMethod = getParametersMethod(testClass);
+            List<Object> allParametersResult;
+            AssumptionViolationRunner assumptionViolationRunner = null;
+            try {
+                allParametersResult = allParameters(testClass, parametersMethod);
+            } catch (AssumptionViolatedException e) {
+                allParametersResult = Collections.emptyList();
+                assumptionViolationRunner = new AssumptionViolationRunner(testClass,
+                        parametersMethod.getName(), e);
+            }
+            allParameters = allParametersResult;
+            runnerOverride = assumptionViolationRunner;
+            parameterCount =
+                    allParameters.isEmpty() ? 0 : normalizeParameters(allParameters.get(0)).length;
+        }
+
+        private List<Runner> createRunners() throws Exception {
+            if (runnerOverride != null) {
+                return Collections.singletonList(runnerOverride);
+            }
+            Parameters parameters = parametersMethod.getAnnotation(Parameters.class);
+            return Collections.unmodifiableList(createRunnersForParameters(
+                    allParameters, parameters.name(),
+                    getParametersRunnerFactory()));
+        }
+
+        private ParametersRunnerFactory getParametersRunnerFactory()
+                throws InstantiationException, IllegalAccessException {
+            UseParametersRunnerFactory annotation = testClass
+                    .getAnnotation(UseParametersRunnerFactory.class);
+            if (annotation == null) {
+                return DEFAULT_FACTORY;
+            } else {
+                Class<? extends ParametersRunnerFactory> factoryClass = annotation
+                        .value();
+                return factoryClass.newInstance();
             }
         }
 
-        throw new Exception("No public static parameters method on class "
-                + getTestClass().getName());
-    }
+        private TestWithParameters createTestWithNotNormalizedParameters(
+                String pattern, int index, Object parametersOrSingleParameter) {
+            Object[] parameters = normalizeParameters(parametersOrSingleParameter);
+            return createTestWithParameters(testClass, pattern, index, parameters);
+        }
 
-    private List<Runner> createRunnersForParameters(
-            Iterable<Object> allParameters, String namePattern,
-            ParametersRunnerFactory runnerFactory)
-            throws InitializationError,
-            Exception {
-        try {
-            List<TestWithParameters> tests = createTestsForParameters(
-                    allParameters, namePattern);
-            List<Runner> runners = new ArrayList<Runner>();
-            for (TestWithParameters test : tests) {
-                runners.add(runnerFactory
-                        .createRunnerForTestWithParameters(test));
+        private static Object[] normalizeParameters(Object parametersOrSingleParameter) {
+            return (parametersOrSingleParameter instanceof Object[]) ? (Object[]) parametersOrSingleParameter
+                    : new Object[] { parametersOrSingleParameter };
+        }
+
+        @SuppressWarnings("unchecked")
+        private static List<Object> allParameters(
+                TestClass testClass, FrameworkMethod parametersMethod) throws Throwable {
+            Object parameters = parametersMethod.invokeExplosively(null);
+            if (parameters instanceof List) {
+                return (List<Object>) parameters;
+            } else if (parameters instanceof Collection) {
+                return new ArrayList<Object>((Collection<Object>) parameters);
+            } else if (parameters instanceof Iterable) {
+                List<Object> result = new ArrayList<Object>();
+                for (Object entry : ((Iterable<Object>) parameters)) {
+                    result.add(entry);
+                }
+                return result;
+            } else if (parameters instanceof Object[]) {
+                return Arrays.asList((Object[]) parameters);
+            } else {
+                throw parametersMethodReturnedWrongType(testClass, parametersMethod);
             }
-            return runners;
-        } catch (ClassCastException e) {
-            throw parametersMethodReturnedWrongType();
         }
-    }
 
-    private List<TestWithParameters> createTestsForParameters(
-            Iterable<Object> allParameters, String namePattern)
-            throws Exception {
-        int i = 0;
-        List<TestWithParameters> children = new ArrayList<TestWithParameters>();
-        for (Object parametersOfSingleTest : allParameters) {
-            children.add(createTestWithNotNormalizedParameters(namePattern,
-                    i++, parametersOfSingleTest));
+        private static FrameworkMethod getParametersMethod(TestClass testClass) throws Exception {
+            List<FrameworkMethod> methods = testClass
+                    .getAnnotatedMethods(Parameters.class);
+            for (FrameworkMethod each : methods) {
+                if (each.isStatic() && each.isPublic()) {
+                    return each;
+                }
+            }
+
+            throw new Exception("No public static parameters method on class "
+                    + testClass.getName());
         }
-        return children;
-    }
 
-    private Exception parametersMethodReturnedWrongType() throws Exception {
-        String className = getTestClass().getName();
-        String methodName = getParametersMethod().getName();
-        String message = MessageFormat.format(
-                "{0}.{1}() must return an Iterable of arrays.",
-                className, methodName);
-        return new Exception(message);
-    }
+        private List<Runner> createRunnersForParameters(
+                Iterable<Object> allParameters, String namePattern,
+                ParametersRunnerFactory runnerFactory) throws Exception {
+            try {
+                List<TestWithParameters> tests = createTestsForParameters(
+                        allParameters, namePattern);
+                List<Runner> runners = new ArrayList<Runner>();
+                for (TestWithParameters test : tests) {
+                    runners.add(runnerFactory
+                            .createRunnerForTestWithParameters(test));
+                }
+                return runners;
+            } catch (ClassCastException e) {
+                throw parametersMethodReturnedWrongType(testClass, parametersMethod);
+            }
+        }
 
-    private static TestWithParameters createTestWithParameters(
-            TestClass testClass, String pattern, int index, Object[] parameters) {
-        String finalPattern = pattern.replaceAll("\\{index\\}",
-                Integer.toString(index));
-        String name = MessageFormat.format(finalPattern, parameters);
-        return new TestWithParameters("[" + name + "]", testClass,
-                Arrays.asList(parameters));
+        private List<TestWithParameters> createTestsForParameters(
+                Iterable<Object> allParameters, String namePattern)
+                throws Exception {
+            int i = 0;
+            List<TestWithParameters> children = new ArrayList<TestWithParameters>();
+            for (Object parametersOfSingleTest : allParameters) {
+                children.add(createTestWithNotNormalizedParameters(namePattern,
+                        i++, parametersOfSingleTest));
+            }
+            return children;
+        }
+
+        private static Exception parametersMethodReturnedWrongType(
+                TestClass testClass, FrameworkMethod parametersMethod) throws Exception {
+            String className = testClass.getName();
+            String methodName = parametersMethod.getName();
+            String message = MessageFormat.format(
+                    "{0}.{1}() must return an Iterable of arrays.", className,
+                    methodName);
+            return new Exception(message);
+        }
+
+        private TestWithParameters createTestWithParameters(
+                TestClass testClass, String pattern, int index,
+                Object[] parameters) {
+            String finalPattern = pattern.replaceAll("\\{index\\}",
+                    Integer.toString(index));
+            String name = MessageFormat.format(finalPattern, parameters);
+            return new TestWithParameters("[" + name + "]", testClass,
+                    Arrays.asList(parameters));
+        }
     }
 }
diff --git a/src/main/java/org/junit/runners/ParentRunner.java b/src/main/java/org/junit/runners/ParentRunner.java
old mode 100755
new mode 100644
index 92641bf..0a0e7cb
--- a/src/main/java/org/junit/runners/ParentRunner.java
+++ b/src/main/java/org/junit/runners/ParentRunner.java
@@ -1,21 +1,25 @@
 package org.junit.runners;
 
+import static org.junit.internal.Checks.notNull;
 import static org.junit.internal.runners.rules.RuleMemberValidator.CLASS_RULE_METHOD_VALIDATOR;
 import static org.junit.internal.runners.rules.RuleMemberValidator.CLASS_RULE_VALIDATOR;
 
 import java.lang.annotation.Annotation;
 import java.lang.reflect.Method;
 import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.Iterator;
+import java.util.LinkedHashMap;
 import java.util.List;
+import java.util.Map;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
 
 import org.junit.AfterClass;
 import org.junit.BeforeClass;
 import org.junit.ClassRule;
+import org.junit.FixMethodOrder;
 import org.junit.Ignore;
 import org.junit.Rule;
 import org.junit.internal.AssumptionViolatedException;
@@ -28,18 +32,22 @@
 import org.junit.runner.Runner;
 import org.junit.runner.manipulation.Filter;
 import org.junit.runner.manipulation.Filterable;
+import org.junit.runner.manipulation.Orderer;
+import org.junit.runner.manipulation.InvalidOrderingException;
 import org.junit.runner.manipulation.NoTestsRemainException;
-import org.junit.runner.manipulation.Sortable;
+import org.junit.runner.manipulation.Orderable;
 import org.junit.runner.manipulation.Sorter;
 import org.junit.runner.notification.RunNotifier;
 import org.junit.runner.notification.StoppedByUserException;
+import org.junit.runners.model.FrameworkMember;
 import org.junit.runners.model.FrameworkMethod;
 import org.junit.runners.model.InitializationError;
+import org.junit.runners.model.InvalidTestClassError;
+import org.junit.runners.model.MemberValueConsumer;
 import org.junit.runners.model.RunnerScheduler;
 import org.junit.runners.model.Statement;
 import org.junit.runners.model.TestClass;
 import org.junit.validator.AnnotationsValidator;
-import org.junit.validator.PublicClassValidator;
 import org.junit.validator.TestClassValidator;
 
 /**
@@ -56,15 +64,15 @@
  * @since 4.5
  */
 public abstract class ParentRunner<T> extends Runner implements Filterable,
-        Sortable {
-    private static final List<TestClassValidator> VALIDATORS = Arrays.asList(
-            new AnnotationsValidator(), new PublicClassValidator());
+        Orderable {
+    private static final List<TestClassValidator> VALIDATORS = Collections.<TestClassValidator>singletonList(
+            new AnnotationsValidator());
 
-    private final Object childrenLock = new Object();
+    private final Lock childrenLock = new ReentrantLock();
     private final TestClass testClass;
 
     // Guarded by childrenLock
-    private volatile Collection<T> filteredChildren = null;
+    private volatile List<T> filteredChildren = null;
 
     private volatile RunnerScheduler scheduler = new RunnerScheduler() {
         public void schedule(Runnable childStatement) {
@@ -84,6 +92,21 @@
         validate();
     }
 
+   /**
+    * Constructs a new {@code ParentRunner} that will run the {@code TestClass}.
+    *
+    * @since 4.13
+    */
+    protected ParentRunner(TestClass testClass) throws InitializationError {
+       this.testClass = notNull(testClass);
+       validate();
+    }
+
+    /**
+     * @deprecated Please use {@link #ParentRunner(org.junit.runners.model.TestClass)}.
+     * @since 4.12
+     */
+    @Deprecated
     protected TestClass createTestClass(Class<?> testClass) {
         return new TestClass(testClass);
     }
@@ -192,6 +215,7 @@
             statement = withBeforeClasses(statement);
             statement = withAfterClasses(statement);
             statement = withClassRules(statement);
+            statement = withInterruptIsolation(statement);
         }
         return statement;
     }
@@ -219,7 +243,7 @@
 
     /**
      * Returns a {@link Statement}: run all non-overridden {@code @AfterClass} methods on this class
-     * and superclasses before executing {@code statement}; all AfterClass methods are
+     * and superclasses after executing {@code statement}; all AfterClass methods are
      * always executed: exceptions thrown by previous steps are combined, if
      * necessary, with exceptions from AfterClass methods into a
      * {@link org.junit.runners.model.MultipleFailureException}.
@@ -251,9 +275,10 @@
      *         each method in the tested class.
      */
     protected List<TestRule> classRules() {
-        List<TestRule> result = testClass.getAnnotatedMethodValues(null, ClassRule.class, TestRule.class);
-        result.addAll(testClass.getAnnotatedFieldValues(null, ClassRule.class, TestRule.class));
-        return result;
+        ClassRuleCollector collector = new ClassRuleCollector();
+        testClass.collectAnnotatedMethodValues(null, ClassRule.class, TestRule.class, collector);
+        testClass.collectAnnotatedFieldValues(null, ClassRule.class, TestRule.class, collector);
+        return collector.getOrderedRules();
     }
 
     /**
@@ -271,6 +296,22 @@
     }
 
     /**
+     * @return a {@link Statement}: clears interrupt status of current thread after execution of statement
+     */
+    protected final Statement withInterruptIsolation(final Statement statement) {
+        return new Statement() {
+            @Override
+            public void evaluate() throws Throwable {
+                try {
+                    statement.evaluate();
+                } finally {
+                    Thread.interrupted(); // clearing thread interrupted status for isolation
+                }
+            }
+        };
+    }
+
+    /**
      * Evaluates whether a child is ignored. The default implementation always
      * returns <code>false</code>.
      * 
@@ -346,8 +387,16 @@
 
     @Override
     public Description getDescription() {
-        Description description = Description.createSuiteDescription(getName(),
-                getRunnerAnnotations());
+        Class<?> clazz = getTestClass().getJavaClass();
+        Description description;
+        // if subclass overrides `getName()` then we should use it
+        // to maintain backwards compatibility with JUnit 4.12
+        if (clazz == null || !clazz.getName().equals(getName())) {
+            description = Description.createSuiteDescription(getName(), getRunnerAnnotations());
+        } else {
+            description = Description.createSuiteDescription(clazz, getRunnerAnnotations());
+        }
+
         for (T child : getFilteredChildren()) {
             description.addChild(describeChild(child));
         }
@@ -358,6 +407,7 @@
     public void run(final RunNotifier notifier) {
         EachTestNotifier testNotifier = new EachTestNotifier(notifier,
                 getDescription());
+        testNotifier.fireTestSuiteStarted();
         try {
             Statement statement = classBlock(notifier);
             statement.evaluate();
@@ -367,6 +417,8 @@
             throw e;
         } catch (Throwable e) {
             testNotifier.addFailure(e);
+        } finally {
+            testNotifier.fireTestSuiteFinished();
         }
     }
 
@@ -375,7 +427,8 @@
     //
 
     public void filter(Filter filter) throws NoTestsRemainException {
-        synchronized (childrenLock) {
+        childrenLock.lock();
+        try {
             List<T> children = new ArrayList<T>(getFilteredChildren());
             for (Iterator<T> iter = children.iterator(); iter.hasNext(); ) {
                 T each = iter.next();
@@ -389,21 +442,70 @@
                     iter.remove();
                 }
             }
-            filteredChildren = Collections.unmodifiableCollection(children);
+            filteredChildren = Collections.unmodifiableList(children);
             if (filteredChildren.isEmpty()) {
                 throw new NoTestsRemainException();
             }
+        } finally {
+            childrenLock.unlock();
         }
     }
 
     public void sort(Sorter sorter) {
-        synchronized (childrenLock) {
+        if (shouldNotReorder()) {
+            return;
+        }
+
+        childrenLock.lock();
+        try {
             for (T each : getFilteredChildren()) {
                 sorter.apply(each);
             }
             List<T> sortedChildren = new ArrayList<T>(getFilteredChildren());
             Collections.sort(sortedChildren, comparator(sorter));
-            filteredChildren = Collections.unmodifiableCollection(sortedChildren);
+            filteredChildren = Collections.unmodifiableList(sortedChildren);
+        } finally {
+            childrenLock.unlock();
+        }
+    }
+
+    /**
+     * Implementation of {@link Orderable#order(Orderer)}.
+     *
+     * @since 4.13
+     */
+    public void order(Orderer orderer) throws InvalidOrderingException {
+        if (shouldNotReorder()) {
+            return;
+        }
+
+        childrenLock.lock();
+        try {
+            List<T> children = getFilteredChildren();
+            // In theory, we could have duplicate Descriptions. De-dup them before ordering,
+            // and add them back at the end.
+            Map<Description, List<T>> childMap = new LinkedHashMap<Description, List<T>>(
+                    children.size());
+            for (T child : children) {
+                Description description = describeChild(child);
+                List<T> childrenWithDescription = childMap.get(description);
+                if (childrenWithDescription == null) {
+                    childrenWithDescription = new ArrayList<T>(1);
+                    childMap.put(description, childrenWithDescription);
+                }
+                childrenWithDescription.add(child);
+                orderer.apply(child);
+            }
+
+            List<Description> inOrder = orderer.order(childMap.keySet());
+
+            children = new ArrayList<T>(children.size());
+            for (Description description : inOrder) {
+                children.addAll(childMap.get(description));
+            }
+            filteredChildren = Collections.unmodifiableList(children);
+        } finally {
+            childrenLock.unlock();
         }
     }
 
@@ -411,20 +513,29 @@
     // Private implementation
     //
 
+    private boolean shouldNotReorder() {
+        // If the test specifies a specific order, do not reorder.
+        return getDescription().getAnnotation(FixMethodOrder.class) != null;
+    }
+
     private void validate() throws InitializationError {
         List<Throwable> errors = new ArrayList<Throwable>();
         collectInitializationErrors(errors);
         if (!errors.isEmpty()) {
-            throw new InitializationError(errors);
+            throw new InvalidTestClassError(testClass.getJavaClass(), errors);
         }
     }
 
-    private Collection<T> getFilteredChildren() {
+    private List<T> getFilteredChildren() {
         if (filteredChildren == null) {
-            synchronized (childrenLock) {
+            childrenLock.lock();
+            try {
                 if (filteredChildren == null) {
-                    filteredChildren = Collections.unmodifiableCollection(getChildren());
+                    filteredChildren = Collections.unmodifiableList(
+                            new ArrayList<T>(getChildren()));
                 }
+            } finally {
+                childrenLock.unlock();
             }
         }
         return filteredChildren;
@@ -449,4 +560,23 @@
     public void setScheduler(RunnerScheduler scheduler) {
         this.scheduler = scheduler;
     }
+
+    private static class ClassRuleCollector implements MemberValueConsumer<TestRule> {
+        final List<RuleContainer.RuleEntry> entries = new ArrayList<RuleContainer.RuleEntry>();
+
+        public void accept(FrameworkMember<?> member, TestRule value) {
+            ClassRule rule = member.getAnnotation(ClassRule.class);
+            entries.add(new RuleContainer.RuleEntry(value, RuleContainer.RuleEntry.TYPE_TEST_RULE,
+                    rule != null ? rule.order() : null));
+        }
+
+        public List<TestRule> getOrderedRules() {
+            Collections.sort(entries, RuleContainer.ENTRY_COMPARATOR);
+            List<TestRule> result = new ArrayList<TestRule>(entries.size());
+            for (RuleContainer.RuleEntry entry : entries) {
+                result.add((TestRule) entry.rule);
+            }
+            return result;
+        }
+    }
 }
diff --git a/src/main/java/org/junit/runners/RuleContainer.java b/src/main/java/org/junit/runners/RuleContainer.java
new file mode 100644
index 0000000..30ddd8d
--- /dev/null
+++ b/src/main/java/org/junit/runners/RuleContainer.java
@@ -0,0 +1,113 @@
+package org.junit.runners;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.IdentityHashMap;
+import java.util.List;
+
+import org.junit.Rule;
+import org.junit.rules.MethodRule;
+import org.junit.rules.TestRule;
+import org.junit.runner.Description;
+import org.junit.runners.model.FrameworkMethod;
+import org.junit.runners.model.Statement;
+
+/**
+ * Data structure for ordering of {@link TestRule}/{@link MethodRule} instances.
+ *
+ * @since 4.13
+ */
+class RuleContainer {
+    private final IdentityHashMap<Object, Integer> orderValues = new IdentityHashMap<Object, Integer>();
+    private final List<TestRule> testRules = new ArrayList<TestRule>();
+    private final List<MethodRule> methodRules = new ArrayList<MethodRule>();
+
+    /**
+     * Sets order value for the specified rule.
+     */
+    public void setOrder(Object rule, int order) {
+        orderValues.put(rule, order);
+    }
+
+    public void add(MethodRule methodRule) {
+        methodRules.add(methodRule);
+    }
+
+    public void add(TestRule testRule) {
+        testRules.add(testRule);
+    }
+
+    static final Comparator<RuleEntry> ENTRY_COMPARATOR = new Comparator<RuleEntry>() {
+        public int compare(RuleEntry o1, RuleEntry o2) {
+            int result = compareInt(o1.order, o2.order);
+            return result != 0 ? result : o1.type - o2.type;
+        }
+
+        private int compareInt(int a, int b) {
+            return (a < b) ? 1 : (a == b ? 0 : -1);
+        }
+    };
+
+    /**
+     * Returns entries in the order how they should be applied, i.e. inner-to-outer.
+     */
+    private List<RuleEntry> getSortedEntries() {
+        List<RuleEntry> ruleEntries = new ArrayList<RuleEntry>(
+                methodRules.size() + testRules.size());
+        for (MethodRule rule : methodRules) {
+            ruleEntries.add(new RuleEntry(rule, RuleEntry.TYPE_METHOD_RULE, orderValues.get(rule)));
+        }
+        for (TestRule rule : testRules) {
+            ruleEntries.add(new RuleEntry(rule, RuleEntry.TYPE_TEST_RULE, orderValues.get(rule)));
+        }
+        Collections.sort(ruleEntries, ENTRY_COMPARATOR);
+        return ruleEntries;
+    }
+
+    /**
+     * Applies all the rules ordered accordingly to the specified {@code statement}.
+     */
+    public Statement apply(FrameworkMethod method, Description description, Object target,
+            Statement statement) {
+        if (methodRules.isEmpty() && testRules.isEmpty()) {
+            return statement;
+        }
+        Statement result = statement;
+        for (RuleEntry ruleEntry : getSortedEntries()) {
+            if (ruleEntry.type == RuleEntry.TYPE_TEST_RULE) {
+                result = ((TestRule) ruleEntry.rule).apply(result, description);
+            } else {
+                result = ((MethodRule) ruleEntry.rule).apply(result, method, target);
+            }
+        }
+        return result;
+    }
+
+    /**
+     * Returns rule instances in the order how they should be applied, i.e. inner-to-outer.
+     * VisibleForTesting
+     */
+    List<Object> getSortedRules() {
+        List<Object> result = new ArrayList<Object>();
+        for (RuleEntry entry : getSortedEntries()) {
+            result.add(entry.rule);
+        }
+        return result;
+    }
+
+    static class RuleEntry {
+        static final int TYPE_TEST_RULE = 1;
+        static final int TYPE_METHOD_RULE = 0;
+
+        final Object rule;
+        final int type;
+        final int order;
+
+        RuleEntry(Object rule, int type, Integer order) {
+            this.rule = rule;
+            this.type = type;
+            this.order = order != null ? order.intValue() : Rule.DEFAULT_ORDER;
+        }
+    }
+}
diff --git a/src/main/java/org/junit/runners/Suite.java b/src/main/java/org/junit/runners/Suite.java
index b37179f..c2c8e58 100644
--- a/src/main/java/org/junit/runners/Suite.java
+++ b/src/main/java/org/junit/runners/Suite.java
@@ -47,7 +47,7 @@
         /**
          * @return the classes to be run
          */
-        public Class<?>[] value();
+        Class<?>[] value();
     }
 
     private static Class<?>[] getAnnotatedClasses(Class<?> klass) throws InitializationError {
@@ -88,7 +88,7 @@
      * @param suiteClasses the classes in the suite
      */
     protected Suite(Class<?> klass, Class<?>[] suiteClasses) throws InitializationError {
-        this(new AllDefaultPossibilitiesBuilder(true), klass, suiteClasses);
+        this(new AllDefaultPossibilitiesBuilder(), klass, suiteClasses);
     }
 
     /**
diff --git a/src/main/java/org/junit/runners/model/FrameworkField.java b/src/main/java/org/junit/runners/model/FrameworkField.java
index 945e389..ea2b16f 100644
--- a/src/main/java/org/junit/runners/model/FrameworkField.java
+++ b/src/main/java/org/junit/runners/model/FrameworkField.java
@@ -14,12 +14,26 @@
 public class FrameworkField extends FrameworkMember<FrameworkField> {
     private final Field field;
 
-    FrameworkField(Field field) {
+    /**
+     * Returns a new {@code FrameworkField} for {@code field}.
+     *
+     * <p>Access relaxed to {@code public} since version 4.13.1.
+     */
+    public FrameworkField(Field field) {
         if (field == null) {
             throw new NullPointerException(
                     "FrameworkField cannot be created without an underlying field.");
         }
         this.field = field;
+
+        if (isPublic()) {
+            // This field could be a public field in a package-scope base class
+            try {
+                field.setAccessible(true);
+            } catch (SecurityException e) {
+                // We may get an IllegalAccessException when we try to access the field
+            }
+        }
     }
 
     @Override
@@ -41,6 +55,11 @@
     }
 
     @Override
+    boolean isBridgeMethod() {
+        return false;
+    }
+
+    @Override
     protected int getModifiers() {
         return field.getModifiers();
     }
diff --git a/src/main/java/org/junit/runners/model/FrameworkMember.java b/src/main/java/org/junit/runners/model/FrameworkMember.java
index 724f096..5634b3f 100644
--- a/src/main/java/org/junit/runners/model/FrameworkMember.java
+++ b/src/main/java/org/junit/runners/model/FrameworkMember.java
@@ -12,15 +12,29 @@
         Annotatable {
     abstract boolean isShadowedBy(T otherMember);
 
-    boolean isShadowedBy(List<T> members) {
-        for (T each : members) {
-            if (isShadowedBy(each)) {
-                return true;
+    T handlePossibleBridgeMethod(List<T> members) {
+        for (int i = members.size() - 1; i >=0; i--) {
+            T otherMember = members.get(i);
+            if (isShadowedBy(otherMember)) {
+                if (otherMember.isBridgeMethod()) {
+                    /*
+                     *  We need to return the previously-encountered bridge method
+                     *  because JUnit won't be able to call the parent method,
+                     *  because the parent class isn't public.
+                     */
+                    members.remove(i);
+                    return otherMember;
+                }
+                // We found a shadowed member that isn't a bridge method. Ignore it.
+                return null;
             }
         }
-        return false;
+        // No shadow or bridge method found. The caller should add *this* member.
+        return (T) this;
     }
 
+    abstract boolean isBridgeMethod();
+
     protected abstract int getModifiers();
 
     /**
diff --git a/src/main/java/org/junit/runners/model/FrameworkMethod.java b/src/main/java/org/junit/runners/model/FrameworkMethod.java
index 3580052..4471407 100644
--- a/src/main/java/org/junit/runners/model/FrameworkMethod.java
+++ b/src/main/java/org/junit/runners/model/FrameworkMethod.java
@@ -28,6 +28,15 @@
                     "FrameworkMethod cannot be created without an underlying method.");
         }
         this.method = method;
+
+        if (isPublic()) {
+            // This method could be a public method in a package-scope base class
+            try {
+                method.setAccessible(true);
+            } catch (SecurityException  e) {
+                // We may get an IllegalAccessException when we try to call the method
+            }
+        }
     }
 
     /**
@@ -149,6 +158,11 @@
     }
 
     @Override
+    boolean isBridgeMethod() {
+        return method.isBridge();
+    }
+
+    @Override
     public boolean equals(Object obj) {
         if (!FrameworkMethod.class.isInstance(obj)) {
             return false;
diff --git a/src/main/java/org/junit/runners/model/InitializationError.java b/src/main/java/org/junit/runners/model/InitializationError.java
index 841b565..dd9c8b3 100644
--- a/src/main/java/org/junit/runners/model/InitializationError.java
+++ b/src/main/java/org/junit/runners/model/InitializationError.java
@@ -14,7 +14,7 @@
     /*
      * We have to use the f prefix until the next major release to ensure
      * serialization compatibility. 
-     * See https://github.com/junit-team/junit/issues/976
+     * See https://github.com/junit-team/junit4/issues/976
      */
     private final List<Throwable> fErrors;
 
diff --git a/src/main/java/org/junit/runners/model/InvalidTestClassError.java b/src/main/java/org/junit/runners/model/InvalidTestClassError.java
new file mode 100644
index 0000000..57be610
--- /dev/null
+++ b/src/main/java/org/junit/runners/model/InvalidTestClassError.java
@@ -0,0 +1,39 @@
+package org.junit.runners.model;
+
+import java.util.List;
+
+/**
+ * Thrown by {@link org.junit.runner.Runner}s in case the class under test is not valid.
+ * <p>
+ * Its message conveniently lists all of the validation errors.
+ *
+ * @since 4.13
+ */
+public class InvalidTestClassError extends InitializationError {
+    private static final long serialVersionUID = 1L;
+
+    private final String message;
+
+    public InvalidTestClassError(Class<?> offendingTestClass, List<Throwable> validationErrors) {
+        super(validationErrors);
+        this.message = createMessage(offendingTestClass, validationErrors);
+    }
+
+    private static String createMessage(Class<?> testClass, List<Throwable> validationErrors) {
+        StringBuilder sb = new StringBuilder();
+        sb.append(String.format("Invalid test class '%s':", testClass.getName()));
+        int i = 1;
+        for (Throwable error : validationErrors) {
+            sb.append("\n  " + (i++) + ". " + error.getMessage());
+        }
+        return sb.toString();
+    }
+
+    /**
+     * @return a message with a list of all of the validation errors
+     */
+    @Override
+    public String getMessage() {
+        return message;
+    }
+}
diff --git a/src/main/java/org/junit/runners/model/MemberValueConsumer.java b/src/main/java/org/junit/runners/model/MemberValueConsumer.java
new file mode 100644
index 0000000..a6157bf
--- /dev/null
+++ b/src/main/java/org/junit/runners/model/MemberValueConsumer.java
@@ -0,0 +1,18 @@
+package org.junit.runners.model;
+
+/**
+ * Represents a receiver for values of annotated fields/methods together with the declaring member.
+ *
+ * @see TestClass#collectAnnotatedFieldValues(Object, Class, Class, MemberValueConsumer)
+ * @see TestClass#collectAnnotatedMethodValues(Object, Class, Class, MemberValueConsumer)
+ * @since 4.13
+ */
+public interface MemberValueConsumer<T> {
+    /**
+     * Receives the next value and its declaring member.
+     *
+     * @param member declaring member ({@link FrameworkMethod} or {@link FrameworkField})
+     * @param value the value of the next member
+     */
+    void accept(FrameworkMember<?> member, T value);
+}
diff --git a/src/main/java/org/junit/runners/model/MultipleFailureException.java b/src/main/java/org/junit/runners/model/MultipleFailureException.java
index 325c645..8e355a7 100644
--- a/src/main/java/org/junit/runners/model/MultipleFailureException.java
+++ b/src/main/java/org/junit/runners/model/MultipleFailureException.java
@@ -1,9 +1,13 @@
 package org.junit.runners.model;
 
+import java.io.PrintStream;
+import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 
+import org.junit.TestCouldNotBeSkippedException;
+import org.junit.internal.AssumptionViolatedException;
 import org.junit.internal.Throwables;
 
 /**
@@ -17,12 +21,22 @@
     /*
      * We have to use the f prefix until the next major release to ensure
      * serialization compatibility. 
-     * See https://github.com/junit-team/junit/issues/976
+     * See https://github.com/junit-team/junit4/issues/976
      */
     private final List<Throwable> fErrors;
 
     public MultipleFailureException(List<Throwable> errors) {
-        this.fErrors = new ArrayList<Throwable>(errors);
+        if (errors.isEmpty()) {
+            throw new IllegalArgumentException(
+                    "List of Throwables must not be empty");
+        }
+        this.fErrors = new ArrayList<Throwable>(errors.size());
+        for (Throwable error : errors) {
+            if (error instanceof AssumptionViolatedException) {
+                error = new TestCouldNotBeSkippedException((AssumptionViolatedException) error);
+            }
+            fErrors.add(error);
+        }
     }
 
     public List<Throwable> getFailures() {
@@ -34,11 +48,32 @@
         StringBuilder sb = new StringBuilder(
                 String.format("There were %d errors:", fErrors.size()));
         for (Throwable e : fErrors) {
-            sb.append(String.format("\n  %s(%s)", e.getClass().getName(), e.getMessage()));
+            sb.append(String.format("%n  %s(%s)", e.getClass().getName(), e.getMessage()));
         }
         return sb.toString();
     }
 
+    @Override
+    public void printStackTrace() {
+        for (Throwable e: fErrors) {
+            e.printStackTrace();
+        }
+    }
+    
+    @Override
+    public void printStackTrace(PrintStream s) {
+        for (Throwable e: fErrors) {
+            e.printStackTrace(s);
+        }
+    }
+    
+    @Override
+    public void printStackTrace(PrintWriter s) {
+        for (Throwable e: fErrors) {
+            e.printStackTrace(s);
+        }
+    }
+    
     /**
      * Asserts that a list of throwables is empty. If it isn't empty,
      * will throw {@link MultipleFailureException} (if there are
diff --git a/src/main/java/org/junit/runners/model/RunnerBuilder.java b/src/main/java/org/junit/runners/model/RunnerBuilder.java
index 7d3eee3..ba7c9e2 100644
--- a/src/main/java/org/junit/runners/model/RunnerBuilder.java
+++ b/src/main/java/org/junit/runners/model/RunnerBuilder.java
@@ -6,7 +6,11 @@
 import java.util.Set;
 
 import org.junit.internal.runners.ErrorReportingRunner;
+import org.junit.runner.Description;
+import org.junit.runner.OrderWith;
 import org.junit.runner.Runner;
+import org.junit.runner.manipulation.InvalidOrderingException;
+import org.junit.runner.manipulation.Ordering;
 
 /**
  * A RunnerBuilder is a strategy for constructing runners for classes.
@@ -49,19 +53,39 @@
     public abstract Runner runnerForClass(Class<?> testClass) throws Throwable;
 
     /**
-     * Always returns a runner, even if it is just one that prints an error instead of running tests.
+     * Always returns a runner for the given test class.
+     *
+     * <p>In case of an exception a runner will be returned that prints an error instead of running
+     * tests.
+     *
+     * <p>Note that some of the internal JUnit implementations of RunnerBuilder will return
+     * {@code null} from this method, but no RunnerBuilder passed to a Runner constructor will
+     * return {@code null} from this method.
      *
      * @param testClass class to be run
      * @return a Runner
      */
     public Runner safeRunnerForClass(Class<?> testClass) {
         try {
-            return runnerForClass(testClass);
+            Runner runner = runnerForClass(testClass);
+            if (runner != null) {
+                configureRunner(runner);
+            }
+            return runner;
         } catch (Throwable e) {
             return new ErrorReportingRunner(testClass, e);
         }
     }
 
+    private void configureRunner(Runner runner) throws InvalidOrderingException {
+        Description description = runner.getDescription();
+        OrderWith orderWith = description.getAnnotation(OrderWith.class);
+        if (orderWith != null) {
+            Ordering ordering = Ordering.definedBy(orderWith.value(), description);
+            ordering.apply(runner);
+        }
+    }
+
     Class<?> addParent(Class<?> parent) throws InitializationError {
         if (!parents.add(parent)) {
             throw new InitializationError(String.format("class '%s' (possibly indirectly) contains itself as a SuiteClass", parent.getName()));
@@ -96,7 +120,7 @@
     }
 
     private List<Runner> runners(Class<?>[] children) {
-        ArrayList<Runner> runners = new ArrayList<Runner>();
+        List<Runner> runners = new ArrayList<Runner>();
         for (Class<?> each : children) {
             Runner childRunner = safeRunnerForClass(each);
             if (childRunner != null) {
diff --git a/src/main/java/org/junit/runners/model/TestClass.java b/src/main/java/org/junit/runners/model/TestClass.java
old mode 100755
new mode 100644
index c8a544d..5962c2b
--- a/src/main/java/org/junit/runners/model/TestClass.java
+++ b/src/main/java/org/junit/runners/model/TestClass.java
@@ -84,20 +84,21 @@
         for (Annotation each : member.getAnnotations()) {
             Class<? extends Annotation> type = each.annotationType();
             List<T> members = getAnnotatedMembers(map, type, true);
-            if (member.isShadowedBy(members)) {
+            T memberToAdd = member.handlePossibleBridgeMethod(members);
+            if (memberToAdd == null) {
                 return;
             }
             if (runsTopToBottom(type)) {
-                members.add(0, member);
+                members.add(0, memberToAdd);
             } else {
-                members.add(member);
+                members.add(memberToAdd);
             }
         }
     }
 
     private static <T extends FrameworkMember<T>> Map<Class<? extends Annotation>, List<T>>
             makeDeeplyUnmodifiable(Map<Class<? extends Annotation>, List<T>> source) {
-        LinkedHashMap<Class<? extends Annotation>, List<T>> copy =
+        Map<Class<? extends Annotation>, List<T>> copy =
                 new LinkedHashMap<Class<? extends Annotation>, List<T>>();
         for (Map.Entry<Class<? extends Annotation>, List<T>> entry : source.entrySet()) {
             copy.put(entry.getKey(), Collections.unmodifiableList(entry.getValue()));
@@ -168,7 +169,7 @@
     }
 
     private static List<Class<?>> getSuperClasses(Class<?> testClass) {
-        ArrayList<Class<?>> results = new ArrayList<Class<?>>();
+        List<Class<?>> results = new ArrayList<Class<?>>();
         Class<?> current = testClass;
         while (current != null) {
             results.add(current);
@@ -224,24 +225,59 @@
 
     public <T> List<T> getAnnotatedFieldValues(Object test,
             Class<? extends Annotation> annotationClass, Class<T> valueClass) {
-        List<T> results = new ArrayList<T>();
+        final List<T> results = new ArrayList<T>();
+        collectAnnotatedFieldValues(test, annotationClass, valueClass,
+                new MemberValueConsumer<T>() {
+                    public void accept(FrameworkMember<?> member, T value) {
+                        results.add(value);
+                    }
+                });
+        return results;
+    }
+
+    /**
+     * Finds the fields annotated with the specified annotation and having the specified type,
+     * retrieves the values and passes those to the specified consumer.
+     *
+     * @since 4.13
+     */
+    public <T> void collectAnnotatedFieldValues(Object test,
+            Class<? extends Annotation> annotationClass, Class<T> valueClass,
+            MemberValueConsumer<T> consumer) {
         for (FrameworkField each : getAnnotatedFields(annotationClass)) {
             try {
                 Object fieldValue = each.get(test);
                 if (valueClass.isInstance(fieldValue)) {
-                    results.add(valueClass.cast(fieldValue));
+                    consumer.accept(each, valueClass.cast(fieldValue));
                 }
             } catch (IllegalAccessException e) {
                 throw new RuntimeException(
                         "How did getFields return a field we couldn't access?", e);
             }
         }
-        return results;
     }
 
     public <T> List<T> getAnnotatedMethodValues(Object test,
             Class<? extends Annotation> annotationClass, Class<T> valueClass) {
-        List<T> results = new ArrayList<T>();
+        final List<T> results = new ArrayList<T>();
+        collectAnnotatedMethodValues(test, annotationClass, valueClass,
+                new MemberValueConsumer<T>() {
+                    public void accept(FrameworkMember<?> member, T value) {
+                        results.add(value);
+                    }
+                });
+        return results;
+    }
+
+    /**
+     * Finds the methods annotated with the specified annotation and returning the specified type,
+     * invokes it and pass the return value to the specified consumer.
+     *
+     * @since 4.13
+     */
+    public <T> void collectAnnotatedMethodValues(Object test,
+            Class<? extends Annotation> annotationClass, Class<T> valueClass,
+            MemberValueConsumer<T> consumer) {
         for (FrameworkMethod each : getAnnotatedMethods(annotationClass)) {
             try {
                 /*
@@ -254,14 +290,13 @@
                  */
                 if (valueClass.isAssignableFrom(each.getReturnType())) {
                     Object fieldValue = each.invokeExplosively(test);
-                    results.add(valueClass.cast(fieldValue));
+                    consumer.accept(each, valueClass.cast(fieldValue));
                 }
             } catch (Throwable e) {
                 throw new RuntimeException(
                         "Exception in " + each.getName(), e);
             }
         }
-        return results;
     }
 
     public boolean isPublic() {
diff --git a/src/main/java/org/junit/runners/parameterized/BlockJUnit4ClassRunnerWithParameters.java b/src/main/java/org/junit/runners/parameterized/BlockJUnit4ClassRunnerWithParameters.java
index 1c49f84..5c70a75 100644
--- a/src/main/java/org/junit/runners/parameterized/BlockJUnit4ClassRunnerWithParameters.java
+++ b/src/main/java/org/junit/runners/parameterized/BlockJUnit4ClassRunnerWithParameters.java
@@ -4,8 +4,12 @@
 import java.lang.reflect.Field;
 import java.util.List;
 
+import org.junit.internal.runners.statements.RunAfters;
+import org.junit.internal.runners.statements.RunBefores;
+import org.junit.runner.RunWith;
 import org.junit.runner.notification.RunNotifier;
 import org.junit.runners.BlockJUnit4ClassRunner;
+import org.junit.runners.Parameterized;
 import org.junit.runners.Parameterized.Parameter;
 import org.junit.runners.model.FrameworkField;
 import org.junit.runners.model.FrameworkMethod;
@@ -18,13 +22,17 @@
  */
 public class BlockJUnit4ClassRunnerWithParameters extends
         BlockJUnit4ClassRunner {
+    private enum InjectionType {
+        CONSTRUCTOR, FIELD
+    }
+
     private final Object[] parameters;
 
     private final String name;
 
     public BlockJUnit4ClassRunnerWithParameters(TestWithParameters test)
             throws InitializationError {
-        super(test.getTestClass().getJavaClass());
+        super(test.getTestClass());
         parameters = test.getParameters().toArray(
                 new Object[test.getParameters().size()]);
         name = test.getName();
@@ -32,10 +40,15 @@
 
     @Override
     public Object createTest() throws Exception {
-        if (fieldsAreAnnotated()) {
-            return createTestUsingFieldInjection();
-        } else {
-            return createTestUsingConstructorInjection();
+        InjectionType injectionType = getInjectionType();
+        switch (injectionType) {
+            case CONSTRUCTOR:
+                return createTestUsingConstructorInjection();
+            case FIELD:
+                return createTestUsingFieldInjection();
+            default:
+                throw new IllegalStateException("The injection type "
+                        + injectionType + " is not supported.");
         }
     }
 
@@ -60,6 +73,13 @@
             int index = annotation.value();
             try {
                 field.set(testClassInstance, parameters[index]);
+            } catch (IllegalAccessException e) {
+                IllegalAccessException wrappedException = new IllegalAccessException(
+                        "Cannot set parameter '" + field.getName()
+                                + "'. Ensure that the field '" + field.getName()
+                                + "' is public.");
+                wrappedException.initCause(e);
+                throw wrappedException;
             } catch (IllegalArgumentException iare) {
                 throw new Exception(getTestClass().getName()
                         + ": Trying to set " + field.getName()
@@ -86,7 +106,7 @@
     @Override
     protected void validateConstructor(List<Throwable> errors) {
         validateOnlyOneConstructor(errors);
-        if (fieldsAreAnnotated()) {
+        if (getInjectionType() != InjectionType.CONSTRUCTOR) {
             validateZeroArgConstructor(errors);
         }
     }
@@ -94,7 +114,7 @@
     @Override
     protected void validateFields(List<Throwable> errors) {
         super.validateFields(errors);
-        if (fieldsAreAnnotated()) {
+        if (getInjectionType() == InjectionType.FIELD) {
             List<FrameworkField> annotatedFieldsByParameter = getAnnotatedFieldsByParameter();
             int[] usedIndices = new int[annotatedFieldsByParameter.size()];
             for (FrameworkField each : annotatedFieldsByParameter) {
@@ -125,18 +145,74 @@
 
     @Override
     protected Statement classBlock(RunNotifier notifier) {
-        return childrenInvoker(notifier);
+        Statement statement = childrenInvoker(notifier);
+        statement = withBeforeParams(statement);
+        statement = withAfterParams(statement);
+        return statement;
+    }
+
+    private Statement withBeforeParams(Statement statement) {
+        List<FrameworkMethod> befores = getTestClass()
+                .getAnnotatedMethods(Parameterized.BeforeParam.class);
+        return befores.isEmpty() ? statement : new RunBeforeParams(statement, befores);
+    }
+
+    private class RunBeforeParams extends RunBefores {
+        RunBeforeParams(Statement next, List<FrameworkMethod> befores) {
+            super(next, befores, null);
+        }
+
+        @Override
+        protected void invokeMethod(FrameworkMethod method) throws Throwable {
+            int paramCount = method.getMethod().getParameterTypes().length;
+            method.invokeExplosively(null, paramCount == 0 ? (Object[]) null : parameters);
+        }
+    }
+
+    private Statement withAfterParams(Statement statement) {
+        List<FrameworkMethod> afters = getTestClass()
+                .getAnnotatedMethods(Parameterized.AfterParam.class);
+        return afters.isEmpty() ? statement : new RunAfterParams(statement, afters);
+    }
+
+    private class RunAfterParams extends RunAfters {
+        RunAfterParams(Statement next, List<FrameworkMethod> afters) {
+            super(next, afters, null);
+        }
+
+        @Override
+        protected void invokeMethod(FrameworkMethod method) throws Throwable {
+            int paramCount = method.getMethod().getParameterTypes().length;
+            method.invokeExplosively(null, paramCount == 0 ? (Object[]) null : parameters);
+        }
     }
 
     @Override
     protected Annotation[] getRunnerAnnotations() {
-        return new Annotation[0];
+        Annotation[] allAnnotations = super.getRunnerAnnotations();
+        Annotation[] annotationsWithoutRunWith = new Annotation[allAnnotations.length - 1];
+        int i = 0;
+        for (Annotation annotation: allAnnotations) {
+            if (!annotation.annotationType().equals(RunWith.class)) {
+                annotationsWithoutRunWith[i] = annotation;
+                ++i;
+            }
+        }
+        return annotationsWithoutRunWith;
     }
 
     private List<FrameworkField> getAnnotatedFieldsByParameter() {
         return getTestClass().getAnnotatedFields(Parameter.class);
     }
 
+    private InjectionType getInjectionType() {
+        if (fieldsAreAnnotated()) {
+            return InjectionType.FIELD;
+        } else {
+            return InjectionType.CONSTRUCTOR;
+        }
+    }
+
     private boolean fieldsAreAnnotated() {
         return !getAnnotatedFieldsByParameter().isEmpty();
     }
diff --git a/src/main/java/org/junit/runners/parameterized/ParametersRunnerFactory.java b/src/main/java/org/junit/runners/parameterized/ParametersRunnerFactory.java
index 16ea1f3..8123e83 100644
--- a/src/main/java/org/junit/runners/parameterized/ParametersRunnerFactory.java
+++ b/src/main/java/org/junit/runners/parameterized/ParametersRunnerFactory.java
@@ -4,7 +4,7 @@
 import org.junit.runners.model.InitializationError;
 
 /**
- * A {@code ParameterizedRunnerFactory} creates a runner for a single
+ * A {@code ParametersRunnerFactory} creates a runner for a single
  * {@link TestWithParameters}.
  * 
  * @since 4.12
diff --git a/src/main/java/org/junit/runners/parameterized/TestWithParameters.java b/src/main/java/org/junit/runners/parameterized/TestWithParameters.java
index 1b86644..1c5abd9 100644
--- a/src/main/java/org/junit/runners/parameterized/TestWithParameters.java
+++ b/src/main/java/org/junit/runners/parameterized/TestWithParameters.java
@@ -1,6 +1,7 @@
 package org.junit.runners.parameterized;
 
 import static java.util.Collections.unmodifiableList;
+import static org.junit.internal.Checks.notNull;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -73,10 +74,4 @@
         return testClass.getName() + " '" + name + "' with parameters "
                 + parameters;
     }
-
-    private static void notNull(Object value, String message) {
-        if (value == null) {
-            throw new NullPointerException(message);
-        }
-    }
 }
diff --git a/src/main/java/org/junit/validator/AnnotationValidatorFactory.java b/src/main/java/org/junit/validator/AnnotationValidatorFactory.java
index 7309fdd..fb2460d 100644
--- a/src/main/java/org/junit/validator/AnnotationValidatorFactory.java
+++ b/src/main/java/org/junit/validator/AnnotationValidatorFactory.java
@@ -27,9 +27,6 @@
         }
 
         Class<? extends AnnotationValidator> clazz = validateWithAnnotation.value();
-        if (clazz == null) {
-            throw new IllegalArgumentException("Can't create validator, value is null in annotation " + validateWithAnnotation.getClass().getName());
-        }
         try {
             AnnotationValidator annotationValidator = clazz.newInstance();
             VALIDATORS_FOR_ANNOTATION_TYPES.putIfAbsent(validateWithAnnotation, annotationValidator);
diff --git a/src/main/java/org/junit/validator/AnnotationsValidator.java b/src/main/java/org/junit/validator/AnnotationsValidator.java
index 30f54a6..d8b5840 100644
--- a/src/main/java/org/junit/validator/AnnotationsValidator.java
+++ b/src/main/java/org/junit/validator/AnnotationsValidator.java
@@ -40,7 +40,7 @@
         return validationErrors;
     }
 
-    private static abstract class AnnotatableValidator<T extends Annotatable> {
+    private abstract static class AnnotatableValidator<T extends Annotatable> {
         private static final AnnotationValidatorFactory ANNOTATION_VALIDATOR_FACTORY = new AnnotationValidatorFactory();
 
         abstract Iterable<T> getAnnotatablesForTestClass(TestClass testClass);
@@ -116,5 +116,5 @@
                 AnnotationValidator validator, FrameworkField field) {
             return validator.validateAnnotatedField(field);
         }
-    };
+    }
 }
diff --git a/src/main/java/org/junit/validator/TestClassValidator.java b/src/main/java/org/junit/validator/TestClassValidator.java
index 43cb787..ba5e892 100644
--- a/src/main/java/org/junit/validator/TestClassValidator.java
+++ b/src/main/java/org/junit/validator/TestClassValidator.java
@@ -17,5 +17,5 @@
      *            the {@link TestClass} that is validated.
      * @return the validation errors found by the validator.
      */
-    public List<Exception> validateTestClass(TestClass testClass);
+    List<Exception> validateTestClass(TestClass testClass);
 }
diff --git a/src/main/java/org/junit/validator/ValidateWith.java b/src/main/java/org/junit/validator/ValidateWith.java
index 03d7906..3725db8 100644
--- a/src/main/java/org/junit/validator/ValidateWith.java
+++ b/src/main/java/org/junit/validator/ValidateWith.java
@@ -1,8 +1,10 @@
 package org.junit.validator;
 
+import java.lang.annotation.ElementType;
 import java.lang.annotation.Inherited;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
 
 /**
  * Allows for an {@link AnnotationValidator} to be attached to an annotation.
@@ -13,6 +15,7 @@
  * @since 4.12
  */
 @Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.ANNOTATION_TYPE)
 @Inherited
 public @interface ValidateWith {
     Class<? extends AnnotationValidator> value();
diff --git a/version b/version
index 8d39259..650edfe 100644
--- a/version
+++ b/version
@@ -1 +1 @@
-4.10
+4.13.2