Repository: junit-team/junit4
Branch: main
Commit: 71c33ce55523
Files: 560
Total size: 1.8 MB
Directory structure:
gitextract_yvgvpu6o/
├── .gitattributes
├── .github/
│ ├── ISSUE_TEMPLATE/
│ │ ├── bug_report.md
│ │ └── config.yml
│ ├── PULL_REQUEST_TEMPLATE.md
│ └── workflows/
│ ├── main.yml
│ └── settings.xml
├── .gitignore
├── .mvn/
│ └── wrapper/
│ └── maven-wrapper.properties
├── .settings/
│ ├── org.eclipse.jdt.core.prefs
│ └── org.eclipse.jdt.ui.prefs
├── BUILDING
├── CODING_STYLE.txt
├── CONTRIBUTING.md
├── KEYS
├── LEGACY_CODING_STYLE.txt
├── LICENSE-junit.txt
├── NOTICE.txt
├── README.md
├── SECURITY.md
├── acknowledgements.txt
├── doc/
│ ├── ReleaseNotes4.10.html
│ ├── ReleaseNotes4.10.md
│ ├── ReleaseNotes4.10.txt
│ ├── ReleaseNotes4.11.html
│ ├── ReleaseNotes4.11.md
│ ├── ReleaseNotes4.11.txt
│ ├── ReleaseNotes4.12.md
│ ├── ReleaseNotes4.13.1.md
│ ├── ReleaseNotes4.13.2.md
│ ├── ReleaseNotes4.13.md
│ ├── ReleaseNotes4.4.html
│ ├── ReleaseNotes4.4.md
│ ├── ReleaseNotes4.4.txt
│ ├── ReleaseNotes4.5.html
│ ├── ReleaseNotes4.5.md
│ ├── ReleaseNotes4.5.txt
│ ├── ReleaseNotes4.6.html
│ ├── ReleaseNotes4.6.md
│ ├── ReleaseNotes4.6.txt
│ ├── ReleaseNotes4.7.html
│ ├── ReleaseNotes4.7.md
│ ├── ReleaseNotes4.7.txt
│ ├── ReleaseNotes4.8.1.html
│ ├── ReleaseNotes4.8.1.md
│ ├── ReleaseNotes4.8.1.txt
│ ├── ReleaseNotes4.8.2.html
│ ├── ReleaseNotes4.8.2.md
│ ├── ReleaseNotes4.8.2.txt
│ ├── ReleaseNotes4.8.html
│ ├── ReleaseNotes4.8.md
│ ├── ReleaseNotes4.8.txt
│ ├── ReleaseNotes4.9.1.md
│ ├── ReleaseNotes4.9.1.txt
│ ├── ReleaseNotes4.9.html
│ ├── ReleaseNotes4.9.md
│ ├── ReleaseNotes4.9.txt
│ ├── building-junit.txt
│ ├── cookstour/
│ │ └── cookstour.htm
│ ├── markdown.sh
│ └── testinfected/
│ └── testing.htm
├── epl-v10.html
├── mvnw
├── mvnw.cmd
├── pom.xml
├── src/
│ ├── main/
│ │ ├── java/
│ │ │ ├── junit/
│ │ │ │ ├── extensions/
│ │ │ │ │ ├── ActiveTestSuite.java
│ │ │ │ │ ├── RepeatedTest.java
│ │ │ │ │ ├── TestDecorator.java
│ │ │ │ │ ├── TestSetup.java
│ │ │ │ │ └── package-info.java
│ │ │ │ ├── framework/
│ │ │ │ │ ├── Assert.java
│ │ │ │ │ ├── AssertionFailedError.java
│ │ │ │ │ ├── ComparisonCompactor.java
│ │ │ │ │ ├── ComparisonFailure.java
│ │ │ │ │ ├── JUnit4TestAdapter.java
│ │ │ │ │ ├── JUnit4TestAdapterCache.java
│ │ │ │ │ ├── JUnit4TestCaseFacade.java
│ │ │ │ │ ├── Protectable.java
│ │ │ │ │ ├── Test.java
│ │ │ │ │ ├── TestCase.java
│ │ │ │ │ ├── TestFailure.java
│ │ │ │ │ ├── TestListener.java
│ │ │ │ │ ├── TestResult.java
│ │ │ │ │ ├── TestSuite.java
│ │ │ │ │ └── package-info.java
│ │ │ │ ├── runner/
│ │ │ │ │ ├── BaseTestRunner.java
│ │ │ │ │ ├── TestRunListener.java
│ │ │ │ │ ├── Version.java
│ │ │ │ │ ├── Version.java.template
│ │ │ │ │ └── package-info.java
│ │ │ │ └── textui/
│ │ │ │ ├── ResultPrinter.java
│ │ │ │ ├── TestRunner.java
│ │ │ │ └── package-info.java
│ │ │ └── org/
│ │ │ └── junit/
│ │ │ ├── After.java
│ │ │ ├── AfterClass.java
│ │ │ ├── Assert.java
│ │ │ ├── Assume.java
│ │ │ ├── AssumptionViolatedException.java
│ │ │ ├── Before.java
│ │ │ ├── BeforeClass.java
│ │ │ ├── ClassRule.java
│ │ │ ├── ComparisonFailure.java
│ │ │ ├── FixMethodOrder.java
│ │ │ ├── Ignore.java
│ │ │ ├── Rule.java
│ │ │ ├── Test.java
│ │ │ ├── TestCouldNotBeSkippedException.java
│ │ │ ├── experimental/
│ │ │ │ ├── ParallelComputer.java
│ │ │ │ ├── categories/
│ │ │ │ │ ├── Categories.java
│ │ │ │ │ ├── Category.java
│ │ │ │ │ ├── CategoryFilterFactory.java
│ │ │ │ │ ├── CategoryValidator.java
│ │ │ │ │ ├── ExcludeCategories.java
│ │ │ │ │ └── IncludeCategories.java
│ │ │ │ ├── max/
│ │ │ │ │ ├── CouldNotReadCoreException.java
│ │ │ │ │ ├── MaxCore.java
│ │ │ │ │ └── MaxHistory.java
│ │ │ │ ├── results/
│ │ │ │ │ ├── FailureList.java
│ │ │ │ │ ├── PrintableResult.java
│ │ │ │ │ └── ResultMatchers.java
│ │ │ │ ├── runners/
│ │ │ │ │ └── Enclosed.java
│ │ │ │ └── theories/
│ │ │ │ ├── DataPoint.java
│ │ │ │ ├── DataPoints.java
│ │ │ │ ├── FromDataPoints.java
│ │ │ │ ├── ParameterSignature.java
│ │ │ │ ├── ParameterSupplier.java
│ │ │ │ ├── ParametersSuppliedBy.java
│ │ │ │ ├── PotentialAssignment.java
│ │ │ │ ├── Theories.java
│ │ │ │ ├── Theory.java
│ │ │ │ ├── internal/
│ │ │ │ │ ├── AllMembersSupplier.java
│ │ │ │ │ ├── Assignments.java
│ │ │ │ │ ├── BooleanSupplier.java
│ │ │ │ │ ├── EnumSupplier.java
│ │ │ │ │ ├── ParameterizedAssertionError.java
│ │ │ │ │ └── SpecificDataPointsSupplier.java
│ │ │ │ └── suppliers/
│ │ │ │ ├── TestedOn.java
│ │ │ │ └── TestedOnSupplier.java
│ │ │ ├── function/
│ │ │ │ └── ThrowingRunnable.java
│ │ │ ├── internal/
│ │ │ │ ├── ArrayComparisonFailure.java
│ │ │ │ ├── AssumptionViolatedException.java
│ │ │ │ ├── Checks.java
│ │ │ │ ├── Classes.java
│ │ │ │ ├── ComparisonCriteria.java
│ │ │ │ ├── ExactComparisonCriteria.java
│ │ │ │ ├── InexactComparisonCriteria.java
│ │ │ │ ├── JUnitSystem.java
│ │ │ │ ├── MethodSorter.java
│ │ │ │ ├── RealSystem.java
│ │ │ │ ├── SerializableMatcherDescription.java
│ │ │ │ ├── SerializableValueDescription.java
│ │ │ │ ├── TextListener.java
│ │ │ │ ├── Throwables.java
│ │ │ │ ├── builders/
│ │ │ │ │ ├── AllDefaultPossibilitiesBuilder.java
│ │ │ │ │ ├── AnnotatedBuilder.java
│ │ │ │ │ ├── IgnoredBuilder.java
│ │ │ │ │ ├── IgnoredClassRunner.java
│ │ │ │ │ ├── JUnit3Builder.java
│ │ │ │ │ ├── JUnit4Builder.java
│ │ │ │ │ ├── NullBuilder.java
│ │ │ │ │ └── SuiteMethodBuilder.java
│ │ │ │ ├── management/
│ │ │ │ │ ├── FakeRuntimeMXBean.java
│ │ │ │ │ ├── FakeThreadMXBean.java
│ │ │ │ │ ├── ManagementFactory.java
│ │ │ │ │ ├── ReflectiveRuntimeMXBean.java
│ │ │ │ │ ├── ReflectiveThreadMXBean.java
│ │ │ │ │ ├── RuntimeMXBean.java
│ │ │ │ │ └── ThreadMXBean.java
│ │ │ │ ├── matchers/
│ │ │ │ │ ├── StacktracePrintingMatcher.java
│ │ │ │ │ ├── ThrowableCauseMatcher.java
│ │ │ │ │ ├── ThrowableMessageMatcher.java
│ │ │ │ │ └── TypeSafeMatcher.java
│ │ │ │ ├── requests/
│ │ │ │ │ ├── ClassRequest.java
│ │ │ │ │ ├── FilterRequest.java
│ │ │ │ │ ├── MemoizingRequest.java
│ │ │ │ │ ├── OrderingRequest.java
│ │ │ │ │ ├── SortingRequest.java
│ │ │ │ │ └── package-info.java
│ │ │ │ └── runners/
│ │ │ │ ├── ClassRoadie.java
│ │ │ │ ├── ErrorReportingRunner.java
│ │ │ │ ├── FailedBefore.java
│ │ │ │ ├── InitializationError.java
│ │ │ │ ├── JUnit38ClassRunner.java
│ │ │ │ ├── JUnit4ClassRunner.java
│ │ │ │ ├── MethodRoadie.java
│ │ │ │ ├── MethodValidator.java
│ │ │ │ ├── SuiteMethod.java
│ │ │ │ ├── TestClass.java
│ │ │ │ ├── TestMethod.java
│ │ │ │ ├── model/
│ │ │ │ │ ├── EachTestNotifier.java
│ │ │ │ │ ├── MultipleFailureException.java
│ │ │ │ │ └── ReflectiveCallable.java
│ │ │ │ ├── package-info.java
│ │ │ │ ├── rules/
│ │ │ │ │ ├── RuleMemberValidator.java
│ │ │ │ │ └── ValidationError.java
│ │ │ │ └── statements/
│ │ │ │ ├── ExpectException.java
│ │ │ │ ├── Fail.java
│ │ │ │ ├── FailOnTimeout.java
│ │ │ │ ├── InvokeMethod.java
│ │ │ │ ├── RunAfters.java
│ │ │ │ └── RunBefores.java
│ │ │ ├── matchers/
│ │ │ │ ├── JUnitMatchers.java
│ │ │ │ └── package-info.java
│ │ │ ├── package-info.java
│ │ │ ├── rules/
│ │ │ │ ├── DisableOnDebug.java
│ │ │ │ ├── ErrorCollector.java
│ │ │ │ ├── ExpectedException.java
│ │ │ │ ├── ExpectedExceptionMatcherBuilder.java
│ │ │ │ ├── ExternalResource.java
│ │ │ │ ├── MethodRule.java
│ │ │ │ ├── RuleChain.java
│ │ │ │ ├── RunRules.java
│ │ │ │ ├── Stopwatch.java
│ │ │ │ ├── TemporaryFolder.java
│ │ │ │ ├── TestName.java
│ │ │ │ ├── TestRule.java
│ │ │ │ ├── TestWatcher.java
│ │ │ │ ├── TestWatchman.java
│ │ │ │ ├── Timeout.java
│ │ │ │ └── Verifier.java
│ │ │ ├── runner/
│ │ │ │ ├── Computer.java
│ │ │ │ ├── Describable.java
│ │ │ │ ├── Description.java
│ │ │ │ ├── FilterFactories.java
│ │ │ │ ├── FilterFactory.java
│ │ │ │ ├── FilterFactoryParams.java
│ │ │ │ ├── JUnitCommandLineParseResult.java
│ │ │ │ ├── JUnitCore.java
│ │ │ │ ├── OrderWith.java
│ │ │ │ ├── OrderWithValidator.java
│ │ │ │ ├── Request.java
│ │ │ │ ├── Result.java
│ │ │ │ ├── RunWith.java
│ │ │ │ ├── Runner.java
│ │ │ │ ├── manipulation/
│ │ │ │ │ ├── Alphanumeric.java
│ │ │ │ │ ├── Filter.java
│ │ │ │ │ ├── Filterable.java
│ │ │ │ │ ├── InvalidOrderingException.java
│ │ │ │ │ ├── NoTestsRemainException.java
│ │ │ │ │ ├── Orderable.java
│ │ │ │ │ ├── Orderer.java
│ │ │ │ │ ├── Ordering.java
│ │ │ │ │ ├── Sortable.java
│ │ │ │ │ ├── Sorter.java
│ │ │ │ │ └── package-info.java
│ │ │ │ ├── notification/
│ │ │ │ │ ├── Failure.java
│ │ │ │ │ ├── RunListener.java
│ │ │ │ │ ├── RunNotifier.java
│ │ │ │ │ ├── StoppedByUserException.java
│ │ │ │ │ ├── SynchronizedRunListener.java
│ │ │ │ │ └── package-info.java
│ │ │ │ └── package-info.java
│ │ │ ├── runners/
│ │ │ │ ├── AllTests.java
│ │ │ │ ├── BlockJUnit4ClassRunner.java
│ │ │ │ ├── JUnit4.java
│ │ │ │ ├── MethodSorters.java
│ │ │ │ ├── Parameterized.java
│ │ │ │ ├── ParentRunner.java
│ │ │ │ ├── RuleContainer.java
│ │ │ │ ├── Suite.java
│ │ │ │ ├── model/
│ │ │ │ │ ├── Annotatable.java
│ │ │ │ │ ├── FrameworkField.java
│ │ │ │ │ ├── FrameworkMember.java
│ │ │ │ │ ├── FrameworkMethod.java
│ │ │ │ │ ├── InitializationError.java
│ │ │ │ │ ├── InvalidTestClassError.java
│ │ │ │ │ ├── MemberValueConsumer.java
│ │ │ │ │ ├── MultipleFailureException.java
│ │ │ │ │ ├── NoGenericTypeParametersValidator.java
│ │ │ │ │ ├── RunnerBuilder.java
│ │ │ │ │ ├── RunnerScheduler.java
│ │ │ │ │ ├── Statement.java
│ │ │ │ │ ├── TestClass.java
│ │ │ │ │ └── TestTimedOutException.java
│ │ │ │ ├── package-info.java
│ │ │ │ └── parameterized/
│ │ │ │ ├── BlockJUnit4ClassRunnerWithParameters.java
│ │ │ │ ├── BlockJUnit4ClassRunnerWithParametersFactory.java
│ │ │ │ ├── ParametersRunnerFactory.java
│ │ │ │ └── TestWithParameters.java
│ │ │ └── validator/
│ │ │ ├── AnnotationValidator.java
│ │ │ ├── AnnotationValidatorFactory.java
│ │ │ ├── AnnotationsValidator.java
│ │ │ ├── PublicClassValidator.java
│ │ │ ├── TestClassValidator.java
│ │ │ └── ValidateWith.java
│ │ └── javadoc/
│ │ └── stylesheet.css
│ ├── site/
│ │ ├── fml/
│ │ │ └── faq.fml
│ │ ├── markdown/
│ │ │ └── cookbook.md
│ │ ├── resources/
│ │ │ ├── css/
│ │ │ │ ├── carousel.css
│ │ │ │ ├── junit-lambda.css
│ │ │ │ └── plain-links.css
│ │ │ └── scripts/
│ │ │ └── index.js
│ │ ├── site.xml
│ │ ├── xdoc/
│ │ │ └── index.xml
│ │ └── xhtml/
│ │ ├── junit-lambda-campaign.xhtml
│ │ ├── junit-lambda-contributors.xhtml
│ │ ├── junit-lambda-spending.xhtml
│ │ ├── junit-lambda.xhtml
│ │ └── junit5.xhtml
│ └── test/
│ ├── java/
│ │ ├── junit/
│ │ │ ├── samples/
│ │ │ │ ├── AllTests.java
│ │ │ │ ├── ListTest.java
│ │ │ │ ├── SimpleTest.java
│ │ │ │ ├── money/
│ │ │ │ │ ├── IMoney.java
│ │ │ │ │ ├── Money.java
│ │ │ │ │ ├── MoneyBag.java
│ │ │ │ │ ├── MoneyTest.java
│ │ │ │ │ └── package-info.java
│ │ │ │ └── package-info.java
│ │ │ └── tests/
│ │ │ ├── AllTests.java
│ │ │ ├── SampleJUnit3Tests.java
│ │ │ ├── WasRun.java
│ │ │ ├── extensions/
│ │ │ │ ├── ActiveTestTest.java
│ │ │ │ ├── AllTests.java
│ │ │ │ ├── ExtensionTest.java
│ │ │ │ ├── RepeatedTestTest.java
│ │ │ │ └── package-info.java
│ │ │ ├── framework/
│ │ │ │ ├── AllTests.java
│ │ │ │ ├── AssertTest.java
│ │ │ │ ├── AssertionFailedErrorTest.java
│ │ │ │ ├── ComparisonCompactorTest.java
│ │ │ │ ├── ComparisonFailureTest.java
│ │ │ │ ├── DoublePrecisionAssertTest.java
│ │ │ │ ├── Failure.java
│ │ │ │ ├── FloatAssertTest.java
│ │ │ │ ├── InheritedTestCase.java
│ │ │ │ ├── NoArgTestCaseTest.java
│ │ │ │ ├── NoTestCaseClass.java
│ │ │ │ ├── NoTestCases.java
│ │ │ │ ├── NotPublicTestCase.java
│ │ │ │ ├── NotVoidTestCase.java
│ │ │ │ ├── OneTestCase.java
│ │ │ │ ├── OverrideTestCase.java
│ │ │ │ ├── Success.java
│ │ │ │ ├── SuiteTest.java
│ │ │ │ ├── TestCaseTest.java
│ │ │ │ ├── TestImplementorTest.java
│ │ │ │ ├── TestListenerTest.java
│ │ │ │ ├── ThreeTestCases.java
│ │ │ │ └── package-info.java
│ │ │ ├── package-info.java
│ │ │ └── runner/
│ │ │ ├── AllTests.java
│ │ │ ├── BaseTestRunnerTest.java
│ │ │ ├── ResultTest.java
│ │ │ ├── StackFilterTest.java
│ │ │ ├── TextFeedbackTest.java
│ │ │ ├── TextRunnerSingleMethodTest.java
│ │ │ ├── TextRunnerTest.java
│ │ │ └── package-info.java
│ │ └── org/
│ │ └── junit/
│ │ ├── AssumptionViolatedExceptionTest.java
│ │ ├── experimental/
│ │ │ └── categories/
│ │ │ ├── AllCategoriesTests.java
│ │ │ ├── CategoriesAndParameterizedTest.java
│ │ │ ├── CategoryFilterFactoryTest.java
│ │ │ ├── CategoryTest.java
│ │ │ ├── CategoryValidatorTest.java
│ │ │ ├── JavadocTest.java
│ │ │ └── MultiCategoryTest.java
│ │ ├── internal/
│ │ │ ├── AllInternalTests.java
│ │ │ ├── ArrayComparisonFailureTest.java
│ │ │ ├── ChecksTest.java
│ │ │ ├── MethodSorterTest.java
│ │ │ ├── StackTracesTest.java
│ │ │ ├── builders/
│ │ │ │ └── AnnotatedBuilderTest.java
│ │ │ ├── matchers/
│ │ │ │ ├── StacktracePrintingMatcherTest.java
│ │ │ │ └── ThrowableCauseMatcherTest.java
│ │ │ └── runners/
│ │ │ ├── ErrorReportingRunnerTest.java
│ │ │ └── statements/
│ │ │ ├── ExpectExceptionTest.java
│ │ │ └── FailOnTimeoutTest.java
│ │ ├── rules/
│ │ │ ├── AllRulesTests.java
│ │ │ ├── BlockJUnit4ClassRunnerOverrideTest.java
│ │ │ ├── ClassRulesTest.java
│ │ │ ├── DisableOnDebugTest.java
│ │ │ ├── ErrorCollectorTest.java
│ │ │ ├── EventCollector.java
│ │ │ ├── ExpectedExceptionTest.java
│ │ │ ├── ExternalResourceRuleTest.java
│ │ │ ├── LoggingMethodRule.java
│ │ │ ├── LoggingStatement.java
│ │ │ ├── LoggingTestRule.java
│ │ │ ├── LoggingTestWatcher.java
│ │ │ ├── MethodRulesTest.java
│ │ │ ├── NameRulesTest.java
│ │ │ ├── RuleChainTest.java
│ │ │ ├── RuleMemberValidatorTest.java
│ │ │ ├── StopwatchTest.java
│ │ │ ├── TempFolderRuleTest.java
│ │ │ ├── TemporaryFolderRuleAssuredDeletionTest.java
│ │ │ ├── TemporaryFolderUsageTest.java
│ │ │ ├── TestRuleTest.java
│ │ │ ├── TestWatcherTest.java
│ │ │ ├── TestWatchmanTest.java
│ │ │ ├── TimeoutRuleTest.java
│ │ │ └── VerifierRuleTest.java
│ │ ├── runner/
│ │ │ ├── AllRunnerTests.java
│ │ │ ├── FilterFactoriesTest.java
│ │ │ ├── FilterOptionIntegrationTest.java
│ │ │ ├── JUnitCommandLineParseResultTest.java
│ │ │ ├── JUnitCoreTest.java
│ │ │ ├── MainRunner.java
│ │ │ ├── OrderWithValidatorTest.java
│ │ │ ├── RequestTest.java
│ │ │ ├── RunnerSpy.java
│ │ │ └── notification/
│ │ │ ├── AllNotificationTests.java
│ │ │ ├── ConcurrentRunNotifierTest.java
│ │ │ ├── RunNotifierTest.java
│ │ │ └── SynchronizedRunListenerTest.java
│ │ ├── runners/
│ │ │ ├── AllRunnersTests.java
│ │ │ ├── CustomBlockJUnit4ClassRunnerTest.java
│ │ │ ├── RuleContainerTest.java
│ │ │ ├── model/
│ │ │ │ ├── AllModelTests.java
│ │ │ │ ├── FrameworkFieldTest.java
│ │ │ │ ├── FrameworkMethodTest.java
│ │ │ │ ├── InvalidTestClassErrorTest.java
│ │ │ │ ├── RunnerBuilderStub.java
│ │ │ │ └── TestClassTest.java
│ │ │ └── parameterized/
│ │ │ ├── AllParameterizedTests.java
│ │ │ ├── BlockJUnit4ClassRunnerWithParametersTest.java
│ │ │ ├── ParameterizedNamesTest.java
│ │ │ └── TestWithParametersTest.java
│ │ ├── samples/
│ │ │ ├── AllSamplesTests.java
│ │ │ ├── ListTest.java
│ │ │ ├── SimpleTest.java
│ │ │ ├── money/
│ │ │ │ ├── MoneyTest.java
│ │ │ │ └── package-info.java
│ │ │ └── package-info.java
│ │ ├── tests/
│ │ │ ├── AllTests.java
│ │ │ ├── ObjectContractTest.java
│ │ │ ├── SampleJUnit4Tests.java
│ │ │ ├── TestSystem.java
│ │ │ ├── assertion/
│ │ │ │ ├── AllAssertionTests.java
│ │ │ │ ├── AssertionTest.java
│ │ │ │ ├── ComparisonFailureTest.java
│ │ │ │ └── MultipleFailureExceptionTest.java
│ │ │ ├── deprecated/
│ │ │ │ ├── AllDeprecatedTests.java
│ │ │ │ └── JUnit4ClassRunnerTest.java
│ │ │ ├── description/
│ │ │ │ ├── AllDescriptionTests.java
│ │ │ │ ├── AnnotatedDescriptionTest.java
│ │ │ │ ├── SuiteDescriptionTest.java
│ │ │ │ ├── TestDescriptionMethodNameTest.java
│ │ │ │ └── TestDescriptionTest.java
│ │ │ ├── experimental/
│ │ │ │ ├── AllExperimentalTests.java
│ │ │ │ ├── AssumptionTest.java
│ │ │ │ ├── MatcherTest.java
│ │ │ │ ├── max/
│ │ │ │ │ ├── AllMaxTests.java
│ │ │ │ │ ├── DescriptionTest.java
│ │ │ │ │ ├── JUnit38SortingTest.java
│ │ │ │ │ └── MaxStarterTest.java
│ │ │ │ ├── parallel/
│ │ │ │ │ ├── AllParallelTests.java
│ │ │ │ │ ├── ParallelClassTest.java
│ │ │ │ │ └── ParallelMethodTest.java
│ │ │ │ ├── results/
│ │ │ │ │ ├── AllResultsTests.java
│ │ │ │ │ ├── PrintableResultTest.java
│ │ │ │ │ └── ResultMatchersTest.java
│ │ │ │ └── theories/
│ │ │ │ ├── AllTheoriesTests.java
│ │ │ │ ├── AssumingInTheoriesTest.java
│ │ │ │ ├── ParameterSignatureTest.java
│ │ │ │ ├── PotentialAssignmentTest.java
│ │ │ │ ├── TestedOnSupplierTest.java
│ │ │ │ ├── TheoryTestUtils.java
│ │ │ │ ├── extendingwithstubs/
│ │ │ │ │ ├── Correspondent.java
│ │ │ │ │ ├── Guesser.java
│ │ │ │ │ ├── GuesserQueue.java
│ │ │ │ │ ├── MethodCall.java
│ │ │ │ │ ├── ReguessableValue.java
│ │ │ │ │ ├── StringableObject.java
│ │ │ │ │ ├── Stub.java
│ │ │ │ │ ├── StubbedTheories.java
│ │ │ │ │ └── StubbedTheoriesTest.java
│ │ │ │ ├── internal/
│ │ │ │ │ ├── AllMembersSupplierTest.java
│ │ │ │ │ ├── AllTheoriesInternalTests.java
│ │ │ │ │ ├── ParameterizedAssertionErrorTest.java
│ │ │ │ │ └── SpecificDataPointsSupplierTest.java
│ │ │ │ └── runner/
│ │ │ │ ├── AllTheoriesRunnerTests.java
│ │ │ │ ├── FailingDataPointMethods.java
│ │ │ │ ├── SuccessfulWithDataPointFields.java
│ │ │ │ ├── TheoriesPerformanceTest.java
│ │ │ │ ├── TypeMatchingBetweenMultiDataPointsMethod.java
│ │ │ │ ├── UnsuccessfulWithDataPointFields.java
│ │ │ │ ├── WhenNoParametersMatch.java
│ │ │ │ ├── WithAutoGeneratedDataPoints.java
│ │ │ │ ├── WithDataPointMethod.java
│ │ │ │ ├── WithExtendedParameterSources.java
│ │ │ │ ├── WithNamedDataPoints.java
│ │ │ │ ├── WithOnlyTestAnnotations.java
│ │ │ │ ├── WithParameterSupplier.java
│ │ │ │ └── WithUnresolvedGenericTypeVariablesOnTheoryParms.java
│ │ │ ├── junit3compatibility/
│ │ │ │ ├── AllJUnit3CompatibilityTests.java
│ │ │ │ ├── AllTestsTest.java
│ │ │ │ ├── ClassRequestTest.java
│ │ │ │ ├── ForwardCompatibilityPrintingTest.java
│ │ │ │ ├── ForwardCompatibilityTest.java
│ │ │ │ ├── InitializationErrorForwardCompatibilityTest.java
│ │ │ │ ├── JUnit38ClassRunnerTest.java
│ │ │ │ ├── JUnit4TestAdapterTest.java
│ │ │ │ ├── OldTestClassAdaptingListenerTest.java
│ │ │ │ ├── OldTests.java
│ │ │ │ └── SuiteMethodTest.java
│ │ │ ├── listening/
│ │ │ │ ├── AllListeningTests.java
│ │ │ │ ├── ListenerTest.java
│ │ │ │ ├── RunnerTest.java
│ │ │ │ ├── TestListenerTest.java
│ │ │ │ ├── TextListenerTest.java
│ │ │ │ └── UserStopTest.java
│ │ │ ├── manipulation/
│ │ │ │ ├── AllManipulationTests.java
│ │ │ │ ├── AlphanumericOrdering.java
│ │ │ │ ├── ComparatorBasedOrdering.java
│ │ │ │ ├── Comparators.java
│ │ │ │ ├── FilterTest.java
│ │ │ │ ├── FilterableTest.java
│ │ │ │ ├── OrderWithTest.java
│ │ │ │ ├── OrderableTest.java
│ │ │ │ ├── ReverseAlphanumericOrdering.java
│ │ │ │ ├── ReverseAlphanumericSorter.java
│ │ │ │ ├── SingleMethodTest.java
│ │ │ │ └── SortableTest.java
│ │ │ ├── package-info.java
│ │ │ ├── running/
│ │ │ │ ├── AllRunningTests.java
│ │ │ │ ├── classes/
│ │ │ │ │ ├── AllClassesTests.java
│ │ │ │ │ ├── BlockJUnit4ClassRunnerTest.java
│ │ │ │ │ ├── ClassLevelMethodsWithIgnoredTestsTest.java
│ │ │ │ │ ├── EnclosedTest.java
│ │ │ │ │ ├── IgnoreClassTest.java
│ │ │ │ │ ├── ParameterizedTestTest.java
│ │ │ │ │ ├── ParentRunnerFilteringTest.java
│ │ │ │ │ ├── ParentRunnerTest.java
│ │ │ │ │ ├── RunWithTest.java
│ │ │ │ │ ├── SuiteTest.java
│ │ │ │ │ ├── ThreadsTest.java
│ │ │ │ │ ├── UseSuiteAsASuperclassTest.java
│ │ │ │ │ └── parent/
│ │ │ │ │ ├── ParentRunnerClassLoaderTest.java
│ │ │ │ │ └── TestWithClassRule.java
│ │ │ │ ├── core/
│ │ │ │ │ ├── AllCoreTests.java
│ │ │ │ │ ├── CommandLineTest.java
│ │ │ │ │ ├── JUnitCoreReturnsCorrectExitCodeTest.java
│ │ │ │ │ └── SystemExitTest.java
│ │ │ │ └── methods/
│ │ │ │ ├── AllMethodsTests.java
│ │ │ │ ├── AnnotationTest.java
│ │ │ │ ├── ExpectedTest.java
│ │ │ │ ├── InheritedTestTest.java
│ │ │ │ ├── ParameterizedTestMethodTest.java
│ │ │ │ ├── TestMethodTest.java
│ │ │ │ └── TimeoutTest.java
│ │ │ └── validation/
│ │ │ ├── AllValidationTests.java
│ │ │ ├── BadlyFormedClassesTest.java
│ │ │ ├── FailedConstructionTest.java
│ │ │ ├── ValidationTest.java
│ │ │ └── anotherpackage/
│ │ │ ├── Sub.java
│ │ │ └── Super.java
│ │ └── validator/
│ │ ├── AllValidatorTests.java
│ │ ├── AnnotationValidatorFactoryTest.java
│ │ ├── AnnotationsValidatorTest.java
│ │ └── PublicClassValidatorTest.java
│ └── resources/
│ ├── junit/
│ │ └── tests/
│ │ └── runner/
│ │ ├── testRunAssumptionFailedResultCanBeReserialised_v4_12
│ │ ├── testRunAssumptionFailedResultCanBeReserialised_v4_13
│ │ ├── testRunFailureResultCanBeReserialised_v4_12
│ │ ├── testRunSuccessResultCanBeReserialised_v4_12
│ │ └── testRunSuccessResultCanBeReserialised_v4_13
│ └── org/
│ └── junit/
│ ├── assumptionViolatedExceptionWithValueAndMatcherCanBeReserialized_v4_13
│ ├── assumptionViolatedExceptionWithoutValueAndMatcherCanBeReserialized_v4_13
│ └── internal/
│ ├── arrayComparisonFailure_411
│ └── arrayComparisonFailure_412
└── to-do.txt
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitattributes
================================================
* 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
================================================
FILE: .github/ISSUE_TEMPLATE/bug_report.md
================================================
---
name: Report a critical bug
about: Please only report critical bugs since the project is in maintenance mode
type: Bug
---
> [!IMPORTANT]
> **JUnit 4 is in maintenance mode.**
>
> At this point, only critical bugs and security issues will be fixed.
> All other issues and PRs will therefore be declined.
> For ongoing development, please check out the [junit-framework](https://github.com/junit-team/junit-framework/) repository.
================================================
FILE: .github/ISSUE_TEMPLATE/config.yml
================================================
blank_issues_enabled: false
================================================
FILE: .github/PULL_REQUEST_TEMPLATE.md
================================================
> [!IMPORTANT]
> **JUnit 4 is in maintenance mode.**
>
> At this point, only critical bugs and security issues will be fixed.
> All other issues and PRs will therefore be declined.
> For ongoing development, please check out the [junit-framework](https://github.com/junit-team/junit-framework/) repository.
## Overview
================================================
FILE: .github/workflows/main.yml
================================================
name: CI
on:
push:
branches:
- main
pull_request:
branches:
- '*'
permissions:
contents: read # to fetch code (actions/checkout)
jobs:
build-and-verify:
name: Build and verify (JDK ${{ matrix.java }})
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
java: ['8', '11', '17', '21']
steps:
- uses: actions/checkout@v2
- name: Download Maven # Download with default JDK because OpenJDK 6 does not support TLS 1.2
run: ./mvnw --version
- name: Set up JDK 6
if: ${{ matrix.java == '6'}}
uses: actions/setup-java@v4
with:
java-version: ${{ matrix.java }}
distribution: temurin
- name: Set up JDK
if: ${{ matrix.java != '6'}}
uses: actions/setup-java@v4
with:
java-version: ${{ matrix.java }}
distribution: temurin
cache: maven
- name: Build and verify
run: ./mvnw verify javadoc:javadoc site:site --batch-mode --errors --settings .github/workflows/settings.xml
publish-snapshots:
name: Publish snapshot artifacts
if: github.event_name == 'push' && github.repository == 'junit-team/junit4' && github.ref == 'refs/heads/main'
needs: build-and-verify
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Download Maven # Download with default JDK because OpenJDK 6 does not support TLS 1.2
run: ./mvnw --version
- name: Set up JDK
uses: actions/setup-java@v4
with:
java-version: 8
distribution: temurin
- name: Publish snapshot artifacts
env:
MAVEN_CENTRAL_USERNAME: ${{ secrets.MAVEN_CENTRAL_USERNAME }}
MAVEN_CENTRAL_PASSWORD: ${{ secrets.MAVEN_CENTRAL_PASSWORD }}
run: ./mvnw deploy --batch-mode --errors --activate-profiles generate-docs --settings .github/workflows/settings.xml
================================================
FILE: .github/workflows/settings.xml
================================================
central-portal${env.MAVEN_CENTRAL_USERNAME}${env.MAVEN_CENTRAL_PASSWORD}
================================================
FILE: .gitignore
================================================
MaxCore.ser
bin
junit4.*
target
MaxCore.max
# IntelliJ
.idea
*.ipr
*.iml
*.iws
out
java.hprof.txt
.DS_Store
================================================
FILE: .mvn/wrapper/maven-wrapper.properties
================================================
# 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.
wrapperVersion=3.3.1
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.6/apache-maven-3.9.6-bin.zip
================================================
FILE: .settings/org.eclipse.jdt.core.prefs
================================================
#Mon Oct 12 21:57:10 EDT 2009
eclipse.preferences.version=1
org.eclipse.jdt.core.codeComplete.argumentPrefixes=
org.eclipse.jdt.core.codeComplete.argumentSuffixes=
org.eclipse.jdt.core.codeComplete.fieldPrefixes=f
org.eclipse.jdt.core.codeComplete.fieldSuffixes=
org.eclipse.jdt.core.codeComplete.localPrefixes=
org.eclipse.jdt.core.codeComplete.localSuffixes=
org.eclipse.jdt.core.codeComplete.staticFieldPrefixes=
org.eclipse.jdt.core.codeComplete.staticFieldSuffixes=
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
org.eclipse.jdt.core.compiler.compliance=1.5
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
org.eclipse.jdt.core.compiler.doc.comment.support=enabled
org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.autoboxing=ignore
org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning
org.eclipse.jdt.core.compiler.problem.deadCode=warning
org.eclipse.jdt.core.compiler.problem.deprecation=warning
org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled
org.eclipse.jdt.core.compiler.problem.discouragedReference=ignore
org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore
org.eclipse.jdt.core.compiler.problem.fatalOptionalError=enabled
org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore
org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning
org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning
org.eclipse.jdt.core.compiler.problem.forbiddenReference=error
org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning
org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=ignore
org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore
org.eclipse.jdt.core.compiler.problem.invalidJavadoc=warning
org.eclipse.jdt.core.compiler.problem.invalidJavadocTags=disabled
org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsDeprecatedRef=disabled
org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsNotVisibleRef=disabled
org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility=protected
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=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
org.eclipse.jdt.core.compiler.problem.missingJavadocTags=ignore
org.eclipse.jdt.core.compiler.problem.missingJavadocTagsOverriding=disabled
org.eclipse.jdt.core.compiler.problem.missingJavadocTagsVisibility=protected
org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=warning
org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning
org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore
org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning
org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning
org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore
org.eclipse.jdt.core.compiler.problem.nullReference=warning
org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning
org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=ignore
org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore
org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning
org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore
org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=warning
org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning
org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore
org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning
org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning
org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore
org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning
org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore
org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=warning
org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=warning
org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled
org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled
org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled
org.eclipse.jdt.core.compiler.problem.unusedImport=warning
org.eclipse.jdt.core.compiler.problem.unusedLabel=warning
org.eclipse.jdt.core.compiler.problem.unusedLocal=warning
org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore
org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled
org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning
org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
org.eclipse.jdt.core.compiler.source=1.5
org.eclipse.jdt.core.compiler.taskCaseSensitive=enabled
org.eclipse.jdt.core.compiler.taskPriorities=NORMAL,NORMAL,HIGH,NORMAL
org.eclipse.jdt.core.compiler.taskTags=TODO,REVISIT,HACK,QUESTION
org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16
org.eclipse.jdt.core.formatter.alignment_for_assignment=0
org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16
org.eclipse.jdt.core.formatter.alignment_for_compact_if=16
org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80
org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0
org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16
org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16
org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16
org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16
org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16
org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16
org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16
org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16
org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16
org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16
org.eclipse.jdt.core.formatter.blank_lines_after_imports=1
org.eclipse.jdt.core.formatter.blank_lines_after_package=1
org.eclipse.jdt.core.formatter.blank_lines_before_field=1
org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0
org.eclipse.jdt.core.formatter.blank_lines_before_imports=1
org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1
org.eclipse.jdt.core.formatter.blank_lines_before_method=1
org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1
org.eclipse.jdt.core.formatter.blank_lines_before_package=0
org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1
org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1
org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line
org.eclipse.jdt.core.formatter.comment.clear_blank_lines=false
org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false
org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false
org.eclipse.jdt.core.formatter.comment.format_block_comments=true
org.eclipse.jdt.core.formatter.comment.format_comments=true
org.eclipse.jdt.core.formatter.comment.format_header=false
org.eclipse.jdt.core.formatter.comment.format_html=true
org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true
org.eclipse.jdt.core.formatter.comment.format_line_comments=true
org.eclipse.jdt.core.formatter.comment.format_source_code=true
org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true
org.eclipse.jdt.core.formatter.comment.indent_root_tags=true
org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert
org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=insert
org.eclipse.jdt.core.formatter.comment.line_length=80
org.eclipse.jdt.core.formatter.compact_else_if=true
org.eclipse.jdt.core.formatter.continuation_indentation=2
org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2
org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false
org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true
org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true
org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true
org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true
org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true
org.eclipse.jdt.core.formatter.indent_empty_lines=false
org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true
org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true
org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true
org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=false
org.eclipse.jdt.core.formatter.indentation.size=4
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation=insert
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_member=insert
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert
org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert
org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert
org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert
org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert
org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert
org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert
org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert
org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert
org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert
org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert
org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert
org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert
org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert
org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert
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=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
org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert
org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert
org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert
org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert
org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert
org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert
org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert
org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert
org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert
org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert
org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert
org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert
org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert
org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false
org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false
org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false
org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false
org.eclipse.jdt.core.formatter.lineSplit=80
org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false
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=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
================================================
FILE: .settings/org.eclipse.jdt.ui.prefs
================================================
#Tue Jul 22 09:31:38 PDT 2008
eclipse.preferences.version=1
formatter_profile=_junit
formatter_settings_version=11
internal.default.compliance=default
org.eclipse.jdt.ui.exception.name=e
org.eclipse.jdt.ui.gettersetter.use.is=true
org.eclipse.jdt.ui.ignorelowercasenames=true
org.eclipse.jdt.ui.importorder=java;javax;com;
org.eclipse.jdt.ui.keywordthis=false
org.eclipse.jdt.ui.ondemandthreshold=99
org.eclipse.jdt.ui.overrideannotation=true
org.eclipse.jdt.ui.text.custom_code_templates=
================================================
FILE: BUILDING
================================================
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
================================================
FILE: CODING_STYLE.txt
================================================
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.
================================================
FILE: CONTRIBUTING.md
================================================
## 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).
## Building
### Command line
You need to have Maven and a JDK (at least version 1.5) installed.
Run `./mvnw verify` to build the code and run the tests
### Eclipse
Maven can generate project files for Eclipse. See [these instructions](https://mkyong.com/maven/how-to-convert-maven-java-project-to-support-eclipse-ide/) for details.
## 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).
================================================
FILE: KEYS
================================================
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-----
================================================
FILE: LEGACY_CODING_STYLE.txt
================================================
==================================
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)
================================================
FILE: LICENSE-junit.txt
================================================
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.
================================================
FILE: NOTICE.txt
================================================
===================================================================================
== Notices and attributions required by libraries that the project depends on ==
===================================================================================
The JUnit depends on Java Hamcrest (http://hamcrest.org/JavaHamcrest/).
================================================
FILE: README.md
================================================
# JUnit 4
JUnit is a simple framework to write repeatable tests. It is an instance of the xUnit architecture for unit testing frameworks.
> [!IMPORTANT]
> **JUnit 4 is in maintenance mode.**
>
> At this point, only critical bugs and security issues will be fixed.
> All other issues and PRs will therefore be declined.
> For ongoing development, please check out the [junit-framework](https://github.com/junit-team/junit-framework/) repository.
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://github.com/junit-team/junit4/actions)
================================================
FILE: SECURITY.md
================================================
# Security Policy
## Supported Versions
| Version | Supported |
| ------- | ------------------ |
| 4.13.x | :white_check_mark: |
| < 4.13 | :x: |
## Reporting a Vulnerability
To report a security vulnerability, please send an email to security@junit.org.
================================================
FILE: acknowledgements.txt
================================================
2006 March 9
Matthias Schmidt: improved org.junit package javadoc
2006 August 3
giovanni: better test for TestCase without a name.
Matthias Pfau: better error message when test case constructor fails
2006 November 21
dakcalouro: Found defect with comparing ints and longs (1555161)
Ben Maurer: Found defect with timeouts taking twice as long as specified (1536198)
2007 February 08
Kazimierz Pogoda: Found defect with null array elements (1438163)
2007 July 09
wangqq: Found defect with @After not running after a timeout (1745048)
2007 July 18
Andrew Dick: Found defect with assertEquals comparing non-Integer Numbers (1715326)
Michael Schechter: Found defect with Filters and suite() methods (1739095)
2008 February 5
Walter Gildersleeve: Found assertEquals(null, "null") defect (1857283)
2008 July 1
Johannes Link: Submitted test for running subclasses of Suite
2008 July 23
Daniel Brolund: Submitted patch for build.xml, fixing 1.5 compatibility (2021396)
2008 Aug 1
Nat Pryce: Found defect in treatment of validation errors from custom
subclasses of the legacy JUnit4ClassRunner.
2008 Aug 18
Nir Soffer: Suggested adding to the cookbook information about running
running JUnit from the command line.
2008 Aug 19
Jack Woehr: Discovered build.xml was missing from junit-4.x.zip
2009 Jan 5
Amanda Robinson: Fixed overly permissive @DataPoint processing.
2009 Feb 9
Mark Shapiro: Discovered bug in test counting after an ignored method (2106324)
2009 Apr 20
Chris Felaco: Discovered regression in handling suite() methods with JUnit 3 runner (1812200)
Toby Byron: Suggested updating linking in javadoc (2090230)
Raphael Parree: Improved docs on Parameterized (2186792)
Robin de Silva Jayasinghe: Fixed Javadoc code sample for AfterClass (2126279)
2009 May 04
James Abbley: Submitted a patch that fixed the 2-second limit on Parallel execution.
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
================================================
FILE: doc/ReleaseNotes4.10.html
================================================
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]
================================================
FILE: doc/ReleaseNotes4.10.md
================================================
## 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]
================================================
FILE: doc/ReleaseNotes4.10.txt
================================================
Please see ReleaseNotes4.10.md
================================================
FILE: doc/ReleaseNotes4.11.html
================================================
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.
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:
@Test
public void featureMatcher() throws Exception {
assertThat("Hello World!", length(is(0)));
}
private Matcher<String> length(Matcher<? super Integer> matcher) {
return new FeatureMatcher<String, Integer>(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
@RunWith(Parameterized.class)
public class FibonacciTest {
@Parameters(name = "{index}: fib({0})={1}")
public static Iterable<Object[]> data() {
return Arrays.asList(new Object[][] { { 0, 0 }, { 1, 1 }, { 2, 1 },
{ 3, 2 }, { 4, 3 }, { 5, 5 }, { 6, 8 } });
}
private int input;
private int expected;
public FibonacciTest(int input, int expected) {
this.input = input;
this.expected = expected;
}
@Test
public void test() {
assertEquals(expected, Fibonacci.compute(input));
}
}
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.
================================================
FILE: doc/ReleaseNotes4.11.md
================================================
## 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
*
* @see Theories
*
* @since 4.4
*/
public class Assume {
/**
* Do not instantiate.
* @deprecated since 4.13.
*/
@Deprecated
public Assume() {
}
/**
* If called with an expression evaluating to {@code false}, the test will halt and be ignored.
*/
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);
}
/**
* 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());
}
/**
* 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());
}
}
================================================
FILE: src/main/java/org/junit/AssumptionViolatedException.java
================================================
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);
}
}
================================================
FILE: src/main/java/org/junit/Before.java
================================================
package org.junit;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 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,
* unless they are overridden in the current class. No other ordering is defined.
*
* Here is a simple example:
*
* public class Example {
* List empty;
* @Before public void initialize() {
* empty= new ArrayList();
* }
* @Test public void size() {
* ...
* }
* @Test public void remove() {
* ...
* }
* }
*
*
* @see org.junit.BeforeClass
* @see org.junit.After
* @since 4.0
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Before {
}
================================================
FILE: src/main/java/org/junit/BeforeClass.java
================================================
package org.junit;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 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
* the test methods in the class. The @BeforeClass methods of superclasses
* will be run before those of the current class, unless they are shadowed in the current class.
*
* For example:
*
* public class Example {
* @BeforeClass public static void onlyOnce() {
* ...
* }
* @Test public void one() {
* ...
* }
* @Test public void two() {
* ...
* }
* }
*
*
* @see org.junit.AfterClass
* @since 4.0
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface BeforeClass {
}
================================================
FILE: src/main/java/org/junit/ClassRule.java
================================================
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:
*
* @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();
* }
* };
* }
*
*
* and the same using a method
*
* @RunWith(Suite.class)
* @SuiteClasses({A.class, B.class, C.class})
* public class UsesExternalResource {
* public static Server myServer= new Server();
*
* @ClassRule
* public static ExternalResource getResource() {
* return new ExternalResource() {
* @Override
* protected void before() throws Throwable {
* myServer.connect();
* }
*
* @Override
* protected void after() {
* myServer.disconnect();
* }
* };
* }
* }
*
*
* 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;
}
================================================
FILE: src/main/java/org/junit/ComparisonFailure.java
================================================
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.
*
* Inspired by a patch from Alex Chaffee (alex@purpletech.com)
*
* @since 4.0
*/
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;
}
}
}
}
================================================
FILE: src/main/java/org/junit/FixMethodOrder.java
================================================
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;
}
================================================
FILE: src/main/java/org/junit/Ignore.java
================================================
package org.junit;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 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:
*
* @Ignore @Test public void something() { ...
*
* @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 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 "";
}
================================================
FILE: src/main/java/org/junit/Rule.java
================================================
package org.junit;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 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:
*
* 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");
* // ...
* }
* }
*
* 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 {
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;
}
================================================
FILE: src/main/java/org/junit/Test.java
================================================
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
* 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:
*
* public class Example {
* @Test
* public void method() {
* org.junit.Assert.assertTrue( new ArrayList().isEmpty() );
* }
* }
*
*
* 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() {
* new ArrayList<Object>().get(1);
* }
*
*
* 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 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;
}
================================================
FILE: src/main/java/org/junit/TestCouldNotBeSkippedException.java
================================================
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);
}
}
================================================
FILE: src/main/java/org/junit/experimental/ParallelComputer.java
================================================
package org.junit.experimental;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import org.junit.runner.Computer;
import org.junit.runner.Runner;
import org.junit.runners.ParentRunner;
import org.junit.runners.model.InitializationError;
import org.junit.runners.model.RunnerBuilder;
import org.junit.runners.model.RunnerScheduler;
public class ParallelComputer extends Computer {
private final boolean classes;
private final boolean 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 methods() {
return new ParallelComputer(false, true);
}
private static Runner parallelize(Runner runner) {
if (runner instanceof ParentRunner) {
((ParentRunner>) runner).setScheduler(new RunnerScheduler() {
private final ExecutorService fService = Executors.newCachedThreadPool();
public void schedule(Runnable childStatement) {
fService.submit(childStatement);
}
public void finished() {
try {
fService.shutdown();
fService.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
} catch (InterruptedException e) {
e.printStackTrace(System.err);
}
}
});
}
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
protected Runner getRunner(RunnerBuilder builder, Class> testClass)
throws Throwable {
Runner runner = super.getRunner(builder, testClass);
return methods ? parallelize(runner) : runner;
}
}
================================================
FILE: src/main/java/org/junit/experimental/categories/Categories.java
================================================
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);
}
}
================================================
FILE: src/main/java/org/junit/experimental/categories/Category.java
================================================
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();
}
================================================
FILE: src/main/java/org/junit/experimental/categories/CategoryFilterFactory.java
================================================
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;
}
}
================================================
FILE: src/main/java/org/junit/experimental/categories/CategoryValidator.java
================================================
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));
}
}
================================================
FILE: src/main/java/org/junit/experimental/categories/ExcludeCategories.java
================================================
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();
}
}
}
================================================
FILE: src/main/java/org/junit/experimental/categories/IncludeCategories.java
================================================
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();
}
}
}
================================================
FILE: src/main/java/org/junit/experimental/max/CouldNotReadCoreException.java
================================================
package org.junit.experimental.max;
/**
* Thrown when Max cannot read the MaxCore serialization
*/
public class CouldNotReadCoreException extends Exception {
private static final long serialVersionUID = 1L;
/**
* Constructs
*/
public CouldNotReadCoreException(Throwable e) {
super(e);
}
}
================================================
FILE: src/main/java/org/junit/experimental/max/MaxCore.java
================================================
package org.junit.experimental.max;
import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
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;
import org.junit.runner.Description;
import org.junit.runner.JUnitCore;
import org.junit.runner.Request;
import org.junit.runner.Result;
import org.junit.runner.Runner;
import org.junit.runners.Suite;
import org.junit.runners.model.InitializationError;
/**
* 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.
*
*/
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 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);
}
}
}
}
================================================
FILE: src/main/java/org/junit/experimental/max/MaxHistory.java
================================================
package org.junit.experimental.max;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;
import org.junit.runner.Description;
import org.junit.runner.Result;
import org.junit.runner.notification.Failure;
import org.junit.runner.notification.RunListener;
/**
* Stores a subset of the history of each test:
*
*
Last failure timestamp
*
Duration of last execution
*
*/
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);
}
}
/*
* 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();
}
}
================================================
FILE: src/main/java/org/junit/experimental/results/FailureList.java
================================================
package org.junit.experimental.results;
import java.util.List;
import org.junit.runner.Result;
import org.junit.runner.notification.Failure;
import org.junit.runner.notification.RunListener;
class FailureList {
private final List 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;
}
}
================================================
FILE: src/main/java/org/junit/experimental/results/PrintableResult.java
================================================
package org.junit.experimental.results;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.util.List;
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;
/**
* A test result that prints nicely in error messages.
* This is only intended to be used in JUnit self-tests.
* For example:
*
*
*/
public class PrintableResult {
private Result result;
/**
* The result of running JUnit on {@code type}
*/
public static PrintableResult testResult(Class> type) {
return testResult(Request.aClass(type));
}
/**
* The result of running JUnit on Request {@code request}
*/
public static PrintableResult testResult(Request request) {
return new PrintableResult(new JUnitCore().run(request));
}
/**
* A result that includes the given {@code failures}
*/
public PrintableResult(List failures) {
this(new FailureList(failures).result());
}
private PrintableResult(Result result) {
this.result = result;
}
/**
* Returns the number of failures in this result.
*/
public int failureCount() {
return result.getFailures().size();
}
/**
* Returns the failures in this result.
*
* @since 4.13
*/
public List failures() {
return result.getFailures();
}
@Override
public String toString() {
ByteArrayOutputStream stream = new ByteArrayOutputStream();
new TextListener(new PrintStream(stream)).testRunFinished(result);
return stream.toString();
}
}
================================================
FILE: src/main/java/org/junit/experimental/results/ResultMatchers.java
================================================
package org.junit.experimental.results;
import org.hamcrest.BaseMatcher;
import org.hamcrest.Description;
import org.hamcrest.Matcher;
import org.hamcrest.TypeSafeMatcher;
/**
* Matchers on a PrintableResult, to enable JUnit self-tests.
* For example:
*
*
*/
public class ResultMatchers {
/**
* Do not instantiate.
* @deprecated will be private soon.
*/
@Deprecated
public 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");
}
@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);
}
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);
}
};
}
}
================================================
FILE: src/main/java/org/junit/experimental/runners/Enclosed.java
================================================
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. 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, 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()]);
}
}
================================================
FILE: src/main/java/org/junit/experimental/theories/DataPoint.java
================================================
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 {};
}
================================================
FILE: src/main/java/org/junit/experimental/theories/DataPoints.java
================================================
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.
*
*
* @DataPoints
* public static String[] dataPoints = new String[] { ... };
*
* @DataPoints
* public static String[] generatedDataPoints() {
* return new String[] { ... };
* }
*
* @Theory
* public void theoryMethod(String param) {
* ...
* }
*
*
* @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 {};
}
================================================
FILE: src/main/java/org/junit/experimental/theories/FromDataPoints.java
================================================
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();
}
================================================
FILE: src/main/java/org/junit/experimental/theories/ParameterSignature.java
================================================
package org.junit.experimental.theories;
import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
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 {
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;
}
}
================================================
FILE: src/main/java/org/junit/experimental/theories/ParameterSupplier.java
================================================
package org.junit.experimental.theories;
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) throws Throwable;
}
================================================
FILE: src/main/java/org/junit/experimental/theories/ParametersSuppliedBy.java
================================================
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();
}
================================================
FILE: src/main/java/org/junit/experimental/theories/PotentialAssignment.java
================================================
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 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;
}
================================================
FILE: src/main/java/org/junit/experimental/theories/Theories.java
================================================
package org.junit.experimental.theories;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
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.Assume;
import org.junit.experimental.theories.internal.Assignments;
import org.junit.experimental.theories.internal.ParameterizedAssertionError;
import org.junit.internal.AssumptionViolatedException;
import org.junit.runners.BlockJUnit4ClassRunner;
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).
*
*
* For example:
*
*
* @RunWith(Theories.class)
* public class UserTest {
* @DataPoint
* public static String GOOD_USERNAME = "optimus";
* @DataPoint
* public static String USERNAME_WITH_SLASH = "optimus/prime";
*
* @Theory
* public void filenameIncludesUsername(String username) {
* assumeThat(username, not(containsString("/")));
* assertThat(new User(username).configFileName(), containsString(username));
* }
* }
*
* 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);
}
/** @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++;
}
}
}
================================================
FILE: src/main/java/org/junit/experimental/theories/Theory.java
================================================
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;
}
================================================
FILE: src/main/java/org/junit/experimental/theories/internal/AllMembersSupplier.java
================================================
package org.junit.experimental.theories.internal;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
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;
/**
* 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 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);
}
}
================================================
FILE: src/main/java/org/junit/experimental/theories/internal/Assignments.java
================================================
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;
import org.junit.experimental.theories.ParameterSignature;
import org.junit.experimental.theories.ParameterSupplier;
import org.junit.experimental.theories.ParametersSuppliedBy;
import org.junit.experimental.theories.PotentialAssignment;
import org.junit.experimental.theories.PotentialAssignment.CouldNotGenerateValueException;
import org.junit.runners.model.TestClass;
/**
* A potentially incomplete list of value assignments for a method's formal
* parameters
*/
public class Assignments {
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 potentialAssignments = new ArrayList(assigned);
potentialAssignments.add(source);
return new Assignments(potentialAssignments, unassigned.subList(1,
unassigned.size()), clazz);
}
public Object[] getActualValues(int start, int stop)
throws CouldNotGenerateValueException {
Object[] values = new Object[stop - start];
for (int i = start; i < stop; i++) {
values[i - start] = assigned.get(i).getValue();
}
return values;
}
public List potentialsForNextUnassigned()
throws Throwable {
ParameterSignature unassigned = nextUnassigned();
List assignments = getSupplier(unassigned).getValueSources(unassigned);
if (assignments.isEmpty()) {
assignments = generateAssignmentsFromTypeAlone(unassigned);
}
return assignments;
}
private List generateAssignmentsFromTypeAlone(ParameterSignature unassigned) {
Class> paramType = unassigned.getType();
if (paramType.isEnum()) {
return new EnumSupplier(paramType).getValueSources(unassigned);
} else if (paramType.equals(Boolean.class) || paramType.equals(boolean.class)) {
return new BooleanSupplier().getValueSources(unassigned);
} else {
return emptyList();
}
}
private ParameterSupplier getSupplier(ParameterSignature unassigned)
throws Exception {
ParametersSuppliedBy annotation = unassigned
.findDeepAnnotation(ParametersSuppliedBy.class);
if (annotation != null) {
return buildParameterSupplierFromClass(annotation.value());
} else {
return new AllMembersSupplier(clazz);
}
}
private ParameterSupplier buildParameterSupplierFromClass(
Class extends ParameterSupplier> cls) throws Exception {
Constructor>[] supplierConstructors = cls.getConstructors();
for (Constructor> constructor : supplierConstructors) {
Class>[] parameterTypes = constructor.getParameterTypes();
if (parameterTypes.length == 1
&& parameterTypes[0].equals(TestClass.class)) {
return (ParameterSupplier) constructor.newInstance(clazz);
}
}
return cls.newInstance();
}
public Object[] getConstructorArguments()
throws CouldNotGenerateValueException {
return getActualValues(0, getConstructorParameterCount());
}
public Object[] getMethodArguments() throws CouldNotGenerateValueException {
return getActualValues(getConstructorParameterCount(), assigned.size());
}
public Object[] getAllArguments() throws CouldNotGenerateValueException {
return getActualValues(0, assigned.size());
}
private int getConstructorParameterCount() {
List signatures = ParameterSignature
.signatures(clazz.getOnlyConstructor());
int constructorParameterCount = signatures.size();
return constructorParameterCount;
}
public Object[] getArgumentStrings(boolean nullsOk)
throws CouldNotGenerateValueException {
Object[] values = new Object[assigned.size()];
for (int i = 0; i < values.length; i++) {
values[i] = assigned.get(i).getDescription();
}
return values;
}
}
================================================
FILE: src/main/java/org/junit/experimental/theories/internal/BooleanSupplier.java
================================================
package org.junit.experimental.theories.internal;
import java.util.Arrays;
import java.util.List;
import org.junit.experimental.theories.ParameterSignature;
import org.junit.experimental.theories.ParameterSupplier;
import org.junit.experimental.theories.PotentialAssignment;
public class BooleanSupplier extends ParameterSupplier {
@Override
public List getValueSources(ParameterSignature sig) {
return Arrays.asList(PotentialAssignment.forValue("true", true),
PotentialAssignment.forValue("false", false));
}
}
================================================
FILE: src/main/java/org/junit/experimental/theories/internal/EnumSupplier.java
================================================
package org.junit.experimental.theories.internal;
import java.util.ArrayList;
import java.util.List;
import org.junit.experimental.theories.ParameterSignature;
import org.junit.experimental.theories.ParameterSupplier;
import org.junit.experimental.theories.PotentialAssignment;
public class EnumSupplier extends ParameterSupplier {
private Class> enumType;
public EnumSupplier(Class> enumType) {
this.enumType = enumType;
}
@Override
public List getValueSources(ParameterSignature sig) {
Object[] enumValues = enumType.getEnumConstants();
List assignments = new ArrayList();
for (Object value : enumValues) {
assignments.add(PotentialAssignment.forValue(value.toString(), value));
}
return assignments;
}
}
================================================
FILE: src/main/java/org/junit/experimental/theories/internal/ParameterizedAssertionError.java
================================================
package org.junit.experimental.theories.internal;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
public class ParameterizedAssertionError extends AssertionError {
private static final long serialVersionUID = 1L;
public ParameterizedAssertionError(Throwable targetException,
String methodName, Object... params) {
super(String.format("%s(%s)", methodName, join(", ", params)));
this.initCause(targetException);
}
@Override
public boolean equals(Object obj) {
return obj instanceof ParameterizedAssertionError && toString().equals(obj.toString());
}
@Override
public int hashCode() {
return toString().hashCode();
}
public static String join(String delimiter, Object... params) {
return join(delimiter, Arrays.asList(params));
}
public static String join(String delimiter, Collection values) {
StringBuilder sb = new StringBuilder();
Iterator iter = values.iterator();
while (iter.hasNext()) {
Object next = iter.next();
sb.append(stringValueOf(next));
if (iter.hasNext()) {
sb.append(delimiter);
}
}
return sb.toString();
}
private static String stringValueOf(Object next) {
try {
return String.valueOf(next);
} catch (Throwable e) {
return "[toString failed]";
}
}
}
================================================
FILE: src/main/java/org/junit/experimental/theories/internal/SpecificDataPointsSupplier.java
================================================
package org.junit.experimental.theories.internal;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import org.junit.experimental.theories.DataPoint;
import org.junit.experimental.theories.DataPoints;
import org.junit.experimental.theories.FromDataPoints;
import org.junit.experimental.theories.ParameterSignature;
import org.junit.runners.model.FrameworkMethod;
import org.junit.runners.model.TestClass;
public class SpecificDataPointsSupplier extends AllMembersSupplier {
public SpecificDataPointsSupplier(TestClass testClass) {
super(testClass);
}
@Override
protected Collection getSingleDataPointFields(ParameterSignature sig) {
Collection fields = super.getSingleDataPointFields(sig);
String requestedName = sig.getAnnotation(FromDataPoints.class).value();
List fieldsWithMatchingNames = new ArrayList();
for (Field field : fields) {
String[] fieldNames = field.getAnnotation(DataPoint.class).value();
if (Arrays.asList(fieldNames).contains(requestedName)) {
fieldsWithMatchingNames.add(field);
}
}
return fieldsWithMatchingNames;
}
@Override
protected Collection getDataPointsFields(ParameterSignature sig) {
Collection fields = super.getDataPointsFields(sig);
String requestedName = sig.getAnnotation(FromDataPoints.class).value();
List fieldsWithMatchingNames = new ArrayList();
for (Field field : fields) {
String[] fieldNames = field.getAnnotation(DataPoints.class).value();
if (Arrays.asList(fieldNames).contains(requestedName)) {
fieldsWithMatchingNames.add(field);
}
}
return fieldsWithMatchingNames;
}
@Override
protected Collection getSingleDataPointMethods(ParameterSignature sig) {
Collection methods = super.getSingleDataPointMethods(sig);
String requestedName = sig.getAnnotation(FromDataPoints.class).value();
List methodsWithMatchingNames = new ArrayList();
for (FrameworkMethod method : methods) {
String[] methodNames = method.getAnnotation(DataPoint.class).value();
if (Arrays.asList(methodNames).contains(requestedName)) {
methodsWithMatchingNames.add(method);
}
}
return methodsWithMatchingNames;
}
@Override
protected Collection getDataPointsMethods(ParameterSignature sig) {
Collection methods = super.getDataPointsMethods(sig);
String requestedName = sig.getAnnotation(FromDataPoints.class).value();
List methodsWithMatchingNames = new ArrayList();
for (FrameworkMethod method : methods) {
String[] methodNames = method.getAnnotation(DataPoints.class).value();
if (Arrays.asList(methodNames).contains(requestedName)) {
methodsWithMatchingNames.add(method);
}
}
return methodsWithMatchingNames;
}
}
================================================
FILE: src/main/java/org/junit/experimental/theories/suppliers/TestedOn.java
================================================
package org.junit.experimental.theories.suppliers;
import static java.lang.annotation.ElementType.PARAMETER;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.junit.experimental.theories.ParametersSuppliedBy;
/**
* Annotating a {@link org.junit.experimental.theories.Theory Theory} method int
* parameter with @TestedOn causes it to be supplied with values from the
* ints array given when run as a theory by the
* {@link org.junit.experimental.theories.Theories Theories} runner. For
* example, the below method would be called three times by the Theories runner,
* once with each of the int parameters specified.
*
*
* @Theory
* public void shouldPassForSomeInts(@TestedOn(ints={1, 2, 3}) int param) {
* ...
* }
*
*/
@ParametersSuppliedBy(TestedOnSupplier.class)
@Retention(RetentionPolicy.RUNTIME)
@Target(PARAMETER)
public @interface TestedOn {
int[] ints();
}
================================================
FILE: src/main/java/org/junit/experimental/theories/suppliers/TestedOnSupplier.java
================================================
package org.junit.experimental.theories.suppliers;
import java.util.ArrayList;
import java.util.List;
import org.junit.experimental.theories.ParameterSignature;
import org.junit.experimental.theories.ParameterSupplier;
import org.junit.experimental.theories.PotentialAssignment;
/**
* @see org.junit.experimental.theories.suppliers.TestedOn
* @see org.junit.experimental.theories.ParameterSupplier
*/
public class TestedOnSupplier extends ParameterSupplier {
@Override
public List getValueSources(ParameterSignature sig) {
List list = new ArrayList();
TestedOn testedOn = sig.getAnnotation(TestedOn.class);
int[] ints = testedOn.ints();
for (final int i : ints) {
list.add(PotentialAssignment.forValue("ints", i));
}
return list;
}
}
================================================
FILE: src/main/java/org/junit/function/ThrowingRunnable.java
================================================
package org.junit.function;
/**
* This interface facilitates the use of
* {@link org.junit.Assert#assertThrows(Class, ThrowingRunnable)} from Java 8. It allows method
* references to void methods (that declare checked exceptions) to be passed directly into
* {@code assertThrows}
* without wrapping. It is not meant to be implemented directly.
*
* @since 4.13
*/
public interface ThrowingRunnable {
void run() throws Throwable;
}
================================================
FILE: src/main/java/org/junit/internal/ArrayComparisonFailure.java
================================================
package org.junit.internal;
import java.util.ArrayList;
import java.util.List;
import org.junit.Assert;
/**
* Thrown when two array elements differ
*
* @see Assert#assertArrayEquals(String, Object[], Object[])
*/
public class ArrayComparisonFailure extends AssertionError {
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 final List fIndices = new ArrayList();
private final String fMessage;
private final AssertionError fCause;
/**
* Construct a new ArrayComparisonFailure with an error text and the array's
* dimension that was not equal
*
* @param cause the exception that caused the array's content to fail the assertion test
* @param index the array position of the objects that are not equal.
* @see Assert#assertArrayEquals(String, Object[], Object[])
*/
public ArrayComparisonFailure(String message, AssertionError cause, int index) {
this.fMessage = message;
this.fCause = cause;
initCause(fCause);
addDimension(index);
}
public void addDimension(int index) {
fIndices.add(0, index);
}
@Override
public synchronized Throwable getCause() {
return super.getCause() == null ? fCause : super.getCause();
}
@Override
public String getMessage() {
StringBuilder sb = new StringBuilder();
if (fMessage != null) {
sb.append(fMessage);
}
sb.append("arrays first differed at element ");
for (int each : fIndices) {
sb.append("[");
sb.append(each);
sb.append("]");
}
sb.append("; ");
sb.append(getCause().getMessage());
return sb.toString();
}
/**
* {@inheritDoc}
*/
@Override
public String toString() {
return getMessage();
}
}
================================================
FILE: src/main/java/org/junit/internal/AssumptionViolatedException.java
================================================
package org.junit.internal;
import java.io.IOException;
import java.io.ObjectOutputStream;
import org.hamcrest.Description;
import org.hamcrest.Matcher;
import org.hamcrest.SelfDescribing;
import org.hamcrest.StringDescription;
/**
* 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
*/
public class AssumptionViolatedException extends RuntimeException implements SelfDescribing {
private static final long serialVersionUID = 2L;
/*
* 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 String fAssumption;
private final boolean fValueMatcher;
private final Object fValue;
private final Matcher> fMatcher;
/**
* @deprecated Please use {@link org.junit.AssumptionViolatedException} instead.
*/
@Deprecated
public AssumptionViolatedException(String assumption, boolean hasValue, Object value, Matcher> matcher) {
this.fAssumption = assumption;
this.fValue = value;
this.fMatcher = matcher;
this.fValueMatcher = hasValue;
if (value instanceof Throwable) {
initCause((Throwable) value);
}
}
/**
* An assumption exception with the given value (String or
* Throwable) and an additional failing {@link Matcher}.
*
* @deprecated Please use {@link org.junit.AssumptionViolatedException} instead.
*/
@Deprecated
public AssumptionViolatedException(Object value, Matcher> matcher) {
this(null, true, value, matcher);
}
/**
* An assumption exception with the given value (String or
* Throwable) and an additional failing {@link Matcher}.
*
* @deprecated Please use {@link org.junit.AssumptionViolatedException} instead.
*/
@Deprecated
public AssumptionViolatedException(String assumption, Object value, Matcher> matcher) {
this(assumption, true, value, matcher);
}
/**
* An assumption exception with the given message only.
*
* @deprecated Please use {@link org.junit.AssumptionViolatedException} instead.
*/
@Deprecated
public AssumptionViolatedException(String assumption) {
this(assumption, false, null, null);
}
/**
* An assumption exception with the given message and a cause.
*
* @deprecated Please use {@link org.junit.AssumptionViolatedException} instead.
*/
@Deprecated
public AssumptionViolatedException(String assumption, Throwable e) {
this(assumption, false, null, null);
initCause(e);
}
@Override
public String getMessage() {
return StringDescription.asString(this);
}
public void describeTo(Description description) {
if (fAssumption != null) {
description.appendText(fAssumption);
}
if (fValueMatcher) {
// a value was passed in when this instance was constructed; print it
if (fAssumption != null) {
description.appendText(": ");
}
description.appendText("got: ");
description.appendValue(fValue);
if (fMatcher != null) {
description.appendText(", expected: ");
description.appendDescriptionOf(fMatcher);
}
}
}
/**
* Override default Java object serialization to correctly deal with potentially unserializable matchers or values.
* By not implementing readObject, we assure ourselves of backwards compatibility and compatibility with the
* standard way of Java serialization.
*
* @param objectOutputStream The outputStream to write our representation to
* @throws IOException When serialization fails
*/
private void writeObject(ObjectOutputStream objectOutputStream) throws IOException {
ObjectOutputStream.PutField putField = objectOutputStream.putFields();
putField.put("fAssumption", fAssumption);
putField.put("fValueMatcher", fValueMatcher);
// We have to wrap the matcher into a serializable form.
putField.put("fMatcher", SerializableMatcherDescription.asSerializableMatcher(fMatcher));
// We have to wrap the value inside a non-String class (instead of serializing the String value directly) as
// A Description will handle a String and non-String object differently (1st is surrounded by '"' while the
// latter will be surrounded by '<' '>'. Wrapping it makes sure that the description of a serialized and
// non-serialized instance produce the exact same description
putField.put("fValue", SerializableValueDescription.asSerializableValue(fValue));
objectOutputStream.writeFields();
}
}
================================================
FILE: src/main/java/org/junit/internal/Checks.java
================================================
package org.junit.internal;
/** @since 4.13 */
public final class Checks {
private Checks() {}
/**
* Checks that the given value is not {@code null}.
*
* @param value object reference to check
* @return the passed-in value, if not {@code null}
* @throws NullPointerException if {@code value} is {@code null}
*/
public static T notNull(T value) {
if (value == null) {
throw new NullPointerException();
}
return value;
}
/**
* Checks that the given value is not {@code null}, using the given message
* as the exception message if an exception is thrown.
*
* @param value object reference to check
* @param message message to use if {@code value} is {@code null}
* @return the passed-in value, if not {@code null}
* @throws NullPointerException if {@code value} is {@code null}
*/
public static T notNull(T value, String message) {
if (value == null) {
throw new NullPointerException(message);
}
return value;
}
}
================================================
FILE: src/main/java/org/junit/internal/Classes.java
================================================
package org.junit.internal;
import static java.lang.Thread.currentThread;
/**
* Miscellaneous functions dealing with classes.
*/
public class Classes {
/**
* Do not instantiate.
* @deprecated will be private soon.
*/
@Deprecated
public Classes() {
}
/**
* Returns Class.forName for {@code className} using the current thread's class loader.
* If the current thread does not have a class loader, falls back to the class loader for
* {@link Classes}.
*
* @param className Name of the class.
*/
public static Class> getClass(String className) throws ClassNotFoundException {
return getClass(className, Classes.class);
}
/**
* Returns Class.forName for {@code className} using the current thread's class loader.
* If the current thread does not have a class loader, falls back to the class loader for the
* passed-in class.
*
* @param className Name of the class.
* @param callingClass Class that is requesting a the class
* @since 4.13
*/
public static Class> getClass(String className, Class> callingClass) throws ClassNotFoundException {
ClassLoader classLoader = currentThread().getContextClassLoader();
return Class.forName(className, true, classLoader == null ? callingClass.getClassLoader() : classLoader);
}
}
================================================
FILE: src/main/java/org/junit/internal/ComparisonCriteria.java
================================================
package org.junit.internal;
import java.lang.reflect.Array;
import java.util.Arrays;
import org.junit.Assert;
/**
* Defines criteria for finding two items "equal enough". Concrete subclasses
* may demand exact equality, or, for example, equality within a given delta.
*/
public abstract class ComparisonCriteria {
/**
* Asserts that two arrays are equal, according to the criteria defined by
* the concrete subclass. 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 void arrayEquals(String message, Object expecteds, Object actuals)
throws ArrayComparisonFailure {
arrayEquals(message, expecteds, actuals, true);
}
private void arrayEquals(String message, Object expecteds, Object actuals, boolean outer)
throws ArrayComparisonFailure {
if (expecteds == actuals
|| Arrays.deepEquals(new Object[] {expecteds}, new Object[] {actuals})) {
// The reflection-based loop below is potentially very slow, especially for primitive
// arrays. The deepEquals check allows us to circumvent it in the usual case where
// the arrays are exactly equal.
return;
}
String header = message == null ? "" : message + ": ";
// Only include the user-provided message in the outer exception.
String exceptionMessage = outer ? header : "";
if (expecteds == null) {
Assert.fail(exceptionMessage + "expected array was null");
}
if (actuals == null) {
Assert.fail(exceptionMessage + "actual array was null");
}
int actualsLength = Array.getLength(actuals);
int expectedsLength = Array.getLength(expecteds);
if (actualsLength != expectedsLength) {
header += "array lengths differed, expected.length="
+ expectedsLength + " actual.length=" + actualsLength + "; ";
}
int prefixLength = Math.min(actualsLength, expectedsLength);
for (int i = 0; i < prefixLength; i++) {
Object expected = Array.get(expecteds, i);
Object actual = Array.get(actuals, i);
if (isArray(expected) && isArray(actual)) {
try {
arrayEquals(message, expected, actual, false);
} catch (ArrayComparisonFailure e) {
e.addDimension(i);
throw e;
} catch (AssertionError e) {
// Array lengths differed.
throw new ArrayComparisonFailure(header, e, i);
}
} else {
try {
assertElementsEqual(expected, actual);
} catch (AssertionError e) {
throw new ArrayComparisonFailure(header, e, i);
}
}
}
if (actualsLength != expectedsLength) {
Object expected = getToStringableArrayElement(expecteds, expectedsLength, prefixLength);
Object actual = getToStringableArrayElement(actuals, actualsLength, prefixLength);
try {
Assert.assertEquals(expected, actual);
} catch (AssertionError e) {
throw new ArrayComparisonFailure(header, e, prefixLength);
}
}
}
private static final Object END_OF_ARRAY_SENTINEL = objectWithToString("end of array");
private Object getToStringableArrayElement(Object array, int length, int index) {
if (index < length) {
Object element = Array.get(array, index);
if (isArray(element)) {
return objectWithToString(componentTypeName(element.getClass()) + "[" + Array.getLength(element) + "]");
} else {
return element;
}
} else {
return END_OF_ARRAY_SENTINEL;
}
}
private static Object objectWithToString(final String string) {
return new Object() {
@Override
public String toString() {
return string;
}
};
}
private String componentTypeName(Class> arrayClass) {
Class> componentType = arrayClass.getComponentType();
if (componentType.isArray()) {
return componentTypeName(componentType) + "[]";
} else {
return componentType.getName();
}
}
private boolean isArray(Object expected) {
return expected != null && expected.getClass().isArray();
}
protected abstract void assertElementsEqual(Object expected, Object actual);
}
================================================
FILE: src/main/java/org/junit/internal/ExactComparisonCriteria.java
================================================
package org.junit.internal;
import org.junit.Assert;
public class ExactComparisonCriteria extends ComparisonCriteria {
@Override
protected void assertElementsEqual(Object expected, Object actual) {
Assert.assertEquals(expected, actual);
}
}
================================================
FILE: src/main/java/org/junit/internal/InexactComparisonCriteria.java
================================================
package org.junit.internal;
import org.junit.Assert;
public class InexactComparisonCriteria extends ComparisonCriteria {
public Object fDelta;
public InexactComparisonCriteria(double delta) {
fDelta = delta;
}
public InexactComparisonCriteria(float delta) {
fDelta = delta;
}
@Override
protected void assertElementsEqual(Object expected, Object actual) {
if (expected instanceof Double) {
Assert.assertEquals((Double) expected, (Double) actual, (Double) fDelta);
} else {
Assert.assertEquals((Float) expected, (Float) actual, (Float) fDelta);
}
}
}
================================================
FILE: src/main/java/org/junit/internal/JUnitSystem.java
================================================
package org.junit.internal;
import java.io.PrintStream;
public interface JUnitSystem {
/**
* Will be removed in the next major release
*/
@Deprecated
void exit(int code);
PrintStream out();
}
================================================
FILE: src/main/java/org/junit/internal/MethodSorter.java
================================================
package org.junit.internal;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Comparator;
import org.junit.FixMethodOrder;
public class MethodSorter {
/**
* DEFAULT sort order
*/
public static final Comparator DEFAULT = new Comparator() {
public int compare(Method m1, Method m2) {
int i1 = m1.getName().hashCode();
int i2 = m2.getName().hashCode();
if (i1 != i2) {
return i1 < i2 ? -1 : 1;
}
return NAME_ASCENDING.compare(m1, m2);
}
};
/**
* Method name ascending lexicographic sort order, with {@link Method#toString()} as a tiebreaker
*/
public static final Comparator NAME_ASCENDING = new Comparator() {
public int compare(Method m1, Method m2) {
final int comparison = m1.getName().compareTo(m2.getName());
if (comparison != 0) {
return comparison;
}
return m1.toString().compareTo(m2.toString());
}
};
/**
* Gets declared methods of a class in a predictable order, unless @FixMethodOrder(MethodSorters.JVM) is specified.
*
* 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; 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. By default, uses an unspecified but deterministic order.
*
* @param clazz a class
* @return same as {@link Class#getDeclaredMethods} but sorted
* @see JDK
* (non-)bug #7023180
*/
public static Method[] getDeclaredMethods(Class> clazz) {
Comparator comparator = getSorter(clazz.getAnnotation(FixMethodOrder.class));
Method[] methods = clazz.getDeclaredMethods();
if (comparator != null) {
Arrays.sort(methods, comparator);
}
return methods;
}
private MethodSorter() {
}
private static Comparator getSorter(FixMethodOrder fixMethodOrder) {
if (fixMethodOrder == null) {
return DEFAULT;
}
return fixMethodOrder.value().getComparator();
}
}
================================================
FILE: src/main/java/org/junit/internal/RealSystem.java
================================================
package org.junit.internal;
import java.io.PrintStream;
public class RealSystem implements JUnitSystem {
/**
* Will be removed in the next major release
*/
@Deprecated
public void exit(int code) {
System.exit(code);
}
public PrintStream out() {
return System.out;
}
}
================================================
FILE: src/main/java/org/junit/internal/SerializableMatcherDescription.java
================================================
package org.junit.internal;
import java.io.Serializable;
import org.hamcrest.BaseMatcher;
import org.hamcrest.Description;
import org.hamcrest.Matcher;
import org.hamcrest.StringDescription;
/**
* This class exists solely to provide a serializable description of a matcher to be serialized as a field in
* {@link AssumptionViolatedException}. Being a {@link Throwable}, it is required to be {@link Serializable}, but most
* implementations of {@link Matcher} are not. This class works around that limitation as
* {@link AssumptionViolatedException} only every uses the description of the {@link Matcher}, while still retaining
* backwards compatibility with classes compiled against its class signature before 4.14 and/or deserialization of
* previously serialized instances.
*/
class SerializableMatcherDescription extends BaseMatcher implements Serializable {
private final String matcherDescription;
private SerializableMatcherDescription(Matcher matcher) {
matcherDescription = StringDescription.asString(matcher);
}
public boolean matches(Object o) {
throw new UnsupportedOperationException("This Matcher implementation only captures the description");
}
public void describeTo(Description description) {
description.appendText(matcherDescription);
}
/**
* Factory method that checks to see if the matcher is already serializable.
* @param matcher the matcher to make serializable
* @return The provided matcher if it is null or already serializable,
* the SerializableMatcherDescription representation of it if it is not.
*/
static Matcher asSerializableMatcher(Matcher matcher) {
if (matcher == null || matcher instanceof Serializable) {
return matcher;
} else {
return new SerializableMatcherDescription(matcher);
}
}
}
================================================
FILE: src/main/java/org/junit/internal/SerializableValueDescription.java
================================================
package org.junit.internal;
import java.io.Serializable;
/**
* This class exists solely to provide a serializable description of a value to be serialized as a field in
* {@link AssumptionViolatedException}. Being a {@link Throwable}, it is required to be {@link Serializable}, but a
* value of type Object provides no guarantee to be serializable. This class works around that limitation as
* {@link AssumptionViolatedException} only every uses the string representation of the value, while still retaining
* backwards compatibility with classes compiled against its class signature before 4.14 and/or deserialization of
* previously serialized instances.
*/
class SerializableValueDescription implements Serializable {
private final String value;
private SerializableValueDescription(Object value) {
this.value = String.valueOf(value);
}
/**
* Factory method that checks to see if the value is already serializable.
* @param value the value to make serializable
* @return The provided value if it is null or already serializable,
* the SerializableValueDescription representation of it if it is not.
*/
static Object asSerializableValue(Object value) {
if (value == null || value instanceof Serializable) {
return value;
} else {
return new SerializableValueDescription(value);
}
}
@Override
public String toString() {
return value;
}
}
================================================
FILE: src/main/java/org/junit/internal/TextListener.java
================================================
package org.junit.internal;
import java.io.PrintStream;
import java.text.NumberFormat;
import java.util.List;
import org.junit.runner.Description;
import org.junit.runner.Result;
import org.junit.runner.notification.Failure;
import org.junit.runner.notification.RunListener;
public class TextListener extends RunListener {
private final PrintStream writer;
public TextListener(JUnitSystem system) {
this(system.out());
}
public TextListener(PrintStream writer) {
this.writer = writer;
}
@Override
public void testRunFinished(Result result) {
printHeader(result.getRunTime());
printFailures(result);
printFooter(result);
}
@Override
public void testStarted(Description description) {
writer.append('.');
}
@Override
public void testFailure(Failure failure) {
writer.append('E');
}
@Override
public void testIgnored(Description description) {
writer.append('I');
}
/*
* Internal methods
*/
private PrintStream getWriter() {
return writer;
}
protected void printHeader(long runTime) {
getWriter().println();
getWriter().println("Time: " + elapsedTimeAsString(runTime));
}
protected void printFailures(Result result) {
List failures = result.getFailures();
if (failures.isEmpty()) {
return;
}
if (failures.size() == 1) {
getWriter().println("There was " + failures.size() + " failure:");
} else {
getWriter().println("There were " + failures.size() + " failures:");
}
int i = 1;
for (Failure each : failures) {
printFailure(each, "" + i++);
}
}
protected void printFailure(Failure each, String prefix) {
getWriter().println(prefix + ") " + each.getTestHeader());
getWriter().print(each.getTrimmedTrace());
}
protected void printFooter(Result result) {
if (result.wasSuccessful()) {
getWriter().println();
getWriter().print("OK");
getWriter().println(" (" + result.getRunCount() + " test" + (result.getRunCount() == 1 ? "" : "s") + ")");
} else {
getWriter().println();
getWriter().println("FAILURES!!!");
getWriter().println("Tests run: " + result.getRunCount() + ", Failures: " + result.getFailureCount());
}
getWriter().println();
}
/**
* Returns the formatted string of the elapsed time. Duplicated from
* BaseTestRunner. Fix it.
*/
protected String elapsedTimeAsString(long runTime) {
return NumberFormat.getInstance().format((double) runTime / 1000);
}
}
================================================
FILE: src/main/java/org/junit/internal/Throwables.java
================================================
package org.junit.internal;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringReader;
import java.io.StringWriter;
import java.lang.reflect.Method;
import java.util.AbstractList;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
/**
* Miscellaneous functions dealing with {@code Throwable}.
*
* @author kcooney@google.com (Kevin Cooney)
* @since 4.12
*/
public final class Throwables {
private Throwables() {
}
/**
* Rethrows the given {@code Throwable}, allowing the caller to
* declare that it throws {@code Exception}. This is useful when
* your callers have nothing reasonable they can do when a
* {@code Throwable} is thrown. This is declared to return {@code Exception}
* so it can be used in a {@code throw} clause:
*
*
* @param e exception to rethrow
* @return does not return anything
* @since 4.12
*/
public static Exception rethrowAsException(Throwable e) throws Exception {
Throwables.rethrow(e);
return null; // we never get here
}
@SuppressWarnings("unchecked")
private static void rethrow(Throwable e) throws T {
throw (T) e;
}
/**
* Returns the stacktrace of the given Throwable as a String.
*
* @since 4.13
*/
public static String getStacktrace(Throwable exception) {
StringWriter stringWriter = new StringWriter();
PrintWriter writer = new PrintWriter(stringWriter);
exception.printStackTrace(writer);
return stringWriter.toString();
}
/**
* Gets a trimmed version of the stack trace of the given exception. Stack trace
* elements that are below the test method are filtered out.
*
* @return a trimmed stack trace, or the original trace if trimming wasn't possible
*/
public static String getTrimmedStackTrace(Throwable exception) {
List trimmedStackTraceLines = getTrimmedStackTraceLines(exception);
if (trimmedStackTraceLines.isEmpty()) {
return getFullStackTrace(exception);
}
StringBuilder result = new StringBuilder(exception.toString());
appendStackTraceLines(trimmedStackTraceLines, result);
appendStackTraceLines(getCauseStackTraceLines(exception), result);
return result.toString();
}
private static List getTrimmedStackTraceLines(Throwable exception) {
List stackTraceElements = Arrays.asList(exception.getStackTrace());
int linesToInclude = stackTraceElements.size();
State state = State.PROCESSING_OTHER_CODE;
for (StackTraceElement stackTraceElement : asReversedList(stackTraceElements)) {
state = state.processStackTraceElement(stackTraceElement);
if (state == State.DONE) {
List trimmedLines = new ArrayList(linesToInclude + 2);
trimmedLines.add("");
for (StackTraceElement each : stackTraceElements.subList(0, linesToInclude)) {
trimmedLines.add("\tat " + each);
}
if (exception.getCause() != null) {
trimmedLines.add("\t... " + (stackTraceElements.size() - trimmedLines.size()) + " trimmed");
}
return trimmedLines;
}
linesToInclude--;
}
return Collections.emptyList();
}
private static final Method getSuppressed = initGetSuppressed();
private static Method initGetSuppressed() {
try {
return Throwable.class.getMethod("getSuppressed");
} catch (Throwable e) {
return null;
}
}
private static boolean hasSuppressed(Throwable exception) {
if (getSuppressed == null) {
return false;
}
try {
Throwable[] suppressed = (Throwable[]) getSuppressed.invoke(exception);
return suppressed.length != 0;
} catch (Throwable e) {
return false;
}
}
private static List getCauseStackTraceLines(Throwable exception) {
if (exception.getCause() != null || hasSuppressed(exception)) {
String fullTrace = getFullStackTrace(exception);
BufferedReader reader = new BufferedReader(
new StringReader(fullTrace.substring(exception.toString().length())));
List causedByLines = new ArrayList();
try {
String line;
while ((line = reader.readLine()) != null) {
if (line.startsWith("Caused by: ") || line.trim().startsWith("Suppressed: ")) {
causedByLines.add(line);
while ((line = reader.readLine()) != null) {
causedByLines.add(line);
}
return causedByLines;
}
}
} catch (IOException e) {
// We should never get here, because we are reading from a StringReader
}
}
return Collections.emptyList();
}
private static String getFullStackTrace(Throwable exception) {
StringWriter stringWriter = new StringWriter();
PrintWriter writer = new PrintWriter(stringWriter);
exception.printStackTrace(writer);
return stringWriter.toString();
}
private static void appendStackTraceLines(
List stackTraceLines, StringBuilder destBuilder) {
for (String stackTraceLine : stackTraceLines) {
destBuilder.append(String.format("%s%n", stackTraceLine));
}
}
private static List asReversedList(final List list) {
return new AbstractList() {
@Override
public T get(int index) {
return list.get(list.size() - index - 1);
}
@Override
public int size() {
return list.size();
}
};
}
private enum State {
PROCESSING_OTHER_CODE {
@Override public State processLine(String methodName) {
if (isTestFrameworkMethod(methodName)) {
return PROCESSING_TEST_FRAMEWORK_CODE;
}
return this;
}
},
PROCESSING_TEST_FRAMEWORK_CODE {
@Override public State processLine(String methodName) {
if (isReflectionMethod(methodName)) {
return PROCESSING_REFLECTION_CODE;
} else if (isTestFrameworkMethod(methodName)) {
return this;
}
return PROCESSING_OTHER_CODE;
}
},
PROCESSING_REFLECTION_CODE {
@Override public State processLine(String methodName) {
if (isReflectionMethod(methodName)) {
return this;
} else if (isTestFrameworkMethod(methodName)) {
// This is here to handle TestCase.runBare() calling TestCase.runTest().
return PROCESSING_TEST_FRAMEWORK_CODE;
}
return DONE;
}
},
DONE {
@Override public State processLine(String methodName) {
return this;
}
};
/** Processes a stack trace element method name, possibly moving to a new state. */
protected abstract State processLine(String methodName);
/** Processes a stack trace element, possibly moving to a new state. */
public final State processStackTraceElement(StackTraceElement element) {
return processLine(element.getClassName() + "." + element.getMethodName() + "()");
}
}
private static final String[] TEST_FRAMEWORK_METHOD_NAME_PREFIXES = {
"org.junit.runner.",
"org.junit.runners.",
"org.junit.experimental.runners.",
"org.junit.internal.",
"junit.extensions",
"junit.framework",
"junit.runner",
"junit.textui",
};
private static final String[] TEST_FRAMEWORK_TEST_METHOD_NAME_PREFIXES = {
"org.junit.internal.StackTracesTest",
};
private static boolean isTestFrameworkMethod(String methodName) {
return isMatchingMethod(methodName, TEST_FRAMEWORK_METHOD_NAME_PREFIXES) &&
!isMatchingMethod(methodName, TEST_FRAMEWORK_TEST_METHOD_NAME_PREFIXES);
}
private static final String[] REFLECTION_METHOD_NAME_PREFIXES = {
"sun.reflect.",
"java.lang.reflect.",
"jdk.internal.reflect.",
"org.junit.rules.RunRules.(",
"org.junit.rules.RunRules.applyAll(", // calls TestRules
"org.junit.runners.RuleContainer.apply(", // calls MethodRules & TestRules
"junit.framework.TestCase.runBare(", // runBare() directly calls setUp() and tearDown()
};
private static boolean isReflectionMethod(String methodName) {
return isMatchingMethod(methodName, REFLECTION_METHOD_NAME_PREFIXES);
}
private static boolean isMatchingMethod(String methodName, String[] methodNamePrefixes) {
for (String methodNamePrefix : methodNamePrefixes) {
if (methodName.startsWith(methodNamePrefix)) {
return true;
}
}
return false;
}
}
================================================
FILE: src/main/java/org/junit/internal/builders/AllDefaultPossibilitiesBuilder.java
================================================
package org.junit.internal.builders;
import java.util.Arrays;
import java.util.List;
import org.junit.runner.Runner;
import org.junit.runners.model.RunnerBuilder;
public class AllDefaultPossibilitiesBuilder extends RunnerBuilder {
private final boolean canUseSuiteMethod;
/**
* @since 4.13
*/
public AllDefaultPossibilitiesBuilder() {
canUseSuiteMethod = true;
}
/**
* @deprecated used {@link #AllDefaultPossibilitiesBuilder()}.
*/
@Deprecated
public AllDefaultPossibilitiesBuilder(boolean canUseSuiteMethod) {
this.canUseSuiteMethod = canUseSuiteMethod;
}
@Override
public Runner runnerForClass(Class> testClass) throws Throwable {
List builders = Arrays.asList(
ignoredBuilder(),
annotatedBuilder(),
suiteMethodBuilder(),
junit3Builder(),
junit4Builder());
for (RunnerBuilder each : builders) {
Runner runner = each.safeRunnerForClass(testClass);
if (runner != null) {
return runner;
}
}
return null;
}
protected JUnit4Builder junit4Builder() {
return new JUnit4Builder();
}
protected JUnit3Builder junit3Builder() {
return new JUnit3Builder();
}
protected AnnotatedBuilder annotatedBuilder() {
return new AnnotatedBuilder(this);
}
protected IgnoredBuilder ignoredBuilder() {
return new IgnoredBuilder();
}
protected RunnerBuilder suiteMethodBuilder() {
if (canUseSuiteMethod) {
return new SuiteMethodBuilder();
}
return new NullBuilder();
}
}
================================================
FILE: src/main/java/org/junit/internal/builders/AnnotatedBuilder.java
================================================
package org.junit.internal.builders;
import org.junit.runner.RunWith;
import org.junit.runner.Runner;
import org.junit.runners.model.InitializationError;
import org.junit.runners.model.RunnerBuilder;
import java.lang.reflect.Modifier;
/**
* The {@code AnnotatedBuilder} is a strategy for constructing runners for test class that have been annotated with the
* {@code @RunWith} annotation. All tests within this class will be executed using the runner that was specified within
* the annotation.
*
* If a runner supports inner member classes, the member classes will inherit the runner from the enclosing class, e.g.:
*
* @RunWith(MyRunner.class)
* public class MyTest {
* // some tests might go here
*
* public class MyMemberClass {
* @Test
* public void thisTestRunsWith_MyRunner() {
* // some test logic
* }
*
* // some more tests might go here
* }
*
* @RunWith(AnotherRunner.class)
* public class AnotherMemberClass {
* // some tests might go here
*
* public class DeepInnerClass {
* @Test
* public void thisTestRunsWith_AnotherRunner() {
* // some test logic
* }
* }
*
* public class DeepInheritedClass extends SuperTest {
* @Test
* public void thisTestRunsWith_SuperRunner() {
* // some test logic
* }
* }
* }
* }
*
* @RunWith(SuperRunner.class)
* public class SuperTest {
* // some tests might go here
* }
*
* The key points to note here are:
*
*
If there is no RunWith annotation, no runner will be created.
*
The resolve step is inside-out, e.g. the closest RunWith annotation wins
*
RunWith annotations are inherited and work as if the class was annotated itself.
*
The default JUnit runner does not support inner member classes,
* so this is only valid for custom runners that support inner member classes.
*
Custom runners with support for inner classes may or may not support RunWith annotations for member
* classes. Please refer to the custom runner documentation.
*
*
* @see org.junit.runners.model.RunnerBuilder
* @see org.junit.runner.RunWith
* @since 4.0
*/
public class AnnotatedBuilder extends RunnerBuilder {
private static final String CONSTRUCTOR_ERROR_FORMAT = "Custom runner class %s should have a public constructor with signature %s(Class testClass)";
private final RunnerBuilder suiteBuilder;
public AnnotatedBuilder(RunnerBuilder suiteBuilder) {
this.suiteBuilder = suiteBuilder;
}
@Override
public Runner runnerForClass(Class> testClass) throws Exception {
for (Class> currentTestClass = testClass; currentTestClass != null;
currentTestClass = getEnclosingClassForNonStaticMemberClass(currentTestClass)) {
RunWith annotation = currentTestClass.getAnnotation(RunWith.class);
if (annotation != null) {
return buildRunner(annotation.value(), testClass);
}
}
return null;
}
private Class> getEnclosingClassForNonStaticMemberClass(Class> currentTestClass) {
if (currentTestClass.isMemberClass() && !Modifier.isStatic(currentTestClass.getModifiers())) {
return currentTestClass.getEnclosingClass();
} else {
return null;
}
}
public Runner buildRunner(Class extends Runner> runnerClass,
Class> testClass) throws Exception {
try {
return runnerClass.getConstructor(Class.class).newInstance(testClass);
} catch (NoSuchMethodException e) {
try {
return runnerClass.getConstructor(Class.class,
RunnerBuilder.class).newInstance(testClass, suiteBuilder);
} catch (NoSuchMethodException e2) {
String simpleName = runnerClass.getSimpleName();
throw new InitializationError(String.format(
CONSTRUCTOR_ERROR_FORMAT, simpleName, simpleName));
}
}
}
}
================================================
FILE: src/main/java/org/junit/internal/builders/IgnoredBuilder.java
================================================
package org.junit.internal.builders;
import org.junit.Ignore;
import org.junit.runner.Runner;
import org.junit.runners.model.RunnerBuilder;
public class IgnoredBuilder extends RunnerBuilder {
@Override
public Runner runnerForClass(Class> testClass) {
if (testClass.getAnnotation(Ignore.class) != null) {
return new IgnoredClassRunner(testClass);
}
return null;
}
}
================================================
FILE: src/main/java/org/junit/internal/builders/IgnoredClassRunner.java
================================================
package org.junit.internal.builders;
import org.junit.runner.Description;
import org.junit.runner.Runner;
import org.junit.runner.notification.RunNotifier;
public class IgnoredClassRunner extends Runner {
private final Class> clazz;
public IgnoredClassRunner(Class> testClass) {
clazz = testClass;
}
@Override
public void run(RunNotifier notifier) {
notifier.fireTestIgnored(getDescription());
}
@Override
public Description getDescription() {
return Description.createSuiteDescription(clazz);
}
}
================================================
FILE: src/main/java/org/junit/internal/builders/JUnit3Builder.java
================================================
package org.junit.internal.builders;
import org.junit.internal.runners.JUnit38ClassRunner;
import org.junit.runner.Runner;
import org.junit.runners.model.RunnerBuilder;
public class JUnit3Builder extends RunnerBuilder {
@Override
public Runner runnerForClass(Class> testClass) throws Throwable {
if (isPre4Test(testClass)) {
return new JUnit38ClassRunner(testClass);
}
return null;
}
boolean isPre4Test(Class> testClass) {
return junit.framework.TestCase.class.isAssignableFrom(testClass);
}
}
================================================
FILE: src/main/java/org/junit/internal/builders/JUnit4Builder.java
================================================
package org.junit.internal.builders;
import org.junit.runner.Runner;
import org.junit.runners.JUnit4;
import org.junit.runners.model.RunnerBuilder;
public class JUnit4Builder extends RunnerBuilder {
@Override
public Runner runnerForClass(Class> testClass) throws Throwable {
return new JUnit4(testClass);
}
}
================================================
FILE: src/main/java/org/junit/internal/builders/NullBuilder.java
================================================
package org.junit.internal.builders;
import org.junit.runner.Runner;
import org.junit.runners.model.RunnerBuilder;
public class NullBuilder extends RunnerBuilder {
@Override
public Runner runnerForClass(Class> each) throws Throwable {
return null;
}
}
================================================
FILE: src/main/java/org/junit/internal/builders/SuiteMethodBuilder.java
================================================
package org.junit.internal.builders;
import org.junit.internal.runners.SuiteMethod;
import org.junit.runner.Runner;
import org.junit.runners.model.RunnerBuilder;
public class SuiteMethodBuilder extends RunnerBuilder {
@Override
public Runner runnerForClass(Class> each) throws Throwable {
if (hasSuiteMethod(each)) {
return new SuiteMethod(each);
}
return null;
}
public boolean hasSuiteMethod(Class> testClass) {
try {
testClass.getMethod("suite");
} catch (NoSuchMethodException e) {
return false;
}
return true;
}
}
================================================
FILE: src/main/java/org/junit/internal/management/FakeRuntimeMXBean.java
================================================
package org.junit.internal.management;
import java.util.Collections;
import java.util.List;
/**
* No-op implementation of RuntimeMXBean when the platform doesn't provide it.
*/
class FakeRuntimeMXBean implements RuntimeMXBean {
/**
* {@inheritDoc}
*
*
Always returns an empty list.
*/
public List getInputArguments() {
return Collections.emptyList();
}
}
================================================
FILE: src/main/java/org/junit/internal/management/FakeThreadMXBean.java
================================================
package org.junit.internal.management;
/**
* No-op implementation of ThreadMXBean when the platform doesn't provide it.
*/
final class FakeThreadMXBean implements ThreadMXBean {
/**
* {@inheritDoc}
*
*
Always throws an {@link UnsupportedOperationException}
*/
public long getThreadCpuTime(long id) {
throw new UnsupportedOperationException();
}
/**
* {@inheritDoc}
*
*
Always returns false.
*/
public boolean isThreadCpuTimeSupported() {
return false;
}
}
================================================
FILE: src/main/java/org/junit/internal/management/ManagementFactory.java
================================================
package org.junit.internal.management;
import org.junit.internal.Classes;
import java.lang.reflect.InvocationTargetException;
/**
* Reflective wrapper around {@link java.lang.management.ManagementFactory}
*/
public class ManagementFactory {
private static final class FactoryHolder {
private static final Class> MANAGEMENT_FACTORY_CLASS;
static {
Class> managementFactoryClass = null;
try {
managementFactoryClass = Classes.getClass("java.lang.management.ManagementFactory");
} catch (ClassNotFoundException e) {
// do nothing, managementFactoryClass will be none on failure
}
MANAGEMENT_FACTORY_CLASS = managementFactoryClass;
}
static Object getBeanObject(String methodName) {
if (MANAGEMENT_FACTORY_CLASS != null) {
try {
return MANAGEMENT_FACTORY_CLASS.getMethod(methodName).invoke(null);
} catch (IllegalAccessException e) {
// fallthrough
} catch (IllegalArgumentException e) {
// fallthrough
} catch (InvocationTargetException e) {
// fallthrough
} catch (NoSuchMethodException e) {
// fallthrough
} catch (SecurityException e) {
// fallthrough
}
}
return null;
}
}
private static final class RuntimeHolder {
private static final RuntimeMXBean RUNTIME_MX_BEAN =
getBean(FactoryHolder.getBeanObject("getRuntimeMXBean"));
private static final RuntimeMXBean getBean(Object runtimeMxBean) {
return runtimeMxBean != null
? new ReflectiveRuntimeMXBean(runtimeMxBean) : new FakeRuntimeMXBean();
}
}
private static final class ThreadHolder {
private static final ThreadMXBean THREAD_MX_BEAN =
getBean(FactoryHolder.getBeanObject("getThreadMXBean"));
private static final ThreadMXBean getBean(Object threadMxBean) {
return threadMxBean != null
? new ReflectiveThreadMXBean(threadMxBean) : new FakeThreadMXBean();
}
}
/**
* @see java.lang.management.ManagementFactory#getRuntimeMXBean()
*/
public static RuntimeMXBean getRuntimeMXBean() {
return RuntimeHolder.RUNTIME_MX_BEAN;
}
/**
* @see java.lang.management.ManagementFactory#getThreadMXBean()
*/
public static ThreadMXBean getThreadMXBean() {
return ThreadHolder.THREAD_MX_BEAN;
}
}
================================================
FILE: src/main/java/org/junit/internal/management/ReflectiveRuntimeMXBean.java
================================================
package org.junit.internal.management;
import org.junit.internal.Classes;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Collections;
import java.util.List;
/**
* Implementation of {@link RuntimeMXBean} using the JVM reflectively.
*/
final class ReflectiveRuntimeMXBean implements RuntimeMXBean {
private final Object runtimeMxBean;
private static final class Holder {
private static final Method getInputArgumentsMethod;
static {
Method inputArguments = null;
try {
Class> threadMXBeanClass = Classes.getClass("java.lang.management.RuntimeMXBean");
inputArguments = threadMXBeanClass.getMethod("getInputArguments");
} catch (ClassNotFoundException e) {
// do nothing, input arguments will be null on failure
} catch (NoSuchMethodException e) {
// do nothing, input arguments will be null on failure
} catch (SecurityException e) {
// do nothing, input arguments will be null on failure
}
getInputArgumentsMethod = inputArguments;
}
}
ReflectiveRuntimeMXBean(Object runtimeMxBean) {
super();
this.runtimeMxBean = runtimeMxBean;
}
/**
* {@inheritDoc}
*/
@SuppressWarnings("unchecked")
public List getInputArguments() {
if (Holder.getInputArgumentsMethod != null) {
try {
return (List) Holder.getInputArgumentsMethod.invoke(runtimeMxBean);
} catch (ClassCastException e) { // no multi-catch with source level 6
// fallthrough
} catch (IllegalAccessException e) {
// fallthrough
} catch (IllegalArgumentException e) {
// fallthrough
} catch (InvocationTargetException e) {
// fallthrough
}
}
return Collections.emptyList();
}
}
================================================
FILE: src/main/java/org/junit/internal/management/ReflectiveThreadMXBean.java
================================================
package org.junit.internal.management;
import org.junit.internal.Classes;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* Implementation of {@link ThreadMXBean} using the JVM reflectively.
*/
final class ReflectiveThreadMXBean implements ThreadMXBean {
private final Object threadMxBean;
private static final class Holder {
static final Method getThreadCpuTimeMethod;
static final Method isThreadCpuTimeSupportedMethod;
private static final String FAILURE_MESSAGE = "Unable to access ThreadMXBean";
static {
Method threadCpuTime = null;
Method threadCpuTimeSupported = null;
try {
Class> threadMXBeanClass = Classes.getClass("java.lang.management.ThreadMXBean");
threadCpuTime = threadMXBeanClass.getMethod("getThreadCpuTime", long.class);
threadCpuTimeSupported = threadMXBeanClass.getMethod("isThreadCpuTimeSupported");
} catch (ClassNotFoundException e) {
// do nothing, the methods will be null on failure
} catch (NoSuchMethodException e) {
// do nothing, the methods will be null on failure
} catch (SecurityException e) {
// do nothing, the methods will be null on failure
}
getThreadCpuTimeMethod = threadCpuTime;
isThreadCpuTimeSupportedMethod = threadCpuTimeSupported;
}
}
ReflectiveThreadMXBean(Object threadMxBean) {
super();
this.threadMxBean = threadMxBean;
}
/**
* {@inheritDoc}
*/
public long getThreadCpuTime(long id) {
if (Holder.getThreadCpuTimeMethod != null) {
Exception error = null;
try {
return (Long) Holder.getThreadCpuTimeMethod.invoke(threadMxBean, id);
} catch (ClassCastException e) {
error = e;
// fallthrough
} catch (IllegalAccessException e) {
error = e;
// fallthrough
} catch (IllegalArgumentException e) {
error = e;
// fallthrough
} catch (InvocationTargetException e) {
error = e;
// fallthrough
}
throw new UnsupportedOperationException(Holder.FAILURE_MESSAGE, error);
}
throw new UnsupportedOperationException(Holder.FAILURE_MESSAGE);
}
/**
* {@inheritDoc}
*/
public boolean isThreadCpuTimeSupported() {
if (Holder.isThreadCpuTimeSupportedMethod != null) {
try {
return (Boolean) Holder.isThreadCpuTimeSupportedMethod.invoke(threadMxBean);
} catch (ClassCastException e) {
// fallthrough
} catch (IllegalAccessException e) {
// fallthrough
} catch (IllegalArgumentException e) {
// fallthrough
} catch (InvocationTargetException e) {
// fallthrough
}
}
return false;
}
}
================================================
FILE: src/main/java/org/junit/internal/management/RuntimeMXBean.java
================================================
package org.junit.internal.management;
import java.util.List;
/**
* Wrapper for {@link java.lang.management.RuntimeMXBean}.
*/
public interface RuntimeMXBean {
/**
* @see java.lang.management.RuntimeMXBean#getInputArguments()
*/
List getInputArguments();
}
================================================
FILE: src/main/java/org/junit/internal/management/ThreadMXBean.java
================================================
package org.junit.internal.management;
/**
* Wrapper for {@link java.lang.management.ThreadMXBean}.
*/
public interface ThreadMXBean {
/**
* @see java.lang.management.ThreadMXBean#getThreadCpuTime(long)
*/
long getThreadCpuTime(long id);
/**
* @see java.lang.management.ThreadMXBean#isThreadCpuTimeSupported()
*/
boolean isThreadCpuTimeSupported();
}
================================================
FILE: src/main/java/org/junit/internal/matchers/StacktracePrintingMatcher.java
================================================
package org.junit.internal.matchers;
import org.hamcrest.Description;
import org.hamcrest.Factory;
import org.hamcrest.Matcher;
import org.junit.internal.Throwables;
/**
* A matcher that delegates to throwableMatcher and in addition appends the
* stacktrace of the actual Throwable in case of a mismatch.
*/
public class StacktracePrintingMatcher extends
org.hamcrest.TypeSafeMatcher {
private final Matcher throwableMatcher;
public StacktracePrintingMatcher(Matcher throwableMatcher) {
this.throwableMatcher = throwableMatcher;
}
public void describeTo(Description description) {
throwableMatcher.describeTo(description);
}
@Override
protected boolean matchesSafely(T item) {
return throwableMatcher.matches(item);
}
@Override
protected void describeMismatchSafely(T item, Description description) {
throwableMatcher.describeMismatch(item, description);
description.appendText("\nStacktrace was: ");
description.appendText(readStacktrace(item));
}
private String readStacktrace(Throwable throwable) {
return Throwables.getStacktrace(throwable);
}
@Factory
public static Matcher isThrowable(
Matcher throwableMatcher) {
return new StacktracePrintingMatcher(throwableMatcher);
}
@Factory
public static Matcher isException(
Matcher exceptionMatcher) {
return new StacktracePrintingMatcher(exceptionMatcher);
}
}
================================================
FILE: src/main/java/org/junit/internal/matchers/ThrowableCauseMatcher.java
================================================
package org.junit.internal.matchers;
import org.hamcrest.Description;
import org.hamcrest.Factory;
import org.hamcrest.Matcher;
import org.hamcrest.TypeSafeMatcher;
/**
* A matcher that applies a delegate matcher to the cause of the current Throwable, returning the result of that
* match.
*
* @param the type of the throwable being matched
*/
public class ThrowableCauseMatcher extends
TypeSafeMatcher {
private final Matcher> causeMatcher;
public ThrowableCauseMatcher(Matcher> causeMatcher) {
this.causeMatcher = causeMatcher;
}
public void describeTo(Description description) {
description.appendText("exception with cause ");
description.appendDescriptionOf(causeMatcher);
}
@Override
protected boolean matchesSafely(T item) {
return causeMatcher.matches(item.getCause());
}
@Override
protected void describeMismatchSafely(T item, Description description) {
description.appendText("cause ");
causeMatcher.describeMismatch(item.getCause(), description);
}
/**
* Returns a matcher that verifies that the outer exception has a cause for which the supplied matcher
* evaluates to true.
*
* @param matcher to apply to the cause of the outer exception
* @param type of the outer exception
*/
@Factory
public static Matcher hasCause(final Matcher> matcher) {
return new ThrowableCauseMatcher(matcher);
}
}
================================================
FILE: src/main/java/org/junit/internal/matchers/ThrowableMessageMatcher.java
================================================
package org.junit.internal.matchers;
import org.hamcrest.Description;
import org.hamcrest.Factory;
import org.hamcrest.Matcher;
import org.hamcrest.TypeSafeMatcher;
public class ThrowableMessageMatcher extends
TypeSafeMatcher {
private final Matcher matcher;
public ThrowableMessageMatcher(Matcher matcher) {
this.matcher = matcher;
}
public void describeTo(Description description) {
description.appendText("exception with message ");
description.appendDescriptionOf(matcher);
}
@Override
protected boolean matchesSafely(T item) {
return matcher.matches(item.getMessage());
}
@Override
protected void describeMismatchSafely(T item, Description description) {
description.appendText("message ");
matcher.describeMismatch(item.getMessage(), description);
}
@Factory
public static Matcher hasMessage(final Matcher matcher) {
return new ThrowableMessageMatcher(matcher);
}
}
================================================
FILE: src/main/java/org/junit/internal/matchers/TypeSafeMatcher.java
================================================
package org.junit.internal.matchers;
import java.lang.reflect.Method;
import org.hamcrest.BaseMatcher;
import org.junit.internal.MethodSorter;
/**
* Convenient base class for Matchers that require a non-null value of a specific type.
* This simply implements the null check, checks the type and then casts.
*
* @author Joe Walnes
* @deprecated Please use {@link org.hamcrest.TypeSafeMatcher}.
*/
@Deprecated
public abstract class TypeSafeMatcher extends BaseMatcher {
private Class> expectedType;
/**
* Subclasses should implement this. The item will already have been checked for
* the specific type and will never be null.
*/
public abstract boolean matchesSafely(T item);
protected TypeSafeMatcher() {
expectedType = findExpectedType(getClass());
}
private static Class> findExpectedType(Class> fromClass) {
for (Class> c = fromClass; c != Object.class; c = c.getSuperclass()) {
for (Method method : MethodSorter.getDeclaredMethods(c)) {
if (isMatchesSafelyMethod(method)) {
return method.getParameterTypes()[0];
}
}
}
throw new Error("Cannot determine correct type for matchesSafely() method.");
}
private static boolean isMatchesSafelyMethod(Method method) {
return "matchesSafely".equals(method.getName())
&& method.getParameterTypes().length == 1
&& !method.isSynthetic();
}
protected TypeSafeMatcher(Class expectedType) {
this.expectedType = expectedType;
}
/**
* Method made final to prevent accidental override.
* If you need to override this, there's no point on extending TypeSafeMatcher.
* Instead, extend the {@link BaseMatcher}.
*/
@SuppressWarnings({"unchecked"})
public final boolean matches(Object item) {
return item != null
&& expectedType.isInstance(item)
&& matchesSafely((T) item);
}
}
================================================
FILE: src/main/java/org/junit/internal/requests/ClassRequest.java
================================================
package org.junit.internal.requests;
import org.junit.internal.builders.AllDefaultPossibilitiesBuilder;
import org.junit.internal.builders.SuiteMethodBuilder;
import org.junit.runner.Runner;
import org.junit.runners.model.RunnerBuilder;
public class ClassRequest extends MemoizingRequest {
/*
* We have to use the f prefix, because IntelliJ's JUnit4IdeaTestRunner uses
* reflection to access this field. See
* https://github.com/junit-team/junit4/issues/960
*/
private final Class> fTestClass;
private final boolean canUseSuiteMethod;
public ClassRequest(Class> testClass, boolean canUseSuiteMethod) {
this.fTestClass = testClass;
this.canUseSuiteMethod = canUseSuiteMethod;
}
public ClassRequest(Class> testClass) {
this(testClass, true);
}
@Override
protected Runner createRunner() {
return new CustomAllDefaultPossibilitiesBuilder().safeRunnerForClass(fTestClass);
}
private class CustomAllDefaultPossibilitiesBuilder extends AllDefaultPossibilitiesBuilder {
@Override
protected RunnerBuilder suiteMethodBuilder() {
return new CustomSuiteMethodBuilder();
}
}
/*
* Customization of {@link SuiteMethodBuilder} that prevents use of the
* suite method when creating a runner for fTestClass when canUseSuiteMethod
* is false.
*/
private class CustomSuiteMethodBuilder extends SuiteMethodBuilder {
@Override
public Runner runnerForClass(Class> testClass) throws Throwable {
if (testClass == fTestClass && !canUseSuiteMethod) {
return null;
}
return super.runnerForClass(testClass);
}
}
}
================================================
FILE: src/main/java/org/junit/internal/requests/FilterRequest.java
================================================
package org.junit.internal.requests;
import org.junit.internal.runners.ErrorReportingRunner;
import org.junit.runner.Request;
import org.junit.runner.Runner;
import org.junit.runner.manipulation.Filter;
import org.junit.runner.manipulation.NoTestsRemainException;
/**
* A filtered {@link Request}.
*/
public final class FilterRequest extends Request {
private final Request request;
/*
* We have to use the f prefix, because IntelliJ's JUnit4IdeaTestRunner uses
* reflection to access this field. See
* https://github.com/junit-team/junit4/issues/960
*/
private final Filter fFilter;
/**
* Creates a filtered Request
*
* @param request a {@link Request} describing your Tests
* @param filter {@link Filter} to apply to the Tests described in
* request
*/
public FilterRequest(Request request, Filter filter) {
this.request = request;
this.fFilter = filter;
}
@Override
public Runner getRunner() {
try {
Runner runner = request.getRunner();
fFilter.apply(runner);
return runner;
} catch (NoTestsRemainException e) {
return new ErrorReportingRunner(Filter.class, new Exception(String
.format("No tests found matching %s from %s", fFilter
.describe(), request.toString())));
}
}
}
================================================
FILE: src/main/java/org/junit/internal/requests/MemoizingRequest.java
================================================
package org.junit.internal.requests;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import org.junit.runner.Request;
import org.junit.runner.Runner;
abstract class MemoizingRequest extends Request {
private final Lock runnerLock = new ReentrantLock();
private volatile Runner runner;
@Override
public final Runner getRunner() {
if (runner == null) {
runnerLock.lock();
try {
if (runner == null) {
runner = createRunner();
}
} finally {
runnerLock.unlock();
}
}
return runner;
}
/** Creates the {@link Runner} to return from {@link #getRunner()}. Called at most once. */
protected abstract Runner createRunner();
}
================================================
FILE: src/main/java/org/junit/internal/requests/OrderingRequest.java
================================================
package org.junit.internal.requests;
import org.junit.internal.runners.ErrorReportingRunner;
import org.junit.runner.Request;
import org.junit.runner.Runner;
import org.junit.runner.manipulation.InvalidOrderingException;
import org.junit.runner.manipulation.Ordering;
/** @since 4.13 */
public class OrderingRequest extends MemoizingRequest {
private final Request request;
private final Ordering ordering;
public OrderingRequest(Request request, Ordering ordering) {
this.request = request;
this.ordering = ordering;
}
@Override
protected Runner createRunner() {
Runner runner = request.getRunner();
try {
ordering.apply(runner);
} catch (InvalidOrderingException e) {
return new ErrorReportingRunner(ordering.getClass(), e);
}
return runner;
}
}
================================================
FILE: src/main/java/org/junit/internal/requests/SortingRequest.java
================================================
package org.junit.internal.requests;
import java.util.Comparator;
import org.junit.runner.Description;
import org.junit.runner.Request;
import org.junit.runner.Runner;
import org.junit.runner.manipulation.Sorter;
public class SortingRequest extends Request {
private final Request request;
private final Comparator comparator;
public SortingRequest(Request request, Comparator comparator) {
this.request = request;
this.comparator = comparator;
}
@Override
public Runner getRunner() {
Runner runner = request.getRunner();
new Sorter(comparator).apply(runner);
return runner;
}
}
================================================
FILE: src/main/java/org/junit/internal/requests/package-info.java
================================================
/**
* Provides implementations of {@link org.junit.runner.Request}.
*
* @since 4.0
*/
package org.junit.internal.requests;
================================================
FILE: src/main/java/org/junit/internal/runners/ClassRoadie.java
================================================
package org.junit.internal.runners;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;
import org.junit.internal.AssumptionViolatedException;
import org.junit.runner.Description;
import org.junit.runner.notification.Failure;
import org.junit.runner.notification.RunNotifier;
import org.junit.runners.BlockJUnit4ClassRunner;
/**
* @deprecated Included for backwards compatibility with JUnit 4.4. Will be
* removed in the next major release. Please use
* {@link BlockJUnit4ClassRunner} in place of {@link JUnit4ClassRunner}.
*/
@Deprecated
public class ClassRoadie {
private RunNotifier notifier;
private TestClass testClass;
private Description description;
private final Runnable runnable;
public ClassRoadie(RunNotifier notifier, TestClass testClass,
Description description, Runnable runnable) {
this.notifier = notifier;
this.testClass = testClass;
this.description = description;
this.runnable = runnable;
}
protected void runUnprotected() {
runnable.run();
}
protected void addFailure(Throwable targetException) {
notifier.fireTestFailure(new Failure(description, targetException));
}
public void runProtected() {
try {
runBefores();
runUnprotected();
} catch (FailedBefore e) {
} finally {
runAfters();
}
}
private void runBefores() throws FailedBefore {
try {
try {
List befores = testClass.getBefores();
for (Method before : befores) {
before.invoke(null);
}
} catch (InvocationTargetException e) {
throw e.getTargetException();
}
} catch (AssumptionViolatedException e) {
throw new FailedBefore();
} catch (Throwable e) {
addFailure(e);
throw new FailedBefore();
}
}
private void runAfters() {
List afters = testClass.getAfters();
for (Method after : afters) {
try {
after.invoke(null);
} catch (InvocationTargetException e) {
addFailure(e.getTargetException());
} catch (Throwable e) {
addFailure(e); // Untested, but seems impossible
}
}
}
}
================================================
FILE: src/main/java/org/junit/internal/runners/ErrorReportingRunner.java
================================================
package org.junit.internal.runners;
import java.lang.reflect.InvocationTargetException;
import java.util.List;
import org.junit.runner.Description;
import org.junit.runner.Runner;
import org.junit.runner.notification.Failure;
import org.junit.runner.notification.RunNotifier;
import org.junit.runners.model.InvalidTestClassError;
import org.junit.runners.model.InitializationError;
import static java.util.Collections.singletonList;
public class ErrorReportingRunner extends Runner {
private final List