diff --git a/.classpath b/.classpath
index 9cecf517e451..f648ca63c5ff 100644
--- a/.classpath
+++ b/.classpath
@@ -2,7 +2,9 @@
+
+
-
+
diff --git a/.cvsignore b/.cvsignore
deleted file mode 100644
index a23e28ce5ddc..000000000000
--- a/.cvsignore
+++ /dev/null
@@ -1,10 +0,0 @@
-bin
-junit4.1
-junit*-SNAPSHOT-*
-target
-reports
-buildfile
-java.hprof.txt
-junit4.5-RC1
-junit4.*
-*.ser
diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 000000000000..43cf4920bd13
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,21 @@
+* text eol=lf
+*.gif binary
+*.GIF binary
+*.jar binary
+*.png binary
+*.jpg binary
+*.svg text eol=lf
+
+# These files do not have unix line endings. Do not normalize them for now.
+# Will fix these right before we cut JUnit 4.13.
+/src/main/java/org/junit/experimental/categories/CategoryFilterFactory.java -text
+/src/main/java/org/junit/experimental/categories/ExcludeCategories.java -text
+/src/main/java/org/junit/experimental/categories/IncludeCategories.java -text
+/src/main/java/org/junit/internal/Classes.java -text
+/src/main/java/org/junit/runner/FilterFactories.java -text
+/src/main/java/org/junit/runner/FilterFactory.java -text
+/src/main/java/org/junit/runner/FilterFactoryParams.java -text
+/src/main/java/org/junit/runner/JUnitCommandLineParseResult.java -text
+/src/test/java/org/junit/experimental/categories/CategoryFilterFactoryTest.java -text
+/src/test/java/org/junit/runner/FilterFactoriesTest.java -text
+/src/test/java/org/junit/runner/JUnitCommandLineParseResultTest.java -text
diff --git a/.gitignore b/.gitignore
index e9e6cf3180f6..54f5aa75e33f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,3 +3,11 @@ bin
junit4.*
target
MaxCore.max
+# IntelliJ
+.idea
+*.ipr
+*.iml
+*.iws
+out
+java.hprof.txt
+.DS_Store
diff --git a/.mvn/wrapper/maven-wrapper.jar b/.mvn/wrapper/maven-wrapper.jar
new file mode 100755
index 000000000000..41c70a7e0b7d
Binary files /dev/null and b/.mvn/wrapper/maven-wrapper.jar differ
diff --git a/.mvn/wrapper/maven-wrapper.properties b/.mvn/wrapper/maven-wrapper.properties
new file mode 100755
index 000000000000..37cb61582de0
--- /dev/null
+++ b/.mvn/wrapper/maven-wrapper.properties
@@ -0,0 +1 @@
+distributionUrl=https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.1.1/apache-maven-3.1.1-bin.zip
\ No newline at end of file
diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs
index 828dcb0ae0b0..d54f4c25de99 100644
--- a/.settings/org.eclipse.jdt.core.prefs
+++ b/.settings/org.eclipse.jdt.core.prefs
@@ -1,4 +1,4 @@
-#Fri Jul 17 17:27:50 EDT 2009
+#Mon Oct 12 21:57:10 EDT 2009
eclipse.preferences.version=1
org.eclipse.jdt.core.codeComplete.argumentPrefixes=
org.eclipse.jdt.core.codeComplete.argumentSuffixes=
@@ -46,7 +46,7 @@ org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore
org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning
org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=warning
org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore
-org.eclipse.jdt.core.compiler.problem.missingJavadocComments=warning
+org.eclipse.jdt.core.compiler.problem.missingJavadocComments=ignore
org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsOverriding=disabled
org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsVisibility=protected
org.eclipse.jdt.core.compiler.problem.missingJavadocTagDescription=no_tag
@@ -247,7 +247,7 @@ org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not in
org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert
org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert
-org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert
org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert
org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert
@@ -351,7 +351,7 @@ org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false
org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0
org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1
org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true
-org.eclipse.jdt.core.formatter.tabulation.char=tab
+org.eclipse.jdt.core.formatter.tabulation.char=space
org.eclipse.jdt.core.formatter.tabulation.size=4
org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false
org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true
diff --git a/.travis.settings.xml b/.travis.settings.xml
new file mode 100644
index 000000000000..332f39daa17b
--- /dev/null
+++ b/.travis.settings.xml
@@ -0,0 +1,22 @@
+
+
+
+ central
+ GCS Maven Central mirror
+ https://maven-central.storage-download.googleapis.com/maven2/
+ google-maven-central
+
+
+
+
+ junit-snapshot-repo
+ ${env.OSSRH_USERNAME}
+ ${env.OSSRH_PASSWORD}
+
+
+ junit-releases-repo
+ ${env.OSSRH_USERNAME}
+ ${env.OSSRH_PASSWORD}
+
+
+
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 000000000000..5b1744397f29
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,69 @@
+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/BUILDING b/BUILDING
new file mode 100644
index 000000000000..496eeb03b820
--- /dev/null
+++ b/BUILDING
@@ -0,0 +1,14 @@
+BUILDING FROM GITHUB:
+=====================
+
+git clone https://github.com/junit-team/junit4.git
+cd junit4
+mvn install
+
+BUILDING FROM JARS OR ZIPS:
+===========================
+
+The contents of the zip and jar files are largely maintained for historical
+reasons. We do not at this time have an official way to build from the src
+jar or zip. If this is an important missing feature, please let us know
+at http://github.com/junit-team/junit4/issues
diff --git a/CODING_STYLE.txt b/CODING_STYLE.txt
new file mode 100644
index 000000000000..fefecdd26f83
--- /dev/null
+++ b/CODING_STYLE.txt
@@ -0,0 +1,9 @@
+JUnit project uses the Google Java Style (https://github.com/google/styleguide) for all new
+code (under org.junit.*). Deviating from this, indentation is 4 spaces instead of 2.
+
+Be sure to set text file encoding to UTF-8 and line delimiters to UNIX style.
+
+Since not all code has been formatted yet, please format only code lines you changed to avoid extraneous changes.
+
+Legacy code (under junit.*) used the legacy guide specified in LEGACY_CODING_STYLE.txt in the
+project root.
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 000000000000..1943d567915c
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,45 @@
+## Project License: Eclipse Public License v1.0
+
+- You will only Submit Contributions where You have authored 100% of the content.
+- You will only Submit Contributions to which You have the necessary rights. This means that if You are employed You have received the necessary permissions from Your employer to make the Contributions.
+- Whatever content You Contribute will be provided under the Project License(s).
+
+## Coding Conventions
+
+### Formatting
+
+See [CODING_STYLE.txt](CODING_STYLE.txt) for how we format our code.
+
+## How to submit a pull request
+
+We love pull requests. Here is a quick guide:
+
+1. You need to have Maven and a JDK (at least version 1.5) installed.
+2. [Fork the repo](https://help.github.com/articles/fork-a-repo).
+3. [Create a new branch](https://help.github.com/articles/creating-and-deleting-branches-within-your-repository/) from `main`.
+4. Ensure that you have a clean state by running `./mvnw verify`.
+5. Add your change together with a test (tests are not needed for refactorings and documentation changes).
+6. Format your code: Import the JUnit project in Eclipse and use its formatter or apply the rules in the `CODING_STYLE` file manually. Only format the code you've changed; reformatting unrelated code makes it harder for us to review your changes.
+7. Run `./mvnw verify` again and ensure all tests are passing.
+8. Push to your fork and [submit a pull request](https://help.github.com/articles/creating-a-pull-request/).
+
+Now you are waiting on us. We review your pull request and at least leave some comments.
+
+
+Note that if you are thinking of providing a fix for one of the bugs or feature requests, it's usually
+a good idea to add a comment to the bug to make sure that there's agreement on how we should proceed.
+
+## Limitations
+
+The JUnit team is not accepting changes to the code under the following paths:
+
+* `src/main/java/junit`
+* `test/java/junit/tests/framework`
+* `test/java/junit/tests/extensions`
+
+The reasoning is that the JUnit team feels that our users should focus on using either the JUnit4 or JUnit5 APIs.
+
+The team is also reluctant to accept changes that only update code from one code style to another.
+Generally the code in JUnit was approved by at least one person, so two people agreed that the style was reasonable.
+
+To find other places where you can have an impact, please see the [Issues tagged "up-for-grabs"](https://github.com/junit-team/junit4/issues?q=is%3Aissue+is%3Aopen+label%3Aup-for-grabs).
diff --git a/KEYS b/KEYS
new file mode 100644
index 000000000000..0433e72f3343
--- /dev/null
+++ b/KEYS
@@ -0,0 +1,70 @@
+This file contains the PGP key that is used to sign releases.
+
+Importing: `pgp < KEYS` or `gpg --import KEYS`
+
+Adding a key:
+`pgp -kxa >> KEYS`,
+or `(pgpk -ll && pgpk -xa ) >> KEYS`,
+or `(gpg --list-sigs && gpg --armor --export ) >> KEYS`
+
+================================
+
+pub rsa4096 2018-04-08 [SC]
+ FF6E2C001948C5F2F38B0CC385911F425EC61B51
+uid [ unknown] Open Source Development
+sig 3 85911F425EC61B51 2018-04-08 Open Source Development
+sub rsa4096 2018-04-08 [E]
+sig 85911F425EC61B51 2018-04-08 Open Source Development
+
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+
+mQINBFrKW9IBEACkqUvM7hU1WqOOeb1gZ7pUsRliHuoUvYIrd+hdp+qhPmJ0NG0W
+YhZK5UtJBmqvtHKRkbwYxUuya9zlBmCfQFf0GpFKJ65JSrPSkZADI3aZ4aUkxIUw
+nIRoUHucmr10Xftpebr/zaJk5oR8RdaL5FapapmcZmAaHR9CDWB8XtI318u314jq
+M5rKatnAZMERoPugOvvuAOz4bfZKwdfCmZKfYUM/TMSrSinXrGExSW6z4RhtqmpC
+E5M/7OoVfvDynVJKqNazqgigpmMNhOyzAhQsiKh1K0akyxTZbjeZKsdYfhCXvq0q
+k9+KM/cTllQ54MPnFWiObLkHeK0Waw8bI/vAJ4h4x/XM9iGYpkXv7F2/FVsHQdPe
+YJcwD/CkD8KHyiPaRKMeApiUtZsdAHU0L4X/lNmcooea/7ipskruUgwcm+RdLhRZ
+P949t1e7nqDZfpEHy90NiFxmlRAPSNqBLwefxY/hwBgog2jabDALJVcLCMosFWPj
+MQhFlGSIODiVcW8folGIjzkyNZbNMWkwnl2QnWp/h2TAwYQJOMqcv2MG9o5pyzpx
+97Iz1ngq1FlM/gJnGnNUydP2tAjT2L2U3MP1uX/EdRChdgPqdolqYhdFfwCr0Fpf
+W527bUZpReHCEiQ29ABSnQ711mO+d9+qM6edRyHUoBWz89IHt8sCunuvNwARAQAB
+tC1PcGVuIFNvdXJjZSBEZXZlbG9wbWVudCA8bWFpbEBtYXJjcGhpbGlwcC5kZT6J
+Ak4EEwEIADgWIQT/biwAGUjF8vOLDMOFkR9CXsYbUQUCWspb0gIbAwULCQgHAgYV
+CAkKCwIEFgIDAQIeAQIXgAAKCRCFkR9CXsYbUQyRD/9xm3BqdpWcRCE5UyB6nbwV
+8TgzMmbOhpFhhcjzobly/pKAbcofKsjhreENJkfBVUo+zAFx21ToC5tbH20wRtIE
+vQVCP6sAIzhYWU1ohafqVFP4+PztNBuYTnS6vGvSwzp0IXLIIoxSxo0IOED9uUS9
+DTxh1n9NnDLDe2pfjrXBblQtLSW3W5ISDoUvcoyO7Hk1OByW6MNsSoLvXIUNeVhB
+ju9TfYxFACJSWBhUxJfgip9Y2GrNBJaYGLZrTAoW1Lh1H1DfLV3wHDClQ1+H+oyx
+IOZULEGYY3MgZTd6Ner2yNAUCB7gVa50NiCZXCS74m+XzMrTEsdWjSMUaOe+dL0I
+9MCrgi4ycUHWIfTKx9gGlIOo3hSDMN+8Nj33XPjLT8kcfoFeUX8jTOvC1HFfTuQJ
+x2t/dKHizdrS3F6A/JQa7v8GNTrZFnEXkwgRTf3ccLoo3gPwzNJeCm2xNjvne1VH
+fvxzwNmq8M05oicEigvEed2VMStMhvT7dSiMAf66rEJHjjaHAoNqbLDEATYrWUP2
+I52txHSSxSJohxVP6Ec6dERnqqYi0mVyzBPo7mmFFBisq74w8RvZXyzvXE3BTiDL
+we1E/Z/AXbtJye9DickQ/G6RFtVLbUHQfzyRS/65JPtlH8rqJr58YWlylGImVLwE
+OsKNQrwLZ0UkfaWV7wqr3rkCDQRaylvSARAAnQG636wliEOLkXN662OZS6Qz2+cF
+ltCWboq9oX9FnA1PHnTY2cAtwS214RfWZxkjg6Stau+d1Wb8TsF/SUN3eKRSyrkA
+xlX0v552vj3xmmfNsslQX47e6aEWZ0du0M8jw7/f7Qxp0InkBfpQwjSg4ECoH4cA
+6dOFJIdxBv8dgS4K90HNuIHa+QYfVSVMjGwOjD9St6Pwkbg1sLedITRo59Bbv0J1
+4nE9LdWbCiwNrkDr24jTewdgrDaCpN6msUwcH1E0nYxuKAetHEi2OpgBhaY3RQ6Q
+PQB6NywvmD0xRllMqu4hSp70pHFtm8LvJdWOsJ5we3KijHuZzEbBVTTl+2DhNMI0
+KMoh+P/OmyNOfWD8DL4NO3pVv+mPDZn82/eZ3XY1/oSQrpyJaCBjRKasVTtfiA/F
+gYqTml6qZMjy6iywg84rLezELgcxHHvjhAKd4CfxyuCCgnGT0iRLFZKw44ZmOUqP
+DkyvGRddIyHag1K7UaM/2UMn6iPMy7XWcaFiH5Huhz43SiOdsWGuwNk4dDxHdxmz
+Sjps0H5dkfCciOFhEc54AFcGEXCWHXuxVqIq/hwqTmVl1RY+PTcQUIOfx36WW1ix
+JQf8TpVxUbooK8vr1jOFF6khorDXoZDJNhI2VKomWp8Y38EPGyiUPZNcnmSiezx+
+MoQwAbeqjFMKG7UAEQEAAYkCNgQYAQgAIBYhBP9uLAAZSMXy84sMw4WRH0JexhtR
+BQJaylvSAhsMAAoJEIWRH0JexhtR0LEP/RvYGlaokoosAYI5vNORAiYEc1Ow2McP
+I1ZafHhcVxZhlwF48dAC2bYcasDX/PbEdcD6pwo8ZU8eI8Ht0VpRQxeV/sP01m2Y
+EpAuyZ6jI7IQQCGcwQdN4qzQJxMAASl9JlplH2NniXV1/994FOtesT59ePMyexm5
+7lzhYXP1PGcdt8dH37r6z3XQu0lHRG/KBn7YhyA3zwJcno324KdBRJiynlc7uqQq
++ZptU9fR1+Nx0uoWZoFMsrQUmY34aAOPJu7jGMTG+VseMH6vDdNhhZs9JOlD/e/V
+aF7NyadjOUD4j/ud7c0z2EwqjDKMFTHGbIdawT/7jartT+9yGUO+EmScBMiMuJUT
+dCP4YDh3ExRdqefEBff3uE/rAP73ndNYdIVq9U0gY0uSNCD9JPfj4aCN52y9a2pS
+7Dg7KB/Z8SH1R9IWP+t0HvVtAILdsLExNFTedJGHRh7uaC7pwRz01iivmtAKYICz
+ruqlJie/IdEFFK/sus6fZek29odTrQxx42HGHO5GCNyEdK9jKVAeuZ10vcaNbuBp
+iP7sf8/BsiEU4wHE8gjFeUPRiSjnERgXQwfJosLgf/K/SShQn2dCkYZRNF+SWJ6Z
+2tQxcW5rpUjtclV/bRVkUX21EYfwA6SMB811mI7AVy8WPXCe8La72ukmaxEGbpJ8
+mdzS2PJko7mm
+=l0XA
+-----END PGP PUBLIC KEY BLOCK-----
diff --git a/LEGACY_CODING_STYLE.txt b/LEGACY_CODING_STYLE.txt
new file mode 100644
index 000000000000..81e553b31f45
--- /dev/null
+++ b/LEGACY_CODING_STYLE.txt
@@ -0,0 +1,132 @@
+==================================
+Coding style
+==================================
+
+----------------------------------
+Tabs and Indents
+----------------------------------
+* Tab size : 4
+* Indent : 4
+* Continuation indent : 8
+* Label indent : 0
+
+> Don't use tab characters.
+
+----------------------------------
+Spaces
+----------------------------------
+Before Parentheses
+* if parentheses
+* for parentheses
+* while parentheses
+* switch parentheses
+* try parentheses
+* catch parentheses
+* synchronized parentheses
+
+Around Operators
+* Assignment operators (=, +=, …)
+* Logical operators (&&, ||)
+* Equality operators (==, !=)
+* Relational operators (<, >, <=, >=)
+* Bitwise operators (&, |, ^)
+* Additive operators (+, -)
+* Multiplicative operators (*, /, %)
+* Shift operators (<<, >>, >>>)
+
+Before Left Brace
+* Class left brace
+* Method left brace
+* if left brace
+* else left brace
+* for left brace
+* while left brace
+* do left brace
+* switch left brace
+* try left brace
+* catch left brace
+* finally left brace
+* synchronized left brace
+
+Before Keywords
+* else keyword
+* while keyword
+* catch keyword
+* finally keyword
+
+In Ternary Operator (?:)
+* Before ?
+* After ?
+* Before :
+* After :
+
+Within Type Arguments
+* After comma
+
+Other
+* After comma
+* After semicolon
+* After type cast
+
+----------------------------------
+Wrapping and Braces
+----------------------------------
+Braces placement
+* In class declaration : End of line
+* In method declaration : End of line
+* Other : End of line
+
+Use Of Braces
+* if() statement : When multiline
+* for() statement : When multiline
+* while() statement : When multiline
+* do .. while() statement : When multiline
+
+Annotations
+* Class annotations : Wrap always
+* Method annotations : Wrap always
+* Field annotations : Wrap always
+* Parameter annotations : Do not wrap
+* Local variable annotations : Do not wrap
+
+----------------------------------
+Blank Lines
+----------------------------------
+Minimum Blank Lines
+* Before package statement : 0
+* After package statement : 1
+* Before imports : 1
+* After imports : 1
+* Around class : 1
+* After class header : 0
+* After anonymous class header : 0
+* Around field in interface : 0
+* Around field : 0
+* Around method in interface : 1
+* Around method : 1
+* Before method body : 0
+
+----------------------------------
+JavaDoc
+----------------------------------
+Alignment
+* Align thrown exception descriptions
+
+Blank Lines
+* After description
+
+Other
+* Enable leading asterisks
+* Use @throws rather than @exception
+* Keep empty lines
+
+----------------------------------
+Imports
+----------------------------------
+import static (all other imports)
+
+import java.*
+import javax.*
+import com.*
+
+import (all other imports)
diff --git a/LICENSE-junit.txt b/LICENSE-junit.txt
new file mode 100644
index 000000000000..fb686291a055
--- /dev/null
+++ b/LICENSE-junit.txt
@@ -0,0 +1,214 @@
+JUnit
+
+Eclipse Public License - v 1.0
+
+THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE PUBLIC
+LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM
+CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT.
+
+1. DEFINITIONS
+
+"Contribution" means:
+
+ a) in the case of the initial Contributor, the initial code and
+ documentation distributed under this Agreement, and
+ b) in the case of each subsequent Contributor:
+
+ i) changes to the Program, and
+
+ ii) additions to the Program;
+
+ where such changes and/or additions to the Program originate from and are
+distributed by that particular Contributor. A Contribution 'originates' from a
+Contributor if it was added to the Program by such Contributor itself or anyone
+acting on such Contributor's behalf. Contributions do not include additions to
+the Program which: (i) are separate modules of software distributed in
+conjunction with the Program under their own license agreement, and (ii) are
+not derivative works of the Program.
+
+"Contributor" means any person or entity that distributes the Program.
+
+"Licensed Patents " mean patent claims licensable by a Contributor which are
+necessarily infringed by the use or sale of its Contribution alone or when
+combined with the Program.
+
+"Program" means the Contributions distributed in accordance with this Agreement.
+
+"Recipient" means anyone who receives the Program under this Agreement,
+including all Contributors.
+
+2. GRANT OF RIGHTS
+
+ a) Subject to the terms of this Agreement, each Contributor hereby grants
+Recipient a non-exclusive, worldwide, royalty-free copyright license to
+reproduce, prepare derivative works of, publicly display, publicly perform,
+distribute and sublicense the Contribution of such Contributor, if any, and
+such derivative works, in source code and object code form.
+
+ b) Subject to the terms of this Agreement, each Contributor hereby grants
+Recipient a non-exclusive, worldwide, royalty-free patent license under
+Licensed Patents to make, use, sell, offer to sell, import and otherwise
+transfer the Contribution of such Contributor, if any, in source code and
+object code form. This patent license shall apply to the combination of the
+Contribution and the Program if, at the time the Contribution is added by the
+Contributor, such addition of the Contribution causes such combination to be
+covered by the Licensed Patents. The patent license shall not apply to any
+other combinations which include the Contribution. No hardware per se is
+licensed hereunder.
+
+ c) Recipient understands that although each Contributor grants the
+licenses to its Contributions set forth herein, no assurances are provided by
+any Contributor that the Program does not infringe the patent or other
+intellectual property rights of any other entity. Each Contributor disclaims
+any liability to Recipient for claims brought by any other entity based on
+infringement of intellectual property rights or otherwise. As a condition to
+exercising the rights and licenses granted hereunder, each Recipient hereby
+assumes sole responsibility to secure any other intellectual property rights
+needed, if any. For example, if a third party patent license is required to
+allow Recipient to distribute the Program, it is Recipient's responsibility to
+acquire that license before distributing the Program.
+
+ d) Each Contributor represents that to its knowledge it has sufficient
+copyright rights in its Contribution, if any, to grant the copyright license
+set forth in this Agreement.
+
+3. REQUIREMENTS
+
+A Contributor may choose to distribute the Program in object code form under
+its own license agreement, provided that:
+
+ a) it complies with the terms and conditions of this Agreement; and
+
+ b) its license agreement:
+
+ i) effectively disclaims on behalf of all Contributors all warranties and
+conditions, express and implied, including warranties or conditions of title
+and non-infringement, and implied warranties or conditions of merchantability
+and fitness for a particular purpose;
+
+ ii) effectively excludes on behalf of all Contributors all liability for
+damages, including direct, indirect, special, incidental and consequential
+damages, such as lost profits;
+
+ iii) states that any provisions which differ from this Agreement are
+offered by that Contributor alone and not by any other party; and
+
+ iv) states that source code for the Program is available from such
+Contributor, and informs licensees how to obtain it in a reasonable manner on
+or through a medium customarily used for software exchange.
+
+When the Program is made available in source code form:
+
+ a) it must be made available under this Agreement; and
+
+ b) a copy of this Agreement must be included with each copy of the
+Program.
+
+Contributors may not remove or alter any copyright notices contained within the
+Program.
+
+Each Contributor must identify itself as the originator of its Contribution, if
+any, in a manner that reasonably allows subsequent Recipients to identify the
+originator of the Contribution.
+
+4. COMMERCIAL DISTRIBUTION
+
+Commercial distributors of software may accept certain responsibilities with
+respect to end users, business partners and the like. While this license is
+intended to facilitate the commercial use of the Program, the Contributor who
+includes the Program in a commercial product offering should do so in a manner
+which does not create potential liability for other Contributors. Therefore, if
+a Contributor includes the Program in a commercial product offering, such
+Contributor ("Commercial Contributor") hereby agrees to defend and indemnify
+every other Contributor ("Indemnified Contributor") against any losses, damages
+and costs (collectively "Losses") arising from claims, lawsuits and other legal
+actions brought by a third party against the Indemnified Contributor to the
+extent caused by the acts or omissions of such Commercial Contributor in
+connection with its distribution of the Program in a commercial product
+offering. The obligations in this section do not apply to any claims or Losses
+relating to any actual or alleged intellectual property infringement. In order
+to qualify, an Indemnified Contributor must: a) promptly notify the Commercial
+Contributor in writing of such claim, and b) allow the Commercial Contributor
+to control, and cooperate with the Commercial Contributor in, the defense and
+any related settlement negotiations. The Indemnified Contributor may
+participate in any such claim at its own expense.
+
+For example, a Contributor might include the Program in a commercial product
+offering, Product X. That Contributor is then a Commercial Contributor. If that
+Commercial Contributor then makes performance claims, or offers warranties
+related to Product X, those performance claims and warranties are such
+Commercial Contributor's responsibility alone. Under this section, the
+Commercial Contributor would have to defend claims against the other
+Contributors related to those performance claims and warranties, and if a court
+requires any other Contributor to pay any damages as a result, the Commercial
+Contributor must pay those damages.
+
+5. NO WARRANTY
+
+EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR
+IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each
+Recipient is solely responsible for determining the appropriateness of using
+and distributing the Program and assumes all risks associated with its exercise
+of rights under this Agreement, including but not limited to the risks and
+costs of program errors, compliance with applicable laws, damage to or loss of
+data, programs or equipment, and unavailability or interruption of operations.
+
+6. DISCLAIMER OF LIABILITY
+
+EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY
+CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST
+PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS
+GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+7. GENERAL
+
+If any provision of this Agreement is invalid or unenforceable under applicable
+law, it shall not affect the validity or enforceability of the remainder of the
+terms of this Agreement, and without further action by the parties hereto, such
+provision shall be reformed to the minimum extent necessary to make such
+provision valid and enforceable.
+
+If Recipient institutes patent litigation against any
+entity (including a cross-claim or counterclaim in a lawsuit) alleging that the
+Program itself (excluding combinations of the Program with other software or
+hardware) infringes such Recipient's patent(s), then such Recipient's rights
+granted under Section 2(b) shall terminate as of the date such litigation is
+filed.
+
+All Recipient's rights under this Agreement shall terminate if it fails to
+comply with any of the material terms or conditions of this Agreement and does
+not cure such failure in a reasonable period of time after becoming aware of
+such noncompliance. If all Recipient's rights under this Agreement terminate,
+Recipient agrees to cease use and distribution of the Program as soon as
+reasonably practicable. However, Recipient's obligations under this Agreement
+and any licenses granted by Recipient relating to the Program shall continue
+and survive.
+
+Everyone is permitted to copy and distribute copies of this Agreement, but in
+order to avoid inconsistency the Agreement is copyrighted and may only be
+modified in the following manner. The Agreement Steward reserves the right to
+publish new versions (including revisions) of this Agreement from time to time.
+No one other than the Agreement Steward has the right to modify this Agreement.
+The Eclipse Foundation is the initial Agreement Steward. The Eclipse Foundation may assign the responsibility to
+serve as the Agreement Steward to a suitable separate entity. Each new version
+of the Agreement will be given a distinguishing version number. The Program
+(including Contributions) may always be distributed subject to the version of
+the Agreement under which it was received. In addition, after a new version of
+the Agreement is published, Contributor may elect to distribute the Program
+(including its Contributions) under the new version. Except as expressly stated
+in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to
+the intellectual property of any Contributor under this Agreement, whether
+expressly, by implication, estoppel or otherwise. All rights in the Program not
+expressly granted under this Agreement are reserved.
+
+This Agreement is governed by the laws of the State of New York and the
+intellectual property laws of the United States of America. No party to this
+Agreement will bring a legal action under this Agreement more than one year
+after the cause of action arose. Each party waives its rights to a jury trial
+in any resulting litigation.
+
diff --git a/NOTICE.txt b/NOTICE.txt
new file mode 100644
index 000000000000..69b4faf86b2b
--- /dev/null
+++ b/NOTICE.txt
@@ -0,0 +1,5 @@
+ ===================================================================================
+ == Notices and attributions required by libraries that the project depends on ==
+ ===================================================================================
+
+ The JUnit depends on Java Hamcrest (http://hamcrest.org/JavaHamcrest/).
diff --git a/README b/README
deleted file mode 100644
index 3533670f18ea..000000000000
--- a/README
+++ /dev/null
@@ -1 +0,0 @@
-Please read README.html
\ No newline at end of file
diff --git a/README.md b/README.md
new file mode 100644
index 000000000000..f73f89ca5ed0
--- /dev/null
+++ b/README.md
@@ -0,0 +1,9 @@
+# JUnit 4
+JUnit is a simple framework to write repeatable tests. It is an instance of the xUnit architecture for unit testing frameworks.
+
+For more information, please visit:
+* [Wiki](https://github.com/junit-team/junit4/wiki)
+* [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)
diff --git a/acknowledgements.txt b/acknowledgements.txt
index 6ad6ccdaf101..bbc24dfe041f 100644
--- a/acknowledgements.txt
+++ b/acknowledgements.txt
@@ -53,4 +53,111 @@
2009 May 04
James Abbley: Submitted a patch that fixed the 2-second limit on Parallel execution.
-
\ No newline at end of file
+
+2009 Nov 16
+ Kristian Rosenvold: Submitted a patch (github#16) that improves thread-safety of
+ result counting
+2010 Feb 08
+ Paul Holser: Submitted additional test for TestName rule.
+
+2010 May 03
+ jonas22@github: Found bug (github#98) with assumptions and expected exceptions.
+
+2011 Jan 03
+ jens.schauder@freenet.de: Found bug (github#74) with Categories and
+ Parameterized.
+
+2011 Jan 18
+ Markus Keller: Reported bug (github#163):
+ Bad comparison failure message when using assertEquals(String, String)
+
+ Kevin Cooney (kcooney@github):
+ Patches for runLeaf, public multiple failure exception,
+ assertion messages and null.
+
+2011 Mar 04
+ Jerome Lacoste (lacostej@github) for initial patch for GH-191.
+
+2011 Apr 15
+ reinholdfuereder@github For initial test for GH-39
+
+2011 Apr 15
+ ububenheimer@github for bug report https://github.com/junit-team/junit4/issues/208
+
+2011 Apr 29
+ reinholdfuereder@github: bug report, test, and fix for GH-38:
+ ParentRunner filtering
+2011 Apr 29
+ Markus Keller (mkeller@github): Report for GH-187:
+ Unintentional dependency on Java 6
+
+2011 May 31
+ Kevin Cooney (kcooney@github): Patches for filtering test suites:
+ copy List returned by getChildren() before mutating it;
+ optimize ParentRunner.filter for nested suites;
+ optimize Filter.intersect for common cases
+
+2011 Jun 06
+ Vampire@github: Report for GH-235: 4.7 release notes incorrect.
+
+2011 Jun 24
+ Samuel Le Berrigaud (sleberrigaud@github): Report for GH-248:
+ protected BlockJUnit4ClassRunner#rules method removed from 4.8.2
+
+2011 Jun 24
+ Daniel Rothmaler (drothmaler@github):
+ #299: random temp file/folder creation
+ #300: ErrorCollector.checkThat overload
+
+2011 Jun 25
+ Juan Cortez (jcortez@github): Fixed issue #219 where floats were being
+ printed and represented as doubles in error messages.
+
+2011 Jul 06
+ Stefan Birkner: Fixed wrong documentation of ClassRule (github#254).
+
+2011 Jul 08
+ Paul Holser (pholser@alumni.rice.edu): Beginnings of fix for GH-64:
+ Theories doesn't honor parameterized types
+
+2011 Jul 09
+ Nigel Charman: Reported Rules bugs github#257 and gihub#258.
+
+2011 Jul 09
+ Stefan Birkner: Fixed rules bugs (github#257, gihub#258, github#260).
+
+2011 Jul 09
+ Stefan Birkner: Fixed rules bugs (github#257, gihub#258, github#260).
+
+2011 Jul 16
+ Rob Dawson: Submitted a patch that makes Results serlializable.
+
+2011 Jul 20
+ Asaf Ary, Stefan Birkner: Fixed FailOnTimeout class (github#265).
+
+2011 Jul 22
+ Andreas Köhler, Stefan Birkner: Fixed wrong documentation of Parameterized (github#89).
+
+2011 Jul 28
+ electrickery, Stefan Birkner: Fixed typo in JavaDoc (github#134).
+
+2011 Aug 07
+ Esko Luontola: Fixed TemporaryFolder creating files in the current working directory (github#278).
+
+2011 Aug 09
+ Stefan Birkner: Fixed JavaDoc links.
+
+2011 Aug 10
+ rodolfoliviero@github and JoseRibeiro@github: feature to create recursive temporary folders.
+
+2011 Aug 12
+ Esko Luontola: Fixed syntax error in Parameterized's usage example (github#285).
+
+2011 Sep 09
+ Robert Munteanu, Stefan Birkner:
+ TestWatcher and TestWatchman don't call failed when assumption is violated (github#296).
+ digulla@github, Stefan Birkner: Removed useless code (github#289).
+
+== NOTE: as of September 2011, we have stopped recording contributions here.
+ For a full list of everyone who has contributed great bug reports and code, please see
+ http://github.com/junit-team/junit4
diff --git a/build.xml b/build.xml
deleted file mode 100644
index fef35b3393e2..000000000000
--- a/build.xml
+++ /dev/null
@@ -1,179 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/build/.cvsignore b/build/.cvsignore
deleted file mode 100644
index 5d6a3e25c536..000000000000
--- a/build/.cvsignore
+++ /dev/null
@@ -1,4 +0,0 @@
-Changes
-java.hprof.txt
-historical_javadoc
-compare_with_44.sh
diff --git a/build/.releaserc b/build/.releaserc
deleted file mode 100644
index b1dc30f57fe5..000000000000
--- a/build/.releaserc
+++ /dev/null
@@ -1,8 +0,0 @@
-sf_user = dsaff
-sf_group_id = 15278
-sf_package_id = 226053
-cpan_user =
-sf_release_match = junit-(.*).jar
-sf_release_replace = $1
-sf_type_id = 2601
-sf_processor_id = 8500
\ No newline at end of file
diff --git a/build/experimental-use-of-antunit/build.xml b/build/experimental-use-of-antunit/build.xml
deleted file mode 100644
index d45c9edad1df..000000000000
--- a/build/experimental-use-of-antunit/build.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/build/experimental-use-of-antunit/junit-remote.ant b/build/experimental-use-of-antunit/junit-remote.ant
deleted file mode 100644
index dad33c468dc8..000000000000
--- a/build/experimental-use-of-antunit/junit-remote.ant
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/build/experimental-use-of-antunit/junit-slow.ant b/build/experimental-use-of-antunit/junit-slow.ant
deleted file mode 100644
index b4d0219007f2..000000000000
--- a/build/experimental-use-of-antunit/junit-slow.ant
+++ /dev/null
@@ -1,51 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/build/experimental-use-of-antunit/junit.ant b/build/experimental-use-of-antunit/junit.ant
deleted file mode 100644
index 86a4a26bfd56..000000000000
--- a/build/experimental-use-of-antunit/junit.ant
+++ /dev/null
@@ -1,140 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/build/experimental-use-of-antunit/junit.properties b/build/experimental-use-of-antunit/junit.properties
deleted file mode 100644
index 578e606d12e8..000000000000
--- a/build/experimental-use-of-antunit/junit.properties
+++ /dev/null
@@ -1,9 +0,0 @@
-junitdir=../..
-antdist=temp-dist-directory-for-ant-unit
-antdistdir=${junitdir}/${antdist}
-testjavadoczip=new-england-javadoc.zip
-exttestjavadoczip=${junitdir}/${testjavadoczip}
-tempdir=tempdir
-test.jarfile=junit-test.version.jar
-test.srcjarfile=junit-test.version-src.jar
-test.hamcrestsrc=${antdist}/temp-hamcrest-for-ant-unit
\ No newline at end of file
diff --git a/build/experimental-use-of-antunit/lib/ant-antunit-1.0.jar b/build/experimental-use-of-antunit/lib/ant-antunit-1.0.jar
deleted file mode 100644
index d8e2fba811cc..000000000000
Binary files a/build/experimental-use-of-antunit/lib/ant-antunit-1.0.jar and /dev/null differ
diff --git a/build/experimental-use-of-antunit/lib/hamcrest-SNAPSHOT.zip b/build/experimental-use-of-antunit/lib/hamcrest-SNAPSHOT.zip
deleted file mode 100644
index c67b09670faf..000000000000
Binary files a/build/experimental-use-of-antunit/lib/hamcrest-SNAPSHOT.zip and /dev/null differ
diff --git a/build/experimental-use-of-antunit/macros.ant b/build/experimental-use-of-antunit/macros.ant
deleted file mode 100644
index 1125d8614ffe..000000000000
--- a/build/experimental-use-of-antunit/macros.ant
+++ /dev/null
@@ -1,32 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/build/experimental-use-of-antunit/touch.ant b/build/experimental-use-of-antunit/touch.ant
deleted file mode 100644
index d7d64db4a786..000000000000
--- a/build/experimental-use-of-antunit/touch.ant
+++ /dev/null
@@ -1,18 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/build/lib/commons-net-1.4.1.jar b/build/lib/commons-net-1.4.1.jar
deleted file mode 100644
index 9666a92c8009..000000000000
Binary files a/build/lib/commons-net-1.4.1.jar and /dev/null differ
diff --git a/build/lib/jakarta-oro-2.0.8.jar b/build/lib/jakarta-oro-2.0.8.jar
deleted file mode 100644
index 23488d2600f5..000000000000
Binary files a/build/lib/jakarta-oro-2.0.8.jar and /dev/null differ
diff --git a/build/profile_junit.sh b/build/profile_junit.sh
deleted file mode 100644
index 660dcc0329ff..000000000000
--- a/build/profile_junit.sh
+++ /dev/null
@@ -1,2 +0,0 @@
-java -classpath ../bin:../lib/hamcrest-core-1.1.jar -agentlib:hprof=cpu=samples,depth=18 org.junit.runner.JUnitCore org.junit.tests.AllTests
-cat java.hprof.txt
\ No newline at end of file
diff --git a/build/release b/build/release
deleted file mode 100755
index 53bdf75b7c59..000000000000
--- a/build/release
+++ /dev/null
@@ -1,389 +0,0 @@
-#!/usr/bin/perl
-
-eval 'exec /usr/bin/perl -S $0 ${1+"$@"}'
- if 0; # not running under some shell
-use strict;
-use warnings;
-
-# $Id: release,v 1.1 2007/09/04 17:59:38 dsaff Exp $
-
-=head1 NAME
-
-release - upload files to the CPAN and SourceForge.net
-
-=head1 SYNOPSIS
-
- release [ LOCAL_FILE [ REMOTE_FILE ] ]
-
- # try a dry run without uploading anything
- release -t
-
- # print a help message
- release -h
-
- # print debugging information
- release -d
-
-=head1 DESCRIPTION
-
-This is the prototype program for using Module::Release. You should
-modify it to fit your needs.
-
-This program automates Perl module releases. It makes the
-distribution, tests it, checks that source control is up to date, tags
-source control, uploads it to the PAUSE anonymous FTP directory and to
-the incoming directory for SourceForge.net, claims it on PAUSE for
-your CPAN account, and releases it on SourceForge.net.
-
-By default this script assumes that you use CVS, but recognizes SVN
-and switches when appropriate.
-
-=head2 Process
-
-The release script checks many things before it actually releases the
-file. Some of these are annoying, but they are also the last line of
-defense against releasing bad distributions.
-
-=over 4
-
-=item Read the configuration data
-
-Look in the current working directory for C<.releaserc>. See the
-Configuration section. If release cannot find the configuration file,
-it dies.
-
-=item Test and make the distribution
-
-Run make realclean, perl Makefile.PL, make test, make dist, make
-disttest. If testing fails, release dies. make dist provides the
-name of the distribution if LOCAL_FILE is not provided on the command
-line.
-
-=item Check that source control is up-to-date
-
-If there are modified files, added files, or extra files so that
-source control complains, fail.
-
-=item Upload to PAUSE and SourceForge.net
-
-Simply drop the distribution in the incoming/ directory of these
-servers.
-
-=item Claim the file on PAUSE
-
-Connect to the PAUSE web thingy and claim the uploaded file for your
-CPAN account.
-
-=item Tag the repository
-
-Use the version number (in the distribution name) to tag the
-repository. You should be able to checkout the code from any release.
-
-=item Release to SourceForge.net
-
-The release name is the distribution name without the .tar.gz. The
-file name is the distribution name. SourceForge.net divides things
-into projects (with project IDs) and packages within the project (with
-package IDs). Specify these in the configuration file.
-
-=back
-
-=head2 Configuration
-
-The release script uses a configuration file in the current working
-directory. The file name is F<.releaserc>. Although most of the
-information is the same for all of your projects, the C
-is probably different. You can get the C from the data
-in the Quick Release Form.
-
-release's own F<.releaserc> looks like this:
-
- sf_user comdog
- sf_group_id 36221
- sf_package_id 56559
- cpan_user BDFOY
-
-=over 4
-
-=item cpan_user
-
-=item sf_user
-
-If C or C is set to C<< >>, the program will
-skip releasing for that system. You must release for at least one system.
-
-=item sf_group_id
-
-=item sf_package_id
-
-=item sf_processor_id
-
-=item sf_type_id
-
-=item sf_release_match
-
-=item sf_release_replace
-
-To find C and C, go to the Add/Edit
-Release page for your project. The link for "[Add Release]" might
-look something like this (this is the link for the F package
-itself):
-
- https://sourceforge.net/project/admin/newrelease.php?package_id=56559&group_id=36221
-
-so C is 56559 and C is 36221.
-
-C and C are optional, and default to "Any"
-and "Source .gz". See the HTML in a file release form on SourceForge.net
-for other options.
-
-C and C are for defining the release
-name, if you don't like the default. For example, the default would
-set the name for this program to something like "release-0.10".
-But if you want the name to be only the version number, set
-C and C.
-
-=item passive_ftp
-
-Set C to "y" or "yes" for passive FTP transfers. Usually
-this is to get around a firewall issue.
-
-=item release_subclass
-
-Specify the name of a subclass to use instead of Module::Release. The
-subclass can override any of the Module::Release methods. This makes
-it possible to maintain your own local releasing procedures. For
-instance, one such subclass might look like this:
-
- package Module::Release::KWILLIAMS;
- use base qw(Module::Release);
-
- sub make_cvs_tag {
- my $self = shift;
- (my $version) = $self->{remote} =~ / - (\d[\w.]*) \.tar \.gz $/x;
- $version =~ s/[^a-z0-9_]/_/gi;
- return "release-$version";
- }
- 1;
-
-To use this subclass, you'd put it in your C<@INC> somewhere, then set
-C to C.
-
-=back
-
-=head2 Environment
-
-=over 4
-
-=item * CPAN_PASS
-
-=item * SF_PASS
-
-release reads the C and C environment variables to
-set the passwords for PAUSE and SourceForge.net, respectively. Of course,
-you don't need to set the password for a system you're not uploading to.
-
-=item * RELEASE_DEBUG
-
-The C environment variable sets the debugging value,
-which is 0 by default. Set C to a true value to get
-debugging output.
-
-=item * PERL
-
-The C environment variable sets the path to perl for use in the
-make; otherwise, the perl used to run release will be used.
-
-=back
-
-=head1 TO DO
-
-=over 4
-
-=item * check make disttest (to catch MANIFEST errors) -- needs error catching and reporting
-
-=back
-
-=head1 SOURCE AVAILABILITY
-
-This source is part of a SourceForge.net project which always has the
-latest sources in CVS, as well as all of the previous releases.
-
- http://sourceforge.net/projects/brian-d-foy/
-
-If, for some reason, I disappear from the world, one of the other
-members of the project can shepherd this software appropriately.
-
-=head1 AUTHOR
-
-brian d foy, C<< >>
-
-=head1 COPYRIGHT AND LICENSE
-
-Copyright 2002-2007, brian d foy, All rights reserved.
-
-You may use this software under the same terms as Perl itself.
-
-=head1 CREDITS
-
-Ken Williams turned the original release(1) script into a module.
-
-Andy Lester contributed to the module and script.
-
-=cut
-
-use Getopt::Std;
-use Module::Release;
-
-my $class = "Module::Release";
-
-
-# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
-my %opts;
-getopts('hdt', \%opts) or $opts{h} = 1;
-
-if( $opts{h} )
- {
- print <<"USE";
-
-Use: release -hdt [ LOCAL_FILE [ REMOTE_FILE ] ]
-
-Will upload current release LOCAL_FILE, naming it REMOTE_FILE. Will
-get LOCAL_FILE and REMOTE_FILE automatically (using same name for
-both) if not supplied.
-
- -h This help
- -d Print extra debugging information
- -t Just make and test distribution, don't tag/upload
-
-The program works in the current directory, and looks for a .releaserc
-or releaserc file and the environment for its preferences. See
-`perldoc $0`, for more information.
-
-USE
-
- exit;
- }
-
-
-# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
-if( -d '.svn' )
- {
- $class = "Module::Release::Subversion";
-
- print STDERR "I see an .svn directory, so I'm loading $class"
- if $opts{d};
-
- eval "use Module::Release::Subversion";
- die "Could not load $class: $@\n" if $@;
- }
-
-my( $script_version ) =
- sprintf "%1.%02d", q$Revision: 1.1 $ =~ m/ (\d+) /xg;
-
-
-# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
-my %params;
-$params{local} = shift @ARGV if @ARGV;
-
-if( @ARGV )
- {
- $params{remote} = shift @ARGV;
- }
-elsif( $params{local} )
- {
- $params{remote} = $params{local};
- }
-
-$params{debug} = 1 if $opts{d};
-
-my $release = $class->new( %params );
-
-print STDERR "release $script_version, using $class " . $class->VERSION . "\n"
- if $release->debug;
-
-
-# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
-$release->clean;
-$release->build_makefile;
-$release->test;
-$release->dist;
-$release->check_kwalitee;
-$release->dist_test;
-# $release->check_cvs;
-
-my $Version = $release->dist_version;
-
-print STDERR "dist version is $Version\n" if $release->debug;
-
-exit if $opts{t};
-
-
-# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
-my $Changes = do {
- my $changes = "Changes";
- my $bak = $changes . ".bak";
-
- die "Changes file does not exist!\n" unless -e $changes;
-
- print "\n", "-" x 73, "\n", "Enter Changes section\n\n> ";
-
- my $str = $Version . " - " . localtime() . "\n";
-
- while( )
- {
- $_ =~ s/^(\S)/\t$1/; # always indent
-
- $str .= $_;
- print "> ";
- }
-
- $str .= "\n";
-
- rename $changes, $bak or die "Could not backup $changes. $!\n";
- open my $in, $bak or die "Could not read old $changes file! $!\n";
- open my $out, ">", $changes;
-
- while( <$in> )
- {
- print $out $_;
- last unless m/\S/;
- }
-
- print $out $str;
-
- print $out $_ while( <$in> );
-
- close $in;
- close $out;
-
- my $command = do {
- if( -d 'CVS' ) { 'cvs' }
- elsif( -d '.svn' ) { 'svn' }
- };
-
- my $cvs_commit = `$command commit -m "* for version $Version" 2>&1`;
-
- print $cvs_commit;
-
- $str;
- };
-
-
-# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
-$release->clean;
-$release->build_makefile;
-$release->dist;
-
-$release->check_for_passwords;
-$release->ftp_upload;
-$release->pause_claim;
-$release->cvs_tag;
-
-$release->sf_login;
-$release->sf_qrs;
-$release->sf_release;
-
-print "Done.\n";
-
-__END__
diff --git a/build/upload_docs.sh b/build/upload_docs.sh
deleted file mode 100644
index b9f402b01960..000000000000
--- a/build/upload_docs.sh
+++ /dev/null
@@ -1,2 +0,0 @@
-scp -r ../doc/* dsaff@web.sourceforge.net:/home/groups/j/ju/junit/htdocs/doc
-scp ../doc/homepage.html dsaff@web.sourceforge.net:/home/groups/j/ju/junit/htdocs/index.html
\ No newline at end of file
diff --git a/cpl-v10.html b/cpl-v10.html
deleted file mode 100644
index 36aa208d4a29..000000000000
--- a/cpl-v10.html
+++ /dev/null
@@ -1,125 +0,0 @@
-
-
-
-Common Public License - v 1.0
-
-
-
-
-
-
-
Common Public License - v 1.0
-
-
THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT.
-
-
1. DEFINITIONS
-
"Contribution" means:
-
-
a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and
-b) in the case of each subsequent Contributor:
-
-
-
i) changes to the Program, and
-
-
-
ii) additions to the Program;
-
-
-
where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program.
-
-
-
"Contributor" means any person or entity that distributes the Program.
-
-
"Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program.
-
-
"Program" means the Contributions distributed in accordance with this Agreement.
-
-
"Recipient" means anyone who receives the Program under this Agreement, including all Contributors.
-
-
2. GRANT OF RIGHTS
-
-
a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form.
-
-
-
-
-
-
b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder.
-
-
-
-
-
-
c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program.
-
-
-
-
-
-
d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement.
-
-
-
-
-
3. REQUIREMENTS
-
A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that:
-
-
a) it complies with the terms and conditions of this Agreement; and
-
-
-
b) its license agreement:
-
-
-
i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose;
-
-
-
ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits;
-
-
-
iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and
-
-
-
iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange.
-
-
-
-
-
When the Program is made available in source code form:
-
-
a) it must be made available under this Agreement; and
-
-
-
b) a copy of this Agreement must be included with each copy of the Program.
-
-
-
Contributors may not remove or alter any copyright notices contained within the Program.
-
-
Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution.
-
-
4. COMMERCIAL DISTRIBUTION
-
Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense.
-
-
For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages.
-
-
5. NO WARRANTY
-
EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations.
-
-
6. DISCLAIMER OF LIABILITY
-
EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
-
-
7. GENERAL
-
If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable.
-
-
If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, if Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed.
-
-
All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive.
-
-
Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved.
-
-
This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation.
-
-
-
-
-
-
\ No newline at end of file
diff --git a/doc/ReleaseNotes4.10.html b/doc/ReleaseNotes4.10.html
new file mode 100644
index 000000000000..b6b9483b8a74
--- /dev/null
+++ b/doc/ReleaseNotes4.10.html
@@ -0,0 +1,93 @@
+
Summary of Changes in version 4.10
+
+
A full summary of commits between 4.9 and 4.10 is on github
+
+
junit-dep has correct contents
+
+
junit-dep-4.9.jar incorrectly contained hamcrest classes, which could lead to version conflicts in projects that depend on hamcrest directly. This is fixed in 4.10 [@dsaff, closing gh-309]
+
+
RuleChain
+
+
The RuleChain rule allows ordering of TestRules:
+
+
public static class UseRuleChain {
+ @Rule
+ public TestRule chain= RuleChain
+ .outerRule(new LoggingRule("outer rule")
+ .around(new LoggingRule("middle rule")
+ .around(new LoggingRule("inner rule");
+
+ @Test
+ public void example() {
+ assertTrue(true);
+ }
+}
+
TemporaryFolder#newFolder(String... folderNames) creates recursively deep temporary folders
+[@rodolfoliviero, closing gh-283]
+
TemporaryFolder#newFile() creates a randomly named new file, and #newFolder() creates a randomly named new folder
+[@Daniel Rothmaler, closing gh-299]
+
+
+
Theories
+
+
The Theories runner does not anticipate theory parameters that have generic
+types, as reported by github#64. Fixing this won't happen until Theories is
+moved to junit-contrib. In anticipation of this, 4.9.1 adds some of the
+necessary machinery to the runner classes, and deprecates a method that only
+the Theories runner uses, FrameworkMethod#producesType().
+The Common Public License that JUnit is released under is now included
+in the source repository.
+
+
Thanks to @pholser for identifying a potential resolution for github#64
+and initiating work on it.
+
+
Bug fixes
+
+
+
Built-in Rules implementations
+
+
TemporaryFolder should not create files in the current working directory if applying the rule fails
+[@orfjackal, fixing gh-278]
+
TestWatcher and TestWatchman should not call failed for AssumptionViolatedExceptions
+[@stefanbirkner, fixing gh-296]
Useless code in RunAfters [@stefanbirkner, fixing gh-289]
+
Parameterized test classes should be able to have @Category annotations
+[@dsaff, fixing gh-291]
+
Error count should be initialized in junit.tests.framework.TestListenerTest [@stefanbirkner, fixing gh-225]
+
AssertionFailedError constructor shouldn't call super with null message [@stefanbirkner, fixing gh-318]
+
Clearer error message for non-static inner test classes [@stefanbirkner, fixing gh-42]
+
+
+
+
Minor changes
+
+
+
Description, Result and Failure are Serializable [@ephox-rob, closing gh-101]
+
FailOnTimeout is reusable, allowing for retrying Rules [@stefanbirkner, closing gh-265]
+
New ErrorCollector.checkThat overload, that allows you to specify a reason [@drothmaler, closing gh-300]
+
diff --git a/doc/ReleaseNotes4.10.md b/doc/ReleaseNotes4.10.md
new file mode 100644
index 000000000000..5f19bf744889
--- /dev/null
+++ b/doc/ReleaseNotes4.10.md
@@ -0,0 +1,86 @@
+## Summary of Changes in version 4.10 ##
+
+Thanks to a full cast of contributors of bug fixes and new features.
+
+A full summary of commits between 4.9 and 4.10 is on [github](https://github.com/junit-team/junit4/compare/r4.9...r4.10)
+
+### junit-dep has correct contents ###
+
+junit-dep-4.9.jar incorrectly contained hamcrest classes, which could lead to version conflicts in projects that depend on hamcrest directly. This is fixed in 4.10 [@dsaff, closing gh-309]
+
+### RuleChain ###
+
+The RuleChain rule allows ordering of TestRules:
+
+```java
+public static class UseRuleChain {
+ @Rule
+ public TestRule chain= RuleChain
+ .outerRule(new LoggingRule("outer rule")
+ .around(new LoggingRule("middle rule")
+ .around(new LoggingRule("inner rule");
+
+ @Test
+ public void example() {
+ assertTrue(true);
+ }
+}
+```
+
+writes the log
+
+ starting outer rule
+ starting middle rule
+ starting inner rule
+ finished inner rule
+ finished middle rule
+ finished outer rule
+
+### TemporaryFolder ###
+
+- `TemporaryFolder#newFolder(String... folderNames)` creates recursively deep temporary folders
+ [@rodolfoliviero, closing gh-283]
+- `TemporaryFolder#newFile()` creates a randomly named new file, and `#newFolder()` creates a randomly named new folder
+ [@Daniel Rothmaler, closing gh-299]
+
+### Theories ###
+
+The `Theories` runner does not anticipate theory parameters that have generic
+types, as reported by github#64. Fixing this won't happen until `Theories` is
+moved to junit-contrib. In anticipation of this, 4.9.1 adds some of the
+necessary machinery to the runner classes, and deprecates a method that only
+the `Theories` runner uses, `FrameworkMethod`#producesType().
+The Common Public License that JUnit is released under is now included
+in the source repository.
+
+Thanks to `@pholser` for identifying a potential resolution for github#64
+and initiating work on it.
+
+### Bug fixes ###
+
+- Built-in Rules implementations
+ - TemporaryFolder should not create files in the current working directory if applying the rule fails
+ [@orfjackal, fixing gh-278]
+ - TestWatcher and TestWatchman should not call failed for AssumptionViolatedExceptions
+ [@stefanbirkner, fixing gh-296]
+- Javadoc bugs
+ - Assert documentation [@stefanbirkner, fixing gh-134]
+ - ClassRule [@stefanbirkner, fixing gh-254]
+ - Parameterized [@stefanbirkner, fixing gh-89]
+ - Parameterized, again [@orfjackal, fixing gh-285]
+- Miscellaneous
+ - Useless code in RunAfters [@stefanbirkner, fixing gh-289]
+ - Parameterized test classes should be able to have `@Category` annotations
+ [@dsaff, fixing gh-291]
+ - Error count should be initialized in junit.tests.framework.TestListenerTest [@stefanbirkner, fixing gh-225]
+ - AssertionFailedError constructor shouldn't call super with null message [@stefanbirkner, fixing gh-318]
+ - Clearer error message for non-static inner test classes [@stefanbirkner, fixing gh-42]
+
+### Minor changes ###
+
+- Description, Result and Failure are Serializable [@ephox-rob, closing gh-101]
+- FailOnTimeout is reusable, allowing for retrying Rules [@stefanbirkner, closing gh-265]
+- New `ErrorCollector.checkThat` overload, that allows you to specify a reason [@drothmaler, closing gh-300]
+
+
+
diff --git a/doc/ReleaseNotes4.10.txt b/doc/ReleaseNotes4.10.txt
new file mode 100644
index 000000000000..bc63f07611c7
--- /dev/null
+++ b/doc/ReleaseNotes4.10.txt
@@ -0,0 +1 @@
+Please see ReleaseNotes4.10.md
diff --git a/doc/ReleaseNotes4.11.html b/doc/ReleaseNotes4.11.html
new file mode 100644
index 000000000000..fefd79f6910a
--- /dev/null
+++ b/doc/ReleaseNotes4.11.html
@@ -0,0 +1,121 @@
+
Summary of changes in version 4.11
+
+
Matchers: Upgrade to Hamcrest 1.3
+
+
JUnit now uses the latest version of Hamcrest. Thus, you can use all the available matchers and benefit from an improved assertThat which will now print the mismatch description from the matcher when an assertion fails.
Running this test will return the following failure message:
+
+
Expected: a String of length that is <0>
+ but: length was <12>
+
+
+
Most of the matchers in JUnitMatchers have been deprecated. Please use org.hamcrest.CoreMatchers directly.
+
+
Parameterized Tests
+
+
In order to easily identify the individual test cases in a Parameterized test, you may provide a name using the @Parameters annotation. This name is allowed to contain placeholders that are replaced at runtime:
+
+
+
{index}: the current parameter index
+
{0}, {1}, …: the first, second, and so on, parameter value
In the example given above, the Parameterized runner creates names like [1: fib(3)=2]. If you don't specify a name, the current parameter index will be used by default.
+
+
Test execution order
+
+
By design, JUnit does not specify the execution order of test method invocations. Until now, the methods were simply invoked in the order returned by the reflection API. However, using the JVM order is unwise since the Java platform does not specify any particular order, and in fact JDK 7 returns a more or less random order. Of course, well-written test code would not assume any order, but some does, and a predictable failure is better than a random failure on certain platforms.
+
+
From now on, JUnit will by default use a deterministic, but not predictable, order (MethodSorters.DEFAULT). To change the test execution order simply annotate your test class using @FixMethodOrder and specify one of the available MethodSorters:
+
+
+
@FixMethodOrder(MethodSorters.JVM): Leaves the test methods in the order returned by the JVM. This order may vary from run to run.
+
@FixMethodOrder(MethodSorters.NAME_ASCENDING): Sorts the test methods by method name, in lexicographic order.
+
+
+
Maven artifacts
+
+
Up until now there were two Maven artifacts for JUnit: junit:junit-dep and junit:junit. From a Maven point-of-view only the former made sense because it did not contain the Hamcrest classes but declared a dependency to the Hamcrest Maven artifact. The latter included the Hamcrest classes which was very un-Maven-like.
+
+
From this release on, you should use junit:junit which will be what junit:junit-dep used to. If you still reference junit:junit-dep, Maven will automatically relocate you to the new junit:junit and issue a warning for you to fix.
+
+
Rules
+
+
A number of improvements have been made to Rules:
+
+
+
MethodRule is no longer deprecated.
+
Both @Rule and @ClassRule can now be used on methods that return a TestRule.
+
ExpectedException now always prints the stacktrace of the actual exception in case of failure.
+
A parent folder can be specified for TemporaryFolder. In addition, the newFile/newFolder methods will now fail when the file or folder could not be created.
+
TestWatcher has a new template method called skipped that is invoked when a test is skipped due to a failed assumption.
+
+
+
Improvements to Assert and Assume
+
+
+
assertNotEquals has been added to Assert.
+
assertEquals has been overloaded in order to check whether two floats are equal given a certain float delta.
+
Most methods in Assume now allow to pass a custom message.
+
diff --git a/doc/ReleaseNotes4.11.md b/doc/ReleaseNotes4.11.md
new file mode 100644
index 000000000000..740c64a09d7c
--- /dev/null
+++ b/doc/ReleaseNotes4.11.md
@@ -0,0 +1,116 @@
+## Summary of changes in version 4.11
+
+### Matchers: Upgrade to Hamcrest 1.3
+
+JUnit now uses the latest version of Hamcrest. Thus, you can use all the available matchers and benefit from an improved `assertThat` which will now print the mismatch description from the matcher when an assertion fails.
+
+#### Example
+
+```java
+assertThat(Long.valueOf(1), instanceOf(Integer.class));
+```
+
+Old error message:
+
+ Expected: an instance of java.lang.Integer
+ got: <1L>
+
+New error message:
+
+ Expected: an instance of java.lang.Integer
+ but: <1L> is a java.lang.Long
+
+Hamcrest's new `FeatureMatcher` makes writing custom matchers that make use of custom mismatch descriptions quite easy:
+
+```java
+@Test
+public void featureMatcher() throws Exception {
+ assertThat("Hello World!", length(is(0)));
+}
+
+private Matcher length(Matcher super Integer> matcher) {
+ return new FeatureMatcher(matcher, "a String of length that", "length") {
+ @Override
+ protected Integer featureValueOf(String actual) {
+ return actual.length();
+ }
+ };
+}
+```
+
+Running this test will return the following failure message:
+
+ Expected: a String of length that is <0>
+ but: length was <12>
+
+
+Most of the matchers in `JUnitMatchers` have been deprecated. Please use `org.hamcrest.CoreMatchers` directly.
+
+### Parameterized Tests
+
+In order to easily identify the individual test cases in a Parameterized test, you may provide a name using the `@Parameters` annotation. This name is allowed to contain placeholders that are replaced at runtime:
+
+* `{index}`: the current parameter index
+* `{0}`, `{1}`, …: the first, second, and so on, parameter value
+
+#### Example
+
+```java
+@RunWith(Parameterized.class)
+public class FibonacciTest {
+
+ @Parameters(name = "{index}: fib({0})={1}")
+ public static Iterable
-
-
-Summary of Changes with version 4.2
-
-
-
Bug fix: Inaccessible base class is caught at test construction time.
-
Bug fix: Circular suites are caught at test construction time.
-
Improved error messages for array comparison("arrays first differed at element [1][0]")
-
Test constructors that throw exceptions are reported correctly.
-
-
-
-
-
-Summary of Changes with version 4.1
-
-
-
Bug fix: listeners now get a correct test running time, rather than always being told 0 secs.
-
The @RunWith annotation is now inherited by subclasses:
-all subclasses of an abstract test class will be run by the same runner.
-
The build script fails if the JUnit unit tests fail
-
The faq has been updated
-
Javadoc has been improved, with more internal links, and package descriptions added (Thanks, Matthias Schmidt!)
-
An acknowledgements.txt file has been created to credit outside contributions
-
The Enclosed runner, which runs all of the static inner classes of a given class, has been added
-to org.junit.runners.
-
-
-
-
Summary of Changes with version 4.0
-
-The architecture of JUnit 4.0 is a substantial departure from that of earlier releases.
-Instead of
-tagging test classes by subclassing junit.framework.TestCase and tagging test methods by
-starting their name with "test", you now tag test methods with the @Test annotation.
-
-
-
-
-Contents of the Release
-
-
-
-
README.html
-
-
this file
-
-
-
-
junit-4.6.jar
-
-
a jar file with the JUnit framework, bundled with the hamcrest-core-1.1 dependency.
-
-
-
-
junit-dep-4.6.jar
-
-
a jar file with the JUnit framework, unbundled from any external dependencies.
-Choosing to use this jar developers will need to also provide in the classpath a compatible version of external dependencies (ie hamcrest-core-1.1+)
-
-
-
-
junit-4.6-src.jar
-
-
a jar file with the source code of the JUnit framework
-
-
-
-
org/junit
-
-
the source code of the basic JUnit annotations and classes
-
-
-
-
samples
-
-
sample test cases
-
-
-
-
tests
-
-
test cases for JUnit itself
-
-
-
-
javadoc
-
-
javadoc generated documentation
-
-
-
-
doc
-
-
documentation and articles
-
-
-
-
-Installation
-Below are the installation steps for installing JUnit:
-
-
-unzip the junit4.6.zip file
-
-
-addjunit-4.6.jar to the CLASSPATH. For example:
- set classpath=%classpath%;INSTALL_DIR\junit-4.6.jar;INSTALL_DIR
-
-
-test the installation by running java org.junit.runner.JUnitCore org.junit.tests.AllTests
-
- Notice: that the tests are not
-contained in the junit-4.6.jar but in the installation directory directly.
-Therefore make sure that the installation directory is on the class path
-
-Important: don't install junit-4.6.jar
-into the extension directory of your JDK installation. If you do so the
-test class on the files system will not be found.
-
-Getting Started
-To get started with unit testing and JUnit read the article:
-JUnit Cookbook.
- This article describes basic test writing using JUnit 4.
-
You find additional samples in the org.junit.samples package:
-
-
-SimpleTest.java - some simple test cases
-
-
-VectorTest.java - test cases for java.util.Vector
-
-
-
-Documentation
-
-
JUnit Cookbook
- A cookbook for implementing tests with JUnit.
- Javadoc
- API documentation generated with javadoc.
- Frequently asked questions
- Some frequently asked questions about using JUnit.
- License
- The terms of the common public license used for JUnit.
-
-The following documents still describe JUnit 3.8.
-
-
-
-
-
-
diff --git a/doc/ReleaseNotes4.5.md b/doc/ReleaseNotes4.5.md
new file mode 100644
index 000000000000..66aac7004a25
--- /dev/null
+++ b/doc/ReleaseNotes4.5.md
@@ -0,0 +1,96 @@
+## Summary of Changes in version 4.5 ##
+
+### Installation ###
+
+- We are releasing `junit-4.5.jar`, which contains all the classes
+ necessary to run JUnit, and `junit-dep-4.5.jar`, which leaves out
+ hamcrest classes, for developers who already use hamcrest outside of
+ JUnit.
+
+### Basic JUnit operation ###
+
+- JUnitCore now more often exits with the correct exit code (0 for
+ success, 1 for failure)
+
+- Badly formed test classes (exceptions in constructors, classes
+ without tests, multiple constructors, Suite without @SuiteClasses)
+ produce more helpful error messages
+
+- Test classes whose only test methods are inherited from superclasses
+ now run.
+
+- Optimization to annotation processing can cut JUnit overhead by more than half
+ on large test classes, especially when using Theories. [Bug 1796847]
+
+- A failing assumption in a constructor ignores the class
+
+- Correct results when comparing the string "null" with potentially
+ null values. [Bug 1857283]
+
+- Annotating a class with `@RunWith(JUnit4.class)` will always invoke the
+ default JUnit 4 runner in the current version of JUnit. This default changed
+ from `JUnit4ClassRunner` in 4.4 to `BlockJUnit4ClassRunner` in 4.5 (see below),
+ and may change again.
+
+### Extension ###
+
+- `BlockJUnit4Runner` is a new implementation of the standard JUnit 4
+ test class functionality. In contrast to `JUnit4ClassRunner` (the old
+ implementation):
+
+ - `BlockJUnit4Runner` has a much simpler implementation based on
+ Statements, allowing new operations to be inserted into the
+ appropriate point in the execution flow.
+
+ - `BlockJUnit4Runner` is published, and extension and reuse are
+ encouraged, whereas `JUnit4ClassRunner` was in an internal package,
+ and is now deprecated.
+
+- `ParentRunner` is a base class for runners that iterate over
+ a list of "children", each an object representing a test or suite to run.
+ `ParentRunner` provides filtering, sorting, `@BeforeClass`, `@AfterClass`,
+ and method validation to subclasses.
+
+- `TestClass` wraps a class to be run, providing efficient, repeated access
+ to all methods with a given annotation.
+
+- The new `RunnerBuilder` API allows extending the behavior of
+ Suite-like custom runners.
+
+- `AssumptionViolatedException.toString()` is more informative
+
+### Extra Runners ###
+
+- `Parameterized.eachOne()` has been removed
+
+- New runner `Enclosed` runs all static inner classes of an outer class.
+
+### Theories ###
+
+- `@Before` and `@After` methods are run before and after each set of attempted parameters
+ on a Theory, and each set of parameters is run on a new instance of the test class.
+
+- Exposed API's `ParameterSignature.getType()` and `ParameterSignature.getAnnotations()`
+
+- An array of data points can be introduced by a field or method
+ marked with the new annotation `@DataPoints`
+
+- The Theories custom runner has been refactored to make it faster and
+ easier to extend
+
+### Development ###
+
+- Source has been split into directories `src/main/java` and
+ `src/test/java`, making it easier to exclude tests from builds, and
+ making JUnit more maven-friendly
+
+- Test classes in `org.junit.tests` have been organized into
+ subpackages, hopefully making finding tests easier.
+
+- `ResultMatchers` has more informative descriptions.
+
+- `TestSystem` allows testing return codes and other system-level interactions.
+
+### Incompatible changes ###
+
+- Removed Request.classes(String, Class>...) factory method
diff --git a/doc/ReleaseNotes4.5.txt b/doc/ReleaseNotes4.5.txt
index 66aac7004a25..704e8023abe5 100644
--- a/doc/ReleaseNotes4.5.txt
+++ b/doc/ReleaseNotes4.5.txt
@@ -1,96 +1 @@
-## Summary of Changes in version 4.5 ##
-
-### Installation ###
-
-- We are releasing `junit-4.5.jar`, which contains all the classes
- necessary to run JUnit, and `junit-dep-4.5.jar`, which leaves out
- hamcrest classes, for developers who already use hamcrest outside of
- JUnit.
-
-### Basic JUnit operation ###
-
-- JUnitCore now more often exits with the correct exit code (0 for
- success, 1 for failure)
-
-- Badly formed test classes (exceptions in constructors, classes
- without tests, multiple constructors, Suite without @SuiteClasses)
- produce more helpful error messages
-
-- Test classes whose only test methods are inherited from superclasses
- now run.
-
-- Optimization to annotation processing can cut JUnit overhead by more than half
- on large test classes, especially when using Theories. [Bug 1796847]
-
-- A failing assumption in a constructor ignores the class
-
-- Correct results when comparing the string "null" with potentially
- null values. [Bug 1857283]
-
-- Annotating a class with `@RunWith(JUnit4.class)` will always invoke the
- default JUnit 4 runner in the current version of JUnit. This default changed
- from `JUnit4ClassRunner` in 4.4 to `BlockJUnit4ClassRunner` in 4.5 (see below),
- and may change again.
-
-### Extension ###
-
-- `BlockJUnit4Runner` is a new implementation of the standard JUnit 4
- test class functionality. In contrast to `JUnit4ClassRunner` (the old
- implementation):
-
- - `BlockJUnit4Runner` has a much simpler implementation based on
- Statements, allowing new operations to be inserted into the
- appropriate point in the execution flow.
-
- - `BlockJUnit4Runner` is published, and extension and reuse are
- encouraged, whereas `JUnit4ClassRunner` was in an internal package,
- and is now deprecated.
-
-- `ParentRunner` is a base class for runners that iterate over
- a list of "children", each an object representing a test or suite to run.
- `ParentRunner` provides filtering, sorting, `@BeforeClass`, `@AfterClass`,
- and method validation to subclasses.
-
-- `TestClass` wraps a class to be run, providing efficient, repeated access
- to all methods with a given annotation.
-
-- The new `RunnerBuilder` API allows extending the behavior of
- Suite-like custom runners.
-
-- `AssumptionViolatedException.toString()` is more informative
-
-### Extra Runners ###
-
-- `Parameterized.eachOne()` has been removed
-
-- New runner `Enclosed` runs all static inner classes of an outer class.
-
-### Theories ###
-
-- `@Before` and `@After` methods are run before and after each set of attempted parameters
- on a Theory, and each set of parameters is run on a new instance of the test class.
-
-- Exposed API's `ParameterSignature.getType()` and `ParameterSignature.getAnnotations()`
-
-- An array of data points can be introduced by a field or method
- marked with the new annotation `@DataPoints`
-
-- The Theories custom runner has been refactored to make it faster and
- easier to extend
-
-### Development ###
-
-- Source has been split into directories `src/main/java` and
- `src/test/java`, making it easier to exclude tests from builds, and
- making JUnit more maven-friendly
-
-- Test classes in `org.junit.tests` have been organized into
- subpackages, hopefully making finding tests easier.
-
-- `ResultMatchers` has more informative descriptions.
-
-- `TestSystem` allows testing return codes and other system-level interactions.
-
-### Incompatible changes ###
-
-- Removed Request.classes(String, Class>...) factory method
+Please see ReleaseNotes4.5.md
diff --git a/doc/ReleaseNotes4.6.md b/doc/ReleaseNotes4.6.md
new file mode 100644
index 000000000000..f1f6a8e6ac6b
--- /dev/null
+++ b/doc/ReleaseNotes4.6.md
@@ -0,0 +1,106 @@
+## Summary of Changes in version 4.6 ##
+
+### Max ###
+
+JUnit now includes a new experimental Core, `MaxCore`. `MaxCore`
+remembers the results of previous test runs in order to run new
+tests out of order. `MaxCore` prefers new tests to old tests, fast
+tests to slow tests, and recently failing tests to tests that last
+failed long ago. There's currently not a standard UI for running
+`MaxCore` included in JUnit, but there is a UI included in the JUnit
+Max Eclipse plug-in at:
+
+ http://www.junitmax.com/junitmax/subscribe.html
+
+Example:
+
+```java
+public static class TwoUnEqualTests {
+ @Test
+ public void slow() throws InterruptedException {
+ Thread.sleep(100);
+ fail();
+ }
+
+ @Test
+ public void fast() {
+ fail();
+ }
+}
+
+@Test
+public void rememberOldRuns() {
+ File maxFile = new File("history.max");
+ MaxCore firstMax = MaxCore.storedLocally(maxFile);
+ firstMax.run(TwoUnEqualTests.class);
+
+ MaxCore useHistory= MaxCore.storedLocally(maxFile);
+ List failures= useHistory.run(TwoUnEqualTests.class)
+ .getFailures();
+ assertEquals("fast", failures.get(0).getDescription().getMethodName());
+ assertEquals("slow", failures.get(1).getDescription().getMethodName());
+}
+```
+
+### Test scheduling strategies ###
+
+`JUnitCore` now includes an experimental method that allows you to
+specify a model of the `Computer` that runs your tests. Currently,
+the only built-in Computers are the default, serial runner, and two
+runners provided in the `ParallelRunner` class:
+`ParallelRunner.classes()`, which runs classes in parallel, and
+`ParallelRunner.methods()`, which runs classes and methods in parallel.
+
+This feature is currently less stable than MaxCore, and may be
+merged with MaxCore in some way in the future.
+
+Example:
+
+```java
+public static class Example {
+ @Test public void one() throws InterruptedException {
+ Thread.sleep(1000);
+ }
+ @Test public void two() throws InterruptedException {
+ Thread.sleep(1000);
+ }
+}
+
+@Test public void testsRunInParallel() {
+ long start= System.currentTimeMillis();
+ Result result= JUnitCore.runClasses(ParallelComputer.methods(),
+ Example.class);
+ assertTrue(result.wasSuccessful());
+ long end= System.currentTimeMillis();
+ assertThat(end - start, betweenInclusive(1000, 1500));
+}
+```
+
+### Comparing double arrays ###
+
+Arrays of doubles can be compared, using a delta allowance for equality:
+
+```java
+@Test
+public void doubleArraysAreEqual() {
+ assertArrayEquals(new double[] {1.0, 2.0}, new double[] {1.0, 2.0}, 0.01);
+}
+```
+
+### `Filter.matchDescription` API ###
+
+Since 4.0, it has been possible to run a single method using the `Request.method`
+API. In 4.6, the filter that implements this is exposed as `Filter.matchDescription`.
+
+### Documentation ###
+
+- A couple classes and packages that once had empty javadoc have been
+ doc'ed.
+
+- Added how to run JUnit from the command line to the cookbook.
+
+- junit-4.x.zip now contains build.xml
+
+### Bug fixes ###
+- Fixed overly permissive @DataPoint processing (2191102)
+- Fixed bug in test counting after an ignored method (2106324)
diff --git a/doc/ReleaseNotes4.6.txt b/doc/ReleaseNotes4.6.txt
index a5decac71667..ab4977e116fe 100644
--- a/doc/ReleaseNotes4.6.txt
+++ b/doc/ReleaseNotes4.6.txt
@@ -1,100 +1 @@
-## Summary of Changes in version 4.6 ##
-
-### Max ###
-
-JUnit now includes a new experimental Core, `MaxCore`. `MaxCore`
-remembers the results of previous test runs in order to run new
-tests out of order. `MaxCore` prefers new tests to old tests, fast
-tests to slow tests, and recently failing tests to tests that last
-failed long ago. There's currently not a standard UI for running
-`MaxCore` included in JUnit, but there is a UI included in the JUnit
-Max Eclipse plug-in at:
-
- http://www.junitmax.com/junitmax/subscribe.html
-
-Example:
-
- public static class TwoUnEqualTests {
- @Test
- public void slow() throws InterruptedException {
- Thread.sleep(100);
- fail();
- }
-
- @Test
- public void fast() {
- fail();
- }
- }
-
- @Test
- public void rememberOldRuns() {
- File maxFile = new File("history.max");
- MaxCore firstMax = MaxCore.storedLocally(maxFile);
- firstMax.run(TwoUnEqualTests.class);
-
- MaxCore useHistory= MaxCore.storedLocally(maxFile);
- List failures= useHistory.run(TwoUnEqualTests.class)
- .getFailures();
- assertEquals("fast", failures.get(0).getDescription().getMethodName());
- assertEquals("slow", failures.get(1).getDescription().getMethodName());
- }
-
-### Test scheduling strategies ###
-
-`JUnitCore` now includes an experimental method that allows you to
-specify a model of the `Computer` that runs your tests. Currently,
-the only built-in Computers are the default, serial runner, and two
-runners provided in the `ParallelRunner` class:
-`ParallelRunner.classes()`, which runs classes in parallel, and
-`ParallelRunner.methods()`, which runs classes and methods in parallel.
-
-This feature is currently less stable than MaxCore, and may be
-merged with MaxCore in some way in the future.
-
-Example:
-
- public static class Example {
- @Test public void one() throws InterruptedException {
- Thread.sleep(1000);
- }
- @Test public void two() throws InterruptedException {
- Thread.sleep(1000);
- }
- }
-
- @Test public void testsRunInParallel() {
- long start= System.currentTimeMillis();
- Result result= JUnitCore.runClasses(ParallelComputer.methods(),
- Example.class);
- assertTrue(result.wasSuccessful());
- long end= System.currentTimeMillis();
- assertThat(end - start, betweenInclusive(1000, 1500));
- }
-
-### Comparing double arrays ###
-
-Arrays of doubles can be compared, using a delta allowance for equality:
-
- @Test
- public void doubleArraysAreEqual() {
- assertArrayEquals(new double[] {1.0, 2.0}, new double[] {1.0, 2.0}, 0.01);
- }
-
-### `Filter.matchDescription` API ###
-
-Since 4.0, it has been possible to run a single method using the `Request.method`
-API. In 4.6, the filter that implements this is exposed as `Filter.matchDescription`.
-
-### Documentation ###
-
-- A couple classes and packages that once had empty javadoc have been
- doc'ed.
-
-- Added how to run JUnit from the command line to the cookbook.
-
-- junit-4.x.zip now contains build.xml
-
-### Bug fixes ###
-- Fixed overly permissive @DataPoint processing (2191102)
-- Fixed bug in test counting after an ignored method (2106324)
+Please see ReleaseNotes4.6.md
diff --git a/doc/ReleaseNotes4.7.html b/doc/ReleaseNotes4.7.html
index 5ff5d7a06911..69b66c6a3768 100644
--- a/doc/ReleaseNotes4.7.html
+++ b/doc/ReleaseNotes4.7.html
@@ -204,42 +204,11 @@
Timeouts
Matchers
-
Hamcrest 1.2 is now incorporated (http://github.com/KentBeck/junit/issues#issue/1)
-
-
-
The following methods from JUnitMatchers are deprecated, and moved to CoreMatchers:
-
JUnitMatchers.hasItem is now CoreMatchers.hasItem
-
JUnitMatchers.hasItems is now CoreMatchers.hasItems
-
JUnitMatchers.containsString is now CoreMatchers.containsString
-
Matchers now have more informative mismatch descriptions. For example:
-
-
@SuppressWarnings("unchecked")
-@Test public void stringIsAnInteger() {
- assertThat("identifier", "actual", matches(is(Integer.class)));
- // prints:
- // Expected: is an instance of java.lang.Integer
- // but: \"actual\" is a java.lang.String
-}
-
Some matchers have slightly changed type signatures, especially those created
-by is() and equalTo. Everything should work, except see BothTest for an
-example of how the both().and() and either().or() constructs may be
-affected. To essentially disable type-checking for a matcher expression,
-use JUnitMatchers.matches() (see below)
-
JUnitMatchers.isOneOf(...) is sugar for the situation where you want to specify
-a finite list of concrete objects that can match. For example:
-
-
assertThat(3, isOneOf(3, 4));
-
JUnitMatchers.matches() disables type-checking of a matcher entirely.
Due to typing incompatibilities, JUnit is still including the 1.1 release
+of hamcrest. This is not a change from 4.6, but is a change from
+pre-beta releases of 4.7. Due to this incompatibility, tests using
+Hamcrest 1.2 must still use the MatcherAssert.assertThat method from
+Hamcrest, not Assert.assertThat from JUnit.
Docs
diff --git a/doc/ReleaseNotes4.7.md b/doc/ReleaseNotes4.7.md
new file mode 100644
index 000000000000..1f9607074106
--- /dev/null
+++ b/doc/ReleaseNotes4.7.md
@@ -0,0 +1,210 @@
+## Summary of Changes in version 4.7 ##
+
+### Rules ###
+
+- Rules allow very flexible addition or redefinition of the behavior
+ of each test method in a test class. Testers can reuse or extend one of the
+ provided Rules below, or write their own.
+
+ For more on this feature, see http://www.threeriversinstitute.org/blog/?p=155
+
+- The TemporaryFolder Rule allows creation of files and folders
+ that are guaranteed to be deleted when the test method finishes
+ (whether it passes or fails):
+
+```java
+public static class HasTempFolder {
+ @Rule
+ public TemporaryFolder folder= new TemporaryFolder();
+
+ @Test
+ public void testUsingTempFolder() throws IOException {
+ File createdFile= folder.newFile("myfile.txt");
+ File createdFolder= folder.newFolder("subfolder");
+ // ...
+ }
+}
+```
+
+- ExternalResource is a base class for Rules (like TemporaryFolder)
+ that set up an external resource before a test (a file, socket, server,
+ database connection, etc.), and guarantee to tear it down afterward:
+
+```java
+public static class UsesExternalResource {
+ Server myServer = new Server();
+
+ @Rule public ExternalResource resource = new ExternalResource() {
+ @Override
+ protected void before() throws Throwable {
+ myServer.connect();
+ }
+
+ @Override
+ protected void after() {
+ myServer.disconnect();
+ }
+ };
+
+ @Test public void testFoo() {
+ new Client().run(myServer);
+ }
+}
+```
+
+- The ErrorCollector Rule allows execution of a test to continue
+ after the first problem is found (for example, to collect _all_ the
+ incorrect rows in a table, and report them all at once):
+
+```java
+public static class UsesErrorCollectorTwice {
+ @Rule
+ public ErrorCollector collector= new ErrorCollector();
+
+ @Test public void example() {
+ collector.addError(new Throwable("first thing went wrong"));
+ collector.addError(new Throwable("second thing went wrong"));
+ }
+}
+```
+
+- Verifier is a base class for Rules like ErrorCollector, which
+ can turn otherwise passing test methods into failing tests if a verification
+ check is failed
+
+```java
+public static class ErrorLogVerifier() {
+ private ErrorLog errorLog = new ErrorLog();
+
+ @Rule
+ public MethodRule verifier = new Verifier() {
+ @Override public void verify() {
+ assertTrue(errorLog.isEmpty());
+ }
+ }
+
+ @Test public void testThatMightWriteErrorLog() {
+ // ...
+ }
+}
+```
+
+- TestWatchman is a base class for Rules that take note
+ of the testing action, without modifying it.
+ For example, this class will keep a log of each passing and failing
+ test:
+
+```java
+public static class WatchmanTest {
+ private static String watchedLog;
+
+ @Rule
+ public MethodRule watchman= new TestWatchman() {
+ @Override
+ public void failed(Throwable e, FrameworkMethod method) {
+ watchedLog+= method.getName() + " "
+ + e.getClass().getSimpleName() + "\n";
+ }
+
+ @Override
+ public void succeeded(FrameworkMethod method) {
+ watchedLog+= method.getName() + " " + "success!\n";
+ }
+ };
+
+ @Test
+ public void fails() {
+ fail();
+ }
+
+ @Test
+ public void succeeds() {
+ }
+}
+```
+
+- The TestName Rule makes the current test name available inside test methods:
+
+```java
+public class NameRuleTest {
+ @Rule public TestName name = new TestName();
+
+ @Test public void testA() {
+ assertEquals("testA", name.getMethodName());
+ }
+
+ @Test public void testB() {
+ assertEquals("testB", name.getMethodName());
+ }
+}
+```
+
+- The Timeout Rule applies the same timeout to all test methods in a class:
+
+```java
+public static class HasGlobalTimeout {
+ public static String log;
+
+ @Rule public MethodRule globalTimeout = new Timeout(20);
+
+ @Test public void testInfiniteLoop1() {
+ log+= "ran1";
+ for(;;) {}
+ }
+
+ @Test public void testInfiniteLoop2() {
+ log+= "ran2";
+ for(;;) {}
+ }
+}
+```
+
+- The ExpectedException Rule allows in-test specification
+ of expected exception types and messages:
+
+```java
+public static class HasExpectedException {
+ @Rule
+ public ExpectedException thrown= ExpectedException.none();
+
+ @Test
+ public void throwsNothing() {
+
+ }
+
+ @Test
+ public void throwsNullPointerException() {
+ thrown.expect(NullPointerException.class);
+ throw new NullPointerException();
+ }
+
+ @Test
+ public void throwsNullPointerExceptionWithMessage() {
+ thrown.expect(NullPointerException.class);
+ thrown.expectMessage("happened?");
+ thrown.expectMessage(startsWith("What"));
+ throw new NullPointerException("What happened?");
+ }
+}
+```
+
+### Timeouts ###
+- Tests that time out now show the stack trace of the test thread.
+
+### Matchers ###
+- Due to typing incompatibilities, JUnit is still including the 1.1 release
+ of hamcrest. This is not a change from 4.6, but is a change from
+ pre-beta releases of 4.7. Due to this incompatibility, tests using
+ Hamcrest 1.2 must still use the MatcherAssert.assertThat method from
+ Hamcrest, not Assert.assertThat from JUnit.
+
+### Docs ###
+- Javadocs now link to online JDK javadocs (bug 2090230)
+- Parameterized runner javadocs improved (bug 2186792)
+- Fixed Javadoc code sample for AfterClass (2126279)
+- Fixed Javadoc for assertArraysEqual(float[], float[])
+
+### Bug fixes ###
+- Fixed: BaseTestRunner.getTest() requires class to extend TestCase (1812200)
+- Fixed: Suite does not allow for inheritance in annotations (2783118)
+- Fixed: ParallelComputer skipped tests that took longer than 2 seconds
diff --git a/doc/ReleaseNotes4.7.txt b/doc/ReleaseNotes4.7.txt
index 11b70c1fa826..58765736986d 100644
--- a/doc/ReleaseNotes4.7.txt
+++ b/doc/ReleaseNotes4.7.txt
@@ -1,194 +1 @@
-## Summary of Changes in version 4.7 ##
-
-### Rules ###
-
-- Rules allow very flexible addition or redefinition of the behavior
- of each test method in a test class. Testers can reuse or extend one of the
- provided Rules below, or write their own.
-
- For more on this feature, see http://www.threeriversinstitute.org/blog/?p=155
-
-- The TemporaryFolder Rule allows creation of files and folders
- that are guaranteed to be deleted when the test method finishes
- (whether it passes or fails):
-
- public static class HasTempFolder {
- @Rule
- public TemporaryFolder folder= new TemporaryFolder();
-
- @Test
- public void testUsingTempFolder() throws IOException {
- File createdFile= folder.newFile("myfile.txt");
- File createdFolder= folder.newFolder("subfolder");
- // ...
- }
- }
-
-- ExternalResource is a base class for Rules (like TemporaryFolder)
- that set up an external resource before a test (a file, socket, server,
- database connection, etc.), and guarantee to tear it down afterward:
-
- public static class UsesExternalResource {
- Server myServer = new Server();
-
- @Rule public ExternalResource resource = new ExternalResource() {
- @Override
- protected void before() throws Throwable {
- myServer.connect();
- };
-
- @Override
- protected void after() {
- myServer.disconnect();
- };
- };
-
- @Test public void testFoo() {
- new Client().run(myServer);
- }
- }
-
-- The ErrorCollector Rule allows execution of a test to continue
- after the first problem is found (for example, to collect _all_ the
- incorrect rows in a table, and report them all at once):
-
- public static class UsesErrorCollectorTwice {
- @Rule
- public ErrorCollector collector= new ErrorCollector();
-
- @Test public void example() {
- collector.addError(new Throwable("first thing went wrong"));
- collector.addError(new Throwable("second thing went wrong"));
- }
- }
-
-- Verifier is a base class for Rules like ErrorCollector, which
- can turn otherwise passing test methods into failing tests if a verification
- check is failed
-
- public static class ErrorLogVerifier() {
- private ErrorLog errorLog = new ErrorLog();
-
- @Rule
- public MethodRule verifier = new Verifier() {
- @Override public void verify() {
- assertTrue(errorLog.isEmpty());
- }
- }
-
- @Test public void testThatMightWriteErrorLog() {
- // ...
- }
- }
-
-- TestWatchman is a base class for Rules that take note
- of the testing action, without modifying it.
- For example, this class will keep a log of each passing and failing
- test:
-
- public static class WatchmanTest {
- private static String watchedLog;
-
- @Rule
- public MethodRule watchman= new TestWatchman() {
- @Override
- public void failed(Throwable e, FrameworkMethod method) {
- watchedLog+= method.getName() + " "
- + e.getClass().getSimpleName() + "\n";
- }
-
- @Override
- public void succeeded(FrameworkMethod method) {
- watchedLog+= method.getName() + " " + "success!\n";
- }
- };
-
- @Test
- public void fails() {
- fail();
- }
-
- @Test
- public void succeeds() {
- }
- }
-
-- The TestName Rule makes the current test name available inside test methods:
-
- public class NameRuleTest {
- @Rule public TestName name = new TestName();
-
- @Test public void testA() {
- assertEquals("testA", name.getMethodName());
- }
-
- @Test public void testB() {
- assertEquals("testB", name.getMethodName());
- }
- }
-
-- The Timeout Rule applies the same timeout to all test methods in a class:
-
- public static class HasGlobalTimeout {
- public static String log;
-
- @Rule public MethodRule globalTimeout = new Timeout(20);
-
- @Test public void testInfiniteLoop1() {
- log+= "ran1";
- for(;;) {}
- }
-
- @Test public void testInfiniteLoop2() {
- log+= "ran2";
- for(;;) {}
- }
- }
-
-- The ExpectedException Rule allows in-test specification
- of expected exception types and messages:
-
- public static class HasExpectedException {
- @Rule
- public ExpectedException thrown= ExpectedException.none();
-
- @Test
- public void throwsNothing() {
-
- }
-
- @Test
- public void throwsNullPointerException() {
- thrown.expect(NullPointerException.class);
- throw new NullPointerException();
- }
-
- @Test
- public void throwsNullPointerExceptionWithMessage() {
- thrown.expect(NullPointerException.class);
- thrown.expectMessage("happened?");
- thrown.expectMessage(startsWith("What"));
- throw new NullPointerException("What happened?");
- }
- }
-
-### Timeouts ###
-- Tests that time out now show the stack trace of the test thread.
-
-### Matchers ###
-- Due to typing incompatibilities, JUnit is still including the 1.1 release
- of hamcrest. This is not a change from 4.6, but is a change from
- pre-beta releases of 4.7. Due to this incompatibility, tests using
- Hamcrest 1.2 must still use the MatcherAssert.assertThat method from
- Hamcrest, not Assert.assertThat from JUnit.
-
-### Docs ###
-- Javadocs now link to online JDK javadocs (bug 2090230)
-- Parameterized runner javadocs improved (bug 2186792)
-- Fixed Javadoc code sample for AfterClass (2126279)
-- Fixed Javadoc for assertArraysEqual(float[], float[])
-
-### Bug fixes ###
-- Fixed: BaseTestRunner.getTest() requires class to extend TestCase (1812200)
-- Fixed: Suite does not allow for inheritance in annotations (2783118)
-- Fixed: ParallelComputer skipped tests that took longer than 2 seconds
+Please see ReleaseNotes4.7.md
diff --git a/doc/ReleaseNotes4.8.1.html b/doc/ReleaseNotes4.8.1.html
new file mode 100644
index 000000000000..32e36a656d8d
--- /dev/null
+++ b/doc/ReleaseNotes4.8.1.html
@@ -0,0 +1,9 @@
+
Summary of Changes in version 4.8.1
+
+
This was a quick bugfix release for an important bug
+
+
Bug fixes
+
+
+
github#61: Category annotations on classes were not honored.
+
diff --git a/doc/ReleaseNotes4.8.1.md b/doc/ReleaseNotes4.8.1.md
new file mode 100644
index 000000000000..bc13f26ae14a
--- /dev/null
+++ b/doc/ReleaseNotes4.8.1.md
@@ -0,0 +1,7 @@
+## Summary of Changes in version 4.8.1 ##
+
+This was a quick bugfix release for an important bug
+
+### Bug fixes ###
+
+- github#61: Category annotations on classes were not honored.
\ No newline at end of file
diff --git a/doc/ReleaseNotes4.8.1.txt b/doc/ReleaseNotes4.8.1.txt
new file mode 100644
index 000000000000..ef1cd68a7a25
--- /dev/null
+++ b/doc/ReleaseNotes4.8.1.txt
@@ -0,0 +1 @@
+Please see ReleaseNotes4.8.1.md
diff --git a/doc/ReleaseNotes4.8.2.html b/doc/ReleaseNotes4.8.2.html
new file mode 100644
index 000000000000..273f03bcf220
--- /dev/null
+++ b/doc/ReleaseNotes4.8.2.html
@@ -0,0 +1,10 @@
+
Summary of Changes in version 4.8.2
+
+
This was a quick bugfix release
+
+
Bug fixes
+
+
+
github#96: TestSuite(MyTestCase.class) should dynamically detect if MyTestCase
+is a TestCase
+
diff --git a/doc/ReleaseNotes4.8.2.md b/doc/ReleaseNotes4.8.2.md
new file mode 100644
index 000000000000..8631275cacbc
--- /dev/null
+++ b/doc/ReleaseNotes4.8.2.md
@@ -0,0 +1,8 @@
+## Summary of Changes in version 4.8.2 ##
+
+This was a quick bugfix release
+
+### Bug fixes ###
+
+- github#96: TestSuite(MyTestCase.class) should dynamically detect if MyTestCase
+ is a TestCase
diff --git a/doc/ReleaseNotes4.8.2.txt b/doc/ReleaseNotes4.8.2.txt
new file mode 100644
index 000000000000..e6a2ec01bcdc
--- /dev/null
+++ b/doc/ReleaseNotes4.8.2.txt
@@ -0,0 +1 @@
+Please see ReleaseNotes4.8.2.md
diff --git a/doc/ReleaseNotes4.8.html b/doc/ReleaseNotes4.8.html
new file mode 100644
index 000000000000..086f5d0f5220
--- /dev/null
+++ b/doc/ReleaseNotes4.8.html
@@ -0,0 +1,59 @@
+
Summary of Changes in version 4.8
+
+
Categories
+
+
From a given set of test classes, the Categories runner
+runs only the classes and methods
+that are annotated with either the category given with the @IncludeCategory
+annotation, or a subtype of that category. Either classes or interfaces can be
+used as categories. Subtyping works, so if you say @IncludeCategory(SuperClass.class),
+a test marked @Category({SubClass.class}) will be run.
+
+
You can also exclude categories by using the @ExcludeCategory annotation
+
+
Example:
+
+
public interface FastTests { /* category marker */ }
+public interface SlowTests { /* category marker */ }
+
+public class A {
+ @Test
+ public void a() {
+ fail();
+ }
+
+ @Category(SlowTests.class)
+ @Test
+ public void b() {
+ }
+}
+
+@Category({SlowTests.class, FastTests.class})
+public class B {
+ @Test
+ public void c() {
+
+ }
+}
+
+@RunWith(Categories.class)
+@IncludeCategory(SlowTests.class)
+@SuiteClasses( { A.class, B.class }) // Note that Categories is a kind of Suite
+public class SlowTestSuite {
+ // Will run A.b and B.c, but not A.a
+}
+
+@RunWith(Categories.class)
+@IncludeCategory(SlowTests.class)
+@ExcludeCategory(FastTests.class)
+@SuiteClasses( { A.class, B.class }) // Note that Categories is a kind of Suite
+public class SlowTestSuite {
+ // Will run A.b, but not A.a or B.c
+}
+
+
+
Bug fixes
+
+
+
github#16: thread safety of Result counting
+
diff --git a/doc/ReleaseNotes4.8.md b/doc/ReleaseNotes4.8.md
new file mode 100644
index 000000000000..cc429ea08b74
--- /dev/null
+++ b/doc/ReleaseNotes4.8.md
@@ -0,0 +1,57 @@
+## Summary of Changes in version 4.8 ##
+
+### Categories ###
+
+From a given set of test classes, the `Categories` runner
+runs only the classes and methods
+that are annotated with either the category given with the `@IncludeCategory`
+annotation, or a subtype of that category. Either classes or interfaces can be
+used as categories. Subtyping works, so if you say `@IncludeCategory(SuperClass.class)`,
+a test marked `@Category({SubClass.class})` will be run.
+
+You can also exclude categories by using the `@ExcludeCategory` annotation
+
+Example:
+
+```java
+public interface FastTests { /* category marker */ }
+public interface SlowTests { /* category marker */ }
+
+public class A {
+ @Test
+ public void a() {
+ fail();
+ }
+
+ @Category(SlowTests.class)
+ @Test
+ public void b() {
+ }
+}
+
+@Category({SlowTests.class, FastTests.class})
+public class B {
+ @Test
+ public void c() {
+ }
+}
+
+@RunWith(Categories.class)
+@IncludeCategory(SlowTests.class)
+@SuiteClasses( { A.class, B.class }) // Note that Categories is a kind of Suite
+public class SlowTestSuite {
+ // Will run A.b and B.c, but not A.a
+}
+
+@RunWith(Categories.class)
+@IncludeCategory(SlowTests.class)
+@ExcludeCategory(FastTests.class)
+@SuiteClasses( { A.class, B.class }) // Note that Categories is a kind of Suite
+public class SlowTestSuite {
+ // Will run A.b, but not A.a or B.c
+}
+```
+
+### Bug fixes ###
+
+- github#16: thread safety of Result counting
diff --git a/doc/ReleaseNotes4.8.txt b/doc/ReleaseNotes4.8.txt
index c2e1746194e0..6f4904e020f4 100644
--- a/doc/ReleaseNotes4.8.txt
+++ b/doc/ReleaseNotes4.8.txt
@@ -1,41 +1 @@
-## Summary of Changes in version 4.7 ##
-
-### Matchers ###
-
-- Hamcrest 1.2 is now incorporated (http://github.com/KentBeck/junit/issues#issue/1)
- - The following methods from `JUnitMatchers` are deprecated, and moved to `CoreMatchers`:
- - `JUnitMatchers.hasItem` is now `CoreMatchers.hasItem`
- - `JUnitMatchers.hasItems` is now `CoreMatchers.hasItems`
- - `JUnitMatchers.containsString` is now `CoreMatchers.containsString`
-
- - Matchers now have more informative mismatch descriptions. For example:
-
- @SuppressWarnings("unchecked")
- @Test public void stringIsAnInteger() {
- assertThat("identifier", "actual", matches(is(Integer.class)));
- // prints:
- // Expected: is an instance of java.lang.Integer
- // but: \"actual\" is a java.lang.String
- }
-
- - Some matchers have slightly changed type signatures, especially those created
- by `is()` and `equalTo`. Everything should work, except see `BothTest` for an
- example of how the `both().and()` and `either().or()` constructs may be
- affected. To essentially disable type-checking for a matcher expression,
- use `JUnitMatchers.matches()` (see below)
-
- - `JUnitMatchers.isOneOf(...)` is sugar for the situation where you want to specify
- a finite list of concrete objects that can match. For example:
-
- assertThat(3, isOneOf(3, 4));
-
- - `JUnitMatchers.matches()` disables type-checking of a matcher entirely.
-
- Goofy example:
-
- assertThat(3, matches(containsString("a")));
-
- Real example:
-
- assertThat(3, either(matches(is(String.class))).or(
- matches(is(Integer.class))));
\ No newline at end of file
+Please see ReleaseNotes4.8.md
diff --git a/doc/ReleaseNotes4.9.1.md b/doc/ReleaseNotes4.9.1.md
new file mode 100644
index 000000000000..eded783dbb66
--- /dev/null
+++ b/doc/ReleaseNotes4.9.1.md
@@ -0,0 +1,14 @@
+## Summary of Changes in version 4.9.1 [unreleased!] ##
+
+### Theories ###
+
+The `Theories` runner does not anticipate theory parameters that have generic
+types, as reported by github#64. Fixing this won't happen until `Theories` is
+moved to junit-contrib. In anticipation of this, 4.9.1 adds some of the
+necessary machinery to the runner classes, and deprecates a method that only
+the `Theories` runner uses, `FrameworkMethod`#producesType().
+The Common Public License that JUnit is released under is now included
+in the source repository.
+
+Thanks to `@pholser` for identifying a potential resolution for github#64
+and initiating work on it.
diff --git a/doc/ReleaseNotes4.9.1.txt b/doc/ReleaseNotes4.9.1.txt
new file mode 100644
index 000000000000..1a0a67b89fa7
--- /dev/null
+++ b/doc/ReleaseNotes4.9.1.txt
@@ -0,0 +1 @@
+Please see ReleaseNotes4.9.1.md
diff --git a/doc/ReleaseNotes4.9.html b/doc/ReleaseNotes4.9.html
new file mode 100644
index 000000000000..36921023a654
--- /dev/null
+++ b/doc/ReleaseNotes4.9.html
@@ -0,0 +1,96 @@
+
Summary of Changes in version 4.9, final
+
+
Release theme: Test-class and suite level Rules.
+
+
ClassRule
+
+
The ClassRule annotation extends the idea of method-level Rules,
+adding static fields that can affect the operation of a whole class. Any
+subclass of ParentRunner, including the standard BlockJUnit4ClassRunner
+and Suite classes, will support ClassRules.
+
+
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:
+
+
@RunWith(Suite.class)
+@SuiteClasses({A.class, B.class, C.class})
+public class UsesExternalResource {
+ public static Server myServer= new Server();
+
+ @ClassRule
+ public static ExternalResource resource= new ExternalResource() {
+ @Override
+ protected void before() throws Throwable {
+ myServer.connect();
+ };
+
+ @Override
+ protected void after() {
+ myServer.disconnect();
+ };
+ };
+}
+
+
+
TestRule
+
+
In JUnit 4.9, fields that can be annotated with either @Rule or @ClassRule
+should be of type TestRule. The old MethodRule type, which only made sense
+for method-level rules, will still work, but is deprecated.
+
+
Most built-in Rules have been moved to the new type already, in a way that
+should be transparent to most users. TestWatchman has been deprecated,
+and replaced by TestWatcher, which has the same functionality, but implements
+the new type.
+
+
Maven support
+
+
Maven bundles have, in the past, been uploaded by kind volunteers. Starting
+with this release, the JUnit team is attempting to perform this task ourselves.
+
+
LICENSE checked in
+
+
The Common Public License that JUnit is released under is now included
+in the source repository.
+
+
Bug fixes
+
+
+
github#98: assumeTrue() does not work with expected exceptions
+
github#74: Categories + Parameterized
+
+
In JUnit 4.8.2, the Categories runner would fail to run correctly
+if any contained test class had a custom Runner with a structure
+significantly different from the built-in Runner. With this fix,
+such classes can be assigned one or more categories at the class level,
+and will be run correctly. Trying to assign categories to methods within
+such a class will flag an error.
+
github#38: ParentRunner filters more than once
+
+
Thanks to @reinholdfuereder
+
github#248: protected BlockJUnit4ClassRunner#rules method removed from 4.8.2
+
github#187: Accidental dependency on Java 6
+
+
+
Thanks to @kcooney for:
+
+
+
github#163: Bad comparison failure message when using assertEquals(String, String)
+
github#227: ParentRunner now assumes that getChildren() returns a modifiable list
+
+
+
Minor changes
+
+
+
Backed out unused folder "experimental-use-of-antunit", replaced by
+bash-based script at build_tests.sh
+
Various Javadoc fixes
+
+
+
Thanks to @kcooney for:
+
+
+
Made MultipleFailureException public, to assist extension writers.
+
github#240: Add "test" target to build.xml, for faster ant-driven testing.
+
github#247: Give InitializationError a useful message
+
diff --git a/doc/ReleaseNotes4.9.md b/doc/ReleaseNotes4.9.md
new file mode 100644
index 000000000000..7d8d75880c48
--- /dev/null
+++ b/doc/ReleaseNotes4.9.md
@@ -0,0 +1,91 @@
+## Summary of Changes in version 4.9, final ##
+
+Release theme: Test-class and suite level Rules.
+
+### ClassRule ###
+
+The `ClassRule` annotation extends the idea of method-level Rules,
+adding static fields that can affect the operation of a whole class. Any
+subclass of `ParentRunner`, including the standard `BlockJUnit4ClassRunner`
+and `Suite` classes, will support `ClassRule`s.
+
+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:
+
+```java
+@RunWith(Suite.class)
+@SuiteClasses({A.class, B.class, C.class})
+public class UsesExternalResource {
+ public static Server myServer= new Server();
+
+ @ClassRule
+ public static ExternalResource resource= new ExternalResource() {
+ @Override
+ protected void before() throws Throwable {
+ myServer.connect();
+ }
+
+ @Override
+ protected void after() {
+ myServer.disconnect();
+ }
+ };
+}
+```
+
+### TestRule ###
+
+In JUnit 4.9, fields that can be annotated with either `@Rule` or `@ClassRule`
+should be of type `TestRule`. The old `MethodRule` type, which only made sense
+for method-level rules, will still work, but is deprecated.
+
+Most built-in Rules have been moved to the new type already, in a way that
+should be transparent to most users. `TestWatchman` has been deprecated,
+and replaced by `TestWatcher`, which has the same functionality, but implements
+the new type.
+
+### Maven support ###
+
+Maven bundles have, in the past, been uploaded by kind volunteers. Starting
+with this release, the JUnit team is attempting to perform this task ourselves.
+
+### LICENSE checked in ###
+
+The Common Public License that JUnit is released under is now included
+in the source repository.
+
+### Bug fixes ###
+
+- github#98: assumeTrue() does not work with expected exceptions
+- github#74: Categories + Parameterized
+
+ In JUnit 4.8.2, the Categories runner would fail to run correctly
+ if any contained test class had a custom Runner with a structure
+ significantly different from the built-in Runner. With this fix,
+ such classes can be assigned one or more categories at the class level,
+ and will be run correctly. Trying to assign categories to methods within
+ such a class will flag an error.
+
+- github#38: ParentRunner filters more than once
+
+ Thanks to `@reinholdfuereder`
+
+- github#248: protected BlockJUnit4ClassRunner#rules method removed from 4.8.2
+- github#187: Accidental dependency on Java 6
+
+Thanks to `@kcooney` for:
+
+- github#163: Bad comparison failure message when using assertEquals(String, String)
+- github#227: ParentRunner now assumes that getChildren() returns a modifiable list
+
+### Minor changes ###
+
+- Backed out unused folder "experimental-use-of-antunit", replaced by
+ bash-based script at build_tests.sh
+- Various Javadoc fixes
+
+Thanks to `@kcooney` for:
+
+- Made MultipleFailureException public, to assist extension writers.
+- github#240: Add "test" target to build.xml, for faster ant-driven testing.
+- github#247: Give InitializationError a useful message
diff --git a/doc/ReleaseNotes4.9.txt b/doc/ReleaseNotes4.9.txt
new file mode 100644
index 000000000000..a9d7d6033877
--- /dev/null
+++ b/doc/ReleaseNotes4.9.txt
@@ -0,0 +1 @@
+Please see ReleaseNotes4.9.md
diff --git a/doc/building-junit.txt b/doc/building-junit.txt
new file mode 100644
index 000000000000..91169e3427b3
--- /dev/null
+++ b/doc/building-junit.txt
@@ -0,0 +1,98 @@
+Steps to build junit:
+
+- Must be manual
+ - Write release notes
+- Not too tedious:
+ - Push to github (junit-team)
+ - Run the ./mvnw clean install
+ - If not done, update $M2_HOME/settings.xml
+ - If not done, copy GnuPG keys in to ${gpg.homedir}. See settings.xml.
+ - Perform Maven deployment of a snapshot or release version in Jenkins
+ Remember that the version specified in the pom.xml indicates the version
+ to be deployed, with -SNAPSHOT indicating that this is an unofficial
+ pre-release version towards the goal of the version without the -SNAPSHOT
+
+ - (to deploy gpg signed snapshot version)
+
+ $ ./mvnw -Pjunit-release clean deploy
+
+ - (to cut a release of the current targetted version)
+
+ $ ./mvnw -B release:prepare release:perform
+
+ This will result in the current pom.xml version having -SNAPSHOT removed
+ and the release cut from that version. The version will then be incremented
+ and -SNAPSHOT added back in anticipation of the next release version.
+
+ - (to cut a release of while changing the version from the current target)
+
+ $ ./mvnw -B -DreleaseVersion=5.0 release:prepare release:perform
+
+ This will ignore the current version in the pom.xml, set it to 5.0 and
+ the release cut from that 5.0 version. Then 5.0 will be incremented (to 5.1)
+ and -SNAPSHOT added back in anticipation of the next release version.
+
+ - (to deploy specified release version and next target release in non-interactive mode -B)
+ An example with the next development version and deploying release version:
+
+ $ ./mvnw -B -DreleaseVersion=4.12 -DdevelopmentVersion=4.13-SNAPSHOT release:prepare release:perform
+
+ - If you are not an official release manager, and you want to cut a release of
+ JUnit for use within your organization, use the following command
+
+ $ ./mvnw -DpushChanges=false -DlocalCheckout '-Darguments=-Dgpg.skip=true -DaltDeploymentRepository=my-company-repo-id::default::my-company-repo-url' -B -DreleaseVersion=4.12-mycompany-1 release:prepare release:perform
+
+ where
+ - my-company-repo-id is the of your company's entry in your
+ settings.xml with the credentials to deploy to your company's Maven repository
+ - my-company-repo-url is the deployment URL of your company's Maven repository
+ - 4.12-mycompany-1 is the version you are deploying, be sure to namespace
+ the version so that you don't conflict with others, hence why the text "mycompany"
+ is included in the example version number.
+
+ - Promote the maven artifacts and close staging repository if released successfully
+- Tedious:
+ - Update SourceForge if major release
+ - Update javadocs on github site (and "latest" link)
+ - Update javadocs on junit.org
+ - Put release notes on github.
+ - Announce on blog, user list, dev list, announce list, junit.org, twitter
+- Profit!
+
+
+===================================================================================
+== Internal template of Maven settings used by JUnit build machine. ==
+== settings.xml ==
+===================================================================================
+
+
+
+
+ junit-snapshot-repo
+
+
+
+
+ junit-releases-repo
+
+
+
+
+
+
+ junit-release
+
+
+ ...
+ false
+ true
+ /private/.../.gnupg
+ /private/.../.gnupg/pubring.gpg
+ /private/.../.gnupg/secring.gpg
+
+
+
+
+===================================================================================
diff --git a/doc/cookbook/cookbook.htm b/doc/cookbook/cookbook.htm
deleted file mode 100644
index 2cf8eecef241..000000000000
--- a/doc/cookbook/cookbook.htm
+++ /dev/null
@@ -1,143 +0,0 @@
-
-
-
-
-
-
- JUnit Cookbook
-
-
-
-
-JUnit Cookbook
-
-
-Kent Beck, Erich Gamma
-
-
- Here is a short cookbook showing you the steps you can follow in writing
-and organizing your own tests using JUnit.
-
-Simple Test Case
-How do you write testing code?
-
The simplest way is as an expression in a debugger. You can change debug
-expressions without recompiling, and you can wait to decide what to write
-until you have seen the running objects. You can also write test expressions
-as statements which print to the standard output stream. Both styles of
-tests are limited because they require human judgment to analyze their
-results. Also, they don't compose nicely- you can only execute one debug
-expression at a time and a program with too many print statements causes
-the dreaded "Scroll Blindness".
-
JUnit tests do not require human judgment to interpret, and it is easy
-to run many of them at the same time. When you need to test something,
-here is what you do:
-
-
-Annotate a method with @org.junit.Test
-
-
-When you want to check a value, import org.junit.Assert.* statically, call assertTrue() and pass a boolean
-that is true if the test succeeds
-
-For example, to test that the sum of two Moneys with the same currency
-contains a value which is the sum of the values of the two Moneys, write:
-
-
@Test public void simpleAdd() {
- Money m12CHF= new Money(12, "CHF");
- Money m14CHF= new Money(14, "CHF");
- Money expected= new Money(26, "CHF");
- Money result= m12CHF.add(m14CHF);
- assertTrue(expected.equals(result));
-}
-
-If you want to write a test similar to one you have already written, write
-a Fixture instead.
-
-Fixture
-What if you have two or more tests that operate on the same or similar
-sets of objects?
-
Tests need to run against the background of a known set of objects.
-This set of objects is called a test fixture. When you are writing tests
-you will often find that you spend more time writing the code to set up
-the fixture than you do in actually testing values.
-
To some extent, you can make writing the fixture code easier by paying
-careful attention to the constructors you write. However, a much bigger
-savings comes from sharing fixture code. Often, you will be able to use
-the same fixture for several different tests. Each case will send slightly
-different messages or parameters to the fixture and will check for different
-results.
-
When you have a common fixture, here is what you do:
-
-
-
-Add a field for each part of the fixture
-
-
-Annotate a method with @org.junit.Before
-and initialize the variables in that method
-
-
-Annotate a method with @org.junit.After
-to release any permanent resources you allocated in setUp
-
-For example, to write several test cases that want to work with different
-combinations of 12 Swiss Francs, 14 Swiss Francs, and 28 US Dollars, first
-create a fixture:
-
public class MoneyTest {
- private Money f12CHF;
- private Money f14CHF;
- private Money f28USD;
-
- @Before public void setUp() {
- f12CHF= new Money(12, "CHF");
- f14CHF= new Money(14, "CHF");
- f28USD= new Money(28, "USD");
- }
-}
-Once you have the Fixture in place, you can write as many Test Cases as
-you'd like. Add as many test methods (annotated with @Test) as you'd like.
-
Running Tests
-How do you run your tests and collect their results?
-
Once you have tests, you'll want to run them. JUnit provides tools
-to define the suite to be run and to display its results. To run tests and see the
-results on the console, run this from a Java program:
-
-or this from the command line, with both your test class and junit on the classpath:
-
-
-java org.junit.runner.JUnitCore TestClass1.class [...other test classes...]
-
-
-
-You make your JUnit 4 test classes accessible to a TestRunner designed to work with earlier versions of JUnit,
-declare a static method suite
-that returns a test.
-
-
public static junit.framework.Test suite() {
- return new JUnit4TestAdapter(Example.class);
-}
-
-
-Expected Exceptions
-How do you verify that code throws exceptions as expected?
-
Verifying that code completes normally is only part of programming. Making sure the code
-behaves as expected in exceptional situations is part of the craft of programming too. For example:
-
-
new ArrayList<Object>().get(0);
-
-
-This code should throw an IndexOutOfBoundsException. The @Test annotation has an optional parameter "expected"
-that takes as values subclasses of Throwable. If we wanted to verify that ArrayList throws the correct exception,
-we would write:
-
-
@Test(expected= IndexOutOfBoundsException.class) public void empty() {
- new ArrayList<Object>().get(0);
-}
-
-To get started with unit testing and JUnit read the article:
-JUnit Cookbook.
- This article describes basic test writing using JUnit 4.
-
You find additional samples in the org.junit.samples package:
-
-
-SimpleTest.java - some simple test cases
-
-
-VectorTest.java - test cases for java.util.Vector
-
-
JUnit 4.x only comes with a textual TestRunner. For graphical feedback,
-most major IDE's support
-JUnit 4. If necessary, you can run JUnit 4 tests in a JUnit 3
-environment by adding the following method to each test class:
-
-public static Test suite() {
- return new JUnit4TestAdapter(ThisClass.class);
-}
-
-
-
-
-Documentation
-
-
JUnit Cookbook
- A cookbook for implementing tests with JUnit.
- Javadoc
- API documentation generated with javadoc.
- Frequently asked questions
- Some frequently asked questions about using JUnit.
-
- Release notes
- Latest JUnit release notes
- License
- The terms of the common public license used for JUnit.
-
-The following documents still describe JUnit 3.8.
-
junit.org - a site for software
- developers using JUnit. It provides instructions for how to integrate JUnit
- with development tools like JBuilder and VisualAge/Java. As well as articles
- about and extensions to JUnit.
-
XProgramming.com -
- various implementations of the xUnit testing framework architecture.
- JUnit celebrates programmers testing their own software. As a result
- bugs, patches, and feature requests which include JUnit TestCases have a
- better
- chance of being addressed than those without.
-
-
- JUnit is forged on
- Sourceforge please use the tools provided for your submissions.
-
-
- JUnit source code is now hosted on GitHub.
-
-
-
-hosted by
-
-
-
diff --git a/doc/index.htm b/doc/index.htm
deleted file mode 100644
index dd19ff3383be..000000000000
--- a/doc/index.htm
+++ /dev/null
@@ -1,21 +0,0 @@
-
-
-
-
-
- JUnit Documentation
-
-
-
-
-JUnit Documentation
-
-
-Kent Beck, Erich Gamma, David Saff
-
-
-We have just begun documenting the new JUnit 4 architecture. The
cookbook has already been updated. You can find the javadoc here.
-The JUnit home page is here.
-
-
-
diff --git a/doc/markdown.sh b/doc/markdown.sh
index 3969665d744e..e235b638aa37 100644
--- a/doc/markdown.sh
+++ b/doc/markdown.sh
@@ -1 +1 @@
-~/bin/Markdown.pl ReleaseNotes4.7.txt >ReleaseNotes4.7.html
\ No newline at end of file
+~/bin/Markdown.pl ReleaseNotes4.8.txt >ReleaseNotes4.8.html
\ No newline at end of file
diff --git a/doc/testinfected/testing.htm b/doc/testinfected/testing.htm
index d11c11cd98d5..c5721e752b8d 100644
--- a/doc/testinfected/testing.htm
+++ b/doc/testinfected/testing.htm
@@ -181,14 +181,14 @@
result report. The value a string representation created by
the toString converter method.
There are
-other asertXXXX variants not discussed here.
+other assertXXXX variants not discussed here.
Now that we have implemented two test cases we notice some code duplication
for setting-up the tests. It would be nice to reuse some of this test set-up
code. In other words, we would like to have a common fixture for running
the tests. With JUnit you can do so by storing the fixture's objects in
instance variables of your
TestCase
-subclass and initialize them by overridding
+subclass and initialize them by overriding
the setUp method. The symmetric operation to setUp is tearDown which you
can override to clean up the test fixture at the end of a test. Each test
runs in its own fixture and JUnit calls setUp and tearDown for each test
@@ -435,7 +435,7 @@
public IMoney addMoneyBag(MoneyBag s) {
return s.addMoney(this);
}
-Here is the implemenation in MoneyBag which assumes additional constructors
+Here is the implementation in MoneyBag which assumes additional constructors
to create a MoneyBag from a Money and a MoneyBag and from two MoneyBags.
public IMoney addMoney(Money m) {
return new MoneyBag(m, this);
diff --git a/done.txt b/done.txt
deleted file mode 100644
index 0a89d4624090..000000000000
--- a/done.txt
+++ /dev/null
@@ -1,50 +0,0 @@
-* name space of JUnit4 is org.junit
-* JUnit4 requires J2SE 5.0
- leverage J2SE 5.0 features
-* @Test annotation
- @Test(expected=IndexOutOfBoundsException.class)
- @Test(timeout= 1000)
-* @Ignore(reason= "...")
-* @Before, @After setup/teardown
-* @BeforeClass, @AfterClass one-time setup/teardown
-* provide ForwardCompatibility so that existing test Runners can
- run JUnit4 tests:
- public static junit.framework.Test suite() {
- return new JUnit4TestAdapter(ListTest.class);
- }
-* add assertEquals(Object[], Object[])
-* Add backward compatibility for old JUnit tests in the new Runner
-* support the assert keyword and use AssertionError
-* remove the old graphical runners
-* simplify: get rid of failures and errors distinction
-* Annotation for runner strategy
-* Parameterized test
-* Should RunNotifier be API?
-* Runner should be abstract class.
-* Run single method with @BeforeClass and @AfterClass
-* Stopping a test run (there was support for this in 3.8 - TestResult.shouldStop())
-
-* Suite annotation example:
- @Suite(tests={MoneyTest.class, SimpleTest.class})
- or with filters
- @Suite(pattern="*Test"}
- @Suite(package="org.junit.test.*")
- @Suite
-
-* be able to run all tests simply from the command line
-* get rid of JUnit4TestCaseAdapter (use JUnit4RunnerStrategy in JUnit4TestAdapter)
-* enable tighter and more flexible IDE integration
- * enable test reordering/prioritization
- * test categorization & filtering (<- seems like a runner issue) @Category(short, integration) @Test(category=windowsOnly)
-* make sure TestListener is symmetric and meets needs of runner developers
- * TestRunEvent
-* Decide how we ship JUnit-- 1.5 only or hybrid
- * README.html
-* add javadoc to API interfaces and Annotations
- http://java.sun.com/j2se/javadoc/writingapispecs/index.html
-* Merge branch back into head
-* review Ant scripts
-* make suites simpler for both the IDE providers and the users
-* ClassRequest should search up the hierarchy for the requested Class to look for @RunWith
-
-
\ No newline at end of file
diff --git a/epl-v10.html b/epl-v10.html
new file mode 100644
index 000000000000..3998fcebeebe
--- /dev/null
+++ b/epl-v10.html
@@ -0,0 +1,261 @@
+
+
+
+
+
+
+Eclipse Public License - Version 1.0
+
+
+
+
+
+
+
Eclipse Public License - v 1.0
+
+
THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE
+PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR
+DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS
+AGREEMENT.
+
+
1. DEFINITIONS
+
+
"Contribution" means:
+
+
a) in the case of the initial Contributor, the initial
+code and documentation distributed under this Agreement, and
+
b) in the case of each subsequent Contributor:
+
i) changes to the Program, and
+
ii) additions to the Program;
+
where such changes and/or additions to the Program
+originate from and are distributed by that particular Contributor. A
+Contribution 'originates' from a Contributor if it was added to the
+Program by such Contributor itself or anyone acting on such
+Contributor's behalf. Contributions do not include additions to the
+Program which: (i) are separate modules of software distributed in
+conjunction with the Program under their own license agreement, and (ii)
+are not derivative works of the Program.
+
+
"Contributor" means any person or entity that distributes
+the Program.
+
+
"Licensed Patents" mean patent claims licensable by a
+Contributor which are necessarily infringed by the use or sale of its
+Contribution alone or when combined with the Program.
+
+
"Program" means the Contributions distributed in accordance
+with this Agreement.
+
+
"Recipient" means anyone who receives the Program under
+this Agreement, including all Contributors.
+
+
2. GRANT OF RIGHTS
+
+
a) Subject to the terms of this Agreement, each
+Contributor hereby grants Recipient a non-exclusive, worldwide,
+royalty-free copyright license to reproduce, prepare derivative works
+of, publicly display, publicly perform, distribute and sublicense the
+Contribution of such Contributor, if any, and such derivative works, in
+source code and object code form.
+
+
b) Subject to the terms of this Agreement, each
+Contributor hereby grants Recipient a non-exclusive, worldwide,
+royalty-free patent license under Licensed Patents to make, use, sell,
+offer to sell, import and otherwise transfer the Contribution of such
+Contributor, if any, in source code and object code form. This patent
+license shall apply to the combination of the Contribution and the
+Program if, at the time the Contribution is added by the Contributor,
+such addition of the Contribution causes such combination to be covered
+by the Licensed Patents. The patent license shall not apply to any other
+combinations which include the Contribution. No hardware per se is
+licensed hereunder.
+
+
c) Recipient understands that although each Contributor
+grants the licenses to its Contributions set forth herein, no assurances
+are provided by any Contributor that the Program does not infringe the
+patent or other intellectual property rights of any other entity. Each
+Contributor disclaims any liability to Recipient for claims brought by
+any other entity based on infringement of intellectual property rights
+or otherwise. As a condition to exercising the rights and licenses
+granted hereunder, each Recipient hereby assumes sole responsibility to
+secure any other intellectual property rights needed, if any. For
+example, if a third party patent license is required to allow Recipient
+to distribute the Program, it is Recipient's responsibility to acquire
+that license before distributing the Program.
+
+
d) Each Contributor represents that to its knowledge it
+has sufficient copyright rights in its Contribution, if any, to grant
+the copyright license set forth in this Agreement.
+
+
3. REQUIREMENTS
+
+
A Contributor may choose to distribute the Program in object code
+form under its own license agreement, provided that:
+
+
a) it complies with the terms and conditions of this
+Agreement; and
+
+
b) its license agreement:
+
+
i) effectively disclaims on behalf of all Contributors
+all warranties and conditions, express and implied, including warranties
+or conditions of title and non-infringement, and implied warranties or
+conditions of merchantability and fitness for a particular purpose;
+
+
ii) effectively excludes on behalf of all Contributors
+all liability for damages, including direct, indirect, special,
+incidental and consequential damages, such as lost profits;
+
+
iii) states that any provisions which differ from this
+Agreement are offered by that Contributor alone and not by any other
+party; and
+
+
iv) states that source code for the Program is available
+from such Contributor, and informs licensees how to obtain it in a
+reasonable manner on or through a medium customarily used for software
+exchange.
+
+
When the Program is made available in source code form:
+
+
a) it must be made available under this Agreement; and
+
+
b) a copy of this Agreement must be included with each
+copy of the Program.
+
+
Contributors may not remove or alter any copyright notices contained
+within the Program.
+
+
Each Contributor must identify itself as the originator of its
+Contribution, if any, in a manner that reasonably allows subsequent
+Recipients to identify the originator of the Contribution.
+
+
4. COMMERCIAL DISTRIBUTION
+
+
Commercial distributors of software may accept certain
+responsibilities with respect to end users, business partners and the
+like. While this license is intended to facilitate the commercial use of
+the Program, the Contributor who includes the Program in a commercial
+product offering should do so in a manner which does not create
+potential liability for other Contributors. Therefore, if a Contributor
+includes the Program in a commercial product offering, such Contributor
+("Commercial Contributor") hereby agrees to defend and
+indemnify every other Contributor ("Indemnified Contributor")
+against any losses, damages and costs (collectively "Losses")
+arising from claims, lawsuits and other legal actions brought by a third
+party against the Indemnified Contributor to the extent caused by the
+acts or omissions of such Commercial Contributor in connection with its
+distribution of the Program in a commercial product offering. The
+obligations in this section do not apply to any claims or Losses
+relating to any actual or alleged intellectual property infringement. In
+order to qualify, an Indemnified Contributor must: a) promptly notify
+the Commercial Contributor in writing of such claim, and b) allow the
+Commercial Contributor to control, and cooperate with the Commercial
+Contributor in, the defense and any related settlement negotiations. The
+Indemnified Contributor may participate in any such claim at its own
+expense.
+
+
For example, a Contributor might include the Program in a commercial
+product offering, Product X. That Contributor is then a Commercial
+Contributor. If that Commercial Contributor then makes performance
+claims, or offers warranties related to Product X, those performance
+claims and warranties are such Commercial Contributor's responsibility
+alone. Under this section, the Commercial Contributor would have to
+defend claims against the other Contributors related to those
+performance claims and warranties, and if a court requires any other
+Contributor to pay any damages as a result, the Commercial Contributor
+must pay those damages.
+
+
5. NO WARRANTY
+
+
EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS
+PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
+OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION,
+ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY
+OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely
+responsible for determining the appropriateness of using and
+distributing the Program and assumes all risks associated with its
+exercise of rights under this Agreement , including but not limited to
+the risks and costs of program errors, compliance with applicable laws,
+damage to or loss of data, programs or equipment, and unavailability or
+interruption of operations.
+
+
6. DISCLAIMER OF LIABILITY
+
+
EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT
+NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING
+WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR
+DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
+HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+
7. GENERAL
+
+
If any provision of this Agreement is invalid or unenforceable under
+applicable law, it shall not affect the validity or enforceability of
+the remainder of the terms of this Agreement, and without further action
+by the parties hereto, such provision shall be reformed to the minimum
+extent necessary to make such provision valid and enforceable.
+
+
If Recipient institutes patent litigation against any entity
+(including a cross-claim or counterclaim in a lawsuit) alleging that the
+Program itself (excluding combinations of the Program with other
+software or hardware) infringes such Recipient's patent(s), then such
+Recipient's rights granted under Section 2(b) shall terminate as of the
+date such litigation is filed.
+
+
All Recipient's rights under this Agreement shall terminate if it
+fails to comply with any of the material terms or conditions of this
+Agreement and does not cure such failure in a reasonable period of time
+after becoming aware of such noncompliance. If all Recipient's rights
+under this Agreement terminate, Recipient agrees to cease use and
+distribution of the Program as soon as reasonably practicable. However,
+Recipient's obligations under this Agreement and any licenses granted by
+Recipient relating to the Program shall continue and survive.
+
+
Everyone is permitted to copy and distribute copies of this
+Agreement, but in order to avoid inconsistency the Agreement is
+copyrighted and may only be modified in the following manner. The
+Agreement Steward reserves the right to publish new versions (including
+revisions) of this Agreement from time to time. No one other than the
+Agreement Steward has the right to modify this Agreement. The Eclipse
+Foundation is the initial Agreement Steward. The Eclipse Foundation may
+assign the responsibility to serve as the Agreement Steward to a
+suitable separate entity. Each new version of the Agreement will be
+given a distinguishing version number. The Program (including
+Contributions) may always be distributed subject to the version of the
+Agreement under which it was received. In addition, after a new version
+of the Agreement is published, Contributor may elect to distribute the
+Program (including its Contributions) under the new version. Except as
+expressly stated in Sections 2(a) and 2(b) above, Recipient receives no
+rights or licenses to the intellectual property of any Contributor under
+this Agreement, whether expressly, by implication, estoppel or
+otherwise. All rights in the Program not expressly granted under this
+Agreement are reserved.
+
+
This Agreement is governed by the laws of the State of New York and
+the intellectual property laws of the United States of America. No party
+to this Agreement will bring a legal action under this Agreement more
+than one year after the cause of action arose. Each party waives its
+rights to a jury trial in any resulting litigation.
+
+
+
+
\ No newline at end of file
diff --git a/lib/hamcrest-core-1.1.jar b/lib/hamcrest-core-1.1.jar
deleted file mode 100644
index 5f1d5ce0c3d6..000000000000
Binary files a/lib/hamcrest-core-1.1.jar and /dev/null differ
diff --git a/lib/hamcrest-core-1.3-sources.jar b/lib/hamcrest-core-1.3-sources.jar
new file mode 100644
index 000000000000..c3c110b4dab6
Binary files /dev/null and b/lib/hamcrest-core-1.3-sources.jar differ
diff --git a/lib/hamcrest-core-1.3.jar b/lib/hamcrest-core-1.3.jar
new file mode 100644
index 000000000000..9d5fe16e3dd3
Binary files /dev/null and b/lib/hamcrest-core-1.3.jar differ
diff --git a/mvnw b/mvnw
new file mode 100755
index 000000000000..e96ccd5fbbb6
--- /dev/null
+++ b/mvnw
@@ -0,0 +1,227 @@
+#!/bin/sh
+# ----------------------------------------------------------------------------
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+# ----------------------------------------------------------------------------
+
+# ----------------------------------------------------------------------------
+# Maven2 Start Up Batch script
+#
+# Required ENV vars:
+# ------------------
+# JAVA_HOME - location of a JDK home dir
+#
+# Optional ENV vars
+# -----------------
+# M2_HOME - location of maven2's installed home dir
+# MAVEN_OPTS - parameters passed to the Java VM when running Maven
+# e.g. to debug Maven itself, use
+# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+# MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+# ----------------------------------------------------------------------------
+
+if [ -z "$MAVEN_SKIP_RC" ] ; then
+
+ if [ -f /etc/mavenrc ] ; then
+ . /etc/mavenrc
+ fi
+
+ if [ -f "$HOME/.mavenrc" ] ; then
+ . "$HOME/.mavenrc"
+ fi
+
+fi
+
+# OS specific support. $var _must_ be set to either true or false.
+cygwin=false;
+darwin=false;
+mingw=false
+case "`uname`" in
+ CYGWIN*) cygwin=true ;;
+ MINGW*) mingw=true;;
+ Darwin*) darwin=true
+ # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
+ # See https://developer.apple.com/library/mac/qa/qa1170/_index.html
+ if [ -z "$JAVA_HOME" ]; then
+ if [ -x "/usr/libexec/java_home" ]; then
+ export JAVA_HOME="`/usr/libexec/java_home`"
+ else
+ export JAVA_HOME="/Library/Java/Home"
+ fi
+ fi
+ ;;
+esac
+
+if [ -z "$JAVA_HOME" ] ; then
+ if [ -r /etc/gentoo-release ] ; then
+ JAVA_HOME=`java-config --jre-home`
+ fi
+fi
+
+if [ -z "$M2_HOME" ] ; then
+ ## resolve links - $0 may be a link to maven's home
+ PRG="$0"
+
+ # need this for relative symlinks
+ while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG="`dirname "$PRG"`/$link"
+ fi
+ done
+
+ saveddir=`pwd`
+
+ M2_HOME=`dirname "$PRG"`/..
+
+ # make it fully qualified
+ M2_HOME=`cd "$M2_HOME" && pwd`
+
+ cd "$saveddir"
+ # echo Using m2 at $M2_HOME
+fi
+
+# For Cygwin, ensure paths are in UNIX format before anything is touched
+if $cygwin ; then
+ [ -n "$M2_HOME" ] &&
+ M2_HOME=`cygpath --unix "$M2_HOME"`
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
+ [ -n "$CLASSPATH" ] &&
+ CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
+fi
+
+# For Mingw, ensure paths are in UNIX format before anything is touched
+if $mingw ; then
+ [ -n "$M2_HOME" ] &&
+ M2_HOME="`(cd "$M2_HOME"; pwd)`"
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
+ # TODO classpath?
+fi
+
+if [ -z "$JAVA_HOME" ]; then
+ javaExecutable="`which javac`"
+ if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
+ # readlink(1) is not available as standard on Solaris 10.
+ readLink=`which readlink`
+ if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
+ if $darwin ; then
+ javaHome="`dirname \"$javaExecutable\"`"
+ javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
+ else
+ javaExecutable="`readlink -f \"$javaExecutable\"`"
+ fi
+ javaHome="`dirname \"$javaExecutable\"`"
+ javaHome=`expr "$javaHome" : '\(.*\)/bin'`
+ JAVA_HOME="$javaHome"
+ export JAVA_HOME
+ fi
+ fi
+fi
+
+if [ -z "$JAVACMD" ] ; then
+ if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ else
+ JAVACMD="`which java`"
+ fi
+fi
+
+if [ ! -x "$JAVACMD" ] ; then
+ echo "Error: JAVA_HOME is not defined correctly." >&2
+ echo " We cannot execute $JAVACMD" >&2
+ exit 1
+fi
+
+if [ -z "$JAVA_HOME" ] ; then
+ echo "Warning: JAVA_HOME environment variable is not set."
+fi
+
+CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
+
+# traverses directory structure from process work directory to filesystem root
+# first directory with .mvn subdirectory is considered project base directory
+find_maven_basedir() {
+
+ if [ -z "$1" ]
+ then
+ echo "Path not specified to find_maven_basedir"
+ return 1
+ fi
+
+ basedir="$1"
+ wdir="$1"
+ while [ "$wdir" != '/' ] ; do
+ if [ -d "$wdir"/.mvn ] ; then
+ basedir=$wdir
+ break
+ fi
+ # workaround for JBEAP-8937 (on Solaris 10/Sparc)
+ if [ -d "${wdir}" ]; then
+ wdir=`cd "$wdir/.."; pwd`
+ fi
+ # end of workaround
+ done
+ echo "${basedir}"
+}
+
+# concatenates all lines of a file
+concat_lines() {
+ if [ -f "$1" ]; then
+ echo "$(tr -s '\n' ' ' < "$1")"
+ fi
+}
+
+BASE_DIR=`find_maven_basedir "$(pwd)"`
+if [ -z "$BASE_DIR" ]; then
+ exit 1;
+fi
+
+export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}
+if [ "$MVNW_VERBOSE" = true ]; then
+ echo $MAVEN_PROJECTBASEDIR
+fi
+MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin; then
+ [ -n "$M2_HOME" ] &&
+ M2_HOME=`cygpath --path --windows "$M2_HOME"`
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
+ [ -n "$CLASSPATH" ] &&
+ CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
+ [ -n "$MAVEN_PROJECTBASEDIR" ] &&
+ MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"`
+fi
+
+WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+exec "$JAVACMD" \
+ $MAVEN_OPTS \
+ -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
+ "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
+ ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"
diff --git a/mvnw.cmd b/mvnw.cmd
new file mode 100755
index 000000000000..019bd74d766e
--- /dev/null
+++ b/mvnw.cmd
@@ -0,0 +1,143 @@
+@REM ----------------------------------------------------------------------------
+@REM Licensed to the Apache Software Foundation (ASF) under one
+@REM or more contributor license agreements. See the NOTICE file
+@REM distributed with this work for additional information
+@REM regarding copyright ownership. The ASF licenses this file
+@REM to you under the Apache License, Version 2.0 (the
+@REM "License"); you may not use this file except in compliance
+@REM with the License. You may obtain a copy of the License at
+@REM
+@REM http://www.apache.org/licenses/LICENSE-2.0
+@REM
+@REM Unless required by applicable law or agreed to in writing,
+@REM software distributed under the License is distributed on an
+@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+@REM KIND, either express or implied. See the License for the
+@REM specific language governing permissions and limitations
+@REM under the License.
+@REM ----------------------------------------------------------------------------
+
+@REM ----------------------------------------------------------------------------
+@REM Maven2 Start Up Batch script
+@REM
+@REM Required ENV vars:
+@REM JAVA_HOME - location of a JDK home dir
+@REM
+@REM Optional ENV vars
+@REM M2_HOME - location of maven2's installed home dir
+@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
+@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending
+@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
+@REM e.g. to debug Maven itself, use
+@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+@REM ----------------------------------------------------------------------------
+
+@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
+@echo off
+@REM enable echoing my setting MAVEN_BATCH_ECHO to 'on'
+@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
+
+@REM set %HOME% to equivalent of $HOME
+if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
+
+@REM Execute a user defined script before this one
+if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
+@REM check for pre script, once with legacy .bat ending and once with .cmd ending
+if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"
+if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd"
+:skipRcPre
+
+@setlocal
+
+set ERROR_CODE=0
+
+@REM To isolate internal variables from possible post scripts, we use another setlocal
+@setlocal
+
+@REM ==== START VALIDATION ====
+if not "%JAVA_HOME%" == "" goto OkJHome
+
+echo.
+echo Error: JAVA_HOME not found in your environment. >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+:OkJHome
+if exist "%JAVA_HOME%\bin\java.exe" goto init
+
+echo.
+echo Error: JAVA_HOME is set to an invalid directory. >&2
+echo JAVA_HOME = "%JAVA_HOME%" >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+@REM ==== END VALIDATION ====
+
+:init
+
+@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
+@REM Fallback to current working directory if not found.
+
+set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
+IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
+
+set EXEC_DIR=%CD%
+set WDIR=%EXEC_DIR%
+:findBaseDir
+IF EXIST "%WDIR%"\.mvn goto baseDirFound
+cd ..
+IF "%WDIR%"=="%CD%" goto baseDirNotFound
+set WDIR=%CD%
+goto findBaseDir
+
+:baseDirFound
+set MAVEN_PROJECTBASEDIR=%WDIR%
+cd "%EXEC_DIR%"
+goto endDetectBaseDir
+
+:baseDirNotFound
+set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
+cd "%EXEC_DIR%"
+
+:endDetectBaseDir
+
+IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
+
+@setlocal EnableExtensions EnableDelayedExpansion
+for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
+@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
+
+:endReadAdditionalConfig
+
+SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
+
+set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
+set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
+if ERRORLEVEL 1 goto error
+goto end
+
+:error
+set ERROR_CODE=1
+
+:end
+@endlocal & set ERROR_CODE=%ERROR_CODE%
+
+if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost
+@REM check for post script, once with legacy .bat ending and once with .cmd ending
+if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat"
+if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd"
+:skipRcPost
+
+@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
+if "%MAVEN_BATCH_PAUSE%" == "on" pause
+
+if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE%
+
+exit /B %ERROR_CODE%
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 000000000000..428715884b4e
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,587 @@
+
+
+ 4.0.0
+
+ junit
+ junit
+ 4.13.1
+
+ JUnit
+ JUnit is a unit testing framework for Java, created by Erich Gamma and Kent Beck.
+ http://junit.org
+ 2002
+
+ JUnit
+ http://www.junit.org
+
+
+
+ Eclipse Public License 1.0
+ http://www.eclipse.org/legal/epl-v10.html
+ repo
+
+
+
+
+
+ dsaff
+ David Saff
+ david@saff.net
+
+
+ kcooney
+ Kevin Cooney
+ kcooney@google.com
+
+
+ stefanbirkner
+ Stefan Birkner
+ mail@stefan-birkner.de
+
+
+ marcphilipp
+ Marc Philipp
+ mail@marcphilipp.de
+
+
+
+
+ JUnit contributors
+ JUnit
+ team@junit.org
+ https://github.com/junit-team/junit4/graphs/contributors
+
+ developers
+
+
+
+
+
+ 3.0.4
+
+
+
+ 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
+
+
+ github
+ https://github.com/junit-team/junit4/issues
+
+
+ travis
+ https://travis-ci.org/junit-team/junit4
+
+
+ https://github.com/junit-team/junit4/wiki/Download-and-Install
+
+ junit-snapshot-repo
+ Nexus Snapshot Repository
+ https://oss.sonatype.org/content/repositories/snapshots/
+
+
+ junit-releases-repo
+ Nexus Release Repository
+ https://oss.sonatype.org/service/local/staging/deploy/maven2/
+
+
+ junit.github.io
+ gitsite:git@github.com/junit-team/junit4.git
+
+
+
+
+ 1.5
+ 2.19.1
+ 1.3
+ ISO-8859-1
+
+ 67893CC4
+
+
+
+
+ org.hamcrest
+ hamcrest-core
+ ${hamcrestVersion}
+
+
+
+ org.hamcrest
+ hamcrest-library
+ ${hamcrestVersion}
+ test
+
+
+
+
+
+
+ ${project.basedir}/src/main/resources
+
+
+ ${project.basedir}
+
+ LICENSE-junit.txt
+
+
+
+
+
+
+
+ maven-enforcer-plugin
+ 1.4
+
+
+ enforce-versions
+ initialize
+
+ enforce
+
+
+ true
+
+
+
+ Current version of Maven ${maven.version} required to build the project
+ should be ${project.prerequisites.maven}, or higher!
+
+ [${project.prerequisites.maven},)
+
+
+ Current JDK version ${java.version} should be ${jdkVersion}, or higher!
+
+ ${jdkVersion}
+
+
+ Best Practice is to never define repositories in pom.xml (use a repository
+ manager instead).
+
+
+
+ No Snapshots Dependencies Allowed!
+
+
+
+
+
+
+
+
+ com.google.code.maven-replacer-plugin
+ replacer
+ 1.5.3
+
+
+ process-sources
+
+ replace
+
+
+
+
+ false
+ ${project.build.sourceDirectory}/junit/runner/Version.java.template
+ ${project.build.sourceDirectory}/junit/runner/Version.java
+ false
+ @version@
+ ${project.version}
+
+
+
+
+ maven-compiler-plugin
+ 3.3
+
+ ${project.build.sourceEncoding}
+ ${jdkVersion}
+ ${jdkVersion}
+ ${jdkVersion}
+ ${jdkVersion}
+ 1.5
+ true
+ true
+ true
+ true
+
+ -Xlint:unchecked
+
+ 128m
+
+
+
+ org.codehaus.mojo
+ animal-sniffer-maven-plugin
+ 1.14
+
+
+ signature-check
+ test
+
+ check
+
+
+
+ org.codehaus.mojo.signature
+ java15
+ 1.0
+
+
+
+
+
+
+
+ maven-surefire-plugin
+ ${surefireVersion}
+
+ org/junit/tests/AllTests.java
+ true
+ false
+
+
+
+ org.apache.maven.surefire
+ surefire-junit47
+ ${surefireVersion}
+
+
+
+
+
+ maven-source-plugin
+ 2.4
+
+
+
+ maven-javadoc-plugin
+ 2.10.3
+
+ ${basedir}/src/main/javadoc/stylesheet.css
+ protected
+ false
+ false
+ false
+ true
+ true
+
+ JUnit API
+ UTF-8
+ en
+ ${jdkVersion}
+
+
+ api_${jdkVersion}
+ http://docs.oracle.com/javase/${jdkVersion}.0/docs/api/
+
+
+ *.internal.*
+ true
+ 32m
+ 128m
+ true
+ true
+
+ org.hamcrest:hamcrest-core:*
+
+
+
+
+ maven-release-plugin
+ 2.5.2
+
+ forked-path
+ false
+ -Pgenerate-docs,junit-release ${arguments}
+ r@{project.version}
+
+
+
+ maven-site-plugin
+ 3.4
+
+
+ com.github.stephenc.wagon
+ wagon-gitsite
+ 0.4.1
+
+
+ org.apache.maven.doxia
+ doxia-module-markdown
+ 1.5
+
+
+
+
+ maven-jar-plugin
+ 2.6
+
+
+ false
+
+ true
+
+
+ junit
+
+
+
+
+
+ maven-clean-plugin
+ 2.6.1
+
+
+ maven-deploy-plugin
+ 2.8.2
+
+
+ maven-install-plugin
+ 2.5.2
+
+
+ maven-resources-plugin
+ 2.7
+
+
+
+
+
+
+
+ maven-project-info-reports-plugin
+ 2.8
+
+ false
+
+
+
+
+
+ index
+ dependency-info
+ modules
+ license
+ project-team
+ scm
+ issue-tracking
+ mailing-list
+ dependency-management
+ dependencies
+ dependency-convergence
+ cim
+ distribution-management
+
+
+
+
+
+ maven-javadoc-plugin
+ 2.10.3
+
+ javadoc/latest
+ ${basedir}/src/main/javadoc/stylesheet.css
+ protected
+ false
+ false
+ false
+ true
+ true
+
+ JUnit API
+ UTF-8
+ en
+ ${jdkVersion}
+
+
+ api_${jdkVersion}
+ http://docs.oracle.com/javase/${jdkVersion}.0/docs/api/
+
+
+ junit.*,*.internal.*
+ true
+ 32m
+ 128m
+ true
+ true
+
+ org.hamcrest:hamcrest-core:*
+
+
+
+
+
+ javadoc
+
+
+
+
+
+
+
+
+
+ junit-release
+
+
+
+
+
+ maven-gpg-plugin
+ 1.6
+
+
+ gpg-sign
+ verify
+
+ sign
+
+
+
+
+
+
+
+
+ generate-docs
+
+
+
+
+ maven-source-plugin
+
+
+ attach-sources
+ prepare-package
+
+ jar-no-fork
+
+
+
+
+
+ maven-javadoc-plugin
+
+
+ attach-javadoc
+ package
+
+ jar
+
+
+
+
+
+
+
+
+ restrict-doclint
+
+
+ [1.8,)
+
+
+
+
+ maven-compiler-plugin
+
+
+ -Xlint:unchecked
+ -Xdoclint:accessibility,reference,syntax
+
+
+
+
+ maven-javadoc-plugin
+
+ -Xdoclint:accessibility -Xdoclint:reference
+
+
+
+
+
+
+
+ maven-javadoc-plugin
+
+ -Xdoclint:accessibility -Xdoclint:reference
+
+
+
+
+
+
+ java9
+
+ [1.9,)
+
+
+
+ 1.6
+
+
+
+
+ maven-javadoc-plugin
+
+ 1.6
+
+
+
+
+
+
+
+ maven-javadoc-plugin
+
+ 1.6
+
+
+
+
+
+
+
diff --git a/src/main/java/junit/extensions/ActiveTestSuite.java b/src/main/java/junit/extensions/ActiveTestSuite.java
index 06235657767b..95c5e2e71062 100644
--- a/src/main/java/junit/extensions/ActiveTestSuite.java
+++ b/src/main/java/junit/extensions/ActiveTestSuite.java
@@ -10,61 +10,61 @@
* test in a separate thread and waits until all
* threads have terminated.
* -- Aarhus Radisson Scandinavian Center 11th floor
- */
+ */
public class ActiveTestSuite extends TestSuite {
- private volatile int fActiveTestDeathCount;
+ private volatile int fActiveTestDeathCount;
- public ActiveTestSuite() {
- }
-
- public ActiveTestSuite(Class extends TestCase> theClass) {
- super(theClass);
- }
-
- public ActiveTestSuite(String name) {
- super (name);
- }
-
- public ActiveTestSuite(Class extends TestCase> theClass, String name) {
- super(theClass, name);
- }
-
- @Override
- public void run(TestResult result) {
- fActiveTestDeathCount= 0;
- super.run(result);
- waitUntilFinished();
- }
-
- @Override
- public void runTest(final Test test, final TestResult result) {
- Thread t= new Thread() {
- @Override
- public void run() {
- try {
- // inlined due to limitation in VA/Java
- //ActiveTestSuite.super.runTest(test, result);
- test.run(result);
- } finally {
- ActiveTestSuite.this.runFinished();
- }
- }
- };
- t.start();
- }
+ public ActiveTestSuite() {
+ }
- synchronized void waitUntilFinished() {
- while (fActiveTestDeathCount < testCount()) {
- try {
- wait();
- } catch (InterruptedException e) {
- return; // ignore
- }
- }
- }
-
- synchronized public void runFinished() {
- fActiveTestDeathCount++;
- notifyAll();
- }
+ public ActiveTestSuite(Class extends TestCase> theClass) {
+ super(theClass);
+ }
+
+ public ActiveTestSuite(String name) {
+ super(name);
+ }
+
+ public ActiveTestSuite(Class extends TestCase> theClass, String name) {
+ super(theClass, name);
+ }
+
+ @Override
+ public void run(TestResult result) {
+ fActiveTestDeathCount = 0;
+ super.run(result);
+ waitUntilFinished();
+ }
+
+ @Override
+ public void runTest(final Test test, final TestResult result) {
+ Thread t = new Thread() {
+ @Override
+ public void run() {
+ try {
+ // inlined due to limitation in VA/Java
+ //ActiveTestSuite.super.runTest(test, result);
+ test.run(result);
+ } finally {
+ ActiveTestSuite.this.runFinished();
+ }
+ }
+ };
+ t.start();
+ }
+
+ synchronized void waitUntilFinished() {
+ while (fActiveTestDeathCount < testCount()) {
+ try {
+ wait();
+ } catch (InterruptedException e) {
+ return; // ignore
+ }
+ }
+ }
+
+ synchronized public void runFinished() {
+ fActiveTestDeathCount++;
+ notifyAll();
+ }
}
\ No newline at end of file
diff --git a/src/main/java/junit/extensions/RepeatedTest.java b/src/main/java/junit/extensions/RepeatedTest.java
index 3b687a5dd07d..22c690a9401b 100644
--- a/src/main/java/junit/extensions/RepeatedTest.java
+++ b/src/main/java/junit/extensions/RepeatedTest.java
@@ -5,34 +5,35 @@
/**
* A Decorator that runs a test repeatedly.
- *
*/
public class RepeatedTest extends TestDecorator {
- private int fTimesRepeat;
+ private int fTimesRepeat;
- public RepeatedTest(Test test, int repeat) {
- super(test);
- if (repeat < 0)
- throw new IllegalArgumentException("Repetition count must be >= 0");
- fTimesRepeat= repeat;
- }
+ public RepeatedTest(Test test, int repeat) {
+ super(test);
+ if (repeat < 0) {
+ throw new IllegalArgumentException("Repetition count must be >= 0");
+ }
+ fTimesRepeat = repeat;
+ }
- @Override
- public int countTestCases() {
- return super.countTestCases() * fTimesRepeat;
- }
+ @Override
+ public int countTestCases() {
+ return super.countTestCases() * fTimesRepeat;
+ }
- @Override
- public void run(TestResult result) {
- for (int i= 0; i < fTimesRepeat; i++) {
- if (result.shouldStop())
- break;
- super.run(result);
- }
- }
+ @Override
+ public void run(TestResult result) {
+ for (int i = 0; i < fTimesRepeat; i++) {
+ if (result.shouldStop()) {
+ break;
+ }
+ super.run(result);
+ }
+ }
- @Override
- public String toString() {
- return super.toString() + "(repeated)";
- }
+ @Override
+ public String toString() {
+ return super.toString() + "(repeated)";
+ }
}
\ No newline at end of file
diff --git a/src/main/java/junit/extensions/TestDecorator.java b/src/main/java/junit/extensions/TestDecorator.java
index d9ae47498153..a3c5e08c548e 100644
--- a/src/main/java/junit/extensions/TestDecorator.java
+++ b/src/main/java/junit/extensions/TestDecorator.java
@@ -8,36 +8,36 @@
* A Decorator for Tests. Use TestDecorator as the base class for defining new
* 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;
-
- public TestDecorator(Test test) {
- fTest= test;
- }
-
- /**
- * The basic run behaviour.
- */
- public void basicRun(TestResult result) {
- fTest.run(result);
- }
-
- public int countTestCases() {
- return fTest.countTestCases();
- }
-
- public void run(TestResult result) {
- basicRun(result);
- }
-
- @Override
- public String toString() {
- return fTest.toString();
- }
-
- public Test getTest() {
- return fTest;
- }
+ protected Test fTest;
+
+ public TestDecorator(Test test) {
+ fTest = test;
+ }
+
+ /**
+ * The basic run behaviour.
+ */
+ public void basicRun(TestResult result) {
+ fTest.run(result);
+ }
+
+ public int countTestCases() {
+ return fTest.countTestCases();
+ }
+
+ public void run(TestResult result) {
+ basicRun(result);
+ }
+
+ @Override
+ public String toString() {
+ return fTest.toString();
+ }
+
+ public Test getTest() {
+ return fTest;
+ }
}
\ No newline at end of file
diff --git a/src/main/java/junit/extensions/TestSetup.java b/src/main/java/junit/extensions/TestSetup.java
index 00dcd21eb572..fcdca8cc51bd 100644
--- a/src/main/java/junit/extensions/TestSetup.java
+++ b/src/main/java/junit/extensions/TestSetup.java
@@ -11,32 +11,32 @@
*/
public class TestSetup extends TestDecorator {
- public TestSetup(Test test) {
- super(test);
- }
+ public TestSetup(Test test) {
+ super(test);
+ }
- @Override
- public void run(final TestResult result) {
- Protectable p= new Protectable() {
- public void protect() throws Exception {
- setUp();
- basicRun(result);
- tearDown();
- }
- };
- result.runProtected(this, p);
- }
+ @Override
+ public void run(final TestResult result) {
+ Protectable p = new Protectable() {
+ public void protect() throws Exception {
+ setUp();
+ basicRun(result);
+ tearDown();
+ }
+ };
+ result.runProtected(this, p);
+ }
- /**
- * Sets up the fixture. Override to set up additional fixture state.
- */
- protected void setUp() throws Exception {
- }
+ /**
+ * Sets up the fixture. Override to set up additional fixture state.
+ */
+ protected void setUp() throws Exception {
+ }
- /**
- * Tears down the fixture. Override to tear down the additional fixture
- * state.
- */
- protected void tearDown() throws Exception {
- }
+ /**
+ * Tears down the fixture. Override to tear down the additional fixture
+ * state.
+ */
+ protected void tearDown() throws Exception {
+ }
}
\ No newline at end of file
diff --git a/src/main/java/junit/framework/Assert.java b/src/main/java/junit/framework/Assert.java
index 9bf8a18ff77a..d10cdb4247b6 100644
--- a/src/main/java/junit/framework/Assert.java
+++ b/src/main/java/junit/framework/Assert.java
@@ -2,285 +2,338 @@
/**
* A set of assert methods. Messages are only displayed when an assert fails.
+ *
+ * @deprecated Please use {@link org.junit.Assert} instead.
*/
-
+@Deprecated
public class Assert {
- /**
- * Protect constructor since it is a static only class
- */
- 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) {
- if (!condition)
- fail(message);
- }
- /**
- * Asserts that a condition is true. If it isn't it throws
- * an AssertionFailedError.
- */
- static public void assertTrue(boolean condition) {
- assertTrue(null, 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) {
- assertTrue(message, !condition);
- }
- /**
- * Asserts that a condition is false. If it isn't it throws
- * an AssertionFailedError.
- */
- static public void assertFalse(boolean condition) {
- assertFalse(null, condition);
- }
- /**
- * Fails a test with the given message.
- */
- static public void fail(String message) {
- throw new AssertionFailedError(message);
- }
- /**
- * Fails a test with no message.
- */
- static public void fail() {
- fail(null);
- }
- /**
- * 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) {
- if (expected == null && actual == null)
- return;
- if (expected != null && expected.equals(actual))
- return;
- failNotEquals(message, expected, actual);
- }
- /**
- * Asserts that two objects are equal. If they are not
- * an AssertionFailedError is thrown.
- */
- static public 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) {
- if (expected == null && actual == null)
- return;
- if (expected != null && expected.equals(actual))
- return;
- throw new ComparisonFailure(message, expected, actual);
- }
- /**
- * Asserts that two Strings are equal.
- */
- static public void assertEquals(String expected, String actual) {
- assertEquals(null, expected, actual);
- }
- /**
- * Asserts that two doubles are equal concerning a delta. If they 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, 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));
- }
- /**
- * 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) {
- assertEquals(null, expected, actual, delta);
- }
- /**
- * Asserts that two floats are equal concerning a positive delta. If they
- * 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) {
- if (Float.compare(expected, actual) == 0)
- return;
- if (!(Math.abs(expected - actual) <= delta))
- failNotEquals(message, new Float(expected), new Float(actual));
- }
- /**
- * 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) {
- assertEquals(null, expected, actual, 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) {
- assertEquals(message, new Long(expected), new Long(actual));
- }
- /**
- * Asserts that two longs are equal.
- */
- static public void assertEquals(long expected, long actual) {
- assertEquals(null, expected, 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) {
- assertEquals(message, Boolean.valueOf(expected), Boolean.valueOf(actual));
- }
- /**
- * Asserts that two booleans are equal.
- */
- static public void assertEquals(boolean expected, boolean actual) {
- assertEquals(null, expected, 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) {
- assertEquals(message, new Byte(expected), new Byte(actual));
- }
- /**
- * Asserts that two bytes are equal.
- */
- static public void assertEquals(byte expected, byte actual) {
- assertEquals(null, expected, 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) {
- assertEquals(message, new Character(expected), new Character(actual));
- }
- /**
- * Asserts that two chars are equal.
- */
- static public void assertEquals(char expected, char actual) {
- assertEquals(null, expected, 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) {
- assertEquals(message, new Short(expected), new Short(actual));
- }
- /**
- * Asserts that two shorts are equal.
- */
- static public void assertEquals(short expected, short actual) {
- assertEquals(null, expected, 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) {
- assertEquals(message, new Integer(expected), new Integer(actual));
- }
- /**
- * Asserts that two ints are equal.
- */
- static public void assertEquals(int expected, int actual) {
- assertEquals(null, expected, actual);
- }
- /**
- * Asserts that an object isn't null.
- */
- static public void assertNotNull(Object object) {
- assertNotNull(null, 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) {
- assertTrue(message, object != null);
- }
- /**
- * Asserts that an object is null.
- */
- static public void assertNull(Object object) {
- assertNull(null, 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) {
- assertTrue(message, object == null);
- }
- /**
- * 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) {
- if (expected == actual)
- return;
- failNotSame(message, expected, 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) {
- assertSame(null, expected, actual);
- }
- /**
- * Asserts that two objects do not refer to the same object. If they do
- * refer to the same object an AssertionFailedError is thrown with the
- * given message.
- */
- static public void assertNotSame(String message, Object expected, Object actual) {
- if (expected == actual)
- failSame(message);
- }
- /**
- * 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) {
- assertNotSame(null, expected, actual);
- }
-
- static public void failSame(String message) {
- String formatted= "";
- if (message != null)
- formatted= message+" ";
- fail(formatted+"expected not same");
- }
-
- static public void failNotSame(String message, Object expected, Object actual) {
- String formatted= "";
- if (message != null)
- formatted= message+" ";
- fail(formatted+"expected same:<"+expected+"> was not:<"+actual+">");
- }
-
- static public void failNotEquals(String message, Object expected, Object actual) {
- fail(format(message, expected, actual));
- }
-
- public static String format(String message, Object expected, Object actual) {
- String formatted= "";
- if (message != null)
- formatted= message+" ";
- return formatted+"expected:<"+expected+"> but was:<"+actual+">";
- }
+ /**
+ * Protect constructor since it is a static only class
+ */
+ 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) {
+ if (!condition) {
+ fail(message);
+ }
+ }
+
+ /**
+ * Asserts that a condition is true. If it isn't it throws
+ * an AssertionFailedError.
+ */
+ static public void assertTrue(boolean condition) {
+ assertTrue(null, 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) {
+ assertTrue(message, !condition);
+ }
+
+ /**
+ * Asserts that a condition is false. If it isn't it throws
+ * an AssertionFailedError.
+ */
+ static public void assertFalse(boolean condition) {
+ assertFalse(null, condition);
+ }
+
+ /**
+ * Fails a test with the given message.
+ */
+ static public void fail(String message) {
+ if (message == null) {
+ throw new AssertionFailedError();
+ }
+ throw new AssertionFailedError(message);
+ }
+
+ /**
+ * Fails a test with no message.
+ */
+ static public void fail() {
+ fail(null);
+ }
+
+ /**
+ * 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) {
+ if (expected == null && actual == null) {
+ return;
+ }
+ if (expected != null && expected.equals(actual)) {
+ return;
+ }
+ failNotEquals(message, expected, actual);
+ }
+
+ /**
+ * Asserts that two objects are equal. If they are not
+ * an AssertionFailedError is thrown.
+ */
+ static public 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) {
+ if (expected == null && actual == null) {
+ return;
+ }
+ if (expected != null && expected.equals(actual)) {
+ return;
+ }
+ String cleanMessage = message == null ? "" : message;
+ throw new ComparisonFailure(cleanMessage, expected, actual);
+ }
+
+ /**
+ * Asserts that two Strings are equal.
+ */
+ static public void assertEquals(String expected, String actual) {
+ assertEquals(null, expected, actual);
+ }
+
+ /**
+ * Asserts that two doubles are equal concerning a delta. If they 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, double expected, double actual, double delta) {
+ if (Double.compare(expected, actual) == 0) {
+ return;
+ }
+ if (!(Math.abs(expected - actual) <= delta)) {
+ failNotEquals(message, Double.valueOf(expected), Double.valueOf(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) {
+ assertEquals(null, expected, actual, delta);
+ }
+
+ /**
+ * Asserts that two floats are equal concerning a positive delta. If they
+ * 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) {
+ if (Float.compare(expected, actual) == 0) {
+ return;
+ }
+ if (!(Math.abs(expected - actual) <= delta)) {
+ failNotEquals(message, Float.valueOf(expected), Float.valueOf(actual));
+ }
+ }
+
+ /**
+ * 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) {
+ assertEquals(null, expected, actual, 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) {
+ assertEquals(message, Long.valueOf(expected), Long.valueOf(actual));
+ }
+
+ /**
+ * Asserts that two longs are equal.
+ */
+ static public void assertEquals(long expected, long actual) {
+ assertEquals(null, expected, 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) {
+ assertEquals(message, Boolean.valueOf(expected), Boolean.valueOf(actual));
+ }
+
+ /**
+ * Asserts that two booleans are equal.
+ */
+ static public void assertEquals(boolean expected, boolean actual) {
+ assertEquals(null, expected, 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) {
+ assertEquals(message, Byte.valueOf(expected), Byte.valueOf(actual));
+ }
+
+ /**
+ * Asserts that two bytes are equal.
+ */
+ static public void assertEquals(byte expected, byte actual) {
+ assertEquals(null, expected, 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) {
+ assertEquals(message, Character.valueOf(expected), Character.valueOf(actual));
+ }
+
+ /**
+ * Asserts that two chars are equal.
+ */
+ static public void assertEquals(char expected, char actual) {
+ assertEquals(null, expected, 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) {
+ assertEquals(message, Short.valueOf(expected), Short.valueOf(actual));
+ }
+
+ /**
+ * Asserts that two shorts are equal.
+ */
+ static public void assertEquals(short expected, short actual) {
+ assertEquals(null, expected, 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) {
+ assertEquals(message, Integer.valueOf(expected), Integer.valueOf(actual));
+ }
+
+ /**
+ * Asserts that two ints are equal.
+ */
+ static public void assertEquals(int expected, int actual) {
+ assertEquals(null, expected, actual);
+ }
+
+ /**
+ * Asserts that an object isn't null.
+ */
+ static public void assertNotNull(Object object) {
+ assertNotNull(null, 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) {
+ assertTrue(message, object != null);
+ }
+
+ /**
+ * Asserts that an object is null. If it isn't an {@link AssertionError} is
+ * thrown.
+ * Message contains: Expected: but was: object
+ *
+ * @param object Object to check or null
+ */
+ static public void assertNull(Object object) {
+ if (object != null) {
+ assertNull("Expected: but was: " + object.toString(), 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) {
+ assertTrue(message, object == null);
+ }
+
+ /**
+ * 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) {
+ if (expected == actual) {
+ return;
+ }
+ failNotSame(message, expected, 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) {
+ assertSame(null, expected, actual);
+ }
+
+ /**
+ * Asserts that two objects do not refer to the same object. If they do
+ * refer to the same object an AssertionFailedError is thrown with the
+ * given message.
+ */
+ static public void assertNotSame(String message, Object expected, Object actual) {
+ if (expected == actual) {
+ failSame(message);
+ }
+ }
+
+ /**
+ * 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) {
+ assertNotSame(null, expected, actual);
+ }
+
+ static public void failSame(String message) {
+ String formatted = (message != null) ? message + " " : "";
+ fail(formatted + "expected not same");
+ }
+
+ static public 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) {
+ fail(format(message, expected, actual));
+ }
+
+ public static String format(String message, Object expected, Object actual) {
+ String formatted = "";
+ if (message != null && message.length() > 0) {
+ formatted = message + " ";
+ }
+ return formatted + "expected:<" + expected + "> but was:<" + actual + ">";
+ }
}
diff --git a/src/main/java/junit/framework/AssertionFailedError.java b/src/main/java/junit/framework/AssertionFailedError.java
index 054f7c96c23a..e11fbec9f16a 100644
--- a/src/main/java/junit/framework/AssertionFailedError.java
+++ b/src/main/java/junit/framework/AssertionFailedError.java
@@ -5,12 +5,25 @@
*/
public class AssertionFailedError extends AssertionError {
- private static final long serialVersionUID= 1L;
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * Constructs a new AssertionFailedError without a detail message.
+ */
+ public AssertionFailedError() {
+ }
- public AssertionFailedError() {
- }
+ /**
+ * Constructs a new AssertionFailedError with the specified detail message.
+ * A null message is replaced by an empty String.
+ * @param message the detail message. The detail message is saved for later
+ * retrieval by the {@code Throwable.getMessage()} method.
+ */
+ public AssertionFailedError(String message) {
+ super(defaultString(message));
+ }
- public AssertionFailedError(String message) {
- super(message);
- }
+ private static String defaultString(String message) {
+ return message == null ? "" : message;
+ }
}
\ No newline at end of file
diff --git a/src/main/java/junit/framework/ComparisonCompactor.java b/src/main/java/junit/framework/ComparisonCompactor.java
index bbc3ba1cd451..81ddd5bda514 100644
--- a/src/main/java/junit/framework/ComparisonCompactor.java
+++ b/src/main/java/junit/framework/ComparisonCompactor.java
@@ -2,71 +2,77 @@
public class ComparisonCompactor {
- private static final String ELLIPSIS= "...";
- private static final String DELTA_END= "]";
- private static final String DELTA_START= "[";
-
- private int fContextLength;
- private String fExpected;
- private String fActual;
- private int fPrefix;
- private int fSuffix;
+ private static final String ELLIPSIS = "...";
+ private static final String DELTA_END = "]";
+ private static final String DELTA_START = "[";
- public ComparisonCompactor(int contextLength, String expected, String actual) {
- fContextLength= contextLength;
- fExpected= expected;
- fActual= actual;
- }
+ private int fContextLength;
+ private String fExpected;
+ private String fActual;
+ private int fPrefix;
+ private int fSuffix;
- public String compact(String message) {
- if (fExpected == null || fActual == null || areStringsEqual())
- return Assert.format(message, fExpected, fActual);
+ public ComparisonCompactor(int contextLength, String expected, String actual) {
+ fContextLength = contextLength;
+ fExpected = expected;
+ fActual = actual;
+ }
- findCommonPrefix();
- findCommonSuffix();
- String expected= compactString(fExpected);
- String actual= compactString(fActual);
- return Assert.format(message, expected, actual);
- }
+ @SuppressWarnings("deprecation")
+ public String compact(String message) {
+ if (fExpected == null || fActual == null || areStringsEqual()) {
+ return Assert.format(message, fExpected, fActual);
+ }
- private String compactString(String source) {
- String result= DELTA_START + source.substring(fPrefix, source.length() - fSuffix + 1) + DELTA_END;
- if (fPrefix > 0)
- result= computeCommonPrefix() + result;
- if (fSuffix > 0)
- result= result + computeCommonSuffix();
- return result;
- }
+ findCommonPrefix();
+ findCommonSuffix();
+ String expected = compactString(fExpected);
+ String actual = compactString(fActual);
+ return Assert.format(message, expected, actual);
+ }
- private void findCommonPrefix() {
- fPrefix= 0;
- int end= Math.min(fExpected.length(), fActual.length());
- for (; fPrefix < end; fPrefix++) {
- if (fExpected.charAt(fPrefix) != fActual.charAt(fPrefix))
- break;
- }
- }
+ private String compactString(String source) {
+ String result = DELTA_START + source.substring(fPrefix, source.length() - fSuffix + 1) + DELTA_END;
+ if (fPrefix > 0) {
+ result = computeCommonPrefix() + result;
+ }
+ if (fSuffix > 0) {
+ result = result + computeCommonSuffix();
+ }
+ return result;
+ }
- private void findCommonSuffix() {
- int expectedSuffix= fExpected.length() - 1;
- int actualSuffix= fActual.length() - 1;
- for (; actualSuffix >= fPrefix && expectedSuffix >= fPrefix; actualSuffix--, expectedSuffix--) {
- if (fExpected.charAt(expectedSuffix) != fActual.charAt(actualSuffix))
- break;
- }
- fSuffix= fExpected.length() - expectedSuffix;
- }
+ private void findCommonPrefix() {
+ fPrefix = 0;
+ int end = Math.min(fExpected.length(), fActual.length());
+ for (; fPrefix < end; fPrefix++) {
+ if (fExpected.charAt(fPrefix) != fActual.charAt(fPrefix)) {
+ break;
+ }
+ }
+ }
- private String computeCommonPrefix() {
- return (fPrefix > fContextLength ? ELLIPSIS : "") + fExpected.substring(Math.max(0, fPrefix - fContextLength), fPrefix);
- }
+ private void findCommonSuffix() {
+ int expectedSuffix = fExpected.length() - 1;
+ int actualSuffix = fActual.length() - 1;
+ for (; actualSuffix >= fPrefix && expectedSuffix >= fPrefix; actualSuffix--, expectedSuffix--) {
+ if (fExpected.charAt(expectedSuffix) != fActual.charAt(actualSuffix)) {
+ break;
+ }
+ }
+ fSuffix = fExpected.length() - expectedSuffix;
+ }
- private String computeCommonSuffix() {
- int end= Math.min(fExpected.length() - fSuffix + 1 + fContextLength, fExpected.length());
- return fExpected.substring(fExpected.length() - fSuffix + 1, end) + (fExpected.length() - fSuffix + 1 < fExpected.length() - fContextLength ? ELLIPSIS : "");
- }
+ private String computeCommonPrefix() {
+ return (fPrefix > fContextLength ? ELLIPSIS : "") + fExpected.substring(Math.max(0, fPrefix - fContextLength), fPrefix);
+ }
- private boolean areStringsEqual() {
- return fExpected.equals(fActual);
- }
+ private String computeCommonSuffix() {
+ int end = Math.min(fExpected.length() - fSuffix + 1 + fContextLength, fExpected.length());
+ return fExpected.substring(fExpected.length() - fSuffix + 1, end) + (fExpected.length() - fSuffix + 1 < fExpected.length() - fContextLength ? ELLIPSIS : "");
+ }
+
+ private boolean areStringsEqual() {
+ return fExpected.equals(fActual);
+ }
}
diff --git a/src/main/java/junit/framework/ComparisonFailure.java b/src/main/java/junit/framework/ComparisonFailure.java
index 507799328a44..66433ef3e87b 100644
--- a/src/main/java/junit/framework/ComparisonFailure.java
+++ b/src/main/java/junit/framework/ComparisonFailure.java
@@ -2,51 +2,55 @@
/**
* Thrown when an assert equals for Strings failed.
- *
+ *
* Inspired by a patch from Alex Chaffee mailto:alex@purpletech.com
*/
public class ComparisonFailure extends AssertionFailedError {
- private static final int MAX_CONTEXT_LENGTH= 20;
- private static final long serialVersionUID= 1L;
-
- private String fExpected;
- private String fActual;
+ private static final int MAX_CONTEXT_LENGTH = 20;
+ private static final long serialVersionUID = 1L;
- /**
- * Constructs a comparison failure.
- * @param message the identifying message or null
- * @param expected the expected string value
- * @param actual the actual string value
- */
- public ComparisonFailure (String message, String expected, String actual) {
- super (message);
- fExpected= expected;
- fActual= actual;
- }
-
- /**
- * Returns "..." in place of common prefix and "..." in
- * place of common suffix between expected and actual.
- *
- * @see Throwable#getMessage()
- */
- @Override
- public String getMessage() {
- return new ComparisonCompactor(MAX_CONTEXT_LENGTH, fExpected, fActual).compact(super.getMessage());
- }
-
- /**
- * Gets the actual string value
- * @return the actual string value
- */
- public String getActual() {
- return fActual;
- }
- /**
- * Gets the expected string value
- * @return the expected string value
- */
- public String getExpected() {
- return fExpected;
- }
+ private String fExpected;
+ private String fActual;
+
+ /**
+ * Constructs a comparison failure.
+ *
+ * @param message the identifying message or null
+ * @param expected the expected string value
+ * @param actual the actual string value
+ */
+ public ComparisonFailure(String message, String expected, String actual) {
+ super(message);
+ fExpected = expected;
+ fActual = actual;
+ }
+
+ /**
+ * Returns "..." in place of common prefix and "..." in
+ * place of common suffix between expected and actual.
+ *
+ * @see Throwable#getMessage()
+ */
+ @Override
+ public String getMessage() {
+ return new ComparisonCompactor(MAX_CONTEXT_LENGTH, fExpected, fActual).compact(super.getMessage());
+ }
+
+ /**
+ * Gets the actual string value
+ *
+ * @return the actual string value
+ */
+ public String getActual() {
+ return fActual;
+ }
+
+ /**
+ * Gets the expected string value
+ *
+ * @return the expected string value
+ */
+ public String getExpected() {
+ return fExpected;
+ }
}
\ No newline at end of file
diff --git a/src/main/java/junit/framework/JUnit4TestAdapter.java b/src/main/java/junit/framework/JUnit4TestAdapter.java
index f5662186ff70..9d32031e4eba 100644
--- a/src/main/java/junit/framework/JUnit4TestAdapter.java
+++ b/src/main/java/junit/framework/JUnit4TestAdapter.java
@@ -9,77 +9,99 @@
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 {
- private final Class> fNewTestClass;
-
- private Runner fRunner;
-
- private JUnit4TestAdapterCache fCache;
-
- public JUnit4TestAdapter(Class> newTestClass) {
- this(newTestClass, JUnit4TestAdapterCache.getDefault());
- }
-
- public JUnit4TestAdapter(final Class> newTestClass,
- JUnit4TestAdapterCache cache) {
- fCache = cache;
- fNewTestClass = newTestClass;
- fRunner = Request.classWithoutSuiteMethod(newTestClass).getRunner();
- }
-
- public int countTestCases() {
- return fRunner.testCount();
- }
-
- public void run(TestResult result) {
- fRunner.run(fCache.getNotifier(result, this));
- }
-
- // reflective interface for Eclipse
- public List getTests() {
- return fCache.asTestList(getDescription());
- }
-
- // reflective interface for Eclipse
- public Class> getTestClass() {
- return fNewTestClass;
- }
-
- public Description getDescription() {
- Description description= fRunner.getDescription();
- return removeIgnored(description);
- }
-
- private Description removeIgnored(Description description) {
- if (isIgnored(description))
- return Description.EMPTY;
- Description result = description.childlessCopy();
- for (Description each : description.getChildren()) {
- Description child= removeIgnored(each);
- if (! child.isEmpty())
- result.addChild(child);
- }
- return result;
- }
-
- private boolean isIgnored(Description description) {
- return description.getAnnotation(Ignore.class) != null;
- }
-
- @Override
- public String toString() {
- return fNewTestClass.getName();
- }
-
- public void filter(Filter filter) throws NoTestsRemainException {
- filter.apply(fRunner);
- }
-
- public void sort(Sorter sorter) {
- sorter.apply(fRunner);
- }
+/**
+ * The JUnit4TestAdapter enables running JUnit-4-style tests using a JUnit-3-style test runner.
+ *
+ *
To use it, add the following to a test class:
+ *
+ public static Test suite() {
+ return new JUnit4TestAdapter(YourJUnit4TestClass.class);
+ }
+
+ */
+public class JUnit4TestAdapter implements Test, Filterable, Orderable, Describable {
+ private final Class> fNewTestClass;
+
+ private final Runner fRunner;
+
+ private final JUnit4TestAdapterCache fCache;
+
+ public JUnit4TestAdapter(Class> newTestClass) {
+ this(newTestClass, JUnit4TestAdapterCache.getDefault());
+ }
+
+ public JUnit4TestAdapter(final Class> newTestClass, JUnit4TestAdapterCache cache) {
+ fCache = cache;
+ fNewTestClass = newTestClass;
+ fRunner = Request.classWithoutSuiteMethod(newTestClass).getRunner();
+ }
+
+ public int countTestCases() {
+ return fRunner.testCount();
+ }
+
+ public void run(TestResult result) {
+ fRunner.run(fCache.getNotifier(result, this));
+ }
+
+ // reflective interface for Eclipse
+ public List getTests() {
+ return fCache.asTestList(getDescription());
+ }
+
+ // reflective interface for Eclipse
+ public Class> getTestClass() {
+ return fNewTestClass;
+ }
+
+ public Description getDescription() {
+ Description description = fRunner.getDescription();
+ return removeIgnored(description);
+ }
+
+ private Description removeIgnored(Description description) {
+ if (isIgnored(description)) {
+ return Description.EMPTY;
+ }
+ Description result = description.childlessCopy();
+ for (Description each : description.getChildren()) {
+ Description child = removeIgnored(each);
+ if (!child.isEmpty()) {
+ result.addChild(child);
+ }
+ }
+ return result;
+ }
+
+ private boolean isIgnored(Description description) {
+ return description.getAnnotation(Ignore.class) != null;
+ }
+
+ @Override
+ public String toString() {
+ return fNewTestClass.getName();
+ }
+
+ public void filter(Filter filter) throws NoTestsRemainException {
+ filter.apply(fRunner);
+ }
+
+ 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/JUnit4TestAdapterCache.java b/src/main/java/junit/framework/JUnit4TestAdapterCache.java
index 26175c54e53a..603f26103309 100644
--- a/src/main/java/junit/framework/JUnit4TestAdapterCache.java
+++ b/src/main/java/junit/framework/JUnit4TestAdapterCache.java
@@ -1,6 +1,3 @@
-/**
- *
- */
package junit.framework;
import java.util.ArrayList;
@@ -14,68 +11,67 @@
import org.junit.runner.notification.RunNotifier;
public class JUnit4TestAdapterCache extends HashMap {
- private static final long serialVersionUID = 1L;
- private static final JUnit4TestAdapterCache fInstance = new JUnit4TestAdapterCache();
+ private static final long serialVersionUID = 1L;
+ private static final JUnit4TestAdapterCache fInstance = new JUnit4TestAdapterCache();
- public static JUnit4TestAdapterCache getDefault() {
- return fInstance;
- }
-
- public Test asTest(Description description) {
- if (description.isSuite())
- return createTest(description);
- else {
- if (!containsKey(description))
- put(description, createTest(description));
- return get(description);
- }
- }
+ public static JUnit4TestAdapterCache getDefault() {
+ return fInstance;
+ }
- Test createTest(Description description) {
- if (description.isTest())
- return new JUnit4TestCaseFacade(description);
- else {
- TestSuite suite = new TestSuite(description.getDisplayName());
- for (Description child : description.getChildren())
- suite.addTest(asTest(child));
- return suite;
- }
- }
+ public Test asTest(Description description) {
+ if (description.isSuite()) {
+ return createTest(description);
+ } else {
+ if (!containsKey(description)) {
+ put(description, createTest(description));
+ }
+ return get(description);
+ }
+ }
- public RunNotifier getNotifier(final TestResult result,
- final JUnit4TestAdapter adapter) {
- RunNotifier notifier = new RunNotifier();
- notifier.addListener(new RunListener() {
- @Override
- public void testFailure(Failure failure) throws Exception {
- result.addError(asTest(failure.getDescription()), failure.getException());
- }
+ Test createTest(Description description) {
+ if (description.isTest()) {
+ return new JUnit4TestCaseFacade(description);
+ } else {
+ TestSuite suite = new TestSuite(description.getDisplayName());
+ for (Description child : description.getChildren()) {
+ suite.addTest(asTest(child));
+ }
+ return suite;
+ }
+ }
- @Override
- public void testFinished(Description description)
- throws Exception {
- result.endTest(asTest(description));
- }
+ public RunNotifier getNotifier(final TestResult result, final JUnit4TestAdapter adapter) {
+ RunNotifier notifier = new RunNotifier();
+ notifier.addListener(new RunListener() {
+ @Override
+ public void testFailure(Failure failure) throws Exception {
+ result.addError(asTest(failure.getDescription()), failure.getException());
+ }
- @Override
- public void testStarted(Description description)
- throws Exception {
- result.startTest(asTest(description));
- }
- });
- return notifier;
- }
+ @Override
+ public void testFinished(Description description) throws Exception {
+ result.endTest(asTest(description));
+ }
- public List asTestList(Description description) {
- if (description.isTest())
- return Arrays.asList(asTest(description));
- else {
- List returnThis = new ArrayList();
- for (Description child : description.getChildren()) {
- returnThis.add(asTest(child));
- }
- return returnThis;
- }
- }
+ @Override
+ public void testStarted(Description description) throws Exception {
+ result.startTest(asTest(description));
+ }
+ });
+ return notifier;
+ }
+
+ public List asTestList(Description description) {
+ if (description.isTest()) {
+ return Arrays.asList(asTest(description));
+ } else {
+ List returnThis = new ArrayList();
+ for (Description child : description.getChildren()) {
+ returnThis.add(asTest(child));
+ }
+ return returnThis;
+ }
+ }
}
\ No newline at end of file
diff --git a/src/main/java/junit/framework/JUnit4TestCaseFacade.java b/src/main/java/junit/framework/JUnit4TestCaseFacade.java
index fd4382231619..5fd8ac75206f 100644
--- a/src/main/java/junit/framework/JUnit4TestCaseFacade.java
+++ b/src/main/java/junit/framework/JUnit4TestCaseFacade.java
@@ -1,33 +1,30 @@
-/**
- *
- */
package junit.framework;
import org.junit.runner.Describable;
import org.junit.runner.Description;
public class JUnit4TestCaseFacade implements Test, Describable {
- private final Description fDescription;
+ private final Description fDescription;
- JUnit4TestCaseFacade(Description description) {
- fDescription = description;
- }
+ JUnit4TestCaseFacade(Description description) {
+ fDescription = description;
+ }
- @Override
- public String toString() {
- return getDescription().toString();
- }
+ @Override
+ public String toString() {
+ return getDescription().toString();
+ }
- public int countTestCases() {
- return 1;
- }
+ public int countTestCases() {
+ return 1;
+ }
- public void run(TestResult result) {
- throw new RuntimeException(
- "This test stub created only for informational purposes.");
- }
+ public void run(TestResult result) {
+ throw new RuntimeException(
+ "This test stub created only for informational purposes.");
+ }
- public Description getDescription() {
- return fDescription;
- }
+ public Description getDescription() {
+ return fDescription;
+ }
}
\ 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 e1432370cfaf..c5ceb16ae038 100644
--- a/src/main/java/junit/framework/Protectable.java
+++ b/src/main/java/junit/framework/Protectable.java
@@ -7,8 +7,8 @@
*/
public interface Protectable {
- /**
- * Run the the following method protected.
- */
- public abstract void protect() throws Throwable;
-}
\ No newline at end of file
+ /**
+ * Run the following method protected.
+ */
+ public abstract void protect() throws Throwable;
+}
diff --git a/src/main/java/junit/framework/Test.java b/src/main/java/junit/framework/Test.java
index a016ee8308f1..db95c6c7ad0e 100644
--- a/src/main/java/junit/framework/Test.java
+++ b/src/main/java/junit/framework/Test.java
@@ -6,12 +6,13 @@
* @see TestResult
*/
public interface Test {
- /**
- * Counts the number of test cases that will be run by this test.
- */
- public abstract int countTestCases();
- /**
- * Runs a test and collects its result in a TestResult instance.
- */
- public abstract void run(TestResult result);
+ /**
+ * Counts the number of test cases that will be run by this test.
+ */
+ public abstract int countTestCases();
+
+ /**
+ * Runs a test and collects its result in a TestResult instance.
+ */
+ public abstract void run(TestResult result);
}
\ 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 b047ec9e1afc..e474a6493664 100644
--- a/src/main/java/junit/framework/TestCase.java
+++ b/src/main/java/junit/framework/TestCase.java
@@ -36,7 +36,7 @@
* assertTrue(result == 5.0);
* }
*
- *
+ *
* Once the methods are defined you can run them. The framework supports
* both a static type safe and more dynamic way to run a test.
* In the static way you override the runTest method and define the method to
@@ -49,7 +49,6 @@
* };
* test.run();
*
- *
* The dynamic way uses reflection to implement {@link #runTest()}. It dynamically finds
* and invokes a method.
* In this case the name of the test case has to correspond to the test method
@@ -58,7 +57,7 @@
* TestCase test= new MathTest("testAdd");
* test.run();
*
- *
+ *
* The tests to be run can be collected into a TestSuite. JUnit provides
* different test runners which can run a test suite and collect the results.
* A test runner either expects a static method suite as the entry
@@ -70,143 +69,441 @@
* return suite;
* }
*
+ *
* @see TestResult
* @see TestSuite
*/
+@SuppressWarnings("deprecation")
public abstract class TestCase extends Assert implements Test {
- /**
- * the name of the test case
- */
- private String fName;
-
- /**
- * No-arg constructor to enable serialization. This method
- * is not intended to be used by mere mortals without calling setName().
- */
- public TestCase() {
- fName= null;
- }
- /**
- * Constructs a test case with the given name.
- */
- public TestCase(String name) {
- fName= name;
- }
- /**
- * Counts the number of test cases executed by run(TestResult result).
- */
- public int countTestCases() {
- return 1;
- }
- /**
- * Creates a default TestResult object
- *
- * @see TestResult
- */
- protected TestResult createResult() {
- return new TestResult();
- }
- /**
- * A convenience method to run this test, collecting the results with a
- * default TestResult object.
- *
- * @see TestResult
- */
- public TestResult run() {
- TestResult result= createResult();
- run(result);
- return result;
- }
- /**
- * Runs the test case and collects the results in TestResult.
- */
- public void run(TestResult result) {
- result.run(this);
- }
- /**
- * Runs the bare test sequence.
- * @throws Throwable if any exception is thrown
- */
- public void runBare() throws Throwable {
- Throwable exception= null;
- setUp();
- try {
- runTest();
- } catch (Throwable running) {
- exception= running;
- }
- finally {
- try {
- tearDown();
- } catch (Throwable tearingDown) {
- if (exception == null) exception= tearingDown;
- }
- }
- if (exception != null) throw exception;
- }
- /**
- * Override to run the test and assert its state.
- * @throws Throwable if any exception is thrown
- */
- protected void runTest() throws Throwable {
- assertNotNull("TestCase.fName cannot be null", fName); // Some VMs crash when calling getMethod(null,null);
- Method runMethod= null;
- try {
- // use getMethod to get all public inherited
- // methods. getDeclaredMethods returns all
- // methods of this class but excludes the
- // inherited ones.
- runMethod= getClass().getMethod(fName, (Class[])null);
- } catch (NoSuchMethodException e) {
- fail("Method \""+fName+"\" not found");
- }
- if (!Modifier.isPublic(runMethod.getModifiers())) {
- fail("Method \""+fName+"\" should be public");
- }
-
- try {
- runMethod.invoke(this);
- }
- catch (InvocationTargetException e) {
- e.fillInStackTrace();
- throw e.getTargetException();
- }
- catch (IllegalAccessException e) {
- e.fillInStackTrace();
- throw e;
- }
- }
- /**
- * Sets up the fixture, for example, open a network connection.
- * This method is called before a test is executed.
- */
- protected void setUp() throws Exception {
- }
- /**
- * Tears down the fixture, for example, close a network connection.
- * This method is called after a test is executed.
- */
- protected void tearDown() throws Exception {
- }
- /**
- * Returns a string representation of the test case
- */
- @Override
- public String toString() {
- return getName() + "(" + getClass().getName() + ")";
- }
- /**
- * Gets the name of a TestCase
- * @return the name of the TestCase
- */
- public String getName() {
- return fName;
- }
- /**
- * Sets the name of a TestCase
- * @param name the name to set
- */
- public void setName(String name) {
- fName= name;
- }
+ /**
+ * the name of the test case
+ */
+ private String fName;
+
+ /**
+ * No-arg constructor to enable serialization. This method
+ * is not intended to be used by mere mortals without calling setName().
+ */
+ public TestCase() {
+ fName = null;
+ }
+
+ /**
+ * Constructs a test case with the given name.
+ */
+ public TestCase(String name) {
+ fName = name;
+ }
+
+ /**
+ * Counts the number of test cases executed by run(TestResult result).
+ */
+ public int countTestCases() {
+ return 1;
+ }
+
+ /**
+ * Creates a default TestResult object.
+ *
+ * @see TestResult
+ */
+ protected TestResult createResult() {
+ return new TestResult();
+ }
+
+ /**
+ * A convenience method to run this test, collecting the results with a
+ * default TestResult object.
+ *
+ * @see TestResult
+ */
+ public TestResult run() {
+ TestResult result = createResult();
+ run(result);
+ return result;
+ }
+
+ /**
+ * Runs the test case and collects the results in TestResult.
+ */
+ public void run(TestResult result) {
+ result.run(this);
+ }
+
+ /**
+ * Runs the bare test sequence.
+ *
+ * @throws Throwable if any exception is thrown
+ */
+ public void runBare() throws Throwable {
+ Throwable exception = null;
+ setUp();
+ try {
+ runTest();
+ } catch (Throwable running) {
+ exception = running;
+ } finally {
+ try {
+ tearDown();
+ } catch (Throwable tearingDown) {
+ if (exception == null) exception = tearingDown;
+ }
+ }
+ if (exception != null) throw exception;
+ }
+
+ /**
+ * Override to run the test and assert its state.
+ *
+ * @throws Throwable if any exception is thrown
+ */
+ protected void runTest() throws Throwable {
+ assertNotNull("TestCase.fName cannot be null", fName); // Some VMs crash when calling getMethod(null,null);
+ Method runMethod = null;
+ try {
+ // use getMethod to get all public inherited
+ // methods. getDeclaredMethods returns all
+ // methods of this class but excludes the
+ // inherited ones.
+ runMethod = getClass().getMethod(fName, (Class[]) null);
+ } catch (NoSuchMethodException e) {
+ fail("Method \"" + fName + "\" not found");
+ }
+ if (!Modifier.isPublic(runMethod.getModifiers())) {
+ fail("Method \"" + fName + "\" should be public");
+ }
+
+ try {
+ runMethod.invoke(this);
+ } catch (InvocationTargetException e) {
+ e.fillInStackTrace();
+ throw e.getTargetException();
+ } catch (IllegalAccessException e) {
+ e.fillInStackTrace();
+ throw e;
+ }
+ }
+
+ /**
+ * Asserts that a condition is true. If it isn't it throws
+ * an AssertionFailedError with the given message.
+ */
+ public static void assertTrue(String message, boolean condition) {
+ Assert.assertTrue(message, condition);
+ }
+
+ /**
+ * Asserts that a condition is true. If it isn't it throws
+ * an AssertionFailedError.
+ */
+ public static void assertTrue(boolean condition) {
+ Assert.assertTrue(condition);
+ }
+
+ /**
+ * Asserts that a condition is false. If it isn't it throws
+ * an AssertionFailedError with the given message.
+ */
+ public static void assertFalse(String message, boolean condition) {
+ Assert.assertFalse(message, condition);
+ }
+
+ /**
+ * Asserts that a condition is false. If it isn't it throws
+ * an AssertionFailedError.
+ */
+ public static void assertFalse(boolean condition) {
+ Assert.assertFalse(condition);
+ }
+
+ /**
+ * Fails a test with the given message.
+ */
+ public static void fail(String message) {
+ Assert.fail(message);
+ }
+
+ /**
+ * Fails a test with no message.
+ */
+ public static void fail() {
+ Assert.fail();
+ }
+
+ /**
+ * Asserts that two objects are equal. If they are not
+ * an AssertionFailedError is thrown with the given message.
+ */
+ public static void assertEquals(String message, Object expected, Object actual) {
+ Assert.assertEquals(message, expected, actual);
+ }
+
+ /**
+ * Asserts that two objects are equal. If they are not
+ * an AssertionFailedError is thrown.
+ */
+ public static void assertEquals(Object expected, Object actual) {
+ Assert.assertEquals(expected, actual);
+ }
+
+ /**
+ * Asserts that two Strings are equal.
+ */
+ public static void assertEquals(String message, String expected, String actual) {
+ Assert.assertEquals(message, expected, actual);
+ }
+
+ /**
+ * Asserts that two Strings are equal.
+ */
+ public static void assertEquals(String expected, String actual) {
+ Assert.assertEquals(expected, actual);
+ }
+
+ /**
+ * Asserts that two doubles are equal concerning a delta. If they are not
+ * an AssertionFailedError is thrown with the given message. If the expected
+ * value is infinity then the delta value is ignored.
+ */
+ public static void assertEquals(String message, double expected, double actual, double delta) {
+ Assert.assertEquals(message, expected, actual, delta);
+ }
+
+ /**
+ * Asserts that two doubles are equal concerning a delta. If the expected
+ * value is infinity then the delta value is ignored.
+ */
+ public static void assertEquals(double expected, double actual, double delta) {
+ Assert.assertEquals(expected, actual, delta);
+ }
+
+ /**
+ * Asserts that two floats are equal concerning a positive delta. If they
+ * are not an AssertionFailedError is thrown with the given message. If the
+ * expected value is infinity then the delta value is ignored.
+ */
+ public static void assertEquals(String message, float expected, float actual, float delta) {
+ Assert.assertEquals(message, expected, actual, delta);
+ }
+
+ /**
+ * Asserts that two floats are equal concerning a delta. If the expected
+ * value is infinity then the delta value is ignored.
+ */
+ public static void assertEquals(float expected, float actual, float delta) {
+ Assert.assertEquals(expected, actual, delta);
+ }
+
+ /**
+ * Asserts that two longs are equal. If they are not
+ * an AssertionFailedError is thrown with the given message.
+ */
+ public static void assertEquals(String message, long expected, long actual) {
+ Assert.assertEquals(message, expected, actual);
+ }
+
+ /**
+ * Asserts that two longs are equal.
+ */
+ public static void assertEquals(long expected, long actual) {
+ Assert.assertEquals(expected, actual);
+ }
+
+ /**
+ * Asserts that two booleans are equal. If they are not
+ * an AssertionFailedError is thrown with the given message.
+ */
+ public static void assertEquals(String message, boolean expected, boolean actual) {
+ Assert.assertEquals(message, expected, actual);
+ }
+
+ /**
+ * Asserts that two booleans are equal.
+ */
+ public static void assertEquals(boolean expected, boolean actual) {
+ Assert.assertEquals(expected, actual);
+ }
+
+ /**
+ * Asserts that two bytes are equal. If they are not
+ * an AssertionFailedError is thrown with the given message.
+ */
+ public static void assertEquals(String message, byte expected, byte actual) {
+ Assert.assertEquals(message, expected, actual);
+ }
+
+ /**
+ * Asserts that two bytes are equal.
+ */
+ public static void assertEquals(byte expected, byte actual) {
+ Assert.assertEquals(expected, actual);
+ }
+
+ /**
+ * Asserts that two chars are equal. If they are not
+ * an AssertionFailedError is thrown with the given message.
+ */
+ public static void assertEquals(String message, char expected, char actual) {
+ Assert.assertEquals(message, expected, actual);
+ }
+
+ /**
+ * Asserts that two chars are equal.
+ */
+ public static void assertEquals(char expected, char actual) {
+ Assert.assertEquals(expected, actual);
+ }
+
+ /**
+ * Asserts that two shorts are equal. If they are not
+ * an AssertionFailedError is thrown with the given message.
+ */
+ public static void assertEquals(String message, short expected, short actual) {
+ Assert.assertEquals(message, expected, actual);
+ }
+
+ /**
+ * Asserts that two shorts are equal.
+ */
+ public static void assertEquals(short expected, short actual) {
+ Assert.assertEquals(expected, actual);
+ }
+
+ /**
+ * Asserts that two ints are equal. If they are not
+ * an AssertionFailedError is thrown with the given message.
+ */
+ public static void assertEquals(String message, int expected, int actual) {
+ Assert.assertEquals(message, expected, actual);
+ }
+
+ /**
+ * Asserts that two ints are equal.
+ */
+ public static void assertEquals(int expected, int actual) {
+ Assert.assertEquals(expected, actual);
+ }
+
+ /**
+ * Asserts that an object isn't null.
+ */
+ public static void assertNotNull(Object object) {
+ Assert.assertNotNull(object);
+ }
+
+ /**
+ * Asserts that an object isn't null. If it is
+ * an AssertionFailedError is thrown with the given message.
+ */
+ public static void assertNotNull(String message, Object object) {
+ Assert.assertNotNull(message, object);
+ }
+
+ /**
+ * Asserts that an object is null. If it isn't an {@link AssertionError} is
+ * thrown.
+ * Message contains: Expected: but was: object
+ *
+ * @param object Object to check or null
+ */
+ public static void assertNull(Object object) {
+ Assert.assertNull(object);
+ }
+
+ /**
+ * Asserts that an object is null. If it is not
+ * an AssertionFailedError is thrown with the given message.
+ */
+ public static void assertNull(String message, Object object) {
+ Assert.assertNull(message, object);
+ }
+
+ /**
+ * Asserts that two objects refer to the same object. If they are not
+ * an AssertionFailedError is thrown with the given message.
+ */
+ public static void assertSame(String message, Object expected, Object actual) {
+ Assert.assertSame(message, expected, actual);
+ }
+
+ /**
+ * Asserts that two objects refer to the same object. If they are not
+ * the same an AssertionFailedError is thrown.
+ */
+ public static void assertSame(Object expected, Object actual) {
+ Assert.assertSame(expected, actual);
+ }
+
+ /**
+ * Asserts that two objects do not refer to the same object. If they do
+ * refer to the same object an AssertionFailedError is thrown with the
+ * given message.
+ */
+ public static void assertNotSame(String message, Object expected, Object actual) {
+ Assert.assertNotSame(message, expected, actual);
+ }
+
+ /**
+ * Asserts that two objects do not refer to the same object. If they do
+ * refer to the same object an AssertionFailedError is thrown.
+ */
+ public static void assertNotSame(Object expected, Object actual) {
+ Assert.assertNotSame(expected, actual);
+ }
+
+ public static void failSame(String message) {
+ Assert.failSame(message);
+ }
+
+ public static void failNotSame(String message, Object expected, Object actual) {
+ Assert.failNotSame(message, expected, actual);
+ }
+
+ public static void failNotEquals(String message, Object expected, Object actual) {
+ Assert.failNotEquals(message, expected, actual);
+ }
+
+ public static String format(String message, Object expected, Object actual) {
+ return Assert.format(message, expected, actual);
+ }
+
+ /**
+ * Sets up the fixture, for example, open a network connection.
+ * This method is called before a test is executed.
+ */
+ protected void setUp() throws Exception {
+ }
+
+ /**
+ * Tears down the fixture, for example, close a network connection.
+ * This method is called after a test is executed.
+ */
+ protected void tearDown() throws Exception {
+ }
+
+ /**
+ * Returns a string representation of the test case.
+ */
+ @Override
+ public String toString() {
+ return getName() + "(" + getClass().getName() + ")";
+ }
+
+ /**
+ * Gets the name of a TestCase.
+ *
+ * @return the name of the TestCase
+ */
+ public String getName() {
+ return fName;
+ }
+
+ /**
+ * Sets the name of a TestCase.
+ *
+ * @param name the name to set
+ */
+ public void setName(String name) {
+ fName = name;
+ }
}
diff --git a/src/main/java/junit/framework/TestFailure.java b/src/main/java/junit/framework/TestFailure.java
index 6662b1fab1b2..d1ddfbc29357 100644
--- a/src/main/java/junit/framework/TestFailure.java
+++ b/src/main/java/junit/framework/TestFailure.java
@@ -1,58 +1,69 @@
package junit.framework;
-import java.io.PrintWriter;
-import java.io.StringWriter;
+import org.junit.internal.Throwables;
/**
- * A TestFailure collects a failed test together with
+ * A {@code TestFailure} collects a failed test together with
* the caught exception.
+ *
* @see TestResult
*/
-public class TestFailure extends Object {
- protected Test fFailedTest;
- protected Throwable fThrownException;
-
-
- /**
- * Constructs a TestFailure with the given test and exception.
- */
- public TestFailure(Test failedTest, Throwable thrownException) {
- fFailedTest= failedTest;
- fThrownException= thrownException;
- }
- /**
- * Gets the failed test.
- */
- public Test failedTest() {
- return fFailedTest;
- }
- /**
- * Gets the thrown exception.
- */
- public Throwable thrownException() {
- return fThrownException;
- }
- /**
- * Returns a short description of the failure.
- */
- @Override
- public String toString() {
- StringBuffer buffer= new StringBuffer();
- buffer.append(fFailedTest+": "+fThrownException.getMessage());
- return buffer.toString();
- }
- public String trace() {
- StringWriter stringWriter= new StringWriter();
- PrintWriter writer= new PrintWriter(stringWriter);
- thrownException().printStackTrace(writer);
- StringBuffer buffer= stringWriter.getBuffer();
- return buffer.toString();
- }
- public String exceptionMessage() {
- return thrownException().getMessage();
- }
- public boolean isFailure() {
- return thrownException() instanceof AssertionFailedError;
- }
+public class TestFailure {
+ protected Test fFailedTest;
+ protected Throwable fThrownException;
+
+ /**
+ * Constructs a TestFailure with the given test and exception.
+ */
+ public TestFailure(Test failedTest, Throwable thrownException) {
+ fFailedTest = failedTest;
+ fThrownException = thrownException;
+ }
+
+ /**
+ * Gets the failed test.
+ */
+ public Test failedTest() {
+ return fFailedTest;
+ }
+
+ /**
+ * Gets the thrown exception.
+ */
+ public Throwable thrownException() {
+ return fThrownException;
+ }
+
+ /**
+ * Returns a short description of the failure.
+ */
+ @Override
+ public String toString() {
+ return fFailedTest + ": " + fThrownException.getMessage();
+ }
+
+ /**
+ * Returns a String containing the stack trace of the error
+ * thrown by TestFailure.
+ */
+ public String trace() {
+ return Throwables.getStacktrace(thrownException());
+ }
+
+ /**
+ * Returns a String containing the message from the thrown exception.
+ */
+ public String exceptionMessage() {
+ return thrownException().getMessage();
+ }
+
+ /**
+ * Returns {@code true} if the error is considered a failure
+ * (i.e. if it is an instance of {@code AssertionFailedError}),
+ * {@code false} otherwise.
+ */
+ public boolean isFailure() {
+ return thrownException() instanceof AssertionFailedError;
+ }
}
\ No newline at end of file
diff --git a/src/main/java/junit/framework/TestListener.java b/src/main/java/junit/framework/TestListener.java
index 9b6944361b9d..32d1a7f23180 100644
--- a/src/main/java/junit/framework/TestListener.java
+++ b/src/main/java/junit/framework/TestListener.java
@@ -4,20 +4,23 @@
* A Listener for test progress
*/
public interface TestListener {
- /**
- * An error occurred.
- */
- public void addError(Test test, Throwable t);
- /**
- * A failure occurred.
- */
- public void addFailure(Test test, AssertionFailedError t);
- /**
- * A test ended.
- */
- public void endTest(Test test);
- /**
- * A test started.
- */
- public void startTest(Test test);
+ /**
+ * An error occurred.
+ */
+ public void addError(Test test, Throwable e);
+
+ /**
+ * A failure occurred.
+ */
+ public void addFailure(Test test, AssertionFailedError e);
+
+ /**
+ * A test ended.
+ */
+ public void endTest(Test test);
+
+ /**
+ * A test started.
+ */
+ public void startTest(Test test);
}
\ No newline at end of file
diff --git a/src/main/java/junit/framework/TestResult.java b/src/main/java/junit/framework/TestResult.java
index 5768e9a4c26f..e01a2b0a72aa 100644
--- a/src/main/java/junit/framework/TestResult.java
+++ b/src/main/java/junit/framework/TestResult.java
@@ -14,156 +14,172 @@
*
* @see Test
*/
-public class TestResult extends Object {
- protected List fFailures;
- protected List fErrors;
- protected List fListeners;
- protected int fRunTests;
- private boolean fStop;
-
- public TestResult() {
- fFailures= new ArrayList();
- fErrors= new ArrayList();
- fListeners= new ArrayList();
- fRunTests= 0;
- fStop= false;
- }
- /**
- * Adds an error to the list of errors. The passed in exception
- * caused the error.
- */
- public synchronized void addError(Test test, Throwable t) {
- fErrors.add(new TestFailure(test, t));
- for (TestListener each : cloneListeners())
- each.addError(test, t);
- }
- /**
- * Adds a failure to the list of failures. The passed in exception
- * caused the failure.
- */
- public synchronized void addFailure(Test test, AssertionFailedError t) {
- fFailures.add(new TestFailure(test, t));
- for (TestListener each : cloneListeners())
- each.addFailure(test, t);
- }
- /**
- * Registers a TestListener
- */
- public synchronized void addListener(TestListener listener) {
- fListeners.add(listener);
- }
- /**
- * Unregisters a TestListener
- */
- public synchronized void removeListener(TestListener listener) {
- fListeners.remove(listener);
- }
- /**
- * Returns a copy of the listeners.
- */
- private synchronized List cloneListeners() {
- List result= new ArrayList();
- result.addAll(fListeners);
- return result;
- }
- /**
- * Informs the result that a test was completed.
- */
- public void endTest(Test test) {
- for (TestListener each : cloneListeners())
- each.endTest(test);
- }
- /**
- * Gets the number of detected errors.
- */
- public synchronized int errorCount() {
- return fErrors.size();
- }
- /**
- * Returns an Enumeration for the errors
- */
- public synchronized Enumeration errors() {
- return Collections.enumeration(fErrors);
- }
-
-
- /**
- * Gets the number of detected failures.
- */
- public synchronized int failureCount() {
- return fFailures.size();
- }
- /**
- * Returns an Enumeration for the failures
- */
- public synchronized Enumeration failures() {
- return Collections.enumeration(fFailures);
- }
-
- /**
- * Runs a TestCase.
- */
- protected void run(final TestCase test) {
- startTest(test);
- Protectable p= new Protectable() {
- public void protect() throws Throwable {
- test.runBare();
- }
- };
- runProtected(test, p);
-
- endTest(test);
- }
- /**
- * Gets the number of run tests.
- */
- public synchronized int runCount() {
- return fRunTests;
- }
- /**
- * Runs a TestCase.
- */
- public void runProtected(final Test test, Protectable p) {
- try {
- p.protect();
- }
- catch (AssertionFailedError e) {
- addFailure(test, e);
- }
- catch (ThreadDeath e) { // don't catch ThreadDeath by accident
- throw e;
- }
- catch (Throwable e) {
- addError(test, e);
- }
- }
- /**
- * Checks whether the test run should stop
- */
- public synchronized boolean shouldStop() {
- return fStop;
- }
- /**
- * Informs the result that a test will be started.
- */
- public void startTest(Test test) {
- final int count= test.countTestCases();
- synchronized(this) {
- fRunTests+= count;
- }
- for (TestListener each : cloneListeners())
- each.startTest(test);
- }
- /**
- * Marks that the test run should stop.
- */
- public synchronized void stop() {
- fStop= true;
- }
- /**
- * Returns whether the entire test was successful or not.
- */
- public synchronized boolean wasSuccessful() {
- return failureCount() == 0 && errorCount() == 0;
- }
-}
\ No newline at end of file
+public class TestResult {
+ protected List fFailures;
+ protected List fErrors;
+ protected List fListeners;
+ protected int fRunTests;
+ private boolean fStop;
+
+ public TestResult() {
+ fFailures = new ArrayList();
+ fErrors = new ArrayList();
+ fListeners = new ArrayList();
+ fRunTests = 0;
+ fStop = false;
+ }
+
+ /**
+ * Adds an error to the list of errors. The passed in exception
+ * caused the error.
+ */
+ public synchronized void addError(Test test, Throwable e) {
+ fErrors.add(new TestFailure(test, e));
+ for (TestListener each : cloneListeners()) {
+ each.addError(test, e);
+ }
+ }
+
+ /**
+ * Adds a failure to the list of failures. The passed in exception
+ * caused the failure.
+ */
+ public synchronized void addFailure(Test test, AssertionFailedError e) {
+ fFailures.add(new TestFailure(test, e));
+ for (TestListener each : cloneListeners()) {
+ each.addFailure(test, e);
+ }
+ }
+
+ /**
+ * Registers a TestListener.
+ */
+ public synchronized void addListener(TestListener listener) {
+ fListeners.add(listener);
+ }
+
+ /**
+ * Unregisters a TestListener.
+ */
+ public synchronized void removeListener(TestListener listener) {
+ fListeners.remove(listener);
+ }
+
+ /**
+ * Returns a copy of the listeners.
+ */
+ private synchronized List cloneListeners() {
+ List result = new ArrayList();
+ result.addAll(fListeners);
+ return result;
+ }
+
+ /**
+ * Informs the result that a test was completed.
+ */
+ public void endTest(Test test) {
+ for (TestListener each : cloneListeners()) {
+ each.endTest(test);
+ }
+ }
+
+ /**
+ * Gets the number of detected errors.
+ */
+ public synchronized int errorCount() {
+ return fErrors.size();
+ }
+
+ /**
+ * Returns an Enumeration for the errors.
+ */
+ public synchronized Enumeration errors() {
+ return Collections.enumeration(fErrors);
+ }
+
+
+ /**
+ * Gets the number of detected failures.
+ */
+ public synchronized int failureCount() {
+ return fFailures.size();
+ }
+
+ /**
+ * Returns an Enumeration for the failures.
+ */
+ public synchronized Enumeration failures() {
+ return Collections.enumeration(fFailures);
+ }
+
+ /**
+ * Runs a TestCase.
+ */
+ protected void run(final TestCase test) {
+ startTest(test);
+ Protectable p = new Protectable() {
+ public void protect() throws Throwable {
+ test.runBare();
+ }
+ };
+ runProtected(test, p);
+
+ endTest(test);
+ }
+
+ /**
+ * Gets the number of run tests.
+ */
+ public synchronized int runCount() {
+ return fRunTests;
+ }
+
+ /**
+ * Runs a TestCase.
+ */
+ public void runProtected(final Test test, Protectable p) {
+ try {
+ p.protect();
+ } catch (AssertionFailedError e) {
+ addFailure(test, e);
+ } catch (ThreadDeath e) { // don't catch ThreadDeath by accident
+ throw e;
+ } catch (Throwable e) {
+ addError(test, e);
+ }
+ }
+
+ /**
+ * Checks whether the test run should stop.
+ */
+ public synchronized boolean shouldStop() {
+ return fStop;
+ }
+
+ /**
+ * Informs the result that a test will be started.
+ */
+ public void startTest(Test test) {
+ final int count = test.countTestCases();
+ synchronized (this) {
+ fRunTests += count;
+ }
+ for (TestListener each : cloneListeners()) {
+ each.startTest(test);
+ }
+ }
+
+ /**
+ * Marks that the test run should stop.
+ */
+ public synchronized void stop() {
+ fStop = true;
+ }
+
+ /**
+ * Returns whether the entire test was successful or not.
+ */
+ public synchronized boolean wasSuccessful() {
+ return failureCount() == 0 && errorCount() == 0;
+ }
+}
diff --git a/src/main/java/junit/framework/TestSuite.java b/src/main/java/junit/framework/TestSuite.java
index 3e95e2fd818b..50cd5f8d120b 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;
@@ -11,8 +9,11 @@
import java.util.List;
import java.util.Vector;
+import org.junit.internal.MethodSorter;
+import org.junit.internal.Throwables;
+
/**
- *
A TestSuite is a Composite of Tests.
+ * A TestSuite is a Composite of Tests.
* It runs a collection of test cases. Here is an example using
* the dynamic test definition.
*
Alternatively, a TestSuite can extract the tests to be run automatically.
+ *
+ * Alternatively, a TestSuite can extract the tests to be run automatically.
* To do so you pass the class of your TestCase class to the
* TestSuite constructor.
*
* TestSuite suite= new TestSuite(MathTest.class);
*
- *
- *
- *
This constructor creates a suite with all the methods
- * starting with "test" that take no arguments.
- *
- *
A final option is to do the same for a large array of test classes.
+ *
+ * This constructor creates a suite with all the methods
+ * starting with "test" that take no arguments.
+ *
+ * A final option is to do the same for a large array of test classes.
*
TestRunner expects the name of a TestCase class as argument.
- * If this class defines a static suite method it
- * will be invoked and the returned test is run. Otherwise all
- * the methods starting with "test" having no arguments are run.
- *
- *
When the wait command line argument is given TestRunner
- * waits until the users types RETURN.
- *
- *
TestRunner prints a trace as the tests are executed followed by a
- * summary at the end.
+ *
+ * TestRunner expects the name of a TestCase class as argument.
+ * If this class defines a static suite method it
+ * will be invoked and the returned test is run. Otherwise all
+ * the methods starting with "test" having no arguments are run.
+ *
+ * When the wait command line argument is given TestRunner
+ * waits until the users types RETURN.
+ *
+ * TestRunner prints a trace as the tests are executed followed by a
+ * summary at the end.
*/
public class TestRunner extends BaseTestRunner {
- private ResultPrinter fPrinter;
-
- public static final int SUCCESS_EXIT= 0;
- public static final int FAILURE_EXIT= 1;
- public static final int EXCEPTION_EXIT= 2;
-
- /**
- * Constructs a TestRunner.
- */
- public TestRunner() {
- this(System.out);
- }
-
- /**
- * Constructs a TestRunner using the given stream for all the output
- */
- public TestRunner(PrintStream writer) {
- this(new ResultPrinter(writer));
- }
-
- /**
- * Constructs a TestRunner using the given ResultPrinter all the output
- */
- public TestRunner(ResultPrinter printer) {
- fPrinter= printer;
- }
-
- /**
- * Runs a suite extracted from a TestCase subclass.
- */
- static public void run(Class extends TestCase> testClass) {
- run(new TestSuite(testClass));
- }
-
- /**
- * Runs a single test and collects its results.
- * This method can be used to start a test run
- * from your program.
- *
- * public static void main (String[] args) {
- * test.textui.TestRunner.run(suite());
- * }
- *
- */
- static public TestResult run(Test test) {
- TestRunner runner= new TestRunner();
- return runner.doRun(test);
- }
-
- /**
- * Runs a single test and waits until the user
- * types RETURN.
- */
- static public void runAndWait(Test suite) {
- TestRunner aTestRunner= new TestRunner();
- aTestRunner.doRun(suite, true);
- }
-
- @Override
- public void testFailed(int status, Test test, Throwable t) {
- }
-
- @Override
- public void testStarted(String testName) {
- }
-
- @Override
- public void testEnded(String testName) {
- }
-
- /**
- * Creates the TestResult to be used for the test run.
- */
- protected TestResult createTestResult() {
- return new TestResult();
- }
-
- public TestResult doRun(Test test) {
- return doRun(test, false);
- }
-
- public TestResult doRun(Test suite, boolean wait) {
- TestResult result= createTestResult();
- result.addListener(fPrinter);
- long startTime= System.currentTimeMillis();
- suite.run(result);
- long endTime= System.currentTimeMillis();
- long runTime= endTime-startTime;
- fPrinter.print(result, runTime);
-
- pause(wait);
- return result;
- }
-
- protected void pause(boolean wait) {
- if (!wait) return;
- fPrinter.printWaitPrompt();
- try {
- System.in.read();
- }
- catch(Exception e) {
- }
- }
-
- public static void main(String args[]) {
- TestRunner aTestRunner= new TestRunner();
- try {
- TestResult r= aTestRunner.start(args);
- if (!r.wasSuccessful())
- System.exit(FAILURE_EXIT);
- System.exit(SUCCESS_EXIT);
- } catch(Exception e) {
- System.err.println(e.getMessage());
- System.exit(EXCEPTION_EXIT);
- }
- }
-
- /**
- * Starts a test run. Analyzes the command line arguments and runs the given
- * test suite.
- */
- public TestResult start(String args[]) throws Exception {
- String testCase= "";
- String method= "";
- boolean wait= false;
-
- for (int i= 0; i < args.length; i++) {
- if (args[i].equals("-wait"))
- wait= true;
- else if (args[i].equals("-c"))
- testCase= extractClassName(args[++i]);
- else if (args[i].equals("-m")) {
- String arg= args[++i];
- int lastIndex= arg.lastIndexOf('.');
- testCase= arg.substring(0, lastIndex);
- method= arg.substring(lastIndex + 1);
- } else if (args[i].equals("-v"))
- System.err.println("JUnit " + Version.id() + " by Kent Beck and Erich Gamma");
- else
- testCase= args[i];
- }
-
- if (testCase.equals(""))
- throw new Exception("Usage: TestRunner [-wait] testCaseName, where name is the name of the TestCase class");
-
- try {
- if (!method.equals(""))
- return runSingleMethod(testCase, method, wait);
- Test suite= getTest(testCase);
- return doRun(suite, wait);
- } catch (Exception e) {
- throw new Exception("Could not create and run test suite: " + e);
- }
- }
-
- protected TestResult runSingleMethod(String testCase, String method, boolean wait) throws Exception {
- Class extends TestCase> testClass= loadSuiteClass(testCase).asSubclass(TestCase.class);
- Test test= TestSuite.createTest(testClass, method);
- return doRun(test, wait);
- }
-
- @Override
- protected void runFailed(String message) {
- System.err.println(message);
- System.exit(FAILURE_EXIT);
- }
-
- public void setPrinter(ResultPrinter printer) {
- fPrinter= printer;
- }
-
-
+ private ResultPrinter fPrinter;
+
+ public static final int SUCCESS_EXIT = 0;
+ public static final int FAILURE_EXIT = 1;
+ public static final int EXCEPTION_EXIT = 2;
+
+ /**
+ * Constructs a TestRunner.
+ */
+ public TestRunner() {
+ this(System.out);
+ }
+
+ /**
+ * Constructs a TestRunner using the given stream for all the output
+ */
+ public TestRunner(PrintStream writer) {
+ this(new ResultPrinter(writer));
+ }
+
+ /**
+ * Constructs a TestRunner using the given ResultPrinter all the output
+ */
+ public TestRunner(ResultPrinter printer) {
+ fPrinter = printer;
+ }
+
+ /**
+ * Runs a suite extracted from a TestCase subclass.
+ */
+ static public void run(Class extends TestCase> testClass) {
+ run(new TestSuite(testClass));
+ }
+
+ /**
+ * Runs a single test and collects its results.
+ * This method can be used to start a test run
+ * from your program.
+ *
+ * public static void main (String[] args) {
+ * test.textui.TestRunner.run(suite());
+ * }
+ *
+ */
+ static public TestResult run(Test test) {
+ TestRunner runner = new TestRunner();
+ return runner.doRun(test);
+ }
+
+ /**
+ * Runs a single test and waits until the user
+ * types RETURN.
+ */
+ static public void runAndWait(Test suite) {
+ TestRunner aTestRunner = new TestRunner();
+ aTestRunner.doRun(suite, true);
+ }
+
+ @Override
+ public void testFailed(int status, Test test, Throwable e) {
+ }
+
+ @Override
+ public void testStarted(String testName) {
+ }
+
+ @Override
+ public void testEnded(String testName) {
+ }
+
+ /**
+ * Creates the TestResult to be used for the test run.
+ */
+ protected TestResult createTestResult() {
+ return new TestResult();
+ }
+
+ public TestResult doRun(Test test) {
+ return doRun(test, false);
+ }
+
+ public TestResult doRun(Test suite, boolean wait) {
+ TestResult result = createTestResult();
+ result.addListener(fPrinter);
+ long startTime = System.currentTimeMillis();
+ suite.run(result);
+ long endTime = System.currentTimeMillis();
+ long runTime = endTime - startTime;
+ fPrinter.print(result, runTime);
+
+ pause(wait);
+ return result;
+ }
+
+ protected void pause(boolean wait) {
+ if (!wait) return;
+ fPrinter.printWaitPrompt();
+ try {
+ System.in.read();
+ } catch (Exception e) {
+ }
+ }
+
+ public static void main(String[] args) {
+ TestRunner aTestRunner = new TestRunner();
+ try {
+ TestResult r = aTestRunner.start(args);
+ if (!r.wasSuccessful()) {
+ System.exit(FAILURE_EXIT);
+ }
+ System.exit(SUCCESS_EXIT);
+ } catch (Exception e) {
+ System.err.println(e.getMessage());
+ System.exit(EXCEPTION_EXIT);
+ }
+ }
+
+ /**
+ * Starts a test run. Analyzes the command line arguments and runs the given
+ * test suite.
+ */
+ public TestResult start(String[] args) throws Exception {
+ String testCase = "";
+ String method = "";
+ boolean wait = false;
+
+ for (int i = 0; i < args.length; i++) {
+ if (args[i].equals("-wait")) {
+ wait = true;
+ } else if (args[i].equals("-c")) {
+ testCase = extractClassName(args[++i]);
+ } else if (args[i].equals("-m")) {
+ String arg = args[++i];
+ int lastIndex = arg.lastIndexOf('.');
+ testCase = arg.substring(0, lastIndex);
+ method = arg.substring(lastIndex + 1);
+ } else if (args[i].equals("-v")) {
+ System.err.println("JUnit " + Version.id() + " by Kent Beck and Erich Gamma");
+ } else {
+ testCase = args[i];
+ }
+ }
+
+ if (testCase.equals("")) {
+ throw new Exception("Usage: TestRunner [-wait] testCaseName, where name is the name of the TestCase class");
+ }
+
+ try {
+ if (!method.equals("")) {
+ return runSingleMethod(testCase, method, wait);
+ }
+ Test suite = getTest(testCase);
+ return doRun(suite, wait);
+ } catch (Exception e) {
+ throw new Exception("Could not create and run test suite: " + e);
+ }
+ }
+
+ protected TestResult runSingleMethod(String testCase, String method, boolean wait) throws Exception {
+ Class extends TestCase> testClass = loadSuiteClass(testCase).asSubclass(TestCase.class);
+ Test test = TestSuite.createTest(testClass, method);
+ return doRun(test, wait);
+ }
+
+ @Override
+ protected void runFailed(String message) {
+ System.err.println(message);
+ System.exit(FAILURE_EXIT);
+ }
+
+ public void setPrinter(ResultPrinter printer) {
+ fPrinter = printer;
+ }
+
+
}
\ No newline at end of file
diff --git a/src/main/java/org/junit/After.java b/src/main/java/org/junit/After.java
index 39aa6e56d14a..eae7e3abf4c6 100644
--- a/src/main/java/org/junit/After.java
+++ b/src/main/java/org/junit/After.java
@@ -6,15 +6,15 @@
import java.lang.annotation.Target;
/**
- *
If you allocate external resources in a {@link org.junit.Before} method you need to release them
+ * If you allocate external resources in a {@link org.junit.Before} method you need to release them
* after the test runs. Annotating a public void method
* with @After causes that method to be run after the {@link org.junit.Test} method. All @After
- * methods are guaranteed to run even if a {@link org.junit.Before} or {@link org.junit.Test} method throws an
+ * methods are guaranteed to run even if a {@link org.junit.Before} or {@link org.junit.Test} method throws an
* exception. The @After methods declared in superclasses will be run after those of the current
- * class.
- *
+ * class, unless they are overridden in the current class.
+ *
* Here is a simple example:
-*
+ *
* public class Example {
* File output;
* @Before public void createOutputFile() {
@@ -28,9 +28,10 @@
* }
* }
*
If you allocate expensive external resources in a {@link org.junit.BeforeClass} method you need to release them
+ * If you allocate expensive external resources in a {@link org.junit.BeforeClass} method you need to release them
* after all the tests in the class have run. Annotating a public static void method
* with @AfterClass causes that method to be run after all the tests in the class have been run. All @AfterClass
- * methods are guaranteed to run even if a {@link org.junit.BeforeClass} method throws an
+ * methods are guaranteed to run even if a {@link org.junit.BeforeClass} method throws an
* exception. The @AfterClass methods declared in superclasses will be run after those of the current
- * class.
- *
+ * class, unless they are shadowed in the current class.
+ *
* Here is a simple example:
-*
+ *
* public class Example {
* private static DatabaseConnection database;
* @BeforeClass public static void login() {
@@ -31,9 +31,10 @@
* }
* }
*
- *
+ *
* @see org.junit.BeforeClass
* @see org.junit.Test
+ * @since 4.0
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
diff --git a/src/main/java/org/junit/Assert.java b/src/main/java/org/junit/Assert.java
index e1c9a7d4b600..65bbc9d3f7ff 100644
--- a/src/main/java/org/junit/Assert.java
+++ b/src/main/java/org/junit/Assert.java
@@ -1,8 +1,8 @@
package org.junit;
-import org.hamcrest.Description;
import org.hamcrest.Matcher;
-import org.hamcrest.StringDescription;
+import org.hamcrest.MatcherAssert;
+import org.junit.function.ThrowingRunnable;
import org.junit.internal.ArrayComparisonFailure;
import org.junit.internal.ExactComparisonCriteria;
import org.junit.internal.InexactComparisonCriteria;
@@ -11,771 +11,1024 @@
* A set of assertion methods useful for writing tests. Only failed assertions
* are recorded. These methods can be used directly:
* Assert.assertEquals(...), however, they read better if they
- * are referenced through static import:
- *
+ * are referenced through static import:
+ *
*
- *
+ *
* @see AssertionError
+ * @since 4.0
*/
public class Assert {
- /**
- * Protect constructor since it is a static only class
- */
- protected Assert() {
- }
-
- /**
- * Asserts that a condition is true. If it isn't it throws an
- * {@link AssertionError} with the given message.
- *
- * @param message
- * the identifying message for the {@link AssertionError} (null
- * okay)
- * @param condition
- * condition to be checked
- */
- static public void assertTrue(String message, boolean condition) {
- if (!condition)
- fail(message);
- }
-
- /**
- * Asserts that a condition is true. If it isn't it throws an
- * {@link AssertionError} without a message.
- *
- * @param condition
- * condition to be checked
- */
- static public void assertTrue(boolean condition) {
- assertTrue(null, condition);
- }
-
- /**
- * Asserts that a condition is false. If it isn't it throws an
- * {@link AssertionError} with the given message.
- *
- * @param message
- * the identifying message for the {@link AssertionError} (null
- * okay)
- * @param condition
- * condition to be checked
- */
- static public void assertFalse(String message, boolean condition) {
- assertTrue(message, !condition);
- }
-
- /**
- * Asserts that a condition is false. If it isn't it throws an
- * {@link AssertionError} without a message.
- *
- * @param condition
- * condition to be checked
- */
- static public void assertFalse(boolean condition) {
- assertFalse(null, condition);
- }
-
- /**
- * Fails a test with the given message.
- *
- * @param message
- * the identifying message for the {@link AssertionError} (null
- * okay)
- * @see AssertionError
- */
- static public void fail(String message) {
- throw new AssertionError(message == null ? "" : message);
- }
-
- /**
- * Fails a test with no message.
- */
- static public void fail() {
- fail(null);
- }
-
- /**
- * Asserts that two objects are equal. If they are not, an
- * {@link AssertionError} is thrown with the given message. If
- * expected and actual are null,
- * they are considered equal.
- *
- * @param message
- * the identifying message for the {@link AssertionError} (null
- * okay)
- * @param expected
- * expected value
- * @param actual
- * actual value
- */
- static public void assertEquals(String message, Object expected,
- Object actual) {
- if (expected == null && actual == null)
- return;
- if (expected != null && isEquals(expected, actual))
- return;
- else if (expected instanceof String && actual instanceof String) {
- String cleanMessage= message == null ? "" : message;
- throw new ComparisonFailure(cleanMessage, (String) expected,
- (String) actual);
- } else
- failNotEquals(message, expected, actual);
- }
-
- private static boolean isEquals(Object expected, Object actual) {
- return expected.equals(actual);
- }
-
- /**
- * Asserts that two objects are equal. If they are not, an
- * {@link AssertionError} without a message is thrown. If
- * expected and actual are null,
- * they are considered equal.
- *
- * @param expected
- * expected value
- * @param actual
- * the value to check against expected
- */
- static public void assertEquals(Object expected, Object actual) {
- assertEquals(null, expected, actual);
- }
-
- /**
- * Asserts that two object arrays are equal. If they are not, an
- * {@link AssertionError} is thrown with the given message. If
- * expecteds and actuals are null,
- * they are considered equal.
- *
- * @param message
- * the identifying message for the {@link AssertionError} (null
- * okay)
- * @param expecteds
- * Object array or array of arrays (multi-dimensional array) with
- * expected values.
- * @param actuals
- * Object array or array of arrays (multi-dimensional array) with
- * actual values
- */
- public static void assertArrayEquals(String message, Object[] expecteds,
- Object[] actuals) throws ArrayComparisonFailure {
- internalArrayEquals(message, expecteds, actuals);
- }
-
- /**
- * Asserts that two object arrays are equal. If they are not, an
- * {@link AssertionError} is thrown. If expected and
- * actual are null, they are considered
- * equal.
- *
- * @param expecteds
- * Object array or array of arrays (multi-dimensional array) with
- * expected values
- * @param actuals
- * Object array or array of arrays (multi-dimensional array) with
- * actual values
- */
- public static void assertArrayEquals(Object[] expecteds, Object[] actuals) {
- assertArrayEquals(null, expecteds, actuals);
- }
-
- /**
- * Asserts that two byte arrays are equal. If they are not, an
- * {@link AssertionError} is thrown with the given message.
- *
- * @param message
- * the identifying message for the {@link AssertionError} (null
- * okay)
- * @param expecteds
- * byte array with expected values.
- * @param actuals
- * byte array with actual values
- */
- public static void assertArrayEquals(String message, byte[] expecteds,
- byte[] actuals) throws ArrayComparisonFailure {
- internalArrayEquals(message, expecteds, actuals);
- }
-
- /**
- * Asserts that two byte arrays are equal. If they are not, an
- * {@link AssertionError} is thrown.
- *
- * @param expecteds
- * byte array with expected values.
- * @param actuals
- * byte array with actual values
- */
- public static void assertArrayEquals(byte[] expecteds, byte[] actuals) {
- assertArrayEquals(null, expecteds, actuals);
- }
-
- /**
- * Asserts that two char arrays are equal. If they are not, an
- * {@link AssertionError} is thrown with the given message.
- *
- * @param message
- * the identifying message for the {@link AssertionError} (null
- * okay)
- * @param expecteds
- * char array with expected values.
- * @param actuals
- * char array with actual values
- */
- public static void assertArrayEquals(String message, char[] expecteds,
- char[] actuals) throws ArrayComparisonFailure {
- internalArrayEquals(message, expecteds, actuals);
- }
-
- /**
- * Asserts that two char arrays are equal. If they are not, an
- * {@link AssertionError} is thrown.
- *
- * @param expecteds
- * char array with expected values.
- * @param actuals
- * char array with actual values
- */
- public static void assertArrayEquals(char[] expecteds, char[] actuals) {
- assertArrayEquals(null, expecteds, actuals);
- }
-
- /**
- * Asserts that two short arrays are equal. If they are not, an
- * {@link AssertionError} is thrown with the given message.
- *
- * @param message
- * the identifying message for the {@link AssertionError} (null
- * okay)
- * @param expecteds
- * short array with expected values.
- * @param actuals
- * short array with actual values
- */
- public static void assertArrayEquals(String message, short[] expecteds,
- short[] actuals) throws ArrayComparisonFailure {
- internalArrayEquals(message, expecteds, actuals);
- }
-
- /**
- * Asserts that two short arrays are equal. If they are not, an
- * {@link AssertionError} is thrown.
- *
- * @param expecteds
- * short array with expected values.
- * @param actuals
- * short array with actual values
- */
- public static void assertArrayEquals(short[] expecteds, short[] actuals) {
- assertArrayEquals(null, expecteds, actuals);
- }
-
- /**
- * Asserts that two int arrays are equal. If they are not, an
- * {@link AssertionError} is thrown with the given message.
- *
- * @param message
- * the identifying message for the {@link AssertionError} (null
- * okay)
- * @param expecteds
- * int array with expected values.
- * @param actuals
- * int array with actual values
- */
- public static void assertArrayEquals(String message, int[] expecteds,
- int[] actuals) throws ArrayComparisonFailure {
- internalArrayEquals(message, expecteds, actuals);
- }
-
- /**
- * Asserts that two int arrays are equal. If they are not, an
- * {@link AssertionError} is thrown.
- *
- * @param expecteds
- * int array with expected values.
- * @param actuals
- * int array with actual values
- */
- public static void assertArrayEquals(int[] expecteds, int[] actuals) {
- assertArrayEquals(null, expecteds, actuals);
- }
-
- /**
- * Asserts that two long arrays are equal. If they are not, an
- * {@link AssertionError} is thrown with the given message.
- *
- * @param message
- * the identifying message for the {@link AssertionError} (null
- * okay)
- * @param expecteds
- * long array with expected values.
- * @param actuals
- * long array with actual values
- */
- public static void assertArrayEquals(String message, long[] expecteds,
- long[] actuals) throws ArrayComparisonFailure {
- internalArrayEquals(message, expecteds, actuals);
- }
-
- /**
- * Asserts that two long arrays are equal. If they are not, an
- * {@link AssertionError} is thrown.
- *
- * @param expecteds
- * long array with expected values.
- * @param actuals
- * long array with actual values
- */
- public static void assertArrayEquals(long[] expecteds, long[] actuals) {
- assertArrayEquals(null, expecteds, actuals);
- }
-
- /**
- * Asserts that two double arrays are equal. If they are not, an
- * {@link AssertionError} is thrown with the given message.
- *
- * @param message
- * the identifying message for the {@link AssertionError} (null
- * okay)
- * @param expecteds
- * double array with expected values.
- * @param actuals
- * double array with actual values
- */
- public static void assertArrayEquals(String message, double[] expecteds,
- double[] actuals, double delta) throws ArrayComparisonFailure {
- new InexactComparisonCriteria(delta).arrayEquals(message, expecteds, actuals);
- }
-
- /**
- * Asserts that two double arrays are equal. If they are not, an
- * {@link AssertionError} is thrown.
- *
- * @param expecteds
- * double array with expected values.
- * @param actuals
- * double array with actual values
- */
- public static void assertArrayEquals(double[] expecteds, double[] actuals, double delta) {
- assertArrayEquals(null, expecteds, actuals, delta);
- }
-
- /**
- * Asserts that two float arrays are equal. If they are not, an
- * {@link AssertionError} is thrown with the given message.
- *
- * @param message
- * the identifying message for the {@link AssertionError} (null
- * okay)
- * @param expecteds
- * float array with expected values.
- * @param actuals
- * float array with actual values
- */
- public static void assertArrayEquals(String message, float[] expecteds,
- float[] actuals, float delta) throws ArrayComparisonFailure {
- new InexactComparisonCriteria(delta).arrayEquals(message, expecteds, actuals);
- }
-
- /**
- * Asserts that two float arrays are equal. If they are not, an
- * {@link AssertionError} is thrown.
- *
- * @param expecteds
- * float array with expected values.
- * @param actuals
- * float array with actual values
- */
- public static void assertArrayEquals(float[] expecteds, float[] actuals, float delta) {
- assertArrayEquals(null, expecteds, actuals, delta);
- }
-
- /**
- * Asserts that two object arrays are equal. If they are not, an
- * {@link AssertionError} is thrown with the given message. If
- * expecteds and actuals are null,
- * they are considered equal.
- *
- * @param message
- * the identifying message for the {@link AssertionError} (null
- * okay)
- * @param expecteds
- * Object array or array of arrays (multi-dimensional array) with
- * expected values.
- * @param actuals
- * Object array or array of arrays (multi-dimensional array) with
- * actual values
- */
- private static void internalArrayEquals(String message, Object expecteds,
- Object actuals) throws ArrayComparisonFailure {
- new ExactComparisonCriteria().arrayEquals(message, expecteds, actuals);
- }
-
- /**
- * Asserts that two doubles or floats are equal to within a positive delta.
- * If they are not, an {@link AssertionError} is thrown with the given
- * message. If the expected value is infinity then the delta value is
- * ignored. NaNs are considered equal:
- * assertEquals(Double.NaN, Double.NaN, *) passes
- *
- * @param message
- * the identifying message for the {@link AssertionError} (null
- * okay)
- * @param expected
- * expected value
- * @param actual
- * the value to check against expected
- * @param delta
- * the maximum delta between expected and
- * actual for which both numbers are still
- * considered equal.
- */
- static public 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));
- }
-
- /**
- * Asserts that two longs are equal. If they are not, an
- * {@link AssertionError} is thrown.
- *
- * @param expected
- * expected long value.
- * @param actual
- * actual long value
- */
- static public void assertEquals(long expected, long actual) {
- assertEquals(null, expected, actual);
- }
-
- /**
- * Asserts that two longs are equal. If they are not, an
- * {@link AssertionError} is thrown with the given message.
- *
- * @param message
- * the identifying message for the {@link AssertionError} (null
- * okay)
- * @param expected
- * long expected value.
- * @param actual
- * long actual value
- */
- static public void assertEquals(String message, long expected, long actual) {
- assertEquals(message, (Long) expected, (Long) actual);
- }
-
- /**
- * @deprecated Use
- * assertEquals(double expected, double actual, double epsilon)
- * instead
- */
- @Deprecated
- static public void assertEquals(double expected, double actual) {
- assertEquals(null, expected, actual);
- }
-
- /**
- * @deprecated Use
- * assertEquals(String message, double expected, double actual, double epsilon)
- * instead
- */
- @Deprecated
- static public void assertEquals(String message, double expected,
- double actual) {
- fail("Use assertEquals(expected, actual, delta) to compare floating-point numbers");
- }
-
- /**
- * Asserts that two doubles or floats are equal to within a positive delta.
- * If they are not, an {@link AssertionError} is thrown. If the expected
- * value is infinity then the delta value is ignored.NaNs are considered
- * equal: assertEquals(Double.NaN, Double.NaN, *) passes
- *
- * @param expected
- * expected value
- * @param actual
- * the value to check against expected
- * @param delta
- * the maximum delta between expected and
- * actual for which both numbers are still
- * considered equal.
- */
- static public void assertEquals(double expected, double actual, double delta) {
- assertEquals(null, expected, actual, delta);
- }
-
- /**
- * Asserts that an object isn't null. If it is an {@link AssertionError} is
- * thrown with the given message.
- *
- * @param message
- * the identifying message for the {@link AssertionError} (null
- * okay)
- * @param object
- * Object to check or null
- */
- static public void assertNotNull(String message, Object object) {
- assertTrue(message, object != null);
- }
-
- /**
- * Asserts that an object isn't null. If it is an {@link AssertionError} is
- * thrown.
- *
- * @param object
- * Object to check or null
- */
- static public void assertNotNull(Object object) {
- assertNotNull(null, object);
- }
-
- /**
- * Asserts that an object is null. If it is not, an {@link AssertionError}
- * is thrown with the given message.
- *
- * @param message
- * the identifying message for the {@link AssertionError} (null
- * okay)
- * @param object
- * Object to check or null
- */
- static public void assertNull(String message, Object object) {
- assertTrue(message, object == null);
- }
-
- /**
- * Asserts that an object is null. If it isn't an {@link AssertionError} is
- * thrown.
- *
- * @param object
- * Object to check or null
- */
- static public void assertNull(Object object) {
- assertNull(null, object);
- }
-
- /**
- * Asserts that two objects refer to the same object. If they are not, an
- * {@link AssertionError} is thrown with the given message.
- *
- * @param message
- * the identifying message for the {@link AssertionError} (null
- * okay)
- * @param expected
- * the expected object
- * @param actual
- * the object to compare to expected
- */
- static public void assertSame(String message, Object expected, Object actual) {
- if (expected == actual)
- return;
- failNotSame(message, expected, actual);
- }
-
- /**
- * Asserts that two objects refer to the same object. If they are not the
- * same, an {@link AssertionError} without a message is thrown.
- *
- * @param expected
- * the expected object
- * @param actual
- * the object to compare to expected
- */
- static public void assertSame(Object expected, Object actual) {
- assertSame(null, expected, actual);
- }
-
- /**
- * Asserts that two objects do not refer to the same object. If they do
- * refer to the same object, an {@link AssertionError} is thrown with the
- * given message.
- *
- * @param message
- * the identifying message for the {@link AssertionError} (null
- * okay)
- * @param unexpected
- * the object you don't expect
- * @param actual
- * the object to compare to unexpected
- */
- static public void assertNotSame(String message, Object unexpected,
- Object actual) {
- if (unexpected == actual)
- failSame(message);
- }
-
- /**
- * Asserts that two objects do not refer to the same object. If they do
- * refer to the same object, an {@link AssertionError} without a message is
- * thrown.
- *
- * @param unexpected
- * the object you don't expect
- * @param actual
- * the object to compare to unexpected
- */
- static public void assertNotSame(Object unexpected, Object actual) {
- assertNotSame(null, unexpected, actual);
- }
-
- static private void failSame(String message) {
- String formatted= "";
- if (message != null)
- formatted= message + " ";
- fail(formatted + "expected not same");
- }
-
- static private void failNotSame(String message, Object expected,
- Object actual) {
- String formatted= "";
- if (message != null)
- formatted= message + " ";
- fail(formatted + "expected same:<" + expected + "> was not:<" + actual
- + ">");
- }
-
- static private 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(""))
- formatted= message + " ";
- String expectedString= String.valueOf(expected);
- String actualString= String.valueOf(actual);
- if (expectedString.equals(actualString))
- return formatted + "expected: "
- + formatClassAndValue(expected, expectedString)
- + " but was: " + formatClassAndValue(actual, actualString);
- else
- return formatted + "expected:<" + expectedString + "> but was:<"
- + actualString + ">";
- }
-
- private static String formatClassAndValue(Object value, String valueString) {
- String className= value == null ? "null" : value.getClass().getName();
- return className + "<" + valueString + ">";
- }
-
- /**
- * Asserts that two object arrays are equal. If they are not, an
- * {@link AssertionError} is thrown with the given message. If
- * expecteds and actuals are null,
- * they are considered equal.
- *
- * @param message
- * the identifying message for the {@link AssertionError} (null
- * okay)
- * @param expecteds
- * Object array or array of arrays (multi-dimensional array) with
- * expected values.
- * @param actuals
- * Object array or array of arrays (multi-dimensional array) with
- * actual values
- * @deprecated use assertArrayEquals
- */
- @Deprecated
- public static void assertEquals(String message, Object[] expecteds,
- Object[] actuals) {
- assertArrayEquals(message, expecteds, actuals);
- }
-
- /**
- * Asserts that two object arrays are equal. If they are not, an
- * {@link AssertionError} is thrown. If expected and
- * actual are null, they are considered
- * equal.
- *
- * @param expecteds
- * Object array or array of arrays (multi-dimensional array) with
- * expected values
- * @param actuals
- * Object array or array of arrays (multi-dimensional array) with
- * actual values
- * @deprecated use assertArrayEquals
- */
- @Deprecated
- public static void assertEquals(Object[] expecteds, Object[] actuals) {
- assertArrayEquals(expecteds, actuals);
- }
-
- /**
- * Asserts that actual satisfies the condition specified by
- * matcher. If not, an {@link AssertionError} is thrown with
- * information about the matcher and failing value. Example:
- *
- *
- *
- * @param
- * the static type accepted by the matcher (this can flag obvious
- * compile-time problems such as {@code assertThat(1, is("a"))}
- * @param actual
- * the computed value being compared
- * @param matcher
- * an expression, built of {@link Matcher}s, specifying allowed
- * values
- *
- * @see org.hamcrest.CoreMatchers
- * @see org.junit.matchers.JUnitMatchers
- */
- public static void assertThat(T actual, Matcher matcher) {
- assertThat("", actual, matcher);
- }
-
- /**
- * Asserts that actual satisfies the condition specified by
- * matcher. If not, an {@link AssertionError} is thrown with
- * the reason and information about the matcher and failing value. Example:
- *
- *
- *
- * @param reason
- * additional information about the error
- * @param
- * the static type accepted by the matcher (this can flag obvious
- * compile-time problems such as {@code assertThat(1, is("a"))}
- * @param actual
- * the computed value being compared
- * @param matcher
- * an expression, built of {@link Matcher}s, specifying allowed
- * values
- *
- * @see org.hamcrest.CoreMatchers
- * @see org.junit.matchers.JUnitMatchers
- */
- public static void assertThat(String reason, T actual,
- Matcher matcher) {
- if (!matcher.matches(actual)) {
- Description description= new StringDescription();
- description.appendText(reason);
- description.appendText("\nExpected: ");
- description.appendDescriptionOf(matcher);
- description.appendText("\n got: ");
- description.appendValue(actual);
- description.appendText("\n");
- throw new java.lang.AssertionError(description.toString());
- }
- }
+ /**
+ * Protect constructor since it is a static only class
+ */
+ protected Assert() {
+ }
+
+ /**
+ * Asserts that a condition is true. If it isn't it throws an
+ * {@link AssertionError} with the given message.
+ *
+ * @param message the identifying message for the {@link AssertionError} (null
+ * okay)
+ * @param condition condition to be checked
+ */
+ public static void assertTrue(String message, boolean condition) {
+ if (!condition) {
+ fail(message);
+ }
+ }
+
+ /**
+ * Asserts that a condition is true. If it isn't it throws an
+ * {@link AssertionError} without a message.
+ *
+ * @param condition condition to be checked
+ */
+ public static void assertTrue(boolean condition) {
+ assertTrue(null, condition);
+ }
+
+ /**
+ * Asserts that a condition is false. If it isn't it throws an
+ * {@link AssertionError} with the given message.
+ *
+ * @param message the identifying message for the {@link AssertionError} (null
+ * okay)
+ * @param condition condition to be checked
+ */
+ public static void assertFalse(String message, boolean condition) {
+ assertTrue(message, !condition);
+ }
+
+ /**
+ * Asserts that a condition is false. If it isn't it throws an
+ * {@link AssertionError} without a message.
+ *
+ * @param condition condition to be checked
+ */
+ public static void assertFalse(boolean condition) {
+ assertFalse(null, condition);
+ }
+
+ /**
+ * Fails a test with the given message.
+ *
+ * @param message the identifying message for the {@link AssertionError} (null
+ * okay)
+ * @see AssertionError
+ */
+ public static void fail(String message) {
+ if (message == null) {
+ throw new AssertionError();
+ }
+ throw new AssertionError(message);
+ }
+
+ /**
+ * Fails a test with no message.
+ */
+ public static void fail() {
+ fail(null);
+ }
+
+ /**
+ * Asserts that two objects are equal. If they are not, an
+ * {@link AssertionError} is thrown with the given message. If
+ * expected and actual are null,
+ * they are considered equal.
+ *
+ * @param message the identifying message for the {@link AssertionError} (null
+ * okay)
+ * @param expected expected value
+ * @param actual actual value
+ */
+ public static void assertEquals(String message, Object expected,
+ Object actual) {
+ if (equalsRegardingNull(expected, actual)) {
+ return;
+ }
+ if (expected instanceof String && actual instanceof String) {
+ String cleanMessage = message == null ? "" : message;
+ throw new ComparisonFailure(cleanMessage, (String) expected,
+ (String) actual);
+ } else {
+ failNotEquals(message, expected, actual);
+ }
+ }
+
+ private static boolean equalsRegardingNull(Object expected, Object actual) {
+ if (expected == null) {
+ return actual == null;
+ }
+
+ return isEquals(expected, actual);
+ }
+
+ private static boolean isEquals(Object expected, Object actual) {
+ return expected.equals(actual);
+ }
+
+ /**
+ * Asserts that two objects are equal. If they are not, an
+ * {@link AssertionError} without a message is thrown. If
+ * expected and actual are null,
+ * they are considered equal.
+ *
+ * @param expected expected value
+ * @param actual the value to check against expected
+ */
+ public static void assertEquals(Object expected, Object actual) {
+ assertEquals(null, expected, actual);
+ }
+
+ /**
+ * Asserts that two objects are not equals. If they are, an
+ * {@link AssertionError} is thrown with the given message. If
+ * unexpected and actual are null,
+ * they are considered equal.
+ *
+ * @param message the identifying message for the {@link AssertionError} (null
+ * okay)
+ * @param unexpected unexpected value to check
+ * @param actual the value to check against unexpected
+ */
+ public static void assertNotEquals(String message, Object unexpected,
+ Object actual) {
+ if (equalsRegardingNull(unexpected, actual)) {
+ failEquals(message, actual);
+ }
+ }
+
+ /**
+ * Asserts that two objects are not equals. If they are, an
+ * {@link AssertionError} without a message is thrown. If
+ * unexpected and actual are null,
+ * they are considered equal.
+ *
+ * @param unexpected unexpected value to check
+ * @param actual the value to check against unexpected
+ */
+ public static void assertNotEquals(Object unexpected, Object actual) {
+ assertNotEquals(null, unexpected, actual);
+ }
+
+ private static void failEquals(String message, Object actual) {
+ String formatted = "Values should be different. ";
+ if (message != null) {
+ formatted = message + ". ";
+ }
+
+ formatted += "Actual: " + actual;
+ fail(formatted);
+ }
+
+ /**
+ * Asserts that two longs are not equals. If they are, an
+ * {@link AssertionError} is thrown with the given message.
+ *
+ * @param message the identifying message for the {@link AssertionError} (null
+ * okay)
+ * @param unexpected unexpected value to check
+ * @param actual the value to check against unexpected
+ */
+ public static void assertNotEquals(String message, long unexpected, long actual) {
+ if (unexpected == actual) {
+ failEquals(message, Long.valueOf(actual));
+ }
+ }
+
+ /**
+ * Asserts that two longs are not equals. If they are, an
+ * {@link AssertionError} without a message is thrown.
+ *
+ * @param unexpected unexpected value to check
+ * @param actual the value to check against unexpected
+ */
+ public static void assertNotEquals(long unexpected, long actual) {
+ assertNotEquals(null, unexpected, actual);
+ }
+
+ /**
+ * Asserts that two doubles are not equal to within a positive delta.
+ * If they are, an {@link AssertionError} is thrown with the given
+ * message. If the unexpected value is infinity then the delta value is
+ * ignored. NaNs are considered equal:
+ * assertNotEquals(Double.NaN, Double.NaN, *) fails
+ *
+ * @param message the identifying message for the {@link AssertionError} (null
+ * okay)
+ * @param unexpected unexpected value
+ * @param actual the value to check against unexpected
+ * @param delta the maximum delta between unexpected and
+ * actual for which both numbers are still
+ * considered equal.
+ */
+ public static void assertNotEquals(String message, double unexpected,
+ double actual, double delta) {
+ if (!doubleIsDifferent(unexpected, actual, delta)) {
+ failEquals(message, Double.valueOf(actual));
+ }
+ }
+
+ /**
+ * Asserts that two doubles are not equal to within a positive delta.
+ * If they are, an {@link AssertionError} is thrown. If the unexpected
+ * value is infinity then the delta value is ignored.NaNs are considered
+ * equal: assertNotEquals(Double.NaN, Double.NaN, *) fails
+ *
+ * @param unexpected unexpected value
+ * @param actual the value to check against unexpected
+ * @param delta the maximum delta between unexpected and
+ * actual for which both numbers are still
+ * considered equal.
+ */
+ public static void assertNotEquals(double unexpected, double actual, double delta) {
+ assertNotEquals(null, unexpected, actual, delta);
+ }
+
+ /**
+ * Asserts that two floats are not equal to within a positive delta.
+ * If they are, an {@link AssertionError} is thrown. If the unexpected
+ * value is infinity then the delta value is ignored.NaNs are considered
+ * equal: assertNotEquals(Float.NaN, Float.NaN, *) fails
+ *
+ * @param unexpected unexpected value
+ * @param actual the value to check against unexpected
+ * @param delta the maximum delta between unexpected and
+ * actual for which both numbers are still
+ * considered equal.
+ */
+ public static void assertNotEquals(float unexpected, float actual, float delta) {
+ assertNotEquals(null, unexpected, actual, delta);
+ }
+
+ /**
+ * Asserts that two object arrays are equal. If they are not, an
+ * {@link AssertionError} is thrown with the given message. If
+ * expecteds and actuals are null,
+ * they are considered equal.
+ *
+ * @param message the identifying message for the {@link AssertionError} (null
+ * okay)
+ * @param expecteds Object array or array of arrays (multi-dimensional array) with
+ * expected values.
+ * @param actuals Object array or array of arrays (multi-dimensional array) with
+ * actual values
+ */
+ public static void assertArrayEquals(String message, Object[] expecteds,
+ Object[] actuals) throws ArrayComparisonFailure {
+ internalArrayEquals(message, expecteds, actuals);
+ }
+
+ /**
+ * Asserts that two object arrays are equal. If they are not, an
+ * {@link AssertionError} is thrown. If expected and
+ * actual are null, they are considered
+ * equal.
+ *
+ * @param expecteds Object array or array of arrays (multi-dimensional array) with
+ * expected values
+ * @param actuals Object array or array of arrays (multi-dimensional array) with
+ * actual values
+ */
+ 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
+ * expecteds and actuals are null,
+ * they are considered equal.
+ *
+ * @param message the identifying message for the {@link AssertionError} (null
+ * okay)
+ * @param expecteds boolean array with expected values.
+ * @param actuals boolean array with expected values.
+ */
+ 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 expected and
+ * actual are null, they are considered
+ * equal.
+ *
+ * @param expecteds boolean array with expected values.
+ * @param actuals boolean array with expected values.
+ */
+ public static void assertArrayEquals(boolean[] expecteds, boolean[] actuals) {
+ assertArrayEquals(null, expecteds, actuals);
+ }
+
+ /**
+ * Asserts that two byte arrays are equal. If they are not, an
+ * {@link AssertionError} is thrown with the given message.
+ *
+ * @param message the identifying message for the {@link AssertionError} (null
+ * okay)
+ * @param expecteds byte array with expected values.
+ * @param actuals byte array with actual values
+ */
+ public static void assertArrayEquals(String message, byte[] expecteds,
+ byte[] actuals) throws ArrayComparisonFailure {
+ internalArrayEquals(message, expecteds, actuals);
+ }
+
+ /**
+ * Asserts that two byte arrays are equal. If they are not, an
+ * {@link AssertionError} is thrown.
+ *
+ * @param expecteds byte array with expected values.
+ * @param actuals byte array with actual values
+ */
+ public static void assertArrayEquals(byte[] expecteds, byte[] actuals) {
+ assertArrayEquals(null, expecteds, actuals);
+ }
+
+ /**
+ * Asserts that two char arrays are equal. If they are not, an
+ * {@link AssertionError} is thrown with the given message.
+ *
+ * @param message the identifying message for the {@link AssertionError} (null
+ * okay)
+ * @param expecteds char array with expected values.
+ * @param actuals char array with actual values
+ */
+ public static void assertArrayEquals(String message, char[] expecteds,
+ char[] actuals) throws ArrayComparisonFailure {
+ internalArrayEquals(message, expecteds, actuals);
+ }
+
+ /**
+ * Asserts that two char arrays are equal. If they are not, an
+ * {@link AssertionError} is thrown.
+ *
+ * @param expecteds char array with expected values.
+ * @param actuals char array with actual values
+ */
+ public static void assertArrayEquals(char[] expecteds, char[] actuals) {
+ assertArrayEquals(null, expecteds, actuals);
+ }
+
+ /**
+ * Asserts that two short arrays are equal. If they are not, an
+ * {@link AssertionError} is thrown with the given message.
+ *
+ * @param message the identifying message for the {@link AssertionError} (null
+ * okay)
+ * @param expecteds short array with expected values.
+ * @param actuals short array with actual values
+ */
+ public static void assertArrayEquals(String message, short[] expecteds,
+ short[] actuals) throws ArrayComparisonFailure {
+ internalArrayEquals(message, expecteds, actuals);
+ }
+
+ /**
+ * Asserts that two short arrays are equal. If they are not, an
+ * {@link AssertionError} is thrown.
+ *
+ * @param expecteds short array with expected values.
+ * @param actuals short array with actual values
+ */
+ public static void assertArrayEquals(short[] expecteds, short[] actuals) {
+ assertArrayEquals(null, expecteds, actuals);
+ }
+
+ /**
+ * Asserts that two int arrays are equal. If they are not, an
+ * {@link AssertionError} is thrown with the given message.
+ *
+ * @param message the identifying message for the {@link AssertionError} (null
+ * okay)
+ * @param expecteds int array with expected values.
+ * @param actuals int array with actual values
+ */
+ public static void assertArrayEquals(String message, int[] expecteds,
+ int[] actuals) throws ArrayComparisonFailure {
+ internalArrayEquals(message, expecteds, actuals);
+ }
+
+ /**
+ * Asserts that two int arrays are equal. If they are not, an
+ * {@link AssertionError} is thrown.
+ *
+ * @param expecteds int array with expected values.
+ * @param actuals int array with actual values
+ */
+ public static void assertArrayEquals(int[] expecteds, int[] actuals) {
+ assertArrayEquals(null, expecteds, actuals);
+ }
+
+ /**
+ * Asserts that two long arrays are equal. If they are not, an
+ * {@link AssertionError} is thrown with the given message.
+ *
+ * @param message the identifying message for the {@link AssertionError} (null
+ * okay)
+ * @param expecteds long array with expected values.
+ * @param actuals long array with actual values
+ */
+ public static void assertArrayEquals(String message, long[] expecteds,
+ long[] actuals) throws ArrayComparisonFailure {
+ internalArrayEquals(message, expecteds, actuals);
+ }
+
+ /**
+ * Asserts that two long arrays are equal. If they are not, an
+ * {@link AssertionError} is thrown.
+ *
+ * @param expecteds long array with expected values.
+ * @param actuals long array with actual values
+ */
+ public static void assertArrayEquals(long[] expecteds, long[] actuals) {
+ assertArrayEquals(null, expecteds, actuals);
+ }
+
+ /**
+ * Asserts that two double arrays are equal. If they are not, an
+ * {@link AssertionError} is thrown with the given message.
+ *
+ * @param message the identifying message for the {@link AssertionError} (null
+ * okay)
+ * @param expecteds double array with expected values.
+ * @param actuals double array with actual values
+ * @param delta the maximum delta between expecteds[i] and
+ * actuals[i] for which both numbers are still
+ * considered equal.
+ */
+ public static void assertArrayEquals(String message, double[] expecteds,
+ double[] actuals, double delta) throws ArrayComparisonFailure {
+ new InexactComparisonCriteria(delta).arrayEquals(message, expecteds, actuals);
+ }
+
+ /**
+ * Asserts that two double arrays are equal. If they are not, an
+ * {@link AssertionError} is thrown.
+ *
+ * @param expecteds double array with expected values.
+ * @param actuals double array with actual values
+ * @param delta the maximum delta between expecteds[i] and
+ * actuals[i] for which both numbers are still
+ * considered equal.
+ */
+ public static void assertArrayEquals(double[] expecteds, double[] actuals, double delta) {
+ assertArrayEquals(null, expecteds, actuals, delta);
+ }
+
+ /**
+ * Asserts that two float arrays are equal. If they are not, an
+ * {@link AssertionError} is thrown with the given message.
+ *
+ * @param message the identifying message for the {@link AssertionError} (null
+ * okay)
+ * @param expecteds float array with expected values.
+ * @param actuals float array with actual values
+ * @param delta the maximum delta between expecteds[i] and
+ * actuals[i] for which both numbers are still
+ * considered equal.
+ */
+ public static void assertArrayEquals(String message, float[] expecteds,
+ float[] actuals, float delta) throws ArrayComparisonFailure {
+ new InexactComparisonCriteria(delta).arrayEquals(message, expecteds, actuals);
+ }
+
+ /**
+ * Asserts that two float arrays are equal. If they are not, an
+ * {@link AssertionError} is thrown.
+ *
+ * @param expecteds float array with expected values.
+ * @param actuals float array with actual values
+ * @param delta the maximum delta between expecteds[i] and
+ * actuals[i] for which both numbers are still
+ * considered equal.
+ */
+ public static void assertArrayEquals(float[] expecteds, float[] actuals, float delta) {
+ assertArrayEquals(null, expecteds, actuals, delta);
+ }
+
+ /**
+ * Asserts that two object arrays are equal. If they are not, an
+ * {@link AssertionError} is thrown with the given message. If
+ * expecteds and actuals are null,
+ * they are considered equal.
+ *
+ * @param message the identifying message for the {@link AssertionError} (null
+ * okay)
+ * @param expecteds Object array or array of arrays (multi-dimensional array) with
+ * expected values.
+ * @param actuals Object array or array of arrays (multi-dimensional array) with
+ * actual values
+ */
+ private static void internalArrayEquals(String message, Object expecteds,
+ Object actuals) throws ArrayComparisonFailure {
+ new ExactComparisonCriteria().arrayEquals(message, expecteds, actuals);
+ }
+
+ /**
+ * Asserts that two doubles are equal to within a positive delta.
+ * If they are not, an {@link AssertionError} is thrown with the given
+ * message. If the expected value is infinity then the delta value is
+ * ignored. NaNs are considered equal:
+ * assertEquals(Double.NaN, Double.NaN, *) passes
+ *
+ * @param message the identifying message for the {@link AssertionError} (null
+ * okay)
+ * @param expected expected value
+ * @param actual the value to check against expected
+ * @param delta the maximum delta between expected and
+ * actual for which both numbers are still
+ * considered equal.
+ */
+ 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));
+ }
+ }
+
+ /**
+ * Asserts that two floats are equal to within a positive delta.
+ * If they are not, an {@link AssertionError} is thrown with the given
+ * message. If the expected value is infinity then the delta value is
+ * ignored. NaNs are considered equal:
+ * assertEquals(Float.NaN, Float.NaN, *) passes
+ *
+ * @param message the identifying message for the {@link AssertionError} (null
+ * okay)
+ * @param expected expected value
+ * @param actual the value to check against expected
+ * @param delta the maximum delta between expected and
+ * actual for which both numbers are still
+ * considered equal.
+ */
+ 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));
+ }
+ }
+
+ /**
+ * Asserts that two floats are not equal to within a positive delta.
+ * If they are, an {@link AssertionError} is thrown with the given
+ * message. If the unexpected value is infinity then the delta value is
+ * ignored. NaNs are considered equal:
+ * assertNotEquals(Float.NaN, Float.NaN, *) fails
+ *
+ * @param message the identifying message for the {@link AssertionError} (null
+ * okay)
+ * @param unexpected unexpected value
+ * @param actual the value to check against unexpected
+ * @param delta the maximum delta between unexpected and
+ * actual for which both numbers are still
+ * considered equal.
+ */
+ public static void assertNotEquals(String message, float unexpected,
+ float actual, float delta) {
+ if (!floatIsDifferent(unexpected, actual, delta)) {
+ failEquals(message, Float.valueOf(actual));
+ }
+ }
+
+ private static boolean doubleIsDifferent(double d1, double d2, double delta) {
+ if (Double.compare(d1, d2) == 0) {
+ return false;
+ }
+ if ((Math.abs(d1 - d2) <= delta)) {
+ return false;
+ }
+
+ return true;
+ }
+
+ private static boolean floatIsDifferent(float f1, float f2, float delta) {
+ if (Float.compare(f1, f2) == 0) {
+ return false;
+ }
+ if ((Math.abs(f1 - f2) <= delta)) {
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Asserts that two longs are equal. If they are not, an
+ * {@link AssertionError} is thrown.
+ *
+ * @param expected expected long value.
+ * @param actual actual long value
+ */
+ public static void assertEquals(long expected, long actual) {
+ assertEquals(null, expected, actual);
+ }
+
+ /**
+ * Asserts that two longs are equal. If they are not, an
+ * {@link AssertionError} is thrown with the given message.
+ *
+ * @param message the identifying message for the {@link AssertionError} (null
+ * okay)
+ * @param expected long expected value.
+ * @param actual long actual value
+ */
+ public static void assertEquals(String message, long expected, long actual) {
+ if (expected != actual) {
+ failNotEquals(message, Long.valueOf(expected), Long.valueOf(actual));
+ }
+ }
+
+ /**
+ * @deprecated Use
+ * assertEquals(double expected, double actual, double delta)
+ * instead
+ */
+ @Deprecated
+ public static void assertEquals(double expected, double actual) {
+ assertEquals(null, expected, actual);
+ }
+
+ /**
+ * @deprecated Use
+ * assertEquals(String message, double expected, double actual, double delta)
+ * instead
+ */
+ @Deprecated
+ public static void assertEquals(String message, double expected,
+ double actual) {
+ fail("Use assertEquals(expected, actual, delta) to compare floating-point numbers");
+ }
+
+ /**
+ * Asserts that two doubles are equal to within a positive delta.
+ * If they are not, an {@link AssertionError} is thrown. If the expected
+ * value is infinity then the delta value is ignored.NaNs are considered
+ * equal: assertEquals(Double.NaN, Double.NaN, *) passes
+ *
+ * @param expected expected value
+ * @param actual the value to check against expected
+ * @param delta the maximum delta between expected and
+ * actual for which both numbers are still
+ * considered equal.
+ */
+ public static void assertEquals(double expected, double actual, double delta) {
+ assertEquals(null, expected, actual, delta);
+ }
+
+ /**
+ * Asserts that two floats are equal to within a positive delta.
+ * If they are not, an {@link AssertionError} is thrown. If the expected
+ * value is infinity then the delta value is ignored. NaNs are considered
+ * equal: assertEquals(Float.NaN, Float.NaN, *) passes
+ *
+ * @param expected expected value
+ * @param actual the value to check against expected
+ * @param delta the maximum delta between expected and
+ * actual for which both numbers are still
+ * considered equal.
+ */
+ public static void assertEquals(float expected, float actual, float delta) {
+ assertEquals(null, expected, actual, delta);
+ }
+
+ /**
+ * Asserts that an object isn't null. If it is an {@link AssertionError} is
+ * thrown with the given message.
+ *
+ * @param message the identifying message for the {@link AssertionError} (null
+ * okay)
+ * @param object Object to check or null
+ */
+ public static void assertNotNull(String message, Object object) {
+ assertTrue(message, object != null);
+ }
+
+ /**
+ * Asserts that an object isn't null. If it is an {@link AssertionError} is
+ * thrown.
+ *
+ * @param object Object to check or null
+ */
+ public static void assertNotNull(Object object) {
+ assertNotNull(null, object);
+ }
+
+ /**
+ * Asserts that an object is null. If it is not, an {@link AssertionError}
+ * is thrown with the given message.
+ *
+ * @param message the identifying message for the {@link AssertionError} (null
+ * okay)
+ * @param object Object to check or null
+ */
+ public static void assertNull(String message, Object object) {
+ if (object == null) {
+ return;
+ }
+ failNotNull(message, object);
+ }
+
+ /**
+ * Asserts that an object is null. If it isn't an {@link AssertionError} is
+ * thrown.
+ *
+ * @param object Object to check or null
+ */
+ public static void assertNull(Object object) {
+ assertNull(null, object);
+ }
+
+ private static void failNotNull(String message, Object actual) {
+ String formatted = "";
+ if (message != null) {
+ formatted = message + " ";
+ }
+ fail(formatted + "expected null, but was:<" + actual + ">");
+ }
+
+ /**
+ * Asserts that two objects refer to the same object. If they are not, an
+ * {@link AssertionError} is thrown with the given message.
+ *
+ * @param message the identifying message for the {@link AssertionError} (null
+ * okay)
+ * @param expected the expected object
+ * @param actual the object to compare to expected
+ */
+ public static void assertSame(String message, Object expected, Object actual) {
+ if (expected == actual) {
+ return;
+ }
+ failNotSame(message, expected, actual);
+ }
+
+ /**
+ * Asserts that two objects refer to the same object. If they are not the
+ * same, an {@link AssertionError} without a message is thrown.
+ *
+ * @param expected the expected object
+ * @param actual the object to compare to expected
+ */
+ public static void assertSame(Object expected, Object actual) {
+ assertSame(null, expected, actual);
+ }
+
+ /**
+ * Asserts that two objects do not refer to the same object. If they do
+ * refer to the same object, an {@link AssertionError} is thrown with the
+ * given message.
+ *
+ * @param message the identifying message for the {@link AssertionError} (null
+ * okay)
+ * @param unexpected the object you don't expect
+ * @param actual the object to compare to unexpected
+ */
+ public static void assertNotSame(String message, Object unexpected,
+ Object actual) {
+ if (unexpected == actual) {
+ failSame(message);
+ }
+ }
+
+ /**
+ * Asserts that two objects do not refer to the same object. If they do
+ * refer to the same object, an {@link AssertionError} without a message is
+ * thrown.
+ *
+ * @param unexpected the object you don't expect
+ * @param actual the object to compare to unexpected
+ */
+ public static void assertNotSame(Object unexpected, Object actual) {
+ assertNotSame(null, unexpected, actual);
+ }
+
+ private static void failSame(String message) {
+ String formatted = "";
+ if (message != null) {
+ formatted = message + " ";
+ }
+ fail(formatted + "expected not same");
+ }
+
+ private static void failNotSame(String message, Object expected,
+ Object actual) {
+ String formatted = "";
+ if (message != null) {
+ formatted = message + " ";
+ }
+ fail(formatted + "expected same:<" + expected + "> was not:<" + actual
+ + ">");
+ }
+
+ 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 && !"".equals(message)) {
+ formatted = message + " ";
+ }
+ String expectedString = String.valueOf(expected);
+ String actualString = String.valueOf(actual);
+ if (equalsRegardingNull(expectedString, actualString)) {
+ return formatted + "expected: "
+ + formatClassAndValue(expected, expectedString)
+ + " but was: " + formatClassAndValue(actual, actualString);
+ } else {
+ return formatted + "expected:<" + expectedString + "> but was:<"
+ + actualString + ">";
+ }
+ }
+
+ 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 + ">";
+ }
+
+ /**
+ * Asserts that two object arrays are equal. If they are not, an
+ * {@link AssertionError} is thrown with the given message. If
+ * expecteds and actuals are null,
+ * they are considered equal.
+ *
+ * @param message the identifying message for the {@link AssertionError} (null
+ * okay)
+ * @param expecteds Object array or array of arrays (multi-dimensional array) with
+ * expected values.
+ * @param actuals Object array or array of arrays (multi-dimensional array) with
+ * actual values
+ * @deprecated use assertArrayEquals
+ */
+ @Deprecated
+ public static void assertEquals(String message, Object[] expecteds,
+ Object[] actuals) {
+ assertArrayEquals(message, expecteds, actuals);
+ }
+
+ /**
+ * Asserts that two object arrays are equal. If they are not, an
+ * {@link AssertionError} is thrown. If expected and
+ * actual are null, they are considered
+ * equal.
+ *
+ * @param expecteds Object array or array of arrays (multi-dimensional array) with
+ * expected values
+ * @param actuals Object array or array of arrays (multi-dimensional array) with
+ * actual values
+ * @deprecated use assertArrayEquals
+ */
+ @Deprecated
+ public static void assertEquals(Object[] expecteds, Object[] actuals) {
+ assertArrayEquals(expecteds, actuals);
+ }
+
+ /**
+ * Asserts that actual satisfies the condition specified by
+ * matcher. If not, an {@link AssertionError} is thrown with
+ * information about the matcher and failing value. Example:
+ *
+ *
+ *
+ * org.hamcrest.Matcher does not currently document the meaning
+ * of its type parameter T. This method assumes that a matcher
+ * typed as Matcher<T> can be meaningfully applied only
+ * to values that could be assigned to a variable of type T.
+ *
+ * @param the static type accepted by the matcher (this can flag obvious
+ * compile-time problems such as {@code assertThat(1, is("a"))}
+ * @param actual the computed value being compared
+ * @param matcher an expression, built of {@link Matcher}s, specifying allowed
+ * values
+ * @see org.hamcrest.CoreMatchers
+ * @deprecated use {@code org.hamcrest.MatcherAssert.assertThat()}
+ */
+ @Deprecated
+ public static void assertThat(T actual, Matcher super T> matcher) {
+ assertThat("", actual, matcher);
+ }
+
+ /**
+ * Asserts that actual satisfies the condition specified by
+ * matcher. If not, an {@link AssertionError} is thrown with
+ * the reason and information about the matcher and failing value. Example:
+ *
+ *
+ *
+ * org.hamcrest.Matcher does not currently document the meaning
+ * of its type parameter T. This method assumes that a matcher
+ * typed as Matcher<T> can be meaningfully applied only
+ * to values that could be assigned to a variable of type T.
+ *
+ * @param reason additional information about the error
+ * @param the static type accepted by the matcher (this can flag obvious
+ * compile-time problems such as {@code assertThat(1, is("a"))}
+ * @param actual the computed value being compared
+ * @param matcher an expression, built of {@link Matcher}s, specifying allowed
+ * values
+ * @see org.hamcrest.CoreMatchers
+ * @deprecated use {@code org.hamcrest.MatcherAssert.assertThat()}
+ */
+ @Deprecated
+ public static 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 assertThrows(Class 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} (null
+ * 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 assertThrows(String message, Class 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 ..."
+ 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 7b6c21a823e5..29b705be6988 100644
--- a/src/main/java/org/junit/Assume.java
+++ b/src/main/java/org/junit/Assume.java
@@ -1,27 +1,25 @@
package org.junit;
import static java.util.Arrays.asList;
+import static org.hamcrest.CoreMatchers.everyItem;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.CoreMatchers.nullValue;
+
import org.hamcrest.Matcher;
-import org.junit.internal.AssumptionViolatedException;
-import org.junit.internal.matchers.Each;
/**
* A set of methods useful for stating assumptions about the conditions in which a test is meaningful.
- * A failed assumption does not mean the code is broken, but that the test provides no useful information.
- * The default JUnit runner treats tests with failing assumptions as ignored. Custom runners may behave differently.
- *
- * For example:
- *
- * // only provides information if database is reachable.
- * \@Test public void calculateTotalSalary() {
- * DBConnection dbc = Database.connect();
- * assumeNotNull(dbc);
- * // ...
- * }
- *
+ * A failed assumption does not mean the code is broken, but that the test provides no useful information. Assume
+ * 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.
+ *
+ * A good example of using assumptions is in Theories where they are needed to exclude certain datapoints that aren't suitable or allowed for a certain test case.
+ *
+ * Failed assumptions are usually not logged, because there may be many tests that don't apply to certain
+ * configurations.
+ *
+ *
* These methods can be used directly: Assume.assumeTrue(...), however, they
* read better if they are referenced through static import:
*
@@ -29,66 +27,143 @@
* ...
* assumeTrue(...);
*
+ *
+ *
+ * @see Theories
+ *
+ * @since 4.4
*/
public class Assume {
- /**
- * If called with an expression evaluating to {@code false}, the test will halt and be ignored.
- * @param b
- */
- public static void assumeTrue(boolean b) {
- assumeThat(b, is(true));
- }
- /**
- * If called with one or more null elements in objects, the test will halt and be ignored.
- * @param objects
- */
- public static void assumeNotNull(Object... objects) {
- assumeThat(asList(objects), Each.each(notNullValue()));
- }
+ /**
+ * 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.
+ */
+ public static void assumeTrue(boolean b) {
+ assumeThat(b, is(true));
+ }
+
+ /**
+ * The inverse of {@link #assumeTrue(boolean)}.
+ */
+ public static void assumeFalse(boolean b) {
+ assumeThat(b, is(false));
+ }
+
+ /**
+ * If called with an expression evaluating to {@code false}, the test will halt and be ignored.
+ *
+ * @param b If false, the method will attempt to stop the test and ignore it by
+ * throwing {@link AssumptionViolatedException}.
+ * @param message A message to pass to {@link AssumptionViolatedException}.
+ */
+ public static void assumeTrue(String message, boolean b) {
+ if (!b) throw new AssumptionViolatedException(message);
+ }
- /**
- * Call to assume that actual satisfies the condition specified by matcher.
- * If not, the test halts and is ignored.
- * Example:
- *
:
- * assumeThat(1, is(1)); // passes
- * foo(); // will execute
- * assumeThat(0, is(1)); // assumption failure! test halts
- * int x = 1 / 0; // will never execute
- *
- *
- * @param the static type accepted by the matcher (this can flag obvious compile-time problems such as {@code assumeThat(1, is("a"))}
- * @param actual the computed value being compared
- * @param matcher an expression, built of {@link Matcher}s, specifying allowed values
- *
- * @see org.hamcrest.CoreMatchers
- * @see org.junit.matchers.JUnitMatchers
- */
- public static void assumeThat(T actual, Matcher matcher) {
- if (!matcher.matches(actual))
- throw new AssumptionViolatedException(actual, matcher);
- }
+ /**
+ * The inverse of {@link #assumeTrue(String, boolean)}.
+ */
+ public static void assumeFalse(String message, boolean b) {
+ assumeTrue(message, !b);
+ }
+
+ /**
+ * 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()));
+ }
+
+ /**
+ * Call to assume that actual satisfies the condition specified by matcher.
+ * If not, the test halts and is ignored.
+ * Example:
+ *
:
+ * assumeThat(1, is(1)); // passes
+ * foo(); // will execute
+ * assumeThat(0, is(1)); // assumption failure! test halts
+ * int x = 1 / 0; // will never execute
+ *
+ *
+ * @param the static type accepted by the matcher (this can flag obvious compile-time problems such as {@code assumeThat(1, is("a"))}
+ * @param actual the computed value being compared
+ * @param matcher an expression, built of {@link Matcher}s, specifying allowed values
+ * @see org.hamcrest.CoreMatchers
+ * @see org.junit.matchers.JUnitMatchers
+ */
+ public static void assumeThat(T actual, Matcher matcher) {
+ if (!matcher.matches(actual)) {
+ throw new AssumptionViolatedException(actual, matcher);
+ }
+ }
+
+ /**
+ * Call to assume that actual satisfies the condition specified by matcher.
+ * If not, the test halts and is ignored.
+ * Example:
+ *
:
+ * assumeThat("alwaysPasses", 1, is(1)); // passes
+ * foo(); // will execute
+ * assumeThat("alwaysFails", 0, is(1)); // assumption failure! test halts
+ * int x = 1 / 0; // will never execute
+ *
+ *
+ * @param the static type accepted by the matcher (this can flag obvious compile-time problems such as {@code assumeThat(1, is("a"))}
+ * @param actual the computed value being compared
+ * @param matcher an expression, built of {@link Matcher}s, specifying allowed values
+ * @see org.hamcrest.CoreMatchers
+ * @see org.junit.matchers.JUnitMatchers
+ */
+ public static void assumeThat(String message, T actual, Matcher matcher) {
+ if (!matcher.matches(actual)) {
+ throw new AssumptionViolatedException(message, actual, matcher);
+ }
+ }
+
+ /**
+ * Use to assume that an operation completes normally. If {@code e} is non-null, the test will halt and be ignored.
+ *
+ * For example:
+ *
+ * \@Test public void parseDataFile() {
+ * DataFile file;
+ * try {
+ * file = DataFile.open("sampledata.txt");
+ * } catch (IOException e) {
+ * // stop test and ignore if data can't be opened
+ * assumeNoException(e);
+ * }
+ * // ...
+ * }
+ *
+ *
+ * @param e if non-null, the offending exception
+ */
+ public static void assumeNoException(Throwable e) {
+ assumeThat(e, nullValue());
+ }
/**
- * Use to assume that an operation completes normally. If {@code t} is non-null, the test will halt and be ignored.
- *
- * For example:
- *
- * \@Test public void parseDataFile() {
- * DataFile file;
- * try {
- * file = DataFile.open("sampledata.txt");
- * } catch (IOException e) {
- * // stop test and ignore if data can't be opened
- * assumeNoException(e);
- * }
- * // ...
- * }
- *
- * @param t if non-null, the offending exception
- */
- public static void assumeNoException(Throwable t) {
- assumeThat(t, nullValue());
- }
+ * Attempts to halt the test and ignore it if Throwable e is
+ * not null. Similar to {@link #assumeNoException(Throwable)},
+ * but provides an additional message that can explain the details
+ * concerning the assumption.
+ *
+ * @param e if non-null, the offending exception
+ * @param message Additional message to pass to {@link AssumptionViolatedException}.
+ * @see #assumeNoException(Throwable)
+ */
+ public static void assumeNoException(String message, Throwable e) {
+ assumeThat(message, e, nullValue());
+ }
}
diff --git a/src/main/java/org/junit/AssumptionViolatedException.java b/src/main/java/org/junit/AssumptionViolatedException.java
new file mode 100644
index 000000000000..1d62190a2315
--- /dev/null
+++ b/src/main/java/org/junit/AssumptionViolatedException.java
@@ -0,0 +1,46 @@
+package org.junit;
+
+import org.hamcrest.Matcher;
+
+/**
+ * An exception class used to implement assumptions (state in which a given test
+ * is meaningful and should or should not be executed). A test for which an assumption
+ * fails should not generate a test case failure.
+ *
+ * @see org.junit.Assume
+ * @since 4.12
+ */
+@SuppressWarnings("deprecation")
+public class AssumptionViolatedException extends org.junit.internal.AssumptionViolatedException {
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * An assumption exception with the given actual value and a matcher describing
+ * the expectation that failed.
+ */
+ public AssumptionViolatedException(T actual, Matcher matcher) {
+ super(actual, matcher);
+ }
+
+ /**
+ * An assumption exception with a message with the given actual value and a
+ * matcher describing the expectation that failed.
+ */
+ public AssumptionViolatedException(String message, T expected, Matcher matcher) {
+ super(message, expected, matcher);
+ }
+
+ /**
+ * An assumption exception with the given message only.
+ */
+ public AssumptionViolatedException(String message) {
+ super(message);
+ }
+
+ /**
+ * An assumption exception with the given message and a cause.
+ */
+ public AssumptionViolatedException(String message, Throwable t) {
+ super(message, t);
+ }
+}
diff --git a/src/main/java/org/junit/Before.java b/src/main/java/org/junit/Before.java
index 66b34eeb09e4..def8adb47ad6 100644
--- a/src/main/java/org/junit/Before.java
+++ b/src/main/java/org/junit/Before.java
@@ -6,13 +6,12 @@
import java.lang.annotation.Target;
/**
- *
When writing tests, it is common to find that several tests need similar
+ * When writing tests, it is common to find that several tests need similar
* objects created before they can run. Annotating a public void method
* with @Before causes that method to be run before the {@link org.junit.Test} method.
- * The @Before methods of superclasses will be run before those of the current class.
- * No other ordering is defined.
- *
- *
+ * The @Before methods of superclasses will be run before those of the current class,
+ * unless they are overridden in the current class. No other ordering is defined.
+ *
* Here is a simple example:
*
* public class Example {
@@ -28,9 +27,10 @@
* }
* }
*
Sometimes several tests need to share computationally expensive setup
- * (like logging into a database). While this can compromise the independence of
+ * Sometimes several tests need to share computationally expensive setup
+ * (like logging into a database). While this can compromise the independence of
* tests, sometimes it is a necessary optimization. Annotating a public static void no-arg method
- * with @BeforeClass causes it to be run once before any of
+ * with @BeforeClass causes it to be run once before any of
* the test methods in the class. The @BeforeClass methods of superclasses
- * will be run before those the current class.
- *
+ * will be run before those of the current class, unless they are shadowed in the current class.
+ *
* For example:
*
* public class Example {
@@ -27,7 +27,9 @@
* }
* }
*
+ *
* @see org.junit.AfterClass
+ * @since 4.0
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
diff --git a/src/main/java/org/junit/ClassRule.java b/src/main/java/org/junit/ClassRule.java
new file mode 100644
index 000000000000..94ee29f9f51d
--- /dev/null
+++ b/src/main/java/org/junit/ClassRule.java
@@ -0,0 +1,118 @@
+package org.junit;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Annotates static fields that reference rules or methods that return them. A field must be public,
+ * static, and a subtype of {@link org.junit.rules.TestRule}. A method must be public static, and return
+ * a subtype of {@link org.junit.rules.TestRule}.
+ *
+ * The {@link org.junit.runners.model.Statement} passed
+ * to the {@link org.junit.rules.TestRule} will run any {@link BeforeClass} methods,
+ * then the entire body of the test class (all contained methods, if it is
+ * a standard JUnit test class, or all contained classes, if it is a
+ * {@link org.junit.runners.Suite}), and finally any {@link AfterClass} methods.
+ *
+ * The statement passed to the {@link org.junit.rules.TestRule} will never throw an exception,
+ * and throwing an exception from the {@link org.junit.rules.TestRule} will result in undefined
+ * behavior. This means that some {@link org.junit.rules.TestRule}s, such as
+ * {@link org.junit.rules.ErrorCollector},
+ * {@link org.junit.rules.ExpectedException},
+ * and {@link org.junit.rules.Timeout},
+ * have undefined behavior when used as {@link ClassRule}s.
+ *
+ * If there are multiple
+ * 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
+ * after Rules defined by methods, i.e. the Statements returned by the former will
+ * be executed around those returned by the latter.
+ *
+ *
Usage
+ *
+ * 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:
+ *
+ * For more information and more examples, see {@link org.junit.rules.TestRule}.
+ *
+ *
Ordering
+ *
+ * You can use {@link #order()} if you want to have control over the order in
+ * which the Rules are applied.
+ *
+ *
+ * public class ThreeClassRules {
+ * @ClassRule(order = 0)
+ * public static LoggingRule outer = new LoggingRule("outer rule");
+ *
+ * @ClassRule(order = 1)
+ * public static LoggingRule middle = new LoggingRule("middle rule");
+ *
+ * @ClassRule(order = 2)
+ * public static LoggingRule inner = new LoggingRule("inner rule");
+ *
+ * // ...
+ * }
+ *
+ *
+ * @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 d37db4fc3af1..d1daa863c3f3 100644
--- a/src/main/java/org/junit/ComparisonFailure.java
+++ b/src/main/java/org/junit/ComparisonFailure.java
@@ -1,138 +1,171 @@
package org.junit;
/**
- * Thrown when an {@link org.junit.Assert#assertEquals(Object, Object) assertEquals(String, String)} fails. Create and throw
- * a ComparisonFailure manually if you want to show users the difference between two complex
- * strings.
- *
+ * Thrown when an {@link org.junit.Assert#assertEquals(Object, Object) assertEquals(String, String)} fails.
+ * Create and throw a ComparisonFailure manually if you want to show users the
+ * difference between two complex strings.
+ *
* Inspired by a patch from Alex Chaffee (alex@purpletech.com)
+ *
+ * @since 4.0
*/
-public class ComparisonFailure extends AssertionError {
- /**
- * The maximum length for fExpected and fActual. If it is exceeded, the strings should be shortened.
- * @see ComparisonCompactor
- */
- private static final int MAX_CONTEXT_LENGTH= 20;
- private static final long serialVersionUID= 1L;
-
- private String fExpected;
- private String fActual;
-
- /**
- * Constructs a comparison failure.
- * @param message the identifying message or null
- * @param expected the expected string value
- * @param actual the actual string value
- */
- public ComparisonFailure (String message, String expected, String actual) {
- super (message);
- fExpected= expected;
- fActual= actual;
- }
-
- /**
- * Returns "..." in place of common prefix and "..." in
- * place of common suffix between expected and actual.
- *
- * @see Throwable#getMessage()
- */
- @Override
- public String getMessage() {
- return new ComparisonCompactor(MAX_CONTEXT_LENGTH, fExpected, fActual).compact(super.getMessage());
- }
-
- /**
- * Returns the actual string value
- * @return the actual string value
- */
- public String getActual() {
- return fActual;
- }
- /**
- * Returns the expected string value
- * @return the expected string value
- */
- public String getExpected() {
- return fExpected;
- }
-
- private static class ComparisonCompactor {
- private static final String ELLIPSIS= "...";
- private static final String DELTA_END= "]";
- private static final String DELTA_START= "[";
-
- /**
- * The maximum length for expected and actual. When contextLength
- * is exceeded, the Strings are shortened
- */
- private int fContextLength;
- private String fExpected;
- private String fActual;
- private int fPrefix;
- private int fSuffix;
-
- /**
- * @param contextLength the maximum length for expected and actual. When contextLength
- * is exceeded, the Strings are shortened
- * @param expected the expected string value
- * @param actual the actual string value
- */
- public ComparisonCompactor(int contextLength, String expected, String actual) {
- fContextLength= contextLength;
- fExpected= expected;
- fActual= actual;
- }
-
- private String compact(String message) {
- if (fExpected == null || fActual == null || areStringsEqual())
- return Assert.format(message, fExpected, fActual);
-
- findCommonPrefix();
- findCommonSuffix();
- String expected= compactString(fExpected);
- String actual= compactString(fActual);
- return Assert.format(message, expected, actual);
- }
-
- private String compactString(String source) {
- String result= DELTA_START + source.substring(fPrefix, source.length() - fSuffix + 1) + DELTA_END;
- if (fPrefix > 0)
- result= computeCommonPrefix() + result;
- if (fSuffix > 0)
- result= result + computeCommonSuffix();
- return result;
- }
-
- private void findCommonPrefix() {
- fPrefix= 0;
- int end= Math.min(fExpected.length(), fActual.length());
- for (; fPrefix < end; fPrefix++) {
- if (fExpected.charAt(fPrefix) != fActual.charAt(fPrefix))
- break;
- }
- }
-
- private void findCommonSuffix() {
- int expectedSuffix= fExpected.length() - 1;
- int actualSuffix= fActual.length() - 1;
- for (; actualSuffix >= fPrefix && expectedSuffix >= fPrefix; actualSuffix--, expectedSuffix--) {
- if (fExpected.charAt(expectedSuffix) != fActual.charAt(actualSuffix))
- break;
- }
- fSuffix= fExpected.length() - expectedSuffix;
- }
-
- private String computeCommonPrefix() {
- return (fPrefix > fContextLength ? ELLIPSIS : "") + fExpected.substring(Math.max(0, fPrefix - fContextLength), fPrefix);
- }
-
- private String computeCommonSuffix() {
- int end= Math.min(fExpected.length() - fSuffix + 1 + fContextLength, fExpected.length());
- return fExpected.substring(fExpected.length() - fSuffix + 1, end) + (fExpected.length() - fSuffix + 1 < fExpected.length() - fContextLength ? ELLIPSIS : "");
- }
-
- private boolean areStringsEqual() {
- return fExpected.equals(fActual);
- }
- }
-}
\ No newline at end of file
+public class ComparisonFailure extends AssertionError {
+ /**
+ * The maximum length for expected and actual strings. If it is exceeded, the strings should be shortened.
+ *
+ * @see ComparisonCompactor
+ */
+ private static final int MAX_CONTEXT_LENGTH = 20;
+ private static final long serialVersionUID = 1L;
+
+ /*
+ * We have to use the f prefix until the next major release to ensure
+ * serialization compatibility.
+ * See https://github.com/junit-team/junit4/issues/976
+ */
+ private String fExpected;
+ private String fActual;
+
+ /**
+ * Constructs a comparison failure.
+ *
+ * @param message the identifying message or null
+ * @param expected the expected string value
+ * @param actual the actual string value
+ */
+ public ComparisonFailure(String message, String expected, String actual) {
+ super(message);
+ this.fExpected = expected;
+ this.fActual = actual;
+ }
+
+ /**
+ * Returns "..." in place of common prefix and "..." in place of common suffix between expected and actual.
+ *
+ * @see Throwable#getMessage()
+ */
+ @Override
+ public String getMessage() {
+ return new ComparisonCompactor(MAX_CONTEXT_LENGTH, fExpected, fActual).compact(super.getMessage());
+ }
+
+ /**
+ * Returns the actual string value
+ *
+ * @return the actual string value
+ */
+ public String getActual() {
+ return fActual;
+ }
+
+ /**
+ * Returns the expected string value
+ *
+ * @return the expected string value
+ */
+ public String getExpected() {
+ return fExpected;
+ }
+
+ private static class ComparisonCompactor {
+ private static final String ELLIPSIS = "...";
+ private static final String DIFF_END = "]";
+ private static final String DIFF_START = "[";
+
+ /**
+ * The maximum length for expected and actual strings to show. When
+ * contextLength is exceeded, the Strings are shortened.
+ */
+ private final int contextLength;
+ private final String expected;
+ private final String actual;
+
+ /**
+ * @param contextLength the maximum length of context surrounding the difference between the compared strings.
+ * When context length is exceeded, the prefixes and suffixes are compacted.
+ * @param expected the expected string value
+ * @param actual the actual string value
+ */
+ public ComparisonCompactor(int contextLength, String expected, String actual) {
+ this.contextLength = contextLength;
+ this.expected = expected;
+ this.actual = actual;
+ }
+
+ public String compact(String message) {
+ if (expected == null || actual == null || expected.equals(actual)) {
+ return Assert.format(message, expected, actual);
+ } else {
+ DiffExtractor extractor = new DiffExtractor();
+ String compactedPrefix = extractor.compactPrefix();
+ String compactedSuffix = extractor.compactSuffix();
+ return Assert.format(message,
+ compactedPrefix + extractor.expectedDiff() + compactedSuffix,
+ compactedPrefix + extractor.actualDiff() + compactedSuffix);
+ }
+ }
+
+ private String sharedPrefix() {
+ int end = Math.min(expected.length(), actual.length());
+ for (int i = 0; i < end; i++) {
+ if (expected.charAt(i) != actual.charAt(i)) {
+ return expected.substring(0, i);
+ }
+ }
+ return expected.substring(0, end);
+ }
+
+ private String sharedSuffix(String prefix) {
+ int suffixLength = 0;
+ int maxSuffixLength = Math.min(expected.length() - prefix.length(),
+ actual.length() - prefix.length()) - 1;
+ for (; suffixLength <= maxSuffixLength; suffixLength++) {
+ if (expected.charAt(expected.length() - 1 - suffixLength)
+ != actual.charAt(actual.length() - 1 - suffixLength)) {
+ break;
+ }
+ }
+ return expected.substring(expected.length() - suffixLength);
+ }
+
+ private class DiffExtractor {
+ private final String sharedPrefix;
+ private final String sharedSuffix;
+
+ /**
+ * Can not be instantiated outside {@link org.junit.ComparisonFailure.ComparisonCompactor}.
+ */
+ private DiffExtractor() {
+ sharedPrefix = sharedPrefix();
+ sharedSuffix = sharedSuffix(sharedPrefix);
+ }
+
+ public String expectedDiff() {
+ return extractDiff(expected);
+ }
+
+ public String actualDiff() {
+ return extractDiff(actual);
+ }
+
+ public String compactPrefix() {
+ if (sharedPrefix.length() <= contextLength) {
+ return sharedPrefix;
+ }
+ return ELLIPSIS + sharedPrefix.substring(sharedPrefix.length() - contextLength);
+ }
+
+ public String compactSuffix() {
+ if (sharedSuffix.length() <= contextLength) {
+ return sharedSuffix;
+ }
+ return sharedSuffix.substring(0, contextLength) + ELLIPSIS;
+ }
+
+ private String extractDiff(String source) {
+ return DIFF_START + source.substring(sharedPrefix.length(), source.length() - sharedSuffix.length())
+ + DIFF_END;
+ }
+ }
+ }
+}
diff --git a/src/main/java/org/junit/FixMethodOrder.java b/src/main/java/org/junit/FixMethodOrder.java
new file mode 100644
index 000000000000..aaa0313e710c
--- /dev/null
+++ b/src/main/java/org/junit/FixMethodOrder.java
@@ -0,0 +1,41 @@
+package org.junit;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import org.junit.runners.MethodSorters;
+
+/**
+ * This class allows the user to choose the order of execution of the methods within a test class.
+ *
+ *
The default order of execution of JUnit tests within a class is deterministic but not predictable.
+ * The order of execution is not guaranteed for Java 7 (and some previous versions), and can even change
+ * from run to run, so the order of execution was changed to be deterministic (in JUnit 4.11)
+ *
+ *
It is recommended that test methods be written so that they are independent of the order that they are executed.
+ * However, there may be a number of dependent tests either through error or by design.
+ * This class allows the user to specify the order of execution of test methods.
+ *
+ *
For possibilities, see {@link MethodSorters}
+ *
+ * Here is an example:
+ *
+ *
+ * @FixMethodOrder(MethodSorters.NAME_ASCENDING)
+ * public class MyTest {
+ * }
+ *
+ *
+ * @see org.junit.runners.MethodSorters
+ * @since 4.11
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.TYPE})
+public @interface FixMethodOrder {
+ /**
+ * Optionally specify value to have the methods executed in a particular order
+ */
+ MethodSorters value() default MethodSorters.DEFAULT;
+}
diff --git a/src/main/java/org/junit/Ignore.java b/src/main/java/org/junit/Ignore.java
index de530a969b66..db23581073bd 100644
--- a/src/main/java/org/junit/Ignore.java
+++ b/src/main/java/org/junit/Ignore.java
@@ -6,34 +6,35 @@
import java.lang.annotation.Target;
/**
- *
Sometimes you want to temporarily disable a test or a group of tests. Methods annotated with
+ * Sometimes you want to temporarily disable a test or a group of tests. Methods annotated with
* {@link org.junit.Test} that are also annotated with @Ignore will not be executed as tests.
- * Also, you can annotate a class containing test methods with @Ignore and none of the containing
- * tests will be executed. Native JUnit 4 test runners should report the number of ignored tests along with the
- * number of tests that ran and the number of tests that failed.
- *
- * For example:
+ * Also, you can annotate a class containing test methods with @Ignore and none of the containing
+ * tests will be executed. Native JUnit 4 test runners should report the number of ignored tests along with the
+ * number of tests that ran and the number of tests that failed.
+ *
+ *
For example:
*
* @Ignore @Test public void something() { ...
*
- * @Ignore takes an optional default parameter if you want to record why a test is being ignored:
+ * @Ignore takes an optional default parameter if you want to record why a test is being ignored:
*
- * @Ignore can also be applied to the test class:
+ * @Ignore can also be applied to the test class:
*
- * @Ignore public class IgnoreMe {
- * @Test public void test1() { ... }
- * @Test public void test2() { ... }
- * }
+ * @Ignore public class IgnoreMe {
+ * @Test public void test1() { ... }
+ * @Test public void test2() { ... }
+ * }
*
*
+ * @since 4.0
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.TYPE})
public @interface Ignore {
- /**
- * The optional reason why the test is ignored.
- */
- String value() default "";
+ /**
+ * The optional reason why the test is ignored.
+ */
+ String value() default "";
}
diff --git a/src/main/java/org/junit/Rule.java b/src/main/java/org/junit/Rule.java
index ee2f24573589..9370e94f51fc 100644
--- a/src/main/java/org/junit/Rule.java
+++ b/src/main/java/org/junit/Rule.java
@@ -1,16 +1,101 @@
package org.junit;
+import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
-
-import org.junit.rules.MethodRule;
+import java.lang.annotation.Target;
/**
- * Annotates fields that contain rules. Such a field must be public, not
- * static, and a subtype of {@link MethodRule}. For more information,
- * see {@link MethodRule}
+ * Annotates fields that reference rules or methods that return a rule. A field must be public, not
+ * static, and a subtype of {@link org.junit.rules.TestRule} (preferred) or
+ * {@link org.junit.rules.MethodRule}. A method must be public, not static,
+ * and must return a subtype of {@link org.junit.rules.TestRule} (preferred) or
+ * {@link org.junit.rules.MethodRule}.
+ *
+ * The {@link org.junit.runners.model.Statement} passed
+ * 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 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
+ * after Rules defined by methods, i.e. the Statements returned by the former will
+ * be executed around those returned by the latter.
+ *
+ *
Usage
+ *
+ * For example, here is a test class that creates a temporary folder before
+ * each test method, and deletes it after each:
+ *
+ * For more information and more examples, see
+ * {@link org.junit.rules.TestRule}.
+ *
+ *
Ordering
+ *
+ * You can use {@link #order()} if you want to have control over the order in
+ * which the Rules are applied.
+ *
+ *
+ * public class ThreeRules {
+ * @Rule(order = 0)
+ * public LoggingRule outer = new LoggingRule("outer rule");
+ *
+ * @Rule(order = 1)
+ * public LoggingRule middle = new LoggingRule("middle rule");
+ *
+ * @Rule(order = 2)
+ * public LoggingRule inner = new LoggingRule("inner rule");
+ *
+ * // ...
+ * }
+ *
+ *
+ * @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 23dc78ae7e8d..1db6fc7ab073 100644
--- a/src/main/java/org/junit/Test.java
+++ b/src/main/java/org/junit/Test.java
@@ -1,68 +1,117 @@
package org.junit;
+import org.junit.function.ThrowingRunnable;
+
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
- *
The Test annotation tells JUnit that the public void method
+ * The Test annotation tells JUnit that the public void method
* to which it is attached can be run as a test case. To run the method,
* JUnit first constructs a fresh instance of the class then invokes the
* annotated method. Any exceptions thrown by the test will be reported
* by JUnit as a failure. If no exceptions are thrown, the test is assumed
- * to have succeeded.
- *
- *
A simple test looks like this:
+ * to have succeeded.
+ *
+ * A simple test looks like this:
*
* public class Example {
- * @Test
+ * @Test
* public void method() {
* org.junit.Assert.assertTrue( new ArrayList().isEmpty() );
* }
* }
*
- *
- *
- *
The Test annotation supports two optional parameters.
- * The first, expected, declares that a test method should throw
+ *
+ * The Test annotation supports two optional parameters for
+ * exception testing and for limiting test execution time.
+ *
+ *
Exception Testing
+ *
+ * The parameter expected 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:
*
- * @Test(expected=IndexOutOfBoundsException.class) public void outOfBounds() {
+ * @Test(expected=IndexOutOfBoundsException.class)
+ * public void outOfBounds() {
* new ArrayList<Object>().get(1);
* }
- *
- *
- *
The second optional parameter, timeout, causes a test to fail if it takes
+ *
+ *
+ * Using the parameter expected 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 assertThrows the code that throws the exception can be
+ * precisely specified. If the exception's message or one of its properties
+ * should be verified, the ExpectedException rule can be used. Further
+ * information about exception testing can be found at the
+ * JUnit Wiki.
+ *
+ *
Timeout
+ *
+ * The parameter timeout causes a test to fail if it takes
* longer than a specified amount of clock time (measured in milliseconds). The following test fails:
*
+ * Warning: while timeout is useful to catch and terminate
+ * infinite loops, it should not be considered deterministic. The
+ * following test may or may not fail depending on how the operating system
+ * schedules threads:
+ *
+ * THREAD SAFETY WARNING: Test methods with a timeout parameter are run in a thread other than the
+ * thread which runs the fixture's @Before and @After methods. This may yield different behavior for
+ * code that is not thread safe when compared to the same test method without a timeout parameter.
+ * Consider using the {@link org.junit.rules.Timeout} rule instead, which ensures a test method is run on the
+ * same thread as the fixture's @Before and @After methods.
+ *
+ * @since 4.0
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface Test {
-
- /**
- * Default empty exception
- */
- static class None extends Throwable {
- private static final long serialVersionUID= 1L;
- private None() {
- }
- }
-
- /**
- * Optionally specify expected, a Throwable, to cause a test method to succeed iff
- * an exception of the specified class is thrown by the method.
- */
- Class extends Throwable> expected() default None.class;
-
- /**
- * Optionally specify timeout in milliseconds to cause a test method to fail if it
- * takes longer than that number of milliseconds.*/
- long timeout() default 0L;
+
+ /**
+ * Default empty exception.
+ */
+ static class None extends Throwable {
+ private static final long serialVersionUID = 1L;
+
+ private None() {
+ }
+ }
+
+ /**
+ * Optionally specify expected, a Throwable, to cause a test method to succeed if
+ * and only if an exception of the specified class is thrown by the method. If the Throwable's
+ * message or one of its properties should be verified, the
+ * {@link org.junit.rules.ExpectedException ExpectedException} rule can be used instead.
+ */
+ Class extends Throwable> expected() default None.class;
+
+ /**
+ * Optionally specify timeout in milliseconds to cause a test method to fail if it
+ * takes longer than that number of milliseconds.
+ *
+ * THREAD SAFETY WARNING: Test methods with a timeout parameter are run in a thread other than the
+ * thread which runs the fixture's @Before and @After methods. This may yield different behavior for
+ * code that is not thread safe when compared to the same test method without a timeout parameter.
+ * Consider using the {@link org.junit.rules.Timeout} rule instead, which ensures a test method is run on the
+ * same thread as the fixture's @Before and @After methods.
+ *
+ */
+ long timeout() default 0L;
}
diff --git a/src/main/java/org/junit/TestCouldNotBeSkippedException.java b/src/main/java/org/junit/TestCouldNotBeSkippedException.java
new file mode 100644
index 000000000000..4804493290ef
--- /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/ParallelComputer.java b/src/main/java/org/junit/experimental/ParallelComputer.java
index fccb97c2e469..97da0f759f48 100644
--- a/src/main/java/org/junit/experimental/ParallelComputer.java
+++ b/src/main/java/org/junit/experimental/ParallelComputer.java
@@ -1,11 +1,8 @@
package org.junit.experimental;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
-import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
import org.junit.runner.Computer;
import org.junit.runner.Runner;
@@ -15,64 +12,56 @@
import org.junit.runners.model.RunnerScheduler;
public class ParallelComputer extends Computer {
- private final boolean fClasses;
+ private final boolean classes;
- private final boolean fMethods;
+ private final boolean methods;
- public ParallelComputer(boolean classes, boolean methods) {
- fClasses= classes;
- fMethods= methods;
- }
+ public ParallelComputer(boolean classes, boolean methods) {
+ this.classes = classes;
+ this.methods = methods;
+ }
- public static Computer classes() {
- return new ParallelComputer(true, false);
- }
+ public static Computer classes() {
+ return new ParallelComputer(true, false);
+ }
- public static Computer methods() {
- return new ParallelComputer(false, true);
- }
+ public static Computer methods() {
+ return new ParallelComputer(false, true);
+ }
- private static Runner parallelize(Runner runner) {
- if (runner instanceof ParentRunner>) {
- ((ParentRunner>) runner).setScheduler(new RunnerScheduler() {
- private final List> fResults= new ArrayList>();
+ private static Runner parallelize(Runner runner) {
+ if (runner instanceof ParentRunner) {
+ ((ParentRunner>) runner).setScheduler(new RunnerScheduler() {
+ private final ExecutorService fService = Executors.newCachedThreadPool();
- private final ExecutorService fService= Executors
- .newCachedThreadPool();
+ public void schedule(Runnable childStatement) {
+ fService.submit(childStatement);
+ }
- public void schedule(final Runnable childStatement) {
- fResults.add(fService.submit(new Callable() {
- public Object call() throws Exception {
- childStatement.run();
- return null;
- }
- }));
- }
+ public void finished() {
+ try {
+ fService.shutdown();
+ fService.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
+ } catch (InterruptedException e) {
+ e.printStackTrace(System.err);
+ }
+ }
+ });
+ }
+ return runner;
+ }
- public void finished() {
- for (Future each : fResults)
- try {
- each.get();
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- });
- }
- return runner;
- }
+ @Override
+ public Runner getSuite(RunnerBuilder builder, java.lang.Class>[] classes)
+ throws InitializationError {
+ Runner suite = super.getSuite(builder, classes);
+ return this.classes ? parallelize(suite) : suite;
+ }
- @Override
- public Runner getSuite(RunnerBuilder builder, java.lang.Class>[] classes)
- throws InitializationError {
- Runner suite= super.getSuite(builder, classes);
- return fClasses ? parallelize(suite) : suite;
- }
-
- @Override
- protected Runner getRunner(RunnerBuilder builder, Class> testClass)
- throws Throwable {
- Runner runner= super.getRunner(builder, testClass);
- return fMethods ? parallelize(runner) : runner;
- }
+ @Override
+ protected Runner getRunner(RunnerBuilder builder, Class> testClass)
+ throws Throwable {
+ Runner runner = super.getRunner(builder, testClass);
+ return methods ? parallelize(runner) : runner;
+ }
}
diff --git a/src/main/java/org/junit/experimental/categories/Categories.java b/src/main/java/org/junit/experimental/categories/Categories.java
new file mode 100644
index 000000000000..0c73ed82afff
--- /dev/null
+++ b/src/main/java/org/junit/experimental/categories/Categories.java
@@ -0,0 +1,375 @@
+package org.junit.experimental.categories;
+
+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;
+import org.junit.runner.manipulation.Filter;
+import org.junit.runner.manipulation.NoTestsRemainException;
+import org.junit.runners.Suite;
+import org.junit.runners.model.InitializationError;
+import org.junit.runners.model.RunnerBuilder;
+
+/**
+ * From a given set of test classes, runs only the classes and methods that are
+ * annotated with either the category given with the @IncludeCategory
+ * annotation, or a subtype of that category.
+ *
+ * Note that, for now, annotating suites with {@code @Category} has no effect.
+ * Categories must be annotated on the direct method or class.
+ *
+ * Example:
+ *
+ * public interface FastTests {
+ * }
+ *
+ * public interface SlowTests {
+ * }
+ *
+ * public interface SmokeTests
+ * }
+ *
+ * public static class A {
+ * @Test
+ * public void a() {
+ * fail();
+ * }
+ *
+ * @Category(SlowTests.class)
+ * @Test
+ * public void b() {
+ * }
+ *
+ * @Category({FastTests.class, SmokeTests.class})
+ * @Test
+ * public void c() {
+ * }
+ * }
+ *
+ * @Category({SlowTests.class, FastTests.class})
+ * public static class B {
+ * @Test
+ * public void d() {
+ * }
+ * }
+ *
+ * @RunWith(Categories.class)
+ * @IncludeCategory(SlowTests.class)
+ * @SuiteClasses({A.class, B.class})
+ * // Note that Categories is a kind of Suite
+ * public static class SlowTestSuite {
+ * // Will run A.b and B.d, but not A.a and A.c
+ * }
+ *
+ *
+ * Example to run multiple categories:
+ *
+ * @RunWith(Categories.class)
+ * @IncludeCategory({FastTests.class, SmokeTests.class})
+ * @SuiteClasses({A.class, B.class})
+ * public static class FastOrSmokeTestSuite {
+ * // Will run A.c and B.d, but not A.b because it is not any of FastTests or SmokeTests
+ * }
+ *
+ *
+ * @version 4.12
+ * @see Categories at JUnit wiki
+ */
+public class Categories extends Suite {
+
+ @Retention(RetentionPolicy.RUNTIME)
+ public @interface IncludeCategory {
+ /**
+ * 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}.
+ */
+ Class>[] value() default {};
+
+ /**
+ * If true, runs tests annotated with any of the categories in
+ * {@link IncludeCategory#value()}. Otherwise, runs tests only if annotated with all of the categories.
+ */
+ boolean matchAny() default true;
+ }
+
+ @Retention(RetentionPolicy.RUNTIME)
+ public @interface ExcludeCategory {
+ /**
+ * 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()}.
+ */
+ Class>[] value() default {};
+
+ /**
+ * If true, the tests annotated with any of the categories in {@link ExcludeCategory#value()}
+ * do not run. Otherwise, the tests do not run if and only if annotated with all categories.
+ */
+ boolean matchAny() default true;
+ }
+
+ public static class CategoryFilter extends Filter {
+ private final Set> included;
+ private final Set> excluded;
+ private final boolean includedAny;
+ private final boolean excludedAny;
+
+ public static CategoryFilter include(boolean matchAny, Class>... categories) {
+ return new CategoryFilter(matchAny, categories, true, null);
+ }
+
+ public static CategoryFilter include(Class> category) {
+ return include(true, category);
+ }
+
+ public static CategoryFilter include(Class>... categories) {
+ return include(true, categories);
+ }
+
+ public static CategoryFilter exclude(boolean matchAny, Class>... categories) {
+ return new CategoryFilter(true, null, matchAny, categories);
+ }
+
+ public static CategoryFilter exclude(Class> category) {
+ return exclude(true, category);
+ }
+
+ public static CategoryFilter exclude(Class>... categories) {
+ return exclude(true, categories);
+ }
+
+ public static CategoryFilter categoryFilter(boolean matchAnyInclusions, Set> inclusions,
+ boolean matchAnyExclusions, Set> exclusions) {
+ 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> includes,
+ boolean matchAnyExcludes, Set> 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()
+ */
+ @Override
+ public String describe() {
+ return toString();
+ }
+
+ /**
+ * Returns string in the form "[included categories] - [excluded categories]", where both
+ * sets have comma separated names of categories.
+ *
+ * @return string representation for the relative complement of excluded categories set
+ * in the set of included categories. Examples:
+ *
+ *
"categories [all]" for all included categories and no excluded ones;
+ *
"categories [all] - [A, B]" for all included categories and given excluded ones;
+ *
"categories [A, B] - [C, D]" for given included categories and given excluded ones.
+ *
+ * @see Class#toString() name of category
+ */
+ @Override public String toString() {
+ StringBuilder description= new StringBuilder("categories ")
+ .append(included.isEmpty() ? "[all]" : included);
+ if (!excluded.isEmpty()) {
+ description.append(" - ").append(excluded);
+ }
+ return description.toString();
+ }
+
+ @Override
+ public boolean shouldRun(Description description) {
+ if (hasCorrectCategoryAnnotation(description)) {
+ return true;
+ }
+
+ for (Description each : description.getChildren()) {
+ if (shouldRun(each)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ private boolean hasCorrectCategoryAnnotation(Description description) {
+ final Set> childCategories= categories(description);
+
+ // If a child has no categories, immediately return.
+ if (childCategories.isEmpty()) {
+ return included.isEmpty();
+ }
+
+ if (!excluded.isEmpty()) {
+ if (excludedAny) {
+ if (matchesAnyParentCategories(childCategories, excluded)) {
+ return false;
+ }
+ } else {
+ if (matchesAllParentCategories(childCategories, excluded)) {
+ return false;
+ }
+ }
+ }
+
+ if (included.isEmpty()) {
+ // Couldn't be excluded, and with no suite's included categories treated as should run.
+ return true;
+ } else {
+ if (includedAny) {
+ return matchesAnyParentCategories(childCategories, included);
+ } else {
+ return matchesAllParentCategories(childCategories, included);
+ }
+ }
+ }
+
+ /**
+ * @return true if at least one (any) parent category match a child, otherwise false.
+ * If empty parentCategories, returns false.
+ */
+ private boolean matchesAnyParentCategories(Set> childCategories, Set> parentCategories) {
+ for (Class> parentCategory : parentCategories) {
+ if (hasAssignableTo(childCategories, parentCategory)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * @return false if at least one parent category does not match children, otherwise true.
+ * If empty parentCategories, returns true.
+ */
+ private boolean matchesAllParentCategories(Set> childCategories, Set> parentCategories) {
+ for (Class> parentCategory : parentCategories) {
+ if (!hasAssignableTo(childCategories, parentCategory)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private static Set> categories(Description description) {
+ Set> categories= new HashSet>();
+ Collections.addAll(categories, directCategories(description));
+ Collections.addAll(categories, directCategories(parentDescription(description)));
+ return categories;
+ }
+
+ private static Description parentDescription(Description description) {
+ Class> testClass= description.getTestClass();
+ return testClass == null ? null : Description.createSuiteDescription(testClass);
+ }
+
+ private static Class>[] directCategories(Description description) {
+ if (description == null) {
+ return new Class>[0];
+ }
+
+ Category annotation= description.getAnnotation(Category.class);
+ return annotation == null ? new Class>[0] : annotation.value();
+ }
+
+ private static Set> copyAndRefine(Set> classes) {
+ Set> c= new LinkedHashSet>();
+ if (classes != null) {
+ c.addAll(classes);
+ }
+ c.remove(null);
+ return c;
+ }
+ }
+
+ public Categories(Class> klass, RunnerBuilder builder) throws InitializationError {
+ super(klass, builder);
+ try {
+ Set> included= getIncludedCategory(klass);
+ Set> excluded= getExcludedCategory(klass);
+ boolean isAnyIncluded= isAnyIncluded(klass);
+ boolean isAnyExcluded= isAnyExcluded(klass);
+
+ filter(CategoryFilter.categoryFilter(isAnyIncluded, included, isAnyExcluded, excluded));
+ } catch (NoTestsRemainException e) {
+ throw new InitializationError(e);
+ }
+ }
+
+ private static Set> getIncludedCategory(Class> klass) {
+ IncludeCategory annotation= klass.getAnnotation(IncludeCategory.class);
+ return createSet(annotation == null ? null : annotation.value());
+ }
+
+ private static boolean isAnyIncluded(Class> klass) {
+ IncludeCategory annotation= klass.getAnnotation(IncludeCategory.class);
+ return annotation == null || annotation.matchAny();
+ }
+
+ private static Set> getExcludedCategory(Class> klass) {
+ ExcludeCategory annotation= klass.getAnnotation(ExcludeCategory.class);
+ return createSet(annotation == null ? null : annotation.value());
+ }
+
+ private static boolean isAnyExcluded(Class> klass) {
+ ExcludeCategory annotation= klass.getAnnotation(ExcludeCategory.class);
+ return annotation == null || annotation.matchAny();
+ }
+
+ private static boolean hasAssignableTo(Set> assigns, Class> to) {
+ for (final Class> from : assigns) {
+ if (to.isAssignableFrom(from)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private static Set> 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();
+ }
+ for (Class> category : classes) {
+ if (category == null) {
+ throw new NullPointerException("has null category");
+ }
+ }
+
+ return classes.length == 1
+ ? Collections.>singleton(classes[0])
+ : new LinkedHashSet>(Arrays.asList(classes));
+ }
+
+ private static Set> 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.>emptySet()
+ : Collections.>singleton(nullableClass);
+ }
+}
diff --git a/src/main/java/org/junit/experimental/categories/Category.java b/src/main/java/org/junit/experimental/categories/Category.java
new file mode 100644
index 000000000000..8eae83677c94
--- /dev/null
+++ b/src/main/java/org/junit/experimental/categories/Category.java
@@ -0,0 +1,48 @@
+package org.junit.experimental.categories;
+
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+import org.junit.validator.ValidateWith;
+
+/**
+ * Marks a test class or test method as belonging to one or more categories of tests.
+ * The value is an array of arbitrary classes.
+ *
+ * This annotation is only interpreted by the Categories runner (at present).
+ *
+ * For example:
+ *
+ * public interface FastTests {}
+ * public interface SlowTests {}
+ *
+ * public static class A {
+ * @Test
+ * public void a() {
+ * fail();
+ * }
+ *
+ * @Category(SlowTests.class)
+ * @Test
+ * public void b() {
+ * }
+ * }
+ *
+ * @Category({SlowTests.class, FastTests.class})
+ * public static class B {
+ * @Test
+ * public void c() {
+ *
+ * }
+ * }
+ *
+ *
+ * For more usage, see code example on {@link Categories}.
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Inherited
+@ValidateWith(CategoryValidator.class)
+public @interface Category {
+ Class>[] value();
+}
\ No newline at end of file
diff --git a/src/main/java/org/junit/experimental/categories/CategoryFilterFactory.java b/src/main/java/org/junit/experimental/categories/CategoryFilterFactory.java
new file mode 100644
index 000000000000..e9bdab77e502
--- /dev/null
+++ b/src/main/java/org/junit/experimental/categories/CategoryFilterFactory.java
@@ -0,0 +1,51 @@
+package org.junit.experimental.categories;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.internal.Classes;
+import org.junit.runner.FilterFactory;
+import org.junit.runner.FilterFactoryParams;
+import org.junit.runner.manipulation.Filter;
+
+/**
+ * Implementation of FilterFactory for Category filtering.
+ */
+abstract class CategoryFilterFactory implements FilterFactory {
+ /**
+ * Creates a {@link org.junit.experimental.categories.Categories.CategoryFilter} given a
+ * {@link FilterFactoryParams} argument.
+ *
+ * @param params Parameters needed to create the {@link Filter}
+ */
+ public Filter createFilter(FilterFactoryParams params) throws FilterNotCreatedException {
+ try {
+ return createFilter(parseCategories(params.getArgs()));
+ } catch (ClassNotFoundException e) {
+ throw new FilterNotCreatedException(e);
+ }
+ }
+
+ /**
+ * Creates a {@link org.junit.experimental.categories.Categories.CategoryFilter} given an array of classes.
+ *
+ * @param categories Category classes.
+ */
+ protected abstract Filter createFilter(List> categories);
+
+ private List> parseCategories(String categories) throws ClassNotFoundException {
+ List> categoryClasses = new ArrayList>();
+
+ for (String category : categories.split(",")) {
+ /*
+ * 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);
+ }
+
+ return categoryClasses;
+ }
+}
diff --git a/src/main/java/org/junit/experimental/categories/CategoryValidator.java b/src/main/java/org/junit/experimental/categories/CategoryValidator.java
new file mode 100644
index 000000000000..491d8accb586
--- /dev/null
+++ b/src/main/java/org/junit/experimental/categories/CategoryValidator.java
@@ -0,0 +1,62 @@
+package org.junit.experimental.categories;
+
+import static java.util.Arrays.asList;
+import static java.util.Collections.unmodifiableList;
+import static java.util.Collections.unmodifiableSet;
+
+import java.lang.annotation.Annotation;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.runners.model.FrameworkMethod;
+import org.junit.validator.AnnotationValidator;
+
+/**
+ * Validates that there are no errors in the use of the {@code Category}
+ * annotation. If there is, a {@code Throwable} object will be added to the list
+ * of errors.
+ *
+ * @since 4.12
+ */
+public final class CategoryValidator extends AnnotationValidator {
+
+ @SuppressWarnings("unchecked")
+ private static final Set> INCOMPATIBLE_ANNOTATIONS = unmodifiableSet(new HashSet>(
+ asList(BeforeClass.class, AfterClass.class, Before.class, After.class)));
+
+ /**
+ * Adds to {@code errors} a throwable for each problem detected. Looks for
+ * {@code BeforeClass}, {@code AfterClass}, {@code Before} and {@code After}
+ * annotations.
+ *
+ * @param method the method that is being validated
+ * @return A list of exceptions detected
+ *
+ * @since 4.12
+ */
+ @Override
+ public List validateAnnotatedMethod(FrameworkMethod method) {
+ List errors = new ArrayList();
+ Annotation[] annotations = method.getAnnotations();
+ for (Annotation annotation : annotations) {
+ for (Class> clazz : INCOMPATIBLE_ANNOTATIONS) {
+ if (annotation.annotationType().isAssignableFrom(clazz)) {
+ addErrorMessage(errors, clazz);
+ }
+ }
+ }
+ return unmodifiableList(errors);
+ }
+
+ private void addErrorMessage(List errors, Class> clazz) {
+ String message = String.format("@%s can not be combined with @Category",
+ clazz.getSimpleName());
+ errors.add(new Exception(message));
+ }
+}
diff --git a/src/main/java/org/junit/experimental/categories/ExcludeCategories.java b/src/main/java/org/junit/experimental/categories/ExcludeCategories.java
new file mode 100644
index 000000000000..8ccb6b5eec04
--- /dev/null
+++ b/src/main/java/org/junit/experimental/categories/ExcludeCategories.java
@@ -0,0 +1,52 @@
+package org.junit.experimental.categories;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.junit.experimental.categories.Categories.CategoryFilter;
+import org.junit.runner.manipulation.Filter;
+
+/**
+ * {@link org.junit.runner.FilterFactory} to exclude categories.
+ *
+ * The {@link Filter} that is created will filter out tests that are categorized with any of the
+ * given categories.
+ *
+ * Usage from command line:
+ *
+ * --filter=org.junit.experimental.categories.ExcludeCategories=pkg.of.Cat1,pkg.of.Cat2
+ *
+ *
+ * Usage from API:
+ *
+ * new ExcludeCategories().createFilter(Cat1.class, Cat2.class);
+ *
+ */
+public final class ExcludeCategories extends CategoryFilterFactory {
+ /**
+ * Creates a {@link Filter} which is only passed by tests that are
+ * not categorized with any of the specified categories.
+ *
+ * @param categories Category classes.
+ */
+ @Override
+ protected Filter createFilter(List> categories) {
+ return new ExcludesAny(categories);
+ }
+
+ private static class ExcludesAny extends CategoryFilter {
+ public ExcludesAny(List> categories) {
+ this(new HashSet>(categories));
+ }
+
+ public ExcludesAny(Set> categories) {
+ super(true, null, true, categories);
+ }
+
+ @Override
+ public String describe() {
+ return "excludes " + super.describe();
+ }
+ }
+}
diff --git a/src/main/java/org/junit/experimental/categories/IncludeCategories.java b/src/main/java/org/junit/experimental/categories/IncludeCategories.java
new file mode 100644
index 000000000000..38eb6934c812
--- /dev/null
+++ b/src/main/java/org/junit/experimental/categories/IncludeCategories.java
@@ -0,0 +1,52 @@
+package org.junit.experimental.categories;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.junit.experimental.categories.Categories.CategoryFilter;
+import org.junit.runner.manipulation.Filter;
+
+/**
+ * {@link org.junit.runner.FilterFactory} to include categories.
+ *
+ * The {@link Filter} that is created will filter out tests that are categorized with any of the
+ * given categories.
+ *
+ * Usage from command line:
+ *
+ * --filter=org.junit.experimental.categories.IncludeCategories=pkg.of.Cat1,pkg.of.Cat2
+ *
+ *
+ * Usage from API:
+ *
+ * new IncludeCategories().createFilter(Cat1.class, Cat2.class);
+ *
+ */
+public final class IncludeCategories extends CategoryFilterFactory {
+ /**
+ * Creates a {@link Filter} which is only passed by tests that are
+ * categorized with any of the specified categories.
+ *
+ * @param categories Category classes.
+ */
+ @Override
+ protected Filter createFilter(List> categories) {
+ return new IncludesAny(categories);
+ }
+
+ private static class IncludesAny extends CategoryFilter {
+ public IncludesAny(List> categories) {
+ this(new HashSet>(categories));
+ }
+
+ public IncludesAny(Set> categories) {
+ super(true, categories, true, null);
+ }
+
+ @Override
+ public String describe() {
+ return "includes " + super.describe();
+ }
+ }
+}
diff --git a/src/main/java/org/junit/experimental/max/CouldNotReadCoreException.java b/src/main/java/org/junit/experimental/max/CouldNotReadCoreException.java
index 03c3c8cb3e27..116d7559d049 100644
--- a/src/main/java/org/junit/experimental/max/CouldNotReadCoreException.java
+++ b/src/main/java/org/junit/experimental/max/CouldNotReadCoreException.java
@@ -4,12 +4,12 @@
* Thrown when Max cannot read the MaxCore serialization
*/
public class CouldNotReadCoreException extends Exception {
- private static final long serialVersionUID= 1L;
+ private static final long serialVersionUID = 1L;
- /**
- * Constructs
- */
- public CouldNotReadCoreException(Throwable e) {
- super(e);
- }
+ /**
+ * Constructs
+ */
+ public CouldNotReadCoreException(Throwable e) {
+ super(e);
+ }
}
diff --git a/src/main/java/org/junit/experimental/max/MaxCore.java b/src/main/java/org/junit/experimental/max/MaxCore.java
index a2a34a97ef92..625cade5b1ea 100644
--- a/src/main/java/org/junit/experimental/max/MaxCore.java
+++ b/src/main/java/org/junit/experimental/max/MaxCore.java
@@ -6,7 +6,6 @@
import java.util.List;
import junit.framework.TestSuite;
-
import org.junit.internal.requests.SortingRequest;
import org.junit.internal.runners.ErrorReportingRunner;
import org.junit.internal.runners.JUnit38ClassRunner;
@@ -21,150 +20,162 @@
/**
* A replacement for JUnitCore, which keeps track of runtime and failure history, and reorders tests
* to maximize the chances that a failing test occurs early in the test run.
- *
+ *
* The rules for sorting are:
*
*
Never-run tests first, in arbitrary order
*
Group remaining tests by the date at which they most recently failed.
*
Sort groups such that the most recent failure date is first, and never-failing tests are at the end.
- *
Within a group, run the fastest tests first.
+ *
Within a group, run the fastest tests first.
*
*/
public class MaxCore {
- private static final String MALFORMED_JUNIT_3_TEST_CLASS_PREFIX= "malformed JUnit 3 test class: ";
-
- /**
- * Create a new MaxCore from a serialized file stored at storedResults
- * @deprecated use storedLocally()
- */
- @Deprecated
- public static MaxCore forFolder(String folderName) {
- return storedLocally(new File(folderName));
- }
-
- /**
- * Create a new MaxCore from a serialized file stored at storedResults
- */
- public static MaxCore storedLocally(File storedResults) {
- return new MaxCore(storedResults);
- }
-
- private final MaxHistory fHistory;
-
- private MaxCore(File storedResults) {
- fHistory = MaxHistory.forFolder(storedResults);
- }
-
- /**
- * Run all the tests in class.
- * @return a {@link Result} describing the details of the test run and the failed tests.
- */
- public Result run(Class> testClass) {
- return run(Request.aClass(testClass));
- }
-
- /**
- * Run all the tests contained in request.
- * @param request the request describing tests
- * @return a {@link Result} describing the details of the test run and the failed tests.
- */
- public Result run(Request request) {
- return run(request, new JUnitCore());
- }
-
- /**
- * Run all the tests contained in request.
- *
- * This variant should be used if {@code core} has attached listeners that this
- * run should notify.
- *
- * @param request the request describing tests
- * @param core a JUnitCore to delegate to.
- * @return a {@link Result} describing the details of the test run and the failed tests.
- */
- public Result run(Request request, JUnitCore core) {
- core.addListener(fHistory.listener());
- return core.run(sortRequest(request).getRunner());
- }
-
- /**
- * @param request
- * @return a new Request, which contains all of the same tests, but in a new order.
- */
- public Request sortRequest(Request request) {
- if (request instanceof SortingRequest) // We'll pay big karma points for this
- return request;
- List leaves= findLeaves(request);
- Collections.sort(leaves, fHistory.testComparator());
- return constructLeafRequest(leaves);
- }
-
- private Request constructLeafRequest(List leaves) {
- final List runners = new ArrayList();
- for (Description each : leaves)
- runners.add(buildRunner(each));
- return new Request() {
- @Override
- public Runner getRunner() {
- try {
- return new Suite((Class>)null, runners) {};
- } catch (InitializationError e) {
- return new ErrorReportingRunner(null, e);
- }
- }
- };
- }
-
- private Runner buildRunner(Description each) {
- if (each.toString().equals("TestSuite with 0 tests"))
- return Suite.emptySuite();
- if (each.toString().startsWith(MALFORMED_JUNIT_3_TEST_CLASS_PREFIX))
- // This is cheating, because it runs the whole class
- // to get the warning for this method, but we can't do better,
- // because JUnit 3.8's
- // thrown away which method the warning is for.
- return new JUnit38ClassRunner(new TestSuite(getMalformedTestClass(each)));
- Class> type= each.getTestClass();
- if (type == null)
- throw new RuntimeException("Can't build a runner from description [" + each + "]");
- String methodName= each.getMethodName();
- if (methodName == null)
- return Request.aClass(type).getRunner();
- return Request.method(type, methodName).getRunner();
- }
-
- private Class> getMalformedTestClass(Description each) {
- try {
- return Class.forName(each.toString().replace(MALFORMED_JUNIT_3_TEST_CLASS_PREFIX, ""));
- } catch (ClassNotFoundException e) {
- return null;
- }
- }
-
- /**
- * @param request a request to run
- * @return a list of method-level tests to run, sorted in the order
- * specified in the class comment.
- */
- public List sortedLeavesForTest(Request request) {
- return findLeaves(sortRequest(request));
- }
-
- private List findLeaves(Request request) {
- List results= new ArrayList();
- findLeaves(null, request.getRunner().getDescription(), results);
- return results;
- }
-
- private void findLeaves(Description parent, Description description, List results) {
- if (description.getChildren().isEmpty())
- if (description.toString().equals("warning(junit.framework.TestSuite$1)"))
- results.add(Description.createSuiteDescription(MALFORMED_JUNIT_3_TEST_CLASS_PREFIX + parent));
- else
- results.add(description);
- else
- for (Description each : description.getChildren())
- findLeaves(description, each, results);
- }
-}
+ private static final String MALFORMED_JUNIT_3_TEST_CLASS_PREFIX = "malformed JUnit 3 test class: ";
+
+ /**
+ * Create a new MaxCore from a serialized file stored at storedResults
+ *
+ * @deprecated use storedLocally()
+ */
+ @Deprecated
+ public static MaxCore forFolder(String folderName) {
+ return storedLocally(new File(folderName));
+ }
+
+ /**
+ * Create a new MaxCore from a serialized file stored at storedResults
+ */
+ public static MaxCore storedLocally(File storedResults) {
+ return new MaxCore(storedResults);
+ }
+
+ private final MaxHistory history;
+
+ private MaxCore(File storedResults) {
+ history = MaxHistory.forFolder(storedResults);
+ }
+
+ /**
+ * Run all the tests in class.
+ *
+ * @return a {@link Result} describing the details of the test run and the failed tests.
+ */
+ public Result run(Class> testClass) {
+ return run(Request.aClass(testClass));
+ }
+
+ /**
+ * Run all the tests contained in request.
+ *
+ * @param request the request describing tests
+ * @return a {@link Result} describing the details of the test run and the failed tests.
+ */
+ public Result run(Request request) {
+ return run(request, new JUnitCore());
+ }
+
+ /**
+ * Run all the tests contained in request.
+ *
+ * This variant should be used if {@code core} has attached listeners that this
+ * run should notify.
+ *
+ * @param request the request describing tests
+ * @param core a JUnitCore to delegate to.
+ * @return a {@link Result} describing the details of the test run and the failed tests.
+ */
+ public Result run(Request request, JUnitCore core) {
+ core.addListener(history.listener());
+ return core.run(sortRequest(request).getRunner());
+ }
+
+ /**
+ * @return a new Request, which contains all of the same tests, but in a new order.
+ */
+ public Request sortRequest(Request request) {
+ if (request instanceof SortingRequest) {
+ // We'll pay big karma points for this
+ return request;
+ }
+ List leaves = findLeaves(request);
+ Collections.sort(leaves, history.testComparator());
+ return constructLeafRequest(leaves);
+ }
+
+ private Request constructLeafRequest(List leaves) {
+ final List runners = new ArrayList();
+ for (Description each : leaves) {
+ runners.add(buildRunner(each));
+ }
+ return new Request() {
+ @Override
+ public Runner getRunner() {
+ try {
+ return new Suite((Class>) null, runners) {
+ };
+ } catch (InitializationError e) {
+ return new ErrorReportingRunner(null, e);
+ }
+ }
+ };
+ }
+
+ private Runner buildRunner(Description each) {
+ if (each.toString().equals("TestSuite with 0 tests")) {
+ return Suite.emptySuite();
+ }
+ if (each.toString().startsWith(MALFORMED_JUNIT_3_TEST_CLASS_PREFIX)) {
+ // This is cheating, because it runs the whole class
+ // to get the warning for this method, but we can't do better,
+ // because JUnit 3.8's
+ // thrown away which method the warning is for.
+ return new JUnit38ClassRunner(new TestSuite(getMalformedTestClass(each)));
+ }
+ Class> type = each.getTestClass();
+ if (type == null) {
+ throw new RuntimeException("Can't build a runner from description [" + each + "]");
+ }
+ String methodName = each.getMethodName();
+ if (methodName == null) {
+ return Request.aClass(type).getRunner();
+ }
+ return Request.method(type, methodName).getRunner();
+ }
+
+ private Class> getMalformedTestClass(Description each) {
+ try {
+ return Class.forName(each.toString().replace(MALFORMED_JUNIT_3_TEST_CLASS_PREFIX, ""));
+ } catch (ClassNotFoundException e) {
+ return null;
+ }
+ }
+
+ /**
+ * @param request a request to run
+ * @return a list of method-level tests to run, sorted in the order
+ * specified in the class comment.
+ */
+ public List sortedLeavesForTest(Request request) {
+ return findLeaves(sortRequest(request));
+ }
+
+ private List findLeaves(Request request) {
+ List results = new ArrayList();
+ findLeaves(null, request.getRunner().getDescription(), results);
+ return results;
+ }
+ private void findLeaves(Description parent, Description description, List results) {
+ if (description.getChildren().isEmpty()) {
+ if (description.toString().equals("warning(junit.framework.TestSuite$1)")) {
+ results.add(Description.createSuiteDescription(MALFORMED_JUNIT_3_TEST_CLASS_PREFIX + parent));
+ } else {
+ results.add(description);
+ }
+ } else {
+ for (Description each : description.getChildren()) {
+ findLeaves(description, each, results);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/org/junit/experimental/max/MaxHistory.java b/src/main/java/org/junit/experimental/max/MaxHistory.java
index e091793f90d3..ab7443f38535 100644
--- a/src/main/java/org/junit/experimental/max/MaxHistory.java
+++ b/src/main/java/org/junit/experimental/max/MaxHistory.java
@@ -24,143 +24,155 @@
*
*/
public class MaxHistory implements Serializable {
- private static final long serialVersionUID= 1L;
-
- /**
- * Loads a {@link MaxHistory} from {@code file}, or generates a new one that
- * will be saved to {@code file}.
- */
- public static MaxHistory forFolder(File file) {
- if (file.exists())
- try {
- return readHistory(file);
- } catch (CouldNotReadCoreException e) {
- e.printStackTrace();
- file.delete();
- }
- return new MaxHistory(file);
- }
-
- private static MaxHistory readHistory(File storedResults)
- throws CouldNotReadCoreException {
- try {
- FileInputStream file= new FileInputStream(storedResults);
- try {
- ObjectInputStream stream= new ObjectInputStream(file);
- try {
- return (MaxHistory) stream.readObject();
- } finally {
- stream.close();
- }
- } finally {
- file.close();
- }
- } catch (Exception e) {
- throw new CouldNotReadCoreException(e);
- }
- }
-
- private final Map fDurations= new HashMap();
-
- private final Map fFailureTimestamps= new HashMap();
-
- private final File fHistoryStore;
-
- private MaxHistory(File storedResults) {
- fHistoryStore= storedResults;
- }
-
- private void save() throws IOException {
- ObjectOutputStream stream= new ObjectOutputStream(new FileOutputStream(
- fHistoryStore));
- stream.writeObject(this);
- stream.close();
- }
-
- Long getFailureTimestamp(Description key) {
- return fFailureTimestamps.get(key.toString());
- }
-
- void putTestFailureTimestamp(Description key, long end) {
- fFailureTimestamps.put(key.toString(), end);
- }
-
- boolean isNewTest(Description key) {
- return !fDurations.containsKey(key.toString());
- }
-
- Long getTestDuration(Description key) {
- return fDurations.get(key.toString());
- }
-
- void putTestDuration(Description description, long duration) {
- fDurations.put(description.toString(), duration);
- }
-
- private final class RememberingListener extends RunListener {
- private long overallStart= System.currentTimeMillis();
-
- private Map starts= new HashMap();
-
- @Override
- public void testStarted(Description description) throws Exception {
- starts.put(description, System.nanoTime()); // Get most accurate
- // possible time
- }
-
- @Override
- public void testFinished(Description description) throws Exception {
- long end= System.nanoTime();
- long start= starts.get(description);
- putTestDuration(description, end - start);
- }
-
- @Override
- public void testFailure(Failure failure) throws Exception {
- putTestFailureTimestamp(failure.getDescription(), overallStart);
- }
-
- @Override
- public void testRunFinished(Result result) throws Exception {
- save();
- }
- }
-
- private class TestComparator implements Comparator {
- public int compare(Description o1, Description o2) {
- // Always prefer new tests
- if (isNewTest(o1))
- return -1;
- if (isNewTest(o2))
- return 1;
- // Then most recently failed first
- int result= getFailure(o2).compareTo(getFailure(o1));
- return result != 0 ? result
- // Then shorter tests first
- : getTestDuration(o1).compareTo(getTestDuration(o2));
- }
-
- private Long getFailure(Description key) {
- Long result= getFailureTimestamp(key);
- if (result == null)
- return 0L; // 0 = "never failed (that I know about)"
- return result;
- }
- }
-
- /**
- * @return a listener that will update this history based on the test
- * results reported.
- */
- public RunListener listener() {
- return new RememberingListener();
- }
-
- /**
- * @return a comparator that ranks tests based on the JUnit Max sorting
- * rules, as described in the {@link MaxCore} class comment.
- */
- public Comparator testComparator() {
- return new TestComparator();
- }
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * Loads a {@link MaxHistory} from {@code file}, or generates a new one that
+ * will be saved to {@code file}.
+ */
+ public static MaxHistory forFolder(File file) {
+ if (file.exists()) {
+ try {
+ return readHistory(file);
+ } catch (CouldNotReadCoreException e) {
+ e.printStackTrace();
+ file.delete();
+ }
+ }
+ return new MaxHistory(file);
+ }
+
+ private static MaxHistory readHistory(File storedResults)
+ throws CouldNotReadCoreException {
+ try {
+ FileInputStream file = new FileInputStream(storedResults);
+ try {
+ ObjectInputStream stream = new ObjectInputStream(file);
+ try {
+ return (MaxHistory) stream.readObject();
+ } finally {
+ stream.close();
+ }
+ } finally {
+ file.close();
+ }
+ } catch (Exception e) {
+ throw new CouldNotReadCoreException(e);
+ }
+ }
+
+ /*
+ * We have to use the f prefix until the next major release to ensure
+ * serialization compatibility.
+ * See https://github.com/junit-team/junit4/issues/976
+ */
+ private final Map fDurations = new HashMap();
+ private final Map fFailureTimestamps = new HashMap();
+ private final File fHistoryStore;
+
+ private MaxHistory(File storedResults) {
+ fHistoryStore = storedResults;
+ }
+
+ private void save() throws IOException {
+ ObjectOutputStream stream = null;
+ try {
+ stream = new ObjectOutputStream(new FileOutputStream(fHistoryStore));
+ stream.writeObject(this);
+ } finally {
+ if (stream != null) {
+ stream.close();
+ }
+ }
+ }
+
+ Long getFailureTimestamp(Description key) {
+ return fFailureTimestamps.get(key.toString());
+ }
+
+ void putTestFailureTimestamp(Description key, long end) {
+ fFailureTimestamps.put(key.toString(), end);
+ }
+
+ boolean isNewTest(Description key) {
+ return !fDurations.containsKey(key.toString());
+ }
+
+ Long getTestDuration(Description key) {
+ return fDurations.get(key.toString());
+ }
+
+ void putTestDuration(Description description, long duration) {
+ fDurations.put(description.toString(), duration);
+ }
+
+ private final class RememberingListener extends RunListener {
+ private long overallStart = System.currentTimeMillis();
+
+ private Map starts = new HashMap();
+
+ @Override
+ public void testStarted(Description description) throws Exception {
+ starts.put(description, System.nanoTime()); // Get most accurate
+ // possible time
+ }
+
+ @Override
+ public void testFinished(Description description) throws Exception {
+ long end = System.nanoTime();
+ long start = starts.get(description);
+ putTestDuration(description, end - start);
+ }
+
+ @Override
+ public void testFailure(Failure failure) throws Exception {
+ putTestFailureTimestamp(failure.getDescription(), overallStart);
+ }
+
+ @Override
+ public void testRunFinished(Result result) throws Exception {
+ save();
+ }
+ }
+
+ private class TestComparator implements Comparator {
+ public int compare(Description o1, Description o2) {
+ // Always prefer new tests
+ if (isNewTest(o1)) {
+ return -1;
+ }
+ if (isNewTest(o2)) {
+ return 1;
+ }
+ // Then most recently failed first
+ int result = getFailure(o2).compareTo(getFailure(o1));
+ return result != 0 ? result
+ // Then shorter tests first
+ : getTestDuration(o1).compareTo(getTestDuration(o2));
+ }
+
+ private Long getFailure(Description key) {
+ Long result = getFailureTimestamp(key);
+ if (result == null) {
+ return 0L; // 0 = "never failed (that I know about)"
+ }
+ return result;
+ }
+ }
+
+ /**
+ * @return a listener that will update this history based on the test
+ * results reported.
+ */
+ public RunListener listener() {
+ return new RememberingListener();
+ }
+
+ /**
+ * @return a comparator that ranks tests based on the JUnit Max sorting
+ * rules, as described in the {@link MaxCore} class comment.
+ */
+ public Comparator testComparator() {
+ return new TestComparator();
+ }
}
diff --git a/src/main/java/org/junit/experimental/results/FailureList.java b/src/main/java/org/junit/experimental/results/FailureList.java
index f4bc9b7a8c3e..e02eeae6a439 100644
--- a/src/main/java/org/junit/experimental/results/FailureList.java
+++ b/src/main/java/org/junit/experimental/results/FailureList.java
@@ -1,6 +1,3 @@
-/**
- *
- */
package org.junit.experimental.results;
import java.util.List;
@@ -10,22 +7,22 @@
import org.junit.runner.notification.RunListener;
class FailureList {
- private final List failures;
+ private final List failures;
- public FailureList(List failures) {
- this.failures= failures;
- }
+ public FailureList(List failures) {
+ this.failures = failures;
+ }
- public Result result() {
- Result result= new Result();
- RunListener listener= result.createListener();
- for (Failure failure : failures) {
- try {
- listener.testFailure(failure);
- } catch (Exception e) {
- throw new RuntimeException("I can't believe this happened");
- }
- }
- return result;
- }
+ public Result result() {
+ Result result = new Result();
+ RunListener listener = result.createListener();
+ for (Failure failure : failures) {
+ try {
+ listener.testFailure(failure);
+ } catch (Exception e) {
+ throw new RuntimeException("I can't believe this happened");
+ }
+ }
+ return result;
+ }
}
\ No newline at end of file
diff --git a/src/main/java/org/junit/experimental/results/PrintableResult.java b/src/main/java/org/junit/experimental/results/PrintableResult.java
index c302c4b5d168..0f67766f9141 100644
--- a/src/main/java/org/junit/experimental/results/PrintableResult.java
+++ b/src/main/java/org/junit/experimental/results/PrintableResult.java
@@ -6,6 +6,7 @@
import org.junit.internal.TextListener;
import org.junit.runner.JUnitCore;
+import org.junit.runner.Request;
import org.junit.runner.Result;
import org.junit.runner.notification.Failure;
@@ -13,47 +14,59 @@
* A test result that prints nicely in error messages.
* This is only intended to be used in JUnit self-tests.
* For example:
- *
+ *
*
*/
public class ResultMatchers {
- /**
- * Matches if the tests are all successful
- */
- public static Matcher isSuccessful() {
- return failureCountIs(0);
- }
- /**
- * Matches if there are {@code count} failures
- */
- public static Matcher failureCountIs(final int count) {
- return new TypeSafeMatcher() {
- public void describeTo(Description description) {
- description.appendText("has " + count + " failures");
- }
+ /**
+ * Do not instantiate.
+ * @deprecated will be private soon.
+ */
+ @Deprecated
+ public ResultMatchers() {
+ }
- @Override
- public boolean matchesSafely(PrintableResult item) {
- return item.failureCount() == count;
- }
- };
- }
-
- /**
- * Matches if the result has exactly one failure, and it contains {@code string}
- */
- public static Matcher hasSingleFailureContaining(final String string) {
- return new BaseMatcher() {
- public boolean matches(Object item) {
- return item.toString().contains(string) && failureCountIs(1).matches(item);
- }
+ /**
+ * Matches if the tests are all successful
+ */
+ public static Matcher isSuccessful() {
+ return failureCountIs(0);
+ }
- public void describeTo(Description description) {
- description.appendText("has single failure containing " + string);
- }
- };
- }
+ /**
+ * Matches if there are {@code count} failures
+ */
+ public static Matcher failureCountIs(final int count) {
+ return new TypeSafeMatcher() {
+ public void describeTo(Description description) {
+ description.appendText("has " + count + " failures");
+ }
- /**
- * Matches if the result has one or more failures, and at least one of them
- * contains {@code string}
- */
- public static Matcher hasFailureContaining(final String string) {
- return new BaseMatcher() {
- public boolean matches(Object item) {
- return item.toString().contains(string);
- }
+ @Override
+ public boolean matchesSafely(PrintableResult item) {
+ return item.failureCount() == count;
+ }
+ };
+ }
- public void describeTo(Description description) {
- description.appendText("has failure containing " + string);
- }
- };
- }
+ /**
+ * Matches if the result has exactly one failure, and it contains {@code string}
+ */
+ public static Matcher hasSingleFailureContaining(final String string) {
+ return new BaseMatcher() {
+ public boolean matches(Object item) {
+ return item.toString().contains(string) && failureCountIs(1).matches(item);
+ }
+
+ public void describeTo(Description description) {
+ description.appendText("has single failure containing " + string);
+ }
+ };
+ }
+
+ /**
+ * Matches if the result has exactly one failure matching the given matcher.
+ *
+ * @since 4.13
+ */
+ public static Matcher hasSingleFailureMatching(final Matcher matcher) {
+ return new TypeSafeMatcher() {
+ @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 hasFailureContaining(final String string) {
+ return new TypeSafeMatcher() {
+ @Override
+ public boolean matchesSafely(PrintableResult item) {
+ return item.failureCount() > 0 && item.toString().contains(string);
+ }
+
+ public void describeTo(Description description) {
+ description.appendText("has failure containing " + string);
+ }
+ };
+ }
}
diff --git a/src/main/java/org/junit/experimental/runners/Enclosed.java b/src/main/java/org/junit/experimental/runners/Enclosed.java
index b0560ed36b5a..610b97066897 100644
--- a/src/main/java/org/junit/experimental/runners/Enclosed.java
+++ b/src/main/java/org/junit/experimental/runners/Enclosed.java
@@ -1,31 +1,45 @@
package org.junit.experimental.runners;
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.List;
+
import org.junit.runners.Suite;
import org.junit.runners.model.RunnerBuilder;
-
/**
* If you put tests in inner classes, Ant, for example, won't find them. By running the outer class
* with Enclosed, the tests in the inner classes will be run. You might put tests in inner classes
- * to group them for convenience or to share constants.
- *
- * So, for example:
- *
- * \@RunWith(Enclosed.class)
- * public class ListTests {
- * ...useful shared stuff...
- * public static class OneKindOfListTest {...}
- * public static class AnotherKind {...}
- * }
- *
- *
- * For a real example, @see org.junit.tests.manipulation.SortableTest.
+ * to group them for convenience or to share constants. Abstract inner classes are ignored.
+ *
+ * So, for example:
+ *
+ * @RunWith(Enclosed.class)
+ * public class ListTests {
+ * ...useful shared stuff...
+ * public static class OneKindOfListTest {...}
+ * public static class AnotherKind {...}
+ * abstract public static class Ignored {...}
+ * }
+ *
*/
public class Enclosed extends Suite {
- /**
- * Only called reflectively. Do not use programmatically.
- */
- public Enclosed(Class> klass, RunnerBuilder builder) throws Throwable {
- super(builder, klass, klass.getClasses());
- }
+ /**
+ * Only called reflectively. Do not use programmatically.
+ */
+ public Enclosed(Class> klass, RunnerBuilder builder) throws Throwable {
+ super(builder, klass, filterAbstractClasses(klass.getClasses()));
+ }
+
+ private static Class>[] filterAbstractClasses(final Class>[] classes) {
+ final List> filteredList= new ArrayList>(classes.length);
+
+ for (final Class> clazz : classes) {
+ if (!Modifier.isAbstract(clazz.getModifiers())) {
+ filteredList.add(clazz);
+ }
+ }
+
+ return filteredList.toArray(new Class>[filteredList.size()]);
+ }
}
diff --git a/src/main/java/org/junit/experimental/theories/DataPoint.java b/src/main/java/org/junit/experimental/theories/DataPoint.java
index 2aaba6a16a75..0a017bb5631e 100644
--- a/src/main/java/org/junit/experimental/theories/DataPoint.java
+++ b/src/main/java/org/junit/experimental/theories/DataPoint.java
@@ -1,9 +1,56 @@
package org.junit.experimental.theories;
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+/**
+ * Annotating an field or method with @DataPoint will cause the field value
+ * or the value returned by the method to be used as a potential parameter for
+ * theories in that class, when run with the
+ * {@link org.junit.experimental.theories.Theories Theories} runner.
+ *
+ * A DataPoint is only considered as a potential value for parameters for
+ * which its type is assignable. When multiple {@code DataPoint}s exist
+ * with overlapping types more control can be obtained by naming each DataPoint
+ * using the value of this annotation, e.g. with
+ * @DataPoint({"dataset1", "dataset2"}), and then specifying
+ * which named set to consider as potential values for each parameter using the
+ * {@link org.junit.experimental.theories.FromDataPoints @FromDataPoints}
+ * annotation.
+ *
+ * Parameters with no specified source (i.e. without @FromDataPoints or
+ * other {@link org.junit.experimental.theories.ParametersSuppliedBy
+ * @ParameterSuppliedBy} annotations) will use all {@code DataPoint}s that are
+ * assignable to the parameter type as potential values, including named sets of
+ * {@code DataPoint}s.
+ *
+ *
+ *
+ * @see org.junit.experimental.theories.Theories
+ * @see org.junit.experimental.theories.Theory
+ * @see org.junit.experimental.theories.DataPoint
+ * @see org.junit.experimental.theories.FromDataPoints
+ */
@Retention(RetentionPolicy.RUNTIME)
+@Target({FIELD, METHOD})
public @interface DataPoint {
-
-}
+ String[] value() default {};
+ Class extends Throwable>[] ignoredExceptions() default {};
+}
\ No newline at end of file
diff --git a/src/main/java/org/junit/experimental/theories/DataPoints.java b/src/main/java/org/junit/experimental/theories/DataPoints.java
index 42145e34d2d4..b47461b388cd 100644
--- a/src/main/java/org/junit/experimental/theories/DataPoints.java
+++ b/src/main/java/org/junit/experimental/theories/DataPoints.java
@@ -1,9 +1,64 @@
package org.junit.experimental.theories;
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+/**
+ * Annotating an array or iterable-typed field or method with @DataPoints
+ * will cause the values in the array or iterable given to be used as potential
+ * parameters for theories in that class when run with the
+ * {@link org.junit.experimental.theories.Theories Theories} runner.
+ *
+ * DataPoints will only be considered as potential values for parameters for
+ * which their types are assignable. When multiple sets of DataPoints exist with
+ * overlapping types more control can be obtained by naming the DataPoints using
+ * the value of this annotation, e.g. with
+ * @DataPoints({"dataset1", "dataset2"}), and then specifying
+ * which named set to consider as potential values for each parameter using the
+ * {@link org.junit.experimental.theories.FromDataPoints @FromDataPoints}
+ * annotation.
+ *
+ * Parameters with no specified source (i.e. without @FromDataPoints or
+ * other {@link org.junit.experimental.theories.ParametersSuppliedBy
+ * @ParameterSuppliedBy} annotations) will use all DataPoints that are
+ * assignable to the parameter type as potential values, including named sets of
+ * DataPoints.
+ *
+ * DataPoints methods whose array types aren't assignable from the target
+ * parameter type (and so can't possibly return relevant values) will not be
+ * called when generating values for that parameter. Iterable-typed datapoints
+ * methods must always be called though, as this information is not available
+ * here after generic type erasure, so expensive methods returning iterable
+ * datapoints are a bad idea.
+ *
+ *
+ *
+ * @see org.junit.experimental.theories.Theories
+ * @see org.junit.experimental.theories.Theory
+ * @see org.junit.experimental.theories.DataPoint
+ * @see org.junit.experimental.theories.FromDataPoints
+ */
@Retention(RetentionPolicy.RUNTIME)
+@Target({ FIELD, METHOD })
public @interface DataPoints {
+ String[] value() default {};
+ Class extends Throwable>[] ignoredExceptions() default {};
}
diff --git a/src/main/java/org/junit/experimental/theories/FromDataPoints.java b/src/main/java/org/junit/experimental/theories/FromDataPoints.java
new file mode 100644
index 000000000000..2b149cae9cf1
--- /dev/null
+++ b/src/main/java/org/junit/experimental/theories/FromDataPoints.java
@@ -0,0 +1,54 @@
+package org.junit.experimental.theories;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import org.junit.experimental.theories.internal.SpecificDataPointsSupplier;
+
+/**
+ * Annotating a parameter of a {@link org.junit.experimental.theories.Theory
+ * @Theory} method with @FromDataPoints will limit the
+ * datapoints considered as potential values for that parameter to just the
+ * {@link org.junit.experimental.theories.DataPoints DataPoints} with the given
+ * name. DataPoint names can be given as the value parameter of the
+ * @DataPoints annotation.
+ *
+ * DataPoints without names will not be considered as values for any parameters
+ * annotated with @FromDataPoints.
+ *
+ * @DataPoints
+ * public static String[] unnamed = new String[] { ... };
+ *
+ * @DataPoints("regexes")
+ * public static String[] regexStrings = new String[] { ... };
+ *
+ * @DataPoints({"forMatching", "alphanumeric"})
+ * public static String[] testStrings = new String[] { ... };
+ *
+ * @Theory
+ * public void stringTheory(String param) {
+ * // This will be called with every value in 'regexStrings',
+ * // 'testStrings' and 'unnamed'.
+ * }
+ *
+ * @Theory
+ * public void regexTheory(@FromDataPoints("regexes") String regex,
+ * @FromDataPoints("forMatching") String value) {
+ * // This will be called with only the values in 'regexStrings' as
+ * // regex, only the values in 'testStrings' as value, and none
+ * // of the values in 'unnamed'.
+ * }
+ *
+ *
+ * @see org.junit.experimental.theories.Theory
+ * @see org.junit.experimental.theories.DataPoint
+ * @see org.junit.experimental.theories.DataPoints
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.PARAMETER)
+@ParametersSuppliedBy(SpecificDataPointsSupplier.class)
+public @interface FromDataPoints {
+ String value();
+}
diff --git a/src/main/java/org/junit/experimental/theories/ParameterSignature.java b/src/main/java/org/junit/experimental/theories/ParameterSignature.java
index e7150fc24f8a..cf225835e5b4 100644
--- a/src/main/java/org/junit/experimental/theories/ParameterSignature.java
+++ b/src/main/java/org/junit/experimental/theories/ParameterSignature.java
@@ -1,6 +1,3 @@
-/**
- *
- */
package org.junit.experimental.theories;
import java.lang.annotation.Annotation;
@@ -8,83 +5,130 @@
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
public class ParameterSignature {
- public static ArrayList signatures(Method method) {
- return signatures(method.getParameterTypes(), method
- .getParameterAnnotations());
- }
-
- public static List signatures(Constructor> constructor) {
- return signatures(constructor.getParameterTypes(), constructor
- .getParameterAnnotations());
- }
-
- private static ArrayList signatures(
- Class>[] parameterTypes, Annotation[][] parameterAnnotations) {
- ArrayList sigs= new ArrayList();
- for (int i= 0; i < parameterTypes.length; i++) {
- sigs.add(new ParameterSignature(parameterTypes[i],
- parameterAnnotations[i]));
- }
- return sigs;
- }
-
- private final Class> type;
-
- private final Annotation[] annotations;
-
- private ParameterSignature(Class> type, Annotation[] annotations) {
- this.type= type;
- this.annotations= annotations;
- }
-
- public boolean canAcceptType(Class> candidate) {
- return type.isAssignableFrom(candidate);
- }
-
- public Class> getType() {
- return type;
- }
-
- public List getAnnotations() {
- return Arrays.asList(annotations);
- }
-
- public boolean canAcceptArrayType(Class> type) {
- return type.isArray() && canAcceptType(type.getComponentType());
- }
-
- public boolean hasAnnotation(Class extends Annotation> type) {
- return getAnnotation(type) != null;
- }
-
- public T findDeepAnnotation(Class annotationType) {
- Annotation[] annotations2= annotations;
- return findDeepAnnotation(annotations2, annotationType, 3);
- }
-
- private T findDeepAnnotation(
- Annotation[] annotations, Class annotationType, int depth) {
- if (depth == 0)
- return null;
- for (Annotation each : annotations) {
- if (annotationType.isInstance(each))
- return annotationType.cast(each);
- Annotation candidate= findDeepAnnotation(each.annotationType()
- .getAnnotations(), annotationType, depth - 1);
- if (candidate != null)
- return annotationType.cast(candidate);
- }
-
- return null;
- }
-
- public T getAnnotation(Class annotationType) {
- for (Annotation each : getAnnotations())
- if (annotationType.isInstance(each))
- return annotationType.cast(each);
- return null;
- }
+
+ private static final Map, Class>> CONVERTABLE_TYPES_MAP = buildConvertableTypesMap();
+
+ private static Map, Class>> buildConvertableTypesMap() {
+ Map, Class>> map = new HashMap, Class>>();
+
+ putSymmetrically(map, boolean.class, Boolean.class);
+ putSymmetrically(map, byte.class, Byte.class);
+ putSymmetrically(map, short.class, Short.class);
+ putSymmetrically(map, char.class, Character.class);
+ putSymmetrically(map, int.class, Integer.class);
+ putSymmetrically(map, long.class, Long.class);
+ putSymmetrically(map, float.class, Float.class);
+ putSymmetrically(map, double.class, Double.class);
+
+ return Collections.unmodifiableMap(map);
+ }
+
+ private static void putSymmetrically(Map map, T a, T b) {
+ map.put(a, b);
+ map.put(b, a);
+ }
+
+ public static ArrayList signatures(Method method) {
+ return signatures(method.getParameterTypes(), method
+ .getParameterAnnotations());
+ }
+
+ public static List signatures(Constructor> constructor) {
+ return signatures(constructor.getParameterTypes(), constructor
+ .getParameterAnnotations());
+ }
+
+ private static ArrayList signatures(
+ Class>[] parameterTypes, Annotation[][] parameterAnnotations) {
+ ArrayList sigs = new ArrayList();
+ for (int i = 0; i < parameterTypes.length; i++) {
+ sigs.add(new ParameterSignature(parameterTypes[i],
+ parameterAnnotations[i]));
+ }
+ return sigs;
+ }
+
+ private final Class> type;
+
+ private final Annotation[] annotations;
+
+ private ParameterSignature(Class> type, Annotation[] annotations) {
+ this.type = type;
+ this.annotations = annotations;
+ }
+
+ public boolean canAcceptValue(Object candidate) {
+ return (candidate == null) ? !type.isPrimitive() : canAcceptType(candidate.getClass());
+ }
+
+ public boolean canAcceptType(Class> candidate) {
+ return type.isAssignableFrom(candidate) ||
+ isAssignableViaTypeConversion(type, candidate);
+ }
+
+ public boolean canPotentiallyAcceptType(Class> candidate) {
+ return candidate.isAssignableFrom(type) ||
+ isAssignableViaTypeConversion(candidate, type) ||
+ canAcceptType(candidate);
+ }
+
+ private boolean isAssignableViaTypeConversion(Class> targetType, Class> candidate) {
+ if (CONVERTABLE_TYPES_MAP.containsKey(candidate)) {
+ Class> wrapperClass = CONVERTABLE_TYPES_MAP.get(candidate);
+ return targetType.isAssignableFrom(wrapperClass);
+ } else {
+ return false;
+ }
+ }
+
+ public Class> getType() {
+ return type;
+ }
+
+ public List getAnnotations() {
+ return Arrays.asList(annotations);
+ }
+
+ public boolean hasAnnotation(Class extends Annotation> type) {
+ return getAnnotation(type) != null;
+ }
+
+ public T findDeepAnnotation(Class annotationType) {
+ Annotation[] annotations2 = annotations;
+ return findDeepAnnotation(annotations2, annotationType, 3);
+ }
+
+ private T findDeepAnnotation(
+ Annotation[] annotations, Class annotationType, int depth) {
+ if (depth == 0) {
+ return null;
+ }
+ for (Annotation each : annotations) {
+ if (annotationType.isInstance(each)) {
+ return annotationType.cast(each);
+ }
+ Annotation candidate = findDeepAnnotation(each.annotationType()
+ .getAnnotations(), annotationType, depth - 1);
+ if (candidate != null) {
+ return annotationType.cast(candidate);
+ }
+ }
+
+ return null;
+ }
+
+ public T getAnnotation(Class annotationType) {
+ for (Annotation each : getAnnotations()) {
+ if (annotationType.isInstance(each)) {
+ return annotationType.cast(each);
+ }
+ }
+ return null;
+ }
}
\ No newline at end of file
diff --git a/src/main/java/org/junit/experimental/theories/ParameterSupplier.java b/src/main/java/org/junit/experimental/theories/ParameterSupplier.java
index 9016c91fde6c..bac8b34282e2 100644
--- a/src/main/java/org/junit/experimental/theories/ParameterSupplier.java
+++ b/src/main/java/org/junit/experimental/theories/ParameterSupplier.java
@@ -2,7 +2,42 @@
import java.util.List;
-
+/**
+ * Abstract parent class for suppliers of input data points for theories. Extend this class to customize how {@link
+ * org.junit.experimental.theories.Theories Theories} runner
+ * finds accepted data points. Then use your class together with @ParametersSuppliedBy on input
+ * parameters for theories.
+ *
+ *
+ * For example, here is a supplier for values between two integers, and an annotation that references it:
+ *
+ *
+ * @Retention(RetentionPolicy.RUNTIME)
+ * @ParametersSuppliedBy(BetweenSupplier.class)
+ * public @interface Between {
+ * int first();
+ *
+ * int last();
+ * }
+ *
+ * public static class BetweenSupplier extends ParameterSupplier {
+ * @Override
+ * public List<PotentialAssignment> getValueSources(ParameterSignature sig) {
+ * List<PotentialAssignment> list = new ArrayList<PotentialAssignment>();
+ * Between annotation = (Between) sig.getSupplierAnnotation();
+ *
+ * for (int i = annotation.first(); i <= annotation.last(); i++)
+ * list.add(PotentialAssignment.forValue("ints", i));
+ * return list;
+ * }
+ * }
+ *
+ *
+ *
+ * @see org.junit.experimental.theories.ParametersSuppliedBy
+ * @see org.junit.experimental.theories.Theories
+ * @see org.junit.experimental.theories.FromDataPoints
+ */
public abstract class ParameterSupplier {
- public abstract List getValueSources(ParameterSignature sig);
+ public abstract List getValueSources(ParameterSignature sig) throws Throwable;
}
diff --git a/src/main/java/org/junit/experimental/theories/ParametersSuppliedBy.java b/src/main/java/org/junit/experimental/theories/ParametersSuppliedBy.java
index 8f090ef33616..846a39e46339 100644
--- a/src/main/java/org/junit/experimental/theories/ParametersSuppliedBy.java
+++ b/src/main/java/org/junit/experimental/theories/ParametersSuppliedBy.java
@@ -1,12 +1,48 @@
package org.junit.experimental.theories;
+import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
+import static java.lang.annotation.ElementType.PARAMETER;
+
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
-
+/**
+ * Annotating a {@link org.junit.experimental.theories.Theory Theory} method
+ * parameter with @ParametersSuppliedBy causes it to be supplied with
+ * values from the named
+ * {@link org.junit.experimental.theories.ParameterSupplier ParameterSupplier}
+ * when run as a theory by the {@link org.junit.experimental.theories.Theories
+ * Theories} runner.
+ *
+ * In addition, annotations themselves can be annotated with
+ * @ParametersSuppliedBy, and then used similarly. ParameterSuppliedBy
+ * annotations on parameters are detected by searching up this hierarchy such
+ * that these act as syntactic sugar, making:
+ *
+ *
+ */
@Retention(RetentionPolicy.RUNTIME)
+@Target({ ANNOTATION_TYPE, PARAMETER })
public @interface ParametersSuppliedBy {
- Class extends ParameterSupplier> value();
+ Class extends ParameterSupplier> value();
}
diff --git a/src/main/java/org/junit/experimental/theories/PotentialAssignment.java b/src/main/java/org/junit/experimental/theories/PotentialAssignment.java
index 0c008d0e6e09..18ca07a4044d 100644
--- a/src/main/java/org/junit/experimental/theories/PotentialAssignment.java
+++ b/src/main/java/org/junit/experimental/theories/PotentialAssignment.java
@@ -1,31 +1,52 @@
package org.junit.experimental.theories;
+import static java.lang.String.format;
+
public abstract class PotentialAssignment {
- public static class CouldNotGenerateValueException extends Exception {
- private static final long serialVersionUID= 1L;
- }
-
- public static PotentialAssignment forValue(final String name, final Object value) {
- return new PotentialAssignment() {
- @Override
- public Object getValue() throws CouldNotGenerateValueException {
- return value;
- }
-
- @Override
- public String toString() {
- return String.format("[%s]", value);
- }
-
- @Override
- public String getDescription()
- throws CouldNotGenerateValueException {
- return name;
- }
- };
- }
-
- public abstract Object getValue() throws CouldNotGenerateValueException;
-
- public abstract String getDescription() throws CouldNotGenerateValueException;
-}
+ public static class CouldNotGenerateValueException extends Exception {
+ private static final long serialVersionUID = 1L;
+
+ public CouldNotGenerateValueException() {
+ }
+
+ public CouldNotGenerateValueException(Throwable e) {
+ super(e);
+ }
+ }
+
+ public static PotentialAssignment forValue(final String name, final Object value) {
+ return new PotentialAssignment() {
+ @Override
+ public Object getValue() {
+ return value;
+ }
+
+ @Override
+ public String toString() {
+ return format("[%s]", value);
+ }
+
+ @Override
+ public String getDescription() {
+ String valueString;
+
+ if (value == null) {
+ valueString = "null";
+ } else {
+ try {
+ valueString = format("\"%s\"", value);
+ } catch (Throwable e) {
+ valueString = format("[toString() threw %s: %s]",
+ e.getClass().getSimpleName(), e.getMessage());
+ }
+ }
+
+ return format("%s ", valueString, name);
+ }
+ };
+ }
+
+ public abstract Object getValue() throws CouldNotGenerateValueException;
+
+ public abstract String getDescription() throws CouldNotGenerateValueException;
+}
\ No newline at end of file
diff --git a/src/main/java/org/junit/experimental/theories/Theories.java b/src/main/java/org/junit/experimental/theories/Theories.java
index cd3b1bd570b8..ac88a364a670 100644
--- a/src/main/java/org/junit/experimental/theories/Theories.java
+++ b/src/main/java/org/junit/experimental/theories/Theories.java
@@ -1,16 +1,14 @@
-/**
- *
- */
package org.junit.experimental.theories;
+import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
-import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.List;
import org.junit.Assert;
-import org.junit.experimental.theories.PotentialAssignment.CouldNotGenerateValueException;
+import org.junit.Assume;
import org.junit.experimental.theories.internal.Assignments;
import org.junit.experimental.theories.internal.ParameterizedAssertionError;
import org.junit.internal.AssumptionViolatedException;
@@ -18,175 +16,295 @@
import org.junit.runners.model.FrameworkMethod;
import org.junit.runners.model.InitializationError;
import org.junit.runners.model.Statement;
+import org.junit.runners.model.TestClass;
+/**
+ * The Theories runner allows to test a certain functionality against a subset of an infinite set of data points.
+ *
+ * A Theory is a piece of functionality (a method) that is executed against several data inputs called data points.
+ * To make a test method a theory you mark it with @Theory. To create a data point you create a public
+ * field in your test class and mark it with @DataPoint. The Theories runner then executes your test
+ * method as many times as the number of data points declared, providing a different data point as
+ * the input argument on each invocation.
+ *
+ *
+ * A Theory differs from standard test method in that it captures some aspect of the intended behavior in possibly
+ * infinite numbers of scenarios which corresponds to the number of data points declared. Using assumptions and
+ * assertions properly together with covering multiple scenarios with different data points can make your tests more
+ * flexible and bring them closer to scientific theories (hence the 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. UserTest will attempt to run filenameIncludesUsername 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. If no parameters can be found that satisfy all assumptions, the test fails.
+ *
+ * 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.
+ *
+ *
+ * The support for Theories has been absorbed from the Popper project, and more complete documentation can be found
+ * from that projects archived documentation.
+ *
+ *
+ * @see Archived Popper project documentation
+ * @see Paper on Theories
+ */
public class Theories extends BlockJUnit4ClassRunner {
- public Theories(Class> klass) throws InitializationError {
- super(klass);
- }
-
- @Override
- protected void collectInitializationErrors(List errors) {
- super.collectInitializationErrors(errors);
- validateDataPointFields(errors);
- }
-
- private void validateDataPointFields(List errors) {
- Field[] fields= getTestClass().getJavaClass().getDeclaredFields();
-
- for (Field each : fields)
- if (each.getAnnotation(DataPoint.class) != null && !Modifier.isStatic(each.getModifiers()))
- errors.add(new Error("DataPoint field " + each.getName() + " must be static"));
- }
-
- @Override
- protected void validateConstructor(List errors) {
- validateOnlyOneConstructor(errors);
- }
-
- @Override
- protected void validateTestMethods(List errors) {
- for (FrameworkMethod each : computeTestMethods())
- if(each.getAnnotation(Theory.class) != null)
- each.validatePublicVoid(false, errors);
- else
- each.validatePublicVoidNoArg(false, errors);
- }
-
- @Override
- protected List computeTestMethods() {
- List testMethods= super.computeTestMethods();
- List theoryMethods= getTestClass().getAnnotatedMethods(Theory.class);
- testMethods.removeAll(theoryMethods);
- testMethods.addAll(theoryMethods);
- return testMethods;
- }
-
- @Override
- public Statement methodBlock(final FrameworkMethod method) {
- return new TheoryAnchor(method);
- }
-
- public class TheoryAnchor extends Statement {
- private int successes= 0;
-
- private FrameworkMethod fTestMethod;
-
- private List fInvalidParameters= new ArrayList();
-
- public TheoryAnchor(FrameworkMethod method) {
- fTestMethod= method;
- }
-
- @Override
- public void evaluate() throws Throwable {
- runWithAssignment(Assignments.allUnassigned(
- fTestMethod.getMethod(), getTestClass()));
-
- if (successes == 0)
- Assert
- .fail("Never found parameters that satisfied method assumptions. Violated assumptions: "
- + fInvalidParameters);
- }
-
- protected void runWithAssignment(Assignments parameterAssignment)
- throws Throwable {
- if (!parameterAssignment.isComplete()) {
- runWithIncompleteAssignment(parameterAssignment);
- } else {
- runWithCompleteAssignment(parameterAssignment);
- }
- }
-
- protected void runWithIncompleteAssignment(Assignments incomplete)
- throws InstantiationException, IllegalAccessException,
- Throwable {
- for (PotentialAssignment source : incomplete
- .potentialsForNextUnassigned()) {
- runWithAssignment(incomplete.assignNext(source));
- }
- }
-
- protected void runWithCompleteAssignment(final Assignments complete)
- throws InstantiationException, IllegalAccessException,
- InvocationTargetException, NoSuchMethodException, Throwable {
- new BlockJUnit4ClassRunner(getTestClass().getJavaClass()) {
- @Override
- protected void collectInitializationErrors(
- List errors) {
- // do nothing
- }
-
- @Override
- public Statement methodBlock(FrameworkMethod method) {
- final Statement statement= super.methodBlock(method);
- return new Statement() {
- @Override
- public void evaluate() throws Throwable {
- try {
- statement.evaluate();
- handleDataPointSuccess();
- } catch (AssumptionViolatedException e) {
- handleAssumptionViolation(e);
- } catch (Throwable e) {
- reportParameterizedError(e, complete
- .getArgumentStrings(nullsOk()));
- }
- }
-
- };
- }
-
- @Override
- protected Statement methodInvoker(FrameworkMethod method, Object test) {
- return methodCompletesWithParameters(method, complete, test);
- }
-
- @Override
- public Object createTest() throws Exception {
- return getTestClass().getOnlyConstructor().newInstance(
- complete.getConstructorArguments(nullsOk()));
- }
- }.methodBlock(fTestMethod).evaluate();
- }
-
- private Statement methodCompletesWithParameters(
- final FrameworkMethod method, final Assignments complete, final Object freshInstance) {
- return new Statement() {
- @Override
- public void evaluate() throws Throwable {
- try {
- final Object[] values= complete.getMethodArguments(
- nullsOk());
- method.invokeExplosively(freshInstance, values);
- } catch (CouldNotGenerateValueException e) {
- // ignore
- }
- }
- };
- }
-
- protected void handleAssumptionViolation(AssumptionViolatedException e) {
- fInvalidParameters.add(e);
- }
-
- protected void reportParameterizedError(Throwable e, Object... params)
- throws Throwable {
- if (params.length == 0)
- throw e;
- throw new ParameterizedAssertionError(e, fTestMethod.getName(),
- params);
- }
-
- private boolean nullsOk() {
- Theory annotation= fTestMethod.getMethod().getAnnotation(
- Theory.class);
- if (annotation == null)
- return false;
- return annotation.nullsAccepted();
- }
-
- protected void handleDataPointSuccess() {
- successes++;
- }
- }
-}
\ No newline at end of file
+ public Theories(Class> klass) throws InitializationError {
+ super(klass);
+ }
+
+ /** @since 4.13 */
+ protected Theories(TestClass testClass) throws InitializationError {
+ super(testClass);
+ }
+
+ @Override
+ protected void collectInitializationErrors(List errors) {
+ super.collectInitializationErrors(errors);
+ validateDataPointFields(errors);
+ validateDataPointMethods(errors);
+ }
+
+ private void validateDataPointFields(List errors) {
+ Field[] fields = getTestClass().getJavaClass().getDeclaredFields();
+
+ for (Field field : fields) {
+ if (field.getAnnotation(DataPoint.class) == null && field.getAnnotation(DataPoints.class) == null) {
+ continue;
+ }
+ if (!Modifier.isStatic(field.getModifiers())) {
+ errors.add(new Error("DataPoint field " + field.getName() + " must be static"));
+ }
+ if (!Modifier.isPublic(field.getModifiers())) {
+ errors.add(new Error("DataPoint field " + field.getName() + " must be public"));
+ }
+ }
+ }
+
+ private void validateDataPointMethods(List errors) {
+ Method[] methods = getTestClass().getJavaClass().getDeclaredMethods();
+
+ for (Method method : methods) {
+ if (method.getAnnotation(DataPoint.class) == null && method.getAnnotation(DataPoints.class) == null) {
+ continue;
+ }
+ if (!Modifier.isStatic(method.getModifiers())) {
+ errors.add(new Error("DataPoint method " + method.getName() + " must be static"));
+ }
+ if (!Modifier.isPublic(method.getModifiers())) {
+ errors.add(new Error("DataPoint method " + method.getName() + " must be public"));
+ }
+ }
+ }
+
+ @Override
+ protected void validateConstructor(List errors) {
+ validateOnlyOneConstructor(errors);
+ }
+
+ @Override
+ protected void validateTestMethods(List errors) {
+ for (FrameworkMethod each : computeTestMethods()) {
+ if (each.getAnnotation(Theory.class) != null) {
+ each.validatePublicVoid(false, errors);
+ each.validateNoTypeParametersOnArgs(errors);
+ } else {
+ each.validatePublicVoidNoArg(false, errors);
+ }
+
+ for (ParameterSignature signature : ParameterSignature.signatures(each.getMethod())) {
+ ParametersSuppliedBy annotation = signature.findDeepAnnotation(ParametersSuppliedBy.class);
+ if (annotation != null) {
+ validateParameterSupplier(annotation.value(), errors);
+ }
+ }
+ }
+ }
+
+ private void validateParameterSupplier(Class extends ParameterSupplier> supplierClass, List errors) {
+ Constructor>[] constructors = supplierClass.getConstructors();
+
+ if (constructors.length != 1) {
+ errors.add(new Error("ParameterSupplier " + supplierClass.getName() +
+ " must have only one constructor (either empty or taking only a TestClass)"));
+ } else {
+ Class>[] paramTypes = constructors[0].getParameterTypes();
+ if (!(paramTypes.length == 0) && !paramTypes[0].equals(TestClass.class)) {
+ errors.add(new Error("ParameterSupplier " + supplierClass.getName() +
+ " constructor must take either nothing or a single TestClass instance"));
+ }
+ }
+ }
+
+ @Override
+ protected List computeTestMethods() {
+ List testMethods = new ArrayList(super.computeTestMethods());
+ List theoryMethods = getTestClass().getAnnotatedMethods(Theory.class);
+ testMethods.removeAll(theoryMethods);
+ testMethods.addAll(theoryMethods);
+ return testMethods;
+ }
+
+ @Override
+ public Statement methodBlock(final FrameworkMethod method) {
+ return new TheoryAnchor(method, getTestClass());
+ }
+
+ public static class TheoryAnchor extends Statement {
+ private int successes = 0;
+
+ private final FrameworkMethod testMethod;
+ private final TestClass testClass;
+
+ private List fInvalidParameters = new ArrayList();
+
+ public TheoryAnchor(FrameworkMethod testMethod, TestClass testClass) {
+ this.testMethod = testMethod;
+ this.testClass = testClass;
+ }
+
+ private TestClass getTestClass() {
+ return testClass;
+ }
+
+ @Override
+ public void evaluate() throws Throwable {
+ runWithAssignment(Assignments.allUnassigned(
+ testMethod.getMethod(), getTestClass()));
+
+ //if this test method is not annotated with Theory, then no successes is a valid case
+ boolean hasTheoryAnnotation = testMethod.getAnnotation(Theory.class) != null;
+ if (successes == 0 && hasTheoryAnnotation) {
+ Assert
+ .fail("Never found parameters that satisfied method assumptions. Violated assumptions: "
+ + fInvalidParameters);
+ }
+ }
+
+ protected void runWithAssignment(Assignments parameterAssignment)
+ throws Throwable {
+ if (!parameterAssignment.isComplete()) {
+ runWithIncompleteAssignment(parameterAssignment);
+ } else {
+ runWithCompleteAssignment(parameterAssignment);
+ }
+ }
+
+ protected void runWithIncompleteAssignment(Assignments incomplete)
+ throws Throwable {
+ for (PotentialAssignment source : incomplete
+ .potentialsForNextUnassigned()) {
+ runWithAssignment(incomplete.assignNext(source));
+ }
+ }
+
+ protected void runWithCompleteAssignment(final Assignments complete)
+ throws Throwable {
+ new BlockJUnit4ClassRunner(getTestClass()) {
+ @Override
+ protected void collectInitializationErrors(
+ List errors) {
+ // do nothing
+ }
+
+ @Override
+ public Statement methodBlock(FrameworkMethod method) {
+ final Statement statement = super.methodBlock(method);
+ return new Statement() {
+ @Override
+ public void evaluate() throws Throwable {
+ try {
+ statement.evaluate();
+ handleDataPointSuccess();
+ } catch (AssumptionViolatedException e) {
+ handleAssumptionViolation(e);
+ } catch (Throwable e) {
+ reportParameterizedError(e, complete
+ .getArgumentStrings(nullsOk()));
+ }
+ }
+
+ };
+ }
+
+ @Override
+ protected Statement methodInvoker(FrameworkMethod method, Object test) {
+ return methodCompletesWithParameters(method, complete, test);
+ }
+
+ @Override
+ public Object createTest() throws Exception {
+ Object[] params = complete.getConstructorArguments();
+
+ if (!nullsOk()) {
+ Assume.assumeNotNull(params);
+ }
+
+ return getTestClass().getOnlyConstructor().newInstance(params);
+ }
+ }.methodBlock(testMethod).evaluate();
+ }
+
+ private Statement methodCompletesWithParameters(
+ final FrameworkMethod method, final Assignments complete, final Object freshInstance) {
+ return new Statement() {
+ @Override
+ public void evaluate() throws Throwable {
+ final Object[] values = complete.getMethodArguments();
+
+ if (!nullsOk()) {
+ Assume.assumeNotNull(values);
+ }
+
+ method.invokeExplosively(freshInstance, values);
+ }
+ };
+ }
+
+ protected void handleAssumptionViolation(AssumptionViolatedException e) {
+ fInvalidParameters.add(e);
+ }
+
+ protected void reportParameterizedError(Throwable e, Object... params)
+ throws Throwable {
+ if (params.length == 0) {
+ throw e;
+ }
+ throw new ParameterizedAssertionError(e, testMethod.getName(),
+ params);
+ }
+
+ private boolean nullsOk() {
+ Theory annotation = testMethod.getMethod().getAnnotation(
+ Theory.class);
+ if (annotation == null) {
+ return false;
+ }
+ return annotation.nullsAccepted();
+ }
+
+ protected void handleDataPointSuccess() {
+ successes++;
+ }
+ }
+}
diff --git a/src/main/java/org/junit/experimental/theories/Theory.java b/src/main/java/org/junit/experimental/theories/Theory.java
index 134fe9d1bf5d..0b9f2c4121fe 100644
--- a/src/main/java/org/junit/experimental/theories/Theory.java
+++ b/src/main/java/org/junit/experimental/theories/Theory.java
@@ -1,12 +1,18 @@
-/**
- *
- */
package org.junit.experimental.theories;
+import static java.lang.annotation.ElementType.METHOD;
+
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+/**
+ * Marks test methods that should be read as theories by the {@link org.junit.experimental.theories.Theories Theories} runner.
+ *
+ * @see org.junit.experimental.theories.Theories
+ */
@Retention(RetentionPolicy.RUNTIME)
+@Target(METHOD)
public @interface Theory {
- boolean nullsAccepted() default true;
+ boolean nullsAccepted() default true;
}
\ No newline at end of file
diff --git a/src/main/java/org/junit/experimental/theories/internal/AllMembersSupplier.java b/src/main/java/org/junit/experimental/theories/internal/AllMembersSupplier.java
index 26e1d789b1b0..f15fb288e4a6 100644
--- a/src/main/java/org/junit/experimental/theories/internal/AllMembersSupplier.java
+++ b/src/main/java/org/junit/experimental/theories/internal/AllMembersSupplier.java
@@ -1,19 +1,19 @@
-/**
- *
- */
package org.junit.experimental.theories.internal;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
-import java.lang.reflect.Modifier;
import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
import java.util.List;
+import org.junit.Assume;
import org.junit.experimental.theories.DataPoint;
import org.junit.experimental.theories.DataPoints;
import org.junit.experimental.theories.ParameterSignature;
import org.junit.experimental.theories.ParameterSupplier;
import org.junit.experimental.theories.PotentialAssignment;
+import org.junit.runners.model.FrameworkField;
import org.junit.runners.model.FrameworkMethod;
import org.junit.runners.model.TestClass;
@@ -21,106 +21,184 @@
* Supplies Theory parameters based on all public members of the target class.
*/
public class AllMembersSupplier extends ParameterSupplier {
- static class MethodParameterValue extends PotentialAssignment {
- private final FrameworkMethod fMethod;
-
- private MethodParameterValue(FrameworkMethod dataPointMethod) {
- fMethod= dataPointMethod;
- }
-
- @Override
- public Object getValue() throws CouldNotGenerateValueException {
- try {
- return fMethod.invokeExplosively(null);
- } catch (IllegalArgumentException e) {
- throw new RuntimeException(
- "unexpected: argument length is checked");
- } catch (IllegalAccessException e) {
- throw new RuntimeException(
- "unexpected: getMethods returned an inaccessible method");
- } catch (Throwable e) {
- throw new CouldNotGenerateValueException();
- // do nothing, just look for more values
- }
- }
-
- @Override
- public String getDescription() throws CouldNotGenerateValueException {
- return fMethod.getName();
- }
- }
-
- private final TestClass fClass;
-
- /**
- * Constructs a new supplier for {@code type}
- */
- public AllMembersSupplier(TestClass type) {
- fClass= type;
- }
-
- @Override
- public List getValueSources(ParameterSignature sig) {
- List list= new ArrayList();
-
- addFields(sig, list);
- addSinglePointMethods(sig, list);
- addMultiPointMethods(list);
-
- return list;
- }
-
- private void addMultiPointMethods(List list) {
- for (FrameworkMethod dataPointsMethod : fClass
- .getAnnotatedMethods(DataPoints.class))
- try {
- addArrayValues(dataPointsMethod.getName(), list, dataPointsMethod.invokeExplosively(null));
- } catch (Throwable e) {
- // ignore and move on
- }
- }
-
- private void addSinglePointMethods(ParameterSignature sig,
- List list) {
- for (FrameworkMethod dataPointMethod : fClass
- .getAnnotatedMethods(DataPoint.class)) {
- Class> type= sig.getType();
- if ((dataPointMethod.producesType(type)))
- list.add(new MethodParameterValue(dataPointMethod));
- }
- }
-
- private void addFields(ParameterSignature sig,
- List list) {
- for (final Field field : fClass.getJavaClass().getFields()) {
- if (Modifier.isStatic(field.getModifiers())) {
- Class> type= field.getType();
- if (sig.canAcceptArrayType(type)
- && field.getAnnotation(DataPoints.class) != null) {
- addArrayValues(field.getName(), list, getStaticFieldValue(field));
- } else if (sig.canAcceptType(type)
- && field.getAnnotation(DataPoint.class) != null) {
- list.add(PotentialAssignment
- .forValue(field.getName(), getStaticFieldValue(field)));
- }
- }
- }
- }
-
- private void addArrayValues(String name, List list, Object array) {
- for (int i= 0; i < Array.getLength(array); i++)
- list.add(PotentialAssignment.forValue(name + "[" + i + "]", Array.get(array, i)));
- }
-
- private Object getStaticFieldValue(final Field field) {
- try {
- return field.get(null);
- } catch (IllegalArgumentException e) {
- throw new RuntimeException(
- "unexpected: field from getClass doesn't exist on object");
- } catch (IllegalAccessException e) {
- throw new RuntimeException(
- "unexpected: getFields returned an inaccessible field");
- }
- }
+ static class MethodParameterValue extends PotentialAssignment {
+ private final FrameworkMethod method;
+
+ private MethodParameterValue(FrameworkMethod dataPointMethod) {
+ method = dataPointMethod;
+ }
+
+ @Override
+ public Object getValue() throws CouldNotGenerateValueException {
+ try {
+ return method.invokeExplosively(null);
+ } catch (IllegalArgumentException e) {
+ throw new RuntimeException(
+ "unexpected: argument length is checked");
+ } catch (IllegalAccessException e) {
+ throw new RuntimeException(
+ "unexpected: getMethods returned an inaccessible method");
+ } catch (Throwable throwable) {
+ DataPoint annotation = method.getAnnotation(DataPoint.class);
+ Assume.assumeTrue(annotation == null || !isAssignableToAnyOf(annotation.ignoredExceptions(), throwable));
+
+ throw new CouldNotGenerateValueException(throwable);
+ }
+ }
+
+ @Override
+ public String getDescription() throws CouldNotGenerateValueException {
+ return method.getName();
+ }
+ }
+
+ private final TestClass clazz;
+
+ /**
+ * Constructs a new supplier for {@code type}
+ */
+ public AllMembersSupplier(TestClass type) {
+ clazz = type;
+ }
+
+ @Override
+ public List getValueSources(ParameterSignature sig) throws Throwable {
+ List list = new ArrayList();
+
+ addSinglePointFields(sig, list);
+ addMultiPointFields(sig, list);
+ addSinglePointMethods(sig, list);
+ addMultiPointMethods(sig, list);
+
+ return list;
+ }
+
+ private void addMultiPointMethods(ParameterSignature sig, List list) throws Throwable {
+ for (FrameworkMethod dataPointsMethod : getDataPointsMethods(sig)) {
+ Class> returnType = dataPointsMethod.getReturnType();
+
+ if ((returnType.isArray() && sig.canPotentiallyAcceptType(returnType.getComponentType())) ||
+ Iterable.class.isAssignableFrom(returnType)) {
+ try {
+ addDataPointsValues(returnType, sig, dataPointsMethod.getName(), list,
+ dataPointsMethod.invokeExplosively(null));
+ } catch (Throwable throwable) {
+ DataPoints annotation = dataPointsMethod.getAnnotation(DataPoints.class);
+ if (annotation != null && isAssignableToAnyOf(annotation.ignoredExceptions(), throwable)) {
+ return;
+ } else {
+ throw throwable;
+ }
+ }
+ }
+ }
+ }
+
+ private void addSinglePointMethods(ParameterSignature sig, List list) {
+ for (FrameworkMethod dataPointMethod : getSingleDataPointMethods(sig)) {
+ if (sig.canAcceptType(dataPointMethod.getType())) {
+ list.add(new MethodParameterValue(dataPointMethod));
+ }
+ }
+ }
+
+ private void addMultiPointFields(ParameterSignature sig, List list) {
+ for (final Field field : getDataPointsFields(sig)) {
+ Class> type = field.getType();
+ addDataPointsValues(type, sig, field.getName(), list, getStaticFieldValue(field));
+ }
+ }
+
+ private void addSinglePointFields(ParameterSignature sig, List list) {
+ for (final Field field : getSingleDataPointFields(sig)) {
+ Object value = getStaticFieldValue(field);
+
+ if (sig.canAcceptValue(value)) {
+ list.add(PotentialAssignment.forValue(field.getName(), value));
+ }
+ }
+ }
+
+ private void addDataPointsValues(Class> type, ParameterSignature sig, String name,
+ List list, Object value) {
+ if (type.isArray()) {
+ addArrayValues(sig, name, list, value);
+ }
+ else if (Iterable.class.isAssignableFrom(type)) {
+ addIterableValues(sig, name, list, (Iterable>) value);
+ }
+ }
+
+ private void addArrayValues(ParameterSignature sig, String name, List list, Object array) {
+ for (int i = 0; i < Array.getLength(array); i++) {
+ Object value = Array.get(array, i);
+ if (sig.canAcceptValue(value)) {
+ list.add(PotentialAssignment.forValue(name + "[" + i + "]", value));
+ }
+ }
+ }
+
+ private void addIterableValues(ParameterSignature sig, String name, List list, Iterable> iterable) {
+ Iterator> iterator = iterable.iterator();
+ int i = 0;
+ while (iterator.hasNext()) {
+ Object value = iterator.next();
+ if (sig.canAcceptValue(value)) {
+ list.add(PotentialAssignment.forValue(name + "[" + i + "]", value));
+ }
+ i += 1;
+ }
+ }
+
+ private Object getStaticFieldValue(final Field field) {
+ try {
+ return field.get(null);
+ } catch (IllegalArgumentException e) {
+ throw new RuntimeException(
+ "unexpected: field from getClass doesn't exist on object");
+ } catch (IllegalAccessException e) {
+ throw new RuntimeException(
+ "unexpected: getFields returned an inaccessible field");
+ }
+ }
+
+ private static boolean isAssignableToAnyOf(Class>[] typeArray, Object target) {
+ for (Class> type : typeArray) {
+ if (type.isAssignableFrom(target.getClass())) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ protected Collection getDataPointsMethods(ParameterSignature sig) {
+ return clazz.getAnnotatedMethods(DataPoints.class);
+ }
+
+ protected Collection getSingleDataPointFields(ParameterSignature sig) {
+ List fields = clazz.getAnnotatedFields(DataPoint.class);
+ Collection validFields = new ArrayList();
+
+ for (FrameworkField frameworkField : fields) {
+ validFields.add(frameworkField.getField());
+ }
+
+ return validFields;
+ }
+
+ protected Collection getDataPointsFields(ParameterSignature sig) {
+ List fields = clazz.getAnnotatedFields(DataPoints.class);
+ Collection validFields = new ArrayList();
+
+ for (FrameworkField frameworkField : fields) {
+ validFields.add(frameworkField.getField());
+ }
+
+ return validFields;
+ }
+
+ protected Collection getSingleDataPointMethods(ParameterSignature sig) {
+ return clazz.getAnnotatedMethods(DataPoint.class);
+ }
+
}
\ No newline at end of file
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 bd94f003cc42..6626797ef089 100644
--- a/src/main/java/org/junit/experimental/theories/internal/Assignments.java
+++ b/src/main/java/org/junit/experimental/theories/internal/Assignments.java
@@ -1,8 +1,8 @@
-/**
- *
- */
package org.junit.experimental.theories.internal;
+import static java.util.Collections.emptyList;
+
+import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
@@ -19,115 +19,135 @@
* parameters
*/
public class Assignments {
- private List fAssigned;
-
- private final List fUnassigned;
-
- private final TestClass fClass;
-
- private Assignments(List assigned,
- List unassigned, TestClass testClass) {
- fUnassigned= unassigned;
- fAssigned= assigned;
- fClass= testClass;
- }
-
- /**
- * Returns a new assignment list for {@code testMethod}, with no params
- * assigned.
- */
- public static Assignments allUnassigned(Method testMethod,
- TestClass testClass) throws Exception {
- List signatures;
- signatures= ParameterSignature.signatures(testClass
- .getOnlyConstructor());
- signatures.addAll(ParameterSignature.signatures(testMethod));
- return new Assignments(new ArrayList(),
- signatures, testClass);
- }
-
- public boolean isComplete() {
- return fUnassigned.size() == 0;
- }
-
- public ParameterSignature nextUnassigned() {
- return fUnassigned.get(0);
- }
-
- public Assignments assignNext(PotentialAssignment source) {
- List assigned= new ArrayList(
- fAssigned);
- assigned.add(source);
-
- return new Assignments(assigned, fUnassigned.subList(1, fUnassigned
- .size()), fClass);
- }
-
- public Object[] getActualValues(int start, int stop, boolean nullsOk)
- throws CouldNotGenerateValueException {
- Object[] values= new Object[stop - start];
- for (int i= start; i < stop; i++) {
- Object value= fAssigned.get(i).getValue();
- if (value == null && !nullsOk)
- throw new CouldNotGenerateValueException();
- values[i - start]= value;
- }
- return values;
- }
-
- public List potentialsForNextUnassigned()
- throws InstantiationException, IllegalAccessException {
- ParameterSignature unassigned= nextUnassigned();
- return getSupplier(unassigned).getValueSources(unassigned);
- }
-
- public ParameterSupplier getSupplier(ParameterSignature unassigned)
- throws InstantiationException, IllegalAccessException {
- ParameterSupplier supplier= getAnnotatedSupplier(unassigned);
- if (supplier != null)
- return supplier;
-
- return new AllMembersSupplier(fClass);
- }
-
- public ParameterSupplier getAnnotatedSupplier(ParameterSignature unassigned)
- throws InstantiationException, IllegalAccessException {
- ParametersSuppliedBy annotation= unassigned
- .findDeepAnnotation(ParametersSuppliedBy.class);
- if (annotation == null)
- return null;
- return annotation.value().newInstance();
- }
-
- public Object[] getConstructorArguments(boolean nullsOk)
- throws CouldNotGenerateValueException {
- return getActualValues(0, getConstructorParameterCount(), nullsOk);
- }
-
- public Object[] getMethodArguments(boolean nullsOk)
- throws CouldNotGenerateValueException {
- return getActualValues(getConstructorParameterCount(),
- fAssigned.size(), nullsOk);
- }
-
- public Object[] getAllArguments(boolean nullsOk)
- throws CouldNotGenerateValueException {
- return getActualValues(0, fAssigned.size(), nullsOk);
- }
-
- private int getConstructorParameterCount() {
- List signatures= ParameterSignature
- .signatures(fClass.getOnlyConstructor());
- int constructorParameterCount= signatures.size();
- return constructorParameterCount;
- }
-
- public Object[] getArgumentStrings(boolean nullsOk)
- throws CouldNotGenerateValueException {
- Object[] values= new Object[fAssigned.size()];
- for (int i= 0; i < values.length; i++) {
- values[i]= fAssigned.get(i).getDescription();
- }
- return values;
- }
+ private final List assigned;
+
+ private final List unassigned;
+
+ private final TestClass clazz;
+
+ private Assignments(List assigned,
+ List unassigned, TestClass clazz) {
+ this.unassigned = unassigned;
+ this.assigned = assigned;
+ this.clazz = clazz;
+ }
+
+ /**
+ * Returns a new assignment list for {@code testMethod}, with no params
+ * assigned.
+ */
+ public static Assignments allUnassigned(Method testMethod,
+ TestClass testClass) {
+ List signatures;
+ signatures = ParameterSignature.signatures(testClass
+ .getOnlyConstructor());
+ signatures.addAll(ParameterSignature.signatures(testMethod));
+ return new Assignments(new ArrayList(),
+ signatures, testClass);
+ }
+
+ public boolean isComplete() {
+ return unassigned.isEmpty();
+ }
+
+ public ParameterSignature nextUnassigned() {
+ return unassigned.get(0);
+ }
+
+ public Assignments assignNext(PotentialAssignment source) {
+ List