diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
new file mode 100644
index 000000000000..65bdbaa62aa3
--- /dev/null
+++ b/.github/workflows/main.yml
@@ -0,0 +1,48 @@
+name: CI
+
+on:
+ push:
+ branches:
+ - main
+ pull_request:
+ branches:
+ - '*'
+
+jobs:
+
+ build-and-verify:
+ name: Build and verify (JDK ${{ matrix.java }})
+ runs-on: ubuntu-latest
+ strategy:
+ fail-fast: false
+ matrix:
+ java: [6, 8, 11, 15, 17-ea]
+ steps:
+ - uses: actions/checkout@v2
+ - name: Download Maven # Download with default JDK because OpenJDK 6 does not support TLS 1.2
+ run: ./mvnw --version
+ - name: Set up JDK
+ uses: actions/setup-java@v1
+ with:
+ java-version: ${{ matrix.java }}
+ - name: Build and verify
+ run: ./mvnw verify javadoc:javadoc site:site --batch-mode --errors --settings .github/workflows/settings.xml
+
+ publish-snapshots:
+ name: Publish snapshot artifacts
+ if: github.event_name == 'push' && github.repository == 'junit-team/junit4' && github.ref == 'refs/heads/main'
+ needs: build-and-verify
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v2
+ - name: Download Maven # Download with default JDK because OpenJDK 6 does not support TLS 1.2
+ run: ./mvnw --version
+ - name: Set up JDK
+ uses: actions/setup-java@v1
+ with:
+ java-version: 6
+ - name: Publish snapshot artifacts
+ env:
+ OSSRH_USERNAME: ${{ secrets.OSSRH_USERNAME }}
+ OSSRH_PASSWORD: ${{ secrets.OSSRH_PASSWORD }}
+ run: ./mvnw deploy --batch-mode --errors --activate-profiles generate-docs --settings .github/workflows/settings.xml
diff --git a/.travis.settings.xml b/.github/workflows/settings.xml
similarity index 100%
rename from .travis.settings.xml
rename to .github/workflows/settings.xml
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index 5b1744397f29..000000000000
--- a/.travis.yml
+++ /dev/null
@@ -1,69 +0,0 @@
-dist: trusty
-
-language: java
-
-script: ./mvnw verify javadoc:javadoc site:site
-
-install:
-- ./mvnw --version
-
-stages:
- - test
- - name: deploy
- if: (branch = main) AND (NOT type IN (pull_request))
-
-jobs:
- include:
- - name: Java 6
- env: JDK=openjdk6
- addons:
- apt:
- packages:
- - openjdk-6-jdk
- install:
- # Download dependencies with JDK 8 because Mave Central supports
- # TLS 1.2 only but OpenJDK 6 does not.
- - export ORIGINAL_JAVA_HOME=$JAVA_HOME
- - jdk_switcher use oraclejdk8
- - ./mvnw test -DskipTests
- # Delete all files created with JDK 8
- - ./mvnw clean
- # Restore desired JDK
- - export JAVA_HOME=$ORIGINAL_JAVA_HOME
- - jdk_switcher use openjdk6
- - ./mvnw --version
- - name: Java 7
- jdk: openjdk7
- - name: Java 8
- jdk: oraclejdk8
- - name: Java 9
- jdk: oraclejdk9
- - name: Java 10
- jdk: openjdk10
- - name: Java 11
- jdk: openjdk11
- - stage: deploy
- name: "Publish snapshot artifacts"
- addons:
- apt:
- packages:
- - openjdk-6-jdk
- install:
- # Download dependencies with JDK 8 because Mave Central supports
- # TLS 1.2 only but OpenJDK 6 does not.
- - export ORIGINAL_JAVA_HOME=$JAVA_HOME
- - jdk_switcher use oraclejdk8
- - ./mvnw test -DskipTests
- # Delete all files created with JDK 8
- - ./mvnw clean
- # Restore desired JDK
- - export JAVA_HOME=$ORIGINAL_JAVA_HOME
- - jdk_switcher use openjdk6
- - ./mvnw --version
- env:
- - JDK=openjdk6
- # OSSRH_USERNAME
- - secure: griGZYDtqDMRUaYex/uAnpkWIQ/yodM6IOn4G8izWKpyGLeCxyXBG0FDcVo81xRq/9mMevj2idyW/xNP/HAQ45G4pyJUk/vTSMkNslzVjr7OBEtQQCN8XahSaOO0l0CJ5lzA6LdwWg7uDaf9znqZ0slt81u0S1NJmUZyYeUEim0=
- # OSSRH_PASSWORD
- - secure: EM7Z2M09HvLJXYJaeD/YmeF5A6tqavG2tBBeDcFZ7C6k0AI/wApe882pEMMoUG06xufKfSlt7WFJxoyU3M+fPOpeK5qZpJQxsHWnNJwbcbKzqMpM9mDsgIL9rtAvm9MuIIbIY2spiT0Cx3sHdh5qofaJHPL/u8Or5L9tE8FV1ew=
- script: ./mvnw deploy --batch-mode --activate-profiles generate-docs --settings .travis.settings.xml
diff --git a/README.md b/README.md
index f73f89ca5ed0..739347df5078 100644
--- a/README.md
+++ b/README.md
@@ -6,4 +6,4 @@ For more information, please visit:
* [Download and Install guide](https://github.com/junit-team/junit4/wiki/Download-and-Install)
* [Getting Started](https://github.com/junit-team/junit4/wiki/Getting-started)
-[](https://travis-ci.org/junit-team/junit4)
+[](https://github.com/junit-team/junit4/actions)
diff --git a/doc/ReleaseNotes4.13.1.md b/doc/ReleaseNotes4.13.1.md
index ab44490622c6..0305102d27f4 100644
--- a/doc/ReleaseNotes4.13.1.md
+++ b/doc/ReleaseNotes4.13.1.md
@@ -1,5 +1,11 @@
## Summary of changes in version 4.13.1
+# Rules
+
+### Security fix: `TemporaryFolder` now limits access to temporary folders on Java 1.7 or later
+
+A local information disclosure vulnerability in `TemporaryFolder` has been fixed. See the published [security advisory](https://github.com/junit-team/junit4/security/advisories/GHSA-269g-pwp5-87pp) for details.
+
# Test Runners
### [Pull request #1669:](https://github.com/junit-team/junit/pull/1669) Make `FrameworkField` constructor public
diff --git a/doc/ReleaseNotes4.13.2.md b/doc/ReleaseNotes4.13.2.md
new file mode 100644
index 000000000000..ba801396d1a4
--- /dev/null
+++ b/doc/ReleaseNotes4.13.2.md
@@ -0,0 +1,38 @@
+## Summary of changes in version 4.13.2
+
+# Rules
+
+### [Pull request #1687:](https://github.com/junit-team/junit/pull/1687) Mark ThreadGroups created by FailOnTimeout as daemon groups
+
+In JUnit 4.13 ([pull request #1517](https://github.com/junit-team/junit4/pull/1517)) an attempt was
+made to fix leakage of the `ThreadGroup` instances created when a test is run with a timeout. That
+change explicitly destroyed the `ThreadGroup` that was created for the time-limited test. Numerous
+people reported problems that were caused by explicitly destroying the `ThreadGroup`.
+
+In this change, the code was updated to call `ThreadGroup.setDaemon(true)` instead of destroying the
+ThreadGroup.
+
+### [Pull request $1691:](https://github.com/junit-team/junit/pull/1691) Only create ThreadGroups if FailOnTimeout.lookForStuckThread is true.
+
+In JUnit 4.12 ([pull request #742](https://github.com/junit-team/junit4/pull/742)) the `Timeout`
+Rule was updated to optionally display the stacktrace of the thread that appears to be stuck
+(enabled on an opt-in basis by passing `true` to `Timeout.Builder.lookForStuckThread(boolean)`).
+When that change was made, time-limited tests were changed to start the new thread in a new
+`ThreadGroup`, even if the test did not call `lookForStuckThread()`. This subtle change in
+behavior resulted in visible behavior changes to some tests (for example, tests of code that uses
+`java.beans.ThreadGroupContext`).
+
+In this change, the code is updated to only create a new `ThreadGroup` if the caller calls
+`Timeout.Builder.lookForStuckThread(true)`. Tests with timeouts that do not make this call will
+behave as they did in JUnit 4.11 (and more similar to tests that do not have a timeout). This
+unfortunately could result in visible changes of tests written or updated since the 4.12
+release. If this change adversely affects your tests, you can create the `Timeout` rule via the
+builder and call `Timeout.Builder.lookForStuckThread(true)`.
+
+# Exceptions
+
+### [Pull request #1654:](https://github.com/junit-team/junit/pull/1654) Fix for issue #1192: NotSerializableException with AssumptionViolatedException
+
+This change fixes an issue where `AssumptionViolatedException` instances could not be serialized
+if they were created with a constructor that takes in an `org.hamcrest.Matcher` instance (these
+constructors are used if you use one of the `assumeThat()` methods in `org.junit.Assume`).
diff --git a/pom.xml b/pom.xml
index 428715884b4e..38be96092f24 100644
--- a/pom.xml
+++ b/pom.xml
@@ -4,7 +4,7 @@
junit
junit
- 4.13.1
+ 4.13.2
JUnit
JUnit is a unit testing framework for Java, created by Erich Gamma and Kent Beck.
@@ -64,15 +64,15 @@
scm:git:git://github.com/junit-team/junit4.git
scm:git:git@github.com:junit-team/junit4.git
https://github.com/junit-team/junit4
- r4.13.1
+ r4.13.2
github
https://github.com/junit-team/junit4/issues
- travis
- https://travis-ci.org/junit-team/junit4
+ github
+ https://github.com/junit-team/junit4/actions
https://github.com/junit-team/junit4/wiki/Download-and-Install
@@ -96,6 +96,9 @@
1.5
2.19.1
1.3
+ 1.4
+ 2.6
+ 2.10.3
ISO-8859-1
67893CC4
@@ -147,7 +150,7 @@
the project, requires only release versions of dependencies of other artifacts.
-->
maven-enforcer-plugin
- 1.4
+ ${enforcerPluginVersion}
enforce-versions
@@ -286,7 +289,7 @@
in jar archive target/junit-*-javadoc.jar.
-->
maven-javadoc-plugin
- 2.10.3
+ ${javadocPluginVersion}
${basedir}/src/main/javadoc/stylesheet.css
protected
@@ -345,7 +348,7 @@
maven-jar-plugin
- 2.6
+ ${jarPluginVersion}
false
@@ -408,7 +411,7 @@
maven-javadoc-plugin
- 2.10.3
+ ${javadocPluginVersion}
javadoc/latest
${basedir}/src/main/javadoc/stylesheet.css
@@ -556,7 +559,7 @@
java9
- [1.9,)
+ [1.9,12)
@@ -583,5 +586,48 @@
+
+ java12
+
+ [12,)
+
+
+
+ 1.7
+ 3.0.0-M3
+ 3.2.0
+ 3.2.0
+
+
+
+
+ maven-javadoc-plugin
+
+ 1.7
+ false
+
+
+
+ maven-compiler-plugin
+
+
+ -Xdoclint:none
+
+
+
+
+
+
+
+
+ maven-javadoc-plugin
+
+ 1.7
+ false
+
+
+
+
+
diff --git a/src/main/java/junit/extensions/ActiveTestSuite.java b/src/main/java/junit/extensions/ActiveTestSuite.java
index 95c5e2e71062..6f0f99dad04e 100644
--- a/src/main/java/junit/extensions/ActiveTestSuite.java
+++ b/src/main/java/junit/extensions/ActiveTestSuite.java
@@ -63,7 +63,7 @@ synchronized void waitUntilFinished() {
}
}
- synchronized public void runFinished() {
+ public synchronized void runFinished() {
fActiveTestDeathCount++;
notifyAll();
}
diff --git a/src/main/java/junit/framework/Assert.java b/src/main/java/junit/framework/Assert.java
index d10cdb4247b6..43482a16b6f2 100644
--- a/src/main/java/junit/framework/Assert.java
+++ b/src/main/java/junit/framework/Assert.java
@@ -17,7 +17,7 @@ protected Assert() {
* 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 @@ static public void assertTrue(String message, boolean condition) {
* 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 @@ static public void assertTrue(boolean condition) {
* 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 @@ static public void assertFalse(String message, boolean condition) {
* 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 @@ static public void fail(String message) {
/**
* Fails a test with no message.
*/
- static public void fail() {
+ public static void fail() {
fail(null);
}
@@ -68,7 +68,7 @@ static public void fail() {
* 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 @@ static public void assertEquals(String message, Object expected, Object actual)
* 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 @@ static public void assertEquals(String message, String expected, String actual)
/**
* 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,7 +112,7 @@ static public void assertEquals(String expected, String actual) {
* 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;
}
@@ -125,7 +125,7 @@ static public void assertEquals(String message, double expected, double actual,
* 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,7 +134,7 @@ static public void assertEquals(double expected, double actual, double delta) {
* 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;
}
@@ -147,7 +147,7 @@ static public void assertEquals(String message, float expected, float actual, fl
* 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 @@ static public void assertEquals(float expected, float actual, float delta) {
* 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 @@ static public void assertEquals(long expected, long actual) {
* 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 @@ static public void assertEquals(boolean expected, boolean actual) {
* 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 @@ static public void assertEquals(byte expected, byte actual) {
* 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 @@ static public void assertEquals(char expected, char actual) {
* 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 @@ static public void assertEquals(short expected, short actual) {
* 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 @@ static public void assertNotNull(Object object) {
* 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 @@ static public void assertNotNull(String message, Object object) {
*
* @param object Object to check or null
*/
- static public void assertNull(Object object) {
+ public static void assertNull(Object object) {
if (object != null) {
assertNull("Expected: but was: " + object.toString(), object);
}
@@ -273,7 +273,7 @@ static public void assertNull(Object object) {
* 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 @@ static public void assertNull(String message, Object object) {
* 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 @@ static public void assertSame(String message, Object expected, Object actual) {
* 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 @@ static public void assertSame(Object expected, Object actual) {
* 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 @@ static public void assertNotSame(String message, Object expected, Object actual)
* 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/runner/Version.java b/src/main/java/junit/runner/Version.java
index 9f263840e40f..bb12a70a95aa 100644
--- a/src/main/java/junit/runner/Version.java
+++ b/src/main/java/junit/runner/Version.java
@@ -9,7 +9,7 @@ private Version() {
}
public static String id() {
- return "4.13.1-SNAPSHOT";
+ return "4.13.2-SNAPSHOT";
}
public static void main(String[] args) {
diff --git a/src/main/java/org/junit/experimental/results/ResultMatchers.java b/src/main/java/org/junit/experimental/results/ResultMatchers.java
index e111093150c1..92f2e6b0482c 100644
--- a/src/main/java/org/junit/experimental/results/ResultMatchers.java
+++ b/src/main/java/org/junit/experimental/results/ResultMatchers.java
@@ -4,7 +4,6 @@
import org.hamcrest.Description;
import org.hamcrest.Matcher;
import org.hamcrest.TypeSafeMatcher;
-import org.junit.runner.notification.Failure;
/**
* Matchers on a PrintableResult, to enable JUnit self-tests.
diff --git a/src/main/java/org/junit/internal/AssumptionViolatedException.java b/src/main/java/org/junit/internal/AssumptionViolatedException.java
index 15c27af1b279..0e79b562f5f2 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;
@@ -108,4 +111,29 @@ public void describeTo(Description description) {
}
}
}
+
+ /**
+ * 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/SerializableMatcherDescription.java b/src/main/java/org/junit/internal/SerializableMatcherDescription.java
new file mode 100644
index 000000000000..e0365572001c
--- /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 extends BaseMatcher implements Serializable {
+
+ private final String matcherDescription;
+
+ private SerializableMatcherDescription(Matcher 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 Matcher asSerializableMatcher(Matcher matcher) {
+ if (matcher == null || matcher instanceof Serializable) {
+ return matcher;
+ } else {
+ return new SerializableMatcherDescription(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 000000000000..4d055d7a4019
--- /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/Throwables.java b/src/main/java/org/junit/internal/Throwables.java
index 67d6b2bc06ec..3f0f7a33b051 100644
--- a/src/main/java/org/junit/internal/Throwables.java
+++ b/src/main/java/org/junit/internal/Throwables.java
@@ -232,7 +232,10 @@ public final State processStackTraceElement(StackTraceElement element) {
"org.junit.runners.",
"org.junit.experimental.runners.",
"org.junit.internal.",
- "junit.",
+ "junit.extensions",
+ "junit.framework",
+ "junit.runner",
+ "junit.textui",
};
private static final String[] TEST_FRAMEWORK_TEST_METHOD_NAME_PREFIXES = {
diff --git a/src/main/java/org/junit/internal/runners/statements/FailOnTimeout.java b/src/main/java/org/junit/internal/runners/statements/FailOnTimeout.java
index 94c12e6e9770..9362cc168965 100644
--- a/src/main/java/org/junit/internal/runners/statements/FailOnTimeout.java
+++ b/src/main/java/org/junit/internal/runners/statements/FailOnTimeout.java
@@ -120,29 +120,40 @@ public FailOnTimeout build(Statement statement) {
public void evaluate() throws Throwable {
CallableStatement callable = new CallableStatement();
FutureTask task = new FutureTask(callable);
- ThreadGroup threadGroup = new ThreadGroup("FailOnTimeoutGroup");
+ ThreadGroup threadGroup = threadGroupForNewThread();
Thread thread = new Thread(threadGroup, task, "Time-limited test");
- try {
- thread.setDaemon(true);
- thread.start();
- callable.awaitStarted();
- Throwable throwable = getResult(task, thread);
- if (throwable != null) {
- throw throwable;
- }
- } finally {
- try {
- thread.join(1);
- } catch (InterruptedException e) {
- Thread.currentThread().interrupt();
- }
+ thread.setDaemon(true);
+ thread.start();
+ callable.awaitStarted();
+ Throwable throwable = getResult(task, thread);
+ if (throwable != null) {
+ throw throwable;
+ }
+ }
+
+ private ThreadGroup threadGroupForNewThread() {
+ if (!lookForStuckThread) {
+ // Use the default ThreadGroup (usually the one from the current
+ // thread).
+ return null;
+ }
+
+ // Create the thread in a new ThreadGroup, so if the time-limited thread
+ // becomes stuck, getStuckThread() can find the thread likely to be the
+ // culprit.
+ ThreadGroup threadGroup = new ThreadGroup("FailOnTimeoutGroup");
+ if (!threadGroup.isDaemon()) {
+ // Mark the new ThreadGroup as a daemon thread group, so it will be
+ // destroyed after the time-limited thread completes. By ensuring the
+ // ThreadGroup is destroyed, any data associated with the ThreadGroup
+ // (ex: via java.beans.ThreadGroupContext) is destroyed.
try {
- threadGroup.destroy();
- } catch (IllegalThreadStateException e) {
- // If a thread from the group is still alive, the ThreadGroup cannot be destroyed.
- // Swallow the exception to keep the same behavior prior to this change.
+ threadGroup.setDaemon(true);
+ } catch (SecurityException e) {
+ // Swallow the exception to keep the same behavior as in JUnit 4.12.
}
}
+ return threadGroup;
}
/**
diff --git a/src/main/java/org/junit/runner/notification/RunNotifier.java b/src/main/java/org/junit/runner/notification/RunNotifier.java
index 8b686cdf287a..752fa3bdf6ac 100644
--- a/src/main/java/org/junit/runner/notification/RunNotifier.java
+++ b/src/main/java/org/junit/runner/notification/RunNotifier.java
@@ -78,7 +78,7 @@ void run() {
fireTestFailures(safeListeners, failures);
}
- abstract protected void notifyListener(RunListener each) throws Exception;
+ protected abstract void notifyListener(RunListener each) throws Exception;
}
/**
diff --git a/src/main/java/org/junit/runners/model/FrameworkField.java b/src/main/java/org/junit/runners/model/FrameworkField.java
index 1f8a101418fb..ea2b16f8c4ae 100644
--- a/src/main/java/org/junit/runners/model/FrameworkField.java
+++ b/src/main/java/org/junit/runners/model/FrameworkField.java
@@ -2,7 +2,6 @@
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
-import java.util.List;
import org.junit.runners.BlockJUnit4ClassRunner;
diff --git a/src/main/java/org/junit/validator/AnnotationsValidator.java b/src/main/java/org/junit/validator/AnnotationsValidator.java
index 44d99d2a2f8d..d8b58404f9a5 100644
--- a/src/main/java/org/junit/validator/AnnotationsValidator.java
+++ b/src/main/java/org/junit/validator/AnnotationsValidator.java
@@ -40,7 +40,7 @@ public List validateTestClass(TestClass testClass) {
return validationErrors;
}
- private static abstract class AnnotatableValidator {
+ private abstract static class AnnotatableValidator {
private static final AnnotationValidatorFactory ANNOTATION_VALIDATOR_FACTORY = new AnnotationValidatorFactory();
abstract Iterable getAnnotatablesForTestClass(TestClass testClass);
diff --git a/src/test/java/junit/tests/SampleJUnit3Tests.java b/src/test/java/junit/tests/SampleJUnit3Tests.java
new file mode 100644
index 000000000000..46f996b3da3a
--- /dev/null
+++ b/src/test/java/junit/tests/SampleJUnit3Tests.java
@@ -0,0 +1,51 @@
+package junit.tests;
+
+import junit.framework.TestCase;
+
+/**
+ * Container for sample JUnit3-style tests used in integration tests.
+ */
+public class SampleJUnit3Tests {
+
+ public static class TestWithOneThrowingTestMethod extends TestCase {
+
+ public void testAlwaysThrows() {
+ new FakeClassUnderTest().throwsExceptionWithoutCause();
+ }
+ }
+
+ public static class TestWithThrowingSetUpMethod extends TestCase {
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ new FakeClassUnderTest().throwsExceptionWithoutCause();
+ }
+
+ public void testAlwaysPasses() {
+ }
+ }
+
+ private static class FakeClassUnderTest {
+
+ public void throwsExceptionWithCause() {
+ doThrowExceptionWithCause();
+ }
+
+ public void throwsExceptionWithoutCause() {
+ doThrowExceptionWithoutCause();
+ }
+
+ private void doThrowExceptionWithCause() {
+ try {
+ throwsExceptionWithoutCause();
+ } catch (Exception e) {
+ throw new RuntimeException("outer", e);
+ }
+ }
+
+ private void doThrowExceptionWithoutCause() {
+ throw new RuntimeException("cause");
+ }
+ }
+}
diff --git a/src/test/java/junit/tests/framework/DoublePrecisionAssertTest.java b/src/test/java/junit/tests/framework/DoublePrecisionAssertTest.java
index 439cc983dd00..f4161091ec14 100644
--- a/src/test/java/junit/tests/framework/DoublePrecisionAssertTest.java
+++ b/src/test/java/junit/tests/framework/DoublePrecisionAssertTest.java
@@ -11,17 +11,19 @@ public class DoublePrecisionAssertTest extends TestCase {
public void testAssertEqualsNaNFails() {
try {
assertEquals(1.234, Double.NaN, 0.0);
- fail();
} catch (AssertionFailedError e) {
+ return;
}
+ fail();
}
public void testAssertNaNEqualsFails() {
try {
assertEquals(Double.NaN, 1.234, 0.0);
- fail();
} catch (AssertionFailedError e) {
+ return;
}
+ fail();
}
public void testAssertNaNEqualsNaN() {
@@ -31,17 +33,19 @@ public void testAssertNaNEqualsNaN() {
public void testAssertPosInfinityNotEqualsNegInfinity() {
try {
assertEquals(Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY, 0.0);
- fail();
} catch (AssertionFailedError e) {
+ return;
}
+ fail();
}
public void testAssertPosInfinityNotEquals() {
try {
assertEquals(Double.POSITIVE_INFINITY, 1.23, 0.0);
- fail();
} catch (AssertionFailedError e) {
+ return;
}
+ fail();
}
public void testAssertPosInfinityEqualsInfinity() {
diff --git a/src/test/java/junit/tests/framework/FloatAssertTest.java b/src/test/java/junit/tests/framework/FloatAssertTest.java
index d390f0b19cf2..aeae9443d80d 100644
--- a/src/test/java/junit/tests/framework/FloatAssertTest.java
+++ b/src/test/java/junit/tests/framework/FloatAssertTest.java
@@ -11,17 +11,19 @@ public class FloatAssertTest extends TestCase {
public void testAssertEqualsNaNFails() {
try {
assertEquals(1.234f, Float.NaN, 0.0);
- fail();
} catch (AssertionFailedError e) {
+ return;
}
+ fail();
}
public void testAssertNaNEqualsFails() {
try {
assertEquals(Float.NaN, 1.234f, 0.0);
- fail();
} catch (AssertionFailedError e) {
+ return;
}
+ fail();
}
public void testAssertNaNEqualsNaN() {
@@ -31,17 +33,19 @@ public void testAssertNaNEqualsNaN() {
public void testAssertPosInfinityNotEqualsNegInfinity() {
try {
assertEquals(Float.POSITIVE_INFINITY, Float.NEGATIVE_INFINITY, 0.0);
- fail();
} catch (AssertionFailedError e) {
+ return;
}
+ fail();
}
public void testAssertPosInfinityNotEquals() {
try {
assertEquals(Float.POSITIVE_INFINITY, 1.23f, 0.0);
- fail();
} catch (AssertionFailedError e) {
+ return;
}
+ fail();
}
public void testAssertPosInfinityEqualsInfinity() {
@@ -53,11 +57,7 @@ public void testAssertNegInfinityEqualsInfinity() {
}
public void testAllInfinities() {
- try {
- assertEquals(Float.POSITIVE_INFINITY, Float.NEGATIVE_INFINITY, Float.POSITIVE_INFINITY);
- fail();
- } catch (AssertionFailedError e) {
- }
+ assertEquals(Float.POSITIVE_INFINITY, Float.NEGATIVE_INFINITY, Float.POSITIVE_INFINITY);
}
}
diff --git a/src/test/java/junit/tests/runner/ResultTest.java b/src/test/java/junit/tests/runner/ResultTest.java
index 7a6042996268..8cd7ac2d657e 100644
--- a/src/test/java/junit/tests/runner/ResultTest.java
+++ b/src/test/java/junit/tests/runner/ResultTest.java
@@ -2,8 +2,6 @@
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
@@ -98,7 +96,7 @@ private void assertResultReserializable(Result result, SerializationFormat resou
fromStream, resourceSerializationFormat);
}
- static public class AssumptionFailedTest {
+ public static class AssumptionFailedTest {
@Test
public void assumptionFailed() throws Exception {
org.junit.Assume.assumeTrue(false);
diff --git a/src/test/java/junit/tests/runner/TextRunnerTest.java b/src/test/java/junit/tests/runner/TextRunnerTest.java
index c74acc21335a..44e16fd599d0 100644
--- a/src/test/java/junit/tests/runner/TextRunnerTest.java
+++ b/src/test/java/junit/tests/runner/TextRunnerTest.java
@@ -32,7 +32,7 @@ void execTest(String testClass, boolean success) throws Exception {
Process p = Runtime.getRuntime().exec(cmd);
InputStream i = p.getInputStream();
while ((i.read()) != -1)
- ; //System.out.write(b);
+ ;
assertTrue((p.waitFor() == 0) == success);
if (success) {
assertTrue(p.exitValue() == 0);
diff --git a/src/test/java/org/junit/AssumptionViolatedExceptionTest.java b/src/test/java/org/junit/AssumptionViolatedExceptionTest.java
index 574cdb13059d..f5dbfcb9813b 100644
--- a/src/test/java/org/junit/AssumptionViolatedExceptionTest.java
+++ b/src/test/java/org/junit/AssumptionViolatedExceptionTest.java
@@ -4,12 +4,27 @@
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.core.IsNot.not;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
import static org.junit.Assume.assumeThat;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+
+import org.hamcrest.BaseMatcher;
+import org.hamcrest.Description;
import org.hamcrest.Matcher;
import org.hamcrest.StringDescription;
import org.junit.experimental.theories.DataPoint;
import org.junit.experimental.theories.Theories;
import org.junit.experimental.theories.Theory;
+import org.junit.rules.TestName;
import org.junit.runner.RunWith;
@RunWith(Theories.class)
@@ -23,6 +38,14 @@ public class AssumptionViolatedExceptionTest {
@DataPoint
public static Matcher NULL = null;
+ @Rule
+ public TestName name = new TestName();
+
+ private static final String MESSAGE = "Assumption message";
+ private static Matcher SERIALIZABLE_IS_THREE = new SerializableIsThreeMatcher();
+ private static final UnserializableClass UNSERIALIZABLE_VALUE = new UnserializableClass();
+ private static final Matcher UNSERIALIZABLE_MATCHER = not(is(UNSERIALIZABLE_VALUE));
+
@Theory
public void toStringReportsMatcher(Integer actual, Matcher matcher) {
assumeThat(matcher, notNullValue());
@@ -92,4 +115,93 @@ public void canSetCauseWithInstanceCreatedWithExplicitThrowableConstructor() {
AssumptionViolatedException e = new AssumptionViolatedException("invalid number", cause);
assertThat(e.getCause(), is(cause));
}
+
+ @Test
+ public void assumptionViolatedExceptionWithoutValueAndMatcherCanBeReserialized_v4_13()
+ throws IOException, ClassNotFoundException {
+ assertReserializable(new AssumptionViolatedException(MESSAGE));
+ }
+
+ @Test
+ public void assumptionViolatedExceptionWithValueAndMatcherCanBeReserialized_v4_13()
+ throws IOException, ClassNotFoundException {
+ assertReserializable(new AssumptionViolatedException(MESSAGE, TWO, SERIALIZABLE_IS_THREE));
+ }
+
+ @Test
+ public void unserializableValueAndMatcherCanBeSerialized() throws IOException, ClassNotFoundException {
+ AssumptionViolatedException exception = new AssumptionViolatedException(MESSAGE,
+ UNSERIALIZABLE_VALUE, UNSERIALIZABLE_MATCHER);
+
+ assertCanBeSerialized(exception);
+ }
+
+ @Test
+ public void nullValueAndMatcherCanBeSerialized() throws IOException, ClassNotFoundException {
+ AssumptionViolatedException exception = new AssumptionViolatedException(MESSAGE);
+
+ assertCanBeSerialized(exception);
+ }
+
+ @Test
+ public void serializableValueAndMatcherCanBeSerialized() throws IOException, ClassNotFoundException {
+ AssumptionViolatedException exception = new AssumptionViolatedException(MESSAGE,
+ TWO, SERIALIZABLE_IS_THREE);
+
+ assertCanBeSerialized(exception);
+ }
+
+ private void assertCanBeSerialized(AssumptionViolatedException exception)
+ throws IOException, ClassNotFoundException {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ ObjectOutputStream oos = new ObjectOutputStream(baos);
+ oos.writeObject(exception);
+
+ ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
+ ObjectInputStream ois = new ObjectInputStream(bais);
+ AssumptionViolatedException fromStream = (AssumptionViolatedException) ois.readObject();
+
+ assertSerializedCorrectly(exception, fromStream);
+ }
+
+ private void assertReserializable(AssumptionViolatedException expected)
+ throws IOException, ClassNotFoundException {
+ String resourceName = name.getMethodName();
+ InputStream resource = getClass().getResourceAsStream(resourceName);
+ assertNotNull("Could not read resource " + resourceName, resource);
+ ObjectInputStream objectInputStream = new ObjectInputStream(resource);
+ AssumptionViolatedException fromStream = (AssumptionViolatedException) objectInputStream.readObject();
+
+ assertSerializedCorrectly(expected, fromStream);
+ }
+
+ private void assertSerializedCorrectly(
+ AssumptionViolatedException expected, AssumptionViolatedException fromStream) {
+ assertNotNull(fromStream);
+
+ // Exceptions don't implement equals() so we need to compare field by field
+ assertEquals("message", expected.getMessage(), fromStream.getMessage());
+ assertEquals("description", StringDescription.asString(expected), StringDescription.asString(fromStream));
+ // We don't check the stackTrace as that will be influenced by how the test was started
+ // (e.g. by maven or directly from IDE)
+ // We also don't check the cause as that should already be serialized correctly by the superclass
+ }
+
+ private static class SerializableIsThreeMatcher extends BaseMatcher implements Serializable {
+
+ public boolean matches(Object item) {
+ return IS_THREE.matches(item);
+ }
+
+ public void describeTo(Description description) {
+ IS_THREE.describeTo(description);
+ }
+ }
+
+ private static class UnserializableClass {
+ @Override
+ public String toString() {
+ return "I'm not serializable";
+ }
+ }
}
diff --git a/src/test/java/org/junit/experimental/categories/CategoriesAndParameterizedTest.java b/src/test/java/org/junit/experimental/categories/CategoriesAndParameterizedTest.java
index 68e842bb53e9..3d792225d179 100644
--- a/src/test/java/org/junit/experimental/categories/CategoriesAndParameterizedTest.java
+++ b/src/test/java/org/junit/experimental/categories/CategoriesAndParameterizedTest.java
@@ -6,9 +6,7 @@
import org.junit.Assert;
import org.junit.Test;
-import org.junit.experimental.categories.Categories;
import org.junit.experimental.categories.Categories.IncludeCategory;
-import org.junit.experimental.categories.Category;
import org.junit.runner.JUnitCore;
import org.junit.runner.Result;
import org.junit.runner.RunWith;
diff --git a/src/test/java/org/junit/experimental/categories/CategoryTest.java b/src/test/java/org/junit/experimental/categories/CategoryTest.java
index 59242b447cfa..6088f1d26229 100644
--- a/src/test/java/org/junit/experimental/categories/CategoryTest.java
+++ b/src/test/java/org/junit/experimental/categories/CategoryTest.java
@@ -1,28 +1,27 @@
package org.junit.experimental.categories;
+import static java.lang.String.format;
import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.core.AnyOf.anyOf;
+import static org.hamcrest.core.Is.is;
+import static org.hamcrest.core.IsEqual.equalTo;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.junit.experimental.results.PrintableResult.testResult;
-import static org.junit.experimental.results.ResultMatchers.isSuccessful;
import static org.junit.experimental.results.ResultMatchers.failureCountIs;
-import static org.hamcrest.core.AnyOf.anyOf;
-import static org.hamcrest.core.Is.is;
-import static org.hamcrest.core.IsEqual.equalTo;
-import static java.lang.String.format;
+import static org.junit.experimental.results.ResultMatchers.isSuccessful;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
+
import org.junit.Ignore;
import org.junit.Test;
-import org.junit.experimental.categories.Categories;
import org.junit.experimental.categories.Categories.CategoryFilter;
import org.junit.experimental.categories.Categories.ExcludeCategory;
import org.junit.experimental.categories.Categories.IncludeCategory;
-import org.junit.experimental.categories.Category;
import org.junit.runner.JUnitCore;
import org.junit.runner.Request;
import org.junit.runner.Result;
@@ -412,7 +411,7 @@ public void classesCanBeCategories() {
}
@Category(SlowTests.class)
- public static abstract class Ancestor{}
+ public abstract static class Ancestor{}
public static class Inherited extends Ancestor {
@Test
diff --git a/src/test/java/org/junit/experimental/categories/CategoryValidatorTest.java b/src/test/java/org/junit/experimental/categories/CategoryValidatorTest.java
index 654622f594bf..6d7c22ec31dd 100644
--- a/src/test/java/org/junit/experimental/categories/CategoryValidatorTest.java
+++ b/src/test/java/org/junit/experimental/categories/CategoryValidatorTest.java
@@ -10,8 +10,6 @@
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
-import org.junit.experimental.categories.Category;
-import org.junit.experimental.categories.CategoryValidator;
import org.junit.runners.model.FrameworkMethod;
import org.junit.runners.model.TestClass;
diff --git a/src/test/java/org/junit/experimental/categories/JavadocTest.java b/src/test/java/org/junit/experimental/categories/JavadocTest.java
index 65fa430f9dbb..fc0df7248bbd 100644
--- a/src/test/java/org/junit/experimental/categories/JavadocTest.java
+++ b/src/test/java/org/junit/experimental/categories/JavadocTest.java
@@ -1,18 +1,16 @@
package org.junit.experimental.categories;
+import static org.hamcrest.core.Is.is;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
import org.junit.Test;
-import org.junit.experimental.categories.Categories;
-import org.junit.experimental.categories.Category;
import org.junit.runner.JUnitCore;
import org.junit.runner.Result;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
-import static org.hamcrest.core.Is.is;
-import static org.junit.Assert.assertThat;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
/**
* @author tibor17
* @version 4.12
diff --git a/src/test/java/org/junit/experimental/categories/MultiCategoryTest.java b/src/test/java/org/junit/experimental/categories/MultiCategoryTest.java
index c7169aca120a..68a580cdead7 100644
--- a/src/test/java/org/junit/experimental/categories/MultiCategoryTest.java
+++ b/src/test/java/org/junit/experimental/categories/MultiCategoryTest.java
@@ -1,19 +1,17 @@
package org.junit.experimental.categories;
-import org.junit.Test;
-import org.junit.experimental.categories.Categories;
-import org.junit.experimental.categories.Category;
-import org.junit.runner.JUnitCore;
-import org.junit.runner.Result;
-import org.junit.runner.RunWith;
-import org.junit.runners.Suite;
-
import static org.hamcrest.core.Is.is;
import static org.hamcrest.core.IsEqual.equalTo;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.fail;
+import org.junit.Test;
+import org.junit.runner.JUnitCore;
+import org.junit.runner.Result;
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+
/**
* @author tibor17
* @version 4.12
diff --git a/src/test/java/org/junit/internal/StackTracesTest.java b/src/test/java/org/junit/internal/StackTracesTest.java
index 748d86a5f9e8..5c0e8a1603a8 100644
--- a/src/test/java/org/junit/internal/StackTracesTest.java
+++ b/src/test/java/org/junit/internal/StackTracesTest.java
@@ -6,7 +6,6 @@
import static org.junit.Assert.fail;
import static org.junit.Assume.assumeTrue;
-import java.lang.reflect.Method;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
@@ -14,25 +13,19 @@
import java.util.concurrent.Future;
import java.util.regex.Pattern;
-import junit.framework.TestCase;
+import junit.tests.SampleJUnit3Tests;
import org.hamcrest.CoreMatchers;
import org.hamcrest.Description;
import org.hamcrest.Matcher;
import org.hamcrest.StringDescription;
import org.hamcrest.TypeSafeMatcher;
import org.junit.AfterClass;
-import org.junit.Before;
import org.junit.BeforeClass;
-import org.junit.ClassRule;
-import org.junit.Rule;
import org.junit.Test;
-import org.junit.rules.MethodRule;
-import org.junit.rules.TestRule;
import org.junit.runner.JUnitCore;
import org.junit.runner.Result;
import org.junit.runner.notification.Failure;
-import org.junit.runners.model.FrameworkMethod;
-import org.junit.runners.model.Statement;
+import org.junit.tests.SampleJUnit4Tests.*;
public class StackTracesTest {
private static final String EOL = System.getProperty("line.separator", "\n");
@@ -58,9 +51,9 @@ public void getTrimmedStackForJUnit4TestFailingInTestMethod() {
assertHasTrimmedTrace(failure,
message("java.lang.RuntimeException: cause"),
- at("org.junit.internal.StackTracesTest$FakeClassUnderTest.doThrowExceptionWithoutCause"),
- at("org.junit.internal.StackTracesTest$FakeClassUnderTest.throwsExceptionWithoutCause"),
- at("org.junit.internal.StackTracesTest$TestWithOneThrowingTestMethod.alwaysThrows"));
+ at("org.junit.tests.SampleJUnit4Tests$FakeClassUnderTest.doThrowExceptionWithoutCause"),
+ at("org.junit.tests.SampleJUnit4Tests$FakeClassUnderTest.throwsExceptionWithoutCause"),
+ at("org.junit.tests.SampleJUnit4Tests$TestWithOneThrowingTestMethod.alwaysThrows"));
assertNotEquals(failure.getTrace(), failure.getTrimmedTrace());
}
@@ -73,14 +66,14 @@ public void getTrimmedStackForJUnit4TestFailingInTestMethodWithCause() {
assertHasTrimmedTrace(failure,
message("java.lang.RuntimeException: outer"),
- at("org.junit.internal.StackTracesTest$FakeClassUnderTest.doThrowExceptionWithCause"),
- at("org.junit.internal.StackTracesTest$FakeClassUnderTest.throwsExceptionWithCause"),
- at("org.junit.internal.StackTracesTest$TestWithOneThrowingTestMethodWithCause.alwaysThrows"),
+ at("org.junit.tests.SampleJUnit4Tests$FakeClassUnderTest.doThrowExceptionWithCause"),
+ at("org.junit.tests.SampleJUnit4Tests$FakeClassUnderTest.throwsExceptionWithCause"),
+ at("org.junit.tests.SampleJUnit4Tests$TestWithOneThrowingTestMethodWithCause.alwaysThrows"),
framesTrimmed(),
message("Caused by: java.lang.RuntimeException: cause"),
- at("org.junit.internal.StackTracesTest$FakeClassUnderTest.doThrowExceptionWithoutCause"),
- at("org.junit.internal.StackTracesTest$FakeClassUnderTest.throwsExceptionWithoutCause"),
- at("org.junit.internal.StackTracesTest$FakeClassUnderTest.doThrowExceptionWithCause"),
+ at("org.junit.tests.SampleJUnit4Tests$FakeClassUnderTest.doThrowExceptionWithoutCause"),
+ at("org.junit.tests.SampleJUnit4Tests$FakeClassUnderTest.throwsExceptionWithoutCause"),
+ at("org.junit.tests.SampleJUnit4Tests$FakeClassUnderTest.doThrowExceptionWithCause"),
framesInCommon());
assertNotEquals(failure.getTrace(), failure.getTrimmedTrace());
}
@@ -94,39 +87,39 @@ public void getTrimmedStackForJUnit4TestFailingInBeforeMethod() {
assertHasTrimmedTrace(failure,
message("java.lang.RuntimeException: cause"),
- at("org.junit.internal.StackTracesTest$FakeClassUnderTest.doThrowExceptionWithoutCause"),
- at("org.junit.internal.StackTracesTest$FakeClassUnderTest.throwsExceptionWithoutCause"),
- at("org.junit.internal.StackTracesTest$TestWithThrowingBeforeMethod.alwaysThrows"));
+ at("org.junit.tests.SampleJUnit4Tests$FakeClassUnderTest.doThrowExceptionWithoutCause"),
+ at("org.junit.tests.SampleJUnit4Tests$FakeClassUnderTest.throwsExceptionWithoutCause"),
+ at("org.junit.tests.SampleJUnit4Tests$TestWithThrowingBeforeMethod.alwaysThrows"));
assertNotEquals(failure.getTrace(), failure.getTrimmedTrace());
}
@Test
public void getTrimmedStackForJUnit3TestFailingInTestMethod() {
- Result result = runTest(JUnit3TestWithOneThrowingTestMethod.class);
+ Result result = runTest(SampleJUnit3Tests.TestWithOneThrowingTestMethod.class);
assertEquals("Should run the test", 1, result.getRunCount());
assertEquals("One test should fail", 1, result.getFailureCount());
Failure failure = result.getFailures().get(0);
assertHasTrimmedTrace(failure,
message("java.lang.RuntimeException: cause"),
- at("org.junit.internal.StackTracesTest$FakeClassUnderTest.doThrowExceptionWithoutCause"),
- at("org.junit.internal.StackTracesTest$FakeClassUnderTest.throwsExceptionWithoutCause"),
- at("org.junit.internal.StackTracesTest$JUnit3TestWithOneThrowingTestMethod.testAlwaysThrows"));
+ at("junit.tests.SampleJUnit3Tests$FakeClassUnderTest.doThrowExceptionWithoutCause"),
+ at("junit.tests.SampleJUnit3Tests$FakeClassUnderTest.throwsExceptionWithoutCause"),
+ at("junit.tests.SampleJUnit3Tests$TestWithOneThrowingTestMethod.testAlwaysThrows"));
assertNotEquals(failure.getTrace(), failure.getTrimmedTrace());
}
@Test
public void getTrimmedStackForJUnit3TestFailingInSetupMethod() {
- Result result = runTest(JUnit3TestWithThrowingSetUpMethod.class);
+ Result result = runTest(SampleJUnit3Tests.TestWithThrowingSetUpMethod.class);
assertEquals("Should run the test", 1, result.getRunCount());
assertEquals("One test should fail", 1, result.getFailureCount());
Failure failure = result.getFailures().get(0);
assertHasTrimmedTrace(failure,
message("java.lang.RuntimeException: cause"),
- at("org.junit.internal.StackTracesTest$FakeClassUnderTest.doThrowExceptionWithoutCause"),
- at("org.junit.internal.StackTracesTest$FakeClassUnderTest.throwsExceptionWithoutCause"),
- at("org.junit.internal.StackTracesTest$JUnit3TestWithThrowingSetUpMethod.setUp"));
+ at("junit.tests.SampleJUnit3Tests$FakeClassUnderTest.doThrowExceptionWithoutCause"),
+ at("junit.tests.SampleJUnit3Tests$FakeClassUnderTest.throwsExceptionWithoutCause"),
+ at("junit.tests.SampleJUnit3Tests$TestWithThrowingSetUpMethod.setUp"));
assertNotEquals(failure.getTrace(), failure.getTrimmedTrace());
}
@@ -139,9 +132,9 @@ public void getTrimmedStackForJUnit4TestFailingInTestRule() {
assertHasTrimmedTrace(failure,
message("java.lang.RuntimeException: cause"),
- at("org.junit.internal.StackTracesTest$FakeClassUnderTest.doThrowExceptionWithoutCause"),
- at("org.junit.internal.StackTracesTest$FakeClassUnderTest.throwsExceptionWithoutCause"),
- at("org.junit.internal.StackTracesTest$ThrowingTestRule.apply"));
+ at("org.junit.tests.SampleJUnit4Tests$FakeClassUnderTest.doThrowExceptionWithoutCause"),
+ at("org.junit.tests.SampleJUnit4Tests$FakeClassUnderTest.throwsExceptionWithoutCause"),
+ at("org.junit.tests.SampleJUnit4Tests$ThrowingTestRule.apply"));
assertNotEquals(failure.getTrace(), failure.getTrimmedTrace());
}
@@ -154,9 +147,9 @@ public void getTrimmedStackForJUnit4TestFailingInClassRule() {
assertHasTrimmedTrace(failure,
message("java.lang.RuntimeException: cause"),
- at("org.junit.internal.StackTracesTest$FakeClassUnderTest.doThrowExceptionWithoutCause"),
- at("org.junit.internal.StackTracesTest$FakeClassUnderTest.throwsExceptionWithoutCause"),
- at("org.junit.internal.StackTracesTest$ThrowingTestRule.apply"));
+ at("org.junit.tests.SampleJUnit4Tests$FakeClassUnderTest.doThrowExceptionWithoutCause"),
+ at("org.junit.tests.SampleJUnit4Tests$FakeClassUnderTest.throwsExceptionWithoutCause"),
+ at("org.junit.tests.SampleJUnit4Tests$ThrowingTestRule.apply"));
assertNotEquals(failure.getTrace(), failure.getTrimmedTrace());
}
@@ -169,9 +162,9 @@ public void getTrimmedStackForJUnit4TestFailingInMethodRule() {
assertHasTrimmedTrace(failure,
message("java.lang.RuntimeException: cause"),
- at("org.junit.internal.StackTracesTest$FakeClassUnderTest.doThrowExceptionWithoutCause"),
- at("org.junit.internal.StackTracesTest$FakeClassUnderTest.throwsExceptionWithoutCause"),
- at("org.junit.internal.StackTracesTest$ThrowingMethodRule.apply"));
+ at("org.junit.tests.SampleJUnit4Tests$FakeClassUnderTest.doThrowExceptionWithoutCause"),
+ at("org.junit.tests.SampleJUnit4Tests$FakeClassUnderTest.throwsExceptionWithoutCause"),
+ at("org.junit.tests.SampleJUnit4Tests$ThrowingMethodRule.apply"));
assertNotEquals(failure.getTrace(), failure.getTrimmedTrace());
}
@@ -185,9 +178,9 @@ public void getTrimmedStackWithSuppressedExceptions() {
assertHasTrimmedTrace(failure,
message("java.lang.RuntimeException: error"),
- at("org.junit.internal.StackTracesTest$TestWithSuppressedException.alwaysThrows"),
+ at("org.junit.tests.SampleJUnit4Tests$TestWithSuppressedException.alwaysThrows"),
message("\tSuppressed: java.lang.RuntimeException: suppressed"),
- at("org.junit.internal.StackTracesTest$TestWithSuppressedException.alwaysThrows"),
+ at("org.junit.tests.SampleJUnit4Tests$TestWithSuppressedException.alwaysThrows"),
framesInCommon());
assertNotEquals(failure.getTrace(), failure.getTrimmedTrace());
}
@@ -336,141 +329,4 @@ private static void assertHasTrimmedTrace(Failure failure, StringMatcher... matc
fail("Missing line in trimmed trace: " + description.toString());
}
}
-
- public static class TestWithOneThrowingTestMethod {
-
- @Test
- public void alwaysThrows() {
- new FakeClassUnderTest().throwsExceptionWithoutCause();
- }
- }
-
- public static class JUnit3TestWithOneThrowingTestMethod extends TestCase {
-
- public void testAlwaysThrows() {
- new FakeClassUnderTest().throwsExceptionWithoutCause();
- }
- }
-
- public static class TestWithOneThrowingTestMethodWithCause {
-
- @Test
- public void alwaysThrows() {
- new FakeClassUnderTest().throwsExceptionWithCause();
- }
- }
-
- public static class TestWithThrowingBeforeMethod {
-
- @Before
- public void alwaysThrows() {
- new FakeClassUnderTest().throwsExceptionWithoutCause();
- }
-
- @Test
- public void alwaysPasses() {
- }
- }
-
- public static class JUnit3TestWithThrowingSetUpMethod extends TestCase {
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- new FakeClassUnderTest().throwsExceptionWithoutCause();
- }
-
- public void testAlwaysPasses() {
- }
- }
-
- public static class ThrowingTestRule implements TestRule {
-
- public Statement apply(
- Statement base, org.junit.runner.Description description) {
- new FakeClassUnderTest().throwsExceptionWithoutCause();
- return base;
- }
- }
-
- public static class TestWithThrowingTestRule {
-
- @Rule
- public final TestRule rule = new ThrowingTestRule();
-
- @Test
- public void alwaysPasses() {
- }
- }
-
- public static class TestWithThrowingClassRule {
-
- @ClassRule
- public static final TestRule rule = new ThrowingTestRule();
-
- @Test
- public void alwaysPasses() {
- }
- }
-
- public static class ThrowingMethodRule implements MethodRule {
-
- public Statement apply(
- Statement base, FrameworkMethod method, Object target) {
- new FakeClassUnderTest().throwsExceptionWithoutCause();
- return base;
- }
- }
-
- public static class TestWithThrowingMethodRule {
-
- @Rule
- public final ThrowingMethodRule rule = new ThrowingMethodRule();
-
- @Test
- public void alwaysPasses() {
- }
- }
-
- private static class FakeClassUnderTest {
-
- public void throwsExceptionWithCause() {
- doThrowExceptionWithCause();
- }
-
- public void throwsExceptionWithoutCause() {
- doThrowExceptionWithoutCause();
- }
-
- private void doThrowExceptionWithCause() {
- try {
- throwsExceptionWithoutCause();
- } catch (Exception e) {
- throw new RuntimeException("outer", e);
- }
- }
-
- private void doThrowExceptionWithoutCause() {
- throw new RuntimeException("cause");
- }
- }
-
- public static class TestWithSuppressedException {
- static final Method addSuppressed = initAddSuppressed();
-
- static Method initAddSuppressed() {
- try {
- return Throwable.class.getMethod("addSuppressed", Throwable.class);
- } catch (Throwable e) {
- return null;
- }
- }
-
- @Test
- public void alwaysThrows() throws Exception {
- final RuntimeException exception = new RuntimeException("error");
- addSuppressed.invoke(exception, new RuntimeException("suppressed"));
- throw exception;
- }
- }
}
diff --git a/src/test/java/org/junit/internal/runners/statements/FailOnTimeoutTest.java b/src/test/java/org/junit/internal/runners/statements/FailOnTimeoutTest.java
index 00c3f0b98276..8bf7823f30af 100644
--- a/src/test/java/org/junit/internal/runners/statements/FailOnTimeoutTest.java
+++ b/src/test/java/org/junit/internal/runners/statements/FailOnTimeoutTest.java
@@ -4,182 +4,155 @@
import static java.lang.Math.atan;
import static java.lang.System.currentTimeMillis;
import static java.lang.Thread.currentThread;
+import static java.lang.Thread.interrupted;
import static java.lang.Thread.sleep;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-import static org.junit.internal.runners.statements.FailOnTimeout.builder;
+import static org.junit.Assume.assumeFalse;
+import static org.junit.Assume.assumeTrue;
import java.util.Arrays;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.Set;
-import java.util.concurrent.TimeUnit;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicReference;
import org.junit.Test;
import org.junit.function.ThrowingRunnable;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameter;
+import org.junit.runners.Parameterized.Parameters;
import org.junit.runners.model.Statement;
import org.junit.runners.model.TestTimedOutException;
+
/**
* @author Asaf Ary, Stefan Birkner
*/
+@RunWith(Parameterized.class)
public class FailOnTimeoutTest {
- private static final long TIMEOUT = 100;
- private static final long DURATION_THAT_EXCEEDS_TIMEOUT = 60 * 60 * 1000; //1 hour
- private final TestStatement statement = new TestStatement();
+ @Parameters(name = "lookingForStuckThread = {0}")
+ public static Iterable getParameters() {
+ return Arrays.asList(Boolean.TRUE, Boolean.FALSE);
+ }
- private final FailOnTimeout failOnTimeout = builder().withTimeout(TIMEOUT, MILLISECONDS).build(statement);
+ @Parameter
+ public boolean lookingForStuckThread;
@Test
- public void throwsTestTimedOutException() {
- assertThrows(
- TestTimedOutException.class,
- evaluateWithWaitDuration(DURATION_THAT_EXCEEDS_TIMEOUT));
+ public void noExceptionIsThrownWhenWrappedStatementFinishesBeforeTimeoutWithoutThrowingException()
+ throws Throwable {
+ FailOnTimeout failOnTimeout = failAfter50Ms(new FastStatement());
+
+ failOnTimeout.evaluate();
+
+ // test is successful when no exception is thrown
}
@Test
- public void throwExceptionWithNiceMessageOnTimeout() {
- TestTimedOutException e = assertThrows(
+ public void throwsTestTimedOutExceptionWithMeaningfulMessage() {
+ Exception e = assertThrows(
TestTimedOutException.class,
- evaluateWithWaitDuration(DURATION_THAT_EXCEEDS_TIMEOUT));
- assertEquals("test timed out after 100 milliseconds", e.getMessage());
+ run(failAfter50Ms(new RunForASecond())));
+ assertEquals("test timed out after 50 milliseconds", e.getMessage());
}
@Test
public void sendUpExceptionThrownByStatement() {
- RuntimeException exception = new RuntimeException();
- RuntimeException e = assertThrows(
- RuntimeException.class,
- evaluateWithException(exception));
+ Exception exception = new RuntimeException();
+ Exception e = assertThrows(
+ Exception.class,
+ run(failAfter50Ms(new Fail(exception))));
assertSame(exception, e);
}
@Test
public void throwExceptionIfTheSecondCallToEvaluateNeedsTooMuchTime()
throws Throwable {
- evaluateWithWaitDuration(0).run();
+ DelegatingStatement statement = new DelegatingStatement();
+ FailOnTimeout failOnTimeout = failAfter50Ms(statement);
+
+ statement.delegate = new FastStatement();
+ failOnTimeout.evaluate();
+
+ statement.delegate = new RunForASecond();
assertThrows(
TestTimedOutException.class,
- evaluateWithWaitDuration(DURATION_THAT_EXCEEDS_TIMEOUT));
+ run(failOnTimeout));
}
@Test
public void throwTimeoutExceptionOnSecondCallAlthoughFirstCallThrowsException() {
- try {
- evaluateWithException(new RuntimeException()).run();
- } catch (Throwable expected) {
- }
+ DelegatingStatement statement = new DelegatingStatement();
+ FailOnTimeout failOnTimeout = failAfter50Ms(statement);
- TestTimedOutException e = assertThrows(
+ statement.delegate = new Fail(new AssertionError("first execution failed"));
+ assertThrows(
+ AssertionError.class,
+ run(failOnTimeout)
+ );
+
+ statement.delegate = new RunForASecond();
+ assertThrows(
TestTimedOutException.class,
- evaluateWithWaitDuration(DURATION_THAT_EXCEEDS_TIMEOUT));
- assertEquals("test timed out after 100 milliseconds", e.getMessage());
+ run(failOnTimeout));
}
@Test
public void throwsExceptionWithTimeoutValueAndTimeUnitSet() {
TestTimedOutException e = assertThrows(
TestTimedOutException.class,
- evaluateWithWaitDuration(DURATION_THAT_EXCEEDS_TIMEOUT));
- assertEquals(TIMEOUT, e.getTimeout());
- assertEquals(TimeUnit.MILLISECONDS, e.getTimeUnit());
- }
-
- private ThrowingRunnable evaluateWithException(final Exception exception) {
- return new ThrowingRunnable() {
- public void run() throws Throwable {
- statement.nextException = exception;
- statement.waitDuration = 0;
- failOnTimeout.evaluate();
- }
- };
- }
-
- private ThrowingRunnable evaluateWithWaitDuration(final long waitDuration) {
- return new ThrowingRunnable() {
- public void run() throws Throwable {
- statement.nextException = null;
- statement.waitDuration = waitDuration;
- failOnTimeout.evaluate();
- }
- };
+ run(failAfter50Ms(new RunForASecond())));
+ assertEquals(50, e.getTimeout());
+ assertEquals(MILLISECONDS, e.getTimeUnit());
}
- private static final class TestStatement extends Statement {
- long waitDuration;
-
- Exception nextException;
+ @Test
+ public void statementThatCanBeInterruptedIsStoppedAfterTimeout() throws Throwable {
+ // RunForASecond can be interrupted because it checks the Thread's
+ // interrupted flag.
+ RunForASecond runForASecond = new RunForASecond();
+ assertThrows(
+ TestTimedOutException.class,
+ run(failAfter50Ms(runForASecond)));
- @Override
- public void evaluate() throws Throwable {
- sleep(waitDuration);
- if (nextException != null) {
- throw nextException;
- }
- }
+ // Thread is explicitly stopped if it finishes faster than its
+ // pre-defined execution time of one second.
+ boolean stopped = runForASecond.finished.await(50, MILLISECONDS);
+ assertTrue("Thread has not been stopped.", stopped);
}
@Test
- public void stopEndlessStatement() throws Throwable {
- InfiniteLoopStatement infiniteLoop = new InfiniteLoopStatement();
- FailOnTimeout infiniteLoopTimeout = builder().withTimeout(TIMEOUT, MILLISECONDS).build(infiniteLoop);
- try {
- infiniteLoopTimeout.evaluate();
- } catch (Exception timeoutException) {
- sleep(20); // time to interrupt the thread
- int firstCount = InfiniteLoopStatement.COUNT;
- sleep(20); // time to increment the count
- assertTrue("Thread has not been stopped.",
- firstCount == InfiniteLoopStatement.COUNT);
- }
- }
-
- private static final class InfiniteLoopStatement extends Statement {
- private static int COUNT = 0;
+ public void stackTraceContainsRealCauseOfTimeout() {
+ TestTimedOutException timedOutException = assertThrows(
+ TestTimedOutException.class,
+ run(failAfter50Ms(new StuckStatement())));
- @Override
- public void evaluate() throws Throwable {
- while (true) {
- sleep(10); // sleep in order to enable interrupting thread
- ++COUNT;
+ StackTraceElement[] stackTrace = timedOutException.getStackTrace();
+ boolean stackTraceContainsTheRealCauseOfTheTimeout = false;
+ boolean stackTraceContainsOtherThanTheRealCauseOfTheTimeout = false;
+ for (StackTraceElement element : stackTrace) {
+ String methodName = element.getMethodName();
+ if ("theRealCauseOfTheTimeout".equals(methodName)) {
+ stackTraceContainsTheRealCauseOfTheTimeout = true;
}
- }
- }
-
- @Test
- public void stackTraceContainsRealCauseOfTimeout() throws Throwable {
- StuckStatement stuck = new StuckStatement();
- FailOnTimeout stuckTimeout = builder().withTimeout(TIMEOUT, MILLISECONDS).build(stuck);
- try {
- stuckTimeout.evaluate();
- // We must not get here, we expect a timeout exception
- fail("Expected timeout exception");
- } catch (Exception timeoutException) {
- StackTraceElement[] stackTrace = timeoutException.getStackTrace();
- boolean stackTraceContainsTheRealCauseOfTheTimeout = false;
- boolean stackTraceContainsOtherThanTheRealCauseOfTheTimeout = false;
- for (StackTraceElement element : stackTrace) {
- String methodName = element.getMethodName();
- if ("theRealCauseOfTheTimeout".equals(methodName)) {
- stackTraceContainsTheRealCauseOfTheTimeout = true;
- }
- if ("notTheRealCauseOfTheTimeout".equals(methodName)) {
- stackTraceContainsOtherThanTheRealCauseOfTheTimeout = true;
- }
+ if ("notTheRealCauseOfTheTimeout".equals(methodName)) {
+ stackTraceContainsOtherThanTheRealCauseOfTheTimeout = true;
}
- assertTrue(
- "Stack trace does not contain the real cause of the timeout",
- stackTraceContainsTheRealCauseOfTheTimeout);
- assertFalse(
- "Stack trace contains other than the real cause of the timeout, which can be very misleading",
- stackTraceContainsOtherThanTheRealCauseOfTheTimeout);
}
+ assertTrue(
+ "Stack trace does not contain the real cause of the timeout",
+ stackTraceContainsTheRealCauseOfTheTimeout);
+ assertFalse(
+ "Stack trace contains other than the real cause of the timeout, which can be very misleading",
+ stackTraceContainsOtherThanTheRealCauseOfTheTimeout);
}
private static final class StuckStatement extends Statement {
@@ -209,21 +182,90 @@ private void notTheRealCauseOfTheTimeout() {
}
@Test
- public void threadGroupNotLeaked() throws Throwable {
- Collection groupsBeforeSet = subGroupsOfCurrentThread();
-
- evaluateWithWaitDuration(0);
-
- for (ThreadGroup group: subGroupsOfCurrentThread()) {
- if (!groupsBeforeSet.contains(group) && "FailOnTimeoutGroup".equals(group.getName())) {
- fail("A 'FailOnTimeoutGroup' thread group remains referenced after the test execution.");
+ public void lookingForStuckThread_threadGroupNotLeaked() throws Throwable {
+ assumeTrue(lookingForStuckThread);
+ final AtomicReference innerThreadGroup = new AtomicReference();
+ final AtomicReference innerThread = new AtomicReference();
+ final ThreadGroup outerThreadGroup = currentThread().getThreadGroup();
+ FailOnTimeout failOnTimeout = failAfter50Ms(new Statement() {
+ @Override
+ public void evaluate() {
+ innerThread.set(currentThread());
+ ThreadGroup group = currentThread().getThreadGroup();
+ assertNotSame("inner thread should use a different thread group",
+ outerThreadGroup, group);
+ innerThreadGroup.set(group);
+ assertTrue("the 'FailOnTimeoutGroup' thread group should be a daemon thread group",
+ group.isDaemon());
+ }
+ });
+
+ failOnTimeout.evaluate();
+
+ assertNotNull("the Statement was never run", innerThread.get());
+ innerThread.get().join();
+ assertTrue("the 'FailOnTimeoutGroup' thread group should be destroyed after running the test",
+ innerThreadGroup.get().isDestroyed());
+ }
+
+ @Test
+ public void notLookingForStuckThread_usesSameThreadGroup() throws Throwable {
+ assumeFalse(lookingForStuckThread);
+ final AtomicBoolean statementWasExecuted = new AtomicBoolean();
+ final ThreadGroup outerThreadGroup = currentThread().getThreadGroup();
+ FailOnTimeout failOnTimeout = failAfter50Ms(new Statement() {
+ @Override
+ public void evaluate() {
+ statementWasExecuted.set(true);
+ ThreadGroup group = currentThread().getThreadGroup();
+ assertSame("inner thread should use the same thread group", outerThreadGroup, group);
+ }
+ });
+
+ failOnTimeout.evaluate();
+
+ assertTrue("the Statement was never run", statementWasExecuted.get());
+ }
+
+ private FailOnTimeout failAfter50Ms(Statement statement) {
+ return FailOnTimeout.builder()
+ .withTimeout(50, MILLISECONDS)
+ .withLookingForStuckThread(lookingForStuckThread)
+ .build(statement);
+ }
+
+ private ThrowingRunnable run(final FailOnTimeout failOnTimeout) {
+ return new ThrowingRunnable() {
+ public void run() throws Throwable {
+ failOnTimeout.evaluate();
}
+ };
+ }
+
+ private static class DelegatingStatement extends Statement {
+ volatile Statement delegate;
+
+ @Override
+ public void evaluate() throws Throwable {
+ delegate.evaluate();
+ }
+ }
+
+ private static class FastStatement extends Statement {
+ @Override
+ public void evaluate() throws Throwable {
}
}
-
- private Collection subGroupsOfCurrentThread() {
- ThreadGroup[] subGroups = new ThreadGroup[256];
- int numGroups = currentThread().getThreadGroup().enumerate(subGroups);
- return Arrays.asList(subGroups).subList(0, numGroups);
+
+ private static final class RunForASecond extends Statement {
+ final CountDownLatch finished = new CountDownLatch(1);
+
+ @Override
+ public void evaluate() throws Throwable {
+ long timeout = currentTimeMillis() + 1000L;
+ while (!interrupted() && currentTimeMillis() < timeout) {
+ }
+ finished.countDown();
+ }
}
}
diff --git a/src/test/java/org/junit/rules/DisableOnDebugTest.java b/src/test/java/org/junit/rules/DisableOnDebugTest.java
index d61db9e528db..8bf6b9deeee4 100644
--- a/src/test/java/org/junit/rules/DisableOnDebugTest.java
+++ b/src/test/java/org/junit/rules/DisableOnDebugTest.java
@@ -48,7 +48,7 @@ public void evaluate() throws Throwable {
}
- public static abstract class AbstractDisableOnDebugTest {
+ public abstract static class AbstractDisableOnDebugTest {
@Rule
public TestRule failOnExecution;
diff --git a/src/test/java/org/junit/rules/MethodRulesTest.java b/src/test/java/org/junit/rules/MethodRulesTest.java
index 93eb68468d28..6c59f7edab3c 100644
--- a/src/test/java/org/junit/rules/MethodRulesTest.java
+++ b/src/test/java/org/junit/rules/MethodRulesTest.java
@@ -44,7 +44,7 @@ public void nothing() {
}
}
- static abstract class NonPublicExampleTest {
+ abstract static class NonPublicExampleTest {
@Rule
public MethodRule example = new TestMethodRule();
diff --git a/src/test/java/org/junit/rules/RuleChainTest.java b/src/test/java/org/junit/rules/RuleChainTest.java
index 914b6a9088c5..54daf8dc59a7 100644
--- a/src/test/java/org/junit/rules/RuleChainTest.java
+++ b/src/test/java/org/junit/rules/RuleChainTest.java
@@ -10,8 +10,6 @@
import static org.junit.experimental.results.PrintableResult.testResult;
import static org.junit.rules.RuleChain.outerRule;
-import java.io.PrintWriter;
-import java.io.StringWriter;
import java.util.ArrayList;
import java.util.List;
diff --git a/src/test/java/org/junit/rules/StopwatchTest.java b/src/test/java/org/junit/rules/StopwatchTest.java
index 69fbcb03ec68..5941eb9b1bb1 100644
--- a/src/test/java/org/junit/rules/StopwatchTest.java
+++ b/src/test/java/org/junit/rules/StopwatchTest.java
@@ -49,7 +49,7 @@ private static class Record {
}
}
- public static abstract class AbstractStopwatchTest {
+ public abstract static class AbstractStopwatchTest {
/**
* Fake implementation of {@link Stopwatch.Clock} that increments the time
diff --git a/src/test/java/org/junit/rules/TestRuleTest.java b/src/test/java/org/junit/rules/TestRuleTest.java
index 23d4bfbc8ff4..cc6db7d9eb34 100644
--- a/src/test/java/org/junit/rules/TestRuleTest.java
+++ b/src/test/java/org/junit/rules/TestRuleTest.java
@@ -1,11 +1,9 @@
package org.junit.rules;
-import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
import static org.junit.experimental.results.PrintableResult.testResult;
import static org.junit.experimental.results.ResultMatchers.hasSingleFailureContaining;
import static org.junit.experimental.results.ResultMatchers.isSuccessful;
@@ -14,11 +12,9 @@
import java.util.List;
import org.junit.After;
-import org.junit.Assume;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
-import org.junit.internal.AssumptionViolatedException;
import org.junit.runner.Description;
import org.junit.runner.JUnitCore;
import org.junit.runner.Result;
diff --git a/src/test/java/org/junit/runners/AllRunnersTests.java b/src/test/java/org/junit/runners/AllRunnersTests.java
index a51072c054a6..5464fb27f9ac 100644
--- a/src/test/java/org/junit/runners/AllRunnersTests.java
+++ b/src/test/java/org/junit/runners/AllRunnersTests.java
@@ -1,7 +1,6 @@
package org.junit.runners;
import org.junit.runner.RunWith;
-import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses;
import org.junit.runners.model.AllModelTests;
import org.junit.runners.parameterized.AllParameterizedTests;
diff --git a/src/test/java/org/junit/runners/RuleContainerTest.java b/src/test/java/org/junit/runners/RuleContainerTest.java
index 714d0dfdf660..8c6649c5022f 100644
--- a/src/test/java/org/junit/runners/RuleContainerTest.java
+++ b/src/test/java/org/junit/runners/RuleContainerTest.java
@@ -2,8 +2,6 @@
import static org.junit.Assert.assertEquals;
-import java.util.Arrays;
-
import org.junit.Test;
import org.junit.rules.MethodRule;
import org.junit.rules.TestRule;
diff --git a/src/test/java/org/junit/tests/SampleJUnit4Tests.java b/src/test/java/org/junit/tests/SampleJUnit4Tests.java
index c42026f2f79f..739f17bc679a 100644
--- a/src/test/java/org/junit/tests/SampleJUnit4Tests.java
+++ b/src/test/java/org/junit/tests/SampleJUnit4Tests.java
@@ -1,6 +1,15 @@
package org.junit.tests;
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Rule;
import org.junit.Test;
+import org.junit.rules.MethodRule;
+import org.junit.rules.TestRule;
+import org.junit.runners.model.FrameworkMethod;
+import org.junit.runners.model.Statement;
+
+import java.lang.reflect.Method;
/**
* Container for sample JUnit4-style tests used in integration tests.
@@ -23,6 +32,85 @@ public void alwaysThrows() {
}
}
+ public static class TestWithThrowingBeforeMethod {
+
+ @Before
+ public void alwaysThrows() {
+ new FakeClassUnderTest().throwsExceptionWithoutCause();
+ }
+
+ @Test
+ public void alwaysPasses() {
+ }
+ }
+
+ public static class ThrowingTestRule implements TestRule {
+
+ public Statement apply(
+ Statement base, org.junit.runner.Description description) {
+ new FakeClassUnderTest().throwsExceptionWithoutCause();
+ return base;
+ }
+ }
+
+ public static class TestWithThrowingTestRule {
+
+ @Rule
+ public final TestRule rule = new ThrowingTestRule();
+
+ @Test
+ public void alwaysPasses() {
+ }
+ }
+
+ public static class TestWithThrowingClassRule {
+
+ @ClassRule
+ public static final TestRule rule = new ThrowingTestRule();
+
+ @Test
+ public void alwaysPasses() {
+ }
+ }
+
+ public static class ThrowingMethodRule implements MethodRule {
+
+ public Statement apply(
+ Statement base, FrameworkMethod method, Object target) {
+ new FakeClassUnderTest().throwsExceptionWithoutCause();
+ return base;
+ }
+ }
+
+ public static class TestWithThrowingMethodRule {
+
+ @Rule
+ public final ThrowingMethodRule rule = new ThrowingMethodRule();
+
+ @Test
+ public void alwaysPasses() {
+ }
+ }
+
+ public static class TestWithSuppressedException {
+ public static final Method addSuppressed = initAddSuppressed();
+
+ static Method initAddSuppressed() {
+ try {
+ return Throwable.class.getMethod("addSuppressed", Throwable.class);
+ } catch (Throwable e) {
+ return null;
+ }
+ }
+
+ @Test
+ public void alwaysThrows() throws Exception {
+ final RuntimeException exception = new RuntimeException("error");
+ addSuppressed.invoke(exception, new RuntimeException("suppressed"));
+ throw exception;
+ }
+ }
+
private static class FakeClassUnderTest {
public void throwsExceptionWithCause() {
diff --git a/src/test/java/org/junit/tests/experimental/AssumptionTest.java b/src/test/java/org/junit/tests/experimental/AssumptionTest.java
index 45e94b026edc..e011619cf679 100644
--- a/src/test/java/org/junit/tests/experimental/AssumptionTest.java
+++ b/src/test/java/org/junit/tests/experimental/AssumptionTest.java
@@ -237,8 +237,8 @@ public void assumeWithExpectedExceptionShouldThrowAssumptionViolatedException()
assertThat(result.getAssumptionFailureCount(), is(1));
}
- final static String message = "Some random message string.";
- final static Throwable e = new Throwable();
+ static final String message = "Some random message string.";
+ static final Throwable e = new Throwable();
/**
* @see AssumptionTest#assumptionsWithMessage()
diff --git a/src/test/java/org/junit/tests/experimental/theories/AssumingInTheoriesTest.java b/src/test/java/org/junit/tests/experimental/theories/AssumingInTheoriesTest.java
index 758e6fbe2b2d..099b50fe14c4 100644
--- a/src/test/java/org/junit/tests/experimental/theories/AssumingInTheoriesTest.java
+++ b/src/test/java/org/junit/tests/experimental/theories/AssumingInTheoriesTest.java
@@ -31,7 +31,7 @@ public void theoryMeansOnlyAssumeShouldFail() throws InitializationError {
public static class TheoryWithNoUnassumedParameters {
@DataPoint
- public final static boolean FALSE = false;
+ public static final boolean FALSE = false;
@Theory
public void theoryWithNoUnassumedParameters(boolean value) {
diff --git a/src/test/java/org/junit/tests/experimental/theories/runner/SuccessfulWithDataPointFields.java b/src/test/java/org/junit/tests/experimental/theories/runner/SuccessfulWithDataPointFields.java
index 2b5d587be21c..80cfd897642d 100644
--- a/src/test/java/org/junit/tests/experimental/theories/runner/SuccessfulWithDataPointFields.java
+++ b/src/test/java/org/junit/tests/experimental/theories/runner/SuccessfulWithDataPointFields.java
@@ -195,7 +195,7 @@ public static void calledTwice() {
}
@RunWith(Theories.class)
- static public class StaticPublicNonDataPoints {
+ public static class StaticPublicNonDataPoints {
// DataPoint which passes the test
@DataPoint
public static int ZERO = 0;
diff --git a/src/test/java/org/junit/tests/junit3compatibility/AllTestsTest.java b/src/test/java/org/junit/tests/junit3compatibility/AllTestsTest.java
index 99468128907a..3f4a7f40435c 100644
--- a/src/test/java/org/junit/tests/junit3compatibility/AllTestsTest.java
+++ b/src/test/java/org/junit/tests/junit3compatibility/AllTestsTest.java
@@ -24,7 +24,7 @@ public void testSomething() {
@RunWith(AllTests.class)
public static class All {
- static public junit.framework.Test suite() {
+ public static junit.framework.Test suite() {
TestSuite suite = new TestSuite();
suite.addTestSuite(OneTest.class);
return suite;
@@ -60,7 +60,7 @@ public void testSomething() {
@RunWith(AllTests.class)
public static class AllJUnit4 {
- static public junit.framework.Test suite() {
+ public static junit.framework.Test suite() {
TestSuite suite = new TestSuite();
suite.addTest(new JUnit4TestAdapter(JUnit4Test.class));
return suite;
diff --git a/src/test/java/org/junit/tests/junit3compatibility/ForwardCompatibilityTest.java b/src/test/java/org/junit/tests/junit3compatibility/ForwardCompatibilityTest.java
index 34673e9fbd1b..79539d1497b4 100644
--- a/src/test/java/org/junit/tests/junit3compatibility/ForwardCompatibilityTest.java
+++ b/src/test/java/org/junit/tests/junit3compatibility/ForwardCompatibilityTest.java
@@ -19,7 +19,7 @@
public class ForwardCompatibilityTest extends TestCase {
static String fLog;
- static public class NewTest {
+ public static class NewTest {
@Before
public void before() {
fLog += "before ";
diff --git a/src/test/java/org/junit/tests/junit3compatibility/JUnit38ClassRunnerTest.java b/src/test/java/org/junit/tests/junit3compatibility/JUnit38ClassRunnerTest.java
index b7a1c515e3f2..429bde6910e7 100644
--- a/src/test/java/org/junit/tests/junit3compatibility/JUnit38ClassRunnerTest.java
+++ b/src/test/java/org/junit/tests/junit3compatibility/JUnit38ClassRunnerTest.java
@@ -53,7 +53,7 @@ public void canUnadaptAnAdapter() {
static int count;
- static public class OneTest extends TestCase {
+ public static class OneTest extends TestCase {
public void testOne() {
}
}
diff --git a/src/test/java/org/junit/tests/junit3compatibility/OldTests.java b/src/test/java/org/junit/tests/junit3compatibility/OldTests.java
index e8b3ab8eca32..bee32f50b84d 100644
--- a/src/test/java/org/junit/tests/junit3compatibility/OldTests.java
+++ b/src/test/java/org/junit/tests/junit3compatibility/OldTests.java
@@ -6,7 +6,7 @@
@RunWith(AllTests.class)
public class OldTests {
- static public Test suite() {
+ public static Test suite() {
return junit.tests.AllTests.suite();
}
}
diff --git a/src/test/java/org/junit/tests/junit3compatibility/SuiteMethodTest.java b/src/test/java/org/junit/tests/junit3compatibility/SuiteMethodTest.java
index edc9eac2b0c4..55c1cd119afe 100644
--- a/src/test/java/org/junit/tests/junit3compatibility/SuiteMethodTest.java
+++ b/src/test/java/org/junit/tests/junit3compatibility/SuiteMethodTest.java
@@ -18,7 +18,7 @@
public class SuiteMethodTest {
public static boolean wasRun;
- static public class OldTest extends TestCase {
+ public static class OldTest extends TestCase {
public OldTest(String name) {
super(name);
}
@@ -41,7 +41,7 @@ public void makeSureSuiteIsCalled() {
assertTrue(wasRun);
}
- static public class NewTest {
+ public static class NewTest {
@Test
public void sample() {
wasRun = true;
@@ -81,7 +81,7 @@ public void descriptionAndRunNotificationsAreConsistent() {
assertEquals(0, description.getChildren().size());
}
- static public class NewTestSuiteFails {
+ public static class NewTestSuiteFails {
@Test
public void sample() {
wasRun = true;
@@ -101,7 +101,7 @@ public void suiteIsUsedWithJUnit4Classes() {
assertFalse(wasRun);
}
- static public class NewTestSuiteNotUsed {
+ public static class NewTestSuiteNotUsed {
private static boolean wasIgnoredRun;
@Test
diff --git a/src/test/java/org/junit/tests/listening/ListenerTest.java b/src/test/java/org/junit/tests/listening/ListenerTest.java
index c76581a0d5c6..b3003394797b 100644
--- a/src/test/java/org/junit/tests/listening/ListenerTest.java
+++ b/src/test/java/org/junit/tests/listening/ListenerTest.java
@@ -8,7 +8,7 @@
import org.junit.runner.notification.RunListener;
public class ListenerTest {
- static private String log;
+ private static String log;
public static class OneTest {
@Test
diff --git a/src/test/java/org/junit/tests/manipulation/SingleMethodTest.java b/src/test/java/org/junit/tests/manipulation/SingleMethodTest.java
index cf62c98e4d79..a15340708fab 100644
--- a/src/test/java/org/junit/tests/manipulation/SingleMethodTest.java
+++ b/src/test/java/org/junit/tests/manipulation/SingleMethodTest.java
@@ -27,7 +27,7 @@
public class SingleMethodTest {
public static int count;
- static public class OneTimeSetup {
+ public static class OneTimeSetup {
@BeforeClass
public static void once() {
count++;
@@ -53,7 +53,7 @@ public void oneTimeSetup() throws Exception {
}
@RunWith(Parameterized.class)
- static public class ParameterizedOneTimeSetup {
+ public static class ParameterizedOneTimeSetup {
@Parameters
public static List